3

我正在使用 nightmare.js 来抓取网页内容。

在验证了 nightmare 实例之后,我遍历了多个页面(需要登录),然后调用 run 方法来执行所有页面加载。

我想从每个页面中获取特定内容,因此我调用了评估函数,以确保我们在浏览器范围内执行。从评估函数返回的任何内容都将成为 run 方法中的参数

但我试图多次运行评估函数(每页一次)。但是evaluate函数只能将输出返回给run方法一次。我尝试将内容推送到全局变量(在主范围内),但无法从浏览器范围内访问它。

谁能建议如何在一个噩梦实例上运行多个评估方法并从每个实例中提取信息?

var Nightmare = require("nightmare");

//Creates the authenticated nightmare instance

var scraper = new Nightmare()
  .goto('https://www.example.com/signin')
  .type('#login', 'username')
  .type('#password', 'password')
  .click('#btn')
  .run(function(err, nightmare) {
    if (err) {
      console.log(err);
    }
    console.log('Done.');
  });

for (var i = 0; i < 4; i++) {
  scraper
    .goto('https://www.example.com/page'+i)
    .wait(1000)
    .evaluate(function(){
      return $('#result > h3').text()
    })
}

scraper.run(function(err, result) {
  console.log(result)
  if (err) {
    console.log(err);
  }
}); )
4

1 回答 1

9

我对噩梦不太了解,但似乎您可能只是在异步方面遇到了问题,这通常是 js 中的一个难题。

好消息是你可以重构你的代码并依靠生成器让它工作起来相当简单。

要实现的关键是,当您*在函数名称之前使用该函数时,该函数将成为生成器函数,它允许您使用yield关键字。每当您yield在进入下一行代码之前,该行代码将等待返回的 Promise 完成,并且它将返回该产生的值作为结果。您可以使用vo库将生成器函数转换为回调,该回调返回一个包含所有已生成结果的数组。

var Nightmare = require('../nightmare')
var vo = require('vo')

vo(run)(function(err, result) {
  if (err) throw err
  console.log('#result > h3: ', result)
})

function *run() {
  var nightmare = Nightmare();
  yield nightmare
    .goto('https://www.example.com/signin')
    .type('#login', 'username')
    .type('#password', 'password')
    .click('#btn')

  for (var i = 0; i < 4; i++) {
    yield nightmare
      .goto('https://www.example.com/page'+i)
      .wait(1000)
      .evaluate(function(){
        return $('#result > h3').text()
      })
  }

  yield nightmare.end()
}
于 2016-02-03T16:05:03.637 回答