【问题标题】:loop across multiple urls in r with rvest [duplicate]使用 rvest 遍历 r 中的多个 url [重复]
【发布时间】:2017-04-01 16:11:18
【问题描述】:

我有一系列 9 个网址,我想从以下网址抓取数据:

http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=0 

当页面从最后一页更改时,链接末尾的 offset= 从 0 变为 900(乘以 100)。我想遍历每一页并刮掉每个表,然后使用 rbind 将每个 df 依次堆叠在一起。我一直在使用 rvest 并且想使用 lapply 因为我比 for 循环更好。

问题与此 (Harvest (rvest) multiple HTML pages from a list of urls) 类似,但有所不同,因为我不希望在运行程序之前不必将所有链接复制到一个向量。我想要一个通用的解决方案来解决如何遍历多个页面并收集数据,每次都创建一个数据框。

以下内容适用于第一页:

library(rvest)
library(stringr)
library(tidyr)

site <- 'http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=0' 

webpage <- read_html(site)
draft_table <- html_nodes(webpage, 'table')
draft <- html_table(draft_table)[[1]]

但我想在所有页面上重复此操作,而不必将网址粘贴到矢量中。我尝试了以下方法,但没有成功:

jump <- seq(0, 900, by = 100)
site <- paste('http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=', jump,'.htm', sep="")

webpage <- read_html(site)
draft_table <- html_nodes(webpage, 'table')
draft <- html_table(draft_table)[[1]]

所以每个页面都应该有一个数据框,我想将它们放在一个列表中然后使用 rbind 将它们堆叠起来会更容易。

任何帮助将不胜感激!

【问题讨论】:

  • 你能收获连第一页吗?
  • @HubertL 是的,刚刚编辑了上面的问题。第一段代码产生一个数据帧
  • 这是另一个潜在的解决方案:stackoverflow.com/questions/39129125/…
  • 在第二个版本中,site 是 URL 的向量,所以这是一个骗局。
  • 我会尝试使用 mode="a" 的download.file,然后从单个磁盘文件中读取所有数据。

标签: html r url web-scraping rvest


【解决方案1】:

您正在尝试对无法在一次调用中获取多个项目的方法进行矢量化。具体来说,read_html() 每次调用需要一页,因为它需要一次读取一个 Web 数据并期望一个标量值。考虑使用lapply 循环遍历site 列表,然后将所有dfs 绑定在一起:

jump <- seq(0, 800, by = 100)
site <- paste('http://www.basketball-reference.com/play-index/draft_finder.cgi?',
              'request=1&year_min=2001&year_max=2014&round_min=&round_max=',
              '&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0',
              '&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y',
              '&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=',
              '&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id',
              '&order_by_asc=&offset=', jump, sep="")

dfList <- lapply(site, function(i) {
    webpage <- read_html(i)
    draft_table <- html_nodes(webpage, 'table')
    draft <- html_table(draft_table)[[1]]
})

finaldf <- do.call(rbind, dfList)             # ASSUMING ALL DFs MAINTAIN SAME COLS

【讨论】:

  • 这真的很直观,但是当我运行它时,我不断收到错误“下标超出范围”。
  • 您在哪一行收到错误消息? dfList 是否填充?
  • 看来错误来自dfList的最后一行。 dfList 不填充
  • 刚刚检查过。原来900 没有表格搜索结果。试着留下那个号码。最高等级是831
  • 如果用900 省略最后一个网址,错误是否仍然存在?
【解决方案2】:

您可以使用curl 一次运行所有请求。我对可能有小型服务器的站点很好,不要炸毁它们。使用此代码,您可以使用末尾的 lapply 清理表格,以便您可以将其与 do.call(rbind, AllOut) 堆叠,但我将把它留给您。

library(rvest)
library(stringr)
library(tidyr)

OffSet <- seq(0, 900, by = 100)

Sites <- paste0('http://www.basketball-reference.com/play-index/draft_finder.cgi?request=1&year_min=2001&year_max=2014&round_min=&round_max=&pick_overall_min=&pick_overall_max=&franch_id=&college_id=0&is_active=&is_hof=&pos_is_g=Y&pos_is_gf=Y&pos_is_f=Y&pos_is_fg=Y&pos_is_fc=Y&pos_is_c=Y&pos_is_cf=Y&c1stat=&c1comp=&c1val=&c2stat=&c2comp=&c2val=&c3stat=&c3comp=&c3val=&c4stat=&c4comp=&c4val=&order_by=year_id&order_by_asc=&offset=', OffSet)


library(curl)

out <<- list()
# This is function, function which will be run if data vendor call is successful
complete = function(res){
  # cat("Request done! Status:", res$status, "\n")
  out <<- c(out, list(res))
}

for(i in 1:length(Sites)){
  curl_fetch_multi(
    Sites[i]
    , done = complete
    , fail = print
    , handle = new_handle(customrequest = "GET")
    )
}

multi_run()

AllOut <- lapply(out, function(x){

  webpage <- read_html(x$content)
  draft_table <- html_nodes(webpage, 'table')
  Tab <- html_table(draft_table)
  if(length(Tab) == 0){
    NULL
  } else {
    Tab
  }

})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    • 2022-09-23
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    相关资源
    最近更新 更多