LINUX.ORG.RU

Быстрый парсинг HTML

 


0

3

Представьте такую парсилку:

1. Сначала разобрать HTML-документ на линейную последовательность тегов. Линейную, карл. Никаких отношений между тегами. Парсер не знает про то, что теги вложены друг в друга, имеют закрывающих собратьев и другое. Тег - имя + набор атрибутов. Иерархии нет. Закрывающий тег - тупо отдельное имя в той же плоской последовательности. Есть тег «TD», а есть тег «/TD», у них просто вот такие имена и парсеру неважно почему они такие. Какой-нибудь простой текст будет в итоге превращён в объект-тег типа «TEXT» с атрибутом value равный самому тексту, допустим.

2. Рассмотреть всю эту последовательность как строку, где вместо char объект «тег» (с атрибутами).

3. Сделать как-бы regexp-машинку, но не совсем regexp: она оперирует не символами текста (char), а этими самыми объектами-тегами, линейно следующими, как обычный текст.

В таком духе:

// заматчить любую пару тегов <TD> + </TD> с любыми тегами между ними.
// повторю: здесь всем пофиг на имена тегов. Никаких отношений между TD и /TD парсер HTML и данная regexp-машина не знают. Для неё это просто 2 каки-то там тега.
TD, * *, /TD


// то же самое, но только <TD> имеющий атрибут "hello" равный 123
TD hello=="123", * *, /TD

// можно замутить встроенный язык с переменными
// При встрече тега HTML создать i = 0
// Пропустить сколько угодно каких угодно тегов
// заматчить много последовательностей <TD> ... </TD>
// При матчинге очередного TD инкрементнуть переменную
// В итоге мы посчитаем число пар <TD>...</TD> заодно.

HTML $i=0, * *, (TD $i++, * *, /TD)*

Не будет ли такое быстрее, чем построение в памяти всего DOM-дерева и исполнение на этом дереве XPath-запросов?

Тебе нужно быстро или корректно? Потому что браузер все равно превращается щитимеле в дерево, и именно дерево для него имеет смысл. Вот если дерево обратно экспортировать в XHTML, то уже можно прыгать с регулярками или их подобиями.

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

Тебе нужно быстро или корректно? Потому что браузер все равно превращается щитимеле в дерево, и именно дерево для него имеет смысл. Вот если дерево обратно экспортировать в XHTML, то уже можно прыгать с регулярками или их подобиями.

Браузер тут ни при чём вроде.

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

HTML - это язык для браузеров, больше у него нет никаких применений. Что значит «браузер тут не при чем»?

Я могу скачать HTML обратившись по HTTP к серверу, не являясь браузером. С целью выпарсить что-то с сайта. Оторажать страничку не трубуется. И сайт не отдаёт то же самое в другом формате.

igloev ()

Ътмл это чистый адок. Если есть вариант взять xml, берите его. Если нет, то придётся чем-то пожертвовать в любом случае. Будет ли такой подход быстрее? Наверное нет. Зависит от объёмов. Эффективней по памяти? Вполне вероятно.

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

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

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

Я это к тому что предварительный парсинг тегов тебе сильно не поможет с дальнейшим парсингом «регулярками».

Почему не поможет? На выходе будет последовательность объектов

DIV, DIV, /DIV, DIV data-div==«</div foo=bar><div>», DIV

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

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

Если на входе

<div>
  <div class="foo">
    <p>FOO</p>
  </div>
  <div class="bar" data-bar="quux">
    <p><i>BAR</i></p>
  </div>
</div>

Твой колбэк получит по очереди что-то вроде:

<div>
<div><div class="foo">
<div><div class="foo"><p>
<div><div class="foo"><p>FOO
<div><div class="bar" data-bar="quux">
<div><div class="bar" data-bar="quux"><p>
<div><div class="bar" data-bar="quux"><p><i>
<div><div class="bar" data-bar="quux"><p><i>BAR

Но в виде объектов с метаинформацией, вроде порядкового номера доченего объекта.

dear_amomynous_v2_1 ()

у тебя там гигабайт html на одной страничке или ты запускаешься на микроконтроллере?

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

Ford_Focus ★★★★★ ()

Ты нуб. HTML — не XML, в нём не всегда теги закрыты. Например, <ul> часто не имеет парного </ul>: во-первых, потому что олдскульных вебмакак так учили, во-вторых — браузеры при наличии закрывающего тега ведут себя иначе и добавляют нежелательные отступы, которые приходится убирать дополнительными CSS-костылями. Непарные теги и вовсе поголовно без слеша юзаются, но это хотя бы решается словарём непарных тегов. Альзо, покури готовые парсеры, там уже наверняка есть нечто проще построения DOM.

anonymous ()

1. Сначала разобрать HTML-документ на линейную последовательность тегов. Тег - имя + набор атрибутов. Иерархии нет. Закрывающий тег - тупо отдельное имя в той же плоской последовательности.

Это называется лексический анализ.

2. Рассмотреть всю эту последовательность как строку символов, где символ - тег.

3. Сделать regexp-машинку, которая оперирует не символами текста, а тегами.

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

Не будет ли такое быстрее, чем построение в памяти всего DOM-дерева и исполнение на этом дереве XPath-запросов?

Результатом работы синтаксического анализатора является синтаксическое дерево, чем, в некотором смысле, и является DOM. Как я понимаю, вопрос можно перформулировать следующим образом: «не будут ли мой клёвый парсер и моё клёвое дерево быстрее, чем те, что я сейчас использую?» Ответ - нет.

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

3. Сделать regexp-машинку, которая оперирует не символами текста, а тегами.

Регекспы были полезны ...

Регекспы были полезны ... когда они были «обыкновенными регулярными выражениями», которые эквивалентны детерминированными конечным автоматам без магазина. Но история ойти пошла другим путем, теперь «регулярными выражениями» называют хер знает что, что даже автомат с магазином не всегда разберет то, что подразумевают под регекспом. И автор темы движется в том же направлении - «сделать regexp-машинку, которая...»

anonymous ()
// заматчить любую пару тегов <TD> + </TD> с любыми тегами между ними.
TD, * *, /TD

Я правильно понимаю, что для «<TD id=1></TD><TD id=2></TD>» этот парсер должен выдать

<TD id=1></TD>
<TD id=1></TD><TD id=2></TD>
<TD id=2></TD>
?

monk ★★★★★ ()

Не будет ли такое быстрее, чем построение в памяти всего DOM-дерева и исполнение на этом дереве XPath-запросов?

Если п.1 читает в память, то объём памяти будет сравним с построением DOM. А вот задачу типа «получить строки таблицы, в которых ровно 16 ячеек» на этом regexp-парсере не решить.

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

markup language.
extended vs hypertext.
всё валидации по ца согласно описанию DTD.
по html первое всплывает что strict, xhtml.
попробуй валидный html по strict скормить xml валидатору с strict.dtd. есть ненулевая вероятность что и он признает его валидным.

etwrq ★★★★ ()

Именно поэтому на смену лютому здецу под названием HTML пришел XHTML, как компромисс между страшным для машины HTML и страшным для человека XML.
Смысл гипертекстовой разметки как раз и заключается в иерархии.

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

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

Владимир

ТС 18.04.19 зарегистрировался /троль не троль время покажет/.
Что касается парсинга страниц, то использую DOM /альтернатива DOM мне не известна/.

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

Неправильно. Для указанного он выдаст

TD id=1, /TD, TD id=2, /TD

Всё тупо линейно. Откуда у вас взялись в «выдаче» закрывающие теги - загадка. Парсер не думает ни про какой DOM, а воспринимает входящий HTML как тупую последовательность любых тегов. Про то, что теги могут быть закрытые или нет он вообще не в курсе. Он рад любому тегу в любой момент последовательности. Закрывающий тег - просто другое имя тега для него. Есть тег TD и есть тег /TD, которые никак не связаны никакой логикой с точки зрения разбора.

igloev ()