【问题标题】:phantomJS scraping with breaks not workingphantomJS 用休息刮擦不起作用
【发布时间】:2014-04-22 14:59:12
【问题描述】:

我正在尝试从 Web 服务中抓取一些 URL,它运行良好,但我需要从同一个 Web 服务中抓取大约 10,000 个页面。

我通过创建多个 phantomJS 进程来做到这一点,它们每个都打开并评估不同的 URL(它是相同的服务,我只更改网站 URL 中的一个参数)。

问题是我不想一次打开 10,000 个页面,因为我不希望他们的服务崩溃,我也不希望我的服务器崩溃。

我正在尝试创建一些打开/评估/插入ToDB ~10 页的逻辑,然后休眠 1 分钟左右。

假设这就是我现在拥有的:

var numOfRequests = 10,000; //Total requests
    for (var dataIndex = 0; dataIndex < numOfRequests; dataIndex++) {
         phantom.create({'port' : freeport}, function(ph) { 
           ph.createPage(function(page) {
             page.open("http://..." + data[dataIncFirstPage], function(status) {

我想在中间的某个地方插入类似的东西:

if(dataIndex % 10 == 0){
   sleep(60); //I can use the sleep module
}

在我尝试放置 sleepJS 的每个地方,程序都会永远崩溃/冻结/循环...

知道我应该尝试什么吗?

我尝试将上面的代码放在 for 循环之后的第一行,但这不起作用(可能是因为正在等待触发的回调函数..) 如果我将它放在phantom.create() 回调中也不起作用..

【问题讨论】:

    标签: node.js web-scraping phantomjs sleep


    【解决方案1】:

    意识到 NodeJS 是异步运行的,在你的 for 循环中,每个方法调用一个接一个地执行。 phantom.create 调用很快就结束了,然后下一个 for 循环开始。

    要回答您的问题,您希望在 phantom.create 块的末尾使用 sleep 命令,仍然在 for 循环中。像这样:

    var numOfRequests = 10000; // Total requests
    for( var dataIndex = 0; dataIndex < numOfRequests; dataIndex++ ) {
      phantom.create( { 'port' : freeport }, function( ph ) {
        // ..whatever in here
      } );
      if(dataIndex % 10 == 0){
        sleep(60); //I can use the sleep module
      }
    }
    

    另外,考虑使用包来帮助解决这些控制流问题。异步是一个很好的方法,has a method, eachLimit 将同时运行多个进程,达到一个限制。便利!您需要为希望运行的每次迭代创建一个输入对象数组,如下所示:

    var dataInputs = [ { id: 0, data: "/abc"}, { id : 1, data : "/def"} ];
    function processPhantom( dataItem, callback ){
      console.log("Starting processing for " + JSON.stringify( dataItem ) );
      phantom.create( { 'port' : freeport }, function( ph ) {
        // ..whatever in here. 
        //When done, in inner-most callback, call:
        //callback(null); //let the next parallel items into the queue
        //or 
        //callback( new Error("Something went wrong") ); //break the processing
      } );
    }
    async.eachLimit( dataInputs, 10, processPhantom, function( err ){
      //Can check for err.
      //It is here that everything is finished.
      console.log("Finished with async.eachLimit");
    });
    

    睡一分钟也不错,但如果以 10 人为一组,则需要 1000 分钟,也就是超过 16 小时!仅在队列中有空间时才调用会更方便 - 并确保记录正在处理和已完成的请求。

    【讨论】:

    • 谢谢 - 我应该在 eachLimit 参数中添加什么?我以前看过它,但找不到合适的方法。我知道该节点是异步的,并且我知道这些方法何时以及如何运行。但是,当幻影孩子完成评估页面时,我的主进程将进入睡眠状态,这不会造成问题吗?如果 5 个虚拟进程完成评估,而我的主进程正在睡觉......这会导致什么?
    • 我已经更新了我的答案。此外,您的主进程“正在休眠”也没有关系。 NodeJS 也是事件驱动的,所以它会很高兴地等待一个事件触发,这个事件可以是你的幻象进程的完成,也可以是来自代码不同部分的另一个回调。如果 5 个同时完成,节点将以单线程方式处理每个(例如,一次一个)。
    • 谢谢!再次感谢您的帮助!
    • 我想我仍然有异步的问题,我将如何控制何时回调新的错误?如果发生什么情况,我应该调用错误的回调吗?
    • 如果调用错误的回调,它将中断异步处理。因此,如果发生小错误,只需记录并继续。只有当您想停止所有处理时,才应调用回调并出现错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 2018-12-07
    • 2020-01-09
    • 2021-09-06
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多