我正在使用 PhantomJS 抓取一些网站,因此使用 r 提取信息。我正在关注this教程。对于单个页面来说一切正常,但我找不到任何关于如何自动化多个页面的简单教程。 到目前为止我的实验:
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 文件,其中包含为我感兴趣的小表制作的页面异常的所有信息。
我试图从 similar questions 收集一些信息。然而,也因为我找不到一个简单的可重现的例子,我不明白我做错了什么。
最佳答案
主要问题似乎是你退出得太早了。您正在循环中创建多个 page
实例。由于 PhantomJS 是异步的,因此对 page.open()
的调用立即存在,并执行下一个 for 循环迭代。
for 循环非常快,但网络请求很慢。这意味着您的循环在加载第一页之前就已完全执行。这也意味着加载的第一个页面也将退出 PhantomJS,因为您在每个 page.open()
回调中调用 phantom.exit()
。我怀疑第二个 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
实例的引用。有关详细信息,请参阅此问题:Q: JavaScript closure inside loops – simple practical example
如果您不想事后清理,那么您应该对所有这些 URL 使用相同的 page
实例。我已经有一个关于这样做的答案:A: Looping over urls to do the same thing
关于javascript - 通过在 PhantomJS 中循环抓取多个 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34120421/