需要帮助来优化大型网络抓取任务中的循环

时间:2019-02-22 18:44:45

标签: r web-scraping rvest sampling

我正在进行一个单独项目,该项目首先使用 rvest 软件包生成库存数据,以进行网络抓取并将其存储在数据表中。

该循环从网站上提取一部分股票报价器,并将其存储在数据框中。我的代码非常古旧(我认为),部分原因是网站的组织方式。该网站按字母顺序排列页面上的符号,每页上带有不同数量的代码(每封信1页)-是的,我必须计算每页多少个。我最终的作品行得通,但运行起来却非常缓慢:

#GET AMEX tickers
alphabet <- c('A','B','C','D','E','F','G','H','I','J','K',
          'L','M','N','O','P','Q','R','S','T','U','V',
          'W','X','Y','Z')
#start at 2
lengths <- c(65,96,89,125,161,154,86,62,173,83,26,43,62,51,
         37,126,25,81,149,52,77,74,34,50,8,11)

amexurls <- paste0("http://findata.co.nz/markets/AMEX/symbols/",toupper(alphabet),".htm",
 sep = "")

iterator <- 0
for(j in 1:26){
  url <- amexurls[j]
  for(k in 2:lengths[j]){

html <- read_html(as.character(url))
iterator 
test <- html_nodes(html,as.character(paste0("tr:nth-child(",k,") a")))
test <- toString(test)
test <-  gsub("<[^>]+>", "", test)
amexsymbols[k-2+iterator] <- test

  }
  iterator <- iterator + lengths[j] + 1
}

上面的for循环需要一个多小时才能运行。我认为这可能主要是因为有许多拨打互联网的电话。

我正在尝试更好地理解矢量化和其他技巧,以最大限度地提高R的效率,尤其是在这样的大型项目中。

我尝试过/看到的东西:

-我已经从循环主体中抽出了很多东西(具体来说是paste0行

-从数据帧切换到数据表

-在更老的帖子中,用户@Gregor(再次感谢)告诉我,我可以利用paste0是矢量化函数,因此 amexurls 不使用for循环来存储-不幸的是,这不是代码的慢部分

这只是一个更大的Web抓取代码的片段。如果我可以优化此块,则可以将其应用于其余部分。我的代码或提示/技巧的任何改进将不胜感激。感谢您的宝贵时间。

1 个答案:

答案 0 :(得分:1)

由于防火墙的限制,我现在无法测试。但我建议您尝试使用html_table()中的rvest函数来收集数据。与手动指定每页上的库存数量并逐个循环浏览相比,动态性要强得多。

library(rvest)

amexurls <- paste0("http://findata.co.nz/markets/AMEX/symbols/", LETTERS,".htm")

ldf <- list()
iterator <- 0

for(url in amexurls){
  iterator <- iterator + 1
  html <- read_html(url)
  ldf[[iterator]] <- html_table(html_nodes(html, "table")[[2]])
}

df <- do.call(rbind, ldf)