无法使用r中的phantomjs刮取多个页面

时间:2016-02-17 06:09:20

标签: javascript r web-scraping phantomjs rselenium

我正在尝试使用来自https://www.washoecounty.us/assessor/cama/?command=assessment_data&parid=07101001的javascript使用由RSelenium控制的phantomjs生成的多个宗地的历史属性值来搜索县评估员数据。 网址中的'paraid'是9位数的包裹号码。我有一个数据框,其中包含我感兴趣的地块编号列表(总共几百个),但一直在尝试使代码适用于其中的一小部分:

parcel_nums
[1] "00905101" "00905102" "00905103" "00905104" "00905105" 
[6] "00905106" "00905107" "00905108" "00905201" "00905202"

我需要抓取页面上为每个宗地生成的表格中的数据并保留它。我选择将页面写入文件“output.htm”,然后解析文件。我的代码如下:

require(plyr)
require(rvest)
require(RSelenium)
require(tidyr)
require(dplyr)

parcel_nums <- prop_attr$APN[1:10]  #Vector of parcel numbers
pJS <- phantom()
remDr <- remoteDriver(browserName = "phantomjs")
remDr$open()

result <- remDr$phantomExecute("var page = this;
                            var fs = require(\"fs\");
                            page.onLoadFinished = function(status) {
                            var file = fs.open(\"output.htm\", \"w\");
                            file.write(page.content);
                            file.close();
                            };")

for (i in 1:length(parcel_nums)){
    url <- paste("https://www.washoecounty.us/assessor/cama/?command=assessment_data&parid=", 
        parcel_nums[i], sep = "")
    Sys.sleep(5)

    emDr$navigate(url)

    dat <- read_html("output.htm", encoding = "UTF-8") %>% 
        html_nodes("table") %>% 
        html_table(, header = T)
    df <- data.frame(dat)

    #assign parcel number to panel
    df$apn <- parcel_nums[i]
    #on first iteratation initialize final data frame, on sebsequent iterations append the final data frame
    ifelse(i == 1, parcel_data <- df, parcel_data <- rbind(parcel_data, df))
}
remDr$close
pJS$stop()

这将完美地适用于循环的一次或两次迭代,但它突然停止保留javascript生成的数据并产生错误:

 Error in `$<-.data.frame`(`*tmp*`, "apn", value = "00905105") : 
 replacement has 1 row, data has 0 

这是由于解析器没有在输出文件中定位表,因为它没有被保留。我不确定我选择的实现是否存在问题,或者是否存在引起问题的特定网站的某些特性。我不熟悉JavaScript,所以使用的代码片段来自我发现的一个例子。感谢您的帮助。

以下答案完美无缺。我还将Sys.sleep(5)移到$导航后,以允许页面时间加载javascript。循环现在正在执行完毕。

2 个答案:

答案 0 :(得分:0)

require(plyr)
require(rvest)
require(RSelenium)
require(tidyr)
require(dplyr)

parcel_nums <- prop_attr$APN[1:10]  #Vector of parcel numbers
#pJS <- phantom()
remDr <- remoteDriver()
remDr$open()

# #result <- remDr$executeScript("var page = this;
#                                var fs = require(\"fs\");
#                                page.onLoadFinished = function(status) {
#                                var file = fs.open(\"output.htm\", \"w\");
#                                file.write(page.content);
#                                file.close();
#                                };")
#length(parcel_nums)
for (i in 1:length(parcel_nums)){
  url <- paste("https://www.washoecounty.us/assessor/cama/?command=assessment_data&parid=", 
               parcel_nums[i], sep = "")
  Sys.sleep(5)

  remDr$navigate(url)
  doc <- htmlParse(remDr$getPageSource()[[1]])
  doc_t<-readHTMLTable(doc,header = TRUE)$`NULL`
  df<-data.frame(doc_t)

  #assign parcel number to panel
  df$apn <- parcel_nums[i]
  #on first iteratation initialize final data frame, on sebsequent iterations append the final data frame
  ifelse(i == 1, parcel_data <- df, parcel_data <- rbind(parcel_data, df))
}
remDr$close

这给了我一个解决方案。这也应该与phantomJS一起使用。我请你测试并回复。

答案 1 :(得分:0)

我已经失去了一整天试图解决类似的问题。所以我分享我的学习,以帮助其他人节省时间和神经..

我想我们需要了解通过远程驱动程序打开,导航和其他浏览操作需要时间来完成。 因此,在我们尝试阅读或在我们期望抓取的页面上做任何事情之前,我们必须等待。

我在问Sys.sleep(5)之后介绍remDr$navigate(url)时解决了我的问题。

似乎整洁的解决方案包括按how to check if page finished loading in RSelenium的建议插入remDr$setTimeout(type = "page load", milliseconds = 10000),但尚未对其进行测试。