Использование регулярных выражений для разбора HTML: почему бы и нет?

208

Кажется, что у каждого вопроса в stackoverflow, когда спрашивающий использует регулярное выражение для получения некоторой информации из HTML, неизбежно будет «ответ», который говорит, что не следует использовать регулярное выражение для анализа HTML.

Почему нет? Я знаю, что существуют «настоящие» парсеры HTML без кавычек, такие как Beautiful Soup , и я уверен, что они мощные и полезные, но если вы просто делаете что-то простое, быстрое или грязное, то почему использовать что-то настолько сложное, когда несколько операторов регулярных выражений будут работать нормально?

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

ntownsend
источник
3
я думаю, что это
дурак
23
Потому что только Чак Норрис может анализировать HTML с помощью регулярных выражений (как объяснено в этой известной статье Zalgo: stackoverflow.com/questions/1732348/… ).
принимает
1
Этот вопрос побудил меня задать еще один вопрос, который как-то связан. Если вам интересно: почему невозможно использовать регулярные выражения для разбора HTML / XML: формальное объяснение в терминах непрофессионала
mac
Остерегайтесь Зальго
Келли С. Френч
Этот вопрос был добавлен в FAQ по регулярному выражению переполнения стека в разделе «Общие задачи проверки».
aliteralmind

Ответы:

212

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

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

Йоханнес Вайс
источник
26
Лучший ответ на данный момент. Если бы он мог соответствовать только обычным грамматикам, то нам понадобилось бы бесконечно большое регулярное выражение для анализа не зависящей от контекста грамматики, такой как HTML. Я люблю, когда эти вещи имеют четкие теоретические ответы.
ntownsend
2
Я предположил, что мы обсуждали регулярные выражения типа Perl, где они на самом деле не являются регулярными выражениями.
Хэнк Гей
5
На самом деле, регулярные выражения .Net могут совпадать с открытием с закрывающими тегами, в некоторой степени, с использованием балансировочных групп и тщательно созданного выражения. Содержать все это в регулярном выражении все еще безумно, конечно, это выглядело бы как отличный код Chtulhu и, вероятно, также вызвало бы реальный код. И, в конце концов, все равно это не сработает. Говорят, что если вы напишите регулярное выражение, которое сможет правильно проанализировать любой HTML, юниверс рухнет на себя.
Алекс Павен
5
Некоторые библиотеки регулярных выражений могут делать рекурсивные регулярные выражения (фактически делая их нерегулярными выражениями :)
Ондра Жижка
43
-1 Этот ответ делает правильный вывод («Это плохая идея для анализа HTML с помощью Regex») из неправильных аргументов («потому что HTML не является обычным языком»). То, что большинство людей в настоящее время имеют в виду, когда говорят «регулярное выражение» (PCRE), вполне способно не только анализировать контекстно-свободные грамматики (на самом деле это тривиально), но и контекстно-зависимые грамматики (см. Stackoverflow.com/questions/7434272/ … )
NikiC
35

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

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

kmkaplan
источник
1
Некоторые библиотеки регулярных выражений могут делать рекурсивные регулярные выражения (фактически делая их нерегулярными выражениями :)
Ондра Жижка
23

http://htmlparsing.com/regexes )

Допустим, у вас есть файл HTML, в котором вы пытаетесь извлечь URL из тегов <img>.

<img src="http://example.com/whatever.jpg">

Итак, вы пишете регулярное выражение в Perl:

if ( $html =~ /<img src="(.+)"/ ) {
    $url = $1;
}

В этом случае $urlдействительно будет содержать http://example.com/whatever.jpg. Но что происходит, когда вы начинаете получать HTML, как это:

<img src='http://example.com/whatever.jpg'>

или

<img src=http://example.com/whatever.jpg>

или

<img border=0 src="http://example.com/whatever.jpg">

или

<img
    src="http://example.com/whatever.jpg">

или вы начинаете получать ложные срабатывания от

<!-- // commented out
<img src="http://example.com/outdated.png">
-->

Это выглядит так просто, и это может быть просто для одного неизменного файла, но для всего, что вы собираетесь делать с произвольными данными HTML, регулярные выражения - всего лишь рецепт будущей душевной боли.

Энди Лестер
источник
4
Это выглядит как реальный ответ - хотя, возможно, можно анализировать произвольный HTML с регулярным выражением, поскольку современные регулярные выражения - это больше, чем просто конечный автомат, для анализа произвольного HTML, а не просто конкретной страницы, вам нужно переопределить анализатор HTML в регулярном выражении. и регулярные выражения, безусловно, становятся нечитаемыми в 1000 раз.
Смит Джонт
1
Эй, Энди, я нашел время, чтобы придумать выражение, которое поддерживает твои упомянутые случаи. stackoverflow.com/a/40095824/1204332 Дайте мне знать, что вы думаете! :)
Иван Чаер
2
Аргументация в этом ответе является способом устаревшей и применяется даже меньше сегодня , чем это было первоначально (который я думаю , что это не так). (Цитируя ОП: «если вы просто делаете что-то простое, быстрое или грязное ...».)
Sz.
16

Две быстрые причины:

  • трудно написать регулярное выражение, способное противостоять злонамеренному вводу; гораздо сложнее, чем с помощью готового инструмента
  • Трудно написать регулярное выражение, которое может работать с нелепой разметкой, с которой вы неизбежно столкнетесь; гораздо сложнее, чем с помощью готового инструмента

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

Хэнк Гей
источник
2
Вот это да? Падение после 2+ лет? На случай, если кому-то интересно, я не сказал «потому что это теоретически невозможно», потому что вопрос четко задан «быстро и грязно», а не «правильно». ОП ясно уже прочитал ответы, которые охватывали теоретически невозможную территорию и все еще не были удовлетворены.
Хэнк Гей
1
Иметь голос после 5+ лет. :) Что касается того, почему вы могли получить отрицательное голосование, я не имею права говорить, но лично мне хотелось бы увидеть некоторые примеры или объяснение, а не заключительный риторический вопрос.
Адам Дженсен
3
По сути, все быстрые и грязные html-разборы, которые выполняются в отгрузочных продуктах или внутренних инструментах, заканчиваются зияющей дырой в безопасности или ошибкой, ожидающей своего появления. Это должно быть обескуражено с удовольствием. Если вы можете использовать регулярные выражения, вы можете использовать правильный HTML-парсер.
Восстановить Монику
16

Что касается синтаксического анализа, регулярные выражения могут быть полезны на этапе «лексического анализа» (lexer), когда входные данные разбиваются на токены. Это менее полезно на стадии «построения дерева разбора».

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

Vatine
источник
8

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

Тамас Чинеге
источник
1
Совершенно верно, большинство HTML там ужасно. Я не понимаю, как неправильное регулярное выражение может создать серьезные пробелы в безопасности. Можете привести пример?
ntownsend
4
ntownsend: Например, вы думаете, что вы удалили все теги сценариев из HTML, но ваш regex терпит неудачу в особом случае (который, скажем, работает только в IE6): бум, у вас есть уязвимость XSS!
Тамас Чинеге
1
Это был строго гипотетический пример, так как большинство примеров из реального мира слишком сложны, чтобы вписаться в эти комментарии, но вы можете найти некоторые из них, быстро взглянув на предмет.
Тамас Чинеге
3
+1 за упоминание угла безопасности. Когда вы взаимодействуете со всем Интернетом, вы не можете позволить себе писать хакерский код «работает большую часть времени».
j_random_hacker
7

Проблема в том, что большинство пользователей, которые задают вопрос, связанный с HTML и регулярным выражением, делают это, потому что они не могут найти собственное регулярное выражение, которое работает. Тогда нужно подумать, будет ли все проще при использовании парсера DOM или SAX или чего-то подобного. Они оптимизированы и сконструированы для работы с XML-подобными структурами документов.

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

Если вы просто хотите найти все URL, которые выглядят так, как будто http://.../вы в порядке с регулярными выражениями. Но если вы хотите найти все URL-адреса в a-элементе, который имеет класс «mylink», вам, вероятно, лучше использовать соответствующий синтаксический анализатор.

okoman
источник
6

Регулярные выражения не предназначены для обработки структуры вложенных тегов, и в лучшем случае сложно (в худшем случае невозможно) обрабатывать все возможные крайние случаи, которые вы получаете с реальным HTML.

Питер Боутон
источник
6

Я считаю, что ответ лежит в теории вычислений. Для анализа языка с помощью регулярных выражений он должен быть по определению «обычный» ( ссылка ). HTML не является обычным языком, так как он не соответствует ряду критериев для обычного языка (во многом благодаря множеству уровней вложенности, присущих HTML-коду). Если вас интересует теория вычислений, я бы порекомендовал эту книгу.

тонкие листы железа
источник
1
Я действительно прочитал эту книгу. Мне просто не пришло в голову, что HTML - это язык без контекста.
ntownsend
4

Это выражение извлекает атрибуты из элементов HTML. Поддерживает:

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

(?:\<\!\-\-(?:(?!\-\-\>)\r\n?|\n|.)*?-\-\>)|(?:<(\S+)\s+(?=.*>)|(?<=[=\s])\G)(?:((?:(?!\s|=).)*)\s*?=\s*?[\"']?((?:(?<=\")(?:(?<=\\)\"|[^\"])*|(?<=')(?:(?<=\\)'|[^'])*)|(?:(?!\"|')(?:(?!\/>|>|\s).)+))[\"']?\s*)

Проверьте это . Лучше работает с флагами "gisx", как в демо.

Иван Чаер
источник
1
Это очень интересно. Не читается, вероятно, трудно отлаживать, но все же: впечатляющая работа!
Эрик Думинил
Это все еще смутно предполагает, что HTML-код правильно сформирован. Без сопоставления контекста это будет сопоставлять видимые URL-адреса в тех контекстах, где вы обычно не хотите их сопоставлять, как в фрагменте кода JavaScript внутри <script>тега.
трипл
4

HTML / XML делится на разметку и контент. Regex полезен только для анализа лексических тегов. Я думаю, вы могли бы вывести содержание. Это был бы хороший выбор для парсера SAX. Теги и контент могут быть доставлены в пользовательскую функцию, где можно отслеживать вложение / закрытие элементов.

Что касается простого анализа тегов, это можно сделать с помощью регулярного выражения и использовать для удаления тегов из документа.

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

Нормальные элементы анализируются с помощью этой формы:

Ядро этих тегов использует это регулярное выражение

 (?:
      " [\S\s]*? " 
   |  ' [\S\s]*? ' 
   |  [^>]? 
 )+

Вы заметите это [^>]?как одно из чередований. Это будет соответствовать несбалансированным цитатам из плохо сформированных тегов.

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

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

Это общая форма для простых старых тегов. Обратите внимание на [\w:]представление имени тега? На самом деле, допустимые символы, представляющие имя тега, представляют собой невероятный список символов Юникода.

 <     
 (?:
      [\w:]+ 
      \s+ 
      (?:
           " [\S\s]*? " 
        |  ' [\S\s]*? ' 
        |  [^>]? 
      )+
      \s* /?
 )
 >

Продвигаясь дальше, мы также видим, что вы просто не можете искать определенный тег без разбора ВСЕХ тегов. Я имею в виду, что вы могли бы, но он должен был бы использовать комбинацию глаголов, таких как (* SKIP) (* FAIL), но все же все теги должны быть проанализированы.

Причина в том, что синтаксис тегов может быть скрыт внутри других тегов и т. Д.

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

Когда новый HTML или XML или любой другой разработают новые конструкции, просто добавьте его в качестве одного из вариантов.


Примечание к веб-странице - я никогда не видел веб-страницу (или xhtml / xml), с которой
возникли проблемы. Если найдешь, дай мне знать.

Примечание по производительности - это быстро. Это самый быстрый анализатор тегов, который я когда-либо видел
(может быть, быстрее, кто знает).
У меня есть несколько конкретных версий. Это также отлично, как скребок
(если вы практический тип).


Полное необработанное регулярное выражение

<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>

Отформатированный вид

 <
 (?:
      (?:
           (?:
                # Invisible content; end tag req'd
                (                             # (1 start)
                     script
                  |  style
                  |  object
                  |  embed
                  |  applet
                  |  noframes
                  |  noscript
                  |  noembed 
                )                             # (1 end)
                (?:
                     \s+ 
                     (?>
                          " [\S\s]*? "
                       |  ' [\S\s]*? '
                       |  (?:
                               (?! /> )
                               [^>] 
                          )?
                     )+
                )?
                \s* >
           )

           [\S\s]*? </ \1 \s* 
           (?= > )
      )

   |  (?: /? [\w:]+ \s* /? )
   |  (?:
           [\w:]+ 
           \s+ 
           (?:
                " [\S\s]*? " 
             |  ' [\S\s]*? ' 
             |  [^>]? 
           )+
           \s* /?
      )
   |  \? [\S\s]*? \?
   |  (?:
           !
           (?:
                (?: DOCTYPE [\S\s]*? )
             |  (?: \[CDATA\[ [\S\s]*? \]\] )
             |  (?: -- [\S\s]*? -- )
             |  (?: ATTLIST [\S\s]*? )
             |  (?: ENTITY [\S\s]*? )
             |  (?: ELEMENT [\S\s]*? )
           )
      )
 )
 >
tripleee
источник
3

"Это зависит", хотя. Это правда, что регулярные выражения не делают и не могут анализировать HTML с истинной точностью по всем причинам, приведенным здесь. Однако, если последствия неправильного понимания (например, не обработка вложенных тегов) незначительны, и если регулярные выражения очень удобны в вашей среде (например, когда вы взламываете Perl), продолжайте.

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

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

Я думаю, я говорю, что это компромисс. Иногда реализация или использование правильного синтаксического анализатора - настолько легкого, насколько это возможно - может не стоить проблем, если точность не критична.

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

кошачья еда
источник
3

Определенно есть случаи, когда использование регулярного выражения для синтаксического анализа некоторой информации из HTML - правильный путь - это во многом зависит от конкретной ситуации.

Консенсус выше, что в целом это плохая идея. Тем не менее, если структура HTML известна (и вряд ли изменится), то это все еще допустимый подход.

Джейсон
источник
3

Имейте в виду, что, хотя сам HTML не является регулярным, части просматриваемой страницы могут быть регулярными.

Например, это ошибка для <form>вложенных тегов; если веб-страница работает правильно, то использование регулярного выражения для захвата <form>будет вполне разумным.

Недавно я сделал несколько операций с использованием только Selenium и регулярных выражений. Я ушел с ним , потому что данные , которые я хотел было положить в <form>, и поставить в простом формате таблицы (так что я мог рассчитывать даже на <table>, <tr>и <td>быть невложенных - что на самом деле очень необычно). В некоторой степени регулярные выражения были даже почти необходимы, потому что некоторые структуры, к которым мне нужно было получить доступ, были ограничены комментариями. (Beautiful Soup может дать вам комментарии, но было бы трудно захватить <!-- BEGIN -->и <!-- END -->заблокировать, используя Beautiful Soup.)

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

Алфей
источник
2

На самом деле, разбор HTML с помощью регулярных выражений вполне возможен в PHP. Вам просто нужно проанализировать всю строку в обратном направлении, используя, strrposчтобы найти <и повторить оттуда регулярное выражение, используя несвязные спецификаторы каждый раз, чтобы преодолеть вложенные теги. Не причудливый и ужасно медленный на больших вещах, но я использовал его для своего личного редактора шаблонов для моего сайта. Я на самом деле не разбирал HTML, но сделал несколько пользовательских тегов для запроса записей в базе данных для отображения таблиц данных (мой <#if()>тег может выделять специальные записи таким образом). Я не был готов пойти на парсер XML только на пару самостоятельно созданных тегов (с очень не XML-данными внутри них) здесь и там.

Таким образом, хотя этот вопрос значительно мертв, он все равно обнаруживается в поиске Google. Я прочитал его и подумал, что «вызов принят», и закончил исправление моего простого кода, не заменяя все. Решил предложить другое мнение любому, кто ищет подобную причину. Также последний ответ был опубликован 4 часа назад, так что это все еще горячая тема.

Deji
источник
2
-1 за предложение УЖАСНОЙ идеи. Рассматривали ли вы пробел между тегом и закрывающей угловой скобкой? (Например, <tag >) Рассматривали ли вы закомментированные закрывающие теги? (Например, <tag> <!-- </tag> -->) Вы рассматривали CDATA? Вы рассматривали теги с непоследовательным регистром? (Например, <Tag> </tAG>) Вы это тоже учли?
rmunn
1
В конкретном случае ваших нескольких пользовательских тегов, да, регулярные выражения работают хорошо. Так что это не значит, что их использование было ошибкой в вашем конкретном случае . Однако это не HTML, а сказать, что «разбор HTML с помощью регулярных выражений вполне возможен в PHP» - это просто ложное утверждение, и это ужасная идея. Несоответствия реального HTML (а их гораздо больше, чем я перечислил) - вот почему вы никогда не должны анализировать настоящий HTML с помощью регулярных выражений. Смотрите, ну, все остальные ответы на этот вопрос, а также тот, на который я ссылался в моем другом комментарии выше.
rmunn
2
PHP - это полный тьюринговый язык, так что он совсем не ложный. Все возможное в вычислительном отношении возможно, в том числе парсинг HTML. Пробелы в тегах НИКОГДА не были проблемой, и с тех пор я адаптировал их для перечисления элементов тегов по порядку. Я использую автоматически исправленные теги с непоследовательным регистром, зачеркнутые комментарии на самом первом этапе и после некоторых последующих добавлений можно легко добавлять все виды тегов (хотя это чувствительно к регистру, по моему собственному выбору). И я уверен, что CDATA на самом деле является элементом XML, а не HTML.
Дежи
2
Мой старый метод (который я описал здесь) был довольно неэффективным, и я недавно начал переписывать многие редакторы контента. Когда дело доходит до этих вещей, возможность не проблема; лучший способ всегда является главной заботой. Реальный ответ - «нет простого способа сделать это в PHP». НИ ОДИН не говорит, что нет никакого способа сделать это на PHP или что это ужасная идея, но это невозможно с помощью регулярных выражений, чего я, честно говоря, никогда не пробовал, но один главный недостаток в моем ответе - я предположил, что вопрос имел в виду регулярное выражение в контексте PHP, что не обязательно так.
Дежи
2

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

Используйте с опциями 'sx'. «g» тоже, если вам повезет:

(?P<content>.*?)                # Content up to next tag
(?P<markup>                     # Entire tag
  <!\[CDATA\[(?P<cdata>.+?)]]>| # <![CDATA[ ... ]]>
  <!--(?P<comment>.+?)-->|      # <!-- Comment -->
  </\s*(?P<close_tag>\w+)\s*>|  # </tag>
  <(?P<tag>\w+)                 # <tag ...
    (?P<attributes>
      (?P<attribute>\s+
# <snip>: Use this part to get the attributes out of 'attributes' group.
        (?P<attribute_name>\w+)
        (?:\s*=\s*
          (?P<attribute_value>
            [\w:/.\-]+|         # Unquoted
            (?=(?P<_v>          # Quoted
              (?P<_q>['\"]).*?(?<!\\)(?P=_q)))
            (?P=_v)
          ))?
# </snip>
      )*
    )\s*
  (?P<is_self_closing>/?)   # Self-closing indicator
  >)                        # End of tag

Этот предназначен для Python (он может работать для других языков, еще не пробовал, он использует положительные взгляды, отрицательные взгляды и именованные обратные ссылки). Поддержка:

  • Открыть тег - <div ...>
  • Закрыть тег - </div>
  • Комментарий - <!-- ... -->
  • CDATA - <![CDATA[ ... ]]>
  • Самозакрывающийся тег - <div .../>
  • Значения необязательных атрибутов - <input checked>
  • Значения атрибутов без кавычек / кавычек - <div style='...'>
  • Одиночные / двойные кавычки - <div style="...">
  • Избегайте цитат <a title='John\'s Story'>
    (это не совсем правильный HTML, но я хороший парень)
  • Пробелы вокруг знаков равенства - <a href = '...'>
  • Названные Захваты Для Интересных Бит

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

Если ваш вкус регулярных выражений поддерживает повторные именованные захваты, то вы великолепны, но Python reнет (я знаю, регулярные выражения поддерживают, но мне нужно использовать ванильный Python). Вот что вы получаете:

  • content- Весь контент до следующего тега. Вы можете оставить это
  • markup - Весь тег со всем в нем.
  • comment - Если это комментарий, содержание комментария.
  • cdata- Если это <![CDATA[...]]>, содержимое CDATA.
  • close_tag- Если это закрывающий тег ( </div>), имя тега.
  • tag- Если это открытый тег ( <div>), имя тега.
  • attributes- Все атрибуты внутри тега. Используйте это, чтобы получить все атрибуты, если у вас нет повторяющихся групп.
  • attribute - Повторяется каждый атрибут.
  • attribute_name - Повторяется, каждый атрибут имени.
  • attribute_value- Повторяется каждое значение атрибута. Это включает в себя кавычки, если это было указано.
  • is_self_closing- Это /если это самозакрывающийся тег, иначе ничего.
  • _qи _v- игнорировать это; они используются внутри для обратных ссылок.

Если ваш движок регулярных выражений не поддерживает повторные именованные захваты, есть раздел, который вы можете использовать для получения каждого атрибута. Просто запустите , что регулярное выражение на attributesгруппы , чтобы получить каждый attribute, attribute_nameи attribute_valueиз него.

Демо здесь: https://regex101.com/r/mH8jSu/11

Hounshell
источник
1

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

гумбо
источник
0

Вы, знаете ... у вас много менталитета, вы НЕ МОЖЕТЕ это сделать, и я думаю, что все по обе стороны забора правы и неправы. Вы МОЖЕТЕ сделать это, но это требует немного больше обработки, чем просто выполнение одного регулярного выражения против него. Возьмите это (я написал это в течение часа) в качестве примера. Предполагается, что HTML-код полностью допустим, но в зависимости от того, какой язык вы используете для применения вышеупомянутого регулярного выражения, вы можете внести некоторые исправления в HTML-код, чтобы убедиться в его успешности. Например, удаление закрывающих тегов, которых там не должно быть: </img>например. Затем добавьте закрывающий одиночный слеш HTML к элементам, в которых они отсутствуют, и т. Д.

Я бы использовал это в контексте написания библиотеки, которая позволила бы мне выполнять поиск элементов HTML [x].getElementsByTagName(), например, JavaScript . Я бы просто разделил функциональность, которую я написал в разделе DEFINE регулярного выражения, и использовал бы ее для перехода внутрь дерева элементов, по одному за раз.

Итак, это будет окончательный 100% ответ для проверки HTML? Нет. Но это начало, и немного больше работы можно сделать. Однако попытка сделать это внутри одного выполнения регулярного выражения не практична и не эффективна.

Erutan409
источник