Perl WWW::Mechanize::Firefox链接循环

Perl WWW::Mechanize::Firefox链接循环,perl,web-scraping,www-mechanize,www-mechanize-firefox,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->selecto

我正在使用
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();
    }
}

我建议为此使用单独的$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();
#    }
}

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

由于链接是绝对链接,因此无需调用
back
。如果您使用了
单击
,则页面中必须有一个链接可供单击,但使用
follow\u link
时,您所做的一切都是指向一个新的URL

也不需要检查要遵循的链接数量,因为空列表上的
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\u link
很挑剔,需要关注当前页面上的链接

我建议您从每个链接中提取
href
属性,并使用
get
而不是
follow\u 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');
    }
}

请让我知道这在您连接的站点上是否有效。

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

页面最终在大约2-3秒后将xpath呈现为“no info”或一些想要的内容。如果没有信息,我们转到下一个URL。我认为存在某种竞争条件,两个XPath不同时存在,从而导致
MozRepl::RemoteObject:TypeError:cannotaccessdead object
间歇性错误(在循环中的
sleep 1
处,非常奇怪)

我的解决方案似乎有效/提高了可靠性,就是将所有
$mech->get
$mech->都包含在
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
};

其他人可能会建议对此进行改进。

为什么建议使用多个Mechanize对象?因为我可以轻松地将此代码更改为与多个线程一起使用。我说的是经典的WWW::Mechanize,当然不是Firefox。模块文档中的函数下列出了
clone
方法,这些函数可能永远不会实现。想必你没有;t测试您的代码?感谢更优雅的解决方案。我得到一个Mozrepl::RemoteObject:TypeError-无法访问此行的死对象:=$mech->follow_link($share)#如上图所示……我认为嵌套的for有问题……我是否需要像前面的答案所建议的那样单独的mech对象?对不起,行是:$mech->follow_link($place);从表面上看,“死物”问题似乎始于Firefox15。我已经更新了我的解决方案以显示另一种方法。感谢您的深入了解,不幸的是,~/MozRepl/RemoteObject.pm行1530中也出现了死对象错误。它只执行第一次迭代…错误出现,然后它打印输出可能现在提取
href
的值已经太晚了。我再次略微编辑了我的解决方案,以便在显示页面时获取
href
链接。请看它现在是否工作。