2012-07-04 30 views
6

我维护HTML格式文章的数据库。不幸的是谁写的文章编辑不知道正确的HTML,所以他们往往有书面的东西,如:如何用Perl解析无效的HTML?

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

我试着用HTML::TreeBuilder解析这个HTML之间,但它的解析和倾倒结果树中的所有元素后<div class="highlight">...</div>不见了。我只剩下<div class="highlight"></div>

的编辑往往也做的事情,如:

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

HTML::TreeBuilder导致空<div class="article"></div>再次解析此。

任何想法如何处理这个破碎的HTML,并实际上有意义吗?

+0

你试过把它看成是xml吗?它可能不是有效的html,但您可以使用xpath将其分开。 –

+4

@BartonChittenden祝你好运。 –

回答

11

我会先通过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); 

输出:

<!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> 

您可以通过设置不同的配置选项控制输出。

然后,通过解析器提供已清理的HTML。

否则,您可以尝试使用HTML::TokeParser::Simple甚至只是HTML::Parser一次一步地构建树,但我相信这种方式就是疯狂。

请记住,尝试构建树表示的解析器将比只是在识别它们时识别各种元素的流解析器更严格。

-1

听起来像Tag soup。 作为另一种方法,您也可以在您的perl程序中使用java程序“html-tagsoup”(例如反引号)。它可以被称为像这样的独立程序。

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

HTML :: Tidy曾经更好或更灵活,我认为。

1

XML::LibXML如果使用正确的话,也许会出人意料地擅长这种清理。它也非常快;一旦你超越了自己的学习曲线,就会变得深刻/灵活。

#!/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 $/, $/; 
} 

给你–

<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这确实令人惊讶。 –

3

你可以尝试使用Marpa::HTML,这是一个高层次的HTML解析器,允许非常自由的解析。它可以解析甚至无效的HTML使用技术称为红宝石拖鞋由其作者; Marpa :: HTML添加了应该在那里的元素。

请参阅Marle parser和Marpa :: HTML的作者Jeffrey Kegler在How to Parse HTML博客文章中重新格式化,美化和制作无效HTML示例。