【问题标题】:Using parallelisation to scrape web pages with R使用并行化使用 R 抓取网页
【发布时间】:2014-01-01 00:07:03
【问题描述】:

我正在尝试抓取大量网页以便稍后对其进行分析。由于 URL 的数量很大,我决定使用 parallel 包和 XML

具体来说,我正在使用来自XMLhtmlParse() 函数,它在与sapply 一起使用时可以正常工作,但在与parSapply 一起使用时会生成HTMLInternalDocument 类的空对象。

url1<- "http://forums.philosophyforums.com/threads/senses-of-truth-63636.html"
url2<- "http://forums.philosophyforums.com/threads/the-limits-of-my-language-impossibly-mean-the-limits-of-my-world-62183.html"
url3<- "http://forums.philosophyforums.com/threads/how-language-models-reality-63487.html"

myFunction<- function(x){
cl<- makeCluster(getOption("cl.cores",detectCores()))
ok<- parSapply(cl=cl,X=x,FUN=htmlParse)
return(ok)
}

urls<- c(url1,url2,url3)

#Works
output1<- sapply(urls,function(x)htmlParse(x))
str(output1[[1]])
> Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument', 'oldClass' <externalptr>
output1[[1]]


#Doesn't work
myFunction<- function(x){
cl<- makeCluster(getOption("cl.cores",detectCores()))
ok<- parSapply(cl=cl,X=x,FUN=htmlParse)
stopCluster(cl)
return(ok)
}

output2<- myFunction(urls)
str(output2[[1]])
> Classes 'HTMLInternalDocument', 'HTMLInternalDocument', 'XMLInternalDocument', 'XMLAbstractDocument', 'oldClass' <externalptr>
output2[[1]]
#empty

谢谢。

【问题讨论】:

  • 希望有更多知识渊博的人加入,但我的直觉是并行化(按照目前的设计)可能效率不高,因为您直接在 htmlParse 和您的所有内核中调用网站可能共享一个互联网连接。您可能想查看RCurl 以获得asynchronous downloads, which are allegedly more efficient
  • @Thomas 谢谢。正如您在前面的问题中帮助过我一样,我欢迎您的建议/cmets。我也会研究 RCurl。
  • 另请注意,如果您的个人网络爬虫不需要那么长时间(以毫秒为单位),那么并行化的开销将导致它比简单的串行处理花费更长的时间。
  • @PaulHiemstra 你说得非常正确。感谢您的评论。尽管在最初的任务中,我使用了大约 500 个 url,并且我检查以确保 parSapply 比 sapply 快两倍。只是结果很奇怪,如玩具示例所示。
  • 我遇到了同样的问题!我可能会为此悬赏以得到答案...

标签: xml r parallel-processing


【解决方案1】:

您可以使用 Rcurl 包中的getURIAsynchronous,它允许调用者指定多个 URI 以同时下载。

library(RCurl)
library(XML)
get.asynch <- function(urls){
  txt <- getURIAsynchronous(urls)
  ## this part can be easily parallelized 
  ## I am juste using lapply here as first attempt
  res <- lapply(txt,function(x){
    doc <- htmlParse(x,asText=TRUE)
    xpathSApply(doc,"/html/body/h2[2]",xmlValue)
  })
}

get.synch <- function(urls){
  lapply(urls,function(x){
    doc <- htmlParse(x)
    res2 <- xpathSApply(doc,"/html/body/h2[2]",xmlValue)
    res2
  })}

这里对 100 个网址进行了一些基准测试,您将解析时间除以 2。

library(microbenchmark)
uris = c("http://www.omegahat.org/RCurl/index.html")
urls <- replicate(100,uris)
microbenchmark(get.asynch(urls),get.synch(urls),times=1)

Unit: seconds
             expr      min       lq   median       uq      max neval
 get.asynch(urls) 22.53783 22.53783 22.53783 22.53783 22.53783     1
  get.synch(urls) 39.50615 39.50615 39.50615 39.50615 39.50615     1

【讨论】:

    猜你喜欢
    • 2014-03-01
    • 2014-12-28
    • 2018-02-15
    • 1970-01-01
    • 2018-09-29
    相关资源
    最近更新 更多