регулярное выражение для извлечения текста из HTML

Я хотел бы извлечь из общей HTML-страницы весь текст (отображается или нет).

Я хочу удалить

  • любые HTML-теги
  • любой javascript
  • любые стили CSS

есть ли регулярное выражение (одно или несколько), которое достигнет этого?

12 ответов


вы не можете разбирать HTML с регулярными выражениями. Это слишком сложно. RE не справится <![CDATA[ разделы правильно вообще. Кроме того, некоторые виды общих HTML-вещей, таких как &lt;text> будет работать в браузере как правильный текст, но может сбить с толку наивный RE.

вы будете счастливее и успешнее с правильным синтаксическим анализатором HTML. Люди Python часто используют что-то Красивый Суп для разбора HTML и удаления тегов и скриптов.


кроме того, браузеры, по дизайну, допускайте искаженный HTML. Таким образом, вы часто будете пытаться разобрать HTML, что явно неправильно, но работает нормально в браузере.

возможно, вы сможете разобрать плохой HTML с RE. Все, что требуется, - это терпение и упорный труд. Но часто проще использовать чужой парсер.


удалить javascript и CSS:

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

удалить теги

<.*?>

требуется решение regex (в php), который вернет обычный текст так же хорошо (или лучше, чем) PHPSimpleDOM, только намного быстрее. Вот решение, которое я придумал:

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

когда я тестировал это на некоторых сложных сайтах (форумы, похоже, содержат некоторые из более жестких html для анализа), Этот метод вернул тот же результат, что и открытый текст PHPSimpleDOM, только намного быстрее. Он также правильно обработал элементы списка (теги li), где PHPSimpleDOM сделал не.

что касается скорости:

  • SimpleDom: 0.03248 сек.
  • регулярное выражение: 0.00087 сек.

37 раз быстрее!


созерцание этого с регулярными выражениями является сложным. Вы рассматривали XSLT? Выражение XPath для извлечения всех текстовых узлов в документе XHTML, за вычетом содержимого скрипта и стиля, будет:

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

вот функция для удаления даже самых сложных тегов 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 );
    }

используя синтаксис perl для определения регулярных выражений, начало может быть:

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

затем примените следующую замену к результату этой группы:

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

это, конечно, не будет форматировать вещи красиво как текстовый файл, но он удаляет все HTML (в основном, есть несколько случаев, когда он может работать не совсем правильно). Однако лучше использовать синтаксический анализатор XML на любом языке, который вы используете для правильного анализа HTML и извлечения текста из него.


Если вы используете PHP, попробуйте простой HTML DOM, доступный в SourceForge.

в противном случае, Google html2text, и вы найдете множество реализаций для разных языков, которые в основном используют серию регулярных выражений, чтобы высосать всю разметку. Будьте осторожны здесь, потому что теги без окончаний, иногда могут быть оставлены, а также специальные символы, такие как & (который &).

кроме того, следите за комментариями и Javascript, как я обнаружил, это особенно раздражает иметь дело с регулярными выражениями, и почему я обычно просто предпочитаю, чтобы бесплатный парсер делал всю работу за меня.


Не уверен на этой странице могу помочь.


самый простой способ для простого HTML (пример в 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])

возвращает это:

'This is my> example HTML, containing tags'

не можете ли вы просто использовать элемент управления WebBrowser, доступный с 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

.


Я верю, что вы можете просто сделать

document.body.innerText

который вернет содержимое всех текстовых узлов в документе, видимых или нет.

[edit (olliej):вздох nevermind, это работает только в Safari и IE, и я не могу беспокоиться о загрузке firefox каждую ночь, чтобы увидеть, существует ли он в багажнике: -/]