html - online - regex skinner




Correspondências abertas de correspondência RegEx, exceto tags auto-contidas XHTML (20)

Eu preciso combinar todas essas tags de abertura:

<p>
<a href="foo">

Mas não estes:

<br />
<hr class="foo" />

Eu vim com isso e queria ter certeza de que estava certo. Eu estou capturando apenas o az .

<([a-z]+) *[^/]*?>

Eu acredito que diz:

  • Encontre um menos do que, então
  • Encontre (e capture) az uma ou mais vezes, depois
  • Encontre zero ou mais espaços e, em seguida,
  • Encontre qualquer caractere zero ou mais vezes, ganancioso, exceto / , em seguida
  • Encontre um maior que

Eu tenho isso certo? E mais importante, o que você acha?


Concordo que a ferramenta certa para analisar XML e especialmente HTML é um analisador e não um mecanismo de expressão regular. No entanto, como outros apontaram, às vezes usar um regex é mais rápido, mais fácil e executa o trabalho se você souber o formato dos dados.

A Microsoft, na verdade, tem uma seção de Melhores Práticas para Expressões Regulares no .NET Framework e fala especificamente sobre Considerar a Origem de Entrada .

Expressões regulares têm limitações, mas você considerou o seguinte?

A estrutura .NET é exclusiva quando se trata de expressões regulares, pois suporta as definições de grupo de balanceamento .

Por esse motivo, acredito que você possa analisar XML usando expressões regulares. Note, no entanto, que deve ser um XML válido (os navegadores são muito tolerantes ao HTML e permitem uma sintaxe XML ruim dentro do HTML ). Isso é possível já que a "Definição do grupo de balanceamento" permitirá que o mecanismo de expressões regulares atue como um PDA.

Cite o artigo 1 citado acima:

Mecanismo de Expressão Regular do .NET

Como descrito acima, construções adequadamente balanceadas não podem ser descritas por uma expressão regular. No entanto, o mecanismo de expressões regulares .NET fornece algumas construções que permitem que construções equilibradas sejam reconhecidas.

  • (?<group>) - envia o resultado capturado na pilha de captura com o grupo de nomes.
  • (?<-group>) - aparece a captura mais alta com o grupo de nomes fora da pilha de captura.
  • (?(group)yes|no) - coincide com a parte yes se existir um grupo com o grupo de nomes, caso contrário, não combina com nenhuma parte.

Essas construções permitem que uma expressão regular .NET emule um PDA restrito, permitindo essencialmente versões simples das operações de pilha: push, pop e empty. As operações simples são praticamente equivalentes a incrementar, decrementar e comparar a zero, respectivamente. Isso permite que o mecanismo de expressão regular do .NET reconheça um subconjunto dos idiomas livres de contexto, em particular aqueles que requerem apenas um contador simples. Isso, por sua vez, permite que as expressões regulares .NET não tradicionais reconheçam construções individuais adequadamente balanceadas.

Considere a seguinte expressão regular:

(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
   <!-- .*? -->                  |
   <[^>]*/>                      |
   (?<opentag><(?!/)[^>]*[^/]>)  |
   (?<-opentag></[^>]*[^/]>)     |
   [^<>]*
)*
(?(opentag)(?!))

Use as bandeiras:

  • Única linha
  • IgnorePatternWhitespace (não é necessário se você reduzir o regex e remover todos os espaços em branco)
  • IgnoreCase (não é necessário)

Expressão Regular Explicada (inline)

(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?>                                        # atomic group / don't backtrack (faster)
   <!-- .*? -->                 |          # match xml / html comment
   <[^>]*/>                     |          # self closing tag
   (?<opentag><(?!/)[^>]*[^/]>) |          # push opening xml tag
   (?<-opentag></[^>]*[^/]>)    |          # pop closing xml tag
   [^<>]*                                  # something between tags
)*                                         # match as many xml tags as possible
(?(opentag)(?!))                           # ensure no 'opentag' groups are on stack

Você pode tentar isso em um melhor analisador de expressões regulares .NET .

Eu usei a fonte de amostra de:

<html>
<body>
<div>
   <br />
   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>
</div>
</body>
</html>

Este encontrou o jogo:

   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>

embora na verdade tenha saído assim:

<ul id="matchMe" type="square">           <li>stuff...</li>           <li>more stuff</li>           <li>               <div>                    <span>still more</span>                    <ul>                         <li>Another &gt;ul&lt;, oh my!</li>                         <li>...</li>                    </ul>               </div>           </li>        </ul>

Por fim, gostei muito do artigo de Jeff Atwood: Parsing Html The Cthulhu Way . Engraçado, cita a resposta para essa pergunta que atualmente tem mais de 4k votos.


Embora seja verdade que pedir regexes para analisar HTML arbitrário é como pedir a um iniciante para escrever um sistema operacional, às vezes é apropriado analisar um conjunto limitado e conhecido de HTML.

Se você tiver um pequeno conjunto de páginas HTML das quais deseja extrair dados e, em seguida, inserir dados em um banco de dados, as regexes poderão funcionar bem. Por exemplo, eu recentemente quis obter os nomes, partidos e distritos de representantes federais australianos, que saí do site do Parlamento. Este foi um trabalho limitado e único.

Regexes funcionou muito bem para mim e foram muito rápidos para configurar.


Há pessoas que lhe dirão que a Terra é redonda (ou talvez que a Terra seja um esferóide oblato se quiser usar palavras estranhas). Eles estão mentindo.

Há pessoas que lhe dirão que Expressões Regulares não devem ser recursivas. Eles estão limitando você. Eles precisam subjugar você, e eles fazem isso mantendo você na ignorância.

Você pode viver em sua realidade ou tomar a pílula vermelha.

Como Lorde Marechal (ele é um parente da classe Marshal .NET?), Eu vi o Regex-Verso baseado em Pilha Subversiva e retornei com poderes que você não pode imaginar. Sim, acho que havia um antigo ou dois protegendo-os, mas eles estavam assistindo futebol na TV, então não foi difícil.

Eu acho que o caso XML é bem simples. O RegEx (na sintaxe do .NET), deflacionado e codificado em base64 para facilitar a compreensão por sua mente fraca, deve ser algo assim:

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
+r/vD34mUADO1P4/AQAA//8=

As opções para definir são RegexOptions.ExplicitCapture . O grupo de captura que você está procurando é ELEMENTNAME . Se o grupo de captura ERROR não estiver vazio, houve um erro de análise e o Regex foi interrompido.

Se você tiver problemas para reconvertê-lo em um regex legível por humanos, isso deve ajudar:

static string FromBase64(string str)
{
    byte[] byteArray = Convert.FromBase64String(str);

    using (var msIn = new MemoryStream(byteArray))
    using (var msOut = new MemoryStream()) {
        using (var ds = new DeflateStream(msIn, CompressionMode.Decompress)) {
            ds.CopyTo(msOut);
        }

        return Encoding.UTF8.GetString(msOut.ToArray());
    }
}

Se você não tem certeza, não, eu não estou brincando (mas talvez eu esteja mentindo). Vai funcionar. Eu construí toneladas de testes unitários para testá-lo, e até usei (parte de) os testes de conformidade . É um tokenizer, não um analisador completo, por isso só dividirá o XML em seus tokens de componente. Não irá analisar / integrar DTDs.

Ah ... se você quiser o código fonte da regex, com alguns métodos auxiliares:

regex para tokenize um xml ou o regex simples


Não ouça esses caras. Você pode totalmente analisar gramáticas livres de contexto com regex se você dividir a tarefa em partes menores. Você pode gerar o padrão correto com um script que faz cada um deles em ordem:

  1. Resolva o problema da parada.
  2. Quadrado um círculo.
  3. Elabore o Problema do Vendedor Viajante em O (log n) ou menos. Se for mais do que isso, você ficará sem RAM e o mecanismo irá travar.
  4. O padrão será bem grande, portanto, certifique-se de ter um algoritmo que comprima dados aleatórios sem perdas.
  5. Quase lá - apenas divida a coisa toda por zero. Mole-mole.

Ainda não terminei a última parte, mas sei que estou chegando perto. Ele continua lançando CthulhuRlyehWgahnaglFhtagnException por algum motivo, então eu vou portá-lo para o VB 6 e usar On Error Resume Next . Vou atualizar com o código assim que eu investigar essa porta estranha que acabou de abrir na parede. Hmm.

PS Pierre de Fermat também descobriu como fazê-lo, mas a margem que ele estava escrevendo não era grande o suficiente para o código.


Você não pode analisar [X] HTML com regex. Porque o HTML não pode ser analisado por regex. O Regex não é uma ferramenta que possa ser usada para analisar corretamente o HTML. Como já respondi em questões de HTML e regex tantas vezes antes, o uso de regex não permitirá que você consuma HTML. Expressões regulares são uma ferramenta insuficientemente sofisticada para entender as construções empregadas pelo HTML. HTML não é uma linguagem regular e, portanto, não pode ser analisada por expressões regulares. As consultas Regex não estão equipadas para dividir o HTML em suas partes significativas. muitas vezes, mas não está chegando a mim. Mesmo as expressões regulares irregulares aprimoradas usadas pelo Perl não estão à altura da tarefa de analisar o HTML. Você nunca vai me fazer crack. HTML é uma linguagem de complexidade suficiente que não pode ser analisada por expressões regulares. Mesmo Jon Skeet não pode analisar HTML usando expressões regulares. Toda vez que você tenta analisar HTML com expressões regulares, a criança profana chora o sangue de virgens, e os hackers russos usam sua webapp. Analisar HTML com regex invoca almas contaminadas no reino dos vivos. HTML e regex andam juntos como amor, casamento e infanticídio ritual. O <center> não consegue segurar, é tarde demais. A força de regex e HTML juntos no mesmo espaço conceitual destruirá sua mente como uma massa aquosa demais. Se você analisar HTML com regex, você estará cedendo a Eles e suas maneiras blasfemas que condenam todos nós a trabalhos desumanos para Aquele cujo Nome não pode ser expresso no Plano Multilíngue Básico, ele vem. O HTML-plus-regexp irá liquefazer as nems do senciente enquanto você observa, sua psique murchando no ataque do horror. Analisadores de HTML baseados em Rege̿̔̉x são o câncer que está matando o . É muito tarde, é muito tarde, não podemos salvar a trangessão de um bebê. O regex irá consumir todo o tecido vivo (exceto o HTML que não pode, como previamente profetizado). nos ajudar como alguém pode sobreviver a este flagelo usando regex para analisar HTML tem condenado a humanidade a uma eternidade de temor tortura e buracos de segurança usando rege x como uma ferramenta para processar HTML estabelece uma lacuna entre este mundo eo domínio temeroso de entidades quebradas (como Entidades de SGML, mas mais corruptas) um mero vislumbre do mundo dos ex-pesquisadores de HTML irá transportar de forma intensa a consciência do programador para um grito incessante, diz ele , a infecção epitelial pestilenta l devorar sua HT ML analisador, aplicação e existência de todos os tempos, como Visual Basic só que pior vier, com es não brigar h PT vem, oi s Unholy Radiance de stro҉ying todos enli̍ ̈Ghtenment, tags HTML vazamento fr̶ǫm yo ur olhos como liq uid p ain, a canção de Regular análise exp re ssion vai EXTI nguish as vozes de homem mor tal do sp aqui eu posso vê-lo, você pode vê-lo é lindo o f inal f rufar as mentiras do homem TUDO É LO Ç ÃO O M eSo O poRo ele chega, ele vem junto com ele ou permeia TODO MEU FAC E MINHA CARA god god god god god god god god ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ͎a̧͈͖r̽̾̈́͒͑e ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ ̽̾̈́͒͑ Ό Ό Ό Ό Ό Ό Ό Ό Ό Ό Ό Ό Ό ̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ ̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ ̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ ̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ ̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝

Você já tentou usar um analisador XML?

Nota do moderador

Esta postagem está bloqueada para evitar edições impróprias em seu conteúdo. O post parece exatamente como deveria - não há problemas com o conteúdo. Por favor, não sinalize a nossa atenção.


Isenção de responsabilidade : use um analisador se você tiver a opção. Dito isto...

Esta é a regex que uso (!) Para corresponder às tags HTML:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>

Pode não ser perfeito, mas eu corri este código através de um monte de HTML. Note que ele até pega coisas estranhas como <a name="badgenerator""> , que aparecem na web.

Eu acho que para fazer isso não combinar com tags independentes, você também quer usar o look-behind negativo de Kobi :

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

ou apenas combinar se e se não.

Para downvoters: este é o código de trabalho de um produto real. Duvido que qualquer pessoa que leia esta página tenha a impressão de que é socialmente aceitável usar regexes em HTML.

Ressalva : devo observar que esse regex ainda se divide na presença de blocos CDATA, comentários e elementos de script e estilo. A boa notícia é que você pode se livrar daqueles que usam um regex ...


Embora não seja adequado e eficaz usar expressões regulares para esse propósito, às vezes expressões regulares fornecem soluções rápidas para problemas simples de correspondência e, a meu ver, não é horrível usar expressões regulares para trabalhos triviais.

Há uma postagem definitiva no blog sobre a correspondência de elementos HTML internos escritos por Steven Levithan.


Experimentar:

<([^\s]+)(\s[^>]*?)?(?<!/)>

É semelhante ao seu, mas o último >não deve ser depois de uma barra, e também aceita h1.


Se você precisa disso para o PHP:

As functionsDOM do PHP não funcionarão corretamente, a menos que seja um XML formatado adequadamente. Não importa quão melhor seja o seu uso para o resto da humanidade.functions

simplehtmldom é bom, mas eu achei um pouco buggy, e é bastante memória pesada [irá falhar em páginas grandes.]

Eu nunca usei QueryPath , então não posso comentar sobre sua utilidade.

Outro para tentar é o meu DOMParser que é muito leve em recursos e eu tenho usado alegremente por um tempo. Simples de aprender e poderoso.

Para Python e Java, links semelhantes foram postados.

Para os downvoters - eu só escrevi minha classe quando os analisadores XML se mostraram incapazes de resistir ao uso real. O downvoting religioso apenas impede que respostas úteis sejam postadas - mantenha as coisas dentro da perspectiva da questão, por favor.


Sun Tzu, um antigo estrategista chinês, general e filósofo, disse:

Dizem que se você conhece seus inimigos e conhece a si mesmo, pode ganhar cem batalhas sem uma única perda. Se você só conhece a si mesmo, mas não o seu oponente, você pode ganhar ou perder. Se você não conhece a si mesmo nem ao seu inimigo, você sempre se colocará em perigo.

Nesse caso, seu inimigo é HTML e você é você mesmo ou regex. Você pode até ser Perl com regex irregular. Conheça o HTML. Conheça a si mesmo.

Eu compus um haiku descrevendo a natureza do HTML.

HTML has
complexity exceeding
regular language.

Eu também compus um haiku descrevendo a natureza do regex em Perl.

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>

Como muitas pessoas já apontaram, o HTML não é uma linguagem comum que pode dificultar a análise. Minha solução para isso é transformá-lo em um idioma regular usando um programa arrumado e, em seguida, usar um analisador XML para consumir os resultados. Existem muitas boas opções para isso. Meu programa é escrito usando Java com a biblioteca jtidy para transformar o HTML em XML e, em seguida, Jaxen para xpath no resultado.


Embora as respostas que você não consegue analisar HTML com expressões regulares estejam corretas, elas não se aplicam aqui. O OP só quer analisar uma tag HTML com regexes, e isso é algo que pode ser feito com uma expressão regular.

O regex sugerido está errado, no entanto:

<([a-z]+) *[^/]*?>

Se você adicionar algo ao regex, retroceder pode ser forçado a combinar coisas bobas como <a >>, [^/]é muito permissivo. Observe também que <space>*[^/]*é redundante, porque [^/]*também pode corresponder a espaços.

Minha sugestão seria

<([a-z]+)[^>]*(?<!/)>

Onde (?<! ... )está (em regexes Perl) o look-behind negativo. Ele lê "a <, depois uma palavra, então qualquer coisa que não seja>, a última das quais pode não ser a /, seguida por>".

Note que isto permite coisas como <a/ >(assim como o regex original), então se você quiser algo mais restritivo, você precisa construir um regex para combinar pares de atributos separados por espaços.


Eu não sei exatamente a sua necessidade, mas se você também estiver usando o .NET, não poderia usar o Html Agility Pack ?

Excerto:

É uma biblioteca de código .NET que permite analisar arquivos HTML "fora da web". O analisador é muito tolerante com o HTML malformado do "mundo real".


Eu sugiro usar o QueryPath para analisar XML e HTML no PHP. É basicamente a mesma sintaxe do jQuery, apenas no lado do servidor.


Existem alguns bons regexes para substituir o HTML pelo BBCode here . Para todos os que dizem, note que ele não está tentando analisar completamente o HTML, apenas para higienizá-lo. Ele provavelmente pode se dar ao luxo de matar tags que seu "analisador" simples não consegue entender.

Por exemplo:

$store =~ s/http:/http:\/\//gi;
$store =~ s/https:/https:\/\//gi;
$baseurl = $store;

if (!$query->param("ascii")) {
    $html =~ s/\s\s+/\n/gi;
    $html =~ s/<pre(.*?)>(.*?)<\/pre>/\[code]$2\[\/code]/sgmi;
}

$html =~ s/\n//gi;
$html =~ s/\r\r//gi;
$html =~ s/$baseurl//gi;
$html =~ s/<h[1-7](.*?)>(.*?)<\/h[1-7]>/\n\[b]$2\[\/b]\n/sgmi;
$html =~ s/<p>/\n\n/gi;
$html =~ s/<br(.*?)>/\n/gi;
$html =~ s/<textarea(.*?)>(.*?)<\/textarea>/\[code]$2\[\/code]/sgmi;
$html =~ s/<b>(.*?)<\/b>/\[b]$1\[\/b]/gi;
$html =~ s/<i>(.*?)<\/i>/\[i]$1\[\/i]/gi;
$html =~ s/<u>(.*?)<\/u>/\[u]$1\[\/u]/gi;
$html =~ s/<em>(.*?)<\/em>/\[i]$1\[\/i]/gi;
$html =~ s/<strong>(.*?)<\/strong>/\[b]$1\[\/b]/gi;
$html =~ s/<cite>(.*?)<\/cite>/\[i]$1\[\/i]/gi;
$html =~ s/<font color="(.*?)">(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<font color=(.*?)>(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<link(.*?)>//gi;
$html =~ s/<li(.*?)>(.*?)<\/li>/\[\*]$2/gi;
$html =~ s/<ul(.*?)>/\[list]/gi;
$html =~ s/<\/ul>/\[\/list]/gi;
$html =~ s/<div>/\n/gi;
$html =~ s/<\/div>/\n/gi;
$html =~ s/<td(.*?)>/ /gi;
$html =~ s/<tr(.*?)>/\n/gi;

$html =~ s/<img(.*?)src="(.*?)"(.*?)>/\[img]$baseurl\/$2\[\/img]/gi;
$html =~ s/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/\[url=$baseurl\/$2]$4\[\/url]/gi;
$html =~ s/\[url=$baseurl\/http:\/\/(.*?)](.*?)\[\/url]/\[url=http:\/\/$1]$2\[\/url]/gi;
$html =~ s/\[img]$baseurl\/http:\/\/(.*?)\[\/img]/\[img]http:\/\/$1\[\/img]/gi;

$html =~ s/<head>(.*?)<\/head>//sgmi;
$html =~ s/<object>(.*?)<\/object>//sgmi;
$html =~ s/<script(.*?)>(.*?)<\/script>//sgmi;
$html =~ s/<style(.*?)>(.*?)<\/style>//sgmi;
$html =~ s/<title>(.*?)<\/title>//sgmi;
$html =~ s/<!--(.*?)-->/\n/sgmi;

$html =~ s/\/\//\//gi;
$html =~ s/http:\//http:\/\//gi;
$html =~ s/https:\//https:\/\//gi;

$html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsi;
$html =~ s/\r\r//gi;
$html =~ s/\[img]\//\[img]/gi;
$html =~ s/\[url=\//\[url=/gi;

O W3C explica a análise em um formato pseudoexpress:
W3C Link

Siga os links var para QName, Se Attributepara obter uma imagem mais clara.
Com base nisso, você pode criar um regexp bastante bom para lidar com coisas como descartar tags.


Recentemente, escrevi um sanitizante de HTML em Java. Ele é baseado em uma abordagem mista de expressões regulares e código Java. Pessoalmente eu odeio expressões regulares e sua insensatez (legibilidade, facilidade de manutenção, etc.), mas se você reduzir o escopo de seus aplicativos, ele pode se adequar às suas necessidades. De qualquer forma, meu desinfetante usa uma lista branca para tags HTML e uma lista negra para alguns atributos de estilo.

Para sua conveniência, configurei um playground para que você possa testar se o código corresponde aos seus requisitos: playground e código Java . Seu feedback será apreciado.

Há um pequeno artigo descrevendo este trabalho no meu blog: http://roberto.open-lab.com


Sempre que eu preciso extrair rapidamente algo de um documento HTML, eu uso o Tidy para convertê-lo em XML e, em seguida, uso XPath ou XSLT para obter o que preciso. No seu caso, algo assim:

//p/a[@href='foo']

Você quer o primeiro >não precedido por um /. Veja here detalhes sobre como fazer isso. É referido como lookbehind negativo.

No entanto, uma implementação ingênua disso terminará correspondendo <bar/></foo>neste documento de exemplo

<foo><bar/></foo>

Você pode fornecer um pouco mais de informações sobre o problema que está tentando resolver? Você está iterando através de tags programaticamente?


<\s*(\w+)[^/>]*>

As partes explicadas:

< : personagem inicial

\s* : pode ter espaços em branco antes do nome da tag (feio mas possível).

(\w+): tags podem conter letras e números (h1). Bem, \wtambém corresponde a '_', mas não faz mal, eu acho. Se curioso use ([a-zA-Z0-9] +) em vez disso.

[^/>]*: qualquer coisa, exceto >e /até o fechamento>

> : fechamento >

NÃO RELACIONADO

E para os companheiros que subestimam as expressões regulares dizendo que são tão poderosas quanto as linguagens regulares:

um n ba n ba n que não é regular e nem mesmo contexto livre, pode ser combinado com^(a+)b\1b\1$

Backreferencing FTW !







xhtml