RGet html-addresses from data frame to rvest



我是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(至少在我的测试中)。

该代码还提供了一个进度条,因为它需要一段时间(在中等体面的连接上可能需要一个小时)。

最新更新