如何在Perl中从HTML表格中提取数据?

7
我正在尝试在Perl中使用正则表达式解析具有以下结构的表格。第一行如下:
<tr class="Highlight"><td>Time Played</a></td><td></td><td>Artist</td><td width="1%"></td><td>Title</td><td>Label</td></tr>

这里我希望提取“播放时间”、“艺术家”、“标题”和“标签”,并将它们打印到输出文件中。
我尝试了许多正则表达式,例如:
$lines =~ / (<td>) /
       OR
$lines =~ / <td>(.*)< /
       OR
$lines =~ / >(.*)< /
   

我的当前程序如下所示:
#!perl -w

open INPUT_FILE, "<", "FIRST_LINE_OF_OUTPUT.txt" or die $!;

open OUTPUT_FILE, ">>", "PLAYLIST_TABLE.txt" or die $!;

my $lines = join '', <INPUT_FILE>;

print "Hello 2\n";

if ($lines =~ / (\S.*\S) /) {
print "this is 1: \n";
print $1;
    if ($lines =~ / <td>(.*)< / ) {
    print "this is the 2nd 1: \n";
    print $1;
    print "the word was: $1.\n";
    $Time = $1;
    print $Time;
    print OUTPUT_FILE $Time;
    } else {
    print "2ND IF FAILED\n";
    }
} else { 
print "THIS FAILED\n";
}

close(INPUT_FILE);
close(OUTPUT_FILE);

请提取HTML文件中的内容使用Perl的方法 - Ken White
这并不是那个问题的重复。 - user181548
@Kinopiko:差不多了。想要提取位于td标签和li标签之间的部分有什么区别? - Ken White
顺便说一下,你似乎对你的任务感到困惑:你要解析的文本在标签内。你想要的字符串是被标记起来的,可以这么说。 - Sinan Ünür
3个回答

17

在这种情况下,所请求的解析相当简单。 - user181548
1
@Ether 看起来有些人喜欢折磨自己。我不知道为什么。 - Sinan Ünür
2
@Sinan:我的理论是正则表达式有一种特殊的学习曲线:起初它们似乎是如此令人惊叹,以至于没有什么它们不能(或不应该)做到。任何看起来像解析问题的东西因此必须可以用正则表达式解决。 - Ether

11

使用HTML::TableExtract。确实如此。

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TableExtract;
use LWP::Simple;

my $file = 'Table3.htm';
unless ( -e $file ) {
    my $rc = getstore(
        'http://www.ntsb.gov/aviation/Table3.htm',
        $file);
    die "Failed to download document\n" unless $rc == 200;
}

my @headers = qw( Year Fatalities );

my $te = HTML::TableExtract->new(
    headers => \@headers,
    attribs => { id => 'myTable' },
);

$te->parse_file($file);

my ($table) = $te->tables;

print join("\t", @headers), "\n";

for my $row ($te->rows ) {
    print join("\t", @$row), "\n";
}

在另一篇文章中,我所说的“任务特定”的HTML解析器就是这个意思。

如果你把精力放在阅读文档上而不是随意尝试正则表达式,你本可以节省很多时间的。


我知道我来晚了,但getstore()是一个非常好的方法,可以避免对某人的服务器造成过多负担。很棒的示例代码。 - Ashley
我点赞了这个回答,因为你提供了可行的代码,尽管我很想不点赞,因为你在结尾处忍不住给OP上了一课。知道该阅读哪些文档并不是那么容易的事情。 - Sue Spence
1
@SueSpence 感谢您的点赞,但是那些不断向无法控制格式的HTML文档中添加一种又一种模式的人需要被提醒,有更好的解决方案。我可以建议您在您的答案中添加可行的代码,而不是对我进行讲课式的批评? - Sinan Ünür

0

这很简单:

my $html = '<tr class="Highlight"><td>Time Played</a></td><td></td><td>Artist</td><td width="1%"></td><td>Title</td><td>Label</td></tr>';
my @stuff = $html =~ />([^<]+)</g;
print join (", ", @stuff), "\n";

如果你想尝试运行它,请查看http://codepad.org/qz9d5Bro


等你看到我因告诉你这个而收到的踩票,你就知道了。 - user181548
4
@nick,因为这种方法会使人反复浪费大量时间和精力,每次需要解析HTML时都要寻找恰到好处的正则表达式。 - Sinan Ünür
1
使用正则表达式解析JSON与解析HTML一样困难,然而,在先前的讨论中,http://stackoverflow.com/questions/1598053/how-can-i-remove-external-links-from-html-using-perl/1598069#1598069上的某个人最固执地认为不应该使用正则表达式来解析HTML,但随后他却赞同使用正则表达式来解决一个涉及使用正则表达式解析JSON的问题:https://dev59.com/gnI-5IYBdhLWcg3w3cnS#1636508。 - user181548
抱歉,上述链接有点错误:https://dev59.com/gnI-5IYBdhLWcg3w3cnS - user181548
2
我不能代表别人发言。我认为在那种情况下使用正则表达式是浪费时间的。因此,我在该线程中添加了一个使用 JSON.pm 的 Perl 一行代码。 - Sinan Ünür
1
@Kinopiko,看起来SO上理解Chomsky层次的人太少了。使用正则表达式解析JSON是愚蠢的,甚至比HTML还要愚蠢,因为有一个真正的解析器可用,比任何半吊子的正则表达式解决方案都要简单得多。这证明了计算机科学在教育程序员方面的价值。 - daotoad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接