无法在 r 中使用 phantomjs 抓取多个页面
Unable to scrape multiple pages using phantomjs in r
我正在尝试使用由 RSelenium 控制的 phantomjs 从 https://www.washoecounty.us/assessor/cama/?command=assessment_data&parid=07101001 中抓取有关使用 javascript 生成的多个包裹的历史 属性 值的县评估员数据。
url中的'paraid'为9位包裹号。我有一个数据框,其中包含我感兴趣的包裹编号列表(总共几百个),但一直在尝试使代码在其中的一小部分上工作:
parcel_nums
[1] "00905101" "00905102" "00905103" "00905104" "00905105"
[6] "00905106" "00905107" "00905108" "00905201" "00905202"
我需要抓取页面上为每个包裹生成的 table 中的数据并保存。我选择将页面写入文件 "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
这是由于解析器没有在输出文件中找到 table,因为它没有被保留。我不确定我选择的实施是否存在问题,或者是否存在导致问题的特定站点的某些特性。我不熟悉 JavaScript,所以使用的代码片段取自我找到的一个示例。感谢您的帮助。
以下答案非常有效。我还将 Sys.sleep(5) 移动到 $navigate 之后,以便页面有时间加载 javascript。循环现在正在执行完成。
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。请您测试并回复。
我花了一整天的时间来解决类似的问题。所以我分享我的学习来帮助别人节省时间和精力..
我想我们需要明白,通过远程驱动程序打开、导航和其他浏览操作需要时间来完成。
所以我们必须等待,然后才能尝试阅读或在我们期望抓取的页面上做任何事情。
当我在 remDr$navigate(url)
调用后引入 Sys.sleep(5)
时,我的问题得到了解决。
似乎更简洁的解决方案包括按照 how to check if page finished loading in RSelenium 中的建议插入 remDr$setTimeout(type = "page load", milliseconds = 10000)
,但尚未对其进行测试。
我正在尝试使用由 RSelenium 控制的 phantomjs 从 https://www.washoecounty.us/assessor/cama/?command=assessment_data&parid=07101001 中抓取有关使用 javascript 生成的多个包裹的历史 属性 值的县评估员数据。 url中的'paraid'为9位包裹号。我有一个数据框,其中包含我感兴趣的包裹编号列表(总共几百个),但一直在尝试使代码在其中的一小部分上工作:
parcel_nums
[1] "00905101" "00905102" "00905103" "00905104" "00905105"
[6] "00905106" "00905107" "00905108" "00905201" "00905202"
我需要抓取页面上为每个包裹生成的 table 中的数据并保存。我选择将页面写入文件 "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
这是由于解析器没有在输出文件中找到 table,因为它没有被保留。我不确定我选择的实施是否存在问题,或者是否存在导致问题的特定站点的某些特性。我不熟悉 JavaScript,所以使用的代码片段取自我找到的一个示例。感谢您的帮助。
以下答案非常有效。我还将 Sys.sleep(5) 移动到 $navigate 之后,以便页面有时间加载 javascript。循环现在正在执行完成。
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。请您测试并回复。
我花了一整天的时间来解决类似的问题。所以我分享我的学习来帮助别人节省时间和精力..
我想我们需要明白,通过远程驱动程序打开、导航和其他浏览操作需要时间来完成。 所以我们必须等待,然后才能尝试阅读或在我们期望抓取的页面上做任何事情。
当我在 remDr$navigate(url)
调用后引入 Sys.sleep(5)
时,我的问题得到了解决。
似乎更简洁的解决方案包括按照 how to check if page finished loading in RSelenium 中的建议插入 remDr$setTimeout(type = "page load", milliseconds = 10000)
,但尚未对其进行测试。