Вопрос

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

Я бы хотел удалить

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

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

Это было полезно?

Решение

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

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


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

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

Другие советы

Удалите javascript и CSS:

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

Удалить теги

<.*?>

Требовалось решение с регулярным выражением (в 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 plaintext, только намного, намного быстрее.Он также правильно обрабатывал элементы списка (теги li), чего не делал PHPSimpleDOM.

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

  • Простой мир:0,03248 сек.
  • Регулярное выражение:0,00087 сек.

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

Мысль о том, чтобы сделать это с помощью регулярных выражений, пугает.Рассматривали ли вы XSLT?Выражение XPath для извлечения всех текстовых узлов в документе XHTML, за вычетом содержимого script & style, будет следующим:

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

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

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

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

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

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

Самый простой способ для простого 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'

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

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

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

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

И не уверен эта страница могло бы помочь.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top