Написание HTML-парсера - PullRequest
       49

Написание HTML-парсера

26 голосов
/ 25 августа 2011

В настоящее время я пытаюсь (или планирую попытаться) написать простую (насколько это возможно) программу для анализа html-документа в дереве.

После поиска в Google я нашел много ответов: «не делай этого, все сделано» (или слова на этот счет); и ссылки на примеры HTML-парсеров; а также довольно убедительная статья о том, почему не следует использовать регулярные выражения. Однако я не нашел руководств по «правильному» способу написания парсера. (Кстати, это то, что я пытаюсь сделать в качестве учебного упражнения, а не чего-либо другого, поэтому я бы предпочел сделать это, а не использовать готовый)

Полагаю, что я мог бы создать работающий анализатор XML, просто прочитав документ и добавив теги / текст и т. Д. В дерево, увеличивая уровень всякий раз, когда я нажимаю на закрывающий тег (опять же, простой, не требующий особой многопоточности или эффективности) на данном этапе.). Однако для HTML не все теги закрыты.

Итак, мой вопрос таков: что бы вы посоветовали в качестве способа борьбы с этим? Единственная идея, которая у меня возникла, - это обращаться с ней аналогично XML, но иметь список тегов, каждый из которых не обязательно закрыт, с условиями для закрытия (например,

заканчивается на

или далее

тег).

Кто-нибудь еще (надеюсь, лучше) предложения? Есть ли лучший способ сделать это вообще?

Ответы [ 5 ]

12 голосов
/ 25 августа 2011

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

Вы сохраните стек (возможно, неявно с деревом) текущего контекста.Например, {<html>, <body>} означает, что вы в настоящее время находитесь в теле HTML-документа.Когда вы сталкиваетесь с новым узлом, вы сравниваете требования для этого узла с тем, что в данный момент находится в стеке.

Предположим, ваш стек в настоящее время просто {html}.Вы столкнулись с тегом <p>.Вы ищите <p> в таблице, в которой говорится, что абзац должен быть внутри <body>.Поскольку вы не в теле, вы неявно помещаете <body> в свой стек (или добавляете узел тела в свое дерево).Затем вы можете поместить <p> в дерево.

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

В конце документа вы вытаскиваете каждый оставшийся элемент из стека, как будто вы видели закрывающий тег для каждого.

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

8 голосов
/ 25 августа 2011

Итак, я постараюсь ответить здесь -

В основном, что делает «простой» синтаксический анализ html (не говоря уже о действительном xhtml здесь) отличным от синтаксического анализа xml, это множество правил, таких как бесконечный <img> тэгов, или, строго говоря, тот факт, что даже самые небрежные из всех html-разметок будут несколько отрисовываться в браузере.Вам понадобится валидатор вместе с парсером, чтобы построить ваше дерево.Но вам нужно будет выбрать стандарт для HTML, который вы хотите поддерживать, так что, когда вы обнаружите слабость в разметке, вы будете знать, что это ошибка, а не просто неаккуратный html.

знать всеправила, создайте валидатор, и тогда вы сможете создать парсер.это план А.

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

надеюсь, что помогло!

7 голосов
/ 31 октября 2013

Поскольку теперь существует стандарт html5, написание html-парсера больше не является методом проб и ошибок или тайным знанием.

Вместо этого вам просто нужно реализовать стандартизированный алгоритм синтаксического анализа .

4 голосов
/ 25 августа 2011

Суровый. Перейти

HTML не является XML. XHTML - это XML. Большинство сайтов на HTML; некоторые из них XHTML. В XHTML все теги должны быть закрыты (или не иметь тела, которое все еще закрыто).

Если вы хотите написать HTML-парсер в качестве учебного эксперимента, тогда сделайте это. Если вы хотите написать следующий «Greaterest HTML parserer», тогда оставьте его. Apache (или кто-то еще) побеждает; важная информация: вы не знаете больше, чем большие группы, специализирующиеся на разборе HTML.

Чтобы ответить на вопрос "Как мне с этим бороться?" Прочитайте спецификацию W3C в HTML . Это отвечает на ваш вопрос. Если ваш ответ «но я тоже не хочу», то вы на самом деле говорите: «Я ленивая тупица, которая хочет притворяться, что учится». Если это так, я предлагаю вам удалить пост и двигаться дальше; У команды Microsoft IE вероятно есть несколько документов, которые могут вас заинтересовать.

Менее резкий ответ

HTML не легко разобрать. Как правило, вам не нужны элементы головы или тела, и многие теги не нужно закрывать. Основное правило при разборе HTML: , если вы встретите новый элемент блока, автоматически закройте предыдущий элемент блока . Для этого нельзя использовать стандартный синтаксический анализатор XML, поскольку HTML не является XML.

Подобно XML, вам нужно будет разбить ваш документ на элементы, в том числе на свободные текстовые элементы.

XHTML намного проще, потому что это должен быть правильно сформированный XML. Для этого вы можете использовать синтаксический анализатор XML.

0 голосов
/ 31 октября 2013

Вы пытались использовать эту библиотеку: http://simplehtmldom.sourceforge.net/?

F.

...