RapidMiner tippek – A Crawl Web operátor
Az előző RapidMiner tippek blogbejegyzésre érkezett pozitív visszajelzéseknek megfelelően – melyeket ezúton is köszönünk – a mostani írás is a RapidMiner mélyebb ismertetéséről, egészen pontosan a Crawl Web operátor trükkös működéséről illetve használatáról szól.
A web-barangolás nem egy tipikus nagyvállalati feladatkör, hiszen meglehetősen ritka az olyan adatelemzési feladat egy multi cégen belül, ahol az első lépések között az internetről kell begyűjtenünk bizonyos weboldalak linkjeit és tartalmait további elemzés céljából. Ennek megfelelően a RapidMiner-ben ez a task csak egy kiegészítő révén valósítható meg (Web Mining Extension), melyet ezidáig majd 50.000-szer töltöttek már le. Kérdés, hogy mennyire hatékony a RapidMiner Crawl Web operátora illetve, hogy mi mennyire ismerjük azt?
Nézzük tehát a web-barangolást, a feladat legyen az alábbi: szeretnénk legyűjteni – a weboldal tulajdonosa által jóváhagyva – egy weboldalhoz tartozó illetve a weboldalról elérhető összes weboldal linkjét és tartalmát valamilyen elemzés céljából. Erre tehát a RapidMiner-ben a Crawl Web operátor szolgál, amelyben megadható a kiinduló URL és “minden” egyéb szükséges paraméter (az idézőjelek használata azonnal magyarázatot kap). A kimeneti adattábla ‘Link’ attribútuma tartalmazza a legyűjtött URL-eket, a ‘Page’ attribútuma pedig azok HTML tartalmát (az attribútum nevek megadására nincs lehetőség, átnevezésük csak egy Rename operátorral lehetséges). Ezután jellemzően valamilyen szövegfeldolgozási lépés következik, ahol a HTML tartalomból megállapítunk mindenféle érdekes dolgot. Tegyük fel, hogy ezen lépés kimenete egyértelműen hozzárendel egy azonosítót az adott oldalhoz tartozó URL-hez: pl. bizonyos linkeken ‘x’ típusú dolgok találhatók, míg más linkeken ‘y’ típusú dolgok stb. (ezek lehetnek termékek, szolgáltatások, illetve bármilyen tartalmak). Ha nem vagyunk elég alaposak, mehetünk is a megrendelőhöz a szépnek tűnő eredménnyel, ahol könnyen igencsak kellemetlen helyzetben találhatjuk magunkat, ugyanis a Crawl Web operátorban nincs lehetőség a cookie-k engedélyeztetésére. Így ha az elemzendő webportál valamely oldala csak úgy tekinthető meg, ha engedélyezve van a böngészőnkben a cookie-k használata, akkor a Crawl Web operátorral, mint egyfajta “böngészővel” nem tudjuk begyűjteni az adott URL-hez tartozó valódi HTML tartalmat, csak a cookie engedélyezés hiányában átirányított weblapot, ami jellemzően arról tájékoztat, hogy miért és hogyan lehet engedélyezni a cookie-kat illetve, hogy ezek használata milyen előnyökkel és következményekkel jár. A cookie-kat használó weboldalak URL-jeihez tehát a legyűjtött átirányított oldal tartalma alapján téves azonosítót fogunk rendelni, ami több, mint ciki.
A probléma viszont orvosolható, mégpedig a Get Pages operátorral, ahol már létezik az “accept cookies” paraméter, melyben az “all” értéket választva a webszerver úgy látja, hogy a kliens oldalon engedélyezve van a cookie-k használata, így begyűjthető a helyes HTML tartalom. A Get Pages operátor használatával viszont van egy “kisebb” probléma, méghozzá, hogy funkcionalitását tekintve ez nem egy web-barangoló operátor, így nem képes felderíteni egy kiinduló URL-ről elérhető összes többi URL-t a meghatározott követési szabályoknak (‘crawling rules’) és egyéb paramétereknek (pl. maximum oldalszám, maximum mélység stb.) megfelelően. Tehát első lépésben le kell gyűjtenünk a Crawl Web operátorral a linkeket, majd ezt a ‘Link’ attribútumot kell átadnunk a Get Pages operátor ‘link attribute’ paraméterének. A probléma a kétszeres futási idő mellett inkább a többszörös memóriahasználat, ami a RapidMiner Achilles-sarka, ugyanis egy nagyobb webportál esetén akár több 10.000 oldalt is elemeznünk kellene, amihez pedig könnyen kevés lehet 10-20 GB memória is, és a teljes feladatmegoldásban még csak a bemeneti adatok gyűjtésénél járunk.
A Get Pages operátor bemenete tehát egy linkeket tartalmazó attribútum (pl. ‘Link’), kimenete pedig több egyéb mellett (pl. a legyűjtés dátuma) egy ‘URL’ és a ‘page attribute’ paraméterben megadott nevű attribútum (pl. ‘Page_2’), mely már nem a bemeneti ‘Link’ attribútum linkjeihez tartozó HTML kódokat tartalmazza, hanem a kimeneti ‘URL’ attribútumban lévő linkek HTML kódjait. Ha tehát nem engedélyezzük a cookie-k használatát a Get Pages operátorban, akkor a ‘Link’ és az ‘URL’ attribútumok nem lesznek azonosak, hiszen az ‘URL’ attribútumban az átirányított oldalak linkjei fognak szerepelni. A Crawl Web operátor HTML kódokat tartalmazó ‘Page’ attribútuma és a Get Pages operátor ‘Page_2’ attribútuma viszont azonos lesz, hiszen mindkettő az átirányított weboldalakat tartalmazza. A cookie-k engedélyezése esetén pedig épp fordított a helyzet: a ‘Link’ és az ‘URL’ attribútumok lesznek az azonosak (helyesek), a ‘Page’ és ‘Page_2’ attribútumok pedig különbözőek (utóbbi a helyes weboldalakkal).
A Crawl Web operátor másik (illetve harmadik) nagy hibája, hogy a weboldalak karakterkódolása sem állítható be, ami viszont alapvető fontosságú a HTML tartalmak helyes szövegelemzése céljából. Ha a webportálról legyűjtött minden weboldal UTF-8 kódolású, akkor szerencsénk van, vagy akkor is, ha a weblapok nem tartalmaznak ékezetes karaktereket. Ha viszont igen, és nem UTF-8 kódolásban, hanem pl. az ISO-8859-2 szabvány szerint (a használt karakterkódolás kinyerhető a normálisabb weboldalak esetén megadott metaadatokból), akkor a Crawl Web operátor ‘Page’ attribútuma megint csak használhatatlan lesz. Rossz hír, hogy ezt a problémát már a Get Pages operátor sem orvosolja. De mint lassan megszokható, ez a hiányosság is kivédhető a RapidMiner-ben, méghozzá a Get Page operátorral, aminek utolsó, ‘override encoding’ paraméterét engedélyezve megadható az aktívvá váló ‘encoding’ paraméterben a weboldalak karakterkódolása. Azonban a Get Page operátor használatának is “ára” van (nem is kicsi), ami jelen esetben egy Loop Examples operátor lesz, ugyanis a Get Page operátor nem rendelkezik bemenettel, így a Crawl Web operátor ‘Link’ attribútumának értékei csak egy makró segítségével adhatók át az ‘url’ paraméternek. Hogy pl. 10.000 weboldal esetén mennyi ideig tart ezzel a módszerrel legyűjteni a linkekhez a weboldalakat, és hogy ehhez milyen teljesítményű gép szükséges, azt próbálja ki mindenki magának, ha napokra nélkülözni tudja számítógépét.
Igazán érdekes feladat lenne, ha több különböző karakterkódolású weblapot is legyűjtenénk, ugyanis ekkor nekünk kellene kibányászni a használt karakterkódolást a HTML kódokból, amit sajnos makróval nem lehet átadni az ‘encoding’ paraméternek, úgyhogy muszáj lenne egy Subprocess operátort és több Get Page-et használni.
Még ebben az esetben sem biztos, hogy sikeres lesz az adatgyűjtés, ugyanis ha nem tulajdonosi engedéllyel gyűjtünk tartalmat egy webportálról, akkor könnyen kitiltás lehet a web-barangolás következménye. Webszerver oldalon a web-crawling azonosítása automatizáltan történhet, melyet nehezíteni lehet pl. a lekérdezések között eltelt idő véletlen változtatásával. A Crawl Web operátorban sajnos erre nincs lehetőség, mivel a ‘delay’ paraméterben csak fix értékek adhatók meg, de a Get Pages operátorban már beállítható a ‘random’ érték (a Get Page operátor értelem szerűen nem rendelkezik ilyen paraméterrel). Ha pedig a Get Page operátort kell használnunk, akkor a Loop Examples operátorban alkalmazhatjuk a Delay operátort, szintén a ‘random’ értékkel. A web-barangolás azonosításának további nehezítése lehet még a random user agent használata, melyre szintén csak a Get Pages és a Get Page operátorokban van lehetőség.
Zárásképpen elmondható, hogy bár a web-crawling csak egy RapidMiner kiegészítő révén válik elérhetővé, mégis – vagy éppen ezért – tele van olyan hiányosságokkal, melyek egyébként implementálva lettek egy-egy másik operátorban, csak épp pont abban nem, melyben kellett volna a hatékony működés érdekében. A Web Mining kiegészítő jelenlegi, 5.3.1-es verziója éppen egy éve került publikálásra. Kíváncsian várjuk, hogy mikor jön ki egy újabb verzió, melyben remélhetőleg már javítva lesznek az itt részletezett hiányosságok is. Arra pedig egy következő bejegyzésben próbálok majd magyarázatot adni, miért használom a Loop Examples operátort a Loop Values helyett, holott az utóbbi több okból is sokkal kézenfekvőbb és logikusabb lenne a fent említett példában.