我尝试使用CasperJS抓取网站,但遇到了问题。
第一页我收集了我想要抓取的链接并使用getLinks()
函数将它们保存到数组中 - 这很有效。
然后我想从这个数组抓取每个页面(我让这个部分工作),我想从这些页面中获取一些细节。
我的代码如下(修剪了像casper start和login等工作内容):
// Casper start here, and some login stuff, all these are working fine so I removed them to have a light example
// ....
// ....
// ....
// Function for saving members to an array
function getLinks() {
var links = document.querySelectorAll(".member_name_and_title");
return Array.prototype.map.call(links, function(link) {
return link.childNodes[1].childNodes[1].href
});
}
casper.then(function() {
// Aggregate results
links = this.evaluate(getLinks);
casper.each(links, function (self, link) {
self.thenOpen(link, function () {
var details = this.evaluate(function(){
document.getElementsByClassName('member_name')[0].textContent;
});
// Grab details for each member
var data = details + " - " + link;
// Save data
var fs = require('fs');
fs.write('results/output.txt', JSON.stringify(data, null, ' '), 'aw');
});
});
});
// Casper run
casper.run(function() {
this.exit();
});
问题是details
var将返回null,因此最终的output.txt
将是这样的:
"null - domain.com/link1"
"null - domain.com/link2"
"null - domain.com/link3"
"null - domain.com/link4"
"null - domain.com/link5"
link
var工作正常,但details
var返回null。
当我从阵列中访问任何网址(例如:domain.com/link1)并在浏览器控制台中运行document.getElementsByClassName('member_name')[0].textContent
时,它会正确返回值,因此我确定定位很好
我不确定我错过了什么或我做错了什么。任何帮助将非常感激。谢谢!
答案 0 :(得分:1)
好吧我最终想到了这一点,完全是菜鸟错误......查询是正确的,问题是由页面加载引起的,或者更好地说在运行实际查询之前没有加载数组中的链接。
为了测试这个,我在self.thenOpen
函数中使用captureSelection()来捕获页面打开时的状态,但是在收集数据之前。
this.captureSelector('1.jpg', '#page');
我立即注意到该页面未完全加载,因此return document.querySelector('.member_name.').textContent;
返回null
。
为了解决这个问题,我增加了1.5秒的等待时间,如下所示:
casper.wait(1500, function() {
var details = this.evaluate(function(){
return document.querySelector('.member_name').textContent;
});
});
新秀的错误,但未来可能会帮助其他人。
答案 1 :(得分:0)
尝试添加如下所述的回报:
var details = this.evaluate(function(){
return document.getElementsByClassName('member_name')[0].textContent;
});
修改强>
这对我有用。我的代码设置如下:
var casper = require('casper').create();
function getLinks() {
var matchedLinks = document.querySelectorAll(".member_name_and_title");
return Array.prototype.map.call(matchedLinks, function(link) {
return link.href;
});
}
casper.start('http://localhost:8080');
casper.then(function() {
// Aggregate results
links = this.evaluate(getLinks);
casper.each(links, function (self, link) {
// INSPECT: Check if it shows the correct link here.
self.echo('Opening link:' + link);
self.thenOpen(link, function () {
var details = this.evaluate(function(){
// INSPECT: Make sure to 'return' the text content.
return document.getElementsByClassName('member_name')[0].textContent;
});
// Grab details for each member
var data = details + " - " + link;
// INSPECT: Check if the data is correct.
self.echo(data);
// Save data
var fs = require('fs');
fs.write('results/output.txt', JSON.stringify(data, null, ' '), 'aw');
});
});
});
casper.run(function(){
this.exit();
});
我的html文件如下:
的index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello CasperJs</title>
</head>
<body>
<a href="page1.html" class="member_name_and_title">Page 1</a>
<a href="page2.html" class="member_name_and_title">Page 2</a>
<a href="page3.html" class="member_name_and_title">Page 3</a>
<a href="page4.html" class="member_name_and_title">Page 4</a>
</body>
</html>
page1.html
<!DOCTYPE html>
<html>
<head>
<title>Page 1 Title</title>
</head>
<body>
<p class="member_name">Page 1 Text</p>
</body>
</html>
page2.html,page3.html和page4.html的类似HTML标记。我的http服务器在8080端口运行。
我的控制台输出如下:
Opening link:http://localhost:8080/page1.html
Opening link:http://localhost:8080/page2.html
Opening link:http://localhost:8080/page3.html
Opening link:http://localhost:8080/page4.html
Page 1 Text - http://localhost:8080/page1.html
Page 2 Text - http://localhost:8080/page2.html
Page 3 Text - http://localhost:8080/page3.html
Page 4 Text - http://localhost:8080/page4.html
我正在使用带有phantomjs 2.1.1的casperjs 1.1.3。
您可以更新代码并共享控制台输出和软件包版本吗?