使用 perl 脚本从 HTML 文件中提取信息

Posted

技术标签:

【中文标题】使用 perl 脚本从 HTML 文件中提取信息【英文标题】:Extracting information from HTML file using perl script 【发布时间】:2021-09-23 01:38:38 【问题描述】:

这是我在标题Item Drop% 下提取某些数据的代码。我想提取该标题下的90.5%。但我只能提取整个列,而不仅仅是那个值。有什么想法吗?

#!/usr/bin/perl

use strict;
use warnings;

use html::TableExtract;
use LWP::Simple;

my $file = 'data.html';
unless ( -e $file ) 
    my $rc = getstore(
        'proj/Desktop/folder1/data.html',
        $file);
    die "Failed to download document\n" unless $rc == 200;




my $te = HTML::TableExtract->new( headers => qw(Item Drop%)]);

$te->parse_file($file);

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

foreach my $ts (ts->tables) 
    print "Table (", join(',', $ts->coords), ");\n";
    foreach my $row ($ts->rows) 
        print join(',', @$row), "\n";
    

我的data.html 是:


 ..
 ..
 ..
<table align = "center" class="" style= .......>
<tr>
<th rowspan="2">EM</th>
<th colspan="2"><a href= "proj/Desktop/folder1/data.html" class = ..../th>
<td> 90.5%</td>
</tr>
..
..
..
..
<tr>
<th rowspan="2">EM</th>
<th colspan="2"><a href= "proj/Desktop/folder1/data.html" class = ..../th>
<td> 40%</td>
</tr>

</table>

【问题讨论】:

您提供的数据 sn-p 不包含 table 标记,因此不包含表。请制作一个最小可重现的示例,即跳过显示您的问题实际上不需要的所有内容(例如使用 LWP)并提供您认为应该可以使用的完整数据文件但与您的代码无关。 大概那里有一张桌子,但您只展示了一个片段,这不足以让我们帮助您。接下来,如果$te 是一个“undefined value”,因为该错误表明,那么事情确实不对,因为您使用的好模块甚至无法解析表。然后,rows 方法在表格上运行,所以$table-&gt;rows。见文件;此外,这里有一些帖子,其中包含处理表格的完整示例(例如,this one,其中包含两个更完整示例的链接) 感谢 cmets ,我想我以某种方式解决了它。将很快再次更新! @Vyshunavi 好的,很好 :) 我刚刚更新了我的评论,提供了一个完整示例的链接,看看 @zdim 会感谢的!我已经更新了我的问题。请看看~~ 【参考方案1】:

以下是基础知识,将给定的表片段完成为一个有意义的表。

use warnings;
use strict;
use feature 'say';

use HTML::TableExtract;
use Scalar::Util qw(looks_like_number);

my $filename = shift // die "Usage: $0 file\n";

my $te = HTML::TableExtract->new;
$te->parse_file($filename);    

my ($tbl) = $te->tables;  # one table in the sample file

my (@values1, @values2);  # for 90.5% and such, processing options

foreach my $row ($tbl->rows)  
    # Tables often come with empty fields; keep them, for counting and such
    my @fields = map  defined($_) ? $_ : '--'  @$row;
    printf "%8s ", $_  for @fields;
    say ''; 

    # Criteria for how to identify the number aren't explained,
    # but may it be the fourth column in a row starting with 'EM'?
    if ($fields[0] =~ /^\s*EM\s*$/) 
        push @values1, $fields[3] =~ s/^\s*|\s*$//gr;  # see note in text
    

    # Or is it simply the number ending with % sign?
    foreach my $fld (@fields)  
        if ($fld =~ /\s*(.+)\s*%/ and looks_like_number($1))  
            push @values2, $1;
        
    

say "@values1";
say "@values2";

注意:正则表达式中的/r 修饰符是added in v5.14。如果您的 Perl 较旧,请参阅脚注

大部分处理过程都用于演示。不需要打印这些值(一旦你弄清楚感兴趣的项目在哪里),我不会用-- 替换undef 字段,这样做是为了更清晰的打印输出,而是用''(空字符串) .此外,我们需要一个标准,而不是两个。

请注意,在第一种情况下,我们保留% 符号,并使用正则表达式清理空格;在第二种情况下,百分位符号被省略(并且空格最终被正则表达式在匹配中自然清除)。当然,这些都可以根据您的实际需要进行调整。

由于既没有给出实际的表,也没有给出其中的数据,也没有给出确切的标准,所以我只能提供代码的提示和示例。有了更多的细节,这可以变得更具体。

注意,在确定最后的细节时,通常使用正则表达式,事情往往会变得挑剔和敏感;太小心了。


上面使用的问题中的片段完成的 html 文件:

<html>    
<style> th, td  padding: 10px  </style>  <!-- to better see it -->

<table align="center" rules="all">    
<tr>
    <th rowspan="2">EM</th>
    <th colspan="2"><a href="http://www.google.com">ggl</a></th>
    <td> 90.5%</td>
</tr>
<tr>
    <td>data</td> <td>more</td> <td>etc</td>
</tr>    

<tr>
<th rowspan="2">EM</th>
<th colspan="2"><a href="http://www.google.com">ggl</a></th>
<td> 0.0%</td>
</tr>
<tr> <td>data</td> <td>more</td> <td>etc</td> </tr>    
</table>    

</html>

替换正则表达式上的/r 修饰符使其返回更改后的字符串(并保持原样)。这正是人们在很多情况下想要的,这里的代码就是一个很好的例子(我们只是想将更改后的字符串添加到数组中)。

但是,在早于 5.14 版的 Perls 中,当引入此功能时,必须做其他事情:要么创建一个具有更改的新变量,如果您需要保持原始变量不变,或者更改该原始变量然后使用它。

由于我们在这里修剪多余的空格,最好简单地更改$fields[3],然后将其添加到数组中。所以不是

if ($fields[0] =~ /^\s*EM\s*$/) 
    push @values1, $fields[3] =~ s/^\s*|\s*$//gr;

if ($fields[0] =~ /^\s*EM\s*$/) 
    $fields[3] =~ s/^\s*|\s*$//g;   # strip leading/trailing spaces
    push @values1, $fields[3];

【讨论】:

好的,让我试试你的代码并尽快回复你! 嗨,它说 bareword 在 if ($fields[0] =~ /^\s*EM\s*$/) push @values1, $fields[3] =~ s/^\s*|\s*$//r; 的预期操作位置找到了 @Vyshunavi 不适合我,它不适合;我对此进行了测试(只是又做了一次),它按预期工作。您是否在使用此代码的真实表格?我不知道您的真实数据,因此编写此文件是为了处理我根据您在问题中提供的内容组成的文件(显示在最后)。如果您的实际 HTML 具有不同的结构,那么您需要相应地调整代码。我不能这样做,因为我不知道你的桌子。 @Vyshunavi 另一方面......你有什么版本的 Perl?正则表达式中的 /r 修饰符是在 5.14 版中添加的。如果您的较早,它将不起作用,所以让我知道在这种情况下添加不同的方式。 我的是v5.8.9,这是否意味着我不能使用它?无论如何我可以把我的html文件发给你吗?

以上是关于使用 perl 脚本从 HTML 文件中提取信息的主要内容,如果未能解决你的问题,请参考以下文章

从 perl 脚本中提取用户名

Perl 脚本自动提取《人民日报》全文数据库中的动态词频数据

从cron运行时,Perl脚本不会将STDOUT输出到文件

如何将信息从 web 传递到 perl 脚本?

提高 LWP::Simple perl 性能

生信学习周如何系统入门Perl