Domanda

Sto creando un'applicazione che avrà un URL come input, recuperare il contenuto HTML della pagina dal Web e l'estratto di tutto ciò che non è contenuto in un tag . In altre parole, il contenuto testuale della pagina, come si è visto dal visitatore a quella pagina. Che include 'mascheramento' fuori tutto incapsulato in <script></script>, <style></style> e <!-- -->, dal momento che queste porzioni contengono testo che non è avvolto all'interno di un tag (ma è meglio lasciare da solo).

Ho costruito questa regex:

(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>)

Seleziona correttamente tutti i contenuti che voglio ignorare, e lascia solo il contenuto del testo della pagina. Tuttavia, ciò significa che quello che voglio estratto non verranno visualizzati nella collezione match (sto usando VB.Net in Visual Studio 2010).

C'è un modo per "invertito" l'abbinamento di un documento complesso come questo, in modo che avrei avuto partite su tutte le stringhe di testo che vengono lasciati fuori dal corrispondente nella regex sopra?

Finora, quello che ho fatto è stato quello di aggiungere un'altra alternativa, alla fine, che seleziona "qualsiasi sequenza che non contiene ", che poi significa che il testo rimanente. Ho chiamato che l'ultimo pezzo di un gruppo di cattura, e quando ho iterare nel corso degli incontri, controllo per la presenza di testo nel gruppo di "testo". Questo funziona, ma mi chiedevo se era possibile fare tutto tramite regex e solo finiscono con partite sul testo in chiaro.

Questo dovrebbe funzionare genericamente, senza sapere di tag specifici nel codice HTML. Si suppone che l'estratto tutti testo. Inoltre, ho bisogno di preservare l'HTML originale modo che la pagina conserva tutti i suoi legami e gli script - ho solo bisogno di essere in grado di estrarre il testo in modo che possa effettuare le ricerche e sostituzioni all'interno di esso, senza timore di "rinominare" qualsiasi tag, attributi o variabili script, ecc (quindi non posso solo fare un "sostituire con niente", a tutte le partite che ricevo, perché anche se sto poi a sinistra con quello che mi serve, è una seccatura per reinserire che di nuovo nelle posizioni corrette della documento completamente funzionale).

Vorrei sapere se questo è a tutto il possibile utilizzando regex (e so di HTML Agility Pack and XPath, ma non me la sento).

Qualche suggerimento?

Aggiornamento: Ecco la soluzione (regex-based) ho finito con: http://www.martinwardener.com/regex/ , implementato in un'applicazione web demo che mostrerà sia le stringhe regex attivi insieme a un motore di prova che consente di eseguire il parsing in qualsiasi pagina html on-line, dando si analizza tempi e risultati estratti (link, URL e il testo porzioni individualmente -. così come vista in cui tutte le partite regex sono evidenziate in luogo del documento HTML completo)

È stato utile?

Soluzione 5

OK, quindi ecco come lo sto facendo:

Usando il mio regex originale (con il modello di ricerca aggiunto per il testo semplice, che risulta essere un testo che è rimasto dopo il tag di ricerche vengono fatte):

(?:(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>))|(?P<text>[^<>]*)

Poi in VB.Net:

Dim regexText As New Regex("(?:(?:<(?<tag>script|style)[\s\S]*?</\k<tag>>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>))|(?<text>[^<>]*)", RegexOptions.IgnoreCase)
Dim source As String = File.ReadAllText("html.txt")
Dim evaluator As New MatchEvaluator(AddressOf MatchEvalFunction)
Dim newHtml As String = regexText.Replace(source, evaluator)

L'attuale sostituzione del testo avviene qui:

Private Function MatchEvalFunction(ByVal match As Match) As String
    Dim plainText As String = match.Groups("text").Value
    If plainText IsNot Nothing AndAlso plainText <> "" Then
        MatchEvalFunction = match.Value.Replace(plainText, plainText.Replace("Original word", "Replacement word"))
    Else
        MatchEvalFunction = match.Value
    End If
End Function

Voila. newHtml ora contiene una copia esatta dell'originale, ad eccezione di ogni occorrenza di "parola originale" nella pagina (come è presentata in un browser) viene commutato con "parola di sostituzione", e tutto il codice HTML e script viene conservata intatta. Naturalmente, si potrebbe / metterebbe in una routine di sostituzione più elaborata, ma questo mostra il principio di base. Si tratta di 12 linee di codice, tra cui dichiarazione di funzione e carico di codice html ecc Sarei molto interessato a vedere una soluzione in parallelo, fatto in DOM etc per il confronto (sì, lo so questo approccio può essere buttato fuori equilibrio certo occorrenze di alcuni tag nidificati stranezze - nello script di riscrittura - ma il danno da quella sarà ancora molto limitati, se del caso (vedere alcune delle osservazioni di cui sopra), e, in generale, questo farà il lavoro dannatamente bene ).

Altri suggerimenti

  

quello che ho fatto è stato quello di aggiungere un'altra alternativa, alla fine, che seleziona "qualsiasi sequenza che non contiene < o >", che poi significa che il testo rimanente. Ho chiamato che l'ultimo pezzo di un gruppo di cattura, e quando ho iterare nel corso degli incontri, controllo per la presenza di testo nel gruppo di "testo".

Questo è ciò che si farebbe normalmente. O ancora più semplice, sostituire ogni partita del modello di markup con e la stringa vuota e quello che hai a sinistra è la roba che stai cercando.

  

E 'sorta di lavori, ma sembra che ci sia una stringa qua e là che viene raccolto che non dovrebbe essere.

Beh, sì, è perché la vostra espressione e regex in generale è insufficiente per analizzare anche HTML valido, per non parlare degli orrori che sono là fuori sul web reale. Prima punta da guardare, se si vuole veramente per inseguire questo approccio futile:. Valori degli attributi (come pure il contenuto del testo in generale) può contenere un carattere > escape

Vorrei suggerire ancora una volta i vantaggi di HTML Agility pacchetto.

ETA:. Dal momento che sembra volerlo, ecco alcuni esempi di markup che sembra che ti viaggio fino l'espressione

<a href=link></a> - unquoted
<a href= link></a> - unquoted, space at front matched but then required at back
<a href="~/link"></a> - very common URL char missing in group
<a href="link$!*'link"></a> - more URL chars missing in group
<a href=lïnk></a> - IRI
<a href
    ="link"> - newline (or tab)
<div style="background-image: url(link);"> - unquoted
<div style="background-image: url( 'link' );"> - spaced
<div style="background-image: u&#114;l('link');"> - html escape
<div style="background-image: ur\l('link');"> - css escape
<div style="background-image: url('link\')link');"> - css escape
<div style="background-image: url(\
'link')"> - CSS folding
<div style="background-image: url
('link')"> - newline (or tab)

e questo è solo del tutto valido markup che non abbinare il link a destra, non è una delle possibilità di formattazione non valida, markup che non dovrebbe, ma non corrisponde un collegamento, o uno qualsiasi dei tanti problemi con l'altra tecnica di scissione markup dal testo. Questa è la punta di un iceberg.

Regex non è affidabile per il recupero di contenuti testuali dei documenti HTML. Regex non è in grado di gestire i tag annidati. Supponendo un documento non contiene alcun tag nidificato, regex richiede ancora ogni tag siano correttamente chiusi.

Se si sta utilizzando PHP, per semplicità, vi consiglio vivamente di utilizzare DOM (Document Object Model) per analizzare / estrarre documenti HTML. biblioteca DOM di solito esiste in ogni linguaggio di programmazione.

Se stai cercando di parti estratto di una stringa non accompagnato da un'espressione regolare, si può semplicemente sostituire le parti che sono abbinato con una stringa vuota per lo stesso effetto.

Si noti che l'unica ragione per cui questo lavoro potrebbe perché i tag siete interessati a rimuovere, <script> e <style> tag, non possono essere nidificate.

Tuttavia, non è raro che un tag <script> per contenere il codice per livello di codice aggiungere un altro tag <script>, nel qual caso il vostro regex fallirà. Sarà anche fallire nel caso in cui un tag non è chiuso.

Non è possibile analizzare HTML con le espressioni regolari.

parsing del codice HTML con le espressioni regolari porta alla tristezza.

So che stai facendo solo per divertimento, ma ci sono così tanti pacchetti là fuori che in realtà fare l'analisi del modo giusto, e farlo in modo affidabile, e sono stati testati.

Non andare reinventare la ruota, e farlo un modo che è tutto, ma garantito per frustrare lungo la strada.

Per vostra informazione,

Invece di Regex, con jQuery, il suo possibile per estrarre il testo da solo da un tag HTML. Per questo si può utilizzare il seguente schema.

$("<div/>").html("#elementId").text()

È possibile fare riferimento questo JSFIDDLE

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