2012-07-04 31 views
6

Tôi duy trì cơ sở dữ liệu các bài viết có định dạng HTML. Đáng tiếc là các biên tập viên người viết bài không biết HTML thích hợp, vì vậy họ thường có những thứ được viết như sau:Làm cách nào để phân tích cú pháp HTML không hợp lệ với Perl?

<div class="highlight"><html><head></head><body><p>Note that ...</p></html></div> 

Tôi đã cố gắng sử dụng HTML::TreeBuilder để phân tích HTML này nhưng sau khi phân tích nó và bán phá giá cây kết quả, tất cả các yếu tố giữa <div class="highlight">...</div> đã biến mất. Tôi chỉ còn lại <div class="highlight"></div>.

Các biên tập viên thường cũng đã làm những việc như:

<div class="article"><style>@font-face { font-family: "Cambria"; }</style>Article starts here</div> 

Phân tích này với HTML::TreeBuilder kết quả trong rỗng <div class="article"></div> một lần nữa.

Bất kỳ ý tưởng nào về cách tiếp cận HTML bị hỏng này và thực sự có ý nghĩa trong số đó?

+0

Bạn đã thử xem nó dưới dạng xml chưa? Nó có thể không phải là html hợp lệ, nhưng bạn có thể chọn nó ngoài bằng cách sử dụng xpath. –

+4

@BartonChittenden Chúc may mắn với điều đó. –

Trả lời

11

tôi lần đầu tiên sẽ chạy nó thông qua HTML::Tidy:

#!/usr/bin/env perl 

use strict; use warnings; 
use HTML::Tidy; 

my $html = <<EO_HTML; 
<div class="highlight"><html><head></head> 
<body><p>Note that ...</p></html> 
</div> 
EO_HTML 

my $tidy = HTML::Tidy->new; 

print $tidy->clean($html); 

Output:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> 
<html> 
<head> 
<meta name="generator" content="tidyp for Windows (v1.04), see www.w3.org"> 
<title></title> 
</head> 
<body> 
<div class="highlight"> 
<p>Note that ...</p> 
</div> 
</body> 
</html> 

Bạn có thể kiểm soát đầu ra bằng cách thiết lập tùy chọn cấu hình khác nhau.

Sau đó, hãy nạp HTML đã làm sạch thông qua trình phân tích cú pháp.

Nếu không, bạn có thể thử xây dựng một cây một bước-tại-một-thời gian sử dụng HTML::TokeParser::Simple hoặc thậm chí chỉ HTML::Parser, nhưng tôi tin rằng theo cách đó là điên rồ.

Hãy nhớ rằng trình phân tích cú pháp cố gắng xây dựng biểu diễn cây sẽ chặt chẽ hơn trình phân tích cú pháp luồng chỉ nhận ra các phần tử khác nhau khi nó nhìn thấy chúng.

-1

Âm thanh như Tag soup. Như một cách tiếp cận khác, bạn cũng có thể sử dụng chương trình java "html-tagsoup" từ bên trong chương trình perl của bạn (ví dụ như backticks). Nó có thể được gọi là một chương trình độc lập như thế này.

java -jar tagsoup-1.2.1 [option ...] [file ...] 

HTML :: Tidy được sử dụng để tốt hơn hoặc linh hoạt hơn, tôi nghĩ vậy.

1

XML::LibXML cũng là, có lẽ đáng ngạc nhiên, tốt ở loại làm sạch này nếu được sử dụng đúng cách. Nó cũng cực kỳ nhanh; và sâu/linh hoạt khi bạn vượt qua đường cong học tập của nó.

#!/usr/bin/env perl 
use strictures; 
use XML::LibXML; 

my @craptastic = ('<div class="article"><style>@font-face{ font-family: "Cambria" }</style>Article starts here</div>', 
        '<div class="highlight"><html><head></head><body><p>Note that ...</p></html></div>'); 

# The inline setting of recover_silently is broken/non-functional so 
# we do the method calls to set. 
my $parser = XML::LibXML->new(); 
$parser->recover_silently(1); 
$parser->keep_blanks(1); 

for my $crap (@craptastic) 
{ 
    my $doc = $parser->load_html(string => $crap); 

    # Optional example for killing style tags not in the <head/> 
    $_->parentNode->removeChild($_) for $doc->findnodes("//body//style"); 

    print $/, $crap, $/; 
    my ($body) = $doc->findnodes("//body"); 
    print "-" x 60, $/; 
    print $_->serialize(1) for $body->childNodes; 
    print $/, $/; 
} 

Cung cấp cho bạn –

<div class="article"><style>@font-face{ font-family: "Cambria" }</style>Article starts here</div> 
------------------------------------------------------------ 
<div class="article">Article starts here</div> 


<div class="highlight"><html><head></head><body><p>Note that ...</p></html></div> 
------------------------------------------------------------ 
<div class="highlight"> 
    <p>Note that ...</p> 
</div> 
+1

+1 Điều đó thực sự đáng ngạc nhiên. –

3

Bạn có thể cố gắng sử dụng Marpa::HTML, mà là một phân tích cú pháp HTML mức cao, cho phép phân tích cực kỳ phóng khoáng. Nó có thể phân tích cú pháp thậm chí HTML không hợp lệ bằng kỹ thuật được gọi là tác giả của tác giả là dép ruby ​​; Marpa :: HTML thêm phần tử cần có.

Xem ví dụ về định dạng lại, định dạng và làm cho hợp lệ HTML không hợp lệ ví dụ trong How to Parse HTML bài đăng blog của Jeffrey Kegler, tác giả của trình phân tích cú pháp Marpa và Marpa :: HTML.

Các vấn đề liên quan