정규 표현식을 사용하여 HTML 구문 분석 : 왜 안되나요?


207

asker가 HTML에서 일부 정보를 가져 오기 위해 정규식을 사용하는 stackoverflow에 대한 모든 질문은 필연적으로 HTML을 구문 분석하기 위해 정규식을 사용하지 않는다는 "응답"을 갖습니다.

왜 안돼? Beautiful Soup 과 같이 인용 부호가없는 "실제"HTML 파서가 있다는 것을 알고 있으며 , 강력하고 유용하다고 확신하지만, 간단하고 빠르거나 더러운 일을하는 이유는 무엇입니까? 몇 가지 정규 표현식 문이 제대로 작동 할 때 너무 복잡한 것을 사용하는 것을 귀찮게합니까?

또한, 정규 표현식에 대해 이해하지 못하는 근본적인 것이 있습니까? 일반적으로 구문 분석하기에 나쁜 선택입니다.



23
Chuck Norris만이 정규 표현식으로 HTML을 구문 분석 할 수 있기 때문에 (이 유명한 Zalgo에 설명 된대로 : stackoverflow.com/questions/1732348/… ).
takeshin

1
이 질문은 어떻게 든 관련이있는 다른 것을 요구하도록 자극했습니다. 관심이있는 경우 : 정규식을 사용하여 HTML / XML을 구문 분석 할 수없는 이유 : 일반인의 용어로 공식 설명
mac


이 질문은 "공통 유효성 검사 작업" 에서 스택 오버플로 정규 표현식 FAQ 에 추가되었습니다 .
aliteralmind

답변:


212

정규 표현식에서는 전체 HTML 구문 분석을 수행 할 수 없습니다. 정규 표현식에서는 불가능한 여는 태그와 닫는 태그의 일치에 따라 달라집니다.

정규식은 정규 언어 와 만 일치 할 수 있지만 HTML은 문맥이없는 언어 이며 정규 언어가 아닙니다 (@StefanPochmann이 지적했듯이, 정규 언어도 문맥이 없으므로 문맥이없는 것이 반드시 정규가 아니라는 것은 아닙니다). HTML에서 정규 표현식으로 할 수있는 유일한 방법은 휴리스틱이지만 모든 조건에서 작동하지는 않습니다. 정규식과 일치하지 않는 HTML 파일을 표시 할 수 있어야합니다.


26
지금까지 가장 좋은 답변입니다. 정규 문법 만 일치시킬 수 있다면 HTML과 같은 문맥없는 문법을 파싱하려면 무한히 큰 정규 표현식이 필요합니다. 나는 이런 것들이 명확한 이론적 대답을 가질 때 사랑합니다.
ntownsend

2
실제로 정규 표현식이 아닌 Perl 유형 정규 표현식에 대해 논의하고 있다고 가정했습니다.
행크 게이

5
실제로 .Net 정규식은 균형 그룹과 신중하게 조작 된 식을 사용하여 닫는 태그로 여는 것과 어느 정도 일치 할 수 있습니다. 정규 표현식 에이 모든 것을 포함 하는 것은 물론 미친 듯이, 그것은 훌륭한 코드 Chtulhu처럼 보이고 아마도 실제 코드를 소환 할 것입니다. 그리고 결국 모든 경우에 여전히 작동하지는 않습니다. 그들은 HTML을 올바르게 구문 분석 할 수있는 정규식을 작성하면 유니버스가 자체적으로 축소 될 것이라고 말합니다.
Alex Paven

5
일부 정규 표현식 라이브러리는 재귀 정규 표현식을 수행 할 수 있습니다 (효과적으로 비정규 표현식으로 만들 수 있습니다).
Ondra Žižka

43
-1이 답변은 잘못된 인수 ( "HTML은 정규 언어가 아니기 때문에")에서 올바른 결론 ( "Regex로 HTML을 구문 분석하는 것은 좋지 않습니다")을 이끌어냅니다. 요즘 대부분의 사람들은 "정규식"(PCRE)이라고 말할 때 문맥이없는 문법 (실제로는 사소한 것)을 구문 분석 할 수있을뿐만 아니라 상황에 맞는 문법도 잘 분석 할 수 있습니다 ( stackoverflow.com/questions/7434272/ 참조). ).
NikiC

35

신속하게 더러워지면 정규 표현식이 잘 수행됩니다. 그러나 알아야 할 기본 사항 은 올바르게 정규 표현식을 구성하는 것이 불가능 하다는 것입니다. HTML 구문 분석 입니다.

그 이유는 정규 표현식이 임의로 중첩 된 표현식을 처리 할 수 ​​없기 때문입니다. 정규식을 사용하여 중첩 패턴을 일치시킬 수 있습니까?를 참조하십시오 .


1
일부 정규 표현식 라이브러리는 재귀 정규 표현식을 수행 할 수 있습니다 (효과적으로 비정규 표현식으로 만들 수 있습니다).
Ondra Žižka

23

( http://htmlparsing.com/regexes에서 )

<img> 태그에서 URL을 추출하려고하는 HTML 파일이 있다고 가정합니다.

<img src="http://example.com/whatever.jpg">

따라서 Perl에서 다음과 같은 정규식을 작성하십시오.

if ( $html =~ /<img src="(.+)"/ ) {
    $url = $1;
}

이 경우 $url실제로 포함합니다 http://example.com/whatever.jpg. 그러나 다음과 같이 HTML을 시작하면 어떻게됩니까?

<img src='http://example.com/whatever.jpg'>

또는

<img src=http://example.com/whatever.jpg>

또는

<img border=0 src="http://example.com/whatever.jpg">

또는

<img
    src="http://example.com/whatever.jpg">

또는 당신은에서 오 탐지를 시작합니다

<!-- // commented out
<img src="http://example.com/outdated.png">
-->

매우 단순 해 보이고 변경되지 않은 단일 파일의 경우 단순 할 수 있지만 임의의 HTML 데이터에서 수행하려는 모든 작업에 대해 정규 표현식은 미래의 상심을위한 레시피 일뿐입니다.


4
이것은 실제 답변 인 것처럼 보입니다. 오늘날 정규 표현식은 유한 automata 이상의 것이기 때문에 임의의 HTML을 정규 표현식으로 구문 분석 할 수 있습니다. 정규 페이지가 아닌 임의의 HTML을 구문 분석하기 위해 정규 표현식에서 HTML 파서를 다시 구현해야합니다 정규식은 확실히 읽을 수없는 1000 배가됩니다.
Johnth '

1
앤디, 시간을내어 언급 한 사례를 뒷받침하는 표현을 생각해 냈습니다. stackoverflow.com/a/40095824/1204332 의견을 보내주세요! :)
Ivan Chaer 2016 년

2
이 답변에서 추론되는 방법 오래된, 그리고 원래보다 더 적은 오늘 (나는 그것을하지 않았다 생각한다)에 적용됩니다. (작품 인용 : "단순하고 빠르거나 더러운 일을하고 있다면 ...")
Sz.

16

두 가지 빠른 이유 :

  • 악의적 인 입력에 견딜 수있는 정규 표현식을 작성하는 것은 어렵습니다. 사전 제작 된 도구를 사용하는 것보다 더 어려운 방법
  • 필연적으로 붙어있을 어리석은 마크 업으로 작업 할 수있는 정규 표현식을 작성하는 것은 어렵습니다. 사전 제작 된 도구를 사용하는 것보다 더 어려운 방법

일반적으로 구문 분석에 대한 정규 표현식의 적합성과 관련하여 적합하지 않습니다. 대부분의 언어를 구문 분석하는 데 필요한 정규 표현식을 본 적이 있습니까?


2
와? 2 년이 지난 후 공감 비? 궁금해하는 사람은 "정확하지 않고" "빠르고 더러워"라는 질문이 명확하게 제기 되었기 때문에 "이론적으로 불가능하기 때문에"라고 말하지 않았습니다. OP는 이미 이론적으로 불가능한 영역에 대한 답변을 읽었으며 여전히 만족하지 못했습니다.
행크 게이

1
5 년 이상 후에 공감대를 가지십시오. :) 왜 당신이 공감대를 받았을 지에 관해서는, 나는 말할 자격이 없지만, 개인적으로, 나는 수사적인 질문이 아닌 몇 가지 예나 설명을보고 싶었습니다.
Adam Jensen

3
기본적으로 제품 또는 내부 도구 배송에서 수행되는 모든 빠르고 html 구문 분석은 보안 허점 또는 버그 발생으로 이어집니다. 그것은 gusto와 낙담해야합니다. 정규식을 사용할 수 있다면 적절한 html 파서를 사용할 수 있습니다.
Monica Monica 복원

16

구문 분석이 진행되는 한 정규 표현식은 입력이 토큰으로 분류되는 "어휘 분석"(렉서) 단계에서 유용 할 수 있습니다. 실제 "구문 분석 트리 작성"단계에서는 그다지 유용하지 않습니다.

HTML 파서의 경우, 잘 구성된 HTML 만 허용하고 정규 표현식이 수행 할 수있는 기능 이외의 기능이 필요합니다 (“계산”할 수 없으며 주어진 수의 여는 요소가 동일한 수로 균형을 유지하는지 확인하십시오) 닫는 요소).


8

브라우저가 다소 자유로운 방식으로 처리하는 HTML을 "나사"하는 방법은 많지만 모든 경우를 정규식으로 처리하기 위해 브라우저의 자유로운 동작을 재현하는 데 약간의 노력이 필요하므로 정규 표현식은 필연적으로 일부 특별한 경우 실패합니다. 이 경우 시스템에 심각한 보안 격차가 발생할 수 있습니다.


1
사실, HTML의 대부분은 끔찍한 것 같습니다. 정규 표현식이 실패하면 심각한 보안 격차가 발생할 수있는 방법을 이해하지 못합니다. 예를 들어 줄 수 있습니까?
ntownsend

4
ntownsend : 예를 들어 HTML에서 모든 스크립트 태그를 제거했다고 생각하지만 정규 표현식이 특수한 경우를 다루지 못한다고 생각합니다 (즉, IE6에서만 작동합니다). 붐, XSS 취약점이 있습니다!
Tamas Czinege

1
대부분의 실제 사례가 이러한 의견에 맞추기에는 너무 복잡하기 때문에 이것은 매우 가설적인 예입니다.
Tamas Czinege

3
보안 각도에 대해 +1 전체 인터넷과 인터페이스 할 때 해킹 된 "대부분의 시간"코드를 작성할 여유가 없습니다.
j_random_hacker

7

문제는 HTML 및 정규식과 관련된 질문을하는 대부분의 사용자가 작동하는 자체 정규식을 찾을 수 없기 때문에이 작업을 수행한다는 것입니다. 그런 다음 DOM 또는 SAX 파서 또는 이와 유사한 것을 사용할 때 모든 것이 더 쉬운 지 생각해야합니다. XML과 유사한 문서 구조로 작업하기 위해 최적화되고 구성됩니다.

물론 정규식으로 쉽게 해결할 수있는 문제가 있습니다. 그러나 강조는 쉽게 이루어 집니다.

http://.../정규 표현식으로 잘 보이는 것처럼 보이는 모든 URL을 찾으려면 . 그러나 클래스가 'mylink'인 a-Element에있는 모든 URL을 찾으려면 적절한 파서를 사용하는 것이 좋습니다.


6

정규식은 중첩 된 태그 구조를 처리하도록 설계되지 않았으며 실제 HTML로 얻을 수있는 모든 가능한 경우를 처리하는 것이 가장 복잡합니다 (최악, 불가능).


6

답은 계산 이론에 있다고 생각합니다. 정규식을 사용하여 언어를 구문 분석하려면 "regular"( link ) 로 정의해야합니다 . HTML은 일반 언어에 대한 여러 기준을 충족하지 않기 때문에 일반 언어가 아닙니다 (html 코드에 내재 된 여러 수준의 중첩과 관련이 있음). 계산 이론에 관심이 있다면 책을 추천 합니다 .


1
나는 실제로 그 책을 읽었습니다. HTML이 상황에 맞는 언어라는 것은 나에게 일어나지 않았습니다.
ntownsend

4

이 표현식은 HTML 요소에서 속성을 검색합니다. 다음을 지원합니다.

  • 따옴표가없는 인용 된 속성,
  • 작은 따옴표 / 큰 따옴표
  • 속성 내 이스케이프 된 따옴표,
  • 공백은 등호,
  • 여러 속성,
  • 태그 내부의 속성 만 확인하고
  • 주석을 피하고
  • 속성 값 내에서 다른 따옴표를 관리하십시오.

(?:\<\!\-\-(?:(?!\-\-\>)\r\n?|\n|.)*?-\-\>)|(?:<(\S+)\s+(?=.*>)|(?<=[=\s])\G)(?:((?:(?!\s|=).)*)\s*?=\s*?[\"']?((?:(?<=\")(?:(?<=\\)\"|[^\"])*|(?<=')(?:(?<=\\)'|[^'])*)|(?:(?!\"|')(?:(?!\/>|>|\s).)+))[\"']?\s*)

확인하십시오 . 데모 에서처럼 "gisx"플래그로 더 잘 작동합니다.


1
매우 흥미 롭습니다. 읽을 수없고 디버깅하기는 어렵지만 여전히 : 인상적인 작업!
Eric Duminil

이것은 여전히 ​​HTML이 잘 구성되어 있다고 모호하게 가정합니다. 컨텍스트 일치가 없으면 <script>태그 내부의 JavaScript 코드와 같이 일반적으로 일치하지 않는 컨텍스트의 명백한 URL과 일치합니다 .
tripleee

4

HTML / XML은 마크 업과 컨텐츠로 구분됩니다. 정규 표현식은 어휘 태그 구문 분석을 수행 할 때만 유용합니다. 내용을 추론 할 수있을 것 같아요. SAX 파서에 적합합니다. 태그 및 컨텐츠는 요소의 중첩 / 폐쇄를 추적 할 수있는 사용자 정의 함수로 전달 될 수 있습니다.

태그를 구문 분석하는 한 정규 표현식으로 수행 할 수 있으며 문서에서 태그를 제거하는 데 사용할 수 있습니다.

수년간의 테스트를 통해 브라우저가 태그를 구문 분석하는 방식의 비결을 발견했습니다.

일반 요소는 다음 형식으로 구문 분석됩니다.

이 태그의 핵심은이 정규식을 사용합니다.

 (?:
      " [\S\s]*? " 
   |  ' [\S\s]*? ' 
   |  [^>]? 
 )+

이것을 [^>]?교대 중 하나로 알 수 있습니다. 이것은 형식이 잘못된 태그의 불균형 따옴표와 일치합니다.

그것은 또한 정규 표현에 대한 모든 악의 단일 뿌리입니다 . 그것이 사용되는 방식은 욕심 많고 일치 해야하는 정량화 된 컨테이너를 만족시키기 위해 충돌을 유발합니다.

수동적으로 사용하면 아무런 문제가 없습니다. 그러나 원하는 속성 / 값 쌍으로 산재하여 무언가를 강제 로 맞추고 역 추적으로부터 적절한 보호를 제공하지 않으면 악의가 없습니다.

이것은 평범한 오래된 태그의 일반적인 형태입니다. (가) 공지 사항 [\w:]태그 이름을 나타내는? 실제로 태그 이름을 나타내는 유효한 문자는 놀라운 유니 코드 문자 목록입니다.

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

계속해서 모든 태그 를 구문 분석하지 않으면 특정 태그를 검색 할 수 없음을 알 수 있습니다 . 할 수는 있지만 (* SKIP) (* FAIL)과 같은 동사 조합을 사용해야하지만 여전히 모든 태그를 파싱해야합니다.

그 이유는 태그 구문이 다른 태그 등에서 숨겨 질 수 있기 때문입니다.

따라서 모든 태그를 수동으로 구문 분석하려면 아래와 같은 정규식이 필요합니다. 이 특정 내용보이지 않는 내용 과도 일치 합니다.

새로운 HTML이나 xml 또는 다른 어떤 것이 새로운 구조를 개발할 때, 그것을 대안의 하나로 추가하십시오.


웹 페이지 참고-
이 문제가 발생한 웹 페이지 (또는 xhtml / xml)는 본 적이 없습니다. 하나를 찾으면 알려주십시오.

성능 메모-빠릅니다. 이것은 내가 본 가장 빠른 태그 파서
입니다 (아는 사람이 더 빠를 수도 있습니다).
몇 가지 특정 버전이 있습니다. 스크레이퍼로도 탁월
합니다 (실습 형인 경우).


완전한 정규식

<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>

형식화 된 모습

 <
 (?:
      (?:
           (?:
                # Invisible content; end tag req'd
                (                             # (1 start)
                     script
                  |  style
                  |  object
                  |  embed
                  |  applet
                  |  noframes
                  |  noscript
                  |  noembed 
                )                             # (1 end)
                (?:
                     \s+ 
                     (?>
                          " [\S\s]*? "
                       |  ' [\S\s]*? '
                       |  (?:
                               (?! /> )
                               [^>] 
                          )?
                     )+
                )?
                \s* >
           )

           [\S\s]*? </ \1 \s* 
           (?= > )
      )

   |  (?: /? [\w:]+ \s* /? )
   |  (?:
           [\w:]+ 
           \s+ 
           (?:
                " [\S\s]*? " 
             |  ' [\S\s]*? ' 
             |  [^>]? 
           )+
           \s* /?
      )
   |  \? [\S\s]*? \?
   |  (?:
           !
           (?:
                (?: DOCTYPE [\S\s]*? )
             |  (?: \[CDATA\[ [\S\s]*? \]\] )
             |  (?: -- [\S\s]*? -- )
             |  (?: ATTLIST [\S\s]*? )
             |  (?: ENTITY [\S\s]*? )
             |  (?: ELEMENT [\S\s]*? )
           )
      )
 )
 >

3

"그것은 달려있다". 여기에 주어진 모든 이유로 정규 표현식이 HTML을 정확한 정확도로 구문 분석 할 수 없으며 구문 분석 할 수 없다는 것이 사실입니다. 그러나 중첩 된 태그를 처리하지 않는 등 잘못된 결과가 미미하고 환경에서 정규 표현식이 매우 편리하다면 (예 : Perl을 해킹 할 때) 계속하십시오.

사이트로 연결되는 웹 페이지 (Google 링크 검색에서 찾은 웹 페이지)를 구문 분석하고 링크를 둘러싼 컨텍스트에 대한 일반적인 아이디어를 얻는 빠른 방법을 원한다고 가정 해 봅시다. 스팸을 연결하도록 경고하는 작은 보고서를 실행하려고합니다.

이 경우 일부 문서를 잘못 해석해도 큰 문제가되지 않습니다. 아무도 당신은 실수를 볼 수 없으며, 운이 좋으면 개별적으로 후속 조치를 취할 수있을 정도로 적습니다.

나는 그것이 절충이라고 말하는 것 같아요. 때로는 정확한 파서를 구현하거나 사용하는 것이 정확도가 중요하지 않은 경우 문제가되지 않을 수 있습니다.

가정에주의하십시오. 예를 들어 공개적으로 표시되는 것을 구문 분석하려는 경우 정규 표현식 단축키가 역효과를 줄 수있는 몇 가지 방법을 생각할 수 있습니다.


3

정규식을 사용하여 HTML의 일부 정보를 구문 분석하는 것이 올바른 방법 인 경우가 있습니다. 특정 상황에 따라 크게 다릅니다.

위의 합의는 일반적으로 나쁜 생각입니다. 그러나 HTML 구조가 알려져 있고 변경되지 않을 경우 여전히 유효한 접근 방식입니다.


3

HTML 자체는 규칙적이지 않지만보고있는 페이지의 일부는 규칙적 일 있습니다.

예를 들어, <form>태그가 중첩 되는 것은 오류입니다 . 웹 페이지가 올바르게 작동하면 정규식을 사용하여 a를 얻는 <form>것이 합리적입니다.

나는 최근에 셀레늄과 정규 표현식 만 사용하여 웹 스크랩을 수행했습니다. 내가 원하는 데이터가에 넣어했기 때문에 나는 그것으로 멀리 있어요 <form>, 그리고 (I조차 믿을 수 있도록 간단한 테이블 형식으로 넣어 <table>, <tr>그리고 <td>- 사실은 매우 이례적인 인 비는 중첩 된 것으로). 어느 정도는 정규 표현식이 거의 필요했습니다. 액세스해야하는 구조 중 일부가 주석으로 구분 되었기 때문입니다. (아름다운 수프는 의견을 줄 수 있지만 Beautiful Soup을 사용하여 차단 <!-- BEGIN -->하고 <!-- END -->차단 하기 어려웠을 것 입니다.)

그러나 중첩 테이블에 대해 걱정해야한다면 내 접근 방식은 효과가 없었을 것입니다! 나는 Beautiful Soup으로 돌아 가야했을 것입니다. 그러나 때로는 정규 표현식을 사용하여 필요한 청크를 잡고 드릴 다운 할 수도 있습니다.


2

실제로, 정규 표현식을 사용한 HTML 파싱은 PHP에서 완벽하게 가능합니다. 중첩 된 태그를 극복 할 때마다 욕심없는 지정자를 사용하여 정규 표현식 strrpos을 찾아 <반복 하기 위해 전체 문자열을 거꾸로 구문 분석해야 합니다. 큰 일에는 환상적이지 않고 속도가 느리지 않지만 웹 사이트의 개인 템플릿 편집기에 사용했습니다. 실제로 HTML을 구문 분석하지는 않았지만 데이터베이스 항목을 쿼리하여 데이터 테이블을 표시하기 위해 만든 몇 가지 사용자 정의 태그 (내 <#if()>태그는이 방법으로 특수 항목을 강조 표시 할 수 있음). 나는 몇 가지 자체 생성 태그 (XML에 매우 비 XML 데이터가있는)에 대한 XML 파서를 여기저기서 갈 준비가되지 않았습니다.

따라서이 질문은 상당히 죽었지 만 여전히 Google 검색에 나타납니다. 나는 그것을 읽고 "도전이 받아 들여졌다"고 생각하고 모든 것을 교체하지 않고도 간단한 코드를 수정했습니다. 비슷한 이유를 찾는 사람에게 다른 의견을 제시하기로 결정했습니다. 또한 마지막 답변은 4 시간 전에 게시되었으므로 여전히 뜨거운 주제입니다.


2
끔찍한 아이디어를 제안하기 위해 -1. 태그와 닫는 꺾쇠 괄호 사이의 공백을 고려 했습니까? (예 <tag >:) 주석 처리 된 닫기 태그를 고려 했습니까? (예 <tag> <!-- </tag> -->:) CDATA를 고려 했습니까? 일치하지 않는 태그를 고려 했습니까? (예 <Tag> </tAG>:) 이것도 고려 했습니까 ?
rmunn

1
소수의 맞춤 태그의 경우에는 정규 표현식이 효과적입니다. 따라서 귀하의 특정 경우귀하 의 사용이 실수가 아니 었습니다 . 그러나 그것은 HTML이 아니며 "정규 표현식으로 HTML 구문 분석은 PHP에서 완벽하게 가능합니다"라고 말하는 것은 잘못된 일이며 끔찍한 생각입니다. 실제 HTML의 불일치 (및 내가 나열한 몇 가지 이상의 방법이 있음)는 실제 HTML을 정규식으로 구문 분석하지 않아야하는 이유입니다. 글쎄,이 질문에 대한 다른 모든 대답과 위의 다른 의견에서 링크 된 답변을 참조하십시오.
rmunn

2
PHP는 완전히 완성 된 언어이므로 전혀 허위가 아닙니다. HTML 파싱을 포함하여 계산 가능한 모든 것이 가능합니다. 태그의 공백은 결코 문제가되지 않았으므로 태그 요소를 순서대로 나열하도록 조정했습니다. 첫 번째 단계에서 일관성이없는 케이스, 주석 처리 된 주석 처리 된 태그가있는 태그를 자동으로 수정하고 나중에 추가 한 후에 모든 종류의 태그를 쉽게 추가 할 수 있습니다 (자체 선택에 따라 대소 문자를 구분하지만). 그리고 CDATA는 실제로 HTML이 아닌 XML 요소라고 확신합니다.
Deji

2
내 이전 방법 (여기에서 설명 했음)은 비효율적이며 최근에 많은 콘텐츠 편집기를 다시 작성하기 시작했습니다. 이런 일을 할 때 가능성은 문제가되지 않습니다. 최선의 방법은 항상 주요 관심사입니다. 실제 답변은 "PHP로 쉽게 할 수있는 방법이 없습니다"입니다. 아무도 PHP에서 그것을 할 수있는 방법이 없거나 끔찍한 생각이라고 말하지만 정직하게 시도한 적이없는 정규식으로는 불가능하지만 내 대답의 가장 큰 결함은 질문이 정규식을 언급하는 것으로 가정합니다 PHP 컨텍스트 내에서 반드시 그런 것은 아닙니다.
Deji

2

나는 이것을 위해 정규 표현식에서 내 손을 시험해 보았다. 다음 HTML 태그와 쌍을 이루는 콘텐츠 청크를 찾는 데 주로 유용하며 찾지 않습니다.닫기 태그와 일치하는닫기 태그를 선택합니다. 해당 언어로 스택을 굴려서 확인하십시오.

'sx'옵션과 함께 사용하십시오. 운이 좋다면 'g'도 :

(?P<content>.*?)                # Content up to next tag
(?P<markup>                     # Entire tag
  <!\[CDATA\[(?P<cdata>.+?)]]>| # <![CDATA[ ... ]]>
  <!--(?P<comment>.+?)-->|      # <!-- Comment -->
  </\s*(?P<close_tag>\w+)\s*>|  # </tag>
  <(?P<tag>\w+)                 # <tag ...
    (?P<attributes>
      (?P<attribute>\s+
# <snip>: Use this part to get the attributes out of 'attributes' group.
        (?P<attribute_name>\w+)
        (?:\s*=\s*
          (?P<attribute_value>
            [\w:/.\-]+|         # Unquoted
            (?=(?P<_v>          # Quoted
              (?P<_q>['\"]).*?(?<!\\)(?P=_q)))
            (?P=_v)
          ))?
# </snip>
      )*
    )\s*
  (?P<is_self_closing>/?)   # Self-closing indicator
  >)                        # End of tag

이것은 파이썬 용으로 설계되었습니다 (다른 언어에서는 작동하지만 시도하지 않았으며 긍정적 인 예측, 부정적인 전망 및 명명 된 역 참조를 사용합니다). 지원합니다 :

  • 태그 열기- <div ...>
  • 태그 닫기- </div>
  • 댓글- <!-- ... -->
  • CDATA- <![CDATA[ ... ]]>
  • 자체 결산 태그- <div .../>
  • 선택적 속성 값- <input checked>
  • 따옴표없는 / 인용 된 속성 값- <div style='...'>
  • 작은 따옴표- <div style="...">
  • 탈출 따옴표- <a title='John\'s Story'>
    (이것은 실제로 유효한 HTML은 아니지만 좋은 사람입니다)
  • 등호 주변의 공백- <a href = '...'>
  • 재미있는 비트를위한 명명 된 캡처

또한 태그를 잊어 버렸을 때와 같이 잘못된 태그를 트리거하지 않는 것이 좋습니다 < 또는 >.

정규 표현식이 반복적으로 명명 된 캡처를 지원하면 황금색이지만 파이썬 re은 그렇지 않습니다 (정규식은 알고 있지만 바닐라 파이썬을 사용해야합니다). 당신이 얻는 것은 다음과 같습니다.

  • content-모든 내용을 다음 태그까지. 당신은 이것을 버릴 수 있습니다.
  • markup -모든 것이 포함 된 전체 태그.
  • comment -댓글 인 경우 댓글 내용입니다.
  • cdata-이 경우 <![CDATA[...]]>CDATA 내용입니다.
  • close_tag-닫기 태그 ( </div>) 인 경우 태그 이름입니다.
  • tag-열린 태그 ( <div>) 인 경우 태그 이름입니다.
  • attributes-태그 내의 모든 속성 반복 된 그룹을 얻지 못한 경우이 속성을 사용하여 모든 속성을 가져옵니다.
  • attribute -각 속성을 반복했습니다.
  • attribute_name -각 속성 이름이 반복되었습니다.
  • attribute_value-각 속성 값을 반복합니다. 인용 된 경우 인용이 포함됩니다.
  • is_self_closing- /자체 폐쇄 태그 인 경우 그렇지 않은 경우입니다.
  • _q그리고 _v-이것들을 무시하십시오; 역 참조를 위해 내부적으로 사용됩니다.

정규식 엔진이 반복적으로 명명 된 캡처를 지원하지 않는 경우 각 속성을 가져 오는 데 사용할 수있는 섹션이 있습니다. 그냥에 그 정규식을 실행 attributes각을 얻기 위해 그룹 attribute, attribute_name그리고 attribute_value그것에서.

여기 데모 : https://regex101.com/r/mH8jSu/11


1

정규 표현식은 HTML과 같은 언어에는 충분하지 않습니다. 물론 정규 표현식을 사용할 수있는 몇 가지 예가 있습니다. 그러나 일반적으로 구문 분석에는 적합하지 않습니다.


0

아시다시피 .. 당신의 생각에는 할 수없는 것이 많고 울타리 양쪽의 모든 사람들이 옳고 그름이라고 생각합니다. 당신은 CAN 그것을 할,하지만 조금 더 단지에 대해 하나의 정규식을 실행하는 것보다 처리합니다. 취하다이것을 예로 들어 (1 시간 안에 이것을 썼다). HTML이 완전히 유효하다고 가정하지만 앞에서 언급 한 정규 표현식을 적용하는 데 사용하는 언어에 따라 HTML을 수정하여 성공할 수 있습니다. 예를 들어, 존재하지 않는 닫는 태그를 제거 </img>합니다 (예 : 그런 다음 닫는 단일 HTML 슬래시를 누락 된 요소 등에 추가하십시오.

[x].getElementsByTagName()예를 들어 JavaScript와 비슷한 HTML 요소 검색을 수행 할 수있는 라이브러리를 작성하는 맥락에서 이것을 사용합니다 . 방금 정규식의 DEFINE 섹션에 작성한 기능을 결합하고 한 번에 하나씩 요소 트리 내부를 스테핑하는 데 사용합니다.

그렇다면 이것이 HTML 유효성 검사에 대한 최종 100 % 답변입니까? 아니요. 그러나 그것은 시작이며 조금 더 많은 노력으로 끝날 수 있습니다. 그러나 하나의 정규식 실행 내에서 시도하는 것은 실용 적이지도 효율적이지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.