2013-10-20 9 views
7

Ich versuche, eine große Anzahl von Webseiten zu kratzen, um sie später zu analysieren. Da die Anzahl der URLs riesig ist, habe ich beschlossen, das parallel Paket zusammen mit XML zu verwenden.Mit der Parallelisierung von Webseiten mit R

Insbesondere Ich bin mit der htmlParse() Funktion von XML, der gut arbeitet, wenn sie mit sapply verwendet, sondern erzeugt leere Objekte der Klasse HTMLInternalDocument, wenn sie mit parSapply verwendet.

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 

Danke.

+3

Jemand mehr Wissen wird hoffentlich in läuten, aber meine Intuition ist, dass diese Parallelisierung (wie sie derzeit entwickelt) möglicherweise nicht so effizient, weil Sie die Websites direkt in "htmlParse" aufrufen und alle Ihre Kerne wahrscheinlich eine einzige Verbindung mit dem Internet teilen. Sie können RCurl für [asynchrone Downloads suchen, die angeblich effizienter sind] (http://www.inside-r.org/packages/cran/RCurl/docs/getURIAsynchronous). – Thomas

+0

@Thomas Danke. Wie in den vorherigen Fragen haben Sie mir geholfen, ich begrüße Ihre Vorschläge/Kommentare. Ich werde auch in RCurl schauen. –

+2

Beachten Sie auch, dass, wenn Ihre einzelnen WebScrapes nicht so lange dauern (Bestellung ms), der Overhead der Parallelisierung dazu führt, dass es länger dauert als die einfache Verarbeitung in der Serie. –

Antwort

9

Sie können getURIAsynchronous aus dem Rcurl-Paket verwenden, mit dem der Aufrufer mehrere URIs gleichzeitig herunterladen kann.

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 
    })} 

Hier einige Benchmarking für 100 URLs, die Sie teilen das Parsing Zeit um den Faktor 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 
+0

+1 danke für die Einführung in diese Funktion! –

Verwandte Themen