构建Web服务以制作页面截图

时间:2012-08-24 20:57:12

标签: python apache webkit gtk

我正在建立一个在线服务,可以制作网页截图,并像图像一样将其返回给用户。工作原理:

1)我为X服务器创建虚拟帧缓冲区 - 进一步不创建真正的窗口

2)在环境变量中注意要使用的显示器

3)创建子进程(否则上一点不会生效)

4)在子进程中创建webkit.WebView(),“显示”窗口并加载网页

5)当我收到关于页面已完全加载的通知时 - 我制作截图并将其保存到文件中(仅在项目的这一步,还有 - 如何将其返回给用户的浏览器?我知道{{1 },但进一步 - gtk.gdk.Pixbuf.save(stdout_file_name)?)

原来如此!问题!如果我从控制台Content type: image/png运行它 - 一切都很完美,但如果我在网络浏览器中打开python parent.cgi(服务器运行parent.cgi) - 那么在真正的浏览器页面尝试无限加载,在服务器上的进程中,我看到apache2出现了加上三个(显然是正确的)Xvfb进程:

python

代码:

parent.cgi:

python return_picture.cgi
python /home/argon/www/wool/cgi-bin/parent.cgi
bash/sh -c python return_picture.cgi

return_picture.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'

1 个答案:

答案 0 :(得分:1)

你应该将屏幕截图请求与他们的一代分开。

让网页插入网址以将截屏截取到队列中。有一个进程从这个队列中拉出项目并运行屏幕截图生成脚本。

通过这种方式,网络浏览器不会等待屏幕截图进程运行(无论如何都可能会失败),您可以轻松处理重复请求,并且您不会淹没您的服务器启动更多WebKit实例而不是它可以同时运行。

我是如何在http://bookmarkly.com

那样做的