HTML 문서에서 무언가를 찾기 위해 정규 표현식을 사용한 후 lxml의 강력한 기능을 다시 사용하는 가장 좋은 방법

StackOverflow https://stackoverflow.com/questions/2421396

문제

나는 많은 수의 HTML 문서(수십만 개)에서 일부 텍스트를 추출하려고 합니다.문서는 실제로 양식이지만 매우 큰 규모의 다양한 조직 그룹에서 준비하므로 문서 작성 방법에 상당한 차이가 있습니다.예를 들어 문서는 여러 장으로 구분됩니다.장의 내용을 분석할 수 있도록 모든 문서에서 5장의 내용을 추출하고 싶을 수도 있습니다.처음에는 이것이 쉬울 것이라고 생각했지만 작성자는 문서 전체에서 중첩되지 않은 테이블 세트를 사용하여 내용을 보관하여 테이블 내부의 td 태그를 사용하여 n장이 표시될 수 있다는 것이 밝혀졌습니다.또는 p 태그, H 태그, div 태그 또는 기타 블록 수준 요소와 같은 다른 요소를 사용할 수도 있습니다.

각 장의 시작과 끝을 식별하는 데 도움이 되도록 lxml을 반복적으로 사용한 후에 정규식을 사용하는 것이 훨씬 더 깔끔하다고 판단했습니다. 왜냐하면 모든 경우에 포함된 html 요소가 무엇이든 상관없이 장 레이블이 항상 있기 때문입니다. 의 형태

>Chapter #

다양한 방식(  또는   또는 공백)으로 표현되는 공백이나 줄바꿈 없는 공백이 있을 수 있다는 점에서 조금 더 복잡합니다.그럼에도 불구하고 각 섹션의 시작을 식별하기 위해 정규식을 작성하는 것은 쉽지 않았습니다.(한 섹션의 시작은 이전 섹션의 끝입니다.)

하지만 이제 lxml을 사용하여 텍스트를 가져오고 싶습니다.내 생각에는 관련 섹션을 찾는 데 사용하는 텍스트를 묶는 요소에 대한 닫기 태그를 찾기 위해 문자열을 따라 걷는 것 외에는 선택의 여지가 없다고 생각합니다.

여기에는 Chapter 이름을 보유하는 요소가 div인 한 가지 예가 있습니다.

<div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="left"><font style="DISPLAY: inline; FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman">Chapter 1.&#160;&#160;&#160;Our Beginnings.</font></div>

그래서 나는 1장과 일치하는 항목을 찾은 위치에서 시작하여 다음 장을 찾기 위한 정규식을 설정한다고 상상하고 있습니다.

</div|</td|</p|</h1 . . .

그래서 이 시점에서 나는 장 제목을 담고 있는 요소의 유형을 확인했습니다.

동일한 논리를 사용하여 정규식을 설정한 해당 요소 내에 있는 모든 텍스트를 찾을 수 있습니다.

>Chapter 1.&#160;&#160;&#160;Our Beginnings.<

그래서 나는 내 챕터 1이 시작되는 곳을 알아냈습니다.

2장(1장이 끝나는 곳)에서도 동일한 작업을 수행할 수 있습니다.

이제 저는 1장이 시작되는 위치를 나타내는 요소로 식별한 요소의 시작 부분에서 시작하여 1장이 시작되는 위치를 나타내는 요소로 식별한 요소의 열기 직전에 끝나는 문서를 캡처할 것이라고 상상하고 있습니다. 2가 시작됩니다.내가 식별한 문자열은 lxml에 공급되어 그 기능을 사용하여 콘텐츠를 가져옵니다.

나는 반복해서 읽었기 때문에 이 모든 문제를 겪게 될 것입니다. HTML 문서에서 내용을 추출하기 위해 정규식을 사용하지 않았고 lxml을 사용하여 시작 및 끝 위치를 식별하는 정확한 방법을 찾지 못했습니다. 내가 추출하고 싶은 텍스트.예를 들어, 1장의 부제가 Our Beginnings인지 확신할 수 없습니다. Our Red Canary일 수도 있습니다.시작 요소와 끝 요소가 있는지 확인하기 위해 lxml을 사용하여 이틀 동안 노력했으며 시간의 60% 미만만 정확할 수 있었지만 매우 짧은 정규식을 사용하여 95% 이상의 성공을 거두었다고 가정하겠습니다.

나는 필요 이상으로 일을 더 복잡하게 만드는 경향이 있으므로 비슷한 문제를 보거나 해결한 사람이 있는지, 그리고 제안하고 싶은 접근 방식(세부 사항은 신경 쓰지 않음)이 있는지 궁금합니다.

도움이 되었습니까?

해결책 3

내가 필요로하는 것을 식별하고 추출하기 위해 LXML을 사용하는 체계적인 방법이 없다고 두려워합니다. 오 H 글쎄, 나는 모두가 삐걱 거리는 소리에 감사한다. 참고-이것은 LXML의 결함이 아니며, 그것은 일관되지 않은 HTML 코딩의 결함이다. 예를 들어. 장은 문서의 합리적인 구분이므로 한 장의 모든 내용은 일부 유형의 요소로 래핑해야합니다. 아마도 가장 유연한 것은 후속 div가 다음 장인 div 태그 일 것입니다. 이것은 장을 나무의 가지로 만들 것입니다. 불행히도 문서의 약 20%가 잘 구성된 문서 일 수 있지만 다른 문서는 그렇지 않습니다.

내 컨텐츠 (div, p)를 보유 해야하는 각 유형의 요소를 테스트하고 모든 어린이와 모든 형제 자매를 잡을 수 있습니다. 섹션의 끝 (다음 섹션의 시작). 그러나 이것은 내가 정규 표현으로 시간의 95% 이상이 좋을 때 너무 많은 일처럼 보입니다.

내가 항상 배우는 모든 답과 의견에 감사드립니다.

다른 팁

때로는 잘못 작성되거나 일관되지 않게 작성된 HTML을 처리할 때 콘텐츠를 가져오는 직선 경로가 없는 경우도 있습니다.

lynx나 텍스트 기반 브라우저 중 하나를 사용하여 페이지 콘텐츠를 파일로 덤프하거나 코드로 파이프한 다음 처리하는 것이 좋습니다.또는 lxml을 사용하여 페이지를 로드하고 구문 분석한 다음 text_content()를 사용하여 텍스트를 추출하고 정규식을 통해 해당 장으로 이동할 수 있습니다.

그들이 말했듯이 GIGO는 쓰레기를 넣고 쓰레기를 버리는 것입니다. 쓰레기를 금으로 바꾸는 것이 개발자로서 우리의 임무입니다.그렇게 하면 꽤 지저분해질 수 있습니다.

당신이 할 수 있는 가장 간단한 일은 tree.getroot().iterdescendants()를 반복하여 다음과 같은 노드를 찾는 것입니다. node.text 원하는 정규 표현식과 일치합니다.이 시점부터 일부 임시 휴리스틱을 사용하여 텍스트의 위치를 ​​확인하는 함수에 노드를 전달할 수 있습니다.(루트의 iterdescendants가 너무 느린 경우 정규식 접근 방식을 사용하고 etree에 들어가서 찾을 수 있습니다. f(text_position) -> node 기능.)

예를 들어, 대상이 다음과 같은 것으로 확인된 경우 //tr/td, node.parent()의 다음 td를 조사하는 일부 테이블 텍스트 찾기 서브루틴에 전달하여 의미가 있는 텍스트(대략 장 길이, 특정 단어 포함 등)가 있는지 확인할 수 있습니다.마찬가지로, 다음과 같은 다른 태그에서 데이터를 찾기 위한 몇 가지 경험적 방법을 구성할 수 있습니다. div 그리고 p.다음과 같은 알 수 없는 태그가 있는 경우 font 처리 방법을 알고 있는 항목을 찾기 위해 제한된 수의 레벨을 버블링해 볼 수 있습니다. 너무 멀리 버블링하지 않도록 주의해야 합니다. 그렇지 않으면 실수로 다른 장에서 텍스트를 검색할 수도 있습니다.

문제의 핵심은 프로그래밍 방식으로 표시되지 않은 데이터를 프로그래밍 방식으로 마이닝한다는 것입니다. 이 경우 일반적으로 인간 상호 작용이 어느 정도 필요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top