我是R的新手,我遇到了一个我无法解决的问题。我想在选区层面抓取瑞典的选举数据。它们的结构可以在这里找到 http://www.val.se/val/val2014/slutresultat/K/valdistrikt/25/82/0134/personroster.html
我使用以下代码获取所需的数据:
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" )
作为旁注,如何更改编码以便正确导入瑞典字母(例如 å、ä、ö)?我设法通过读取.csv和指定encoding='utf-8'
而不是read_csv
在此数据框中,LAN、KOM 和 VALDIST 列给出了地区的身份(请注意,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
任何帮助将不胜感激!
万事如意,理查
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
但是,您应该添加随机延迟以避免作为机器人被阻止,并且应该考虑用purrr::safely()
包装read_html()
,因为并非所有这些LAN/KOM/VALDIST
组合都是有效的 URL(至少在我的测试中)。
该代码还提供了一个进度条,因为它需要一段时间(在中等体面的连接上可能需要一个小时)。