C # 정규식을 사용하여 HTML 태그 제거


139

C # 정규식을 사용하여 꺾쇠 괄호를 포함한 모든 HTML 태그를 바꾸거나 제거하려면 어떻게합니까? 누군가 코드를 도와 줄 수 있습니까?



당신은 그것을 나타내지는 않지만 태그와 태그를 제거하는 것이 아니라 스크립트와 스타일 요소를 완전히 제거하고 싶다고 추론하고 있습니다. 아래의 HTML Agility Pack 답변은 태그를 제거하는 데는 정확하지만 스크립트와 스타일을 제거하려면 stackoverflow.com/questions/13441470/…
John

1
복제본으로 표시된 질문에는 많은 정보 (및 Tony the Pony!)가 있지만 모든 태그가 아니라 태그 만 열도록 요청했습니다. 따라서 기술적으로 중복인지 확실하지 않습니다. 대답은 동일합니다.
goodeye

답변:


154

이전에 자주 언급했듯이 정규식을 사용하여 XML 또는 HTML 문서를 처리해서는 안됩니다. 중첩 된 구조를 일반적인 방식으로 표현할 수있는 방법이 없기 때문에 HTML 및 XML 문서에서 잘 수행되지 않습니다.

다음을 사용할 수 있습니다.

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

이것은 대부분의 경우 작동하지만 예상대로 작동하지 않는 경우 (예 : 꺾쇠 괄호가 포함 된 CDATA)가 있습니다.


13
이것은 순진한 구현입니다. 즉, <div id = "x <4>">는 불행히도 유효한 html입니다. 대부분의 제정신 사건을 처리합니다 ..
Ryan Emerle

8
언급 한 바와 같이,이 표현은 어떤 경우에는 실패 할 것임을 알고 있습니다. 일반적인 경우를 오류없이 정규 표현식으로 처리 할 수 ​​있는지 확실하지 않습니다.
Daniel Brückner

1
모든 경우에 이것이 실패하지는 않습니다! 욕심.
Jake

13
@Cipher, 왜 탐욕이 문제라고 생각합니까? 일치하는 HTML 태그가 시작될 때 일치한다고 가정하면 해당 태그의 끝을 넘어 확장되지 않습니다. 그것이 [^>]의 목적입니다.
Alan Moore

1
@AlanMoore html은 "일반 언어"가 아닙니다. 즉, 유효한 html 인 모든 것을 정규 표현식과 올바르게 일치시킬 수 없습니다. 참조 : stackoverflow.com/questions/590747/...
Kache

78

정답은 그렇지 않습니다 . HTML 민첩성 팩을 사용하십시오 .

추가하기 위해 편집 :

jesse가 아래의 코멘트에서 뻔뻔스럽게 훔치지 않고 이번에 질문에 부적절하게 대답했다는 비난을 피하기 위해 HTML 민첩성 팩을 사용하는 간단하고 신뢰할 수있는 스 니펫이 있습니다.

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 해커에 노출되지 않도록하십시오.


27
HTML 민첩성 팩은 HTML 작업과 관련된 모든 것에 대한 답이 아닙니다 (예 : HTML 코드 조각으로 만 작업하려면 어떻게해야합니까?!).
PropellerHead

7
HTML 조각과 잘 작동하며 원본 포스터에서 설명한 시나리오에 가장 적합한 옵션입니다. 반면에 정규 표현식은 이상적인 HTML로만 작동하며 HTML 문법이 규칙적이지 않기 때문에 완벽하게 유효한 HTML로 중단됩니다. 그가 Ruby를 사용하고 있다면, 나는 여전히 nokogiri 나 hpricot, 또는 Python을위한 beautifulsoup을 제안했을 것입니다. 문법이없는 임의의 텍스트 스트림이 아닌 HTML과 같은 HTML을 처리하는 것이 가장 좋습니다.
JasonTrue

1
HTML은 정규 문법이 아니므로 정규 표현식으로 만 구문 분석 할 수 없습니다. 렉싱에는 정규식을 사용할 수 있지만 구문 분석에는 사용할 수 없습니다. 정말 간단합니다. 언어 학자들은 HTML이 존재하기 전에 이에 동의했을 것입니다.
JasonTrue

20
이것은 의견의 문제가 아닙니다. 정규 표현식은 대부분의 시간에 원하는 것을 얻을 수 있지만 매우 일반적인 경우에는 실패합니다. HTML Agility Pack보다 더 나은 / 빠른 파서를 찾을 수 있다면 갈아 타십시오. 그러나 세상이 더 깨진 HTML 해커에 노출되지 않도록하십시오.
JasonTrue

2
HTML을 구문 분석하지 않으면 HTML 태그를 정확하게 식별 할 수 없습니다. HTML의 모든 문법을 이해하십니까? 다른 답변에서 제안하는 "거의 가깝게"얻기 위해 사악한 해킹을 확인하고 왜 유지해야하는지 알려주십시오. 샘플 입력에 대한 해키 빠른 시도가 작동하기 때문에 저에게 투표는 솔루션을 올바르게 만들 수 없습니다. HTML 콘텐츠에서 보고서를 생성하거나 정규식을 사용하여 CSS 참조를 수정하기 위해 정규 표현식을 사용했습니다. & gt; 오류 가능성을 제한하기 위해 추가 검증을 수행했습니다. 일반적인 목적이 아니 었습니다.
JasonTrue

38

질문이 너무 광범위하여 결정적으로 대답 할 수 없습니다. 웹 페이지와 같은 실제 HTML 문서에서 모든 태그를 제거하는 것에 대해 이야기하고 있습니까? 그렇다면 다음을 수행해야합니다.

  • <! DOCTYPE 선언 또는 존재하는 경우 <? xml 프롤로그를 제거하십시오.
  • 모든 SGML 주석 제거
  • 전체 HEAD 요소 제거
  • 모든 SCRIPT 및 STYLE 요소를 제거하십시오.
  • FORM 및 TABLE 요소로 Grabthar-knows-what을 수행
  • 남은 태그를 제거
  • CDATA 섹션에서 <! [CDATA [and]]> 시퀀스를 제거하되 내용은 그대로 두십시오.

그것은 내 머리 꼭대기에 있습니다. 더 많은 것이있을 것입니다. 모든 것을 마치면 어떤 곳에서는 단어, 문장 및 단락이 결합되고 다른 곳에서는 쓸모없는 공백이 생깁니다.

그러나 조각으로 만 작업하고 모든 태그를 제거하는 것으로 벗어날 수 있다고 가정하면 여기에 사용할 정규 표현식이 있습니다.

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

작은 따옴표와 큰 따옴표로 묶은 문자열을 다른 방법으로 일치 시키면 속성 값의 꺾쇠 괄호 문제를 해결할 수 있습니다. Ryan의 답변에있는 정규 표현식과 같이 태그 내부의 속성 이름 및 기타 항목을 명시 적으로 일치시킬 필요가 없습니다. 첫 번째 대안은이 모든 것을 처리합니다.

이러한 (?>...)구조 에 대해 궁금한 경우 원자 그룹 입니다. 정규식을 좀 더 효율적으로 만들지 만 더 중요한 점은 런 어웨이 역 추적을 방지하는 것입니다. 나는 그것이 그것이 여기서 문제가 될 것이라고 생각하지 않지만, 그것을 언급하지 않으면 다른 누군가가 알 것입니다. ;-)

이 정규 표현식은 물론 완벽하지는 않지만 필요한만큼 좋을 것입니다.


1
이것이 가장 좋은 대답입니다. 포스터의 질문에 답하고 주어진 작업에 정규식을 사용해서는 안되는 이유를 설명하십시오. 잘 했어.
JWilliams 2012 년

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

출처


18

@JasonTrue는 HTML 태그 제거가 정규식을 통해 수행되지 않아야한다는 것이 맞습니다.

HtmlAgilityPack을 사용하여 HTML 태그를 제거하는 것은 매우 간단합니다.

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

1
나는 이것에 대해 조금 늦었지만 Word 및 다른 사무용 제품과 같은 XML에서도 작동한다고 언급하고 싶습니다. Word xml을 다루어야 할 필요가있는 사람은이 기능을 사용하는 것이 좋습니다. 특히 내가 필요로하는 내용에서 태그를 제거 해야하는 경우 특히 도움이되기 때문입니다.
Steve Pettifer

다른 모든 것이 실패한 것처럼 보였을 때이 간단한 코드 스 니펫이 하루를 절약했습니다. 감사!
Ted Krapf

14

때로는 Html을 순진하게 구문 분석하고 텍스트 내용을 꺼내야하지만 Jason의 응답을 에코하고 싶습니다.

풍부한 텍스트 편집기, 항상 재미와 게임으로 만든 일부 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"
    }

1
명백한 크로스 플랫폼 줄 바꿈 문제와는 달리 내용이 구분 될 때 불확실한 수량자를 갖는 것은 느립니다. 첫 번째와 마지막에 수정 자 <xml>.*(?!</xml>)</xml>와 같은 것을 사용하십시오 . 첫 번째 태그는 첫 번째 태그 이름에서 캡처 된 대체와 네거티브 lookahead 및 최종 태그에서 역 참조로 결합 될 수도 있습니다. RegexOptions.SingleLine<[^>]*>
ChrisF

5

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

3

이것을 사용하십시오 ..

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


-1

이 방법을 사용하여 태그를 제거하십시오.

public string From_To(string text, string from, string to)
{
    if (text == null)
        return null;
    string pattern = @"" + from + ".*?" + to;
    Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    MatchCollection matches = rx.Matches(text);
    return matches.Count <= 0 ? text : matches.Cast<Match>().Where(match => !string.IsNullOrEmpty(match.Value)).Aggregate(text, (current, match) => current.Replace(match.Value, ""));
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.