2016-11-05 5 views
0

Я очищаю сайт, который использует компоненты React, используя PhantomJS в Nodejs.Скребок с сайтом 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);' и он возвращает успех. Я получаю весь контент HTML, кроме реагирующих компонентов, где я получаю '' – DennisKo

+0

Я подозреваю 'статус', если из обратного вызова' page.open', и вам нужно проверить наличие ошибок на странице .onError callback. Может быть что-то вроде этого: [Почему я не могу сделать свое приложение ReactJS с помощью PhantomJS] (http://stackoverflow.com/questions/38469005/why-i-am-not-able-to-render-my-reactjs -application-using-phantomjs-2-1-1) – Vaviloff

ответ

3

Думаю, вам стоит ждать рендеринга элементов реакции на странице после загрузки страницы. Пример такой функции ожидания, используя обещания Q, приведен ниже. Эта функция возвращает обещание и проверяет состояние страницы каждые 50 мс. Если достигнуто требуемое состояние страницы, функция выполняет обещание. В случае таймаута функция отвергает обещание.

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