2016-11-05 113 views
0

我正在使用Nodejs中的PhantomJS來刮取使用React組件的網站。用Phantomjs刮掉React站點

有了這個: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);'並且它返回成功。我得到整個HTML內容,除了反應組件,我得到了'<! - react-empty:1 - >' – DennisKo

+0

我懷疑'status',如果來自'page.open'回調,並且您需要檢查頁面中的錯誤.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橋連接到PhantomJS的問題? – Vaviloff

+0

@Vaviloff我採用了橋樑的例子 –

+0

對不起,我無法測試你的解決方案。我切換到NightmareJS(看我更新的問題)。這大大簡化了我的問題。 – DennisKo