我使用CasperJS进行网页抓取,但我在抓取下面描述的页面时遇到了一些问题。
页面的html如下所示:
<img id="trigger">
<img id="cur_img_xxx" class="show">
<img id="cur_img_yyy" class="cache">
所有<img>
元素共享相同的维度,"#trigger"
位于最顶层。当图像具有.show
类时,它将显示在页面上;当它的.cache
类时,它会被下载但隐藏。这样,当用户点击图像(实际上是触发器)时,将显示下一个图像,并通过AJAX下载新图像。结果html变为:
<img id="trigger">
<img id="cur_img_xxx" class="cache">
<img id="cur_img_yyy" class="show">
<img id="cur_img_zzz" class="cache">
我认为这是一个增加用户体验的好策略,有利于避免网页抓取,但我仍然想要抓住:P
我在网络控制台中尝试了$("#trigger").click()
,图片得到了导航和下载更正。但是,当我尝试使用CasperJS模拟此过程时,导航和图像下载均无效。请参阅代码:
var casper = require ("casper").create({
clientScripts: [
'include/jquery.js'
],
pageSettings: {
loadImages: false, // this won't affect since this will only forbid
loadPlugins: false // inline imgs from loading, but all imgs in this
}, // page are loaded dynamically
verbose: true
});
casper.start("http://www.example.com/1234.html");
casper.then(function () {
console.log("Connected! Current Url = " + this.getCurrentUrl());
});
casper.then(function () {
// findInitialImgs will find imgs that have already been loaded
imgs = this.evaluate(findInitialImgs);
this.waitForSelector("#image_trigger").thenClick("#image_trigger");
var next = this.evaluate(function () {
return $("img[id^='cur_img_']").last().attr("href");
});
console.log(next);
});
casper.run(function () {
this.echo('End').exit();
});
右键单击"#trigger"
后,最后一个条目会有所不同,即从<img id="cur_img_yyy">
变为<img id="cur_img_zzz">
。但是,next
仍然保留<img id="cur_img_yyy">
。我做错了吗?
答案 0 :(得分:1)
您如何确认没有任何反应?所有wait*()
和then*()
函数都是异步步骤函数,但evaluate
不是,因此它在其他两个函数之前执行。您需要在evaluate
块中包装最后一次then
调用,以确保在单击后执行包含它的步骤。
由于图像加载可能是异步执行的,因此您需要在evaluate
块中包含最后wait
次调用,但等待时间很短:
casper.then(function () {
// findInitialImgs will find imgs that have already been loaded
imgs = this.evaluate(findInitialImgs);
this.waitForSelector("#image_trigger")
.thenClick("#image_trigger")
.wait(1000, function(){
var next = this.evaluate(function () {
return $("img[id^='cur_img_']").last()[0].id;
});
console.log(next);
});
});
请注意,您无法将DOM节点传递出页面上下文(evaluate()
),因此您需要使用某种表示方式。这里我使用了最后一个元素的id。
对于reference(casper.evaluate()
只是PhantomJS&#39; page.evaluate()
的包装器):
注意:
evaluate
函数的参数和返回值必须是一个简单的原始对象。经验法则:如果它可以通过JSON序列化,那就没关系了。闭包,函数,DOM节点等将不工作!
答案 1 :(得分:0)
这似乎是JQuery
的问题。删除JQuery
注入后,将$("img[id^='cur_img_']").last().attr("href")
更改为
var imgs = document.querySelectorAll("img[id^='cur_img_']");
return imgs[imgs.length - 1].getAttribute("href");
一切正常。
然后我发现这个答案非常强大:CasperJS click event having AJAX call
因此确认,当您将JQuery
注入使用$
JQuery
的网页时,原始脚本将会被破坏。