Návrh postupu pro stahování a ukládání stránek

Modul pro stahování stránek bude sloužit k naplnění a údržbě výše popsané databáze stránek. V následujícím textu se pokusím popsat, jak by měl modul pro stahování stránek pracovat a jaké další pomocné datové struktury budeme potřebovat.

URL stránek, jež potřebujeme stáhnout, budeme průběžně ukládat do fronty, ze které budou postupně čtena. Stahnutí a zpracování stránky by mělo probíhat zhruba podle následujícího scénáře:

  1. Stažení stránky z daného URL. Pokud je stránka nedostupná, zapíše se do tabulky URL chybový kód a stahování se ukončí.

  2. Normalizace kódování stránek. Pro další zpracování je nezbytně nutné sjednotit kódování češtiny používané na stránkách. Pro naše potřeby bude asi nejvhodnější všechny stránky převést do kódování ISO 8859-2, nebo UTF-8. Detekce kódování není zcela triviální záležitost, ale můžeme se inspirovat například zdrojovými kódy vyhledávače Sherlock [29], který tento problém poměrně uspokojivě řeší.

  3. Kanonizace do XML. Převážná většina dnešních HTML stránek obsahuje mnoho syntaktických chyb a znemožňuje jejich snadné zpracování pomocí jednoduchého parseru. Při načítání proto všechny stránky převedeme do XML, a tím usnadníme jejich zpracování dalším aplikacím.

    Tento krok se vyplatí i s ohledem na budoucnost. Další verze HTML – XHTML – má již přímo syntaxi XML, na Webu se postupně objeví informace dostupné pouze v XML.

  4. Testování změny stránky a opakovaného výskytu. V tomto kroku zjistíme, zda se načtená stránka již v databázi nevyskytuje pod jiným URL, nebo zda nedošlo ke změně stránky od jejího posledního zařazení do databáze.

  5. Aktualizace databáze. V závislosti na předchozím kroku jsou příslušné tabulky v databázi modifikovány – buď je přidána nová stránka, nebo jsou upraveny údaje o stávajících stránkách a URL.

  6. Aktualizace fronty dokumentů ke stažení. Ze zpracovaného dokumentu získáme všechny odkazy. Ty, které ještě nemáme uložené v tabulce URL nebo ve frontě, přidáme do fronty URL adres ke zpracování.

Stahování stránek z daného URL

Samotné stažení stránky z dané URL adresy není příliš složité, protože mnoho programovacích jazyků již přímo obsahuje funkce, které toto umožňují. Pokud však stahujeme větší množství stránek z více serverů, musíme zvážit i další okolnosti.

Existuje všeobecně akceptovaný standard [36], kterým může správce webového serveru zakázat stahování stránek pro automaticky pracující roboty. Informace o stránkách, které by se neměly stahovat, se ukládají do souboru robots.txt v kořenovém adresáři webového serveru. Pro naše potřeby bychom si měli pro každý server (doménové jméno + port) pamatovat obsah tohoto souboru a při stahování se jím řídit.

Zákaz indexování a zpracování dalších odkazů lze uvést i přímo v záhlaví dokumentu. Náš robot by měl respektovat i toto nastavení v hlavičce stránky:

<META name="ROBOTS" content="NOINDEX, NOFOLLOW">

Pro efektivní stahování by bylo výhodné stahovat stránky paralelně z několika serverů najednou. Aby nedocházelo k přetěžování serverů, nemělo by probíhat stahování více souborů z jednoho serveru zároveň. Fronta URL ke stažení proto bude muset fungovat jako několik samostatných front pro jednotlivé servery.

Z našeho úhlu pohledu budeme jako webový server chápat dvojici jeho doménového jména (případně IP adresy, pokud doménové jméno nebude k dispozici) a portu. Pro každý webový server si budeme pamatovat informace získané z robots.txt a stavový kód poslední operace. Pokud bude výsledkem poslední operace na serveru chyba, která znamená nefunkčnost serveru, budeme muset na nějaký čas přerušit stahování ze serveru.

Normalizace kódování

Jazyk HTML používá jako znakovou sadu Unicode [35], [41]. Pro zápis unicodových znaků však mohou různé stránky používat různá kódování. Pro češtinu se nejčastěji používají kódování windows-1250, iso-8859-2 a utf-8. Mnoho stránek je z historických důvodů přístupných pomocí různých modulů pro dynamickou změnu kódování i v několika dalších kódováních – např. Mac CE, CP852, kódování bratří Kamenických apod.

Správné rozpoznání kódování je klíčové pro namapování získané sekvence bajtů na unicodový textový řetězec. Ten pak může posloužit jako vstup pro další moduly. Specifikace HTML [35] v části 5.2 popisuje, jakým způsobem se má zjišťovat kódování dokumentu. Nejvyšší prioritu má obsah hlavičky Content-type z HTTP odpovědi. Ten může obsahovat např.:

Content-type: text/html;charset=iso-8859-2

Hlavička říká, že se jedná o HTML dokument (MIME typ text/html) a že je v kódování iso-8859-2. Pokud není kódování určeno v HTTP hlavičkách, hledá se odpovídající meta tag v přímo v HTML dokumentu.

<meta http-equiv="Content-type" 
      content="text/html;charset=iso-8859-2">

Jediný problém je v tom, že některé stránky neobsahují ani meta tag, ani se informace o kódování neposílá v hlavičkách. V tomto případě musíme kódování uhodnout. Jednak můžeme použít analýzu četnosti výskytu jednotlivých znaků, která se pro různá kódování samozřejmě liší. Pro stránky v češtině navíc platí, že nejčastěji bývají právě v kódování windows-1250.

Kanonizace do XML

Pro převod HTML stránek do XML můžeme použít program HTML-Tidy [34]. Ten kromě převodu do XML odstraní mnoho chyb, které se dnes v HTML kódu vyskytují.

Převod XML a XHTML[11] do XML není vůbec nutný. Dokument zkrátka jen uložíme do databáze.

Převod textových dokumentů do XML je velice jednoduchý. Můžeme se pokusit vytvořit heuristiky, které budou hledat například jednotlivé odstavce textu a uzavřou je do nějakého elementu.

Převod SGML dokumentů také nebude nikterak obtížný. Pokud SGML dokument znormalizujeme,[12] dostaneme formát, z něhož lze XML vyrobit velice jednoduše.

Dalšími složitějšími formáty, jako je PDF nebo DOC, se zatím zabývat nebudeme. Nicméně je vhodné převod do XML napsat modulárně tak, aby šla v budoucnu snadno přidat podpora pro další vstupní formáty.

Testování změny a opakovaného výskytu

Pokud budeme chtít nějakým efektivním způsobem zjistit, zda právě získaná stránka již není v naší databázi pod jiným URL, s výhodou využijeme vlastnosti algoritmu MD5 nebo obdobného „message digest“ algoritmu. Funkce MD5 přiřazuje každému textu 128bitové číslo. Z vlastností algoritmu vyplývá, že pokud jsou dva texty různé, je pravděpodobnost, že budou mít stejnou hodnotu MD5, velmi malá.

Pro stránku proto spočítáme MD5 a snadno tak zjistíme, zda již stejnou stránku nemáme zaindexovanou – měla by stejné MD5. Pro jistotou můžeme ještě stránky se stejným MD5 klasicky porovnat.

Některé stránky jsou na webu dostupné v několika různých kódováních včetně us-ascii – bez diakritiky. U každé stránky bychom proto také měli spočítat MD5 jejího textu po odstranění diakritiky. Jen tak můžeme dostatečně důkladně detekovat duplicitní stránky. Při ukládání dáváme samozřejmě přednost stránce s diakritikou před stránkou bez diakritiky – ocení to zejména lingvistické moduly.

Kromě hledání duplicitních stránek nám MD5 umožní snadno zjistit, zda se stránka s daným URL od posledního stažení nezměnila. Při změně obsahu stránky se samozřejmě změní i její MD5.