web-dev-qa-db-ja.com

Phantomjsで下にスクロールして動的コンテンツを読み込む方法

ユーザーが下にスクロールするときにコンテンツを動的に生成するページからリンクをスクレイピングしようとしています(無限スクロール)。 Phantomjsでさまざまなことを試みましたが、最初のページを超えてリンクを収集できません。コンテンツをロードする下部の要素にクラス_.has-more-items_があるとしましょう。スクロール中に最終コンテンツがロードされ、DOMで使用できなくなるまで使用可能です(display:none)。ここに私が試したものがあります-

  • var page = require('webpage').create();の直後にviewportSizeを大きな高さに設定する

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、function(){//console.log('check for execution ');});

そのままで、_document.ready_内でも。 JSコードについても同様です

_window.scrollBy(0,10000)
_

そのままで_window.onload_の内部

私は今2日間本当にそれに打たれ、方法を見つけることができません。ヘルプまたはヒントをいただければ幸いです。

更新

https://groups.google.com/forum/?fromgroups=#!topic/phantomjs/8LrWRW8ZrA で役立つコードを見つけました

_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 };_を以下のコードでも置き換えようとしました(一度に1つずつ)

_window.document.body.scrollTop = '1000';
location.href = ".has-more-items";
page.scrollPosition = { top: page.scrollPosition + 1000, left: 0 };
document.location.href=".has-more-items";
_

しかし、何もうまくいかないようです。

46
Puneet Saini

それを行う方法を見つけ、あなたの状況に適応しようとしました。コンテキストが異なるため、ページの一番下を見つける最良の方法をテストしませんでしたが、チェックしてみてください。問題は、ページがロードされるまで少し待つ必要があり、javascriptが非同期に動作するため、setIntervalまたはsetTimeoutを使用する必要があることです( see )。

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

});
45
João Pesce

かなり前に回答されたことは知っていますが、特定のシナリオの解決策も見つけました。結果は、ページの下部にスクロールするJavaScriptの一部です。待ち時間を短縮するために最適化されています。

デフォルトではPhantomJS用に作成されていないため、変更する必要があります。ただし、初心者またはルートアクセス権を持たない人にとっては、JavaScriptを挿入したIframe(Google Chrome with --disable-javascript parameter)を実行すると、より小さな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はタイムアウト変数です。これが誰かに役立つことを願っています:)

以下のコードスニペットは、pinterestで正常に機能します。 phantomjsなしでpinterestをスクレイプするために多くのことを研究しましたが、無限のスクロールトリガーリンクを見つけることは不可能です。以下のコードは、他の無限スクロールWebページをスクレイピングするのに役立つと思います。

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();
            })
1
Suben Saha