2013-08-17 1 views
3

XML 파일의 일부 HTML에서 텍스트의 몇 단락을 추출하기 위해 Perl에서 HTML :: TreeBuilder를 사용하는 가장 좋은 방법을 알아 내려고합니다.HTML을 사용하여 perl에서 단락 찾기 div : TreeBuilder

$tree->address (또는 내가 생각하기에) 모든 항목이 같은 순서가 아님을 깨달을 때까지 사용했다.

목록에있는 모든 항목을 제외하고 각 항목에 여러 개의 <div> 요소가 있지만 그 중 하나에 <div> 중 하나에만 <p> 개의 요소가있는 것으로 보입니다. 그리고 <div>에는 아무 것도 없기 때문에 쉽게 만들 수있는 클래스가 없습니다.

나는 여러 가지 방법으로 시도 했으므로 내가 원하는 텍스트를 추출 할 수있는 것은 아무것도 없다. 몇 가지 다른 예를 살펴 보았지만 실제로는 그렇지 않습니다.

$bodyText = $tree->look_down('_tag' => 'div' => 'p'); 

을하지만 그것은 나에게 오류 제공합니다 :

이런 일이 일을하면 좋을 것

어쨌든
param list to look_down ends in a key! 

, 어쩌면 누군가가 내가 가진, 올바른 방향으로 날 지점 수 있도록 할 수 있습니다 밤새 보였고, 이제는 내 두뇌가 아파요.

감사합니다.

+0

HTML 예제 스 니펫을 추가 할 수 있습니까? – simbabque

답변

2

귀하의 오류 메시지가 의미가 있습니다. look_down 메서드는 해시 (물론 목록 임)를 기대합니다. 당신은 세 가지 요소를 부여하고 있습니다. 그래서 마지막 요소가 열쇠입니다. =>뚱뚱한 쉼표라고도하며 ,을 작성하는 데 더 읽기 쉬운 방법 일뿐입니다. 그것은 다소 이상한 오류 메시지입니다.

당신이해야 할 일은 <div>을 먼저 구문 분석하고 <p>에 대한 구문을 분석하는 것입니다. HTML :: TreeBuilder를 사용하면 한 번에 할 수 없습니다. 첫 번째 foreach에서 <div> 각각에 대해 HTML :: Element 객체가 생성됩니다. <p>에 대해 look_down을 들여 보내십시오.

use strict; 
use warnings; 
use feature qw(say); 
use HTML::TreeBuilder 5 -weak; 

my $tree = HTML::TreeBuilder->new_from_content(<DATA>); 
foreach my $e ($tree->look_down(_tag => 'div')) { 
    foreach my $f ($e->look_down(_tag => 'p')) { 
    say $f->as_text; 
    } 
} 

__DATA__ 
<html> 
<body> 
<div>foo</div> 
<div><p>hello world</p></div> 
<div>foo2</div> 
<div>foo3</div> 
<div><p>hello again</p></div> 
</body> 
</html> 
0
use Web::Query 'wq'; 
print wq("<html><div><p>I'm trapped under a hat</p></div><div /><div /><div /><div /><div />") 
     ->find('div p')->text; 
+0

매우 깔끔합니다. 그러나 설명은 좋을 것이다. ;-) – simbabque

2

나는 이것에 대한 XPath를를 사용하는 것이 좋습니다 : HTML::TreeBuilder의 바닐라 양식

use strict; 
use warnings; 
use feature qw(say); 
use HTML::TreeBuilder::XPath; 

my $tree = HTML::TreeBuilder->new_from_content(<DATA>); 
foreach my $e ($tree->findnodes('//div/p')) { 

    say $e->as_text; 
} 

__DATA__ 
<html> 
<body> 
<div>foo</div> 
<div><p>hello world</p></div> 
<div>foo2</div> 
<div>foo3</div> 
<div><p>hello again</p></div> 
</body> 
</html> 
3

이 가장 look_down의 기준으로 코드 참조를 사용하여 수행됩니다. 서브 루틴은 모든 이전 기준을 통과하는 트리의 각 노드에 대해 호출되며 서브 루틴이 true 값을 반환하면 노드는 유지됩니다.

이 프로그램은 그 사용법을 보여줍니다. 익명 서브 루틴은 전달 된 노드의 자식을 확인하기 위해 grep을 사용하여 p 태그가있는 모든 요소를 ​​계산합니다. 배열 @divs에는 p 자식 요소가있는 모든 div 요소가 포함되어 있습니다. @divs에 정확히 하나의 요소가 포함되도록 할 수 있습니다.

use strict; 
use warnings; 

use feature 'say'; 

use HTML::TreeBuilder; 

my $doc = HTML::TreeBuilder->new_from_content(<<__HTML__); 
<div>content</div> 
<div>content</div> 
<div><p>paragraph</p></div> 
<div>content</div> 
<div>content</div> 
__HTML__ 

my @divs = $doc->look_down(
    _tag => 'div', 
    sub { grep { ref eq 'HTML::Element' and $_->tag eq 'p' } $_[0]->content_list } 
); 

say scalar @divs, " found:\n"; 
say $divs[0]->as_HTML('<>&', ' '); 

출력

1 found: 

<div> 
    <p>paragraph</div> 

그러나 매우 깔끔한 데이터 XPath 식을 이용하여 다루어 질 수있는 향상된 HTML::TreeBuilder::XPath을 사용하는 것이다.

my @divs = $doc->findnodes('//div[p]'); 

및 결과는 상기 코드의 것과 동일하다 :이 look_downfindnodes 전화로 대체 될 수있다.

+0

첫 번째 예제를 시도해 본 결과 다음과 같은 오류가 발생했습니다 : '메소드를 호출 할 수 없습니다'isa "패키지 또는 객체 참조가 없으면 ... '하지만 확실하지 않은 이유는 무엇입니까? –

+0

@ 존경 : 사과드립니다. 나는 빈 문자열에'isa '를 부를 수 없다는 것을 잊었다. 나는 그것을 고쳤다. – Borodin