我试图从当用户向下滚动到底部(无限滚动)时动态生成内容的页面中抓取链接。我尝试过使用 Phantomjs 做不同的事情,但无法收集首页之外的链接。假设底部加载内容的元素具有类
.has-more-items
。它一直可用,直到滚动时加载最终内容,然后在 DOM 中变得不可用(display:none)。这是我尝试过的事情-
var page = require('webpage').create();
page.viewportSize = { 宽度:1600,高度:10000, };
page.scrollPosition = { top: 10000, left: 0 }
内使用page.open
但没有类似-page.open('http://example.com/?q=houston', function(status) { if (status == "success") { page.scrollPosition = { top: 10000, left: 0 }; } });
page.evaluate
函数中,但这给出了 引用错误:找不到变量页面
page.evaluate
和page.open
中使用jQuery和JS代码,但无济于事-$("html, body").animate({scrollTop: $(document).height() }, 10, 功能() { //console.log('检查执行情况'); });
原样,也在里面
document.ready
。 JS 代码也是如此 -
window.scrollBy(0,10000)
原样,也在里面
window.onload
我已经被这个问题困扰了两天了,但找不到方法。任何帮助或提示将不胜感激。
更新
我在 https://groups.google.com/forum/?fromgroups=#!topic/phantomjs/8LrWRW8ZrA0
找到了一段有用的代码var hitRockBottom = false; while (!hitRockBottom) {
// Scroll the page (not sure if this is the best way to do so...)
page.scrollPosition = { top: page.scrollPosition + 1000, left: 0 };
// Check if we've hit the bottom
hitRockBottom = page.evaluate(function() {
return document.querySelector(".has-more-items") === null;
}); }
其中
.has-more-items
是我想要访问的元素类,它最初位于页面底部,当我们向下滚动时,它会进一步向下移动,直到所有数据加载完毕,然后变得不可用。
但是,当我测试时,很明显它会在不向下滚动的情况下陷入无限循环(我渲染图片进行检查)。我也尝试用下面的代码替换
page.scrollPosition = { top: page.scrollPosition + 1000, left: 0 };
(一次一个)
window.document.body.scrollTop = '1000';
location.href = ".has-more-items";
page.scrollPosition = { top: page.scrollPosition + 1000, left: 0 };
document.location.href=".has-more-items";
但似乎没有任何效果。
找到了一种方法并尝试适应您的情况。我没有测试查找页面底部的最佳方法,因为我有不同的上下文,但请检查下面的解决方案。这里的问题是,您必须等待一段时间才能加载页面,并且 javascript 异步工作,因此您必须使用
setInterval
或 setTimeout
(see) 来实现此目的。
page.open('http://example.com/?q=houston', function () {
// Check for the bottom div and scroll down from time to time
window.setInterval(function() {
// Check if there is a div with class=".has-more-items"
// (not sure if there's a better way of doing this)
var count = page.content.match(/class=".has-more-items"/g);
if(count === null) { // Didn't find
page.evaluate(function() {
// Scroll to the bottom of page
window.document.body.scrollTop = document.body.scrollHeight;
});
}
else { // Found
// Do what you want
...
phantom.exit();
}
}, 500); // Number of milliseconds to wait between scrolls
});
我知道很久以前就已经回答了,但我也找到了针对我的具体场景的解决方案。结果是一段滚动到页面底部的 JavaScript。它经过优化以减少等待时间。
默认情况下它不是为 PhantomJS 编写的,因此必须进行修改。然而,对于初学者或没有 root 访问权限的人来说,注入 javascript 的 Iframe(使用 --disable-javascript 参数运行 Google Chrome)是抓取较小的 ajax 页面集的一个很好的替代方法。主要好处是它易于调试,因为您可以直观地了解刮刀的运行情况。
function ScrollForAjax () {
scrollintervals = 50;
scrollmaxtime = 1000;
if(typeof(scrolltime)=="undefined"){
scrolltime = 0;
}
scrolldocheight1 = $(iframeselector).contents().find("body").height();
$("body").scrollTop(scrolldocheight1);
setTimeout(function(){
scrolldocheight2 = $("body").height();
if(scrolltime===scrollmaxtime || scrolltime>scrollmaxtime){
scrolltime = 0;
$("body").scrollTop(0);
ScrapeCurrentPage(iframeselector);
}
else if(scrolldocheight2>scrolldocheight1){
scrolltime = 0;
ScrollForAjax (iframeselector);
}
else if(scrolldocheight1>=scrolldocheight2){
ScrollForAjax (iframeselector);
}
},scrollintervals);
scrolltime += scrollintervals;
}
scrollmaxtime 是一个超时变量。希望这对某人有用:)
“正确”的解决方案对我不起作用。而且,据我所知,CasperJS 不使用
window
(但我可能是错的),这让我怀疑 window
是否有效。
以下内容在 Firefox/Chrome 控制台中适用于我;但是,在 CasperJS 中不起作用(在
casper.evaluate
函数内)。
$(document).scrollTop($(document).height());
CasperJS 对我有用的是:
casper.scrollToBottom();
casper.wait(1000, function waitCb() {
casper.capture("loadedContent.png");
});
将
casper.capture
移动到 Casper 的 then
函数中也有效。
但是,上述解决方案在 Twitter 等某些网站上不起作用; jQuery 似乎破坏了
casper.scrollToBottom()
功能,当我在 Twitter 中工作时,我不得不删除对 jQuery 的 clientScripts
引用。
var casper = require('casper').create({
clientScripts: [
// 'jquery.js'
]
});
一些网站(例如 BoingBoing.net)似乎可以很好地使用 jQuery 和 CasperJS
scrollToBottom()
。不知道为什么有些网站可以运行,而另一些则不能。
下面的代码片段对于 pinterest 来说工作得很好。我做了很多研究,在没有 phantomjs 的情况下抓取 pinterest,但不可能找到无限滚动触发链接。我认为下面的代码将有助于其他无限滚动网页的抓取。
page.open(pageUrl).then(function (status) {
var count = 0;
// Scrolls to the bottom of page
function scroll2btm() {
if (count < 500) {
page.evaluate(function(limit) {
window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
return document.getElementsByClassName('pinWrapper').length; // use desired contents (eg. pin) selector for count presence number
}).then(function(c) {
count = c;
console.log(count); // print no of content found to check
});
setTimeout(scroll2btm,3000);
} else {
// required number of item found
}
}
scroll2btm();
});