Skjermskraping med RoboMaker

Vi skal ta for oss ”database for offentlige innkjøp”, www.doffin.no. Her kan du søke fritt i kunngjøringer og få opp lister som i sin tur kan skrapes ned.

La oss begynne med listen over de siste 30 dagers kunngjøringer, som ligger her: http://www.doffin.no/search/search_30daysResultsList.aspx.

Liste over kunngjøringer på doffin.no
Figur 1: Listen over kunngjøringene på doffin.no den siste måneden.

Listen består av en lineær oversikt over alle kunngjøringene, fordelt på flere sider. Ved å klikke på tittelen får du opp detaljer om hver oppføring.

Listen er presentasjonsorientert og ikke semantisk. Med andre ord: Dataene er tilpasset visning på websiden, og ikke til databaseprogrammer eller regneark. For at vi skal kunne nyttegjøre oss informasjonen til CAR-formål, må vil hente ut dataene i et strukturert format.

Vi skal nå forsøke å laste ned informasjon om de enkelte kunngjøringene og organisere dataene slik at de kan viderebehandles i for eksempel Excel. Jobben vår blir nå å sette navn på de ulike datafeltene - tenk på dem som kolonnenavnene i Excel.

Hva kan vi hente?

Hver informasjonsbit gjentas på samme sted for hver eneste oppføring. Vi kan for eksempel tenke oss følgende kolonneoverskrifter i Excel:

Dette burde gi oss et godt utgangspunkt for å få en datakilde vi kan bruke til videre analyse. Tid for å åpne OpenKapow RoboMaker.

Sett opp roboten

Start RoboMaker. Programmet åpner med en veiviser som spør hva du vil gjøre. Den første dialogboksen ber deg spesifisere hva slags datainnsamling du vil gjøre.

RoboMaker spør hva slags datafeed du vil lage
Figur 2: RoboMaker spør her hva slags feed du vil lage. For oss passer det best med en såkalt REST-feed.

For oss passer det best å velge "REST Web Service", siden denne innstillingen tillater oss brukerdefinerte feltnavn.

Altså: Velg "REST Web Service" og trykk OK.

En ny dialog kommer opp. Her er det meningen at du skal skrive inn URL-en til siden der roboten skal starte. I vårt eksempel er dette den første siden i listen over Anbud. Skriv eller kopier følgende URL inn i dialogboksen: http://www.doffin.no/search/search_30daysResultsList.aspx

Trykk OK og deretter Neste for å hoppe over input values.

Angi feltnavn

Neste dialog spør etter output values. Her skal du fylle ut de aktuelle feltnavnene (kolonneoverskriftene).

Angi feltnavn
Figur 3: RoboMaker ber deg angi feltnavn. Skriv inn feltnavnene vi anga ovenfor.

Skriv inn feltnavn og trykk Add for å legge dem til i listen.

For at resten av veiledningen skal stemme, er det viktig at du legger inn feltnavnene i samme rekkefølge som de er listet opp ovenfor. Hvert felt blir nemlig tilordnet et nummerert REST output-felt.

Du kan godt bruke egne feltnavn, men husk at du ikke kan bruke mellomrom eller spesialtegn som for eksempel nordiske tegn (æ,ø eller å) i feltnavnet.

Klikk Finish for å starte.

Kort om brukergrensesnittet

RoboMaker er et meget avansert stykke programvare som gir deg verktøyet du trenger for å skrape ned og bearbeide informasjon fra nettsider.

De ulike delene av hovedvinduet.

Hovedvinduet
Figur 4: Hovedvinduet til RoboMaker kan nok gi et avskrekkende førsteinntrykk. Men ting er heldigvis enklere enn de ser ut.

De forskjellige delene av hovedvinduet kan kort oppsummeres på denne måten:

Programmere roboten

Vi skal nå programmere roboten til å hente ut datafeltene vi har bestemt oss for å samle inn.

Begynn med å klikke på "Return Response" i flytskjemaet, slik at RoboMaker laster siden med listen over kunngjøringer.

Når pilen med "Return Response" er blitt grønn, er du klar til å fortsette.

Tomt flytskjema, ingen operasjoner er lagt inn mellom innlasting og retur
Figur 5: Når Roboten starter opp, har flytskjemaet to trinn, en begynnelse og en slutt: "Load page" og "Return Response". Vi må legge våre operasjoner inn mellom disse to trinnene.

Hvis vi ser på listen på doffin.no, ser vi at den inneholder en rekke rader. Hver rad representerer én kunngjøring.

1 rad = 1 kunngjøring
Figur 6: Hver kunngjøring er én rad i listen.

Vi vil at roboten skal gå gjennom rad for rad nedover listen og hente ut den samme informasjonen fra hver eneste kunngjøring.

Vi må begynne med å isolere disse enkeltradene i HTML-koden. Det enkleste måten er å først klikke inne i den øverste raden med kunngjøringer i websidevisningen.

Markeringen er den samme i alle vinduene, men den blir vist på tre forskjellige måter
Figur 7: Når du gjør en markering, blir den synlig i alle de tre visningene.

Vi er ute etter å markere hele raden, ikke bare en del av den. Dette kan være vanskelig å få til i websidevisningen (1), siden raden består av flere markérbare felter som fyller tabellraden helt opp. Derfor går vi i stedet til HTML-treet (2).

Det er lettere å få tak i hele tabellraden ved å klikke på tr-taggen som omslutter den aktuelle raden.

Hvis du scroller deg opp i HTML-treet, så vil du se flere tagger, blant annet td (tabelldata) og tr (tabellrad).

Du skal klikke på den nærmeste tr-taggen over det markerte området.

Hvis du har truffet riktig tagg, vil du se at hele raden (kunngjøringen) nå er markert med grønt i websidevisningen.

Du kunne også ha gjort markeringen i HTML-visningen (3). Resultatet ville blitt nøyaktig det samme. Det er imidlertid ofte enklere å bla seg opp til riktig tag i treet (dokumenthierarkiet) enn å lete etter den aktuelle starttaggen i en lineær HTML-kode.

Høyreklikk og velg Loops - For Each Tag
Figur 8: Når hele raden er markert, høyreklikk på den og velg "Loops - For Each Tag".

For å iterere gjennom alle linjene, må vi ha en såkalt løkke (loop) som gjentar de påfølgende handlingene én gang for hver rad.

Når raden er markert, som anvist ovenfor, kan du høyreklikke på den. Igjen spiller det ingen rolle om du høyreklikker på den i webside-visningen, html-treet eller html-visningen.

I eksempelet til høyre har vi valgt å høyreklikke i html-treet. En popup-meny kommer opp. Her skal du velge Loops -> For Each Tag.

Du har nå lagt til et nytt trinn på flytskjemaet.

Det nye trinnet "For Each Tag" legger seg mellom "Load Page" og "Return Response" i flytskjemaet.

Løkken sender hver enkelt rad i listen videre til de påfølgende trinnene, slik at påfølgende operasjoner vil bli gjentatt for hver rad.

Flytskjema med "For Each&qout;-løkke lagt inn
Figur 9: "For Each"-løkken har et nummer til høyre i boksen. Dette er telleren, som viser hvilken rad den er på.

"For Each"-løkken synes i flytskjemaet, med et nummer til høyre i boksen. Dette er telleren, som holder rede på hvilken rad roboten er på akkurat nå.

Test at løkken fungerer ved å klikke på telleknappen oppe i verktøymenyen
Figur 10: Bruk telleknappen (innfelt) til å sjekke at løkken itererer gjennom hver rad i listen.

Du kan bruke tellerknappen i verktøylinjen for å øke telleren.

Klikk et par ganger på opp- og ned-knappen. Legg merke til hvordan det blå, stiplede rektangelet flytter seg tilsvarende opp og ned i listen. Rektangelet viser hvilken rad som er valgt i gjeldende iterasjon.

Legg merke til hva som skjer når du setter telleren til startposisjonen, "1". Tittelraden i tabellen er valgt, og ikke den øverste kunngjøringen slik den burde.

Dette er fordi tittelraden også ligger i en tr-tagg. Dermed vil roboten starte med tittelraden - med mindre vi setter den opp til å hoppe over den øverste raden.

Endre startraden fra 0 til 1 for at roboten skal hoppe over tittelraden
Figur 11: "For Each"-løkken ignorerer tittelraden hvis du endrer "First tag number" fra 0 til 1.

For å hoppe over den øverste raden, markér "For Each"-boksen i flytskjemaet og gå til "Action"-arkfanen i panelet til høyre.

Endre verdien i feltet "First tag number" fra 0 til 1. Dette nummeret korresponderer til tagnummereringen i HTML-treet, der tr-taggene er nummerert fra 0 til N: tr[0], tr[1], tr[2]..., tr[N].

I vårt eksempel er det altså tr[0] som er tittel-raden. Og den hopper vi elegant over ved å sette "First tag number" til verdien 1, altså tr[1], som er den første av radene med kunngjøringer.

Prøv å sette telleren til "1" igjen. Nå ser du at roboten begynner der den skal - på første kunngjøring i listen.

De påfølgende operasjonene, som settes inn etter "For Each"-boksen i flytskjemaet, blir gjentatt én gang for hver kunngjøring. Og det er telleren som bestemmer hvilken rad (kunngjøring eller tr-tag) som er den gjeldende.

Uthenting av data

Vi har nå fått roboten vår til å gå gjennom rad for rad i listen. Neste skritt blir å hente ut dataene vi er ute etter.

Sett telleren til 1, slik at den øverste kunngjøringen i listen er markert med stiplet blå strek
Figur 12: Still telleren på "1" slik at den øverste kunngjøringen er markert med stiplet blå strek.

Begynn med å sette telleren til "1", slik at den øverste raden er markert i websidevisningen.

Pass på å markere boksen "Return response" i flytskjemaet, slik at denne er grønn før du fortsetter.

Det første feltet vi skal hente ut, er tittelen. Det er viktig at du velger felter fra den gjeldende raden, det vil si raden som er markert med blå stiplet linje.

I eksempelet som er vist her er dette linjen øverst, der det står "Driftsmaskin / redskapsbærer". Klikk på denne linjen i websidevisningen for å markere feltet.

Høyreklikk på tittelen og velg Extraction - Extract Text - RESTOutput - RESTOutput.value1 (Tittel)
Figur 13: Hent ut tittelen ved å høyreklikke på tittelen og velge "Extraction -> Extract Text -> RESTOutput -> RESTOutput.value1 (Tittel)".

En grønn stiplet linje markerer tittellinjen når du har klikket på den.

Høyreklikk på tittelen, og velg "Extraction -> Extract Text -> RESTOutput -> RESTOutput.value1 (Tittel)".

En ny boks kommer til syne i flytskjemaet: "Extract Value 1".

Rett til neste felt, publiseringsdato. Høyreklikk på publiseringsdaoten til venstre i kunngjøringen og velg "Extraction -> Extract Text -> RESTOutput -> RESTOutput.value2 (Publiseringsdato)".

En ny boks kommer til syne i flytskjemaet: "Extract Value 2".

Gjenta prosedyren for de øvrige feltene vi har definert. Når du kommer til URL, så marker tittelen og velg følgende:

Extraction -> Extract URL -> RESTOutput -> RESTOutput.URL - dette for at vi skal hente URL-en og ikke selve lenketeksten til tittelen.

Når du er ferdig skal flytskjemaet se slik ut:

Det foreløpige flytskjemaet ser slik ut
Figur 14: Slik skal flytskjemaet se ut når alle feltene er lagt inn.

Prøvekjør roboten

Vi har nå en foreløpig versjon av roboten. Nå skal vi testkjøre den, for å se om den henter inn dataene slik vi ønsker.

Åpne debuggeren for å kjøre roboten
Figur 15: Du åpner debuggeren ved å klikke på knappen med bilde av en bille (bug) i verktøylinjen.

Du må åpne debuggeren for å kjøre roboten. Klikk på knappen i verktøylinjsen som har bilde av en bille (bug) på seg.

Det er fra debuggeren at du må kjøre roboten. Senere vil du også kunne lagre de innsamlede dataene som tekstfil herfra.

For å kjøre roboten, klikk på "play"-knappen oppe til venstre i debuggeren. Roboten begynner nå å laste siden.

Den vil nå begynne på toppen av listen over kunngjøringer. For hver linje samler den inn dataene og legger dem inn i output-panelet nedenfor.

I løpet av noen sekunder har roboten gått gjennom listen på 50 oppføringer. Du skal da kunne se datafeltene i output-panelet i debuggeren.

Output-panelet og listen over nedlastet informasjon
Figur 16: Dataene du har skrapet ned er nå synlig i output-panelet i debuggeren.

Det som kan virke litt ulogisk når du ser på listen, er at navnet på feltene kommer før feltverdiene. Ideelt sett burde feltnavnene være synlige som kolonnetitler. Dette er imidlertid ikke tilfelle for REST-feeden, noe vi retter opp i Excel senere.

Denne foreløpige versjonen av roboten tar kun med seg de 50 første oppføringene på listen.

Vi vil imidlertid ha ned alle oppføringene fra inneværende måned. Det betyr at roboten må bygges ut litt.

Lukk debuggeren og gå tilbake til RoboMakers hovedvindu.

Legge inn repetisjon

Vi vil at roboten skal bla seg gjennom resultatsidene, en for en. For hver siden skal den gå gjennom alle linjene og skrape ned dataene.

Konfigurer trinn
Figur 17: Konfigurer det nye trinnet, velg "Select An Action -> Loops -> Repeat".

Markér "For Each"-boksen i flytskjemaet og høyreklikk. I menyen som kommer opp, velg "Insert step before". En tom boks dukker opp mellom "Load Page" og "For Each".

Pass på at den nye, blanke boksen er markert før du går videre.

I panelet oppe til høyre, velg "Select An Action -> Loops -> Repeat". Den nye boksen endrer utseende og får teksten "Repeat".

Handlingen "Repeat" fungerer sammen med handlingen "Next" slik at alle trinn mellom "Repeat" og "Next" vil bli gjentatt helt til roboten er ferdig, eller en feilkondisjon oppstår.

Legg til forgrening
Figur 18: En forgrening kan ses på som en måte å dele inn oppgavene på.

Vi vil at roboten først skal gå gjennom den nedlastede siden slik den gjorde da vi testet den. Men når den er ferdig med den første siden, vil vi at den skal gå videre til de neste sidene og gjenta prosedyren.

Dette løser vi ved å lage en ny løkke. Lukk debuggeren og gå tilbake til RoboMakers hovedvindu.

Vi skal sette inn den nye løkken mellom "Load Page" og "For Each". Begynn med å markere "For Each"-boksen i flytskjemaet.

Listeboks for å navigere mellom listesidene
Figur 19: Denne listeboksen (markert med grønt) brukes for å navigere mellom visningssidene.

I Websidevisningen ser du at du kan navigere deg fra side til side ved hjelp av en listeboks (rullegardinliste) oppe til venstre. Vi vil ha roboten vår til å bla seg gjennom alle sidene.

Markér listeboksen og høyreklikk på den. I menyen som kommer opp, velg "Forms" -> "For Each Option".

Dette er alt som skal til for at roboten nå også blar seg gjennom alle sidene. For hver side vil den så iterere gjennom alle kunngjøringene og laste ned informasjonen på sidene.

Flytskjemaet ser nå slik ut
Figur 20: Slik skal flytskjemaet se ut når den siste løkken er lagt inn.

Eksportere dataene

Nå skal vi lagre resultatet som tekstfil. Begynn med å åpne debuggeren igjen (knappen med en bille på), men uten å starte roboten.

For å skrive til fil må vi konfigurere et par viktige miljøparametre. Velg først "Options" -> "Use Environments" slik at dette valget er avkrysset.

Konfigurer miljø
Figur 21: Konfigurér miljøer (file storage, message, input object).

Velg deretter "Options" -> "Configure Environments". En ny dialog kommer opp. Tre miljøer må være til stede for at fileksporten skal fungere:

Hvis et eller flere av miljøene mangler i dialogboksen, bruk + -knappen for å legge det til. Deretter kan du klikke på "Select An Environment" for å velge riktig type.

Når du er ferdig, skal dialogboksen se ut som over, med alle de tre miljøene inkludert.

Vi må nå konfigurere miljøene.

Dobbeltklikk på "File Storage Environment". Fyll inn ønsket filnavn på resultatfilen (uten mellomrom eller nordiske tegn). Sett "File Format" til "Semicolon Separated Values (SCSV)". Klikk OK.

Dobbeltklikk på "File Message Environment". Fyll inn et filnavn på loggfilen, hvor eventuelle feilmeldinger skrives (uten mellomrom eller nordiske tegn). Klikk OK.

Dobbeltklikk på "Input Object Environment". Trykk på pluss-tegnet for å legge til et Input Object. Velg deretter "RESTInput" fra rullegardinlisten under. Klikk OK.

Lukk deretter dialogen med miljøene ved å klikke OK.

Nå kan du starte roboten med play-knappen oppe til venstre i debuggeren.

Hvis du har gjort jobben din, er det bare å lene seg tilbake og vente til roboten er ferdig.