WWW :: Mechanize :: Firefox循环链接

时间:2013-03-11 10:22:24

标签: perl web-scraping www-mechanize www-mechanize-firefox

我使用foreach循环链接。我是否需要$mech->back();来继续循环,或者是隐含的。

此外,我是否需要为每个循环嵌套一个单独的$mech2对象?

我目前的代码卡住了(它没有完成),并在找不到td#tabcolor3的第一页上结束。

foreach my $sector ($mech->selector('a.link2'))
{
    $mech->follow_link($sector);

    foreach my $place ($mech->selector('td#tabcolor3'))
    {
            if (($mech->selector('td#tabcolor3', all=>1)) >= 1)
    {
        $mech->follow_link($place);
            print $_->{innerHTML}, '\n'
            for $mech->selector('td.dataCell');
        $mech->back();
    }
    else
    {
        $mech->back();
    }
}

3 个答案:

答案 0 :(得分:1)

我建议使用单独的$ mech对象:

foreach my $sector ($mech->selector('a.link2'))
{
    my $mech = $mech->clone();
    $mech->follow_link($sector);

    foreach my $place ($mech->selector('td#tabcolor3'))
    {
            if (($mech->selector('td#tabcolor3', all=>1)) >= 1)
    {
            my $mech = $mech->clone();
            $mech->follow_link($place);
            print $_->{innerHTML}, '\n'
            for $mech->selector('td.dataCell');
        #$mech->back();
    }
#    else
#    {
#        $mech->back();
#    }
}

答案 1 :(得分:1)

当页面不再显示时,您无法访问该页面中的信息。但是,foreach的工作方式是在迭代之前先构建列表,因此您编写的代码应该没问题。

由于链接是绝对的,因此无需调用back。如果您使用了click,那么页面中必须有一个链接才能点击,但是follow_link您正在做的所有内容都是新网址。

也无需检查要遵循的链接数量,因为空列表上的for循环将无法执行。

为了使事情更清楚,我建议您在循环之前将selector的结果分配给数组。

喜欢这个

my @sectors = $mech->selector('a.link2');
for my $sector (@sectors) {

    $mech->follow_link($sector);

    my @places = $mech->selector('td#tabcolor3');
    for my $place (@places) {

        $mech->follow_link($place);

        print $_->{innerHTML}, '\n' for $mech->selector('td.dataCell');
    }
}

<强>更新

道歉。似乎follow_link很挑剔,需要关注当前页面上的链接

我建议您从每个链接中提取href属性,然后使用get代替follow_link

my @selectors = map $_->{href}, $mech->selector('a.link2');
for my $selector (@selectors) {

    $mech->get($selector);

    my @places = map $_->{href}, $mech->selector('td#tabcolor3');
    for my $place (@places) {

        $mech->get($place);

        print $_->{innerHTML}, '\n' for $mech->selector('td.dataCell');
    }
}

请告诉我这是否适用于您要连接的网站。

答案 2 :(得分:0)

我正在使用WWW:Mechanize :: Firefox来循环一堆带有大量Javascript的URL。页面不会立即呈现,因此在决定下一步操作之前,需要测试特定页面元素是否可见(类似于Mechanize :: Firefox文档中的建议,测试中除了2个xpath)。

该页面在大约2-3秒后最终将xpath呈现为“no info”或某些想要的东西。如果没有信息,我们会转到下一个网址。我认为存在某种竞争条件,两个xpath都不会立即存在,导致间歇性地出现 MozRepl::RemoteObject: TypeError: can't access dead object 错误(在循环中的sleep 1奇怪的情况下)。

我的解决方案似乎有效/提高可靠性是将所有$mech->get$mech->is_visible括在eval{};中,如下所示:

eval{ 
  $mech->get("$url");
  $retries = 15; #test to see if element visible = page complete
  while ($retries-- and ! $mech->is_visible( xpath => $xpath_btn ) and  ! $mech->is_visible( xpath => $xpath_no_info )){
    sleep 1;
  };
  last if($mech->is_visible( xpath => $xpath_no_info) ); #skip rest if no info page
};

其他人可能会建议改进。