我的目标是打开许多页面(延迟很短)并将我的数据保存到文件中。
但我的代码不起作用。
var gamesList = [url1,url2,url3];
//gamesList is getting from a file
var urls = [];
var useragent = [];
useragent.push('Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14');
useragent.push('Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50');
var page = require('webpage').create();
page.settings.userAgent = useragent[Math.floor(Math.random() * useragent.length)];
console.log('Loading a web page');
function handle_page(url){
page.open(url,function(){
//...
var html= page.evaluate(function(){
// ...do stuff...
page.injectJs('jquery.min.js');
return $('body').html();
});
//save to file
var file = fs.open('new_test.txt', "w");
file.write(html + '\n');
file.close();
console.log(html);
setTimeout(next_page,1000);
});
}
function next_page(urls){
var url=urls.shift();
if(!urls){
phantom.exit(0);
}
handle_page(url);
}
next_page(urls);
phantom.exit();
我在写phantom.exit();
的地方有用吗?如果我最后在page.open()
回调中写它,那么第一页就会打开。
答案 0 :(得分:13)
您使用递归打开多个页面的想法是正确的,但是您遇到了一些问题。
正如您所正确指出的那样,phantom.exit()
存在问题。由于page.open()
和setTimeout()
是异步的,因此您只需在完成后退出。当您在脚本末尾调用phantom.exit()
时,您将在第一页加载之前退出。
只需删除最后一个phantom.exit()
,因为您已经在正确的位置有另一个出口。
page.evaluate()
提供对DOM上下文(页面上下文)的访问。问题是它是沙箱。在该回调内部,您无法访问外部定义的变量。您可以显式传递变量,但它们必须是page
不是的原始对象。您只需访问page
内的page.evaluate()
即可。您需要在调用page.evaluate()
之前注入jQuery。
您通过不更改文件名来覆盖每次迭代中的文件。您需要更改文件名或使用追加模式'a'
而不是'w'
。
然后,当您只想写一次时,您不需要打开流。变化:
var file = fs.open('new_test.txt', "w");
file.write(html + '\n');
file.close();
到
fs.write('new_test.txt', html + '\n', 'a');
调用next_page()
函数的递归步骤要求您传入URL。由于urls
已经是全局变量,并且您在每次迭代中都更改了它,因此您无需传入urls
。
您也不需要添加setTimeout()
,因为page.open()
回调内部的所有内容都是同步的。
//...
var urls = [/*....*/];
function handle_page(url){
page.open(url, function(){
//...
page.injectJs('jquery.min.js');
var html = page.evaluate(function(){
// ...do stuff...
return $('body').html();
});
//save to file
fs.write('new_test.txt', html + '\n', 'a');
console.log(html);
next_page();
});
}
function next_page(){
var url = urls.shift();
if(!url){
phantom.exit(0);
}
handle_page(url);
}
next_page();
答案 1 :(得分:0)
上面的说明对我很有帮助。因此,thanx很多。说到这一点,在这种情况下,有时即使页面已经加载后js函数也呈现,在这种情况下,setTimeout()方法非常有用。而且,在抓取多个网站时遇到了这样的问题。...我以这种方式使用setTimeout()方法,
`
function handle_page(url){page.open(url, function() {setTimeout(function() {var html_text=page.evaluate(function(){
var is= document.querySelectorAll("li.bookinDetails_c1_180616")[0].textContent;
var isbn=is.trim();
//return s1;
var w,x,y,z,z1,w1,u,a;
a= document.querySelectorAll("li.selectableBook");
if(a.length==5){
w1=document.querySelectorAll("span.bookPrice")[0].textContent;
w=w1.trim();
x1=document.querySelectorAll("span.bookPrice")[1].textContent;
x=x1.trim();
y1=document.querySelectorAll("span.bookPrice")[2].textContent;
y=y1.trim();
z1=document.querySelectorAll("span.bookPrice")[3].textContent;
z=z1.trim();
u=isbn+"=>["+"RENT USED:-"+w+","+"RENT NEW:-"+x+","+"BUY USED:-"+y+","+"BUY NEW:-"+z+"]";
return u;
}else{
y1=document.querySelectorAll("span.bookPrice")[0].textContent;
y=y1.trim();
z1=document.querySelectorAll("span.bookPrice")[1].textContent;
z=z1.trim();
u=isbn+"=>["+"BUY USED:-"+y+","+"BUY NEW:-"+z+"]";
return u;
}
});
fs.write('html.txt',html_text+'\r\n','a');
next_page();
}, 400);
});
}
`