Pergunta

Eu gostaria de extrair de uma página HTML geral, todo o texto (exibido ou não).

Eu gostaria de remover

  • Quaisquer tags HTML
  • Qualquer javascript
  • Quaisquer estilos CSS

Existe uma expressão regular (uma ou mais) que conseguirá isso?

Foi útil?

Solução

Você não pode realmente analisar o HTML com expressões regulares. É muito complexo. Re está <![CDATA[ seções corretamente. Além disso, alguns tipos de coisas comuns de HTML como &lt;text> Funcionará em um navegador como texto adequado, mas poderá confundir um RE ingênuo.

Você ficará mais feliz e mais bem -sucedido com um analisador HTML adequado. As pessoas do python costumam usar algo Linda sopa Para analisar HTML e tirar tags e scripts.


Além disso, os navegadores, por design, toleram HTML malformados. Então, você geralmente se vê tentando analisar o HTML, o que é claramente impróprio, mas funciona bem em um navegador.

Você pode analisar o HTML ruim com RE. Tudo o que requer é paciência e trabalho duro. Mas muitas vezes é mais simples usar o analisador de outra pessoa.

Outras dicas

Remova JavaScript e CSS:

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

Remova tags

<.*?>

Precisava de uma solução regex (em php) isso retornaria o texto simples da mesma forma (ou melhor que) phpsimpledom, apenas muito mais rápido. Aqui está a solução que eu criei:

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 testei isso em alguns sites complicados (os fóruns parecem conter parte do HTML mais difícil para analisar), esse método retornou o mesmo resultado que o texto simples phpsimpledom, apenas muito, muito mais rápido. Ele também lidou com os itens da lista (tags Li) corretamente, onde o phpsimpledom não.

Quanto à velocidade:

  • SimpleDom: 0,03248 seg.
  • Regex: 0,00087 seg.

37 vezes mais rápido!

Contenção de fazer isso com expressões regulares é assustador. Você já considerou o XSLT? A expressão do XPath para extrair todos os nós de texto em um documento XHTML, menos script e conteúdo de estilo, seria:

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

Usando a sintaxe Perl para definir as regexes, um começo pode ser:

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

Em seguida, aplicando a seguinte substituição ao resultado desse grupo:

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

É claro que isso não formará as coisas bem como um arquivo de texto, mas retira todo o HTML (principalmente, há alguns casos em que pode não funcionar bem). Uma idéia melhor é usar um analisador XML em qualquer idioma que você estiver usando para analisar o HTML corretamente e extrair o texto disso.

A maneira mais simples de simples html (exemplo no 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])

Retorna isto:

'This is my> example HTML, containing tags'

Aqui está uma função para remover as tags HTML mais complexas.

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 você estiver usando o PHP, tente o simples HTML DOM, disponível no SourceForge.

Caso contrário, o Google HTML2Text e você encontrará uma variedade de implementações para diferentes idiomas que basicamente usam uma série de expressões regulares para sugar toda a marcação. Cuidado aqui, porque as tags sem finais às vezes podem ser deixadas, bem como caracteres especiais como & (que é &).

Além disso, cuidado com os comentários e o JavaScript, pois achei particularmente irritante lidar com expressões regulares e por que geralmente prefiro deixar um analisador gratuito fazer todo o trabalho por mim.

Nem com certeza esta página Poderia ajudar.

Você não pode simplesmente usar o controle WebBrowser disponível com 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

.

Eu acredito que você pode simplesmente fazer

document.body.innerText

Que retornará o conteúdo de todos os nós de texto no documento, visível ou não.

Edit (Olliej): suspirar Não esquece, isso só funciona no Safari e no IE, e não posso me incomodar em baixar um Firefox todas as noites para ver se ele existe no porta-malas:-/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top