web-dev-qa-db-ja.com

C#正規表現を使用してHTMLタグを削除する

C#正規表現を使用して、山括弧を含むすべてのHTMLタグを置換/削除するにはどうすればよいですか?誰かがコードを手伝ってくれますか?

136
Steve

前述のように、XMLドキュメントまたはHTMLドキュメントの処理に正規表現を使用しないでください。ネストされた構造を一般的な方法で表現する方法がないため、HTMLおよびXMLドキュメントではあまりうまく機能しません。

以下を使用できます。

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);

これはほとんどの場合に機能しますが、これが期待どおりに機能しない場合(山括弧を含むCDATAなど)があります。

148

正解はそうしないで、 HTML Agility Pack を使用してください。

追加して編集:

以下のjesseのコメントから恥知らずに盗み、この質問に不適切に答えていると非難されるのを避けるために、HTMLの最も不完全で気まぐれなHTMLでも機能するHTML Agility Packを使用したシンプルで信頼できるスニペットを以下に示します。

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());

HTMLは、非伝統的な正規表現エンジンでさえ提供するのが非常に苦痛なコンテキスト認識なしでは正しく解析できないため、HTMLの解析に正規表現を使用するための防御可能なケースはほとんどありません。 RegExを使用するとそこに到達できますが、手動で確認する必要があります。

Html Agility Packは、HTMLをコンテキストフリーの文法として単純に扱うことによって生じる可能性のある異常を手動で修正する必要性を減らす堅牢なソリューションを提供できます。

正規表現を使用すると、ほとんどの場合に必要なものを取得できますが、非常に一般的なケースでは失敗します。 HTML Agility Packよりも優れた/高速なパーサーを見つけることができれば、それを選択してください。しかし、壊れたHTMLハッカーを世界にさらさないでください。

78
JasonTrue

質問は広すぎて、明確に答えることができません。 Webページのような実際のHTMLドキュメントからすべてのタグを削除することについて話しているのですか?もしそうなら、あなたはする必要があります:

  • <!DOCTYPE宣言または<?xmlプロローグが存在する場合は削除します
  • すべてのSGMLコメントを削除します
  • HEAD要素全体を削除します
  • すべてのSCRIPTおよびSTYLE要素を削除します
  • fORMおよびTABLE要素でGrabthar-knows-whatを実行します
  • 残りのタグを削除します
  • cDATAセクションから<![CDATA [および]]>シーケンスを削除しますが、その内容はそのままにします

それは私の頭のてっぺんから外れているだけです。きっともっとあるはずです。これらすべてを実行すると、単語、文、段落がいくつかの場所で一緒に実行され、他の場所では役に立たない空白の大きな塊になってしまいます。

ただし、フラグメントだけで作業しており、すべてのタグを削除するだけで済むと仮定すると、ここで使用する正規表現は次のとおりです。

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"

属性値の不等号括弧の問題に対処するには、単一引用符と二重引用符で囲まれた文字列を独自の選択肢で一致させるだけで十分です。 Ryanの答えの正規表現のように、タグ内の属性名やその他のものを明示的に一致させる必要はありません。最初の選択肢がすべてを処理します。

これらの(?>...)コンストラクトについて疑問に思っている場合、それらは 原子グループ です。それらは正規表現をもう少し効率的にしますが、もっと重要なことは、暴走バックトラッキングを防ぐことです。私はそれがここで問題になるとは本当に思いませんが、私がそれについて言及しなければ、他の誰かがそうするでしょう。 ;-)

もちろん、この正規表現は完璧ではありませんが、おそらくあなたが必要とするのと同じくらい良いでしょう。

37
Alan Moore
Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);

ソース

25
Ryan Emerle

@JasonTrueは正しいです。HTMLタグの除去は正規表現を介して行われるべきではありません。

HtmlAgilityPackを使用してHTMLタグを削除するのは非常に簡単です。

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}
17
zzzzBov

Jasonの応答をエコーし​​たいのですが、Htmlを単純に解析してテキストコンテンツを取り出す必要がある場合があります。

リッチテキストエディターによって作成されたHtmlを使用してこれを行う必要がありました。常に楽しいゲームです。

この場合、タグ自体だけでなく、一部のタグのコンテンツも削除する必要がある場合があります。

私の場合、タグはこのミックスにスローされました。私の(非常にわずかな)素朴な実装が有用な出発点であると感じる人もいるかもしれません。

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }
13
CountZero

次のURLで正規表現の方法を試してください: http://www.dotnetperls.com/remove-html-tags

/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}
5
Owidat

これを使って..

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"
3
Swaroop

.+?<[^>]*>を追加し、この正規表現を試してください( this に基づいてください):

<[^>].+?>

c#.net regex demoenter image description here

2
GRUNGER