Pregunta

Me gustaría extraer de una página HTML general, todo el texto (mostrado o no).

Me gustaría eliminar

  • cualquier etiqueta HTML
  • Cualquier javascript
  • Cualquier estilo CSS

¿Hay alguna expresión regular (una o más) que logre eso?

¿Fue útil?

Solución

Realmente no puedes analizar HTML con expresiones regulares. Es muy complejo Los RE no manejarán <![CDATA[ secciones correctamente en absoluto. Además, algunos tipos de elementos HTML comunes como &lt;text> funcionarán en un navegador como texto adecuado, pero podrían desconcertar a un ingenuo RE.

Serás más feliz y más exitoso con un analizador HTML adecuado. La gente de Python a menudo usa algo Beautiful Soup para analizar HTML y eliminar etiquetas y secuencias de comandos.


Además, los navegadores, por diseño, toleran HTML con formato incorrecto. Por lo tanto, a menudo te encontrarás tratando de analizar HTML que es claramente incorrecto, pero que funciona bien en un navegador.

Es posible que pueda analizar HTML incorrecto con RE. Todo lo que requiere es paciencia y trabajo duro. Pero a menudo es más sencillo usar el analizador de otra persona.

Otros consejos

Eliminar javascript y CSS:

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

Eliminar etiquetas

<.*?>

Necesitaba una solución de expresiones regulares ( en php ) que devolviera el texto plano igual de bien (o mejor que) PHPSimpleDOM, solo que mucho más rápido. Aquí está la solución que se me ocurrió:

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;
}

Cuando probé esto en algunos sitios complicados (los foros parecen contener algunos de los html más difíciles de analizar), este método arrojó el mismo resultado que el texto sin formato PHPSimpleDOM, solo que mucho, mucho más rápido. También manejó los elementos de la lista (etiquetas li) correctamente, donde PHPSimpleDOM no lo hizo.

En cuanto a la velocidad:

  • SimpleDom: 0.03248 seg.
  • RegEx: 0.00087 seg.

¡37 veces más rápido!

Contemplar hacer esto con expresiones regulares es desalentador. ¿Has considerado XSLT? La expresión XPath para extraer todos los nodos de texto en un documento XHTML, menos script & Amp; contenido de estilo, sería:

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

Usando la sintaxis perl para definir las expresiones regulares, un comienzo podría ser:

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

Luego aplicando el siguiente reemplazo al resultado de ese grupo:

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

Esto, por supuesto, no formateará bien las cosas como un archivo de texto, pero elimina todo el HTML (principalmente, hay algunos casos en los que podría no funcionar del todo bien). Sin embargo, una mejor idea es utilizar un analizador XML en cualquier idioma que esté utilizando para analizar el HTML correctamente y extraer el texto de eso.

La forma más simple para HTML simple (ejemplo en 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])

Devuelve esto:

'This is my> example HTML, containing tags'

Aquí hay una función para eliminar incluso las etiquetas html más complejas.

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 );
    }

Si está usando PHP, pruebe con HTML simple DOM, disponible en SourceForge.

De lo contrario, Google html2text, y encontrará una variedad de implementaciones para diferentes lenguajes que básicamente usan una serie de expresiones regulares para absorber todo el marcado. Tenga cuidado aquí, porque a veces se pueden dejar etiquetas sin terminaciones, así como caracteres especiales como & Amp; (que es & amp; amp;).

Además, tenga cuidado con los comentarios y Javascript, ya que he encontrado que es particularmente molesto tratar con expresiones regulares, y por qué generalmente prefiero dejar que un analizador gratuito haga todo el trabajo por mí.

Tampoco estoy seguro de que esta página pueda ayudar.

¿No puedes usar el control WebBrowser disponible 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

.

Creo que puedes hacer

document.body.innerText

Que devolverá el contenido de todos los nodos de texto en el documento, visible o no.

[edit (olliej): suspiro no importa, esto solo funciona en Safari e IE, y no me molesto en descargar un firefox todas las noches para ver si existe en el tronco: - /]

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top