Wyrażenie regularne do wyodrębniania tekstu z HTML

Chciałbym wyodrębnić z ogólnej strony HTML cały tekst (wyświetlany lub nie).

Chciałbym usunąć

  • dowolne znaczniki HTML
  • dowolny javascript
  • dowolne style CSS

Czy istnieje wyrażenie regularne (jedno lub więcej), które to osiągnie?

Author: Charles Stewart, 2008-10-08

12 answers

Nie możesz analizować HTML za pomocą wyrażeń regularnych. To zbyt skomplikowane. RE w ogóle nie obsługuje sekcji <![CDATA[ poprawnie. Co więcej, niektóre typowe rzeczy HTML, takie jak &lt;text>, będą działać w przeglądarce jako właściwy tekst, ale mogą zaskoczyć naiwnego RE.

Będziesz szczęśliwszy i bardziej udany dzięki odpowiedniemu parserowi HTML. Ludzie Pythona często używają czegoś Beautiful Soup do analizowania HTML i usuwania tagów i skryptów.


Również przeglądarki, z założenia, tolerują wady HTML. Tak więc często będziesz próbował parsować HTML, który jest wyraźnie niewłaściwy, ale zdarza się, że działa dobrze w przeglądarce.

Możesz być w stanie przeanalizować zły HTML z RE. wszystko, co wymaga to cierpliwości i ciężkiej pracy. Ale często łatwiej jest użyć cudzego parsera.

 11
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-28 02:00:25

Usuń javascript i CSS:

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

Usuń tagi

<.*?>
 12
Author: nickf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 01:53:36

Potrzebne jest rozwiązanie regex (w php), które zwróci zwykły tekst równie dobrze (lub lepiej niż) PHPSimpleDOM, tylko znacznie szybciej. Oto rozwiązanie, które wymyśliłem:

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

Kiedy testowałem to na niektórych skomplikowanych stronach (fora wydają się zawierać niektóre z trudniejszych do przetworzenia html), ta metoda zwróciła ten sam wynik co tekst jawny phpsimpledom, tylko znacznie, znacznie szybciej. Poprawnie obsĹ 'ugiwaĺ' rĂłwnieĹź elementy listy (znaczniki li), gdzie PHPSimpleDOM nie.

Co do prędkość:

  • Czas generowania: 0.03248 sek.
  • RegEx: 0.00087 sek.

37 razy szybciej!

 6
Author: Joe Bergevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-26 17:04:23

Kontemplowanie tego za pomocą wyrażeń regularnych jest zniechęcające. Rozważałeś XSLT? Wyrażenie XPath, aby wyodrębnić wszystkie węzły tekstowe w dokumencie XHTML, minus zawartość skryptu i stylu, to:

//body//text()[not(ancestor::script)][not(ancestor::style)]
 3
Author: Chris Noe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 12:38:51

Oto funkcja do usuwania nawet najbardziej złożonych znaczników html.

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 );
    }
 2
Author: Ayush,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-09 10:14:27

Używając składni Perla do definiowania wyrażeń regularnych, początek może być następujący:

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

Następnie stosując następujące zastąpienie do wyniku tej grupy:

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

To oczywiście nie sformatuje rzeczy ładnie jako plik tekstowy, ale usuwa cały HTML(w większości przypadków jest kilka przypadków, w których może to nie działać prawidłowo). Lepszym pomysłem jest jednak użycie parsera XML w dowolnym języku, którego używasz, aby poprawnie przeanalizować HTML i wyodrębnić z niego tekst.

 1
Author: Matthew Scharley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 01:51:37

Jeśli używasz PHP, spróbuj prostego HTML DOM, dostępnego na SourceForge.

W Przeciwnym Razie Google html2text, a znajdziesz wiele implementacji dla różnych języków, które zasadniczo używają serii wyrażeń regularnych, aby wyssać wszystkie znaczniki. Bądź ostrożny, ponieważ czasem można pozostawić znaczniki bez zakończeń, a także znaki specjalne, takie jak & (czyli&).

Uważaj również na komentarze i Javascript, ponieważ uważam, że jest to szczególnie denerwujące, aby radzić sobie z wyrażeniami regularnymi i dlaczego generalnie wolę pozwolić darmowemu parserowi wykonać całą pracę za mnie.

 1
Author: Robert Elwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 01:51:56

No sure ta strona może pomóc.

 1
Author: unigogo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-01 08:10:40

Najprostszy sposób na prosty HTML (przykład w Pythonie):

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])

Zwraca to:

'This is my> example HTML, containing tags'
 1
Author: David Avsajanishvili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-21 19:04:39

Nie możesz po prostu użyć kontrolki WebBrowser dostępnej w 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);
 1
Author: Shiroy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-01 13:59:05
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

.

 1
Author: mahesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-03 05:54:50

I believe you can just do

document.body.innerText

Który zwróci zawartość wszystkich węzłów tekstu w dokumencie, widocznych lub nie.

[edit (olliej): sigh nevermind, to działa tylko w Safari i IE, a mi nie przeszkadza ściąganie Firefoksa, żeby sprawdzić czy istnieje w bagażniku : -/]

 0
Author: olliej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-08 02:38:20