Podgląd strony do pliku jpg?

Poruszenie w Internecie tematyką wprowadzania cenzury, o której ostatnio pisałem, podsunęło mi pewien pomysł, który mam nadzieję niebawem Wam przedstawię. W między czasie uznałem, że w projekcie przyda mi się funkcjonalność zautomatyzowanego robienia podglądów (thumbnail) stron WWW do obrazków. Miałem przy tym całkiem dużo frajdy i mam nadzieję, że efekty mojej pracy komuś się to przydadzą.

Serwisów które przygotowują podgląd stron jest w sieci niewiele, a takich, które za darmo udostępniają wygodne API, nie mają śmiesznie małych limitów przygotowań podglądów nie znalazłem. Napisałem sobie takie narzędzie sam. Jeśli ktoś chce wykorzystać ten kod – proszę bardzo – proszę tylko o informację gdzie jest on dostępny oraz liczę na darmowy dostęp ;)

Twoja własna mini-przeglądarka

Jak szybko zrobić sobie przeglądarkę z obsługą Flasha, JavaScriptu i tych wszystkich urozmaiceń? Wystarczyło mi kilkanaście minut :) Zdecydowałem się na użycie GTK (domyślnego zestawu kontrolek dla m.in. Gnome) oraz Webkit’a – silnika do renderowania wykorzystywanego w takich przeglądarkach jak Safari (Mac OS), Google Chrome (Windows) czy Midori (Linux):

#!/usr/bin/env python

url = 'http://www.nme.pl'
size = [800, 600]

import gtk,webkit
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(size[0], size[1])
window.connect('destroy', gtk.main_quit)
preview = webkit.WebView()
preview.open(url)
scrolled = gtk.ScrolledWindow()
scrolled.add(preview)
window.add(scrolled)
window.show_all()
gtk.main()

Właściwy podgląd strony

Kod trzeba było trochę rozbudować. Konfiguracja jest w klasie conf. Uruchamiając kod w pierwszym parametrze należy podać adres strony (nie zapominając o nazwie protokołu, np. http://www.nme.pl).

w katalogu w którym znajduje się skrypt trzeba założyć podkatalog thumb, w którym zapisywane będą obrazki jpg.

shot.py:

#!/usr/bin/env python

__author__ = 'mw AT nme.pl'
__version__ = '1.0'
__date__ = 'wto, 25 sie 2009, 09:15:48 CEST'

import pygtk
pygtk.require('2.0')
import gtk,gtk.gdk,gobject
import webkit
import hashlib
import os,sys

class conf:
    show_scrollbars = True
    show_progress = True
    script_timeout_secs = 15
    size = [1024, 768]

class Snapshot:

    def load_progress_changed(self, view, progress):
        print '%d%%' % progress

    def load_finished(self, view, frame):
        print 'loading finished'
        w = gtk.gdk.get_default_root_window()
        wp = self.window.get_position()
        ws = self.window.get_size()
        sz = w.get_size()
        pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,ws[0],ws[1])
        pb = pb.get_from_drawable(w,w.get_colormap(),wp[0],wp[1],0,0,ws[0],ws[1])
        if (pb != None):
            pb.save('thumbs/'+self.file+'.jpg','jpeg',{'quality':'95'})
        gtk.main_quit()

    def __init__(self, url=None):

        self.url = url
        self.file = hashlib.sha512(url).hexdigest()
        self.overtime = False
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_default_size(conf.size[0], conf.size[1])
        self.window.set_decorated(False)
        self.window.connect('destroy', gtk.main_quit)
        self.preview = webkit.WebView()
        self.preview.open(self.url)
        if conf.show_progress:
            self.preview.connect('load-progress-changed',self.load_progress_changed)
        self.preview.connect('load-finished',self.load_finished)
        self.scrolled = gtk.ScrolledWindow()
        if conf.show_scrollbars:
            self.scrolled.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC
            self.scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
        else:
            self.scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER
            self.scrolled.props.vscrollbar_policy = gtk.POLICY_NEVER
        self.scrolled.add(self.preview)
        self.window.add(self.scrolled)
        self.window.show_all()
        gobject.timeout_add(conf.script_timeout_secs*1000, self.timeout)
        gtk.main()

    def timeout(self):
        gtk.main_quit()
        sys.exit(1)

if len(sys.argv)==2:
    Snapshot(url=sys.argv[1])
else:
    print >> sys.stderr, "Usage: %s url\n" % sys.argv[0]
    sys.exit(1)

Wrapper do generowania właściwego poglądu

Skrypt działa, ale wymaga działania X’ów, coś nam jeszcze wyświetla i zapisuje obrazek w skali 1:1. Da się to zrobić w tle. Potrzebujemy do tego dwóch narzędzi – convert z pakietu imagemagick oraz pakietu xvfbVirtual Framebuffer ‘fake’ X server. Mając już te narzędzia – całą robotę zrobi za nas skrypt o nazwie snap:

#!/bin/bash

state=0
plik=`python -c "import hashlib; print hashlib.sha512('$1').hexdigest()+'.jpg'"`
[ -e "thumbs/$plik" ] || {
	xvfb-run -a --server-args='-screen 0 1024x768x16' python shot.py $1
}
state=$?
[ "$state" -eq "0" ] && {
	[ -e "thumbs/$plik" ] && {
		convert -scale 310x -quality 75 thumbs/$plik thumbs/$plik
	} || {
		exit 1
	}
} || {
	exit 1
}

skryptowi nadajemy prawa do jego uruchamiania:

chmod +x snap

i uruchamiamy:

./snap http://www.nme.pl

w katalogu thumb odnajdujemy gotowego jpg’a (jego nazwa jest hashem sha512 URL’a). Wygląda to tak:

www.nme.pl-thumb

Powiązane, teksty w języku angielskim:

  1. Podobne rozwiązanie w oparciu o Qt, warto obejrzeć.
  2. Przykładowy opis jak można uruchomić serwis do generowania podglądów w oparciu o Django z nawiązaniem do gotowych już rozwiązań.

Comments

5 odpowiedzi do wpisu “Podgląd strony do pliku jpg?”
  1. baderman pisze:

    Ah, żeby tak gnome’a i webkita mieszać, no nie ładnie, nie ładnie :) .
    Wszystkie dzieci pamiętają, że gnome jest be a qt rulezi :)

    A tak zupełnie na poważnie, to zgrabna i w sumie prosta rzecz. Podoba mnie się :)

  2. nme pisze:

    -WebKit? ot, taka kontrolka GTK.
    ;)

    QT zaczyna być rulez od kiedy zmieniła mu się licencja, czyli od wersji 4. Wcześniej ten prodakt zupełnie mnie nie interesował :)

  3. Red pisze:

    Mała sugestia, po powtórnym przejrzeniu kodu.
    Wywal gtk_scrolled_window i osadź WebKit wprost na oknie, a pozbędziesz się zbędnych pasków przewijania na zrzucie ekranu (tylko szpecą, a pożytku z nich tu żadnego).

    Tak swoją drogą, tworzenie okna jest nadmiarowe, WebKit posiada zdolność renderingu poza oknem, nie wiem tylko jak to się ma do portu GTK.

    (Tak swoją drogą, ja właśnie pozbywam się uprzedzeń do Qt)

  4. nme pisze:

    Ja już nie pamiętam dokładnie, ale one po coś mi były potrzebne :) Ta funkcjonalność renderowania dotyczyła całych stron a ja chciałem mieć pogląd początku strony 4:3.

    Co do interfejsów desktopowych – nie specjalnie mi się za nimi tęskni. Wiem, że większość desktopowych aplikacji Canonicala albo taki virt-manager są robione w pythonie, co powinno sprawiać, że będę patrzył na nie bardziej przychylnym okiem, ale… nie patrzę :) Wybrałbym pewnie to API o smaku GTK, bo i tak pracuję w Gnome.

    Swoją drogą, te interfejsy desktopowe jeszcze się rozwijają?

  5. Red pisze:

    … i będziesz mieć, jedyne co robi gtk_scrolled_window to rysowanie paska przewijania.

    Ja również nie tęsknię za desktopem, ale dochodzę do prostego wniosku – skoro oko nie widzi różnicy pomiędzy gtk i qt, to jest mi obojętne jakich kontrolek używa aplikacja. Wybór powinien należeć włącznie do twórcy aplikacji.

    …a desktop rozwija jak zawsze, tak samo jak aplikacje działające w terminalu – świat jest wystarczająco złożony by było miejsce dla każdego typu programów.

Zostaw komentarz