Screenshot a URL with Python and Qt and WebKit
I’ve spent the last 4 days working on the problem of how to make a screenshot of a URL on a Linux server with no display. Furthermore, I need it to be programmatic, so I could call it from a web app when needed. Additionally, I wanted some architecture that could conceivably lend itself to threading in the future, so that we could scale the thing.
Essentially, all the solutions I found did this:
- Create a headless X server with something like Xvfb.
- Open some sort of browser on that in-memory X window.
- Screenshot the contents of that browser.
- Render that screenshot content out to some image format.
That’s when I found the work of Roland Tapken. His script and explanation were the solution I needed. It made nice screenshots, had the configuration options I needed (screen size, scaling image, destruction of X server, etc.). I thank him deeply for his work and his sharing it with the world.
The only problem off the bat was that it requires at least 2 packages that were not installed for me on Ubuntu 7.10 (Gutsy). In fact, they aren’t available in the versions I needed until the most recent Ubuntu 8.10 (Intrepid). Those packages are libqt4-webkit and python-qt4. Even on Intrepid (at least on my slicehost slice), I needed to install these and their dependencies. You’ll need to make sure to get libqt4-core as well. The libqt4-webkit didn’t seem to require it according to aptitude.
I had a small problem with the script as far as passing arguments into the Xvfb server. For that reason, I’m sharing my version of the code. However, all kudos go to Roland. His blog post on this subject provides a nice overview of the thought process and rationale behind this code. If you’d like a little more on the how and why, check it out. He also provides a simpler version if you’d just like to test out the Qt WebKit stuff and see how it works.
In summary, to use this code:
- Read Roland’s blog post.
- Install the necessary libraries: libqt4-core, libqt4-webkit, python-qt4, xvfb.
- Grab my code here. Change the extension to py.
- To run, use a command like this: python webkit2png.py -x -o cnn.png –debug http://www.cnn.com
If you have questions, comments, or code to add, please post in the comments or pingback this post. I will try to update once I have a good threading model built out around this functionality.