Datajournalistik er et varmt emne i mit fag og det er der ikke noget at sige til - der bliver færre journalister og flere data. Kan computeren hjælpe os?
Min kollega Mads skriver om videnskabelige tidsskrifter, som ikke er helt fine i ærmet. Her er der ingen rigtig peer review, og der er vist tale om fup. Til sin artikel vil Mads gerne i kontakt med danske forskere, som har skrevet i den slags tidsskrifter. Men hvordan gør man lige det, spørger han mig.
Læs også: Ingeniøren: Over 100 danske forskere har publiceret i fuptidsskrifter ?
Jeg har tidligere eksperimenteret med Windows Subsystem for Linux (WSL), som giver mulighed for at bruge en Linux-terminal, med det kæmpe udvalg af smarte kommando-programmer, der medfølger, men på min Windows 10-pc, i stedet for Linux. Mon ikke det kan bruges til opgaven.
Et af de omtalte fup-forlag hedder WASET og har 'abstracts' på sin hjemmeside - sammendrag af tidsskrifternes artikler. Her står forfatternes navne, og det er dem, vi skal have fat i. Når vi først har dem, skal vi filtrere de dansk-klingende fra - men den tid, den sorg.
Windows Subsystem for Linux understøtter en række forskellige slags varianter. Vi går ind i Windows’ App-store og vælger Ubuntu, tidens populære Linux-smag.
Linux-terminal på Windows
Det er nu ikke helt rigtigt, at det er Ubuntu-Linux, der er tale om. Der er nemlig ikke rigtig nogen Linux-kerne i systemet, som benytter sig af Windows’ drivere og tjenester. I stedet får vi et terminalprogram - af varianten ‘Bash’ - og de kommandoer, som Ubuntu-terminalen byder på, sammen med dem, som kan installeres fra Ubuntus programbibliotek. Og der er mange.
Med et hack kan man endda installere grafiske desktop-programmer under WSL, med varierende held - men hvis man er nået til den yderlighed, er det nok bare bedre at lave et dual-boot-system på sin computer.
Jeg er glad og tilfreds med Windows 10, men Linux-terminalen kan jeg godt være misundelig på. Den kan bare alt muligt, som man ikke kan med Windows’ Dos-terminal - og den nye Windows Powershell er jeg ikke rigtig blevet gode venner med. Linux har jeg lidt erfaring med over årene - jeg installerede min første Red Hat for 20 år siden - så det er et sted at starte. Windows' mapper kan tilgås i Bash-terminalen med deres 'rigtige' filnavne - så som Man kan kopiere og indsætte fra Bash og til Windows med enter-tasten - der kopierer det, som er opmærket i terminalen med musen - og højreklik, der indsætter fra Windows' udklipsholder.Tips til Windows Subsystem for Linux
C:\Users\tan\Downloads\Mads Research
. Det er det navn, der fremkommer, hvis man indsætter markøren i et filvindues adresselinje. Så skal stien blot ændres til /mnt/c/Users/tan/Downloads/Mads Research.
Når WSL-Ubuntu er installeret, startes Windows’ terminal op. Det er denne terminal, der lægger ryg til Bash-programmer, men det er også muligt at afvikle Bash i andre Windows-baserede terminalprogrammer.
Kommandoer gør arbejdet
Nu kan vi gå i gang med opgaven. Mit Windows-drev C:/ kan findes i Bash med kommandoen
$ cd /mnt/c
Cd betyder change directory, ligesom i Dos. Hvis man har et langt og indviklet navn på en mappe, kan man bare skrive de første par bogstaver, og så trykke på tabulator-tasten - så skriver Bash selv navnet færdigt. Smart i en fart.
Jeg er ikke nogen haj til Linux-kommandoer, så jeg søger på nettet efter eksempler på det, jeg har til hensigt at gøre, og prøver mig lidt frem og tilbage. Resten af fortællingen herunder har ikke alle mine mislykkede forsøg med, men så svært var det nu hellere ikke. Det er heller ikke nødvendigvis den smarteste løsning jeg har fundet, men det går stærkt, så det gør ikke så meget.
Nok snak, lad os komme i gang. Vi navigerer hen til en ny mappe med cd og snupper en kopi af websitet, som det problematiske tidsskrift-forlag står bag. Vi downloader websitet med kommandoen wget, som kan downloade webresurser. Det ser sådan ud:
$ wget --mirror -R gif,jpg,png,xml,json https://waset.org
‘mirror’-flaget betyder, at vi ønsker at spejle websitet - altså lave en lokal kopi. ‘R’ står for reject, og betyder at vi ikke vil downloade resurser, hvis navn slutter med de filkoder, vi har angivet. Wget kigger ikke på selve filtypen, binært set, så hvis resursen ikke har nogen filkode, bliver den downloadet alligevel.
Download med wget, filtrer med grep
Vi sætter wget i sving, og kommandoen downloader i timevis...
Efter fem gigabyte stopper vi kommandoen, med Ctrl+C (der stopper alle slags kommandoers afvikling), for nu må det være nok. Vi skal ikke finde én specifik oplysning, men gennemtrawle for danske navne, og mon ikke fem gigabyte skulle være nok som udgangspunkt.
Næste skridt er at finde tekstlinjer i filerne, der indeholder forfatternavnene. Ved at kigge i en html-fil, finder vi forfatternes navne i en linje som denne:
<div class='block'><b>Authors:</b> <div class='presenter'><a href='/abstracts?q=Nishit L. Sanil' >Nishit L. Sanil</a>, <a href='/abstracts?q=Raza M. Khan' >Raza M. Khan</a></div></div>
Vi kan bruge Linux’ grep-kommando til at finde alle disse linjer med. Grep benytter regular expressions til at finde linjer i tekstfiler. Det ser sådan ud for os:
$ grep -Erh "<div class='presenter'>.*</div>$" * > ../ud1.txt
Der er tre flag til kommandoen, E, r, h, og dem kan man bare smaske sammen foran en enkelt streg. E betyder, at vi bruger moderne regular expressions, r står for ‘recursive’ og gør, at grep også kigger i underliggende mapper, og h - hvad gør h?
Bash har en indbygget manual, der giver en nødtørftig forklaring af kommandoerne. Den kaldes med:
$ man grep
Hvis vi bladrer lidt ned i manualen, står der følgende:
-h, --no-filename Suppress the prefixing of file names on output. This is the default when there is only one file (or only standard input) to search.
Grep skriver nemlig som udgangspunkt, hvor i en fil den har fundet et match, men det skal vi ikke bruge - vi skal bare have den fundne streng. Man skal også lige være obs på, at kommandoernes flag er case-sensitive, som man siger på programmør-dansk - så stort H gør noget helt andet.
Efter flagene angiver vi streng-mønstret
"<div class='presenter'>.*</div>$"
Det betyder, at vi vil snuppe teksten, der står inde i det givne div-element i html-dokumenterne.
Derefter kommer der en asterisk *, som betyder ‘søg i alle filer’, og kommandoen slutter med > ../ud1.txt, som betyder: Skriv uddata til filen ud1.txt, der befinder sig i den overliggende mappe - så der ikke bliver for meget rod i mappen, og vi kan kigge resultatet igennem bag efter.
Grep bruger lidt til på sit arbejde, og så kommer Bash-prompten tilbage igen. Grep skriver en linje, for hver, den har fundet, så vi kan tælle antallet af linjer med kommandoen wc, word count (der tæller linjer, når kommandoen udstyres med flaget -l):
$ wc -l ud1.txt
Vi kan også kigge på starten af filen med kommandoen head:
$ head ud1.txt <div class='block'><b>Authors:</b> <div class='presenter'><a href='/abstracts?q=Roman Kalvin' >Roman Kalvin</a>, <a href='/abstracts?q=Anam Nadeem' >Anam Nadeem</a>, <a href='/abstracts?q=Saba Arif' >Saba Arif</a></div></div>
De fundne linjer ser ud som html-klumpen ovenfor, og nu starter vi med at slette alle html-tags.
Slet med sed, sorter med sort
Her bruger vi sed-kommandoen, som kan behandle en strøm af tekst på forskellige måder. Lidt søgning på nettet fører til denne løsning:
$ sed "s/<[^>]\+>//g" ud1.txt > ud2.txt
Det første argument er et regulært udtryk, ligesom med grep. ‘s’ står for substitute, erstat, som i vores tilfælde erstatter det fundne med ingenting - med andre ord sletter den delstrenge, som passer til udtrykket, der siger følgende: ’Noget, der starter med en <, efterfulgt af noget, som ikke er >, og som afsluttes med en >’. ‘//g’ betyder globalt, dvs. alle linjer.
Summa summarum: Alle html-tags slettes. Dem skal vi ikke bruge. Nu ser resultatet sådan ud:
$ head ud2* Authors: Roman Kalvin, Anam Nadeem, Saba Arif Authors: Barenten Suciu
(Man behøver ikke skrive hele filnavnet - en stjerne kan gøre det ud for halen i navnet.) Nu skal vi have slettet "Authors:" og have lavet komma om til linjeskift, så vi får ét navn pr. linje. Vi udfører begge dele i en glidende tackling med kommandoen:
$ sed 's/Authors: //' ud2.txt | tr ',' '\n' > ud3.txt
'Pipe'-symbolet | sender uddata fra sed-kommandoen over i tr (for 'translate'), som udskifter komma med linjeskift.
Den er dog ikke helt i vinkel. Der er lidt snask i starten af nogle af linjerne:
$ head ud3.txt Roman Kalvin Anam Nadeem Saba Arif
Det fjerner vi med den noget uigennemskuelige kommando:
$ awk '{$1=$1};1' ud3.txt | sort | uniq > ud4.txt
Awk-kommandoen trimmer vores linjer, og vi 'piper' uddata videre til sort, der sorterer linjerne alfabetisk, og videre til uniq, der fjerner dubletter.
Match med danske efternavne
Nu skal vi finde dansk-klingende navne blandt dem på listen.
På Ankestyrelsens hjemmeside finder vi en liste over såkaldt frie efternavne, som er de efternavne, der bæres af mere end 2.000 personer. Der er 196 navne på listen, og mon ikke det er et meget godt net i forhold til at finde navne, især da Danmarks Statistik fortæller os, at de blot 20 mest brugte navne dækker knap to millioner danskere.
Her begår jeg den frygtelige fejl at bruge Windows-programmet Notepad++, til at gemme tekstfilen med efternavne, med CR-LF som linjeafslutningstegn, mens Linux og Unix bruger LF. Det tager et stykke tid for mig at finde ud af, at det er det, der gør, at jeg ikke kan få grep-kommandoen til at makke ret.
Senere finder jeg ud af, at jeg kan ændre linjeskift i Notepad++ med menuen Rediger > Linjeskiftkonvertering, som klarer konvertering mellem Windows og Unix. Herefter går det godt.
Vi gemmer efternavnene i en tekstfil, med det rigtige LF-linjeafslutningstegn, og grep'er igen:
$ grep -wFf navne.txt ud4.txt > ud5.txt
Denne udgave af grep finder ordene - efternavnene - i den første fil, når de optræder i den anden fil. Flaget 'w' kigger kun efter hele ord, og flaget 'F' slår regular expressions fra, så der søges på eksakte strenge.
Det giver en liste, der starter således - vi har dog ændret navnene lidt.
A. Buk A. C. Jensen A. F. Petersen A. Vang Alex Michelsen
Vi gjorde det samme med hjemmesiden for forlaget OMICS, og de fundne navne indgik i min kollega Mads' videre research.
Tekst i PDF'er
I midlertid er der også en del artikler i PDF-format i det downloadede materiale fra WASET. Det kunne være interessant også at kigge på navne i disse filer. Disse PDF-dokumenter befinder sig i en bestemt mappe.
Inde i mappen afvikler vi dette shell-script:
for file in *; do fileinfo=$(file $file) if [[ $fileinfo = \*"PDF"\* ]]; then newfilename=$file.txt echo ${newfilename} pdftotext $file ${newfilename} fi done
(I Bash kan man bare kopiere scriptet ind, og så kører det lystigt.)
For-linjen gennemløber alle filer i mappen. Fileinfo-variablen sættes til uddata fra file-kommandoen, som skriver oplysninger om hver enkelt fil. Hvis den indeholder noget med 'PDF' udføres if-sætningen.
Kroppen i if-sætningen laver et nyt filnavn, som ender med '.txt'. Derefter udtrækkes teksten i PDF'en med kommandoen pdftotext.
De fremkomne tekstdokumenter indeholder linjer som:
Authors : Mahvish Anjum
– og så kan vi bruge de samme teknikker som tidligere til at udtrække og filtrere navnene.

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.
Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.
Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.
Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.