[html] 정규 표현식을 사용하지 않는 경우 HTML 구문 분석은 어떻게 작동합니까?

나는 매일 HTML 문자열에서 무언가를 구문 분석하거나 추출하는 방법을 묻는 질문을 봅니다. 첫 번째 답변 / 주석은 항상 “분노를 느끼지 않도록 HTML 구문 분석에 RegEx를 사용하지 마십시오!”입니다. (마지막 부분은 때때로 생략됩니다).

이것은 나에게 다소 혼란 스럽습니다. 일반적으로 복잡한 문자열을 구문 분석하는 가장 좋은 방법은 정규식을 사용하는 것이라고 항상 생각했습니다. 그렇다면 HTML 파서는 어떻게 작동합니까? 정규식을 사용하여 구문 분석하지 않습니다.

정규식 사용에 대한 한 가지 특정 인수는 항상 구문 분석 대안이있는 것은 아니라는 것입니다 (예 : DOMDocument가 보편적으로 사용 가능한 옵션이 아닌 JavaScript). 예를 들어 jQuery는 정규식을 사용하여 HTML 문자열을 DOM 노드로 변환하여 잘 관리하는 것처럼 보입니다.

이것이 CW인지 아닌지 확실하지 않은 것은 내가 답변을 받고 싶은 진정한 질문이며 실제로 토론 스레드가 될 의도가 아닙니다.



답변

일반적으로 토크 나이저를 사용합니다. 초안 HTML5 사양에는 “실제 HTML”처리를 위한 광범위한 알고리즘 이 있습니다.


답변

그렇다면 HTML 파서는 어떻게 작동합니까? 정규식을 사용하여 구문 분석하지 않습니까?

음 … 아니.

당신의 두뇌에서 계산 이론으로 되돌아 가면, 하나를 수강했거나, 컴파일러 코스 또는 이와 유사한 것을 수강했다면, 다른 종류의 언어와 계산 모델이 있다는 것을 기억할 것입니다. 모든 세부 사항을 다룰 자격은 없지만 몇 가지 주요 사항을 함께 검토 할 수 있습니다.

(이러한 목적을위한) 가장 간단한 유형의 언어 및 계산은 일반 언어입니다. 정규 표현식으로 생성 할 수 있으며 유한 오토마타로 인식 할 수 있습니다. 기본적으로 이는 이러한 언어의 “파싱”문자열이 상태를 사용하지만 보조 메모리는 사용하지 않음을 의미합니다. HTML은 확실히 일반 언어가 아닙니다. 생각해 보면 태그 목록이 임의로 깊이 중첩 될 수 있습니다. 예를 들어 테이블에는 테이블이 포함될 수 있고 각 테이블에는 많은 중첩 태그가 포함될 수 있습니다. 정규식을 사용하면 한 쌍의 태그를 선택할 수 있지만 임의로 중첩 된 것은 없습니다.

규칙적이지 않은 고전적인 단순 언어는 괄호와 올바르게 일치합니다. 시도해보십시오. 항상 작동하는 정규식 (또는 유한 오토 마톤)을 만들 수 없습니다. 중첩 깊이를 추적하려면 메모리가 필요합니다.

메모리 용 스택이있는 상태 머신은 컴퓨팅 모델의 다음 강점입니다. 이를 푸시 다운 자동화라고하며 문맥없는 문법에 의해 생성 된 언어를 인식합니다. 여기에서 정확하게 일치하는 괄호를 인식 할 수 있습니다. 실제로 스택은이를위한 완벽한 메모리 모델입니다.

이게 HTML에 충분할까요? 안타깝게도 아닙니다. 실제로 모든 태그가 항상 완벽하게 정렬되는 엄청나게 신중하게 검증 된 XML의 경우 일 수 있습니다. 실제 HTML에서는 <b><i>wow!</b></i>. 이것은 분명히 중첩되지 않으므로 올바르게 구문 분석하기 위해 스택은 충분히 강력하지 않습니다.

다음 수준의 계산은 일반 문법에 의해 생성되고 튜링 머신에서 인식되는 언어입니다. 이것은 일반적으로 가장 강력한 계산 모델로 받아 들여집니다. 보조 메모리가있는 상태 머신은 어디에서나 메모리를 수정할 수 있습니다. 이것이 프로그래밍 언어가 할 수있는 일입니다. 이것은 HTML이 존재하는 복잡성의 수준입니다.

여기에 모든 것을 한 문장으로 요약하려면 일반 HTML을 구문 분석하려면 정규식이 아닌 실제 프로그래밍 언어가 필요합니다.

HTML은 다른 언어가 파싱되는 것과 같은 방식으로 파싱됩니다 : 렉싱과 파싱. 렉싱 단계는 개별 문자의 흐름을 의미있는 토큰으로 나눕니다. 구문 분석 단계는 상태와 메모리를 사용하여 토큰을 논리적으로 일관된 문서로 조합하여 처리 할 수 ​​있습니다.


답변

정규식은 파서의 한 형태 일뿐입니다. 정직한 HTML 파서는 재귀 하강 , 예측 및 텍스트를 적절하게 해석하기 위해 여러 다른 기술을 사용하여 정규식으로 표현할 수있는 것보다 훨씬 더 복잡 합니다. 정말로 들어가고 싶다면 lex & yacc 및 유사한 도구를 확인할 수 있습니다 .

HTML 구문 분석에 정규 표현식을 사용하는 것에 대한 금지는 아마도 ” HTML 구문 분석을 위해 순진한 정규 표현식을 사용하지 마십시오 …” (분노를 느끼지 않도록) “… 그리고 결과를주의해서 처리하십시오.”와 같이 더 정확하게 작성되어야합니다 . 특정 목표의 경우 정규식이 완벽하게 적절할 수 있지만 정규식의 제한 사항을 인식하고 구문 분석하는 텍스트의 소스에 적합한만큼 신중해야합니다 (예 : 사용자 입력, 실제로 매우 조심하십시오).


답변

HTML 구문 분석은 선형 텍스트를 트리 구조로 변환하는 것입니다. 정규식은 일반적으로 트리 구조를 처리 할 수 ​​없습니다. 다음 토큰을 얻기 위해 각 지점에서 필요한 정규식은 항상 변경됩니다. 파서에서 정규식을 사용할 수 있지만 가능한 각 구문 분석 상태에 대해 전체 정규식 배열이 필요합니다.


답변

100 % 솔루션을 원하는 경우 : HTML을 문자별로 반복하는 사용자 정의 코드를 작성해야하며 현재 노드를 중지하고 시작해야하는지 여부를 결정하기위한 엄청난 양의 논리가 필요합니다. 다음.

그 이유는 이것이 유효한 HTML이기 때문입니다.

<ul>
<li>One
<li>Two
<li>Three
</ul>

그러나 이것은 다음과 같습니다.

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>

“90 % 솔루션”에 동의하는 경우 : 그러면 XML 파서를 사용하여 문서를로드하는 것이 좋습니다. 또는 Regex를 사용합니다 (하지만 콘텐츠의 마스터라면 xml이 더 쉽습니다).


답변