我正在尝试使用 github.com/segmentio/nightmare
自动化2个网站示例:
........... 等
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!');
});
复杂事情怎么样? 谢谢
答案 0 :(得分:2)
在这里,我创建了一个函数来获取不同条件的html源代码,我正在抓取TimeWarnerCable页面以获取有关TV,Internet和Bundle计划的信息,因此我的函数获取了一些参数并对每个参数做出反应一个人在不同的电话中:
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;
}
答案 1 :(得分:1)
Nightmare现在使用Electron而不是PhantomJS,API与以前不同。文档仅显示如何使用生成器。这就是我如何在不使用生成器的情况下做你想做的事情,而是使用promises。完成后,您可以使用这三个命令终止电子浏览器。
此外,请确保验证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();