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
链接。请看它现在是否工作。