Címke: szkript

Avagy hogyan migráltam a webni.innen.hu tartalmát erre a WordPress oldalra? Ebben a bejegyzésben a költöztetés első lépéséről olvashatsz: milyen, nem teljesen erre a feladatra kitalált technológiával exportáltam a régi oldalam tartalmait.

A webni.innen.hu költöztetése című bejegyzésben már nagyvonalakban leírtam a folyamatot, most egy jóval részletesebben mutatom be az első lépéseket. Ez a tapasztalatok azoknak lehetnek érdekesek, akik komplexebb weboldalak tartalmait szeretnék maguk is költöztetni.

Első lépés: a Zwiki-vel készült szájt szkrépelése

Strukturált tartalom előállítása

Egy webszájt költöztetésének első lépése, hogy a megszüntetésre ítélt szájton fent lévő tartalmat valamilyen strukturált formába öntsük. Mivel hogy esetünkben egy Zwiki tartalomkezelő rendszerrel készült szájtról beszélünk, a strukturált szón különös hangsúly van. A Wiki jellegű weboldalak egyik fő ismérve, hogy igen gyakran egy adott weblapon megjelenített összes tartalom egyetlen mezőben játszik: a Zwiki esetében például ugyanabban a sima szöveges mezőben kapott helyet az oldal tulajdonképpeni tartalma és az összes, az oldalhoz szó szerint hozzáfűzött komment. A rendszer pedig ebből az ömlesztett szövegből egy egyszerű speciális szövegformázási megoldás értelmezésével ismerte fel, hogy melyek a hozzászólások, és melyik az oldal szövegtörzse. Emiatt az oldal tartalmának strukturált letöltése során az én szkriptemnek is meg kellett találnia ezeket a jellegzetességeket, hogy külön el tudjam raktározni a szövegtörzset és az egyes hozzászólásokat.

Speciális markup formázás kezelése

További kihívás volt, hogy a Zwiki, a többi wiki rendszerrel egyetemben, egy speciális, a HTML-nél jóval egyszerűbb formázási nyelvet használ, amit egy mai tartalomkezelő rendszer nem ismer fel. Pl. a fejezetcímet és annak szintjét úgy lehetett renkívül egyszerűen meghatározni, hogy hány szóköz szerepelt egy sortörés után következő sor elején. Emiatt a szerkesztőfelületen a szerkesztőmezőből kinyert szöveggel nem sokat tudtam volna kezdeni, így a publikus felületről kellett leszedni a már HTML formátumban renderelt tartalmakat.

Letöltés emberi látogatók imitálásával

Mivel alaposan ismerek és használok egy pár web scraper / web automatizáló eszközt, ezért a költöztetésnél is erre – az eredendően az emberi látogatók imitálására épülő –technológiára esett a választásom. Mintha egy átlagos látogató végigkattintaná az összes elérhető weblapot, és lementené a saját meghajtójára. Ezzel a módszerrel nem kötött az, hogy milyen export formátumokat kínál fel a régi oldal (semmilyet), és milyen import formátumokat tesz elérhetővé az új CMS. Ezekkel az online marketing programozás-ról szóló bejegyzésemben is említett rendszerekkel bármelyik részét meg tudom szerezni egy weboldalnak, bármilyen reguláris kifejezéssel fel tudom dolgozni, továbbá tetszőleges formátumban le tudom menteni.

A letöltő (szkréper) szkript logikája

A Wiki alapú tartalomkezelő rendszereknek van egy jó tulajdonsága, ami nagyban megkönnyíti az általuk kezelt oldal összes tartalmának megtalálását: szinte mindegyiküknél van ugyanis egy tartalomjegyzék-szerű weblap, ahol az összes wikilap ki van listázva. Emiatt a letöltő szkriptnek nagyon egyszerű logikája lehetett: kinyitni a tartalomjegyzék-oldalt, leszedni az összes ottani linket, majd egyenként végigmenve a linkek listáján, megnyitni az összes lapot, megtalálni a html kódban a címet, a szülőoldalakat, a szövegtörzset és a hozzászólásokat, majd átkattintani változtatástörténet aloldalára, ahonnan a legutolsó módosítás dátumát lehetett megszerezni.

Kimenetként készült egy .csv fájl, ami az oldalhierarchiát tartalmazta: hogy melyik weblapnak melyek a szülőoldalai, egy másik .csv táblázat, ami a lapok főbb adatai (mint az eredeti URL, cím, módosítás dátuma) mellett a tulajdonképpeni szövegtörzset tartalmazta egy-egy sorban. Készült még egy fájl, ami soronként tartalmazta az összes hozzászólást, szintén főbb adataikkal, végül egy hibakeresésre szolgáló fájl, ahol ömlesztve volt a fent említett egyetlen szöveges mező tartalma a szövegtörzzsel és a hozzászólásokkal – ha netán valamit elrontottam volna az utófeldolgozásnál.

A szkript megvalósítása UBot Studio-val

Mivel az egész folyamat nem tűnt túl bonyolultnak, ezért az Ubot Studio-ra esett a választásom a megvalósításnál. Ez egy olyan vizuális programozási felületet ad, ami elsősorban kevés elágazással és egymásba ágyazott ciklussal rendelkező, lineáris logikájú szkripteknél tud jól működni. Ezt a szoftvert tulajdonképpen egy online marketingeseknek való autmatizáló rendszerként hírdetik, de a fejlesztésének eredeti célja a weboldalak szkrépelése és szpemmelése volt linkbeküldésekkel, hozzászólások elküldésével, stb. Ettől függetlenül még számos egyéb webes automatizációs feladatra használható. Egyik legjobb funkciója, hogy segítségével .exe formátumú, Windows operációs rendszereken egyszerűen futtatható programokat építhetünk. A botok futtatásához tehát nincsen szükség magára – az egyébként elég borsos árú – szoftverre. Mivel magyar nyelvterületen kb. rajtam kívül még egy-két helyen használták ezt a tartalomkezelő rendszert, ezért ezt az .exe fájlt nem raknám ki letölthető formában, de ha írsz nekem, vagy hozzászólsz ehhez a bejegyzéshez, akkor szívesen elküldöm, ha szükséged lenne a saját ZWiki oldalad költöztetéséhez erre.

A másik érdekes koncepciója az Ubot Studionak, hogy a vizuális programozási nézetből – ahol dobozokat húzkodsz, majd nyitsz meg a paraméterek beállítása céljából – át lehet váltani kódnézetbe is, ahol egy egyszerű szintaxisú kódnyelv segítségével is áttekintheted illetve szerkesztheted a szkriptedet. Egy kis türelemmel és az alábbi kód elolvasásával megértheted, hogy pontosan hogyan is épült fel ez a szkript:

 ui text box("Domain to scrape (without http(s)://):",#domain)
 allow javascript("No")
 navigate("{#domain}/FrontPage/contents","Wait")
 wait for browser event("Everything Loaded","")
 wait(5)
 set(#scraped,$scrape attribute(<class="formcontent">,"innerhtml"),"Global")
 add list to list(%pageurls,$find regular expression(#scraped,"(?<=href=\")[^\"]+"),"Delete","Global")
 loop($list total(%pageurls)) {
     set(#pageurl,$list item(%pageurls,1),"Global")
     navigate(#pageurl,"Wait")
     wait for browser event("Everything Loaded","")
     wait(5)
     set(#content,$scrape attribute(<class="content">,"innerhtml"),"Global")
     set(#content,$replace regular expression(#content,"<a\\ class=\"new\\ .+?(?=</a>)</a>","<!-- no wikipage yet -->"),"Global")
     set(#content,$replace(#content,$new line,$nothing),"Global")
     set(#content,$replace regular expression(#content,"\\t"," "),"Global")
     set(#contentonly,$replace regular expression(#content,"<p><div\\ class=\"subtopics\"><a\\ name=\"subtopics\">.+",$nothing),"Global")
     set(#contentonly,$replace regular expression(#contentonly,"<p><a name=\"comments\">.+",$nothing),"Global")
     set(#contentonly,$replace regular expression(#contentonly,"<a name=\"bottom\">.+",$nothing),"Global")
     add list to list(%parents,$scrape attribute(<class="outline expandable">,"innertext"),"Delete","Global")
     set(#parentlist,$list item(%parents,0),"Global")
     clear list(%parents)
     add list to list(%parents,$list from text(#parentlist,$new line),"Delete","Global")
     set(#parentlist,$replace(#parentlist,$new line,";"),"Global")
     set(#posttitle,$list item(%parents,$eval($subtract($list total(%parents),1))),"Global")
     set(#posttitle,$replace(#posttitle," ...",$nothing),"Global")
     if($comparison($list total(%parents),"> Greater than",1)) {
         then {
             set(#parent,$list item(%parents,$eval($subtract($list total(%parents),2))),"Global")
         }
         else {
             set(#parent,$nothing,"Global")
         }
     }
     append to file("{$special folder("Desktop")}\\{#domain}-page-hierarchy.csv","{#pageurl}    {#posttitle}    {#parent}    {#parentlist}    {$new line}","End")
     clear list(%parents)
     add list to list(%comments,$find regular expression(#content,"<p><a[^>]+name=\"msg.+?(?=<p><a[^>]+name=\"msg.+)"),"Delete","Global")
     loop($list total(%comments)) {
         set(#comment,$list item(%comments,0),"Global")
         set(#date,$find regular expression(#comment,"(?<=name=\"msg)[^@]+"),"Global")
         set(#title,$find regular expression(#comment,"(?<=<b>).+?(?=</b>\\ --)"),"Global")
         set(#title,$replace regular expression(#title,"<[^>]+>",$nothing),"Global")
         set(#author,$find regular expression(#comment,"(?<=</b>\\ --).+?(?=<a\\ href=\"{#pageurl})"),"Global")
         set(#author,$replace regular expression(#author,"<[^>]+>",$nothing),"Global")
         set(#author,$replace regular expression(#author,",\\ *$",$nothing),"Global")
         set(#comment,$find regular expression(#comment,"(?<=<br(|\\ /)>).+"),"Global")
         set(#comment,"<p>{#comment}","Global")
         set(#comment,$replace regular expression(#comment,"\\t"," "),"Global")
         append to file("{$special folder("Desktop")}\\{#domain}-page-comments.csv","    {#pageurl}    {#date}    {#title}    {#author}    {#comment}    {$new line}","End")
         remove from list(%comments,0)
     }
     navigate("{#pageurl}/history","Wait")
     wait for browser event("Everything Loaded","")
     wait(5)
     scrape table(<outerhtml=w"<table>*">,&edithistory)
     set(#lastedited,$table cell(&edithistory,0,4),"Global")
     clear table(&edithistory)
     append to file("{$special folder("Desktop")}\\{#domain}-page-content-raw.csv","{#pageurl}    {#lastedited}    {#content}    {$new line}","End")
     append to file("{$special folder("Desktop")}\\{#domain}-page-content-only.csv","{#pageurl}    {#posttitle}    {#lastedited}    {#contentonly}    {$new line}","End")
     remove from list(%pageurls,0)
 }

2. lépés: A tartalom feltöltése erre a WordPress oldalra

Miután végigment a szkript az összes tartalmon és strukturált formátumba hozta a tartalmat, majd lementette .csv fájlokba, további szkriptekre volt szükségem ahhoz, hogy ezekből a táblázatokból „táplálkozva” feltöltsem a tartalmakat a WordPress oldalra. Ennél a résznél is egy hasonló technológiához folyamodtam, tehát a szkriptem bejelentkezett az oldal admin felületére, majd megnyomta az „Új oldal létrehozása” gombot, kitöltötte a szerkesztő űrlap különböző mezőit, kiválasztotta a legördülő menükben a megfelelő opciókat, majd megnyomta a „Közzététel” gombot. Hogy hogyan és miért így csináltam, és mi volt ennek az értelme, arról talán majd egy következő bejegyzésben lesz szó.

Mivel az online marketing területére az információépítészet felől érkeztem, egy tartalomkezelő rendszer kódjának barkácsolása, vagy akár egy komplett WordPress sablon létrehozása sosem okozott lelki válságot. Bár ezekben a tevékenységekben is volt egy nagy adag logika, programozásnak ezt legkevésbé sem nevezném. Öt éve azonban tulajdonképpen egy véletlen folytán megismertem egy olyan szoftvert, amivel én is egyszerűen megírhattam kisebb-nagyobb programocskákat, ezzel pedig új szintre emelhettem mindazt, amit azóta online marketing vagy webfejlesztés címén csinálok.

Web automatizálás: vissza a programozáshoz

Én még a nyolcvanas években kaptam az első számítógépem, amikor szinte minden számítógéptulajdonos tudott valamicskét programozni is. Valahogy azonban ez sosem feküdt annyira, így végül nem lett belőlem programozó. 2012 elején azonban újból kódolni kezdtem: ekkoriban mindenféle, keresőmarketinggel kapcsolatos munkákat csináltam, és egy ideje már azon voltam, hogy további olyan szoftvereket találjak, amik még jobban segítettek volna automatizálni a tömeges linképítéssel kapcsolatos szolgáltatásainkat.

Miközben egy újabb és jobb linkbeküldő, linkbeküldés-automatizáló szoftvert kerestem, rábukkantam egy általános web automatizációs szoftverre. Ezt és a hozzá hasonló programokat elsősorban web szpemmelésre találták ki, azonban megláttam bennük azt is, hogy emellett mennyi minden másra is használhatóak még. Az első komolyabb szkriptemet két hétig írtam, majd újabb két hetet vett igénybe, míg a kezdeti tapasztalatok alapján újraírtam mindent, de a végén kaptam egy olyan programocskát, ami sokáig ki tudta váltani egy fél ember munkáját.

Az alapprobléma ugyanis az volt, hogy ha mi beküldtünk egy linket egy linkgyűjteménybe, akkor szinte sosem tudtuk, hogy hol, milyen URL-en fog megjelenni, így a legtöbb linkgyűjteményben utólag, kézzel kellett leellenőrizni, hogy jóváhagyták-e a linkbeküldéseket. Ehelyett a kis szkriptem végigment a katalógusokon, rákeresett a linkjeinkre az oldalakon magán és a keresőkben, majd összeírta, hogy hová, milyen paraméterekkel kerültünk be. Pont úgy zajlott, mintha valaki kézzel megcsinálta volna mindezt, viszont a „robotnak” nem kellett fizetést adni, és utána járulékokat fizetni.

Ekkor még nem is gondoltam, hogy a későbbiekben mennyi minden egyébre fogom használni ezt az újonnan megismert, vizuális programozási technológiát, és ez mennyire fogja megváltoztatni mindazt, amivel és ahogy foglalkozom majd az elkövetkezendőekben.

 

Vizuális programozás online marketingeseknek

Az elmúlt öt évben egyre több és több dolgot csináltam, és egyre több tapasztalatot szereztem ezekkel az eszközökkel. Mindez fokozatosan alakította, hogy mit gondolok arról, hogy mi az, amit egy modern oline marketingesnek tudnia kellene az adatok gyűjtésével, feldolgozásával és értékelésével kapcsolatban – származzon az a webről, saját látogatottsági statisztikákból, vagy egyéb belső adatforrásból.

Tény, hogy vannak tudományosabb, gyorsabb és hatékonyabb módjai is annak, hogy mindenféle weboldalakkal vagy adatokkal kapcsolatos repetitív feladatokat automatizáljunk. Nekem azonban rengeteg segítséget adott, hogy különböző ötleteimet gyorsan meg tudjam valósítani, legyen szó adatfeldolgozásról, vagy fárasztó, monoton feladatok felgyorsításáról, vagy akár olyan projektek megvalósításáról, amit emberi erővel szinte lehetetlen lenne megcsinálni. Mindezt pedig számottevő programozói tudás nélkül, illetve programozó közreműködése nélkül is megtehettem.

A programozás diadalmenete

Tekintve, hogy már az eredeti szakmám, az építészet területén is egyre divatosabb a vizuális programozás és az algoritmikus tervezés, talán nem túlzás azt állítani, hogy lassan egyre több és több szakma művelői számára lesz elengedhetetlen, hogy hosszabb-rövidebb algoritmusokat maguk is meg tudjanak írni. Így talán itt is érdeklődésre tarhat számot, ha ezután részletesebben is írni fogok arról, hogy az online marketingben, keresőoptimalizálásban, keresőmarketingben és webfejlesztésben hogyan segített előrelépni a vizuális programozás.

Nem kevés előkészület után véglegesen bezártam a webni.innen.hu-t, miután átköltöztettem ide minden tartalmát. De miért kellett megszüntetni, átköltöztetni, majd bezárni az oldalt? Mi értelme egyáltalán foglalkozni régi weboldalak tartalmainak átköltöztetésével?

A webni.innen.hu számokban

2004 októberétől 2008 decemberéig 408 bejegyzés és 8051 hozzászólás született az oldalon, elsősorban a keresőoptimalizálás, keresés témáiban, ill. Google akkori szolgáltatásaival kapcsolatban (Google kereső, Google AdSense majd Google AdWords).

2006*-2009 végéig terjedő időszakban 619 860 felhasználó 1 751 910 oldalmegtekintést generált.  *(korábban nem létezett még Google Analytics)

Az összes forgalom 69,94%-a a keresők felől érkezett, miközben a keresőoptimalizálás kulcsszó önmagában csak 3%-át hozta a látogatottságnak még úgy is, hogy erre a kifejezésre rendre a második helyen volt az oldal. Aki ekkoriban keresés, keresőoptimalizálás, google vagy keresőmarketing témáiban keresett, az gyakorlatileg előbb-utóbb ebbe az oldalba botlott.

Miért szűnt meg az oldal?

A webni.innen.hu-t egy speciális Wiki-alapú tartalomkezelő rendszerrel írtam. A kétezres évek elején még ígéretesnek tűnt a Wiki oldalak jövője, de az évtized vége felé nyilvánvalóvá vált, hogy az egyszerű olvasókban nincs meg a szándék és/vagy a tudás az ilyen oldalak tartalmainak aktív fejlesztésére, így végül számos Wiki tartalomkezelő rendszer fejlődése is megrekedt – az egyedüli kivétel a Wikipédia maradt. Így az általam használt Zwiki is egyre inkább lemaradt attól, amit az akkori tartalomkezelő rendszerek (pl. Plone) nyújtottak, így egyre kevésbé tudtam azt és úgy csinálni a tartalmaimmal, ahogy azt szerettem volna. Így végül az oldalgazda.hu címen egy újabb oldal létrehozásába fogtam, immár Plone alapokon.

Mi történt most a költözéssel?

A webni.innen.hu után az általam használt tartalomkezelő rendszerek logikája nagyban különbözött a korábban használt Wiki oldal szervezőelveitől, ezért csak úgy, egyszerűen kiexportálni és beimportálni a tartalmakat az aktuális weboldalamba gyakorlatilag lehetetlen lett volna. Eddig egy szinte csak erre a célra fenntartott szerveren lakott az oldal, évek óta változatlan formában. Noha kb. 2012 óta áll rendelkezésemre az a tudás, amivel bármilyen weboldal tartalmát bármilyen másik tartalomkezelő rendszerbe át tudom költöztetni, de végül csak most került sor erre a folyamatra:

  • Egy szkript végigjárta a régi oldalt, és strukturált, táblázatos formába lementette a régi oldal tartalmát.
  • Egy másik szkript, egy emberi látogatót imitálva végigment a lementett táblázat sorain, és az ott talált szöveges adatokat szépen felrakta erre a WordPress oldalra, miközben feltöltötte a képeket, átírta az URL-jeiket, kiválasztotta a kiemelt képet, beállította a dátumokat, címkéket, stb. továbbá megadta az oldalak helyzetét a hierarchiában.
  • Miután lezajlott az összes tartalom feltöltése, és így meglett az összes bejegyzés régi és új címe, egy újabb szkript végigment az összes tartalmon, és a bejegyzések közötti sűrű hivatkozások URL-jeit átírta az új weboldalnak megfelelő linkekre.
  • Végül a domainnevet átirányítottam egy másik tárhelyre, ahol semmi más nincs, mint  a régi webni.innen.hu URL-ek / új oldalgazda.hu URL-ek párosait tartalmazó, átirányításokat meghatározó fájl: így ha valaki a régi szájt egyik aloldalát kéri le, már az új szájton fog kikötni.

Az egész folyamat tulajdonképpen csak abból állt, hogy meghatároztam a logikáját a költözésnek, majd megírtam hozzá a szkripteket – illetve javítgattam az először kitalált logikám kisebb-nagyobb hibáit.

Miért volt értelme megtartani a tartalmakat?

Régi heppem, hogy a tartalom érték, ezért sose töröljünk tartalmat. Emiatt amolyan bort iszik, vizet prédikál típusú dolog lett volna, ha az egyszerűség kedvéért simán csak lekapcsolom a régi oldalt. A tartalmak átmozgatásának azonban voltak további indokai is:

  • Látogatók: Bár már nyolc éve nem nyúltam az oldalhoz, még mindig számottevően látogatták az oldalt, és manapság, amikor eléggé korlátos az „ingyen” megszerezhető látogatók mennyisége, kár lett volna lemondani róluk.
  • Linkek: A még mindig meglévő látogatottság nagy hányadáért az a rengeteg értékes link felelt, ami a szájt különböző aloldalaira hivatkozott. Ezeknek a linkeknek az ereje most közvetlenül is támogatja majd a legújabb bejegyzéseim olvasottságát is.
  • Értékes tartalom: Az értékes linkjeim létrejöttét is szinte kizárólag a minőségi tartalom generálta, ami talán még így, elavultságában is értéket jelenthet bizonyos esetekben.
  • Személyes motivációk: Mint azt a számok is mutatták, elég sok embernél sikerült előidézzek szemléletváltást abban, ahogy oldalait építi, promotálja; de leginkább talán az én életemben okozta a legnagyobb változást, ezért mindig egy kedves emlék marad nekem.
  • A bizonyíték kedvéért: nem kevés vállalkozás ajánlja azóta is saját szolgáltatásait a tőlem lopott szövegekkel, úgyhogy emiatt is gondoltam, érdemes megtartani ezeket a tartalmakat, ha még egyszer megint ráveszem magam, hogy utánamenjek ezeknek az ügyeknek.

Összefoglalás

Számos oka lehet annak, hogy ne akarjunk megválni régebben létrehozott tartalmainktól. A legegyszerűbb megoldás persze, ha a régi oldalt hagyjuk ott, ahol van, de hosszú távon még praktikusabb lehet, ha átköltöztetjük a tartalmait arra az oldalra, ahol jelenleg is aktívak vagyunk. Még az sem feltétlenül akadály, ha a korábban létrehozott tartalom nagyságrendje miatt a tartalmak átköltöztetése egy új oldalra kézzel, belátható időn belül nem lenne megoldható.