Web pages creenshots using WebKit, Qt, C++ and Ruby on Rails - Part 1
There are many places where we would love to see web sites screenshots in our applications. And there are places that you can get some, check out his list.
However, with some nice Linux libraries, and a bit of C++ development skills (really a bit), you can get some for free.
In this tutorial I will use Trolltech’s Qt Library version 4.4 beta. Please make sure that you have Qt 4.4 beta or greater installed in your system before trying to compile example program.
Goals
Today, our goal is to create simple C++ app, that will work from command line and will allow us to take web site screenshots of any pages.
Later on, we will use it from within our Rails application.
Requirements
You’ll need Qt version 4.4 beta or greater, a c++ compiler and virtual X server for your Unix server on which application will be installed. I am going to use Xvfb, which is part of standard Linux X server.
Source code
Our application will consist of 3 files: main.cpp, shoter.h and shoter.cpp. main.cpp will be only used to call object Shoter that’s specified in two other files and take screenshots.
main.cpp
#include <QtGui>
#include <QtWebKit>
#include <shoter.h>
int main(int argc, char** argv) {
if (argc != 3) {
qDebug("Usage: webkitshoter http://exampleurl.com file.png");
exit(EXIT_FAILURE);
}
QApplication app(argc, argv);
Shoter* w = new Shoter(QString(argv[1]), QString(argv[2]));
w->show();
app.exec();
return 0;
} shoter.h
#ifndef SHOTER_H #define SHOTER_H class QWebView; #include/** @author Hubert ??picki */ class Shoter : public QWidget { Q_OBJECT public: Shoter(QString url, QString filename, QWidget *parent = 0); ~Shoter(); public slots: void grabScreen(); private: QWebView* view; protected: QString filename; QString url; int width; int height; }; #endif
shoter.cpp
#include "shoter.h" #include#include Shoter::Shoter(QString url, QString filename, QWidget *parent) : QWidget(parent) { this->url = url; this->filename = filename; QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, false); view = new QWebView(this); view->load(QUrl(url)); width = 1024; height = 768; connect(view, SIGNAL(loadFinished()), this, SLOT(grabScreen())); resize(width, height); view->resize(width, height); } Shoter::~Shoter() { } /*! \fn Shoter::grabScreen() */ void Shoter::grabScreen() { qDebug("taking shot"); QPixmap shot = QPixmap::grabWidget(this->view); shot.save(filename, "JPG"); qDebug("shot taken"); this->close(); }
Well, more or less that’s it for very basic screenshoter! You can dowlnoad this code as a KDevelop project from here.
Compiling the project
It’s a fairly straightforward for Qt program, let’s comile it with: “qmake && make”.
Creating screenshots
You can find “webkitshoter” executable in “bin” folder. You use it like this:
./webkitshoter http://google.com googleshot.png
That’s it! You get 1024x768 screenshot.
Notes on how to use it from within Rails application in my next post!
Alternatives (the most important part of this post ;))
The code I have shown you here is pretty basic one. I know that there might bebetter alternatives you want to use. Good one is khtml2png, however it’s using KHTML engine which is not as good as WebKit (these two are much related!). I have used this one and even modified it so I can take screenshots of full web pages, not only part of them. Pretty neat stuff, I think it might be topic of next post…
If you are using WebKit on MacOS X, try WebKit2PNG. It does basically what my program does, but is using standard MacOS X WebKit engine and libraries (python).
And finally there are scripts that embed Gecko rendering engine into GTK+ windows. I found my installation of Gecko working unreliable in comparison with WebKit/KHTML, but you might try it! Good description is found on hackdiary.