social data science Data Gathering Sebastian Barfort August 10, - - PowerPoint PPT Presentation

social data science
SMART_READER_LITE
LIVE PREVIEW

social data science Data Gathering Sebastian Barfort August 10, - - PowerPoint PPT Presentation

social data science Data Gathering Sebastian Barfort August 10, 2016 University of Copenhagen Department of Economics 1/54 ethics On the ethics of web scraping and data journalism If an institution publishes data on its website, this data


slide-1
SLIDE 1

social data science

Data Gathering

Sebastian Barfort August 10, 2016

University of Copenhagen Department of Economics 1/54

slide-2
SLIDE 2

ethics

On the ethics of web scraping and data journalism If an institution publishes data on its website, this data should automatically be public If a regular user can’t access the data, we shouldn’t try to get it (that would be hacking) Always read the user terms and conditions Always check the robots.txt file, which states what is allowed to be scraped

2/54

slide-3
SLIDE 3

rules of web scraping

  • 1. You should check a site’s terms and conditions before you

scrape them. It’s their data and they likely have some rules to govern it.

  • 2. Be nice - A computer will send web requests much quicker than

a user can. Make sure you space out your requests a bit so that you don’t hammer the site’s server.

  • 3. Scrapers break - Sites change their layout all the time. If that

happens, be prepared to rewrite your code.

  • 4. Web pages are inconsistent - There’s sometimes some manual

clean up that has to happen even after you’ve gotten your data.

3/54

slide-4
SLIDE 4

4/54

slide-5
SLIDE 5

how does a web page look like?

https://sebastianbarfort.github.io/

5/54

slide-6
SLIDE 6

motivating example

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

6/54

slide-7
SLIDE 7

example

rvest is a nice R package for scraping web pages that don’t have an API To extract something, you start with selectorgadget to figure out which css selector matches the data we want Selectorgadget is a browser extension for quickly extracting desired parts of an HTML page. With some user feedback, the gadget find out the CSS selector that returns the highlighted page elements.

7/54

slide-8
SLIDE 8

library(”rvest”) link = paste0(”http://en.wikipedia.org/”, ”wiki/Table_(information)”) link.data = link %>% read_html() %>% html_node(”.wikitable”) %>% # extract first node with class wikitable html_table() # then convert the HTML table into a data frame html_table usually only works on ‘nicely’ formatted HTML tables.

8/54

slide-9
SLIDE 9

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

9/54

slide-10
SLIDE 10

This is a nice format? Really? Yes, really. It’s the format used to render 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

slide-11
SLIDE 11

scraping jyllands posten

http://jyllands-posten.dk/

11/54

slide-12
SLIDE 12

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

slide-13
SLIDE 13

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

slide-14
SLIDE 14

## [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

slide-15
SLIDE 15

garbage

Notice that there are still some garbage characters in the scraped text 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

slide-16
SLIDE 16

Truende milliardtab tvinger borgmestre til U-vending: Vil sejle udenlandsk affald til Amager Hvem er mest undertrykt her? Forslag: Slut med burka og dobbelt statsborgerskab Dna-spor har ført til ny teori om ruten til Amerika Liveblog fra OL: Følg danskerne, stjernerne og de store begivenheder Cancellara tog OL-guld i enkeltstart

16/54

slide-17
SLIDE 17

str_trim

str_trim: Trim whitespace from start and end of string library(”stringr”) jp.data2 = jp.data %>% str_trim()

17/54

slide-18
SLIDE 18

Truende milliardtab tvinger borgmestre til U-vending: Vil sejle udenlandsk affald til Amager Hvem er mest undertrykt her? Forslag: Slut med burka og dobbelt statsborgerskab Dna-spor har ført til ny teori om ruten til Amerika Liveblog fra OL: Følg danskerne, stjernerne og de store begivenheder Cancellara tog OL-guld i enkeltstart

18/54

slide-19
SLIDE 19

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

slide-20
SLIDE 20

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

slide-21
SLIDE 21

looping through collection of links

We now have jp.links, a vector of all the links to news stories from JP’s front page Let’s loop through every link and extract some information.

21/54

slide-22
SLIDE 22

cleaning the vector

Assume that we’re only interested in domestic and international politics 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

slide-23
SLIDE 23

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

slide-24
SLIDE 24

## [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 sikkerhed

  • g 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

slide-25
SLIDE 25

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

slide-26
SLIDE 26

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

slide-27
SLIDE 27

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

slide-28
SLIDE 28

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

slide-29
SLIDE 29

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

slide-30
SLIDE 30

exercise

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

page

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

30/54

slide-31
SLIDE 31

name title Kibrom Araya Abay Postdoc Steffen Altmann Lektor Asger Lau Andersen Adjunkt Sebastian Barfort Post Doc Jeanet Sinding Bentzen Adjunkt

31/54

slide-32
SLIDE 32

Gathering data from APIs

32/54

slide-33
SLIDE 33

api

API: Application Program Interface Programmatic instructions for how to interact with a piece of software Many data sources have API’s - largely for talking to other web interfaces Consists of a set of methods to search, retrieve, or submit data to, a data source We can write R code to interface with an API (lot’s require authentication though) Many packages already connect to well-known API’s

33/54

slide-34
SLIDE 34

apis

Most APIs are REST APIs Implemented in R in httr package. GET: Retrieve whatever is specified by the URL POST: Create resource at URL with given data

34/54

slide-35
SLIDE 35

example: github issues

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

35/54

slide-36
SLIDE 36

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

slide-37
SLIDE 37

api output

Output from APIs come in one of two formats: XML or JSON JSON: 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

slide-38
SLIDE 38

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

slide-39
SLIDE 39

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 applications with XML.</description> </book>

39/54

slide-40
SLIDE 40

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

slide-41
SLIDE 41

get.1.data number comments user.login closed_at 2064 2 pierucci 2016-08-10T16:52:25Z 2063 santhoshn24 2016-08-10T12:52:36Z 2062 santhoshn24 2016-08-10T12:52:25Z 2061 4 phirsch 2016-08-10T12:49:11Z 2050 5 dhagmann 2016-08-02T14:12:36Z 2039 1 Tutuchan 2016-07-27T11:44:36Z 2037 2 jlegewie 2016-08-09T12:34:08Z 2034 2 joethorley 2016-07-22T19:16:25Z

41/54

slide-42
SLIDE 42

get.2.data number comments user.login closed_at 1870 6 RobertMyles 2016-06-20T13:24:47Z 1831 1 iangow 2016-07-05T12:30:09Z 1803 6 mdsumner 2016-05-26T15:47:38Z 1800 4 jennybc 2016-05-26T13:32:38Z 1789 4 davharris 2016-06-01T19:53:06Z 1779 4 hadley 2016-05-27T20:02:17Z 1751 7 gtumuluri 2016-05-27T19:37:26Z 1750 2 karldw 2016-05-03T09:17:42Z

42/54

slide-43
SLIDE 43

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 APIs Check some of them out here

43/54

slide-44
SLIDE 44

twitter

twitteR is an R package which provides access to the Twitter API Create 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

slide-45
SLIDE 45

interesting api packages

[rfacebook](https://github.com/pablobarbera/Rfacebook) streamR instaR rtimes tuber ggmap

45/54

slide-46
SLIDE 46

gmapsdistance

Another useful package is gmapsdistance It uses the Google Maps Distance Matrix API to compute the distance(s) and time(s) between two points or two vectors of points install.packages(”gmapsdistance”)

46/54

slide-47
SLIDE 47

library(”gmapsdistance”) results = gmapsdistance(origin = ”København”, destination = ”Roskilde”, mode = ”driving”)

47/54

slide-48
SLIDE 48

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

48/54

slide-49
SLIDE 49

Compute walking distance between Marathon and Athens results = gmapsdistance(

  • rigin = ”38.1621328+24.0029257”,

destination = ”37.9908372+23.7383394”, mode = ”walking”)

49/54

slide-50
SLIDE 50

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

50/54

slide-51
SLIDE 51

geocode

library(”ggmap”) geocode(”Økonomisk Institut, Københavns Universitet, København”) ## lon lat ## 1 12.56834 55.6761

51/54

slide-52
SLIDE 52

geocode(”The White House”) ## lon lat ## 1 -77.03653 38.89768

52/54

slide-53
SLIDE 53

statistics denmark api

https://github.com/rOpenGov/dkstat Lets you programatically work with Statistics Denmark data library(”devtools”) install_github(”rOpenGov/dkstat”)

53/54

slide-54
SLIDE 54

extensions

selanium selaniumPipes tabulizer

54/54