使用HTML::TreeBuilder从HTML-Perl中提取文本

使用HTML::TreeBuilder从HTML-Perl中提取文本,html,perl,html-content-extraction,text-extraction,htmlcleaner,Html,Perl,Html Content Extraction,Text Extraction,Htmlcleaner,我正在尝试访问.html文件并提取标记中的文本。从逻辑上讲,我下面的代码应该可以工作。通过使用HTML::TreeBuilder。我解析html,然后使用find_by_属性(“p”)提取中的文本。但是我的脚本出现了空目录。我遗漏了什么吗 #!/usr/bin/perl use strict; use HTML::TreeBuilder 3; use FileHandle; my @task = ('ar','cn','en','id','vn'); foreach my $lang (@

我正在尝试访问.html文件并提取
标记中的文本。从逻辑上讲,我下面的代码应该可以工作。通过使用HTML::TreeBuilder。我解析html,然后使用find_by_属性(“p”)提取
中的文本。但是我的脚本出现了空目录。我遗漏了什么吗

#!/usr/bin/perl

use strict;
use HTML::TreeBuilder 3;
use FileHandle;

my @task = ('ar','cn','en','id','vn');

foreach my $lang (@task) {
mkdir "./extract_$lang", 0777 unless -d "./extract_$lang";
opendir (my $dir, "./$lang/") or die "$!";
my @files = grep (/\.html/,readdir ($dir));
closedir ($dir);

foreach my $file (@files) {
    open (my $fh, '<', "./$lang/$file") or die "$!";
    my $root = HTML::TreeBuilder->new;
    $root->parse_file("./$lang/$file");
    my @all_p = $root->find_by_attribute("p");
    foreach my $p (@all_p) {
        my $ptag = HTML::TreeBuilder->new_from_content ($p->as_HTML);
        my $filewrite = substr($file, 0, -5); 
        open (my $outwrite, '>>', "extract_$lang/$filewrite.txt") or die $!;
        print $outwrite $ptag->as_text . "\n";  
        my $pcontents = $ptag->as_text;
        print $pcontents . "\n";
        close (outwrite);
    }
close (FH);
}
}

使用
find_by_tag_name
搜索标记名,而不是
find_by_attribute
您想要的
find_by_tag_name
,而不是
find_by_attribute

my @all_p = $root->find_by_tag_name("p");
从:

$h->按标签名称查找标签('tag',…)

在列表上下文中,返回在$h或以下具有 任何指定的标记名。在标量上下文中,返回第一个 (在树的预顺序遍历中)找到该元素,如果 没有

你弄糊涂了。该程序可以编写得更加简洁:

#!/usr/bin/env perl
use strictures;
use File::Glob qw(bsd_glob);
use Path::Class qw(file);
use URI::file qw();
use Web::Query qw(wq);
use autodie qw(:all);

foreach my $lang (qw(ar cn en id vn)) {
    mkdir "./extract_$lang", 0777 unless -d "./extract_$lang";
    foreach my $file (bsd_glob "./$lang/*.html") {
        my $basename = file($file)->basename;
        $basename =~ s/[.]html$/.txt/;
        open my $out, '>>:encoding(UTF-8)', "./extract_$lang/$basename";
        $out->say($_) for wq(URI::file->new_abs($file))->find('p')->text;
        close $out;
    }
}

您可能想看看Mojo::DOM,它允许您使用CSS选择器。

这是否意味着如果嵌入了标记,我可能需要再次运行循环?e、 g.
……
@2er0此方法将立即返回所有
p
元素。您可以依次在结果元素上使用它来查找嵌套的
p
s。我在extract.pl第24行收到一条警告消息
宽字符。
TreeBuilder有限制吗?即使perl给出警告,它仍然会打印出来,对吗?您必须指定文本输出编码。将我打开输出文件的方式与您打开输出文件的方式进行比较。了解Perl中的编码主题。我尝试使用您的代码,但在
使用Structures
中出现编译错误,在其他
使用
属性中也出现错误。我需要安装一个新的perl来让它们工作吗?错误:
在extract-daxim.pl第3行的@INC(@INC-contains:/etc/perl/usr/local/lib/perl/5.12.4/local/share/perl/5.12.4/usr/lib/usr/share/perl/5.12/usr/local/lib/site_perl.)中找不到structures.pm。
替换
使用Structures
使用严格;使用警告
或安装CPAN的
Structures
分发版。
#!/usr/bin/env perl
use strictures;
use File::Glob qw(bsd_glob);
use Path::Class qw(file);
use URI::file qw();
use Web::Query qw(wq);
use autodie qw(:all);

foreach my $lang (qw(ar cn en id vn)) {
    mkdir "./extract_$lang", 0777 unless -d "./extract_$lang";
    foreach my $file (bsd_glob "./$lang/*.html") {
        my $basename = file($file)->basename;
        $basename =~ s/[.]html$/.txt/;
        open my $out, '>>:encoding(UTF-8)', "./extract_$lang/$basename";
        $out->say($_) for wq(URI::file->new_abs($file))->find('p')->text;
        close $out;
    }
}