2017-12-06 19 views
-1

Ich bin Web Scraping in R aus dem WFP der UN-Website, um einen Datensatz mit den Updates zur Ernährungssicherheit (http://www.fao.org/countryprofiles/en/) zu erstellen. Die Pakete sind: rvest, stringr, tidyr, data.table, plyr, xml2, jsonlite. Dennoch habe ich in meinen Datensatz Landnamen, URL der Artikel, Titel der Artikel und Text der Artikel importiert. Nun, aus Gründen der Parsing leichter, würde ich eine neue Variable einschließlich einiger Schlüsselwort mich interessiert (z. B. "Ernährungssicherheit", "Dürre", etc.) und beachten Sie die Vorkommen der oben genannten Schlüsselwörter. Diese Variable würde meine Forschung enorm vereinfachen. Irgendwelche Vorschläge?R webscraping setting keywords

Hier ist der grundlegende Code, den ich verwende.

## 01. Creating a function in order to scrape data from a website (in this case, FAO's) 

WFP_get_news <- function(countries) {              GET(
url = "http://www1.wfp.org/countries/common/allnews/en/", 
query = list(countries=countries) 
) -> res 

warn_for_status(res) 

if (status_code(res) > 399) return(NULL) 

out <- content(res, as="text", encoding="UTF-8") 
out <- jsonlite::fromJSON(out) 
out$countries <- countries 

tbl_df(out) 
} 


## 02. Setting all the Country urls in order for them to be automatically scraped 

pb <- progress_estimated(length(countrycode_data$countries[])) 
map_df(countrycode_data$countries[], ~{ 
pb$tick()$print() 
Sys.sleep(5) 
wfp_get_news(.x) 
}) -> xdf 



## 03. Setting keywords (of course, this process is arbitrary: one can decide any keywor s/he prefers) 
keywords <- c("drought", "food security")           


keyword_regex <- sprintf("(%s)", paste0(keywords, collapse="|")) 


## 04. Setting the keywords search 
bind_cols(                     
xdf, 
stri_match_all_regex(tolower(xdf$bodytext), keyword_regex) %>% 
map(~.x[,2]) %>% 
map_df(~{ 
res <- table(.x, useNA="always") 
nm <- names(res) 
nm <- ifelse(is.na(nm), "NONE", stri_replace_all_regex(nm, "[ -]", "_")) 
as.list(set_names(as.numeric(res), nm)) 
}) 
) %>% 
select(-NONE) -> xdf_with_keyword_counts 

Das Ergebnis, das ich von Punkt 04. ist

Error in overscope_eval_next(overscope, expr) : 
object "NONE" not found 
Furthermore: Warning message: 
Unknown or uninitialised column: 'data.frame'. 

Jeder Hinweis?

+0

Bitte zeigen Sie uns den Code, den Sie versuchen Sie –

+0

der Code nach oben – Ileeo

+1

Sie filtern die Daten auf den Schlüsselwörtern Post basierend Schaben Daten erwähnt Gezeigte besser helfen kann ' grep() 'usw. sollte helfen. Irgendein Problem mit diesem Ansatz? – abhiieor

Antwort

0

Erstens, eine allgemeine Regel zu behalten ist, wenn Sie> 2-3x ausschneiden/einfügen, ist es Zeit für eine Funktion.

wir Hilfe brauchen:

library(countrycode) 
library(httr) 
library(rvest) 
library(stringi) 
library(tidyverse) 

Hier ist eine Funktion, die Sie mit einem iso3 Code aufrufen kann, um die Daten zu erhalten [Rahmen] Sie wollen:

fao_get_news <- function(iso3) { 

    GET(
    url = "http://www.fao.org/countryprofiles/common/allnews/en/", 
    query = list(iso3=iso3) 
) -> res 

    warn_for_status(res) 

    if (status_code(res) > 399) return(NULL) 

    out <- content(res, as="text", encoding="UTF-8") 
    out <- jsonlite::fromJSON(out) 
    out$iso3 <- iso3 

    tbl_df(out) 

} 

Nun wir iterieren über alle möglichen iso3 Codes mit einem Hilfsdatenrahmen aus dem countrycode Paket.

HINWEIS: Entfernen Sie die [1:20] in den nächsten 2 Zeilen für die Produktion, um alle zu bekommen, die ich nicht alle Daten brauche, also verbrenne ich nicht Zeit/Bandbreite. Wenn du dich überhaupt für ethische Fragen interessierst, nicht verbannt wirst oder die Server einer gemeinnützigen Organisation hämmerst, dann behalte die Sys.sleep(5) da drin. Wenn du egoistisch bist, dann halte es immer noch da, denn deine Bedürfnisse sind nicht die der FAO.

pb <- progress_estimated(length(countrycode_data$iso3c[1:20])) 
map_df(countrycode_data$iso3c[1:20], ~{ 
    pb$tick()$print() 
    Sys.sleep(5) # no crawl delay specified in site robots.txt so this is the ethical default 
    fao_get_news(.x) 
}) -> xdf 

Das führt uns einen schönen, sauberen Datenrahmen mit all den Nachrichten (mit einem iso3 Feld) ergibt:

glimpse(xdf) 
## Observations: 736 
## Variables: 10 
## $ uid   <chr> "1069933", "1069560", "1045264", "1044139", "103833... 
## $ table  <chr> "news", "news", "news", "news", "news", "news", "ne... 
## $ title  <chr> "FAO Calls for Stronger Collaboration on Transbound... 
## $ date  <chr> "1511823600", "1511737200", "1508191200", "15081048... 
## $ bodytext <chr> "28 November 2017- Chief Veterinary Officers and ex... 
## $ date_format <chr> "28/11/2017", "27/11/2017", "17/10/2017", "16/10/20... 
## $ image  <chr> "http://www.fao.org/fileadmin/user_upload/rne/img/I... 
## $ pid   <chr> "50840", "16275", "70992", "16275", "2330", "40990"... 
## $ detail_pid <chr> "/neareast/news/view/en/c/1069933/", "/asiapacific/... 
## $ iso3  <chr> "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "A... 

Setzen Sie alle Ihre Keywords (Kleinbuchstabe) hier:

keywords <- c("drought", "food security") 

Wir bauen eine Regex daraus

keyword_regex <- sprintf("(%s)", paste0(keywords, collapse="|")) 

Jetzt fügen wir Keyword-Spalten zu unserem bestehenden Datenrahmen hinzu.Der Umriss, dass die stri_match… ++ tut, ist, dass für jede Nachricht Blob:

  • niedriger Fall die Nachricht blob
  • alle Vorkommen jedes Schlüsselwort finden (falls vorhanden) in einer Presse blob
  • capture a Zählung der Anzahl der Ereignisse zusammen mit dem Stichwort
  • (leicht) das Stichwort gewährleisten kann ohne Schlüsselwörter
  • machen eine neue Spalte für jedes gefundene Stichwort
  • Blobs eine gültige Spaltenname wird nur ein 012.342 habenfür den gefundenen Zählwert

Wir hätten den Keyword-Ergebnisse Datenrahmen count() und spread() aber es ist nicht eine schnelle Operation gemacht. Die Verwendung von table() bedeutet ein bisschen mehr Tipparbeit, aber viel schnellere Ergebnisse.

bind_cols(
    xdf, 
    stri_match_all_regex(tolower(xdf$bodytext), keyword_regex) %>% 
    map(~.x[,2]) %>% 
    map_df(~{ 
     res <- table(.x, useNA="always") 
     nm <- names(res) 
     nm <- ifelse(is.na(nm), "NONE", stri_replace_all_regex(nm, "[ -]", "_")) 
     as.list(set_names(as.numeric(res), nm)) 
    }) 
) %>% 
    select(-NONE) -> xdf_with_keyword_counts 

Hier ist das Ergebnis:

glimpse(xdf_with_keyword_counts) 
## Observations: 736 
## Variables: 12 
## $ uid   <chr> "1069933", "1069560", "1045264", "1044139", "1038339", "... 
## $ table   <chr> "news", "news", "news", "news", "news", "news", "news", ... 
## $ title   <chr> "FAO Calls for Stronger Collaboration on Transboundary A... 
## $ date   <chr> "1511823600", "1511737200", "1508191200", "1508104800", ... 
## $ bodytext  <chr> "28 November 2017- Chief Veterinary Officers and experts... 
## $ date_format <chr> "28/11/2017", "27/11/2017", "17/10/2017", "16/10/2017", ... 
## $ image   <chr> "http://www.fao.org/fileadmin/user_upload/rne/img/IMG_64... 
## $ pid   <chr> "50840", "16275", "70992", "16275", "2330", "40990", "40... 
## $ detail_pid <chr> "/neareast/news/view/en/c/1069933/", "/asiapacific/news/... 
## $ iso3   <chr> "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "ALA", ... 
## $ food_security <int> NA, NA, 2, 1, NA, 1, NA, NA, NA, 1, NA, NA, NA, NA, 1, N... 
## $ drought  <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ... 
+0

Danke! Das ist sehr interessant und viel eleganter als meines. Ich werde es sicher verwenden! Tausend Dank! – Ileeo

+0

Wenn ich laufen 'pb <- progress_estimated (Länge (countrycode_data $ ISO3))' ich die folgende Fehlermeldung 'Fehler in .subset2 erhalten (public_bind_env "initialisieren") (...): lazy-Last Datenbank '/home/.../Rdata.rdb' ist beschädigt Inoltre: Warnmeldungen: 1: In .subset2 (public_bind_env "initialisieren") (...): Neustarten unterbrochen Versprechen Auswertung 2 : In .subset2 (public_bind_env, "initialize") (...): interner Fehler -3 in R_decompress1' – Ileeo

+0

klingt wie ein oder mehrere pkgs nicht gut installiert. Der beste Rat ist, R komplett zu schließen. Installieren Sie das Paket neu und starten Sie es erneut. – hrbrmstr