我正在构建一个在线服务,可以制作网页截图并将其像图像一样返回给用户。这个怎么运作:
1)我为 X 服务器创建虚拟帧缓冲区 - 进一步不要创建真正的窗口
2)在环境变量中注意要使用什么显示
3)创建子进程(否则前一点不会生效)
4) 在子进程中创建 webkit.WebView(),“显示”窗口并加载网页
5)当我收到有关页面已完全加载的通知时-我制作屏幕截图并将其保存到文件中(仅在项目的这一步中,也-如何将其返回到用户的浏览器?我知道Content type: image/png
,但更进一步-gtk。 gdk.Pixbuf.save(stdout_file_name)?)
所以!问题!如果我从控制台运行它python parent.cgi
- 一切都很完美,但如果我在 Web 浏览器中打开parent.cgi
(服务器运行apache2
) - 然后在真正的浏览器页面中尝试无限加载,并且在服务器上的进程中我看到Xvfb
出现并加上三个(显然是和正确)python
过程:
python return_picture.cgi
python /home/argon/www/wool/cgi-bin/parent.cgi
bash/sh -c python return_picture.cgi
编码:
父.cgi:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import gtk,webkit,gobject,sys,os,time,subprocess,logging
import cgitb,cgi
import signal
cgitb.enable()
logging.basicConfig(format = u'%(levelname)-8s [%(asctime)s] %(message)s', level = logging.INFO, filename = u'mylog.log')
logging.critical('ONE MORE TIME')
print "Content-Type: text/html;charset=utf-8"
print '' #it is importantly required
class writer(object):
def write(self, data):
logging.critical(data)
sys.stdout = writer()
sys.stderr = writer()
class XServer():
def __init__(self, silence_xvfb=True, display='1', screen='0', xvfb_timeout=3):
self.pidfile = '/tmp/.X%s-lock' % display
redirect = '> /dev/null 2>&1'
redirect = ''
if not silence_xvfb:
redirect = ''
cmd = ' '.join(['Xvfb', ':'+display, '-screen', screen, '1600x1200x24', redirect])
if(os.path.isfile(self.pidfile)):
self._kill_xvfb()
#os.system(cmd+' &')
subprocess.Popen(cmd+' &', shell=True) #works througth filenodes thats why it is impossible to redirect to log - overriding of file.write() does not make sense
print 'XVFB STARTED'
self.xvfb = True
start = time.time()
while(True):
diff = time.time() - start
if(diff > xvfb_timeout):
raise SystemError("Timed-Out waiting for Xvfb to start - {0} sec".format(xvfb_timeout))
if(os.path.isfile(self.pidfile)):
break
else:
time.sleep(0.05)
os.putenv('DISPLAY', ':%s' % display)
def _kill_xvfb(self):
pid = int(open(self.pidfile).read().strip())
os.kill(pid, signal.SIGINT)
print 'KILLED'
def __del__(self):
# Kill the frame buffer
if(self.xvfb):
self._kill_xvfb()
xserver = XServer()
logging.debug('lets create child')
child = subprocess.Popen("python return_picture.cgi",shell=True,stdout=subprocess.PIPE)
s=child.stdout.readline()
print 'there again'
return_picture.cgi:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from blessings import Terminal
import gtk,webkit,gobject,sys,os,time,signal,logging
import cgitb,cgi
cgitb.enable()
t = Terminal()
logging.basicConfig(format = u'%(levelname)-8s [%(asctime)s] %(message)s', level = logging.DEBUG, filename = u'mylog.log')
class writer(object):
def write(self, data):
logging.critical(data)
sys.stdout = writer()
sys.stderr = writer()
logging.debug('IN CHILD')
#print "Content-Type: image/png"
#print "Content-Type: text/html;charset=utf-8"
#print '' #it is importantly required
#print 'hello'
web=webkit.WebView()
win=gtk.Window()
index = 0
finished = False
def finished_cb(web_view,sig,res):
global finished
global index
index += 1
#print index,': ',
status = web_view.get_property("load-status").value_name
logging.debug(str(index)+': '+status)
if "FINISH" in status and not finished:
finished = True
gobject.timeout_add(500,drawWindow)
print 'timeout'
return
sig2= "resource-load-finished"
web.connect(sig2, finished_cb)
url = 'http://google.com/'
web.open(url)
win.add(web)
def drawWindow():
width, height = win.get_size()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width, height)
screenshot = pixbuf.get_from_drawable(win.window, win.get_colormap(),
0, 0, 0, 0, width, height)
ret = screenshot.subpixbuf(0,0,300,20)
ret = screenshot
stdot_filename = os.readlink('/proc/self/fd/0')
print stdot_filename
#screenshot.save(stdot_filename, 'png')
gtk.main_quit()
screenshot.save('screenshot.png', 'png')
print 'screenshot saved'
win.show_all()
gtk.main()