我是PhantomJS的新手并试图捕捉Trade Me的主页。到目前为止,这是我的代码:
var page = require('webpage').create();
page.open('http://trademe.co.nz', function () {
// Checks for bottom div and scrolls down from time to time
window.setInterval(function() {
// Checks if there is a div with class=".has-more-items"
// (not sure if this is the best way of doing it)
// var count = page.content.match(/class=".site-footer"/g);
var footer_visible = page.evaluate(function() {
return $('.site-footer').is(':visible');
});
if(!footer_visible) { // Didn't find
console.log('Scrolling');
page.evaluate(function() {
// Scrolls to the bottom of page
window.document.body.scrollTop = document.body.scrollHeight;
});
}
else { // Found
console.log('Found');
// Do what you want
window.setTimeout( function() {
console.log('Capturing');
page.render('phantom-capture.png', {format: 'png'});
phantom.exit();
}, 10000);
}
}, 1000); // Number of milliseconds to wait between scrolls
});
有几件事令我困惑:
Scrolling
这个词永远不会被打印出来。Found
,并且该单词被打印10次。我认为这是因为它包含在setInterval
块中,间隔为1秒,并且由setTimeout
导致等待10秒?Loading...
消息。我对这一切都很陌生,而且我对Javascript的了解非常生疏。
答案 0 :(得分:3)
您遇到了如何判断网页何时完全加载的常见问题。这其实很难!我在很久以前写过一篇关于这个问题的博客文章:https://sorcery.smugmug.com/2013/12/17/using-phantomjs-at-scale/(请参阅问题#1)以下是我对您的代码和问题的反馈:
首先,你不需要滚动来知道页脚是否已加载,如果元素占用文档中的空格,jQuery的:visible
选择器将返回true,而不是在视口中:https://api.jquery.com/visible-selector/。我一般也不会使用PhantomJS的视口可见性,因为它确实无头。
其次,page.open()
回调会在页面加载时触发。根据PhantomJS。这个主要是意味着什么时候它已经完全加载了HTML及其所有包含的资产。但是,这并不意味着已加载异步加载的内容。
第三,我相信你会看到输出'发现'十倍,因为您使用window.setInterval
检查页脚和使用window.setTimeout
进行渲染。发生了什么事:
page.open()
的回调。footer_visible
为真如果你真的想在页脚在文档中时呈现页面,这是你的固定代码:
var page = require('webpage').create();
page.open('http://trademe.co.nz', function () {
window.setInterval(function() {
var footer_visible = page.evaluate(function() {
return $('.site-footer').is(':visible');
});
if(footer_visible) {
page.render('phantom-capture.png', {format: 'png'});
phantom.exit();
}
}, 1000);
});
但是,一旦加载了所有内容,这将无法呈现,这是很多更难的问题。请阅读我上面链接的博客文章,了解如何执行此操作的提示。这是一个非常难的问题。如果您不想阅读我的博文,这里是TLDR;
通过大量的手动测试和质量保证,我们最终来到了 我们跟踪PhantomJS发出的每个HTTP请求的解决方案 并观察交易的每一步(开始,进展,结束, 失败)。每个请求只完成一次(或失败等) 我们开始'等待'。我们给500ms页面开始制作更多 请求或完成向DOM添加内容。在超时之后我们 假设页面已完成。
答案 1 :(得分:2)
Ryan Doherty提供了很好的解释,为什么console.log('Scrolling');
永远不会被调用,你弄清楚为什么Found
被自己打印10次!
我想谈谈如何处理那些被禁化的页面。一般来说,当你使用这些网站时,你可以找出判断页面是否已加载的标准,或者至少部分是你需要的标准(尽管有时,正如Ryan正确指出的那样,它可能非常难,特别是如果有的话是一个页面上的很多外部资源和/或iframe)。
在这种情况下,我想我们可以决定在没有&#34;加载&#34;标签留下。所以我们关闭javascript并检查这些标签。原来他们是<div class="carousel-loading-card">
。这意味着我们只需要等到它们消失。但要触发加载,我们必须模拟页面滚动。在PhantomJS中你可以原生地&#34;通过更改page.scrollPosition设置来实现这一点。
var page = require('webpage').create();
// Let's not confuse the target site by our default useragent
// and native viewport dinemsions of 400x300
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0';
page.viewportSize = { width: 1280, height: 1024 };
var totalHeight, scroll = 0;
page.open('http://trademe.co.nz', function(){
totalHeight = page.evaluate(function(){
return $(document).height();
});
wait();
});
function wait()
{
var loading = page.evaluate(function(){
return $(".carousel-loading-card").length;
});
if(loading > 0) {
if(scroll <= totalHeight)
{
scroll += 200;
page.scrollPosition = {
top: scroll,
left: 0
};
page.render('trademe-' + (new Date()).getTime() + '.jpg');
}
console.log(loading + " panels left. Scroll: " + scroll + "px");
setTimeout(wait, 3000);
} else {
// Restore defaults to make a full page screenshot at the end
page.scrollPosition = { top: 0, left: 0 };
page.render('trademe-ready.png');
phantom.exit();
}
}