我正在尝试使用Nightmare抓取网页,但要等到#someelem它实际存在时才等待出现。否则,我希望梦Night继续前进。如何使用来完成.wait()?
#someelem
.wait()
我不能用.wait(ms)。使用.wait(selector)手段,噩梦将一直等待直到该元素出现,但如果页面永远不会包含此元素,则噩梦将永远等待。
.wait(ms)
.wait(selector)
最后一个选项是使用.wait(fn)。我尝试过这样的事情
.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它是在浏览器范围内完成的。
.wait
提前致谢!
我认为通过现有cheerio库并不能很好地工作。参数被序列化(或多或少)以传递给子Electron进程,因此传递整个库可能不起作用。
cheerio
从好的方面来说,的fn一部分.wait(fn)在页面上下文中执行- 意味着您可以完全访问document它及其拥有的方法(例如querySelector)。您也可以访问页面的jQuery上下文(如果存在),或者甚至可以使用.inject()它来注入它。
fn
document
querySelector
.inject()
抛开这一点,就.wait()(并且.evaluate()就此而言)您期望同步方法是正确的,至少直到可以直接在中使用.evaluate()诸如promises之类的情况为止。
.evaluate()
在此之前,您可以.action()用来模仿您想要的行为:
.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); });