Domanda

vedo domande ogni giorno chiedendo come analizzare o estrarre qualcosa da qualche stringa HTML e la prima risposta / commento è sempre "Non utilizzare RegEx per analizzare HTML, per non sentire l'ira!" (Che l'ultima parte è a volte omesso).

Questo è piuttosto confuso per me, ho sempre pensato che, in generale, il modo migliore per analizzare qualsiasi stringa complicata è quella di usare un'espressione regolare. Quindi, come funziona un parser HTML? Non è usare le espressioni regolari per analizzare.

Un particolare argomento per l'utilizzo di un espressione regolare è che non c'è sempre un parsing alternativo (come JavaScript, dove DOMDocument non è un'opzione universalmente disponibile). jQuery, per esempio, sembra gestire bene utilizzando un'espressione regolare per convertire una stringa HTML da nodi DOM.

Non è sicuro o meno di CW questo, è una domanda vera e propria che voglio essere risolta e non veramente destinato ad essere un thread di discussione.

È stato utile?

Soluzione

Di solito utilizzando una tokeniser. Il progetto di HTML5 specifica ha una vasta algoritmo per la gestione di "mondo reale HTML" .

Altri suggerimenti

  

Quindi, come funziona un parser HTML? Non è usare le espressioni regolari per analizzare?

Be ', no.

Se si raggiunge indietro nel vostro cervello per una teoria della computazione naturalmente, se hai preso uno, o un corso di compilatori, o qualcosa di simile, si può ricordare che ci sono diversi tipi di linguaggi e modelli computazionali. Io non sono qualificato per entrare in tutti i dettagli, ma posso rivedere alcuni dei principali punti con voi.

Il tipo più semplice di linguaggio e di calcolo (per questi scopi) è un linguaggio regolare. Questi possono essere generati con le espressioni regolari, e riconosciuti con automi a stati finiti. Fondamentalmente, ciò significa che "parsing" stringhe in questi linguaggi utilizzare lo stato, ma non memoria ausiliaria. HTML non è certamente un linguaggio regolare. Se ci pensate, l'elenco dei tag possono essere nidificate arbitrariamente profondamente. Ad esempio, le tabelle possono contenere tabelle e ogni tabella possono contenere un sacco di tag annidati. Con le espressioni regolari, si può essere in grado di individuare una coppia di tag, ma certamente non nulla arbitrariamente annidate.

Un linguaggio semplice classico che non è normale è parentesi correttamente abbinate. Prova come si potrebbe, non si sarà mai in grado di costruire un'espressione regolare (o automa a stati finiti) che funziona sempre. È necessario memoria per tenere traccia della profondità di annidamento.

Una macchina a stati con uno stack di memoria è la seguente forza del modello computazionale. Questo si chiama un automa push-down, e riconosce linguaggi generati da grammatiche context-free. Qui, possiamo riconoscere parentesi correttamente abbinate -. Anzi, uno stack è il modello di memoria perfetto per questo

Bene, questo è abbastanza buono per HTML? Purtroppo no. Forse per super-super XML accuratamente convalidato, in realtà, in cui tutti i tag si allineano sempre perfettamente. In HTML mondo reale, si può facilmente trovare frammenti come <b><i>wow!</b></i>. Questo fa ovviamente non nido, così al fine di analizzare in modo corretto, una pila è sufficiente semplicemente non potente.

Il livello successivo di calcolo è linguaggi generati da grammatiche generali, e riconosciuti dalle macchine di Turing. Questo è generalmente accettato come efficacemente il forte modello computazionale è - una macchina a stati, con memoria ausiliaria, cui memoria può essere modificato ovunque. Questo è ciò che i linguaggi di programmazione possono fare. Questo è il livello di complessità in cui vive HTML.

Per riassumere tutto qui in una sola frase: per analizzare HTML generale, è necessario un vero e proprio linguaggio di programmazione, non è un'espressione regolare

.

HTML viene analizzato allo stesso modo altre lingue vengono analizzati: lexing e l'analisi. Il passo lexing rompe il flusso di singoli caratteri in token significativi. Il passo analisi assembla i gettoni, utilizzando gli stati e la memoria, in un documento logicamente coerente che possa essere agito su.

Le espressioni regolari sono solo una forma di parser. Un parser HTML onesto-to-bontà sarà molto più complicato di quanto può essere espresso in espressioni regolari, utilizzando discesa ricorsiva , la previsione, e diverse altre tecniche per interpretare correttamente il testo. Se davvero si vuole entrare in esso, si potrebbe verificare lex & yacc e strumenti analoghi.

Il divieto di utilizzare espressioni regolari per l'analisi HTML dovrebbe probabilmente essere scritto più correttamente come: "Non usare ingenui le espressioni regolari per analizzare HTML ..." (se non volete sentire l'ira ) "... e trattare i risultati con cautela." Per alcuni obiettivi specifici, una regex potrebbe essere perfettamente adeguato, ma è necessario essere molto attenti a essere consapevoli dei limiti della vostra regex e cauti come è appropriato alla fonte del testo che stai analisi (ad esempio, se si tratta di l'input dell'utente, essere molto attenti in effetti).

parsing del codice HTML è la trasformazione di un testo lineare in una struttura ad albero. Le espressioni regolari non possono in genere gestire strutture ad albero. L'espressione regolare è necessario in ogni punto per ottenere il token successivo cambia tutto il tempo. È possibile utilizzare le espressioni regolari in un parser, ma avrete bisogno di tutta una serie di espressioni regolari per ogni possibile stato di parsing.

Se si desidera avere una soluzione 100%: è necessario scrivere il proprio codice personalizzato che consente di scorrere il codice HTML carattere per carattere ed è necessario avere un enorme quantità di logica per determinare se è necessario arrestare il nodo corrente e avviare la successiva.

La ragione è che questo è valido HTML:

<ul>
<li>One
<li>Two
<li>Three
</ul>

Ma lo è anche questo:

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>

Se si sono ok con la "soluzione 90%": Quindi, utilizzando un parser XML per caricare un documento va bene. O utilizzando Regex (anche se l'XML è più facile se si è allora padrone del contenuto).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top