LINUX.ORG.RU

php-шный loadHTML неверно работает с JS

 loadhtml,


0

2

Пытаюсь загрузить следующий код в domDocument (код упрощён):

<html>
  <body>
    <div>
      <script type="text/javascript">
        <!--
        div.innerHTML = "<div><table><tr><td><a href='#'>close</a></td></tr></table></div>";
        //-->
      </script>
    </div>
  </body>
</html>

Затем делаю saveHTML, на выходе получается:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
  <body>
	<div>
	  <script type="text/javascript">
		<!--
		div.innerHTML = "<div><table><tr><td><a href='#'>close</script>
		</div>";
	    //--&gt;
</body></html>

Т.е. JS парсится как обычный HTML. В документации по loadHTML нет особых упоминаний, как можно управлять её работой. Оборачивание в //<![CDATA[ не помогает. В интернетах информации по проблеме крайне мало, самое подробное, что удалось найти: http://bytes.com/topic/php/answers/646507-problem-loading-html-containing-scr..., но это аж за 2007 год и без решения. Подозреваю, что я просто что-то упустил, но не понимаю что. Кто-нибудь сталкивался?

★★
Ответ на: комментарий от Deleted

И? Парсер разберёт правильно в любом случае, регэксп — нет. О чём и речь.

1 вариант:
<body>
<div>Адрес: ...................</div>
<span></span>
</body>
2 вариант:
<body>
<div></div>
<span>Адрес: ...................</span>
</body>

вытащи из обоих вариантов адрес без регэкспов.

Те, которые ты предусмотрел. Это сложнее, чем кажется.

Остальные парсеры можно писать не задумываясь о том какие будут входные данные?

У ТСа ПХП, это уже совсем другая история.

В каком смысле?))

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

вытащи из обоих вариантов адрес без регэкспов.

Это уже данные, из которых ты уже как хочешь можешь что-то получить. ПХП уже не умеет работать со строками? А чтобы этот «Адрес: .......» найти, тебе надо сначала документ разобрать. Что корректно во всех случаях ты не сделаешь регэкспами, потому что там может быть кроме этого чёрти что ещё, в т.ч. другие атрибуты.

Остальные парсеры можно писать не задумываясь о том какие будут входные данные?

Смешно, да. Подумай на тему того, как работают регэкспы и почему другой парсер сможет, а они нет. Подсказка: ты здесь пытаешься написать свой парсер, используя грамматику, которая не предназначена для этих данных. Причём ТСу, собственно, хочется не новый парсер изобрести.

В каком смысле?))

http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/ :}

Deleted
()
Ответ на: комментарий от Deleted

Это уже данные, из которых ты уже как хочешь можешь что-то получить. ПХП уже не умеет работать со строками? А чтобы этот «Адрес: .......» найти, тебе надо сначала документ разобрать. Что корректно во всех случаях ты не сделаешь регэкспами, потому что там может быть кроме этого чёрти что ещё, в т.ч. другие атрибуты.

Если может быть «черти что» то это проблема для всех парсеров.
А если задача вполне определена, как в данном случае, то она только регэкспами и решается.

Смешно, да. Подумай на тему того, как работают регэкспы и почему другой парсер сможет, а они нет.

Что другой парсер сможет, чего не смогут регэкспы?
У регэкспов единственная проблема это увеличение сложности регулярного выражения пропорционально рандомности входных данных.
А для других парсеров я уже привел выше пример нерешаемой ситуации. Причём этот пример не мифический, он встречается на практике.

Подсказка: ты здесь пытаешься написать свой парсер, используя грамматику, которая не предназначена для этих данных. Причём ТСу, собственно, хочется не новый парсер изобрести.

Да не пытаюсь я ничего написать) тема уже давно перешла в холивар.

http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/ :}

Солидарен с этим мнением. Но это не о чём не говорит. Если ты знаешь добротный парсер html, реализованный на других языках, с удовольствием буду пользоваться им вместо регэкспов, там где это будет оправдано.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

>Если может быть «черти что» то это проблема для всех парсеров.
>А если задача вполне определена, как в данном случае, то она только регэкспами и решается.
У тебя программа только на _одном_ наборе данных работает что ли? Ну, тогда да.

>Что другой парсер сможет, чего не смогут регэкспы?
Ты про грамматики то почитай что-нибудь :} Погугли, примеры того, как разваливается этот весь регэксп, смелее.

>Но это не о чём не говорит.
Это говорит о том, что там всё криво само по себе.

>Если ты знаешь добротный парсер html, реализованный на других языках, с удовольствием буду пользоваться им вместо регэкспов, там где это будет оправдано.
А что, все не работают? Берёшь язык, смотришь что там есть, и вперёд.

Deleted
()
Ответ на: комментарий от TDrive

А для других парсеров я уже привел выше пример нерешаемой ситуации

нерешаемой

Чё, правда? Решается примерно так: //*[text()[starts-with(.,'Адрес')]]
Я выше привёл пример задачи выкусывания родителя subtitle, которая не решается регулярными выражениями, но ты как-то промолчал.

SOmni ★★
() автор топика
Ответ на: комментарий от Deleted

У тебя программа только на _одном_ наборе данных работает что ли? Ну, тогда да.

Я так и не понял, что для тебя набор данных.

А что, все не работают? Берёшь язык, смотришь что там есть, и вперёд.

Другими словами, ты такого не знаешь и то, что ты говоришь это твоих домыслы имеющие мало общего с практикой.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

>Я так и не понял, что для тебя набор данных.
Входные HTML файлы. Их разметка может быть какой угодно. Регэкспами все варианты не продумаешь. Это так сложно понять?

>Другими словами, ты такого не знаешь и то, что ты говоришь это твоих домыслы имеющие мало общего с практикой.
Доо. Уже бегу искать. В моих домыслах я беру парсер, который предоставляет мне язык или одна из библиотек, описанных в доках, и пользуюсь. Мне тебе документации читать?

Deleted
()
Ответ на: комментарий от TDrive

это просто пример, думаю можно и более точное составить

Поверь, когда регексп достигает хотя бы половины возможностей xpath, он становится исключительно write-only, страшно глючит и хочет уйму времени на написание :)

Я такие регекспы много лет писал, пока с xquery не познакомился. Понятно, что можно и судоходный канал лопатой выкопать. И так их и копали когда-то. Но на дворе XXI век и экскаваторы.

KRoN73 ★★★★★
()
Ответ на: комментарий от SOmni

Я выше привёл пример задачи выкусывания родителя subtitle, которая не решается регулярными выражениями, но ты как-то промолчал.

#!/usr/bin/perl
use strict;
my $str = '<h1><span></span><div id=«subtitle»></div><a></a></h1>
<h3><span></span><div id=«subtitle»></div><a></a><a></a><a></a><a></a></h3>
<div><div id=«subtitle»></div><a></a></div>';

print «passed: $1\n» while ($str =~ m/(<([a-zA-Z0-9]+)>.*?<div id=«subtitle»><\/div>.*?<\/\2>)/g );

./test.pl
passed: <h1><span></span><div id=«subtitle»></div><a></a></h1>
passed: <h3><span></span><div id=«subtitle»></div><a></a><a></a><a></a><a></a></h3>
passed: <div><div id=«subtitle»></div><a></a></div>


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

Чё, правда? Решается примерно так: //*[text()[starts-with(.,'Адрес')]]

а если перед «Адрес» рандомное количество пробелов? Только не говори что там есть спецсимволы и квантификаторы потому, что получится тоже самое регэксп только другими средствами)

TDrive ★★★★★
()
Ответ на: комментарий от KRoN73

Регекспы много чего не могут.

И парсеры не на регэкспах тоже много чего не могут. И разные задачи иногда удобнее решать регэкспами иногда нет.

Просто считать, что регэкспы не подходят для парсинга html не правильно. Разные задачи - разные инструменты. А с учётом глючности и не прозрачности «специализированных парсеров» в простеньких задачах я бы отдал предпочтение регэкспам.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

И парсеры не на регэкспах тоже много чего не могут

Само собой. Только от того, что вилкой неудобно кушать суп, ты предлагаешь ложкой резать мясо.

А ты напоминаешь человека, который впервые взял в руки молоток и которому теперь всё начало напоминать гвозди.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

ОК, вот пример с первого поста, там не просто ошибка с js, а пропадает часть тегов и нарушается структура документа,а если это повлияет на результат парсинга? а если этот js появляется только в определённых случаях? а если там есть ещё 25 ошибок подобного характера? как их искать?

Если ножи на столько кривые, что можно отрезать голову, то приходится резать мясо ложкой.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Если ножи на столько кривые, что можно отрезать голову, то приходится резать мясо ложкой.

Проблема ещё в том, что хоть ножи и кривые, но у твоей ложки постоянно отваливается ручка и каждый день нужно затыкать дырки в днище :)

Я так понимаю, что у тебя просто практики работы с XPath нет. А у меня она довольно широкая и с ним, и с регекспами. Так что могу сравнивать.

У регекспов есть широкая область применения. И частично парсинг HTML регекспами оправдан. Но в конкретных и специфичных случаях. В общем случае манипуляции через DOM несравнимо эффективнее и надёжнее.

KRoN73 ★★★★★
()
Ответ на: комментарий от TDrive

Пример сильно упрощённый но суть должна быть понятна

Нет, не понятна. Эти примеры настолько упрощены, что это даже за попытку считать нельзя. И не забывай, что subtitle сам не пустой. Нельзя сказать, насколько это будет на практике сложнее, потому что нельзя делить на ноль.

это всё тоже решаемо

В том-то и соль, что это нерешаемо.

получится тоже самое регэксп только другими средствами

нет, получится «другими средствами с использованием регэкспов» - это разные вещи.

SOmni ★★
() автор топика
Ответ на: комментарий от SOmni

Нет, не понятна.

Тогда не чем не могу помочь.

нет, получится «другими средствами с использованием регэкспов» - это разные вещи.

лол, как скажите.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Проблем не вижу.

Проблема в том, что на любой предложенный тобой регэксп мы всегда найдем пример, когда он не работает. Ты доработаешь его для этого случая (попутно делая регэксп еще более нечитаемым), снова покажешь, мы снова найдем случай, когда он не работает.

И так будет бесконечно, потому что регэкспы не могут полностью решить проблему.

stevejobs ★★★★☆
()
Ответ на: комментарий от TDrive

Всё время парсил, а тут оказывается нельзя) эпично.

тебе надо почитать какую-нибудь хорошую книгу про языки программирования

stevejobs ★★★★☆
()
Ответ на: комментарий от TDrive

Рандомная структура DOM дерева это не корректные данные?

Структура DOM формально описана. Возможности ECMAScript и его синтаксис - тоже формально описаны.

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

И для XPath всегда можно найти пример когда он не работает. Я выше показал пример который не решаем без регэкспов. Причём в случае регэкспов это приводит к усложнению, а в случае XPath это приводит к использованию регэкспов.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

Я выше показал пример который не решаем без регэкспов

1. Он решаем, просто вместо starts-with уместнее использовать contains.
2. Он не имеет отношения к анализу DOM, это обычный парсинг, когда нужно найти шаблон в тексте. Тот факт, что текст при этом содержит тэги не играет никакой роли, поэтому там проще и правильнее использовать регулярки.

SOmni ★★
() автор топика
Ответ на: комментарий от SOmni

Можно придумать пример когда меняется DOM. Это не принципиально.
Суть в том что регэкспы для парсинга html вполне годны, а иногда только ими и можно добиться результата. По этому говорить что регэкспы вообще не нужны и все тру программисты парсять без регэкспов, как минимум глупо.
Просто для каждой задачи нужно выбирать тот способ который лучше подходит, учитываю плюсы и минусы XPath и регэкспов.

Давайте на этом и закончим.

TDrive ★★★★★
()
Ответ на: комментарий от TDrive

ANTLR (для грамматик LL(*)), YACC/Bison (для грамматик LALR). Есть еще всякое разное.
В первом случае нужно делать так, чтобы оно не было left-recursive. Во втором — иметь секос со странными ошибками. Имхо, ANTLR проще.

Например, вебкит (хром, сафари) использует YACC/Bison.

Возможно, вот эта статья наведет на какие-то размышления: http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/

stevejobs ★★★★☆
()
Ответ на: комментарий от TDrive

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

Если автор документа написал какую-то лажу, не подходящую ни под один из стандартов, такой документ можно не парсить. Написатели говна должны страдать :)

stevejobs ★★★★☆
()
Ответ на: комментарий от TDrive

HTML DOM - это то, что описано в стандартах типа этого: http://www.w3.org/TR/DOM-Level-2-HTML/html.html

И других стандартах, посвященных DOM: http://www.w3.org/TR/#tr_DOM

AST и промежуточные parse tree - не стандарт, ты об этом?

===

Если коротко, PCRE парсят регулярные языки, а HTML - контекстно свободный.

Иначе говоря, в общем случае, DOM полученный в результате работы PCRE не будет совпадать с настоящим DOM этого документа.

Вот, держи крутой документ для размышлений, как это должно быть по-настоящему: http://www.whatwg.org/specs/web-apps/current-work/multipage/index.html#auto-t...

Практический вывод - вместо PCRE нужно использовать парсеры (генераторы парсеров), как советовал «неадекват на Stackoverflow».

ТС в топике как раз жалуется, что парсер в PHP - говно. То есть, делает всё правильно.

Больше о способах разбора текста на языках программирования ты можешь узнать, прочитав какую-нибудь хорошую книжку.

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Опять 25).
Перечитывайте этот тред с первого поста до полного просветления.

TDrive ★★★★★
()
Ответ на: комментарий от anonymous

Когда я парсил тысячи сайтов, самое нормальное было это phpquery, хотя вот ошибки всё равно были, но это из-за мудачья которые где то теги не закрывали, где еще что, в некоторых наблюдался сжатый js код. И при этом всё же ошибок было сравнимо меньше чем мои регулярки выдавали.

Я представляю как мучались по поводу поисковые системы.

spiritkhl
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.