9

ほぼ完全にJavaScriptで生成されたWebサイトのHTMLをダウンロードしようとしています。したがって、ブラウザアクセスをシミュレートする必要があり、PhantomJSで遊んでいます。問題は、サイトがハッシュバンURLを使用していて、PhantomJSにハッシュバンを処理させることができないようです。ホームページを呼び出し続けるだけです。

このサイトはhttp://www.regulations.govです。デフォルトでは、#!homeに移動します。次のコード(ここから)を使用して、さまざまなハッシュバンを処理してみました。

if (phantom.state.length === 0) {
     if (phantom.args.length === 0) {
        console.log('Usage: loadreg_1.js <some hash>');
        phantom.exit();
     }
     var address = 'http://www.regulations.gov/';
     console.log(address);
     phantom.state = Date.now().toString();
     phantom.open(address);

} else {
     var hash = phantom.args[0];
     document.location = hash;
     console.log(document.location.hash);
     var elapsed = Date.now() - new Date().setTime(phantom.state);
     if (phantom.loadStatus === 'success') {
             if (!first_time) {
                     var first_time = true;
                     if (!document.addEventListener) {
                             console.log('Not SUPPORTED!');
                     }
                     phantom.render('result.png');
                     var markup = document.documentElement.innerHTML;
                     console.log(markup);
                     phantom.exit();
             }
     } else {
             console.log('FAIL to load the address');
             phantom.exit();
     }
}

このコードは正しいハッシュバンを生成しますが(たとえば、ハッシュを「#!contactus」に設定できます)、動的に異なるHTMLを生成することはなく、デフォルトのページだけを生成します。ただし、を呼び出したときの出力は正しく行われますdocument.location.hash

また、初期アドレスをハッシュバンに設定しようとしましたが、スクリプトがハングして何もしません。たとえば、URLをhttp://www.regulations.gov/#!searchResults;rpp=10;po=0スクリプトに設定すると、アドレスを端末に出力した後にハングし、何も起こりません。

4

1 に答える 1

5

ここでの問題は、ページのコンテンツが非同期で読み込まれることですが、ページが読み込まれるとすぐに利用できるようになると期待しています。

コンテンツを非同期でロードするページをスクレイプするには、関心のあるコンテンツがロードされるまでスクレイプを待つ必要があります。ページによって確認方法は異なりますが、最も簡単なのは、見たいものが見つかるまで定期的に確認することです。

ここでの秘訣は、何を探すべきかを理解することです。目的のコンテンツが読み込まれるまでページに表示されないものが必要です。この場合、トップレベルのページで私が見つけた最も簡単なオプションは、各ページに表示されると予想されるH1タグを手動で入力し、ハッシュにキー入力することです。

var titleMap = {
    '#!contactUs': 'Contact Us',
    '#!aboutUs': 'About Us'
    // etc for the other pages
};

h1次に、成功ブロックで、繰り返しタイムアウトを設定して、タグで必要なタイトルを探すことができます。それが表示されたら、ページをレンダリングできることがわかります。

if (phantom.loadStatus === 'success') {
    // set a recurring timeout for 300 milliseconds
    var timeoutId = window.setInterval(function () {
        // check for title element you expect to see
        var h1s = document.querySelectorAll('h1');
        if (h1s) {
            // h1s is a node list, not an array, hence the
            // weird syntax here
            Array.prototype.forEach.call(h1s, function(h1) {
                if (h1.textContent.trim() === titleMap[hash]) {
                    // we found it!
                    console.log('Found H1: ' + h1.textContent.trim());
                    phantom.render('result.png');
                    console.log("Rendered image.");
                    // stop the cycle
                    window.clearInterval(timeoutId);
                    phantom.exit();
                }
            });
            console.log('Found H1 tags, but not ' + titleMap[hash]);
        }
        console.log('No H1 tags found.');
    }, 300);
}

上記のコードは私のために働きます。ただし、検索結果を取得する必要がある場合は機能しません。タイトルを事前に知らなくても、検索できる識別要素またはテキストを把握する必要があります。

編集:また、PhantomJSの最新バージョンはonResourceReceived、新しいデータを取得したときにイベントをトリガーするようになりました。これについては調べていませんが、リスナーをこのイベントにバインドして同じ効果を得ることができる場合があります。

于 2011-06-24T19:29:23.753 に答える