梦魇有条件的等待()

我正在尝试使用梦魇来抓取网页,但是只有等到#someelem存在时才会出现。 否则,我想让梦魇继续前进。 这怎么可以使用.wait()

我不能使用.wait(ms) 。 使用.wait(selector)意味着梦魇将一直等待,直到元素出现,但是如果页面永远不会有这个元素,那么梦魇将永远等待。

最后一个选项是使用.wait(fn) 。 我已经尝试过这样的事情了

 .wait(function(cheerio) { var $ = cheerio.load(document.body.outerHTML); var attempt = 0; function doEval() { if ( $('#elem').length > 0 ) { return true; } else { attempt++; if ( attempt < 10 ) { setTimeout(doEval,2000); //This seems iffy. } else { return true; } } } return doEval(); },cheerio) 

所以,等待并再次尝试(达到阈值),如果找不到元素,那就继续前进。 该代码似乎错误setTimeout周围,因为。 .wait在浏览器范围内完成。

提前致谢!

我不认为通过cheerio图书馆,因为你会得到很好的工作。 参数被序列化(或多或less)被传递给子电subprocess,所以传递整个库可能不起作用。

另一方面, .wait(fn)fn部分是在页面上下文中执行的 – 这意味着您可以完全访问document及其具有的方法(例如querySelector )。 你也可以访问页面的jQuery上下文(如果存在),或者甚至可以使用.inject()注入它,如果不存在的话。

除此之外,对于.wait() (和.evaluate() ,你可以期待一个同步方法,至less可以直接在.evaluate()使用promises之类的东西。

在可用之前,您可以使用.action()来模拟所需的行为:

 var Nightmare = require('nightmare'); Nightmare.action('deferredWait', function(done) { var attempt = 0; var self = this; function doEval() { self.evaluate_now(function(selector) { return (document.querySelector(selector) !== null); }, function(result) { if (result) { done(null, true); } else { attempt++; if (attempt < 10) { setTimeout(doEval, 2000); //This seems iffy. } else { done(null, false); } } }, '#elem'); }; doEval(); return this; }); var nightmare = Nightmare(); nightmare.goto('http://example.com') .deferredWait() .then(function(result) { console.log(result); }); 
  1. 正如在nightmarejs的文件中提到的,

等待(select器)等到元素select器存在,例如.wait('#pay-button')

等待等待在这种情况下才起作用,直到元素第一次变得可见,如果没有,那么它将工作到30秒的默认超时

  1. 等function

    .wait(function () { return (document.querySelector(selector) === null); })

其中select器是基于在我们等待的DOM中存在的元素。

在这里我创build一个函数来获取不同条件的html源代码,我爬行TimeWarnerCable页面获取有关电视,互联网和捆绑计划的信息,所以我的函数获取一些参数,并在不同的调用中的每个参数作出反应。 你可以使用.exists()来检查select器,然后继续做噩梦

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