2

我一直都知道,好的编码意味着:不要重复自己。但是这些天我一直在重复自己,试图让我的爬虫处理超时错误。

对于我单击的每个链接或按钮,我添加一个救援异常 => e 并刷新页面。

例如

browser.link(:xpath, "//tr[@class='pager'][1]/td/a").when_present.click

变成

begin
  browser.link(:xpath, "//tr[@class='pager'][1]/td/a").wait_until_present
  browser.link(:xpath, "//tr[@class='pager'][1]/td/a").click
rescue Exception => e
  sleep (10)
  puts "timed out, let's refresh"
  browser.refresh
end

也许有一个更清洁、不重复的解决方案。我试过操纵 Watir::wait 但我无法让它工作..

class Watir::Wait
  alias_method :__do_wait, :wait_until
  def wait_until
    begin
      __do_wait{ yield }
    rescue Exception => e
      puts "timed out. let's refresh"
      $browser.refresh
    end
  end
end
4

2 回答 2

2

如果我正确理解您的要求,我认为您想覆盖method_missingWhenPresentDecorator 的处理。

require 'watir-webdriver'

module Watir
  class WhenPresentDecorator
    def method_missing(m, *args, &block)
      unless @element.respond_to?(m)
        raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#{@element.class}"
      end

      begin
        Watir::Wait.until(@timeout, @message) { @element.present? }
      rescue
        sleep(10)
        puts "timed out, let's refresh"
        @element.browser.refresh
      else
        @element.__send__(m, *args, &block)
      end
    end
  end # WhenPresentDecorator  
end

使用这个猴子补丁,when_present将等待元素出现。如果元素存在,它将执行操作(即在您的示例中单击)。如果元素不存在,它将捕获异常,忽略它,刷新页面并继续下一条语句。

例如,给定以下具有显示页面加载时间的 div 标签的页面:

<html>
  <head>
    <script>
      function startTime()
      {
        var today=new Date();
        var h=today.getHours();
        var m=today.getMinutes();
        var s=today.getSeconds();
        document.getElementById('txt').innerHTML=h+":"+m+":"+s;
      }
    </script>
  </head>
  <body onload="startTime()">
    <div id="txt"></div>
  </body>
</html>

您可以看到访问确实存在的元素(链接)时没有发生异常。同样,页面会在尝试找到该元素后刷新。

puts browser.div(:id => 'txt').text  
#=> "22:48:25"

browser.link(:id => 'asdf').when_present.click
#=> "timed out, let's refresh"

puts browser.div(:id => 'txt').text
#=> "22:48:36"
于 2013-08-14T03:39:48.493 回答
1

对不起我的英语,我是法国人....大声笑这个脚本允许刷新浏览器而不跳过一个步骤,例如当你必须登录时,你不能跳过一个步骤......如果你有一个链接太多,带宽低的网站......

我认为seeb会这样做:

module Watir

class WhenPresentDecorator
def method_missing(m, *args, &block)
  unless @element.respond_to?(m)
    raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#   {@element.class}"
  end

  begin
    while !@element.present? 
     sleep(10)
    puts "timed out, let's refresh"
    @element.browser.refresh
    end
   rescue

   else
     @element.__send__(m, *args, &block)
   end
      end
     end # WhenPresentDecorator  
   end
于 2013-12-03T01:16:58.117 回答