Social Data Science - Data Gathering · I forhold til vores velfærdsstat er vi nødt til at sælge...

Post on 18-Oct-2020

1 views 0 download

transcript

social data scienceData Gathering

Sebastian BarfortAugust 10, 2016

University of CopenhagenDepartment of Economics

1/54

ethics

On the ethics of web scraping and data journalism

If an institution publishes data on its website, this datashould automatically be public

If a regular user can’t access the data, we shouldn’t try toget it (that would be hacking)

Always read the user terms and conditions

Always check the robots.txt file, which states what isallowed to be scraped

2/54

rules of web scraping

1. You should check a site’s terms and conditions before youscrape them. It’s their data and they likely have some rules togovern it.

2. Be nice - A computer will send web requests much quicker thana user can. Make sure you space out your requests a bit so thatyou don’t hammer the site’s server.

3. Scrapers break - Sites change their layout all the time. If thathappens, be prepared to rewrite your code.

4. Web pages are inconsistent - There’s sometimes some manualclean up that has to happen even after you’ve gotten your data.

3/54

4/54

how does a web page look like?

https://sebastianbarfort.github.io/

5/54

motivating example

https://en.wikipedia.org/wiki/Table_%28information%29

6/54

example

rvest is a nice R package for scraping web pages that don’t have anAPI

To extract something, you start with selectorgadget to figure outwhich css selector matches the data we wantSelectorgadget is a browser extension for quickly extracting desiredparts of an HTML page.

With some user feedback, the gadget find out the CSS selector thatreturns the highlighted page elements.

7/54

library(”rvest”)link = paste0(”http://en.wikipedia.org/”,

”wiki/Table_(information)”)link.data = link %>%read_html() %>%html_node(”.wikitable”) %>%# extract first node with class wikitablehtml_table()# then convert the HTML table into a data frame

html_table usually only works on ‘nicely’ formatted HTML tables.

8/54

First name Last name Age

Tinu Elejogun 14Blaszczyk Kostrzewski 25Lily McGarrett 16Olatunkboh Chijiaku 22Adrienne Anthoula 22Axelia Athanasios 22Jon-Kabat Zinn 22

9/54

This is a nice format? Really? Yes, really. It’s the format used torender tables on webpages (remember: programming sucks)

<table class=”wikitable”><tr>

<th>First name</th><th>Last name</th><th>Age</th>

</tr><tr>

<td>Bielat</td><td>Adamczak</td><td>24</td>

</tr>...

</table>

10/54

scraping jyllands posten

http://jyllands-posten.dk/

11/54

scraping jyllands posten in rvest

Assume we want to extract the headlines

· Fire up Selectorgadget· Find the correct selector

· css selector: .artTitle a· Want to use xpath? no problem.

12/54

scraping headlines

css.selector = ”.artTitle a”link = ”http://jyllands-posten.dk/”

jp.data = link %>%read_html() %>%html_nodes(css = css.selector) %>%html_text()

13/54

## [1] ”\r\n\t\t\tTruende milliardtab tvinger borgmestre til U-vending: Vil sejle udenlandsk affald til Amager ”## [2] ”\r\n\t\t\tHvem er mest undertrykt her? ”## [3] ”\r\n\t\t\tForslag: Slut med burka og dobbelt statsborgerskab ”## [4] ”\r\n\t\t\tDna-spor har ført til ny teori om ruten til Amerika ”## [5] ”\r\n\t\t\tLiveblog fra OL: Følg danskerne, stjernerne og de store begivenheder ”

14/54

garbage

Notice that there are still some garbage characters in the scrapedtext

So we need our string processing skills to clean the scraped data

Can be done in many ways

library(”stringr”)jp.data1 = jp.data %>%str_replace_all(pattern = ”\\n|\\t|\\r” ,

replacement = ””)

15/54

Truende milliardtab tvinger borgmestre til U-vending: Vil sejle udenlandsk affald til AmagerHvem er mest undertrykt her?Forslag: Slut med burka og dobbelt statsborgerskabDna-spor har ført til ny teori om ruten til AmerikaLiveblog fra OL: Følg danskerne, stjernerne og de store begivenhederCancellara tog OL-guld i enkeltstart

16/54

str_trim

str_trim: Trim whitespace from start and end of string

library(”stringr”)jp.data2 = jp.data %>%str_trim()

17/54

Truende milliardtab tvinger borgmestre til U-vending: Vil sejle udenlandsk affald til AmagerHvem er mest undertrykt her?Forslag: Slut med burka og dobbelt statsborgerskabDna-spor har ført til ny teori om ruten til AmerikaLiveblog fra OL: Følg danskerne, stjernerne og de store begivenhederCancellara tog OL-guld i enkeltstart

18/54

extracting attributes

What if we also wanted the links embedded in those headlines?

jp.links = link %>%read_html(encoding = ”UTF-8”) %>%html_nodes(css = css.selector) %>%html_attr(name = ’href’)

19/54

http://finans.dk/finans/erhverv/ECE8904112/truende-milliardtab-tvinger-borgmestre-til-uvending-vil-sejle-udenlandsk-affald-til-amager/http://jyllands-posten.dk/sport/ol/ECE8909430/hvem-er-mest-undertrykt-her/http://www.jyllands-posten.dk/protected/premium/international/ECE8909823/vi-afviser-denne-delte-loyalitet-de-der-vil-gaa-ind-i-udenlandske-regeringers-politik-foreslaar-vi-at-forlade-tyskland/http://jyllands-posten.dk/nyviden/ECE8909952/de-foerste-mennesker-kom-til-amerika-via-en-anden-rute-end-hidtil-antaget/http://jyllands-posten.dk/sport/ol/ECE8898888/liveblog-fra-ol-foelg-danskerne-stjernerne-og-de-store-begivenheder/http://jyllands-posten.dk/sport/ol/cykling/ECE8909671/cancellara-tog-olguld-i-enkeltstart/

20/54

looping through collection of links

We now have jp.links, a vector of all the links to news storiesfrom JP’s front page

Let’s loop through every link and extract some information.

21/54

cleaning the vector

Assume that we’re only interested in domestic and internationalpolitics

jp.keep = jp.links %>%str_detect(”politik|indland|international”)

jp.links.clean = jp.links[jp.keep]jp.remove.index = jp.links.clean %>%str_detect(”protected|premium|finans”)

jp.links.clean = jp.links.clean[!jp.remove.index]

22/54

grab info from first link

first.link = jp.links.clean[1]first.link.text = first.link %>%read_html(encoding = ”UTF-8”) %>%html_nodes(”#articleText”) %>%html_text()

23/54

## [1] ”\r\n\t\tKongehuset og Udenrigsministeriet har gjort ret i at udsætte statsbesøget til Tyrkiet i oktober, lyder det fra langt de fleste af udenrigsordførerne på Christiansborg. Men ikke alle er enige om, hvorfor det er den rigtige beslutning. Mens det fra udenrigsminister Kristian Jensen (V) tidligere på dagen lød, at beslutningen var blevet truffet udelukkende af sikkerhedsmæssige årsager, fordi Tyrkiet er i undtagelsestilstand, glæder man sig hos Enhedslisten over det implicitte signal, som nogle vælger at tolke ud af udsættelsen. »Jeg synes, det er positivt, at udenrigsministeren har fulgt Enhedslistens opfordring og nu aflyser besøget. Det ville være fuldstændig absurd, hvis den tyrkiske præsident, Reccep Tayyip Erdogan, skulle have opbakning med et statsbesøg fra Danmark på et tidspunkt, hvor den kritiske opposition og journalister fængsles,« siger Nikolaj Villumsen, udenrigsordfører (EL). \r\n\t\t\t\t\r\n\t\t\tDanmark udsætter statsbesøg i Tyrkiet\r\n\t\t\t\r\n Men der er bare to ting. For det første er der tale om en udsættelse og ikke en aflysning, og for det andet ligger der altså ifølge udenrigsministeren ikke en »politisk overvejelse bag udsættelsen«: »For det er jo ikke sådan, at vi ikke kan besøge lande, vi ikke er enige med om alting,« sagde Kristian Jensen onsdag til Ritzau. Og den beslutning får ros fra blandt andre Socialdemokraterne. »Det er vigtigt for mig, at forklaringen går på sikkerhedsmæssige hensyn, for jeg synes, at det hører med til Danmarks aktivistiske udenrigspolitik at have dialog også med styrer og regimer, som vi ikke bryder os om,« siger Nick Hækkerup, udenrigsordfører (S), og fortsætter: »Vores mulighed for at påvirke verden afhænger af, at vi er til stede og snakker med folk, også der, hvor vi måske ikke er enige med, hvordan tingene gøre. Og der er virkeligt meget at kritisere Tyrkiet for i øjeblikket, så derfor er det vigtigt at holde dialogen kørende.« \r\n\t\t\t\t\r\n\t\t\tKristian Jensen: Udsat statsbesøg i Tyrkiet handler om sikkerhed\r\n\t\t\t\r\n Også Dansk Folkeparti mener, at det er en fornuftig beslutning, særligt fordi den er blevet truffet i samarbejde med den tyrkiske regering. Statsbesøget er tidligere blevet kritiseret af både Alternativet, Enhedslisten og SF, fordi det kunne tolkes som en blåstempling af den politik, præsident Reccep Tayyip Erdogan har ført i landet, både før og efter statskuppet i Tyrkiet.Men den kritik mener Dansk Folkepartis udenrigsordfører, Søren Espersen, er forkert. Han kalder den politiske diskussion af statsbesøgene for et »cirkus,« der er »unfair over for dronningen«, og konkluderer derefter, at: »Det afgørende for mig er, at vi samhandler med alle lande på jorden, uanset hvilket styre de har; at vi har diplomatiske forbindelser med alle, også dem, vi ikke kan lide; og at statsbesøg og diplomatiske arrangementer af den her art kører sit eget liv. Vi kan ikke have en situation, hvor det eneste land, vi kan besøge efterhånden, er Norge. I forhold til vores velfærdsstat er vi nødt til at sælge vores varer til udlandet, så vi kan bevare den stærke økonomi, vi har,« siger udenrigsordføreren, der dog straks efter understreger: »Men vi burde fortælle tyrkerne, at de aldrig nogensinde bliver medlemmer af EU.« \r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\tInternational 09.08.2016\r\n\t\t\t\t\t\t\t\t\t\r\n \r\n\r\n \r\n \r\n \n\t\t\t\t\n\t\t\t\t\t\r\n \r\n \r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\tTyske politikere kritiserer Ankaras forlængede arm\r\n\t\t\t\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n Oven på det mislykkede kup i Tyrkiet, undtagelsestilstanden og pro-Erdogan-demonstrationen i Köln retter medlemmer af Forbundsdagen en skarp kritik af flere tyrkisk-muslimske organisationer i Tyskland. \r\n\t\t\t\t\t\t\t\t\t\t\t\r\n \r\n \r\n \r\n \r\n \r\n Hos Liberal Alliance er udenrigsordfører Mette Bock ikke overrasket over beslutningen, og hun mener, at begrundelsen er den eneste fornuftige: »Den eneste fornuftige begrundelse, hvis man skal være på diplomatiets knivsæg, er jo netop at referere til sikkerhedsmæssige grunde og ikke til noget, som handler om den nuværende politiske situation. Ellers politiserede man jo hele Kongehusets virke på en måde, som ikke er hensigtsmæssig - heller ikke på længere sigt,« siger hun og mener, at det netop er Udenrigsministeriets opgave at værne om, at Kongehuset forbliver upolitisk. »Vi har meget ofte diskussioner om Kongehusets besøg i forskellige lande, og sådan må det være i et åbent demokrati, men for mig at se må det væsentligste være, at vi videst mulige forstand værner om Kongehusets armslængde i forhold til konkret politik.« Men det er Rasmus Nordqvist, udenrigsordfører i Alternativet ganske uenig i. Han glæder sig over, at dronningen har udsat sit statsbesøg, men er ikke begejstret for begrundelsen. »Jeg synes, at det er en skam, at vi tilsyneladende har truffet den beslutning på baggrund af sikkerhedog ikke fordi, at vi skal passe på med, hvem vi støtter op om, når vi tager på statsbesøg,« siger han. \r\n\t\t\t\t\r\n\t\t\tSkal Danmark sige stop? Dronningerejse og løfter om dødsstraf presser regeringen\r\n\t\t\t\r\n Rasmus Nordqvist har kritiseret statsbesøget og talt for, at det skulle aflyses tidligere. Han vil bevare en kritisk dialog med Tyrkiet, men understreger også at Kongehuset af netop den grund intet har at gøre i landet. Ikke så længe kongefamilien holder sig fra politik, i hvert fald. »Jeg mener ikke, at vi skal lukke i for handel med Tyrkiet, og jeg synes også, at det er fint, når vores ministre har en kritisk dialog blandt andet om menneskerettigheder i Tyrkiet. Men når kongefamilien tager derned, så kommer de ikke med med den hensigt. Det så vi også i Saudi-Arabien, da kronprinseparret var der. Kongefamilien kommer som en reklamesøjle for Danmark og blåstempler de her regimer og lande. Der er en stor forskel, synes jeg,« siger udenrigsordføreren. Nikolaj Villumsen, udenrigsordfører (EL), hæfter sig knapt så meget ved begrundelsen som hans kolleger på Christiansborg. »Jeg synes ærlig talt, at begrundelsen lyder som en søforklaring, og jeg tror, at spindoktorerne har haft travlt i Udenrigsministeret. Men det ændrer ikke på resultatet; nemlig, at besøget udskydes, som vi har opfordret til fra Enhedslisten,« siger han. ”

24/54

while we’re at it…

Let’s also grab the author of the article

first.link %>%read_html(encoding = ”UTF-8”) %>%html_nodes(”.bylineAuthorName span”) %>%html_text()

## [1] ”THOMAS AAGAARD”

25/54

turning it into a function

Function: automate the boring stuff.

Iteration: apply a function to many elements.

Let’s write a function that for each new link will return article text.

26/54

scraping function

scrape_jp = function(link){my.link = link %>%

read_html(encoding = ”UTF-8”)author = my.link %>%

html_nodes(”.bylineAuthorName span”) %>%html_text()

if (length(author) == 0){ author = NA }link.text = my.link %>%

html_nodes(”#articleText”) %>%html_text()

if (length(link.text) == 0){ link.text = NA }return(data.frame(author = author,

link = link, text = link.text ))}

27/54

Now we can iterate through all the links and grab the data

library(”purrr”)jp.article.data = jp.links.clean[1:5] %>%map_df(scrape_jp)

28/54

Output

## Observations: 5## Variables: 3## $ author (chr) ”THOMAS AAGAARD”, ”MADS BONDE BROBERG”, ”SARAH KOTT”, ”...## $ link (chr) ”http://jyllands-posten.dk/politik/ECE8909425/politiker...## $ text (chr) ”\r\n\t\tKongehuset og Udenrigsministeriet har gjort re...

29/54

exercise

1. Go to http://www.econ.ku.dk/ansatte/vip/2. Create a vector of all links to the researcher’s personal homepage

3. Go to each researchers page and grab their title4. Create a data frame of all researchers’ names and title

30/54

name title

Kibrom Araya Abay PostdocSteffen Altmann LektorAsger Lau Andersen AdjunktSebastian Barfort Post DocJeanet Sinding Bentzen Adjunkt

31/54

Gathering data from APIs

32/54

api

API: Application Program Interface

Programmatic instructions for how to interact with a piece ofsoftware

Many data sources have API’s - largely for talking to other webinterfaces

Consists of a set of methods to search, retrieve, or submit data to, adata source

We can write R code to interface with an API (lot’s requireauthentication though)

Many packages already connect to well-known API’s

33/54

apis

Most APIs are REST APIsImplemented in R in httr package.GET: Retrieve whatever is specified by the URL

POST: Create resource at URL with given data

34/54

example: github issues

https://developer.github.com/v3/issues/

35/54

library(”httr”)url = ”https://api.github.com/repos/hadley/dplyr/issues”get.1 = GET(url, query = list(state = ”closed”))get.2 = GET(url, query = list(state = ”closed”,

labels = ”bug”))

36/54

api output

Output from APIs come in one of two formats: XML or JSONJSON: Javascript Object Notation

· Widely used in web APIs· Becoming de facto standard for online data format· Read into R with jsonlite package

XML: Extensible Markup Language

· Less common today· Read into R with xml2 package

37/54

JSON

{”Title”: ”Frozen”,”Year”: ”2013”,”Rated”: ”PG”,”Released”: ”27 Nov 2013”,”Runtime”: ”102 min”,”Genre”: ”Animation, Adventure, Comedy”,”Director”: ”Chris Buck, Jennifer Lee”...}

38/54

XML

<?xml version=”1.0”?><catalog>

<book id=”bk101”><author>Gambardella, Matthew</author><title>XML Developer’s Guide</title><genre>Computer</genre><price>44.95</price><publish_date>2000-10-01</publish_date><description>An in-depth look at creating applicationswith XML.</description>

</book>

39/54

parsing

library(”jsonlite”)get.1.parsed = content(get.1, as = ”text”)get.1.data = fromJSON(get.1.parsed, flatten = TRUE)get.2.parsed = content(get.2, as = ”text”)get.2.data = fromJSON(get.2.parsed, flatten = TRUE)

40/54

get.1.data

number comments user.login closed_at

2064 2 pierucci 2016-08-10T16:52:25Z2063 0 santhoshn24 2016-08-10T12:52:36Z2062 0 santhoshn24 2016-08-10T12:52:25Z2061 4 phirsch 2016-08-10T12:49:11Z2050 5 dhagmann 2016-08-02T14:12:36Z2039 1 Tutuchan 2016-07-27T11:44:36Z2037 2 jlegewie 2016-08-09T12:34:08Z2034 2 joethorley 2016-07-22T19:16:25Z

41/54

get.2.data

number comments user.login closed_at

1870 6 RobertMyles 2016-06-20T13:24:47Z1831 1 iangow 2016-07-05T12:30:09Z1803 6 mdsumner 2016-05-26T15:47:38Z1800 4 jennybc 2016-05-26T13:32:38Z1789 4 davharris 2016-06-01T19:53:06Z1779 4 hadley 2016-05-27T20:02:17Z1751 7 gtumuluri 2016-05-27T19:37:26Z1750 2 karldw 2016-05-03T09:17:42Z

42/54

packages for working with apis

Luckily, you rarely have to access APIs manually

R already has a lot of packages for easy access to many APIsCheck some of them out here

43/54

twitter

twitteR is an R package which provides access to the Twitter APICreate an app here

library(”twitteR”)consumer_key = ’your key’consumer_secret = ’your secret’access_token = ’your access token’access_secret = ’your access secret’

setup_twitter_oauth(consumer_key,consumer_secret,access_token,access_secret)

searchTwitter(”#dkpol”, n=500)

44/54

gmapsdistance

Another useful package is gmapsdistanceIt uses the Google Maps Distance Matrix API to compute thedistance(s) and time(s) between two points or two vectors of points

install.packages(”gmapsdistance”)

46/54

library(”gmapsdistance”)results = gmapsdistance(origin = ”København”,

destination = ”Roskilde”,mode = ”driving”)

47/54

## $Time## [1] 2125#### $Distance## [1] 34657#### $Status## [1] ”OK”

48/54

Compute walking distance between Marathon and Athens

results = gmapsdistance(origin = ”38.1621328+24.0029257”,destination = ”37.9908372+23.7383394”,mode = ”walking”)

49/54

## $Time## [1] 30025#### $Distance## [1] 39507#### $Status## [1] ”OK”

50/54

geocode

library(”ggmap”)geocode(”Økonomisk Institut,

Københavns Universitet, København”)

## lon lat## 1 12.56834 55.6761

51/54

geocode(”The White House”)

## lon lat## 1 -77.03653 38.89768

52/54

statistics denmark api

https://github.com/rOpenGov/dkstatLets you programatically work with Statistics Denmark data

library(”devtools”)install_github(”rOpenGov/dkstat”)

53/54