Usando expressões regulares para analisar HTML: por que não?

207

Parece que todas as perguntas no stackoverflow em que o solicitante está usando o regex para obter algumas informações do HTML terão inevitavelmente uma "resposta" que diz para não usar o regex para analisar o HTML.

Por que não? Estou ciente de que existem analisadores HTML "reais" entre aspas, como Beautiful Soup , e tenho certeza de que são poderosos e úteis, mas se você está apenas fazendo algo simples, rápido ou sujo, por que se preocupa em usar algo tão complicado quando algumas instruções regex funcionarão bem?

Além disso, existe algo fundamental que eu não entendo sobre o regex que os torna uma má escolha para analisar em geral?

Ntownsend
fonte
3
Acho que este é um joguete de stackoverflow.com/questions/133601
jcrossley3
23
Porque apenas Chuck Norris pode analisar HTML com regex (como explicado nesta famosa coisa do Zalgo: stackoverflow.com/questions/1732348/… ).
takeshin
1
Essa pergunta me levou a fazer outra que, de alguma forma, está relacionada. No caso de você estiver interessado: Por que não é possível usar regex para analisar HTML / XML: uma explicação formal em termos leigos
mac
Cuidado com Zalgo
Kelly S. French
Esta pergunta foi adicionada às Perguntas frequentes sobre a expressão regular de estouro de pilha , em "Tarefas comuns de validação".
precisa saber é o seguinte

Respostas:

212

A análise HTML inteira não é possível com expressões regulares, pois depende da correspondência entre a abertura e a tag de fechamento, o que não é possível com as expressões regulares.

Expressões regulares podem corresponder apenas a linguagens regulares, mas HTML é uma linguagem livre de contexto e não uma linguagem regular (como o @StefanPochmann apontou, as linguagens regulares também são livres de contexto, portanto, sem contexto não significa necessariamente não regular). A única coisa que você pode fazer com regexps em HTML é heurística, mas isso não funcionará em todas as condições. Deve ser possível apresentar um arquivo HTML que corresponderá incorretamente a qualquer expressão regular.

Johannes Weiss
fonte
26
Melhor resposta até agora. Se ele puder corresponder apenas a gramáticas regulares, precisaríamos de uma regexp infinitamente grande para analisar uma gramática sem contexto, como HTML. Adoro quando essas coisas têm respostas teóricas claras.
Ntownsend
2
Eu assumi que estávamos discutindo expressões regulares do tipo Perl onde elas não são realmente expressões regulares.
Hank Gay
5
Na verdade, as expressões regulares .Net podem combinar a abertura com as tags de fechamento, até certo ponto, usando grupos de balanceamento e uma expressão cuidadosamente criada. Contenir tudo isso em uma regexp ainda é uma loucura, é claro, seria semelhante ao grande código Chtulhu e provavelmente convocaria o código real também. E no final, ainda não funcionará para todos os casos. Eles dizem que se você escrever uma expressão regular que possa analisar corretamente qualquer HTML, o universo entrará em colapso.
Alex Paven 16/09/10
5
Alguns libs regex pode fazer expressões regulares recursiva (efetivamente tornando-as expressões não-regulares :)
Ondra Žižka
43
-1 Esta resposta tira a conclusão correta ("É uma má idéia analisar o HTML com o Regex") a partir de argumentos errados ("Como o HTML não é uma linguagem comum"). O que a maioria das pessoas hoje em dia quer dizer quando diz "regex" (PCRE) é bem capaz não apenas de analisar gramáticas sem contexto (isso é trivial, na verdade), mas também de gramáticas sensíveis ao contexto (consulte stackoverflow.com/questions/7434272/ ... )
NikiC 17/09/11
35

Para quickexnirty, o regexp se sairá bem. Mas o fundamental é saber que é impossível construir um regexp que analise corretamente o HTML.

O motivo é que os regexps não podem manipular expressões aninhadas arbitrariamente. Consulte Expressões regulares podem ser usadas para corresponder a padrões aninhados?

kmkaplan
fonte
1
Alguns libs regex pode fazer expressões regulares recursiva (efetivamente tornando-as expressões não-regulares :)
Ondra Žižka
23

(Em http://htmlparsing.com/regexes )

Digamos que você tenha um arquivo HTML onde está tentando extrair URLs das tags <img>.

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

Então você escreve um regex como este no Perl:

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

Nesse caso, $urlconterá de fato http://example.com/whatever.jpg. Mas o que acontece quando você começa a obter HTML assim:

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

ou

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

ou

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

ou

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

ou você começa a receber falsos positivos de

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

Parece tão simples e pode ser simples para um único arquivo imutável, mas para qualquer coisa que você esteja fazendo com dados HTML arbitrários, as expressões regulares são apenas uma receita para futuras mágoas.

Andy Lester
fonte
4
Essa parece ser a resposta real - embora provavelmente seja possível analisar HTML arbitrário com regex, já que os regexes de hoje são mais do que apenas um autômato finito, para analisar html arbitrário e não apenas uma página concreta, é necessário reimplementar um analisador de HTML no regexp e regexes certamente se tornam 1000 vezes ilegíveis.
precisa saber
1
Ei Andy, aproveitei o tempo para criar uma expressão que apóie os casos mencionados. stackoverflow.com/a/40095824/1204332 Deixe-me saber o que você pensa! :)
Ivan Chaer
2
O raciocínio nesta resposta é maneira ultrapassada, e aplica-se ainda menos hoje do que originalmente (o que eu acho que não). (Citando OP: "se você está apenas fazendo algo simples, rápido ou sujo ...".)
Sz.
16

Duas razões rápidas:

  • escrever um regex que resista a entradas maliciosas é difícil; muito mais difícil do que usar uma ferramenta pré-construída
  • é difícil escrever um regex que possa trabalhar com a marcação ridícula que você inevitavelmente ficará preso; muito mais difícil do que usar uma ferramenta pré-construída

Quanto à adequação de expressões regulares para análise em geral: elas não são adequadas. Você já viu os tipos de expressões regulares necessárias para analisar a maioria dos idiomas?

Hank Gay
fonte
2
Uau? Um voto negativo após mais de 2 anos? Caso alguém estivesse se perguntando, eu não disse "Porque é teoricamente impossível", porque a pergunta claramente feita sobre "rápido e sujo", não "correto". O OP claramente já leu respostas que cobriam o território teoricamente impossível e ainda não estavam satisfeitas.
Hank Gay
1
Tenha um voto positivo após mais de 5 anos. :) Quanto ao motivo pelo qual você recebeu o voto negativo, não estou qualificado para dizer, mas pessoalmente, eu gostaria de ver alguns exemplos ou explicações, em vez da pergunta retórica final.
Adam Jensen
3
Essencialmente, todas as análises html rápidas e sujas feitas nos produtos de remessa ou nas ferramentas internas acabam sendo uma brecha na segurança ou um bug esperando para acontecer. Deve ser desencorajado com gosto. Se alguém pode usar um regex, pode usar um analisador de html adequado.
Reinstale Monica
16

No que diz respeito à análise, expressões regulares podem ser úteis no estágio "análise lexical" (lexer), onde a entrada é dividida em tokens. É menos útil no estágio "construir uma árvore de análise" real.

Para um analisador de HTML, espero que ele aceite apenas HTML bem formado e que exija recursos fora do que uma expressão regular pode fazer (eles não podem "contar" e garantir que um determinado número de elementos de abertura seja equilibrado pelo mesmo número) de elementos de fechamento).

Vatine
fonte
8

Como existem muitas maneiras de "estragar" o HTML que os navegadores tratam de uma maneira bastante liberal, seria necessário bastante esforço para reproduzir o comportamento liberal do navegador para cobrir todos os casos com expressões regulares, portanto sua regex falhará inevitavelmente em alguns itens especiais. casos, e isso possivelmente introduziria sérias falhas de segurança em seu sistema.

Tamas Czinege
fonte
1
É verdade que a maioria do HTML parece ser horrível. Não entendo como uma expressão regular com falha pode introduzir sérias falhas de segurança. Você pode dar um exemplo?
Ntownsend
4
ntownsend: Por exemplo, você acha que retirou todas as tags de script do HTML, mas sua regex falha cobre um caso especial (que, digamos, funciona apenas no IE6): boom, você tem uma vulnerabilidade no XSS!
266 Tamas Czinege
1
Este foi um exemplo estritamente hipotético, já que a maioria dos exemplos do mundo real é muito complicada para caber nesses comentários, mas você pode encontrar alguns pesquisando rapidamente sobre o assunto.
266 Tamas Czinege
3
+1 por mencionar o ângulo de segurança. Quando você está interagindo com toda a Internet, não pode se dar ao luxo de escrever códigos "hackers" na maioria das vezes.
j_random_hacker
7

O problema é que a maioria dos usuários que fazem uma pergunta relacionada ao HTML e à regex o fazem porque não conseguem encontrar uma própria regex que funcione. Então é preciso pensar se tudo seria mais fácil ao usar um analisador DOM ou SAX ou algo semelhante. Eles são otimizados e construídos com o objetivo de trabalhar com estruturas de documentos semelhantes a XML.

Claro, existem problemas que podem ser resolvidos facilmente com expressões regulares. Mas a ênfase está na facilidade .

Se você quiser apenas encontrar todos os URLs que parecem http://.../bons com os regexps. Mas se você deseja encontrar todos os URLs que estão em um elemento a que tem a classe 'mylink', provavelmente é melhor usar um analisador apropriado.

okoman
fonte
6

As expressões regulares não foram projetadas para lidar com uma estrutura de marca aninhada e, na melhor das hipóteses, é complicado (na pior das hipóteses, impossível) lidar com todos os casos de borda possíveis que você obtém com HTML real.

Peter Boughton
fonte
6

Eu acredito que a resposta está na teoria da computação. Para que um idioma seja analisado usando regex, ele deve ser por definição "regular" ( link ). O HTML não é uma linguagem comum, pois não atende a vários critérios para uma linguagem regular (muito a ver com os vários níveis de aninhamento inerentes ao código html). Se você estiver interessado na teoria da computação, eu recomendaria este livro.

taggers
fonte
1
Na verdade, eu li esse livro. Apenas não me ocorreu que o HTML é uma linguagem livre de contexto.
Ntownsend
4

Essa expressão recupera atributos de elementos HTML. Suporta:

  • atributos não citados / citados,
  • aspas simples / duplas,
  • aspas escapadas dentro de atributos,
  • espaços em torno de sinais de igual,
  • qualquer número de atributos,
  • verifique apenas os atributos dentro das tags,
  • escapar comentários e
  • gerenciar cotações diferentes em um valor de atributo.

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

Confira . Funciona melhor com os sinalizadores "gisx", como na demonstração.

Ivan Chaer
fonte
1
Isso é muito interessante. Não legível, provavelmente difícil de depurar, mas ainda assim: trabalho impressionante!
precisa
Isso ainda pressupõe vagamente que o HTML esteja bem formado. Sem correspondência de contexto, isso corresponderá a URLs aparentes em contextos em que você normalmente não deseja correspondê-los, como em um pedaço de código JavaScript dentro de uma <script>tag.
Tripleee
4

HTML / XML é dividido em marcação e conteúdo. Regex é útil apenas na análise de tags lexicais. Eu acho que você poderia deduzir o conteúdo. Seria uma boa escolha para um analisador SAX. Tags e conteúdo podem ser entregues a uma função definida pelo usuário, onde o aninhamento / fechamento de elementos pode ser mantido.

Na medida em que apenas analisa as tags, isso pode ser feito com regex e usado para retirar as tags de um documento.

Ao longo de anos de testes, descobri o segredo da maneira como os navegadores analisam as tags, bem e mal formadas.

Os elementos normais são analisados ​​com este formulário:

O núcleo dessas tags usa esse regex

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

Você notará isso [^>]?como uma das alternâncias. Isso corresponderá a aspas desequilibradas de tags mal formadas.

É também a mais raiz de todos os males às expressões regulares. A maneira como é usada aciona um bump-along para satisfazer seu recipiente quantificado ganancioso e que deve corresponder.

Se usado passivamente, nunca há um problema Mas, se você forçar a correspondência de algo, intercalando-o com um par de atributo / valor desejado e não fornecer proteção adequada contra retorno, é um pesadelo fora de controle.

Essa é a forma geral para tags antigas simples. Observe a [\w:]representação do nome da tag? Na realidade, os caracteres legais que representam o nome da marca são uma lista incrível de caracteres Unicode.

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

Continuando, também vemos que você não pode procurar uma tag específica sem analisar TODAS as tags. Quero dizer que você poderia, mas teria que usar uma combinação de verbos como (* SKIP) (* FAIL), mas ainda assim todas as tags precisam ser analisadas.

O motivo é que a sintaxe das tags pode estar oculta dentro de outras tags, etc.

Portanto, para analisar passivamente todas as tags, é necessário um regex como o abaixo. Este em particular também combina com conteúdo invisível .

À medida que o novo HTML ou xml ou qualquer outro desenvolver novas construções, adicione-o como uma das alternativas.


Nota da página da Web - nunca vi uma página da Web (ou xhtml / xml) com a qual
havia problemas. Se você encontrar um, me avise.

Nota de desempenho - É rápido. Este é o analisador de tags mais rápido que eu já vi
(pode ser mais rápido, quem sabe).
Eu tenho várias versões específicas. Também é excelente como raspador
(se você é do tipo hands-on).


Regex bruto completo

<(?:(?:(?:(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]*?))))>

Aparência formatada

 <
 (?:
      (?:
           (?:
                # 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]*? )
           )
      )
 )
 >
triplo
fonte
3

"Depende" embora. É verdade que as expressões regulares não podem e não podem analisar HTML com precisão verdadeira, por todos os motivos apresentados aqui. Se, no entanto, as conseqüências de errar (como não manipular tags aninhadas) são menores e se as expressões regulares são super convenientes no seu ambiente (como quando você está invadindo o Perl), vá em frente.

Suponha que você esteja, oh, talvez analisando páginas da web com links para o seu site - talvez você as tenha encontrado com uma pesquisa no link do Google - e deseje uma maneira rápida de ter uma idéia geral do contexto ao redor do seu link. Você está tentando gerar um pequeno relatório que pode alertá-lo para vincular spam, algo assim.

Nesse caso, interpretar incorretamente alguns dos documentos não será um grande problema. Ninguém, exceto você, verá os erros e, se tiver muita sorte, haverá poucos o suficiente para que você possa acompanhar individualmente.

Acho que estou dizendo que é uma troca. Às vezes, implementar ou usar um analisador correto - por mais fácil que seja - pode não valer a pena se a precisão não for crítica.

Apenas tenha cuidado com suas suposições. Posso pensar em algumas maneiras pelas quais o atalho regexp pode sair pela culatra se você estiver tentando analisar algo que será mostrado em público, por exemplo.

comida de gato
fonte
3

Definitivamente, existem casos em que o uso de uma expressão regular para analisar algumas informações do HTML é o caminho correto a seguir - depende muito da situação específica.

O consenso acima é que, em geral, é uma má ideia. No entanto, se a estrutura HTML for conhecida (e provavelmente não será alterada), ainda será uma abordagem válida.

Jason
fonte
3

Lembre-se de que, embora o próprio HTML não seja regular, partes da página que você está visualizando podem ser regulares.

Por exemplo, é um erro que as <form>tags sejam aninhadas; se a página da web estiver funcionando corretamente, o uso de uma expressão regular para obter um <form>seria completamente razoável.

Recentemente, fiz algumas raspagens na Web usando apenas Selenium e expressões regulares. I conseguiu acabar com ela porque os dados que eu queria era colocar em um <form>, e colocar em um formato de tabela simples (de modo que eu pudesse contar com <table>, <tr>e <td>para ser não-aninhados - que na verdade é altamente incomum). Em certo grau, expressões regulares eram quase necessárias, porque parte da estrutura que eu precisava acessar era delimitada por comentários. (A Beautiful Soup pode fazer comentários, mas teria sido difícil agarrar <!-- BEGIN -->e <!-- END -->bloquear usando a Beautiful Soup.)

Se eu tivesse que me preocupar com tabelas aninhadas, no entanto, minha abordagem simplesmente não teria funcionado! Eu teria que recorrer à Beautiful Soup. Mesmo assim, às vezes, você pode usar uma expressão regular para agarrar o pedaço necessário e, em seguida, detalhar a partir daí.

alpheus
fonte
2

Na verdade, a análise de HTML com regex é perfeitamente possível no PHP. Você só precisa analisar a cadeia inteira de trás strrpospara frente para localizar <e repetir a regex de lá, usando especificadores não agradáveis ​​a cada vez para superar as tags aninhadas. Não é chique e muito lento em coisas grandes, mas eu o usei para o meu próprio editor de modelos pessoal para o meu site. Na verdade, eu não estava analisando HTML, mas algumas tags personalizadas que fiz para consultar entradas do banco de dados para exibir tabelas de dados (minha <#if()>tag poderia destacar entradas especiais dessa maneira). Eu não estava preparado para usar um analisador XML em apenas algumas tags criadas automaticamente (com dados muito não XML) aqui e ali.

Portanto, mesmo que essa pergunta esteja consideravelmente morta, ela ainda aparece em uma pesquisa no Google. Eu li e pensei "desafio aceito" e terminei de corrigir meu código simples sem precisar substituir tudo. Decidiu oferecer uma opinião diferente para quem procura por um motivo semelhante. Além disso, a última resposta foi postada há 4 horas, por isso esse ainda é um tópico importante.

Deji
fonte
2
-1 por sugerir uma idéia TERRÍVEL. Você considerou o espaço em branco entre a etiqueta e o colchete angular de fechamento? (Por exemplo, <tag >) Você considerou tags de fechamento comentadas? (Por exemplo, <tag> <!-- </tag> -->) Você considerou o CDATA? Você considerou tags de casos inconsistentes? (Por exemplo, <Tag> </tAG>) Você considerou isso também?
rmunn
1
No caso específico de suas poucas tags personalizadas, sim, expressões regulares funcionam bem. Portanto, não é que seu uso deles tenha sido um erro no seu caso particular . Porém, isso não é HTML, e dizer "a análise de HTML com regex é perfeitamente possível no PHP" é simplesmente falso, e uma idéia TERRÍVEL. As inconsistências do HTML real (e existem muito mais do que as poucas que listei) são por que você nunca deve analisar o HTML real com expressões regulares. Veja, bem, todas as outras respostas a esta pergunta, bem como a que eu vinculei no meu outro comentário acima.
rmunn
2
O PHP é uma linguagem completa, por isso não é totalmente falsa. Tudo computacionalmente possível é possível, incluindo a análise de HTML. Os espaços nas tags NUNCA foram um problema e, desde então, eu os adaptei para listar os elementos das tags em ordem. Meu uso corrigiu automaticamente as tags com invólucro inconsistente, removeu os itens comentados no primeiro estágio e, após algumas adições posteriores, todos os tipos de tags podem ser facilmente adicionados (embora seja sensível a maiúsculas e minúsculas) por minha própria escolha). E tenho certeza que CDATA é realmente um elemento XML, não um elemento HTML.
Deji
2
Meu método antigo (que descrevi aqui) era bastante ineficiente e recentemente comecei a reescrever muitos editores de conteúdo. Quando se trata de fazer essas coisas, a possibilidade não é o problema; o melhor caminho é sempre a principal preocupação. A resposta real é "não há uma maneira FÁCIL de fazer isso em PHP". NINGUÉM diz que não há como fazê-lo em PHP ou que é uma péssima ideia, mas que é impossível com regex, o que sinceramente nunca tentei, mas a principal falha na minha resposta é que eu assumi que a pergunta se referia a regex dentro do contexto do PHP, o que não é necessariamente o caso.
1111 Deji De
2

Eu tentei minha mão em um regex para isso também. É principalmente útil para encontrar partes do conteúdo emparelhadas com a próxima tag HTML, e não procura por tags fechadas correspondentes , mas seleciona as tags fechadas. Role uma pilha no seu próprio idioma para verificá-las.

Use com as opções 'sx'. 'g' também se você estiver com sorte:

(?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

Este foi desenvolvido para Python (pode funcionar para outras linguagens, ainda não o testou, usa visões positivas, visões negativas e referências remotas). Apoia:

  • Tag aberta - <div ...>
  • Fechar etiqueta - </div>
  • Comente - <!-- ... -->
  • CDATA - <![CDATA[ ... ]]>
  • Etiqueta de fecho automático - <div .../>
  • Valores de atributo opcionais - <input checked>
  • Valores de atributos não citados / citados - <div style='...'>
  • Cotações simples / duplas - <div style="...">
  • Citações escapadas - <a title='John\'s Story'>
    (esse HTML não é realmente válido, mas eu sou um cara legal)
  • Espaços em torno de sinais de igual - <a href = '...'>
  • Capturas nomeadas para bits interessantes

Também é muito bom não acionar tags malformadas, como quando você esquece um <ou >.

Se o seu sabor regex suporta capturas nomeadas repetidas, você é dourado, mas o Python renão (eu sei que o regex sim, mas preciso usar o baunilha Python). Aqui está o que você recebe:

  • content- Todo o conteúdo até a próxima tag. Você poderia deixar isso de fora.
  • markup - A tag inteira com tudo nela.
  • comment - Se for um comentário, o conteúdo do comentário.
  • cdata- Se for um <![CDATA[...]]>, o conteúdo do CDATA.
  • close_tag- Se for uma marca fechada ( </div>), o nome da marca.
  • tag- Se for uma tag aberta ( <div>), o nome da tag.
  • attributes- Todos os atributos dentro da tag. Use isso para obter todos os atributos se você não receber grupos repetidos.
  • attribute - Repetido, cada atributo.
  • attribute_name - Repetido, cada nome de atributo.
  • attribute_value- Repetido, cada valor de atributo. Isso inclui as aspas, se foi citado.
  • is_self_closing- Isso é /se for uma tag de fechamento automático, caso contrário nada.
  • _qe _v- ignore-os; eles são usados ​​internamente para referências anteriores.

Se o seu mecanismo de expressão regular não suportar capturas nomeadas repetidas, há uma seção chamada que você pode usar para obter cada atributo. Basta executar esse regex no attributesgrupo para obter cada attribute, attribute_namee attribute_valuefora dele.

Demonstração aqui: https://regex101.com/r/mH8jSu/11

Hounshell
fonte
1

Expressões regulares não são poderosas o suficiente para uma linguagem como HTML. Claro, existem alguns exemplos em que você pode usar expressões regulares. Mas, em geral, não é apropriado para a análise.

quiabo
fonte
0

Você sabe ... há muita mentalidade em que você NÃO PODE fazê-lo e acho que todo mundo dos dois lados da cerca está certo e errado. Você pode fazê-lo, mas é preciso um pouco mais de processamento do que apenas executar um regex nele. Tome isso (escrevi isso dentro de uma hora) como exemplo. Ele assume que o HTML é completamente válido, mas, dependendo do idioma que você está usando para aplicar a regex acima mencionada, você pode fazer algumas correções no HTML para garantir que ele seja bem-sucedido. Por exemplo, removendo tags de fechamento que não deveriam estar lá: </img>por exemplo. Em seguida, adicione a barra de fechamento HTML única de fechamento aos elementos que estão faltando, etc.

Eu usaria isso no contexto de escrever uma biblioteca que me permitiria recuperar elementos HTML semelhantes aos do JavaScript [x].getElementsByTagName(), por exemplo. Eu apenas dividia a funcionalidade que escrevi na seção DEFINE do regex e a usava para entrar em uma árvore de elementos, uma de cada vez.

Então, essa será a resposta final de 100% para a validação de HTML? Não. Mas é um começo e com um pouco mais de trabalho, isso pode ser feito. No entanto, tentar fazê-lo dentro de uma execução de regex não é prático nem eficiente.

Erutan409
fonte