4

I'm working with PyQt (as a Python beginner). I need to be able to take screenshots of a website on a headless system. I was using PhantomJS earlier for another project, but they dropped Flash support in 1.5 and I don't want to rely on a deprecated 1.4 version for my new project.

So I'm using PyQt to do my stuff on my own. I'm able to take a screenshot of a website with a given url, no problem.

But I keep having the "blue dice" flash plugin icon on flash placeholder (yes, javascript and plugins are activated)

self.settings.setAttribute(QtWebKit.QWebSettings.PluginsEnabled,True) 
self.settings.setAttribute(QtWebKit.QWebSettings.JavascriptEnabled,True) 

I'm making some test on a Youtube video page, here is an example of my issues:

image

The second part, that may be related to the first one: How can I tell PyQt to wait few seconds before taking the screenshot ? As you can see on the example, images on the right are still unloaded, because they are loaded using javascript and data attribute and in my script, I take the screenshot on the loadFinished signal (onLoad() javascript equivalent)).

My first guess was simply to

time.sleep(2) 

Before calling my capture method, but it's not working. I'm assuming that the Webkit loading is also asleep during this sleep time, preventing anything to load on the page.

I tried to create a custom signal, but then I still don't know how to trigger it without sleeping.

My last guess is that I need to thread my application. Am I right?

If you have any hint/script to help me displaying flash content and/or to add a setTimeout like signal, I would be really grateful!

Thanks in advance for you help.

EDIT: Just a quick edit to add my solution:

timeoutTimer = QTimer()
timeoutTimer.setInterval(3000) # wait for 3secs
timeoutTimer.setSingleShot(True)
timeoutTimer.timeout.connect(theMethodToCallOnTimeout)

About the flash thing: it looks like the flash player is broken on OSX (maybe related to a 32/64 bits issue).

Maxime Zielony
  • 103
  • 1
  • 7

2 Answers2

6

If you time.sleep you are freezing the whole application, instead, you can use a QTimer, QEventLoop, QThread, etc. Here is the PyQt4 version:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *

class browser(QWebView):
    def __init__(self, parent=None):
        super(browser, self).__init__(parent)

        self.timerScreen = QTimer()
        self.timerScreen.setInterval(2000)
        self.timerScreen.setSingleShot(True)
        self.timerScreen.timeout.connect(self.takeScreenshot)

        self.loadFinished.connect(self.timerScreen.start)
        self.load(QUrl("http://www.google.com/ncr"))    

    def takeScreenshot(self):    
        image   = QImage(self.page().mainFrame().contentsSize(), QImage.Format_ARGB32)
        painter = QPainter(image)

        self.page().mainFrame().render(painter)

        painter.end()
        image.save(self.title() + ".png")

        sys.exit()

if __name__ == "__main__":
    import  sys        
    app  = QApplication(sys.argv)
    main = browser()
    app.exec_()

QWebView Screenshot

4

I recommend using selenium. It is made for doing web automation, screenshots, and testing. Because it uses firefox it is very easy to have full flash support. It can also be run in a headless mode. The code below works at taking a screenshot of a web page with flash like the youtube video you had. You can see the screenshot it took below. A few things to keep in mind. selenium has a save_screenshot method which you can see is commented out in the code. I didn't use it because it wasn't taking proper screenshot of flash components, you can correct this by using the technique in Taking screenshot of flash object using Selenium with Webdriver. I chose though to just take a screenshot of the screen using the imagemagic import command. This is a screenshot tool that works in Linux. You can check out Take a screenshot via a python script. [Linux] and Get screenshot on Windows with Python? for other approaches of taking screenshots.

code

import time, selenium.webdriver, subprocess
browser = selenium.webdriver.Firefox()
browser.get('http://www.youtube.com/watch?v=bFEoMO0pc7k')
time.sleep(6)
#browser.save_screenshot('test.png')
subprocess.check_output('import -window root screen.png', shell=True)
browser.quit()

screenshot

enter image description here

Community
  • 1
  • 1
Marwan Alsabbagh
  • 25,364
  • 9
  • 55
  • 65
  • That's a screenshot of the website + the browser ;) –  Dec 20 '12 at 19:11
  • @X.Jacobs thats correct, the screenshot is actually the whole screen. I cropped the image for the posting. – Marwan Alsabbagh Dec 20 '12 at 19:17
  • I'll do some tests using Selenium. But I have to say that it's always a bit bothering me when you ask "how to do X on Y" and that somebody answer, well, on Z it's quite easy. Sometime you have to stick to your initial choice and deal with it. But this can definitely help me, so thank you! – Maxime Zielony Dec 21 '12 at 10:23
  • @MaximeZielony I know what you mean. I tried to do it with PyQt4 first but I couldn't get flash working, so I fell back on to selenium. – Marwan Alsabbagh Dec 21 '12 at 15:28
  • @Marwan Alsabbagh flash video working in Pyside / PyQt4 by enabling plugins.. please check my post here http://stackoverflow.com/questions/26377440/pyside-to-take-flash-webvideo-screenshot . i am facing an issue on taking screenshot of this youtube video. it shows black screen – AGR Oct 15 '14 at 11:44