我想要抓几个网站。这是我的代码:
for (var i = 0; i < urls.length; i++) {
url = urls[i];
console.log("Start scraping: " + url);
page.open(url, function () {
waitFor(function() {
return page.evaluate(function() {
return document.getElementById("progressWrapper").childNodes.length == 1;
});
}, function() {
var price = page.evaluate(function() {
// do something
return price;
});
console.log(price);
result = url + " ; " + price;
output = output + "\r\n" + result;
});
});
}
fs.write('test.txt', output);
phantom.exit();
我想抓取数组网址中的所有网站,提取一些信息,然后将此信息写入文本文件。
但是for循环似乎有问题。在不使用循环的情况下仅抓取一个站点时,所有站点都可以正常工作。但是对于循环,首先没有任何反应,然后是行
console.log("Start scraping: " + url);
显示,但有一次太多了。 如果url = {a,b,c},那么phantomjs会:
Start scraping: a
Start scraping: b
Start scraping: c
Start scraping:
似乎没有调用page.open。 我是JS的新手,所以我很抱歉这个愚蠢的问题。
答案 0 :(得分:4)
PhantomJS是异步的。通过使用循环多次调用page.open()
,您基本上会急于执行回调。在完成新请求之前,您将覆盖当前请求,然后再次覆盖该请求。你需要一个接一个地执行它们,例如:
page.open(url, function () {
waitFor(function() {
// something
}, function() {
page.open(url, function () {
waitFor(function() {
// something
}, function() {
// and so on
});
});
});
});
但这很乏味。有些实用程序可以帮助您编写更好的代码,如async.js。您可以通过npm将其安装在phantomjs脚本的目录中。
var async = require("async"); // install async through npm
var tests = urls.map(function(url){
return function(callback){
page.open(url, function () {
waitFor(function() {
// something
}, function() {
callback();
});
});
};
});
async.series(tests, function finish(){
fs.write('test.txt', output);
phantom.exit();
});
如果您不想要任何依赖项,那么定义您自己的递归函数也很容易(来自here):
var urls = [/*....*/];
function handle_page(url){
page.open(url, function(){
waitFor(function() {
// something
}, function() {
next_page();
});
});
}
function next_page(){
var url = urls.shift();
if(!urls){
phantom.exit(0);
}
handle_page(url);
}
next_page();