Chinaunix首页 | 论坛 | 博客
  • 博客访问: 470159
  • 博文数量: 142
  • 博客积分: 4126
  • 博客等级: 上校
  • 技术积分: 1545
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-22 10:03
文章分类

全部博文(142)

文章存档

2011年(8)

2010年(7)

2009年(64)

2008年(63)

我的朋友

分类:

2008-11-19 14:18:59

分析多个文件
下面讲一个实际的例子:一个学生的网页作业的自动评分程序。这个程序首先由一些html文件来构建一些树形结构,然后把他们存储在一个@trees数组中:
 

my @trees;
foreach (@files) {
    print " building tree for $_ ...\n" if $options{v};
    my $tree = HTML::TreeBuilder->new;
    $tree->parse_file($_);
    push( @trees, $tree );
}

 

doitem()子函数遍历@trees数组,并且请求一个代码块来在每棵树中寻找特定的html元素,并且存贮代码块返回的结果。它调用printd()函数显示发现的html元素和这些元素所在的文件名(当使用-v选项被设置的话):

 

sub doitem {
    my $func = shift;
    my $num = 0;
    foreach my $i ( 0 .. $#files ) {

        my @elements = $func->( $files[$i], $trees[$i] );
        printd $files[$i], @elements;
        $num += @elements;
    }
    return $num;
}

上面提到的代码块是一个需要两个参数的子函数,两个参数一个是文件名另一个是该文件对应的html树,它返回书中找到元素的数组。下面的例子代码将返回所有网页中的斜体字,包括标签元素(例如:text)和font-style属性为斜体的元素(例如:text).

 

 

$n = doitem sub {
    my ( $file, $tree ) = @_;
    return ( $tree->find("i"),
        $tree->look_down( "style" => qr/font-style *: *italic/ ) );
    };

marking "Italicized text (2 points): "
  . ( ( $n > 0 ) ? "good. 2" : "no italic text. 0"
);

 

这样,在页面中的斜体字的两种方式都被检测了。marking函数报告检测的结果,并且在程序的最后进行测试,帮助计算总节点数。

其他的需求可以使用相同的方法,下面的代码看上去更加难理解,它使用了一个正则帮助我们选出网页中没定义颜色的元素。

my $pattern = qr/(^|[^-])color *: *rgb\( *[0-9]*, *[0-9]*, *[0-9]*\)/;
return $tree->look_down(
    "style" => $pattern,
    sub { $_[0]->as_trimmed_text ne "" }
);

nvu(一个可视化网页编辑器)使用rgb(R,G,B)形式的style属性设置文本的颜色(例如:text)。上面这段代码比斜体字的代码稍微严格一些,因为它还过滤那些没有包含任何文字的元素。代码中的as_trimmed_text()方法返回cut掉开头和结尾部空白字符的文本内容。

下面这段代码使用了嵌套的look_down()函数来定位有边框并且有连接的图表。它可以找到任何被包裹的有边框的

 

return $tree->look_down(
    "_tag" => "a",
    sub {
       $_[0]->look_down( "_tag" => "img", sub { hasBorder( $_[0] ) } );
    }
);

检查没有连接的图表更加有趣,它需要look_down()和look_up()两个函数,下面这段代码只找出没有被包裹的元素。

 

 

return $tree->look_down(
    "_tag" => "img",
    sub { !$_[0]->look_up( "_tag" => "a" ) and hasBorder( $_[0] ); }
);

检测正当的内部连接需要使用look_down()函数里的代码块排除一般的外部连接,通过检查href的值是否有协议名。还要验证连接到的文件是否真正存在。

 

 

use File::Basename;
$n = doitem sub {
    my ( $file, $tree ) = @_;
    return $tree->look_down(
        "_tag" => "a",
        "href" => qr//,
        sub {
            !( $_[0]->attr("href") =~ /^ *(http:|https:|ftp:|mailto:)/)
            and -e dirname($file) . "/" . decodeURL( $_[0]->attr("href") );
        }
    );
};

nvu通过指定body标签中的style的颜色属性来改变页面的字体颜色,就像:。下面代码使用一个正则去匹配style属性并且取回三个颜色的值,任何不为零的颜色值就表示页面不是默认的颜色。

 

my $pattern = qr/(?:^|[^-])color *: *rgb\(( *[0-9]*),( *[0-9]*),( *[0-9]*)\)/;
return $tree->look_down(
    "_tag" => "body",
    "style" => qr//,
    sub {
        $_[0]->attr("style") =~ $pattern and
        ( $1 != 0 or $2 != 0 or $3 != 0 );
    }
);

合理的使用look_down(),look_up(),as_trimmed_text()等函数,我们的代码可以定位和标记出很html元素(图片,内部链接,背景图片等等)的存在。

阅读(1238) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~