Domanda

Vorrei estrarre da una pagina HTML generale, tutto il testo (visualizzato o meno).

Vorrei rimuovere

  • eventuali tag HTML
  • Qualsiasi javascript
  • Qualsiasi stile CSS

Esiste un'espressione regolare (una o più) che lo raggiungerà?

È stato utile?

Soluzione

Non puoi davvero analizzare HTML con espressioni regolari. È troppo complesso Le RE non gestiranno le sezioni <![CDATA[ correttamente. Inoltre, alcuni tipi di cose HTML comuni come &lt;text> funzioneranno in un browser come testo corretto, ma potrebbero confondere un RE ingenuo.

Sarai più felice e di successo con un parser HTML adeguato. Le persone di Python usano spesso qualcosa Beautiful Soup per analizzare HTML e rimuovere tag e script.


Inoltre, i browser, in base alla progettazione, tollerano HTML non valido. Quindi spesso ti ritroverai a analizzare HTML che è chiaramente improprio, ma funziona bene in un browser.

Potresti essere in grado di analizzare HTML non valido con RE. Tutto ciò che richiede è pazienza e duro lavoro. Ma spesso è più semplice usare il parser di qualcun altro.

Altri suggerimenti

Rimuovi javascript e CSS:

<(script|style).*?</\1>

Rimuovi tag

<.*?>

Avevo bisogno di una soluzione regex ( in php ) che restituisse il testo normale (o meglio di) PHPSimpleDOM, solo molto più velocemente. Ecco la soluzione che mi è venuta in mente:

function plaintext($html)
{
    // remove comments and any content found in the the comment area (strip_tags only removes the actual tags).
    $plaintext = preg_replace('#<!--.*?-->#s', '', $html);

    // put a space between list items (strip_tags just removes the tags).
    $plaintext = preg_replace('#</li>#', ' </li>', $plaintext);

    // remove all script and style tags
    $plaintext = preg_replace('#<(script|style)\b[^>]*>(.*?)</(script|style)>#is', "", $plaintext);

    // remove br tags (missed by strip_tags)
    $plaintext = preg_replace("#<br[^>]*?>#", " ", $plaintext);

    // remove all remaining html
    $plaintext = strip_tags($plaintext);

    return $plaintext;
}

Quando l'ho provato su alcuni siti complicati (i forum sembrano contenere alcuni degli html più difficili da analizzare), questo metodo ha restituito lo stesso risultato del semplice testo PHPSimpleDOM, solo molto, molto più veloce. Ha anche gestito correttamente le voci dell'elenco (tag li), dove PHPSimpleDOM non lo ha fatto.

Per quanto riguarda la velocità:

  • SimpleDom: 0,03248 sec.
  • RegEx: 0.00087 sec.

37 volte più veloce!

Contemplare farlo con espressioni regolari è scoraggiante. Hai considerato XSLT? L'espressione XPath per estrarre tutti i nodi di testo in un documento XHTML, meno script & Amp; contenuto di stile, sarebbe:

//body//text()[not(ancestor::script)][not(ancestor::style)]

Usando la sintassi perl per definire le regex, un inizio potrebbe essere:

!<body.*?>(.*)</body>!smi

Quindi applicare il seguente rimpiazzo al risultato di quel gruppo:

!<script.*?</script>!!smi
!<[^>]+/[ \t]*>!!smi
!</?([a-z]+).*?>!!smi
/<!--.*?-->//smi

Questo ovviamente non formatterà le cose come un file di testo, ma rimuove tutto l'HTML (principalmente, ci sono alcuni casi in cui potrebbe non funzionare abbastanza bene). Un'idea migliore è quella di usare un parser XML in qualunque lingua tu stia usando per analizzare correttamente l'HTML ed estrarne il testo.

Il modo più semplice per HTML semplice (esempio in Python):

text = "<p>This is my> <strong>example</strong>HTML,<br /> containing tags</p>"
import re
" ".join([t.strip() for t in re.findall(r"<[^>]+>|[^<]+",text) if not '<' in t])

Restituisce questo:

'This is my> example HTML, containing tags'

Ecco una funzione per rimuovere anche i tag html più complessi.

function strip_html_tags( $text ) 
{

$text = preg_replace(
    array(
        // Remove invisible content
        '@<head[^>]*?>.*?</head>@siu',
        '@<style[^>]*?>.*?</style>@siu',
        '@<script[^>]*?.*?</script>@siu',
        '@<object[^>]*?.*?</object>@siu',
        '@<embed[^>]*?.*?</embed>@siu',
        '@<applet[^>]*?.*?</applet>@siu',
        '@<noframes[^>]*?.*?</noframes>@siu',
        '@<noscript[^>]*?.*?</noscript>@siu',
        '@<noembed[^>]*?.*?</noembed>@siu',

        // Add line breaks before & after blocks
        '@<((br)|(hr))@iu',
        '@</?((address)|(blockquote)|(center)|(del))@iu',
        '@</?((div)|(h[1-9])|(ins)|(isindex)|(p)|(pre))@iu',
        '@</?((dir)|(dl)|(dt)|(dd)|(li)|(menu)|(ol)|(ul))@iu',
        '@</?((table)|(th)|(td)|(caption))@iu',
        '@</?((form)|(button)|(fieldset)|(legend)|(input))@iu',
        '@</?((label)|(select)|(optgroup)|(option)|(textarea))@iu',
        '@</?((frameset)|(frame)|(iframe))@iu',
    ),
    array(
        ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
        "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0",
        "\n\$0", "\n\$0",
    ),
    $text );

// Remove all remaining tags and comments and return.
return strip_tags( $text );
    }

Se stai usando PHP, prova Simple HTML DOM, disponibile su SourceForge.

Altrimenti, Google html2text, e troverai una varietà di implementazioni per linguaggi diversi che fondamentalmente usano una serie di espressioni regolari per risucchiare tutto il markup. Fai attenzione qui, perché a volte possono essere lasciati tag senza finali, così come caratteri speciali come & Amp; (che è & amp; amp;).

Inoltre, fai attenzione ai commenti e Javascript, poiché ho scoperto che è particolarmente fastidioso gestire le espressioni regolari e perché generalmente preferisco lasciare che un parser gratuito faccia tutto il lavoro per me.

Né certo questa pagina potrebbe essere d'aiuto.

Non puoi semplicemente usare il controllo WebBrowser disponibile con C #?

        System.Windows.Forms.WebBrowser wc = new System.Windows.Forms.WebBrowser();
        wc.DocumentText = "<html><body>blah blah<b>foo</b></body></html>";
        System.Windows.Forms.HtmlDocument h = wc.Document;
        Console.WriteLine(h.Body.InnerText);
string decode = System.Web.HttpUtility.HtmlDecode(your_htmlfile.html);
                Regex objRegExp = new Regex("<(.|\n)+?>");
                string replace = objRegExp.Replace(g, "");
                replace = replace.Replace(k, string.Empty);
                replace.Trim("\t\r\n ".ToCharArray());

then take a label and do "label.text=replace;" see on label out put

.

Credo che tu possa semplicemente fare

document.body.innerText

Che restituirà il contenuto di tutti i nodi di testo nel documento, visibile o no.

[edit (olliej): sigh non importa, funziona solo in Safari e IE, e non posso preoccuparmi di scaricare un firefox ogni notte per vedere se esiste nel trunk: - /]

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