通过url来做同样的事情

我正在努力刮几个网站。 这是我的代码:

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(); 

我想抓取数组url中的所有网站,提取一些信息,然后将这些信息写入文本文件。

但是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的新手,所以我很抱歉这个愚蠢的问题。

PhantomJS是asynchronous的。 通过使用一个循环多次调用page.open() ,你本质上是急于执行callback。 覆盖当前请求,然后再覆盖新的请求。 你需要一个接一个地执行它们,例如像这样:

 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(); }); 

如果你不需要任何依赖关系,那么也很容易定义你自己的recursion函数(从这里 ):

 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();