[英]R web scraping >1000 pages, times out
我有以下代码来抓取工作评价。
reviewDate <- lapply(paste0('https://www.glassdoor.com/Interview/Sears-Interview-Questions-E37984_P', 1:1100, '.htm', sep=''),
function(url){
url %>% read_html() %>%
html_nodes(".date") %>%
html_text()
})
如果我只有几百个页面(我可以运行1:280),则此代码有效,但是我有两个问题:1)似乎重复了所有内容,以便每条信息中都有2; 2)运行时对于所有1100页,我得到以下错误,这停止了循环:
Error in open.connection(x, "rb") : HTTP error 504.
我读过有关在代码中添加Sys.sleep()的信息,但我不确定它在代码中的位置以使其正常工作。 我也想知道是否还有另一个或更完善的解决方案?
最后,我有多个节点。 我可以将它们全部添加到一个函数中并将所有内容对齐到一个数据框中吗? 以下代码对我不起作用,因为它返回的列表为2,但是每个都是character(0)。 (我只以1:2的速度进行了快速试用。)
reviewDate <- lapply(paste0('https://www.glassdoor.com/Interview/Sears-Interview-Questions-E37984_P', 1:2, '.htm', sep=''),
function(url){
url %>% read_html() %>%
html_nodes(".date") %>%
html_nodes(".summary") %>%
html_nodes(".authorJobTitle") %>%
html_nodes(".pros") %>%
html_nodes(".cons") %>%
html_nodes(".adviceMgmt") %>%
html_text()
})
Sys.sleep
仅使循环在每次迭代时暂停。 因此它可以循环到任何地方。 在这里,我们可以将其放置在开头,这样就不会干扰输出,因为您无需使用return
语句从该函数中显式返回某些内容
reviewDate <- lapply(paste0('https://www.glassdoor.com/Interview/Sears-Interview-Questions-E37984_P', 1:1100, '.htm', sep=''),
function(url){
Sys.sleep(.1)
url %>% read_html() %>%
html_nodes(".date") %>%
html_text()
})
请注意,这不能保证您不会收到超时错误。 垃圾邮件可能会导致此类错误,但也可能由于您无法控制的原因而发生。 理想情况下,您将希望逃避或坚持尝试获取所需的数据。 tryCatch
在那里,因此您的程序不会在出现故障的第一个迹象时立即停止。 这是一种方法
getData = function(url){
Sys.sleep(.1)
tryCatch({
url %>% read_html() %>%
html_nodes(".date") %>%
html_text()
}, error = function(e){
NULL
})
}
n = 1100
scrapedData = vector(length = n,mode = 'list')
while(TRUE){
indexes = which(sapply(scrapedData,is.null))
for (i in indexes){
scrapedData[[i]] = getData(paste0('https://www.glassdoor.com/Interview/Sears-Interview-Questions-E37984_P', i, '.htm'))
}
if(!any(sapply(scrapedData,is.null))){
break
}
}
在完成一轮请求后,我回去问所有我错过的事情。 tryCatch
确保不会停止执行。 请注意,如果您的链接确实很差,它将永远运行,因此您可能希望限制其运行的次数。
对于第二点,我不知道您为什么认为您的方法应该有效,但这暗示了对管道或html_nodes
函数的基本误解。 当您将html_nodes(".date")
的输出通过管道html_nodes(".date")
到html_nodes(".summary")
,对象不再具有summary
部分。 您使用上一个命令隔离了date
,因此您一无所获。 这些需要分别调用并分配给不同的变量
您需要做的就是确保函数返回一个数组,该数组以后可以合并到数据框中。
喜欢
getData = function(url){
Sys.sleep(.1)
tryCatch({
html = url %>% read_html()
date =html %>%
html_nodes(".date") %>%
html_text()
summary = html %>%
html_nodes('.summary') %>%
html_text
return(list(date,summary))
}, error = function(e){
NULL
})
}
请注意,这里我返回一个列表,因为读取的对象数量似乎不匹配,并且使它们匹配的确切方法不在问题范围内。 您需要查看页面并获得更好的选择器来抓取所需内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.