2013-03-11 58 views
1

我通過鏈接使用foreach循環。我需要$mech->back();來繼續循環還是隱式的。WWW ::機械化:: Firefox的循環雖然鏈接

此外,我需要一個單獨的$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(); 
    } 
} 

回答

1

不能從頁面訪問信息,當它不再顯示。然而,這樣foreach作品是建立列表第一它是通過迭代之前,所以你寫的代碼應該罰款。

由於鏈接是絕對的,因此不需要撥打back。如果您用過click那麼就必須在頁面點擊一個鏈接,但與follow_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_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'); 
    } 
} 

請讓我知道這是否適用於您要連接到的網站。

+0

感謝更多優雅的解決方案。我得到一個Mozrepl :: RemoteObject:TypeError - 不能訪問這個行的死對象:= $ mech-> follow_link($ share); #it​​顯示在上面...我認爲有一個嵌套的問題...我是否需要一個單獨的機甲物體作爲以前的答案建議? – surfer190 2013-03-11 11:43:08

+0

對不起,行是:$ mech-> follow_link($ place); – surfer190 2013-03-11 12:07:56

+0

從[*最新的修改列表*](http://cpansearch.perl.org/src/CORION/WWW-Mechanize-Firefox-0.70/Changes),它看起來像從Firefox 15開始的「死對象」問題。已經更新了我的解決方案以展示另一種方法。 – Borodin 2013-03-11 12:51:50

1

我建議使用單獨的$機甲的對象是:

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(); 
# } 
} 
+0

爲什麼你推薦多個機械化對象? – Borodin 2013-03-11 11:20:02

+0

因爲我可以很容易地將此​​代碼更改爲與多個線程一起使用。我在談論經典的WWW :: Mechanize當然不是Firefox。 – gangabass 2013-03-11 11:57:53

+0

'克隆'方法列在模塊文檔下的*函數中,可能永遠不會實現*。假設你沒有測試過你的代碼? – Borodin 2013-03-11 12:14:08

0

我使用WWW:機械化:: Firefox來遍歷使用Javascript的負荷一堆網址。頁面不立即渲染,因此需要測試一個特定的頁面元素是否可見(類似於Mechanize :: Firefox文檔中的建議,除了測試中的兩個xpaths),然後再決定下一個操作。

頁面最終呈現一個XPath來「無信息」或某些約2-3秒後想要的東西。如果沒有信息,我們會轉到下一個網址。我認爲存在某種競爭條件,這兩種xpath不會立即導致間歇性地(在循環中的sleep 1足夠奇怪)造成MozRepl::RemoteObject: TypeError: can't access dead object錯誤。

我的解決方案,似乎工作/提高可靠性是包圍所有$mech->get$mech->is_visibleeval{};這樣的:

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 
}; 

其他人可能會認爲這一改進。