[英]Scraping multiple URLs by looping in PhantomJS
我正在使用PhantomJS抓取某些網站,因此使用r提取信息。 我正在關注本教程。 單個頁面的所有功能都可以正常運行,但是我找不到任何有關如何自動化多個頁面的簡單教程。 到目前為止,我的實驗是:
var countries = [ "Albania" ,"Afghanistan"];
var len = countries.length;
var name1 = ".html";
var add1 = "http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=";
var country ="";
var name ="";
var add="";
for (i=1; i <= len; i++){
country = countries[i]
name = country.concat(name1)
add = add1.concat(name1)
var webPage = require('webpage');
var page = webPage.create();
var fs = require('fs');
var path = name
page.open(add, function (status) {
var content = page.content;
fs.write(path,content,'w')
phantom.exit();
});
}
我在運行代碼時似乎沒有任何錯誤,該腳本僅為第二個國家/地區創建了一個html文件,其中包含有關我感興趣的小表的頁面異常的所有信息。
我試圖從類似的問題中收集一些信息。 但是,同樣因為我找不到簡單的可復制示例,所以我不理解自己在做什么錯。
主要問題似乎是您退出得太早。 您正在循環創建多個page
實例。 由於PhantomJS是異步的,因此對page.open()
的調用立即存在,並執行下一個for循環迭代。
for循環非常快,但是Web請求很慢。 這意味着即使在加載第一頁之前,循環也已完全執行。 這也意味着,加載的第一頁也將退出PhantomJS,因為你打電話phantom.exit()
在每個那些page.open()
回調。 我懷疑第二個URL由於某種原因會更快,因此總是被寫入。
var countFinished = 0,
maxFinished = len;
function checkFinish(){
countFinished++;
if (countFinished + 1 === maxFinished) {
phantom.exit();
}
}
for (i=1; i <= len; i++) {
country = countries[i]
name = country.concat(name1)
add = add1.concat(country)
var webPage = require('webpage');
var page = webPage.create();
var fs = require('fs');
var path = name
page.open(add, function (status) {
var content = page.content;
fs.write(path, content,'w')
checkFinish();
});
}
問題在於您要創建很多page
實例而沒有清理。 完成使用后,應關閉它們:
for (i=1; i <= len; i++) {
(function(i){
country = countries[i]
name = country.concat(name1)
add = add1.concat(country)
var webPage = require('webpage');
var page = webPage.create();
var fs = require('fs');
var path = name
page.open(add, function (status) {
var content = page.content;
fs.write(path, content,'w');
page.close();
checkFinish();
});
})(i);
}
由於JavaScript具有函數級作用域,因此您需要使用IIFE在page.open()
回調中保留對正確page
實例的page.open()
。 有關此問題的更多信息,請參見此問題: 問:循環內的JavaScript閉合–簡單的實際示例
如果您不想在此之后進行清理,則應在所有這些URL上使用相同的page
實例。 我已經有一個關於在這里執行此操作的答案: A:遍歷url以執行相同的操作
鑒於我對js的了解非常有限,我考慮了解決該問題的方法。 我仍然對正確解決問題感興趣,但是我預計這將花費一些時間。
目前,我通過在R中進行一些實驗性工作來獲得所需的結果。我沒有在js中運行循環,而是使用R編寫了多個單個js代碼,從而繞過了“ phantomjs是異步問題”。
訣竅在於使用帶有參數quote = F的write.table導出js代碼塊,並使用.js作為文件擴展名,以便將其正確識別為js文件。 我猜想這種解決方法將適用性限制在其他類似的任務上,但是它仍然可以幫助某人。 評論非常感謝。
countries <- c("Afghanistan", "Albania", "Algeria")
for (i in unique(countries)){
df <- data.frame(lines=character(11),
stringsAsFactors=FALSE)
outputline <- paste("var path = '", i, ".html'" , sep="")
inputline <- paste("page.open('http://www.kluwerarbitration.com/CommonUI/BITs.aspx?country=", i ,"', function (status) {", sep="")
df$lines[1] <- "var webPage = require('webpage');"
df$lines[2] <- "var page = webPage.create();"
df$lines[3] <- "var fs = require('fs');"
df$lines[4] <- ""
df$lines[5] <- outputline
df$lines[6] <- ""
df$lines[7] <- inputline
df$lines[8] <- " var content = page.content;"
df$lines[9] <- " fs.write(path,content,'w')"
df$lines[10] <- " phantom.exit();"
df$lines[11] <- "});"
write.table(df, paste(i, ".js", sep = ""), sep=" ", quote=F, row.names=F, col.names=F)
}
library(rvest)
library(stringr)
library(plyr)
library(dplyr)
library(ggvis)
library(knitr)
options(digits = 4)
#run all individual javascript files
index <- 1
for (i in countries){
javacode <- paste0("./phantomjs", sep=" ", countries, ".js")
system(javacode[index])
index <- index + 1
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.