3

我正在尝试使用github.com/segmentio/nightmare自动化 2 个站点

例子:

  1. 我想去site_1(临时电子邮件服务)并收到一封电子邮件。
  2. 然后转到site_2并填写该电子邮件,然后提交表格。
  3. 然后转到site_1并检查电子邮件是否到达
  4. 解析电子邮件以获取激活链接
  5. 然后单击该链接并再次转到site_2

........... ETC

Nightmare js 和 node.js 是否适合这种浏览器操作?

因为在官方 API 上这样的简单事情是可以的:

var Nightmare = require('nightmare');
new Nightmare()
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit')
.run(function (err, nightmare) {
  if (err) return console.log(err);
  console.log('Done!');
});

复杂的事情呢? 谢谢

4

2 回答 2

3

在这里,我创建了一个函数来获取不同条件的 html 源,我正在爬取TimeWarnerCable页面以获取有关电视、互联网和捆绑计划的信息,因此我的函数获取一些参数并在不同的调用中对每个参数做出反应:

function getSource(url,serviceQuantity,zip){
  var defer=Q.defer();
  var Nightmare = require('nightmare');
  var nightmare = Nightmare({openDevTools:browserDev ,show: browserVisible,'webPreferences':{partition: 'nopersist'}});

  nightmare
  .goto(url)
  .cookies.clear()
  .wait(2000)
  .exists('div.messagebox-wrapper.twc-container[style="display: block;"]')
  .then(function(noZipSet){
    if (noZipSet){
      debug('No zipcode settled down');
      nightmare
      .insert('fieldset > div > input[placeholder="Enter Your ZIP Code"]',zip)
      .type('fieldset > div > input[placeholder="Enter Your ZIP Code"]', '\u000d');//I do "Enter" because nightmare can't find the submit button
    }else{
      debug('Zipcode settled down');
      nightmare
      .click('div.section.newHeaderIcons > div > ul > li:nth-child(4) > div > a')
      .wait(2000)
      .insert('form.geoLoc > fieldset > div > input[placeholder="Update Your ZIP Code"]',zip)
      .type('form.geoLoc > fieldset > div > input[placeholder="Update Your ZIP Code"]', '\u000d');//I do "Enter" because nightmare can't find the submit button
    }
    nightmare
    .wait(8500)
    .exists('div[style="display: block;"] > div > div > div > div > div > div > div.parsys.oof-error-content > div > div > div > div > div > div > p[style="color: #333333;"]')
    .then(function(zipNotAvailable){
      if (zipNotAvailable){
        debug('Service not available in '+zip+' for '+serviceQuantity+' services');
        nightmare
          .end()
          .then(function(){
            defer.resolve('');
          });
      }else{
        debug('Service available on the zipcode');
      switch (serviceQuantity) {
          case 1:
              nightmare
                  .evaluate(function(){
                    return document.querySelector('html').innerHTML;
                  })
                  .end()
                  .then(function (result) {
                    defer.resolve(result);
                  })
                  .catch(function (error) {
                    debug('ERROR >> Search failed:', error);
                  });
              break;
          case 2:
              nightmare
                .click('#tv-filter')
                .wait(500)
                .click('#internet-filter')
                .wait(500)
                .evaluate(function(){
                  return document.querySelector('html').innerHTML;
                })
                .end()
                .then(function (result) {
                   defer.resolve(result);
                })
                .catch(function (error) {
                   debug('ERROR >> Search failed:', error);
                });
              break;
          case 3:
              nightmare
                  .click('#tv-filter')
                  .wait(500)
                  .click('#internet-filter')
                  .wait(500)
                  .click('#phone-filter')
                  .wait(500)
                  .evaluate(function(){
                    return document.querySelector('html').innerHTML;
                  })
                  .end()
                  .then(function (result) {
                    defer.resolve(result);
                  })
                  .catch(function (error) {
                    debug('ERROR >> Search failed:', error);
                  });
                  break;
       }
      }
    });
  });
  return defer.promise;
}
于 2016-07-21T19:48:26.863 回答
2

Nightmare 现在使用 Electron 而不是 PhantomJS,并且 API 与以前不同。文档仅显示如何与生成器一起使用。以下是我将如何在不使用生成器的情况下执行您想要的操作,而是使用 Promise。完成后,您可以使用这三个命令杀死电子浏览器。

此外,确保验证 DOM 操作的每个步骤(使用受控递归)并在操作之间留出足够的等待时间。否则你不会总是得到你所期望的。

var Nightmare   = require('nightmare'),
    Promise     = require('q').Promise;

var nightmare = new Nightmare({show: true});

function goToSite1(data){
    Promise.resolve(nightmare
        .goto('http://stackoverflow.com/questions/32518777/nightmare-js-browsing-and-parsing-multiple-sites')
        .evaluate(function(){
            return $('#question-header > h1 > a').text();
        })).then(function(html){
            goToSite2(html);
        });
}

function goToSite2(data){
    Promise.resolve(nightmare
        .goto('https://github.com/segmentio/nightmare')
    ).then(function(){
        nightmare.proc.disconnect();
        nightmare.proc.kill();
        nightmare.ended = true;
        doOtherStuff(data);
    })
}

function doOtherStuff(data){
    console.log(data)
}

goToSite1();
于 2015-10-24T11:50:32.033 回答