【问题标题】:Script to build HTML page from from extracted DIVs from other HTML pages从其他 HTML 页面提取的 DIV 构建 HTML 页面的脚本
【发布时间】:2010-11-15 18:02:50
【问题描述】:

我有一组 HTML 报告,每个报告都包含两个具有特定 ID 的 DIV 元素,我需要将其剥离并编译成一个总体摘要报告(同样是一个 HTML 文件)。

我最初的想法是,这是 Perl 脚本的理想工作,但是我们没有最新的内部 Perl 技能(我们是一家 .NET C# 商店)。

欢迎对推荐方法提出想法和建议...

【问题讨论】:

    标签: perl reporting html-parsing


    【解决方案1】:

    如果您的 div 包含嵌套的 div,则直接正则表达式可能不够。这是因为结束的 div 元素不包含 ID,所以正则表达式很难匹配结束标记。

    如果你的 div 是:

    <div id="findme">
        <!-- No other divs here! -->
    </div>
    

    然后你可以使用正则表达式(只是要小心贪婪),这是一个更优雅的版本:

    <div id="findme">(.*?)</div>
    

    注意:我很确定 regexp 不会运行,已经有一段时间了!

    我会考虑使用 HTML 解析器库来解析结构并获取 div 内部的字符偏移量,然后从缓冲区中获取该范围。使用 HTML 库将允许您解析并找到您想要的 div 的结束位置。

    this tutorial 之类的东西可能有用。这些解析器可能允许您准确地提取包含在标签中的数据,例如您的 div。

    您也可以使用 C# HTML parser,它们都做类似的工作,只需查看文档以确保它们不只是构建树,并允许您获取字符偏移量封闭的 div 数据(以便您可以提取它)或允许访问该数据。

    【讨论】:

    • 不需要负前瞻(实际上是?!不是!?)。只要没有嵌套的 div,m{<div id="findme">(.*?)</div>} 就可以工作。
    【解决方案2】:

    使用 Perl,HTML::TokeParser 和 HTML::Template 会有所帮助。这是一个简单的例子:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use HTML::TokeParser;
    use HTML::Template;
    
    use Data::Dumper;
    
    my ($html_file) = @ARGV;
    
    open my $html_handle, '<:utf8', $html_file
        or die "Cannot open '$html_file': $!";
    
    my $parser = HTML::TokeParser->new( $html_handle );
    
    my @divs;
    
    while ( my $tag = $parser->get_tag('div') ) {
        my $attr = $tag->[1];
        next unless ref $attr eq 'HASH';
        next unless defined( my $id = $attr->{id} );
        next unless $id eq 'div1' or $id eq 'div2';
    
        my $div = $tag->[-1];
        my $in_wanted = 1;
    
        while ( $in_wanted ) {
            my $token = $parser->get_token;
            if ( $token->[0] eq 'T' ) {
                $div .= $token->[1];
            }
            else {
                $div .= $token->[-1];
            }
            my ($type, $name) = @$token[0, 1];
            if ( $name eq 'div' ) {
                $in_wanted += $type eq 'S' ?  1
                            : $type eq 'E' ? -1
                            : 0;
                next;
            }
            if ( $type eq 'E' and $name eq 'html' ) {
                warn "Warning: Reached the end of '$html_file'\n";
                last;
            }
        }
    
        push @divs, {DIV => $div};
    }
    
    print output( @divs );
    
    sub output {
        my $tmpl_html = <<EO_TMPL;
    <html>
    <body>
    <TMPL_LOOP DIVS>
        <TMPL_VAR DIV>
    </TMPL_LOOP>
    </body>
    </html>
    EO_TMPL
        my $tmpl = HTML::Template->new(
            scalarref => \$tmpl_html,
        );
        $tmpl->param( DIVS => \@_ );
        return $tmpl->output;
    }
    

    【讨论】:

      【解决方案3】:

      使用合适的 HTML 解析器; Perl 有 HTML::Parser,我相信 C# 也有几个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-29
        • 2019-12-02
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多