Как прокрутить вниз с помощью Phantomjs для загрузки динамического содержимого
Я пытаюсь очистить ссылки со страницы, которая динамически генерирует контент, когда пользователь прокручивается вниз (бесконечная прокрутка). Я пробовал делать разные вещи с Phantomjs, но не смог собрать ссылки за первой страницей. Пусть говорят, что элемент внизу, который загружает контент, имеет класс .has-more-items
. Он доступен до тех пор, пока окончательный контент не будет загружен во время прокрутки, а затем будет недоступен в DOM (display: none). Вот что я пробовал -
- Настройка viewportSize на большую высоту сразу после
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
, но это дает
Исходная ошибка: не удается найти переменную страницу
- Пробовал использовать jQuery и JS-код внутри
page.evaluate
и page.open
, но безрезультатно -
$( "html, body" ). animate ({scrollTop: $(document).height()}, 10, function() { //console.log('check for execution '); });
как есть, а также внутри document.ready
. Аналогично для JS-кода -
window.scrollBy(0,10000)
как есть, а также внутри window.onload
Я действительно ударил его уже 2 дня и не смог найти способ. Любая помощь или намек будут оценены.
Обновление
Я нашел полезный фрагмент кода в 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";
Но ничего не работает.
Ответы
Ответ 1
Нашел способ сделать это и попытался адаптироваться к вашей ситуации. Я не тестировал лучший способ найти нижнюю часть страницы, потому что у меня был другой контекст, но проверьте его. Проблема в том, что вам нужно немного подождать, чтобы страница загружалась, а javascript работает асинхронно, поэтому вам нужно использовать setInterval
или setTimeout
(см.).
page.open('http://example.com/?q=houston', 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=".has-more-items"/g);
if(count === null) { // Didn't find
page.evaluate(function() {
// Scrolls 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
});
Ответ 2
Я знаю, что он был дан ответ уже давно, но я также нашел решение для моего конкретного сценария. Результатом является фрагмент javascript, который прокручивается в нижней части страницы. Он оптимизирован для уменьшения времени ожидания.
Он не написан для PhantomJS по умолчанию, поэтому его нужно будет изменить. Тем не менее, для новичков или тех, у кого нет доступа к корню, IFrame с внедренным javascript (запустите Google Chrome с параметром --disable-javascript) является хорошим альтернативным методом для сокрытия меньшего набора страниц 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 - это переменная времени ожидания. Надеюсь, это полезно кому-то:)
Ответ 3
"Правильное" решение для меня не сработало. И из того, что я читал, 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
в функцию Каспера then
.
Однако вышеупомянутое решение не будет работать на некоторых сайтах, таких как Twitter; jQuery, похоже, нарушает функцию casper.scrollToBottom()
, и мне пришлось удалить ссылку clientScripts
для jQuery при работе в Twitter.
var casper = require('casper').create({
clientScripts: [
// 'jquery.js'
]
});
Некоторые веб-сайты (например, BoingBoing.net), похоже, отлично работают с jQuery и CasperJS scrollToBottom()
. Не уверен, почему некоторые сайты работают, а другие нет.
Ответ 4
Ниже приведенный ниже фрагмент кода отлично подходит для pinterest. Я много исследовал, чтобы очистить pinterest без phantomjs, но невозможно найти бесконечную ссылку триггера прокрутки. Я думаю, что приведенный ниже код поможет очистить веб-страницу другой бесконечной прокрутки.
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();
})