2016-07-08 21 views
0

我是R新手,我遇到了一個我無法解決的問題。我想在選區一級摘取瑞典選舉數據。它們被構造爲可使用此代碼在這裏http://www.val.se/val/val2014/slutresultat/K/valdistrikt/25/82/0134/personroster.htmlR - 從數據框中獲取html地址到rvest

我得到我想要的數據發現:

library(rvest) 
district.data <- read_html("http://www.val.se/val/val2014/slutresultat/K/kommun/25/82/0134/personroster.html") 
prost <- district.data %>% 
html_nodes("table") %>% 
.[[2]] %>% 
html_table() 

但是,這僅僅是一個區出6,227個區。這些區域由html地址標識。在上面提到的網站中,它被標識爲「25/82/0134」。我可以在這裏找到http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv

各區的身份和我讀到這個分號通過使用此代碼分離文件到R:

valres <-read_csv2("http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv")

(作爲一個方面說明,我怎麼能改編碼使瑞典字母(例如å,ä,ö)正確導入?我設法使用read.csv並指定encoding='utf-8'而不是用read_csv)

在此數據框中,列LAN,KOM和VALDIST給出該地區的身份s(注意,VALDIST有時只有2個字符)。因此,地址具有以下結構http://www.val.se/val/val2014/slutresultat/K/kommun/LAN/KOM/VALDIST /personroster.html

所以,我想用相結合各行中得到區的身份,刮信息進入R,添加一個具有區域標識的列(即LAN,KOM和VALDIST合併爲一個字符串),並在所有6,227個區域中添加,並將來自每個區域的信息附加到單個數據框中。我假設我需要使用某種循環或其中一些應用函數來遍歷數據框架,但我還沒有弄清楚它是如何實現的。

更新: 在我在下面的答案中收到(謝謝!)的幫助後,現在的代碼如下。我剩下的問題是,我想爲每個網站添加區域標識(即paste0(LAN, KOM, VALDIST)),這些網站被截取到最終數據框中的列。有人能幫助我完成最後一步嗎?

# Read the indentities of the districts (w Swedish letters) 
districts_url <- "http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv" 
valres <- read_csv2(districts_url, locale=locale("sv",encoding="ISO-8859-1", asciify=FALSE)) 

# Add a variabel to separate the two types of electoral districts 
valres$typ <- "valdistrikt" 
valres$typ [nchar(small_valres$VALDIST) == 2] <- "onsdagsdistrikt" 

# Create a vector w all the web addresses to the district data 
base_url <- "http://www.val.se/val/val2014/slutresultat/K/%s/%s/%s/%s/personroster.html" 
urls <- with(small_valres, sprintf(base_url, typ, LAN, KOM, VALDIST)) 

# Scrape the data 
pb <- progress_estimated(length(urls)) 
map_df(urls, function(x) { 

    pb$tick()$print() 
    # Maybe add Sys.sleep(1) 
    read_html(x) %>% 
     html_nodes("table") %>% 
     .[[2]] %>% 
     html_table() 
}) -> df 

任何幫助將不勝感激!

一切順利, 理查德

回答

1

您可以使用sprintf()做位置替換,然後用purrr::map_df()遍歷URL的矢量和產生的數據幀:

library(rvest) 
library(readr) 
library(purrr) 
library(dplyr) 

districts_url <- "http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv" 
valres <- read_csv2(districts_url, locale=locale("sv",encoding="UTF-8", asciify=FALSE)) 

base_url <- "http://www.val.se/val/val2014/slutresultat/K/valdistrikt/%s/%s/%s/personroster.html" 

urls <- with(valres, sprintf(base_url, LAN, KOM, VALDIST)) 

pb <- progress_estimated(length(urls)) 
map_df(urls, function(x) { 

    pb$tick()$print() 

    read_html(x) %>% 
    html_nodes("table") %>% 
    .[[2]] %>% 
    html_table() 

}) -> df 

然而,你應該添加一個隨機延遲,以避免被阻止作爲機器人,並應該看看包裝read_html()purrr::safely()因爲不是所有這些LAN/KOM/VALDIST組合都是有效的URL(至少在我的測試中)。

該代碼還提供了一個進度條,因爲它需要一段時間(在適度體面的連接上每小時一小時)。

+0

謝謝你的回答!只有幾個後續問題:1)如何添加隨機延遲? 2)我注意到,即使編碼爲「UTF-8」,字符也不能正確導入,我可以在編碼中指定ISO代碼嗎?對於所有問題抱歉,R對我來說是非常新的。 – user2245655

+0

我認爲我得到的錯誤信息是「open.connection(x,」rb「)中的錯誤:HTTP錯誤404。」,是因爲沒有延遲。對不起,還有一個問題 - 我如何將創建的數據框中的區域(即LAN,KOM和VALDIST合併爲一個字符串變量)的標識添加爲附加列? – user2245655

+0

對不起,錯誤消息似乎是由於一些html地址無效的事實,正如你所提到的。 VALDIST只有兩個字符的地址是不同的。我設法通過添加'valres $ typ < - 「valdistrikt」' 'valres $ typ [nchar(small_valres $ VALDIST)== 2] < - 「onsdagsdistrikt」'來解決這個問題。 'base_url < - 「http://www.val.se/val/val2014/slutresultat/K/%s/%s/%s/%s/personroster.html」''urls < - with(valres,sprintf( base_url,typ,LAN,KOM,VALDIST))''。但是我仍然不知道如何添加一個帶分區id的列,即LAN,KOM和VALDIST。 – user2245655