2016-11-05 21 views
0

NodejsでPhantomJSを使用して、Reactコンポーネントを使用しているWebサイトを削っています。これによりPhantomjsでサイトを掻き集める

https://github.com/amir20/phantomjs-node

ここではコードです:

phantom.create().then(ph => { 
    _ph = ph; 
    return _ph.createPage(); 
}).then(page => { 
    _page = page; 
    return _page.open(url); 
}).then(status => { 
    return _page.property('content'); 
}).then(content => { 
    console.log(content); 
    _page.close(); 
    _ph.exit(); 
}).catch(e => console.log(e)); 

問題が反応したコンテンツがレンダリングされていないで、それだけで言う:実際には、コンポーネントがロードされるべき反応<!-- react-empty: 1 -->"

レンダリングされた反応コンポーネントをスクラップするにはどうすればよいですか?私は最初、純粋なノード要求ソリューションからPhantomJSに切り替えてこれを修正しましたが、今は止まっています。


UPDATE:

だから私はまだ真の解決策を持っていけません。私はNightmareJS(https://github.com/segmentio/nightmare)に切り替えました。これは、.wait('.some-selector')機能があり、指定されたセレクタがロードされるまで待機します。これにより、動的に読み込まれた反応コンポーネントの問題が修正されました。

+0

このパッケージはpage.onErrorコールバックの受信をサポートしていますか?何か間違いはありますか? – Vaviloff

+0

はい、 'console.log(status);'が成功したことを返します。 '<! - react-empty:1 - >' – DennisKo

+0

'page.open'コールバックから' status'疑いがあり、ページ内のエラーをチェックする必要があります.onErrorコールバック。このようなものかもしれません:[なぜPhantomJSを使って私のReactJSアプリケーションをレンダリングできないのですか?](http://stackoverflow.com/questions/38469005/why-i-am-not-able-to-render-my-reactjs -application-using-phantomjs-2-1-1) – Vaviloff

答えて

3

ページがロードされた後、反応要素をページ上にレンダリングするのを待つべきだと思います。このような待機関数の例は、Qの約束を用いて以下の通りです。この関数は約束を返し、50msごとにページ状態をチェックします。必要なページ状態に達すると、関数は約束を解決します。タイムアウトの場合、関数は約束を拒否します。

var phantom = require('phantom'); 
var Q = require('q'); 
var _ph, _page, _outObj; 
var url = 'https://tech.yandex.ru/maps/jsbox/'; 

phantom.create().then(ph => { 
    _ph = ph; 
    return _ph.createPage(); 
}).then(page => { 
    _page = page; 
    return _page.open(url); 
}).then(status => { 
    console.log(status); 
    return waitState(textPopulated, 3); 
}).then(() => { 
    return _page.property('content'); 
}).then(content => { 
    console.log(content); 
_page.close(); 
_ph.exit(); 
}).catch(e => console.log(e)); 

function textPopulated() { 
    return _page.evaluate(function() { 
     var layer = document.querySelector('.ace_text-layer'); 
     return layer && layer.childElementCount; 
    }).then(function(childElementCount) { 
     console.log('childElementCount: ' + childElementCount); 
     return childElementCount > 0; 
    }); 
} 

function waitState(state, timeout) { // timeout in seconds is optional 
    console.log('Start waiting for state: ' + state.name); 

    var limitTime = timeout * 1000 || 20000; 
    var startTime = new Date(); 

    return wait(); 

    function wait() { 
     return state().then(function(result) { 
      if (result) { 
       console.log('Reached state: ' + state.name); 
       return; 
      } else if (new Date() - startTime > limitTime) { 
       var errorMessage = 'Timeout state: ' + state.name; 
       console.log(errorMessage); 
       throw new Error(errorMessage); 
      } else { 
       return Q.delay(50).then(wait); 
      } 
     }).catch(function(error) { 
      throw error; 
     }); 
    } 
} 
+1

node.js bridgeとPhantomJSの使用方法を教えてください。 – Vaviloff

+0

@Vaviloff私はブリッジの例を採用しました –

+0

申し訳ありませんが、私はあなたのソリューションをテストできませんでした。私はNightmareJSに切り替えました(私の更新された質問を見てください)。私の問題は大幅に簡素化されます。 – DennisKo

関連する問題