Selenium, PIL, python i screenshoty stron www.

Data publikacji: 2012-11-30 | Tagi:

Przy okazji pisania SEO katalogu stron, który działa i ma się dobrze, wynikł problem miniaturek stron www, który można sformułować mniej więcej tak:

W chwili obecnej nie jest możliwe stworzenie serwisu, który po stronie serwera generowałby w łatwy sposób miniatury stron www.

Do wygenerowania takiej miniatury potrzebny jest działający silnik renderowania html - np. silnik Gecko na którym bazuje przeglądarka firefox. Firefox zaś potrzebuje do działania Xów, które nie są częstym widokiem na serwerach.

Co zatem robić? Znalazłem trzy rozwiązania:

  • Korzystać z zewnętrznego serwisu generującego miniatury
  • Generować miniatury ręcznie (screenshot + obróbka ręczna)
  • Stworzyć skrypt, który na moim desktopowym sprzęcie wygeneruje wszystkie niezbędne miniatury w odpowiednim rozmiarze
Zewnętrzny serwis generujący miniatury

Odrzuciłem te rozwiązanie bardzo szybko. Darmowe usługi są mizernej jakości i oferują niewielkie rozmiary miniatur oraz długi czas czekania na ich wygenerowanie. Chociaż przyznaję, że wdrożenie tego typu generatora byłoby chyba najprostszym rozwiązaniem. Jednak jego wady szybko odwiodły mnie od realizacji. Szczególnie, że zawsze staram się ograniczyć korzystanie z zewnętrznych usług do minimum.

Generowanie ręczne

No cóż tu dużo tłumaczyć - palce na Alt+PrintScreen i do dzieła. Ręczne kadrowanie takich zdjęć już po piątym staje się mordęgą. Wprawdzie można dopisać do gimpa jakiś skrypt automatyzujący, ale i tak jest to mierne rozwiązanie.

Skrypt generujący miniaturki na sprzęcie wyposażonym w Xy

Tutaj zaczyna robić się ciekawie, szczególnie jeśli połączymy siły Selenium i PILa.

Po kilku momentach, kilkunastu przekleństwach i chwili szperania w sieci miałem już w miarę sprawnie działające rozwiązanie.

# -*- coding: utf-8 -*-
from selenium import webdriver
from PIL import Image

host = "http://programowo.blogspot.com"
filename = "screenshot.jpg"
cr_width = 1024
cr_height = 768

browser = webdriver.Firefox()
browser.set_window_size(1300, 1024)
browser.get(host)
browser.get_screenshot_as_file('temp.png')
browser.quit()

img = Image.open('temp.png')
width, height = img.size
if width > cr_width:
    wpercent = (cr_width/float(width))
    height = int((float(height)*float(wpercent)))
    width = cr_width

img.thumbnail((width, height), Image.ANTIALIAS)
if height > cr_height:
    height = cr_height

new_img = img.crop((0, 0, width, height))
new_img.convert('RGB')
new_img.save(filename, 'JPEG', quality=75)

Krótkie podsumowanie skryptu:

Przy pomocy Selenium otwieramy instancję przeglądarki, w niej wyświetlamy stronę www, a następnie zapisujemy zrzut do tymczasowego pliku temp.png. Selenium ma również metodę pobierania screenshota do base64 ale odpuściłem ją sobie, żeby nie komplikować bez potrzeby.

Następnie przy pomocy PIL odczytujemy taki obrazek, dokonujemy przeskalowania, przycięcia i zapisujemy pod nową nazwą jako plik jpg.

Tu mała uwaga - można się obyć bez PIL - wtedy otrzymamy screenshot przedstawiający cały render strony - od nagłówka, aż po stopkę. PIL jest użyty tylko do wygenerowania podglądu tego, co zwykle widzimy otwierając stronę, czyli powiedzmy obrazu o wysokości około 1024px.

Dla ciekawskich link do źródła pythonowych bindingów do Selenium: http://code.google.com/p/selenium/source/browse/trunk/py/selenium/webdriver/remote/webdriver.py

Oczywiście opuściłem tutaj wymagania skryptu - potrzebuje firefoxa, selenium, pythona i PIL'a z wkompilowaną obsługą png i jpg.


Oceń ten post:
Podziel się:

comments powered by Disqus

IT w obrazkach: