Utilizzo delle espressioni regolari per analizzare l'HTML: perché no?


208

Sembra che ogni domanda su StackOverflow in cui il richiedente sta usando regex per ottenere alcune informazioni dall'HTML avrà inevitabilmente una "risposta" che dice di non usare regex per analizzare l'HTML.

Perchè no? Sono consapevole che ci sono parser HTML "reali" senza virgolette là fuori come Beautiful Soup , e sono sicuro che sono potenti e utili, ma se stai facendo qualcosa di semplice, veloce o sporco, allora perché preoccuparti di usare qualcosa di così complicato quando alcune dichiarazioni regex funzioneranno bene?

Inoltre, c'è qualcosa di fondamentale che non capisco sul regex che li rende una cattiva scelta per l'analisi in generale?


3
Penso che questo sia una vittima di stackoverflow.com/questions/133601
jcrossley3

23
Perché solo Chuck Norris può analizzare HTML con regex (come spiegato in questo famoso cosa Zalgo: stackoverflow.com/questions/1732348/... ).
Takeshin,

1
Questa domanda mi ha spinto a chiederne un altro che è in qualche modo correlato. Nel caso in cui tu sia interessato: perché non è possibile usare regex per analizzare HTML / XML: una spiegazione formale in parole
povere


Questa domanda è stata aggiunta alle Domande frequenti sull'espressione regolare di overflow dello stack , in "Attività di convalida comuni".
aliteralmind

Risposte:


212

L'analisi HTML completa non è possibile con le espressioni regolari, poiché dipende dall'abbinamento del tag di apertura e chiusura che non è possibile con regexps.

Le espressioni regolari possono corrispondere solo alle lingue normali ma l'HTML è una lingua senza contesto e non una lingua normale (Come sottolineato da @StefanPochmann, anche le lingue regolari sono senza contesto, quindi senza contesto non significa necessariamente non regolare). L'unica cosa che puoi fare con regexps su HTML è l'euristica ma non funzionerà su tutte le condizioni. Dovrebbe essere possibile presentare un file HTML che verrà erroneamente associato a qualsiasi espressione regolare.


26
La migliore risposta finora. Se può solo abbinare grammatiche regolari, avremmo bisogno di una regexp infinitamente grande per analizzare una grammatica senza contesto come HTML. Adoro quando queste cose hanno chiare risposte teoriche.
ntownsend,

2
Ho pensato che stessimo discutendo di regex di tipo Perl dove non sono in realtà espressioni regolari.
Hank Gay,

5
In realtà, le espressioni regolari .Net possono abbinare l'apertura con i tag di chiusura, in una certa misura, usando gruppi di bilanciamento e un'espressione accuratamente realizzata. Contenere tutto ciò in una regexp è ovviamente folle, sembrerebbe il grande codice Chtulhu e probabilmente evocherebbe anche quello vero. E alla fine non funzionerà ancora per tutti i casi. Dicono che se scrivi un'espressione regolare che può analizzare correttamente qualsiasi HTML l'universo crollerà su se stesso.
Alex Paven,

5
Alcune librerie regex possono fare espressioni regolari ricorsive (rendendole effettivamente espressioni non regolari :)
Ondra Žižka,

43
-1 Questa risposta trae la giusta conclusione ("È una cattiva idea analizzare HTML con Regex") da argomenti errati ("Perché HTML non è un linguaggio normale"). La cosa che oggigiorno la maggior parte delle persone intende dire quando dice "regex" (PCRE) è in grado non solo di analizzare le grammatiche libere dal contesto (che in realtà è banale), ma anche di grammatiche sensibili al contesto (vedi stackoverflow.com/questions/7434272/ ... ).
NikiC,


23

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

Supponi di avere un file HTML in cui stai cercando di estrarre gli URL dai tag <img>.

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

Quindi scrivi una regex come questa in Perl:

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

In questo caso, $urlconterrà davvero http://example.com/whatever.jpg. Ma cosa succede quando inizi a ricevere HTML in questo modo:

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

o

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

o

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

o

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

o inizi a ricevere falsi positivi da

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

Sembra così semplice e potrebbe essere semplice per un singolo file immutabile, ma per tutto ciò che farai su dati HTML arbitrari, le regex sono solo una ricetta per il mal di cuore futuro.


4
Questa sembra essere la vera risposta - mentre è probabilmente possibile analizzare HTML arbitrario con regex poiché le regex di oggi sono più di un semplice automa finito, per analizzare HTML arbitrario e non solo una pagina concreta devi reimplementare un parser HTML in regexp e le regex diventano sicuramente 1000 volte illeggibili.
Smit Johnth,

1
Ehi Andy, mi sono preso il tempo di trovare un'espressione a supporto dei tuoi casi citati. stackoverflow.com/a/40095824/1204332 Fammi sapere cosa ne pensi! :)
Ivan Chaer,

2
Il ragionamento in questa risposta è così superata, e vale ancora meno oggi di quanto abbia fatto in origine (che penso che non ha fatto). (Citando OP: "se stai solo facendo qualcosa di semplice, veloce o sporco ...".)
Sz.

16

Due motivi rapidi:

  • scrivere una regex in grado di resistere a input dannosi è difficile; molto più difficile rispetto all'utilizzo di uno strumento predefinito
  • scrivere una regex in grado di funzionare con il markup ridicolo con cui rimarrai inevitabilmente bloccato è difficile; molto più difficile rispetto all'utilizzo di uno strumento predefinito

Per quanto riguarda l'idoneità delle regex per l'analisi in generale: non sono adatte. Hai mai visto il tipo di regex di cui avresti bisogno per analizzare la maggior parte delle lingue?


2
Wow? Un downvote dopo 2+ anni? Nel caso qualcuno si stesse chiedendo, non ho detto "Perché è teoricamente impossibile" perché la domanda era chiaramente posta su "veloce e sporco", non "corretto". L'OP chiaramente ha già letto le risposte che coprivano il territorio teoricamente impossibile e non erano ancora soddisfatte.
Hank Gay,

1
Avere un voto dopo 5+ anni. :) Per quanto riguarda il motivo per cui potresti aver ricevuto il downvote, non sono qualificato a dirlo, ma personalmente, mi sarebbe piaciuto vedere alcuni esempi o spiegazioni piuttosto che la domanda retorica di chiusura.
Adam Jensen,

3
Fondamentalmente tutto l'analisi rapida HTML sporca che viene eseguita nei prodotti di spedizione o strumenti interni finisce per essere un buco di sicurezza spalancato, o un bug in attesa di accadere. Deve essere scoraggiato con gusto. Se si può usare un regex, si può usare un parser html appropriato.
Ripristina Monica il

16

Per quanto riguarda l'analisi, le espressioni regolari possono essere utili nella fase di "analisi lessicale" (lexer), in cui l'input è suddiviso in token. È meno utile nell'attuale fase "costruisci un albero di analisi".

Per un parser HTML, mi aspetto che accetti solo HTML ben formato e che richiede capacità al di fuori di ciò che può fare un'espressione regolare (non possono "contare" e assicurarsi che un determinato numero di elementi di apertura sia bilanciato dallo stesso numero di elementi di chiusura).


8

Perché ci sono molti modi per "rovinare" l'HTML che i browser tratteranno in modo piuttosto liberale, ma ci vorrebbe abbastanza sforzo per riprodurre il comportamento liberale del browser per coprire tutti i casi con espressioni regolari, quindi il tuo regex fallirà inevitabilmente in alcuni casi e ciò potrebbe introdurre gravi lacune nella sicurezza del sistema.


1
È vero, la maggior parte dell'HTML disponibile sembra essere orribile. Non capisco come un'espressione regolare non riuscita possa introdurre gravi lacune nella sicurezza. Puoi fare un esempio?
ntownsend,

4
ntownsend: Ad esempio, pensi di aver rimosso tutti i tag di script dall'HTML ma la tua regex non copre un caso speciale (che, diciamo, funziona solo su IE6): boom, hai una vulnerabilità XSS!
Tamas Czinege,

1
Questo è stato un esempio strettamente ipotetico poiché la maggior parte degli esempi del mondo reale sono troppo complicati per adattarsi a questi commenti, ma puoi trovarne alcuni cercandoti rapidamente su Google.
Tamas Czinege,

3
+1 per menzionare l'angolo di sicurezza. Quando ti interfacci con l'intera Internet non puoi permetterti di scrivere il codice "funziona quasi sempre".
j_random_hacker,

7

Il problema è che la maggior parte degli utenti che fanno una domanda che ha a che fare con HTML e regex lo fanno perché non riescono a trovare una propria regex che funzioni. Quindi bisogna pensare se tutto sarebbe più semplice quando si usa un parser DOM o SAX o qualcosa di simile. Sono ottimizzati e costruiti allo scopo di lavorare con strutture di documenti simili a XML.

Certo, ci sono problemi che possono essere risolti facilmente con le espressioni regolari. Ma l'enfasi si trova facilmente .

Se vuoi solo trovare tutti gli URL che sembrano http://.../a posto con regexps. Ma se vuoi trovare tutti gli URL che si trovano in un a-Element che ha la classe 'mylink', probabilmente è meglio usare un parser appropriato.


6

Le espressioni regolari non sono state progettate per gestire una struttura di tag nidificata ed è, nella migliore delle ipotesi, complicato (nella peggiore delle ipotesi, impossibile) gestire tutti i possibili casi limite che si ottengono con HTML reale.


6

Credo che la risposta stia nella teoria del calcolo. Perché una lingua possa essere analizzata usando regex, deve essere per definizione "normale" ( link ). L'HTML non è un linguaggio normale in quanto non soddisfa una serie di criteri per un linguaggio normale (molto a che fare con i numerosi livelli di annidamento inerenti al codice HTML). Se sei interessato alla teoria del calcolo, consiglierei questo libro.


1
In realtà ho letto quel libro. Non mi è venuto in mente che l'HTML sia un linguaggio privo di contesto.
ntownsend,

4

Questa espressione recupera gli attributi dagli elementi HTML. Supporta:

  • attributi non quotati / citati,
  • virgolette singole / doppie,
  • virgolette di escape all'interno degli attributi,
  • spazi attorno a segni di uguale,
  • qualsiasi numero di attributi,
  • controlla solo gli attributi all'interno dei tag,
  • commenti di escape e
  • gestire diverse virgolette all'interno di un valore di attributo.

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

Dai un'occhiata . Funziona meglio con i flag "gisx", come nella demo.


1
È molto interessante. Non leggibile, probabilmente difficile da eseguire il debug ma comunque: lavoro impressionante!
Eric Duminil,

Ciò presuppone ancora vagamente che l'HTML sia ben formato. Senza la corrispondenza del contesto, questo corrisponderà agli URL apparenti in contesti in cui in genere non si desidera abbinarli, come in un pezzo di codice JavaScript all'interno di un <script>tag.
Tripleee

4

HTML / XML è diviso in markup e contenuto. Regex è utile solo per eseguire un'analisi tag lessicale. Immagino che tu possa dedurre il contenuto. Sarebbe una buona scelta per un parser SAX. Tag e contenuti potrebbero essere consegnati a una funzione definita dall'utente in cui è possibile tenere traccia di annidamento / chiusura di elementi.

Per quanto riguarda solo l'analisi dei tag, può essere fatto con regex e utilizzato per rimuovere i tag da un documento.

Nel corso di anni di test, ho scoperto il segreto del modo in cui i browser analizzano i tag, sia in forma che in forma.

Gli elementi normali vengono analizzati con questo modulo:

Il nucleo di questi tag usa questa regex

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

Noterai questo [^>]?come una delle alternative. Ciò corrisponderà a virgolette non bilanciate da tag mal formati.

È anche la singola radice più cattiva di tutte le espressioni regolari. Il modo in cui viene utilizzato attiverà un bump-along per soddisfare il suo contenitore quantificato avido, da abbinare.

Se usato passivamente, non c'è mai un problema. Ma se costringi qualcosa a corrispondere intervallandolo con una coppia di attributo / valore desiderata e non fornisci una protezione adeguata dal backtracking, è un incubo fuori controllo.

Questa è la forma generale per semplici tag vecchi. Notare che [\w:]rappresenta il nome del tag? In realtà, i caratteri legali che rappresentano il nome del tag sono un incredibile elenco di caratteri Unicode.

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

Andando avanti, vediamo anche che non puoi semplicemente cercare un tag specifico senza analizzare TUTTI i tag. Voglio dire, potresti, ma dovrebbe usare una combinazione di verbi come (* SKIP) (* FAIL) ma tutti i tag devono essere analizzati.

Il motivo è che la sintassi dei tag può essere nascosta all'interno di altri tag, ecc.

Quindi, per analizzare passivamente tutti i tag, è necessaria una regex come quella qui sotto. Questo particolare corrisponde anche a contenuti invisibili .

Man mano che nuovi HTML o xml o altri sviluppano nuovi costrutti, basta aggiungerlo come una delle alternative.


Nota sulla pagina Web: non ho mai visto una pagina Web (o xhtml / xml) con cui questo ha
avuto problemi. Se ne trovi uno, fammelo sapere.

Nota sulle prestazioni: è veloce. Questo è il parser tag più veloce che abbia mai visto
(potrebbe esserci più veloce, chissà).
Ho diverse versioni specifiche. È anche eccellente come raschietto
(se sei il tipo pratico).


Regex grezzo 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]*?))))>

Aspetto formattato

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

3

"Dipende" però. È vero che le regex non lo fanno e non possono analizzare l'HTML con vera accuratezza, per tutti i motivi indicati qui. Se, tuttavia, le conseguenze di sbagliare (come non gestire i tag nidificati) sono minori, e se le regex sono super convenienti nel tuo ambiente (come quando stai hackerando Perl), vai avanti.

Supponiamo che tu stia forse analizzando le pagine web che rimandano al tuo sito - forse le hai trovate con una ricerca di link di Google - e vuoi un modo rapido per avere un'idea generale del contesto che circonda il tuo link. Stai tentando di eseguire un piccolo rapporto che potrebbe avvisarti di collegare lo spam, qualcosa del genere.

In tal caso, analizzare in modo errato alcuni dei documenti non sarà un grosso problema. Nessuno, ma vedrai gli errori, e se sei molto fortunato ci saranno pochi abbastanza che puoi seguire individualmente.

Immagino che sto dicendo che è un compromesso. A volte l'implementazione o l'utilizzo di un parser corretto - per quanto facile possa essere - potrebbe non valere la pena se l'accuratezza non è critica.

Fai solo attenzione ai tuoi presupposti. Posso pensare ad alcuni modi in cui il collegamento regexp può ritorcersi contro se stai cercando di analizzare qualcosa che verrà mostrato in pubblico, ad esempio.


3

Ci sono sicuramente casi in cui l'uso di un'espressione regolare per analizzare alcune informazioni dall'HTML è la strada giusta da percorrere - dipende molto dalla situazione specifica.

Il consenso sopra è che in generale è una cattiva idea. Tuttavia, se la struttura HTML è nota (ed è improbabile che cambi), è comunque un approccio valido.


3

Tieni presente che mentre l'HTML stesso non è regolare, le parti di una pagina che stai guardando potrebbero essere regolari.

Ad esempio, è un errore per i <form>tag da annidare; se la pagina web funziona correttamente, allora usare un'espressione regolare per afferrare un <form>sarebbe completamente ragionevole.

Recentemente ho fatto qualche raschio sul web usando solo selenio ed espressioni regolari. Ho franca perché i dati che volevo era messo in una <form>, e mettere in un semplice formato tabellare (così ho potuto anche contare su <table>, <tr>e <td>di essere non nidificati - che in realtà è molto insolito). In una certa misura, le espressioni regolari erano persino quasi necessarie, poiché parte della struttura a cui avevo bisogno di accedere era delimitata da commenti. (Beautiful Soup può darti commenti, ma sarebbe stato difficile afferrare <!-- BEGIN -->e <!-- END -->bloccare usando Beautiful Soup.)

Se dovessi preoccuparmi delle tabelle nidificate, tuttavia, il mio approccio semplicemente non avrebbe funzionato! Avrei dovuto ricorrere a Beautiful Soup. Anche in questo caso, tuttavia, a volte puoi usare un'espressione regolare per afferrare il pezzo di cui hai bisogno e quindi eseguire il drill down da lì.


2

In realtà, l'analisi PHP con regex è perfettamente possibile in PHP. Devi solo analizzare l'intera stringa all'indietro usando strrposper trovare <e ripetere la regex da lì usando gli identificatori ungreedy ogni volta per superare i tag nidificati. Non elegante e terribilmente lento su grandi cose, ma l'ho usato per il mio editor di template personale per il mio sito Web. In realtà non stavo analizzando HTML, ma alcuni tag personalizzati che ho creato per interrogare le voci del database per visualizzare tabelle di dati (il mio <#if()>tag potrebbe evidenziare voci speciali in questo modo). Non ero preparato a cercare un parser XML solo su un paio di tag auto-creati (con dati molto non XML al loro interno) qua e là.

Quindi, anche se questa domanda è considerevolmente morta, appare ancora in una ricerca su Google. L'ho letto e ho pensato "sfida accettata" e ho finito di correggere il mio semplice codice senza dover sostituire tutto. Ha deciso di offrire un'opinione diversa a chiunque cerchi un motivo simile. Anche l'ultima risposta è stata pubblicata 4 ore fa, quindi questo è ancora un argomento caldo.


2
-1 per aver suggerito un'idea TERRIBILE. Hai preso in considerazione uno spazio tra il tag e la parentesi angolare di chiusura? (Ad esempio, <tag >) Hai considerato i tag di chiusura commentati? (Ad esempio, <tag> <!-- </tag> -->) Hai considerato CDATA? Hai considerato tag incoerenti? (Ad esempio, <Tag> </tAG>) Hai considerato anche questo ?
rmunn,

1
Nel caso particolare dei tuoi pochi tag personalizzati, sì, le espressioni regolari funzionano bene. Quindi non è che il tuo uso di essi sia stato un errore nel tuo caso particolare . Questo non è HTML, tuttavia, e dire "L'analisi HTML con regex è perfettamente possibile in PHP" è semplicemente falso e un'idea TERRIBILE. Le incoerenze del vero HTML (e ce ne sono molte più delle poche che ho elencato) sono il motivo per cui non dovresti mai analizzare il vero HTML con espressioni regolari. Vedi, bene, tutte le altre risposte a questa domanda, così come quella a cui ho collegato nell'altro mio commento sopra.
rmunn,

2
PHP è un linguaggio completo, quindi non è affatto falso. Tutto è possibile dal punto di vista computazionale, compreso l'analisi dell'HTML. Gli spazi nei tag non sono mai stati un problema e da allora l'ho adattato per elencare gli elementi dei tag in ordine. Il mio uso ha corretto automaticamente i tag con involucro incoerente, elementi commentati eliminati nella prima fase e dopo alcune aggiunte successive è possibile aggiungere facilmente tutti i tipi di tag (anche se fa distinzione tra maiuscole e minuscole, a mia scelta). E sono abbastanza sicuro che CDATA sia in realtà un elemento XML, non HTML.
Deji,

2
Il mio vecchio metodo (che ho descritto qui) era piuttosto inefficiente e recentemente ho iniziato una riscrittura di molti editor di contenuti. Quando si tratta di fare queste cose, la possibilità non è il problema; il modo migliore è sempre la preoccupazione principale. La vera risposta è "non esiste un modo FACILE per farlo in PHP". NESSUNO dice che non c'è modo di farlo in PHP o che è un'idea terribile, ma che è impossibile con regex, che onestamente non ho mai provato, ma l'unico grande difetto nella mia risposta è che ho pensato che la domanda si riferisse a regex nel contesto di PHP, il che non è necessariamente il caso.
Deji,

2

Ho provato a regex anche per questo. È utile soprattutto per trovare blocchi di contenuti associati al prossimo tag HTML e non cerca tag vicini corrispondenti , ma raccoglierà tag vicini. Lancia uno stack nella tua lingua per controllarli.

Utilizzare con le opzioni 'sx'. 'g' anche se ti senti fortunato:

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

Questo è progettato per Python (potrebbe funzionare per altre lingue, non l'ho mai provato, utilizza lookahead positivi, lookbehind negativi e backreferences denominati). supporti:

  • Apri tag - <div ...>
  • Chiudi tag - </div>
  • Commento - <!-- ... -->
  • CDATA - <![CDATA[ ... ]]>
  • Etichetta a chiusura automatica - <div .../>
  • Valori di attributi opzionali - <input checked>
  • Valori di attributi non quotati / citati - <div style='...'>
  • Quotazioni singole / doppie - <div style="...">
  • Citazioni di escape - <a title='John\'s Story'>
    (questo non è HTML molto valido, ma sono un bravo ragazzo)
  • Spazi attorno ai segni di uguale - <a href = '...'>
  • Catture nominate per bit interessanti

È anche abbastanza buono non innescare tag non validi, come quando si dimentica un <o >.

Se il tuo sapore regex supporta acquisizioni con nome ripetuto, allora sei d'oro, ma Python reno (so che regex lo fa, ma ho bisogno di usare Python vaniglia). Ecco cosa ottieni:

  • content- Tutto il contenuto fino al tag successivo. Potresti lasciarlo fuori.
  • markup - L'intero tag con tutto ciò che contiene.
  • comment - Se è un commento, il contenuto del commento.
  • cdata- Se è un <![CDATA[...]]>contenuto CDATA.
  • close_tag- Se si tratta di un tag vicino ( </div>), il nome del tag.
  • tag- Se è un tag aperto ( <div>), il nome del tag.
  • attributes- Tutti gli attributi all'interno del tag. Usa questo per ottenere tutti gli attributi se non ottieni gruppi ripetuti.
  • attribute - Ripetuto, ogni attributo.
  • attribute_name - Ripetuto, ogni nome di attributo.
  • attribute_value- Ripetuto, ogni valore di attributo. Questo include le virgolette se è stato quotato.
  • is_self_closing- Questo è /se si tratta di un tag a chiusura automatica, altrimenti niente.
  • _qe _v- ignorarli; sono utilizzati internamente per i riferimenti secondari.

Se il tuo motore regex non supporta acquisizioni con nome ripetute, c'è una sezione chiamata che puoi usare per ottenere ogni attributo. Basta eseguire quella regex sul attributesgruppo per ottenerne ciascuno attribute, attribute_namee attribute_valuefuori di esso.

Demo qui: https://regex101.com/r/mH8jSu/11


1

Le espressioni regolari non sono abbastanza potenti per un linguaggio del genere come HTML. Certo, ci sono alcuni esempi in cui puoi usare espressioni regolari. Ma in generale non è appropriato per l'analisi.


0

Sai ... c'è molta mentalità da parte tua NON PUOI farlo e penso che tutti su entrambi i lati della barriera abbiano ragione e torto. È POSSIBILE farlo, ma ci vuole un po 'più di una semplice elaborazione che esegue uno regex contro di essa. Prendi questo (l'ho scritto entro un'ora) come esempio. Presuppone che l'HTML sia completamente valido, ma a seconda della lingua utilizzata per applicare la regex sopra menzionata, è possibile effettuare alcune correzioni dell'HTML per assicurarsi che abbia esito positivo. Ad esempio, rimuovere i tag di chiusura che non dovrebbero essere presenti: </img>ad esempio. Quindi, aggiungi la barra rovesciata HTML singola di chiusura agli elementi mancanti, ecc.

Lo userei nel contesto della scrittura di una libreria che mi consentirebbe di eseguire il recupero di elementi HTML simile a quello di JavaScript [x].getElementsByTagName(), ad esempio. Aggiungevo semplicemente la funzionalità che avevo scritto nella sezione DEFINE del regex e la usavo per entrare all'interno di un albero di elementi, uno alla volta.

Quindi, questa sarà la risposta finale al 100% per la convalida dell'HTML? No. Ma è un inizio e con un po 'più di lavoro, si può fare. Tuttavia, provare a farlo all'interno di un'esecuzione regex non è pratico, né efficiente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.