噩梦条件等待()
Nightmare conditional wait()
我正在尝试使用 Nightmare 抓取网页,但想等待 #someelem
出现,前提是它确实存在。否则,我希望 Nightmare 继续前进。如何使用 .wait()
?
完成此操作
我无法使用 .wait(ms)
。使用 .wait(selector)
意味着 Nightmare 将一直等待直到元素出现,但如果页面永远不会有此元素,Nightmare 将永远等待。
最后一个选项是使用.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
库不会很好地工作。参数被序列化(或多或少)以传递给子 Electron 进程,因此传递整个库可能行不通。
从好的方面来说,.wait(fn)
的 fn
部分在页面上下文中执行 - 这意味着您可以完全访问 document
及其具有的方法(例如,querySelector
).您还可以访问页面的 jQuery 上下文(如果存在),或者如果不存在,您甚至可以使用 .inject()
来注入它。
先把它放在一边,就 .wait()
(和 .evaluate()
,就此而言)你是对的,至少在 promises could be used directly in .evaluate()
.
在此之前,您可以使用 .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);
});
我在这里创建了一个函数来获取 html 不同条件下的来源,我正在抓取 TimeWarnerCable 页面以获取有关电视、互联网和捆绑计划的信息,因此我的函数获取了一些参数并在不同的电话中对每个人做出反应。您可以使用 .exists() 检查选择器,然后继续 nightmare
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;
}
- 如 nightmarejs 文档中所述,
.wait(selector)
Wait until the element selector is present e.g. .wait('#pay-button')
wait 在这种情况下仅在元素第一次可见之前有效,如果不可见,则它将一直有效到默认超时 30 秒
- 等待功能
.wait(function () {
return (document.querySelector(selector) === null);
})
其中选择器是基于其存在于我们等待的 DOM 中的元素。
我正在尝试使用 Nightmare 抓取网页,但想等待 #someelem
出现,前提是它确实存在。否则,我希望 Nightmare 继续前进。如何使用 .wait()
?
我无法使用 .wait(ms)
。使用 .wait(selector)
意味着 Nightmare 将一直等待直到元素出现,但如果页面永远不会有此元素,Nightmare 将永远等待。
最后一个选项是使用.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
库不会很好地工作。参数被序列化(或多或少)以传递给子 Electron 进程,因此传递整个库可能行不通。
从好的方面来说,.wait(fn)
的 fn
部分在页面上下文中执行 - 这意味着您可以完全访问 document
及其具有的方法(例如,querySelector
).您还可以访问页面的 jQuery 上下文(如果存在),或者如果不存在,您甚至可以使用 .inject()
来注入它。
先把它放在一边,就 .wait()
(和 .evaluate()
,就此而言)你是对的,至少在 promises could be used directly in .evaluate()
.
在此之前,您可以使用 .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);
});
我在这里创建了一个函数来获取 html 不同条件下的来源,我正在抓取 TimeWarnerCable 页面以获取有关电视、互联网和捆绑计划的信息,因此我的函数获取了一些参数并在不同的电话中对每个人做出反应。您可以使用 .exists() 检查选择器,然后继续 nightmare
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;
}
- 如 nightmarejs 文档中所述,
.wait(selector) Wait until the element selector is present e.g. .wait('#pay-button')
wait 在这种情况下仅在元素第一次可见之前有效,如果不可见,则它将一直有效到默认超时 30 秒
- 等待功能
.wait(function () { return (document.querySelector(selector) === null); })
其中选择器是基于其存在于我们等待的 DOM 中的元素。