Zpět na seznam článků     Číst komentáře (21)     Verze pro tisk

Programování spiderů v Pythonu 1

Autor: Jakub Tětek   
3.3.2014

Někdy je užitečné automatizovaně procházet, sledovat, či jinak interagovat s webovými stránkami. V tu chvíli na scénu přicházejí internetoví spideři, nebo boti, jak se jim také říká. V této krátké sérii článků Vám ukáži, jak jednoduchého bota naprogramovat.


Veškeré ukázky budou psané v Pythonu 2.7 a bude nutné umět psát (nebo alespoň číst) jednoduché regulární výrazy. Pokud jste ještě regexy nepoužívali, tak doporučuji tutoriál na regexone.com.

K čemu je internetový bot dobrý?

Když potřebujete automatizovat nějakou interakci s webem, můžete napsat bota, který udělá většinu práce za Vás. Je jedno, jestli se jedná o kontrolování, zda se nezměnil obsah webové stránky, nebo o vytvoření a správu tisíce emailových účtů.

Nebezpečí internetových robotů

Bot PythonPokud stránka vysloveně nepovoluje používání webových robotů a vy nemáte v plánu se provozovatele webové aplikace ptát, zda můžete bota použít, vystavujete se nebezpečí zablokování vaší IP adresy. Naštěstí se ale většinou jedná pouze o zablokování dočasné, protože nelze s určitostí zjistit, zda bota spouštíte úmyslně, nebo zda je součástí malware. Blokací se navíc provozovatel webu připravuje o návštěvníka, a tak je i pro něj často výhodnější uživatele po čase odblokovat. O tom, jak se banu vyhnout, budu psát v některém z dalších dílů.

Jak internetový bot funguje?

Bot stáhne webovou stránku, prohledá ji (většinou pomocí regulárních výrazů) a podle toho, co na stránce nalezne, se zachová. Bot může zaslat e-mail s upozorněním, stáhnout jinou webovou stránku, nebo může udělat cokoliv jiného, co mu řeknete. Ukážeme si také, jak vyplnit a odeslat formulář.

Namísto regexů lze použít HTML parser, který je ale většinou výrazně pomalejší, než dobře napsaný regex a nemá tak velké možnosti vyhledávání. Proto jsem se rozhodl pro regulrní výrazy.

Než začnete psát bota, doporučuji se podívat, zda už jeho funkcionalitu nepodporuje služba samotná. Proč například programovat bota, který bude zasílat newsletter, když už to webová služba nabízí? Také je dobré zjistit, zda služba nepodporuje API, které vám umožní se služby dotazovat mnohem efektivněji. Je zbytečné stahovat celý obsah HTML stránky, ze které pak budete regexem získávat informace, když byste si o ně mohli zažádat přes API. HTML stránka je většinou několikanásobně větší, než API request, čímž ušetříte bandwidth nejen sobě, ale i poskytovateli služby.

Píšeme prvního bota

Náš první bot udělá jednoduchou věc. Vypíše titulky všech novinek na první straně webu ItWorld.com. Využijeme při tom knihovny urllib2, která nám pomůže stáhnout obsah webové stránky.

Stáhnutí webové stránky provedeme tímto kódem:

Download webové stránky
  1. from urllib2 import urlopen # z knihovny urllib2 importujeme funkci urlopen
  2. response = urlopen(“http://www.itworld.com/news”) # funkce urlopen vrátí objekt s z odpovědí na náš http požadavek
  3. html = response.read() # z objektu odpovědi přečteme html kód stránky


Nyní tedy máme v proměnné html uložen HTML kód cílové stránky. Jak z něj ale dostat titulky? Abychom to zjistili, budeme si ho muset prohlédnout. Bez velkého úsilí zjistíme, jak titulky vypadají na úrovni HTML.

Zápis titulků na cílové stránce
  1. <h3 class="title">
  2.       <a href="adresa článku">Titulek, který chceme vyseparovat</a>    </h3>


Z HTML kódu nyní budeme muset vystáhnou pouze obsah titulku, tedy tu část kódu, která se nachází na místě označeném"Titulek, který chceme vyseparovat". Napíšeme proto jednoduchý regex, kterým budeme tyto titulky vyhledávat.

Regulární výraz pro extrakci obsahu titulků
  1. <h3 class="title">\n      <a href="[^"]*">([^<]*)</a>    </h3>


K tomuto regexu asi není co dotat, snad jen to, že část "[^"]*" matchuje odkaz. Ten nás sice nezajímá, ale je nutné ho ve výrazu uvést tímto způsobem, protože je jeho obsah proměnlivý. Část výrazu uzavřená v závorkách matchuje samotný titulek, který si přejeme vyextrahovat. Závorka je použita proto, abychom se na toto místo mohli odkazovat a mohli přečíst na tomto místě uvedený obsah. Díky tomu, že je v regexu použit pouze jeden pár závorek a používame na vyhledávání funkci findall, není vrácen seznam všech substringů, které byly nalezeny, ale pouze seznam částí, které byly matchnuty tím, co je v závorce. Pokud bychom v regexu použili závorek více, byl by nám vrácen seznam s tuply (datová struktura podobná seznamu), které by v sobě teprve měly jednotlivé části matche. Podíváte-li se pozorně, zjistíte, že závorka (respektive to co je v ní) v našem příkladu matchuje právě textový titulek.

Pythoní zdroják pro vyhledání titulků naším regexem by vypadal následovně.

Extrakce textových titluků ze stránky
  1. from re import findall # z knihovny re importujeme funkci findall
  2. titles = findall('<h3 class="title">\n      <a href="[^"]*">([^<]*)</a>    </h3>', html) # prohledáme obsah proměnné “html” naším regexem


Nyní už máme všechny titulky v jednom seznamu a stačí je jen vypsat.

Celý program pak bude vypadat asi takto:

Kompletní zdrojový kód
  1. from urllib2 import urlopen # z knihovny urllib2
  2. from re import findall # z knihovny re importujeme funkci findall
  3.  
  4. response = urlopen(“http://www.itworld.com/news”) # funkce urlopen vrátí objekt obsahující odpověď na náš http požadavek
  5. html = response.read() # z objektu odpovědi přečteme html kód stránky
  6.  
  7. titles = findall('<h3 class="title">\n      <a href="[^"]*">([^<]*)</a>    </h3>', html) # prohledáme obsah proměnné <i>html</i> naším regexem
  8.  
  9. print titles # vypíšeme seznam obsahující titulky


Abyste se v psaní botů procvičili, můžete zkusit udělat drobnou úpravu, aby program vypisoval také webové adresy článků. Pokud se kdekoliv zaseknete, zeptejte v komentářích a já se Vás pokusím popostrčit správným směrem.

Pro tentokrát je to vše. V příštím díle budeme stahovat Google mapy a naučíme se vyplňovat formuláře pomocí knihovny Mechanize.


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.79/24

1  2  3  4  5    
(známkování jako ve škole)