Kartlägg en Facebookgrupp, del I

Av: Leo Wallentin, Datajournalist, J++ och Newsworthy

Hem/Inlägg/Kartlägg en Facebookgrupp, del I

En introduktion till webbläsarskrejping

Det här är den första delen av två, där vi kartlägger Facebookgrupper. I den första delen samlar vi in data, och i den andra delen analyserar vi den. 

Skrejping är ett samlingsnamn på olika tekniker för att hämta hem data från webben på ett strukturerat sätt. Oftast är det något vi förknippar med programmering, och/eller molntjänster som Scrapinghub och Import.io. Men det finns skrejpinguppgifter som går att lösa med betydligt enklare verktyg än så. I den här artikeln kommer vi att använda ett enkelt webbläsarplugin för att hämta information från en annars notoriskt svårskrejpad sajt: Facebook.

Olika verktyg för olika typer av skrejping

Skrejping kan vara utmanande på olika sätt: Å ena sidan kan datan vi vill hämta vara komplex eller svårtåtkomlig. Kanske vill vi hämta information från miljontals sidor, som var och en ligger flera klick bort. Kanske måste vi fylla i ett formulär för varje sida vi vill hitta. I sådana fall behöver vi nästan alltid programmera, så att vi kan instruera datorn att klicka sig fram till alla sidor åt oss. Ett typexempel här är kanske att hämta all information om alla bolag från det luxemburgska företagsregistret online.

Å andra sidan kan själva sajten göra det svårt för oss att skrejpa den automatiskt. Kanske använder den captchas, eller blockar dig om du besöker den flera gånger i rad från samma IP-adress, eller alltid klickar på samma pixel på en knapp. Här är det alltså inte automatiseringen som är svår, utan tillgången, och i sådana fall är det effektivaste verktyget ibland en helt vanlig webbläsare! Ett typexempel är att hämta all medlemmar ur en Facebookgrupp. Det är något som Facebook vill ska vara enkelt för en webbläsare (=människa), men svårt för en robot.

Vi kan beskriva det med en fyrfältare, där olika verktyg (detta är bara ett litet urval av alla som finns) passar olika typer av utmaningar:

I den här texten rör vi oss alltså i det övre vänstra hörnet: Datan är okomplicerad, men sajten är svår.

Installera webbläsartillägg

Det finns en uppsjö olika webbläsartillägg för att samla in data från webbsidor. Generellt kan sägas att de mest lättanvända ofta inte är flexibla nog för att vara till hjälp, och att de mest svåranvända kräver ganska omfattande kunskaper i xPath-uttryck (vi återkommer till dem) eller liknande. I den här genomgången använder vi två Chrome-plugin som befinner sig lite på varsin sida mitten på den skalan. Testa gärna andra verktyg själv! Olika verktyg gör ett olika bra jobb på olika sajter.

Våra plugin finns här:

Detta är alltså Chrome-plugin, så om du sitter i en annan webbläsare är det dags att starta Google Chrome nu! Flera liknande verktyg finns även för Firefox.

Ditt ena tillägg, Instant Data Scraper, finns i bland webbläsartilläggen i verktygsraden, eller dolda under pusselbitsikonen. Det andra, Scraper, finns under kontextmenyn (”högerklicksmenyn”), och heter där ”Scrape similar”, när du högerklickar på något på en sajt.

Instant Data Scraper

Det här webbläsartillägget är egentligen helt självförklarande. När du öppnar det, försöker det automatiskt identifiera listor eller tabeller på sidan du befinner dig på. Hittar den inte det du söker direkt, kan du låta den testa vidare, till den (förhoppningsvis) hittar rätt. Det är smidigt när det fungerar, men till priset av att du inte själv kan ange exakt vad du söker när automatiken sviker dig.

Låt oss testa Instant Data Scraper (IDS) på medlemmarna i en Facebookgrupp! Leta rätt på en grupp med öppen medlemslista, eller gå till en grupp du själv är medlem i (varför inte datajournalistikgruppen https://www.facebook.com/groups/datajournalistik/members?)

När du först öppnar IDS på sidan med medlemmar är det inte säkert att du hittar rätt, men klicka på ”try another table”, till dess att tabellen i botten på verktyget innehåller en kolumn med namn på medlemmar (och några andra kolumner). Troligen är tabellen bara 10 rader lång. Det beror på att Facebook laddar in nya medlemmar i listan i takt med att du scrollar nedåt på sidan (oändlig scroll brukar det kallas, även om det rimligen finns ett slut någonstans). Det här är ju ett populärt alternativ till traditionell paginering på sociala medier, och ställer till ett litet problem för oss. Eftersom vi använder webbläsaren för att skrejpa, kan vi bara hämta det webbläsaren ser. Lyckligtvis har IDS en funktion för den här typen av sidor. Kryssa bara i ”Infinite scroll”-rutan, och klicka sedan på ”Start crawling”, så ska den börja bläddra nedåt på sidan, och fylla på tabellen allt eftersom. Det är möjligt att du behöver justera väntetiden medan scrollningarna för att det ska fungera; En sekund som det står från början är lite snålt tilltaget. När den väl är igång och rullar, så kan du passa på att ta en kaffepaus. Att skrejpa med en webbläsare är en långsam process!

När IDS inte lyckas scrolla längre (oavsett om det berodde på att vi nått botten på listan, eller att sajten tog för lång tid på sig att ladda), så stannar den, och du kan använda de gröna nerladdningsknapparna för att spara en Excel-fil med resultatet!

Scraper

Det andra webbläsartillägg vi installerade är betydligt mer rudimentärt, men i gengäld får du här styra exakt vad nu hämtar för data (om du vill, mer om det i sista avsnittet).

Den här gången behöver du högerklicka på en av de saker du vill hämta, till exempel ett namn på en gruppmedlem. Välj ”Scrape similar”, för att öppna Scraper. Även det här verktyget försöker gissa vad du vill hämta, men här är logiken bakom gissningen mycket enklare, och sämre (för det mesta). Om du testar några gånger så bör du dock kunna få en lista över namn (och profillänkar) även här.

Till skillnad från IDS så hjälper oss inte Scraper att scrolla neråt på sidan, så det får vi göra själva. Att sida och trycka på <end>-tangenten till vi når botten är förstås ohyggligt tråkigt. Lyckligtvis går det att programmera webbläsaren att göra det åt oss! Tryck <F12> för att öppna de så kallade ”utvecklarverktygen”. De finns i de flesta moderna webbläsare, och låter dig bland annat köra Javascript-program direkt i webbläsaren.

När du öppnar utvecklarverktygen på en Facebooksida får du en stor röd varningstext:

Det är en varning att ta på allvar! Kör ALDRIG kod som du inte litar på eller helt och hållet förstår här. Det är fullt möjligt för att skript som körs här att, exempelvis, posta något i ditt namn på Facebook, eller värre saker än så. Vår kod är dock tämligen harmlös: Den ska scrolla till botten av sidan, och fortsätta göra det ända tills det inte går att scroll längre. 

Du klistrar in koden i sin helhet, och trycker <enter> för att köra den:

/*****************************************************************/
/* Adjust these three values as needed:                          */
/*                                                               */
var jpp_gMaxFails = 2;     // Stop trying after this many fails
var jpp_gMaxScrolls = 200; // Stop scolling after this many pages
var jpp_gDelay = 0.5;      // Wait this many seconds between pages
/*                                                               */
/* Slow internet connection? Try increasing the delay.           */
/* Shaky site? Try increasing number of allowed fails.           */
/* Expecting very long pages? Increase the number of scrolls.    */
/* Tiny/lowres display? Again, increase the number of scrolls.   */
/*                                                               */
/* Suggestions? Email stockhom@jplusplus.org                     */
/*                                                               */
/*****************************************************************/
var jpp_gCounter = 0;
var jpp_gLastHeight = null;
var jpp_gFailCounter = 0;
var jpp_gScroller = window.setInterval(function(){
  jpp_gCounter++;
  if (jpp_gLastHeight === document.body.scrollHeight){
    jpp_gFailCounter++
  } else {
    jpp_gFailCounter = 0;
  }
  if (jpp_gFailCounter > jpp_gMaxFails){clearInterval(jpp_gScroller)};
  jpp_gLastHeight = document.body.scrollHeight;
  window.scrollTo(0, jpp_gLastHeight);
  if (jpp_gCounter>jpp_gMaxScrolls){clearInterval(jpp_gScroller)};
}, jpp_gDelay * 1000);

Översta halvan är kommentarer och inställningar. Du kan ändra siffrorna vid till exempel jpp_gMaxFails för att ändra beteendet enligt beskrivningen. Därefter sätter skriptet en timer (window.setInterval) som varje sekund försöker scrolla nedåt. Om inget händer efter två  försök (det är 2:an efter jpp_gMaxFails), så tar vi bort timern (clearInterval).

Så är det återigen kaffepaus! När skriptet efter en tid scrollat till botten, kan du använda klicka på ”Scrape” i verktyget igen, för att hämta alla namn som nu finns på skärmen. Klicka sedan på ”copy to clipboard”, och klistra in resultatet i ett Excelark!

Överkurs: Skrejpa med xPath-uttryck

Om du är bekant med HTML sedan tidigare kan det vara värt att också lära sig lite xPath för att enklare kunna skrejpa webbsidor. Om det känns övermäktigt, så gå vidare till nästa steg, där vi börjar analysera datan vi samlat in!

Till vänster i Scrape-verktyget finns ett fält som heter xPath, med ett ganska långt och tillkrånglat uttryck. Om du vill bestämma exakt vad Scraper ska hämta från en webbsida, är det här du talar om det. xPath är ett språk för att (bland annat) peka ut information i HTML-dokument. Med xPath kan vi säga saker som ”ge mig alla rubriker på sidan”, eller ”ge mig all text på sidan som är kursiv och börjar på en 1:a”. 

För att kunna använda xPath behöver vi ha ett hum om hur HTML, koden som bygger upp webbsidor, ser ut. Om du högerklickar på ett namn i medlemslistan i din Facebookgrupp och väljer ”inspect element”, ”inspektera”, eller liknande, så öppnas utvecklarverktyget igen, men den här gången inte för att köra kod, utan för att visa dig hur HTML-koden som bygger upp just personens namn ser ut.

Det är lätt att bli överväldigad här, men det centrala är att HTML-koden är uppbyggda av taggar som kommer parvis (en start- och en sluttagg), och som är ordnade i en hierarki. Det är den hierarkin vi försöker hitta rätt i. På bilden ligger namnet Leo Wallentin, som jag har klicka på, i en tag som heter <a class=”…., som i sin tur ligger i <div class=”nc684nl6″>, som i sin tur ligger i <span class>. Taggarna är ordnade så att indragen följer hierarkin. Varje sluttagg ligger alltså rakt under sin starttagg. Den goda nyheten här är att du inte behöver förstå ett jota av vad taggarna betyder! Du behöver bara kunna känna igen dem.

 

Taggarna i det här exemplet heter ”span”, ”div” och ”a”. De kommer som sagt i par, med en starttagg och en sluttag: <span> och </span>. Snedstrecket betyder sluttagg. Dessutom innehåller de ibland en del annan information, så kallade attribut. På bilden till exempel class=”…”role=”link” och tabindex=”0″.

Vi kan använda all den här informationen, eller bara en liten del av den, för att peka ut mitt namn. Utmaningen är att hitta ett tillräckligt precist uttryck. Vi skulle till exempel kunna be om ”alla a-taggar” för att få mitt namn, men då skulle vi nog få med oss en massa andra saker på webbsidan som också ligger i en a-tagg. (En a-tagg är en länk, men det är egentligen inte viktigt nu). Vi kan specificera oss ytterligare genom att be om ”a-taggar i div-taggar i span-taggar”. Och vi kan till och med be om ”a-taggar som ligger i div-taggar som har ett attribut som heter class=”nc684nl6″”. Detta är vad verktyget vi använder har försökt gissa sig till i xPath-rutan. 

xPath-uttryck består av namn på taggar avdelade med snedstreck. //span/div/a betyder ”alla a-taggar som ligger i en div-tagg som ligger i en span-tagg” (testa gärna!).
Attribut anger vi med hakparenteser, så att //div[@class=’nc684nl6′] betyder ”alla div-taggar med class=’nc684nl6′ (notera citattecknen! De måste vara med här). Testa det uttrycket på Faceook-gruppsidan igen. Nu bör du få alla namn i medlemslistan , om allt gått rätt. 

En fördel med xPath-uttrycken är att du förstås kan spara dem och använda dem igen, när du väl listat ut dem! Så är //div[@class=’nc684nl6′] i skrivande stund (vintern 2020/2021) uttrycket som låter dig hämta alla namn i en Facebookgrupp. Det kommer fungera till nästa gång Facebook bygger om lite bakom kulisserna. Då behöver du hitta ett liknande uttryck igen.