سؤال

أرغب في الاستخراج من صفحة HTML العامة ، كل النص (معروض أم لا).

وأود أن إزالة

  • أي علامات HTML
  • أي جافا سكريبت
  • أي أنماط CSS

هل هناك تعبير منتظم (واحد أو أكثر) سيحقق ذلك؟

هل كانت مفيدة؟

المحلول

لا يمكنك حقًا تحليل HTML مع تعبيرات منتظمة. إنه معقد للغاية. لن يتعامل مع <![CDATA[ أقسام بشكل صحيح على الإطلاق. علاوة على ذلك ، مثل بعض أنواع HTML المشتركة مثل &lt;text> سيعمل في متصفح كنص مناسب ، ولكن قد يربك عملية إعادة ساذجة.

ستكون أكثر سعادة وأكثر نجاحًا مع محلل HTML المناسب. غالبًا ما يستخدم الناس Python شيئًا حساء جميل لتحليل HTML وتجريد العلامات والبرامج النصية.


أيضا ، المتصفحات ، حسب التصميم ، تحمل HTML المشوهة. لذلك ستجد نفسك في كثير من الأحيان تحاول تحليل HTML وهو غير لائق بشكل واضح ، ولكن يحدث أن تعمل بشكل جيد في متصفح.

قد تكون قادرًا على تحليل HTML السيئ مع RE. كل ما يتطلبه الأمر هو الصبر والعمل الجاد. ولكن من الأسهل في كثير من الأحيان استخدام محلل شخص آخر.

نصائح أخرى

قم بإزالة JavaScript و CSS:

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

إزالة العلامات

<.*?>

تحتاج إلى حل Regex (في PHP) من شأنه أن يعيد النص العادي تمامًا (أو أفضل من) phpsempledom ، أسرع بكثير. هذا هو الحل الذي توصلت إليه:

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 الأكثر صرامة للحالة) ، أعادت هذه الطريقة نفس النتيجة الناتجة عن نص phpsempledom ، وأسرع بكثير وأسرع بكثير. كما تعامل مع عناصر القائمة (علامات LI) بشكل صحيح ، حيث لم يفعل phpsempledom.

أما بالنسبة للسرعة:

  • Simpledom: 0.03248 ثانية.
  • Regex: 0.00087 ثانية.

37 مرة أسرع!

التفكير في القيام بذلك مع التعبيرات العادية أمر شاق. هل فكرت في XSLT؟ سيكون تعبير XPath لاستخراج جميع العقد النصية في مستند XHTML ، ناقص محتوى البرنامج النصي والأناقة ،:

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

باستخدام بناء جملة Perl لتحديد regexes ، قد تكون البداية:

!<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 ، جرب Simple HTML DOM ، متاح في SourceForge.

بخلاف ذلك ، ستجد Google HTML2Text ، وستجد مجموعة متنوعة من التطبيقات للغات المختلفة التي تستخدم بشكل أساسي سلسلة من التعبيرات العادية لامتصاص جميع العلامات. كن حذرًا هنا ، لأنه يمكن في بعض الأحيان ترك العلامات بدون نهايات ، وكذلك الشخصيات الخاصة مثل & (التي هي &).

أيضًا ، احترس من التعليقات و JavaScript ، حيث وجدت أنه من المزعج بشكل خاص التعامل معها للتعبيرات العادية ، ولماذا أفضّل عمومًا السماح لمحلل مجاني بعمل كل العمل بالنسبة لي.

ولا بالتأكيد هذه الصفحة يمكن ان تساعد.

ألا يمكنك فقط استخدام التحكم في 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): تنهد فما باللك ، هذا يعمل فقط في Safari و IE ، ولا يمكن أن أزعجني تنزيل Firefox Nightly لمعرفة ما إذا كان موجودًا في Trunk:-/

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top