CasperJS с селекторами jQuery и CSS3 не работает должным образом

У меня возникли проблемы с выбором элементов на некоторых страницах со старым HTML.

Если я введу jQuery в консоль javascript Chrome и сам выполню код, он вернет правильное значение. Однако, когда я пытаюсь сделать это в CasperJS, это не работает. Поэтому я сделал небольшой скрипт, чтобы проверить, что происходит:

(casper.start и casper.run опущены)

casper.then(function() {
    this.echo("1: Entire Row");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3)").html();
    }));

    this.echo("2: More specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2)").html();
    }));

    this.echo("3: More specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p").html();
    }));

    this.echo("4: Even more specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));

    this.echo("5: Using jQuery functions");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3)").children("td:nth-child(2)").children("p").children("font").html();
    })); //Ugly workaround

});

И когда я запускаю его, это результат:

1: Entire Row
<td height="23" width="226" style="border-style: solid; border-width: 1px" bordercolor="#666666" colspan="2">
        <p>
        <img width="16px" height="16px" src="upload/imagens/bandeira_eua.gif">
        <strong>Dólar americano (USD)</strong>
</p></td>
<td height="23" width="80" style="border-style: solid; border-width: 1px" bordercolor="#666666">
        <p><font size="2">2,400</font>
</p></td>
<td height="23" width="81" style="border-style: solid; border-width: 1px" bordercolor="#666666">
        <p><font size="2">2,600</font>
</p></td>

2: More specific //Correct so far...
<p><font size="2">2,400</font> 
</p>

3: More specific //What? This is from another row!!
<font size="2">3,060</font>

4: Even more specific
null //What??

5: Using jQuery functions
2,400 //Correct result

Однако, если я захожу на веб-сайт с помощью Chrome и добавляю тот же jQuery в консоль, он работает, как и ожидалось:

$("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
"2,400"

Что происходит??? Использование нативных методов CasperJS для получения значения тоже не работает.

ps: CasperJS версии 1.1.0-beta3 с PhantomJS версии 1.9.0

ps1: путь CSS был сгенерирован в Chrome Dev Tools, «Копировать путь CSS».

РЕДАКТИРОВАТЬ: Еще более странно: этот скрипт

casper.then(function() {
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));

    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));
});

возвращает:

2,400
null

Стабильно работает только в первый раз, даже если разбить на 2 каспер.потом.


person Rogerio    schedule 27.09.2014    source источник
comment
Возможно ли, что контент все еще загружался? Добавьте casper.wait(5000); перед блоком then. Что происходит при обновлении до текущей версии PhantomJS 1.9.7. Какие нативные функции casperjs вы пробовали casper.getHTML или, может быть, document.querySelector("...").innerHTML в контексте страницы? Возможно, разметка страницы каким-то образом искажена, и PhantomJS делает ошибки при разборе/запросе. Вы можете попробовать сравнить версию CasperJS с версиями getHTML и Chrome с исходным кодом. Вы даже можете проверить версию Casper через W3C.   -  person Artjom B.    schedule 27.09.2014
comment
casper.getHTML возвращает то же самое, но возвращает ошибку, когда не находит, а не возвращает null. document.querySelector(...).innerHTML в контексте страницы также возвращает то же самое, что и jQuery.   -  person Rogerio    schedule 27.09.2014


Ответы (1)


К сожалению, Casper/PhantomJS Webkit отличается от Chrome. Xpath, которые работают на хроме, не всегда будут работать на PhantomJS, и чтобы найти причину, нужно копаться в сложном коде C++.

По сути, это не отвечает на вопрос, но подтверждает, что я сталкивался с такими же ситуациями раньше. обходной путь заключается в том, чтобы найти более последовательный развернутый xpath для поиска элемента с помощью текста, атрибута, класса, идентификатора и т. д., чем детализировать оттуда. Даже если вам нужно пройти мимо своего элемента, чтобы работать, он доходит до родителя или родного брата и т. Д., Он более надежен, чем абсолютный путь dom, основанный на общих тегах.

xpath, такие как //div/div/div/p/a/span/text(), не очень надежны в phantomjs.

person Chris Hawkes    schedule 01.10.2014