使用Watir检查错误的链接

时间:2011-04-12 00:46:33

标签: ruby watir

我有一个无序的链接列表,我保存到一边,我想点击每个链接,并确保它进入一个真实的页面,并没有404,500等。

问题是我不知道该怎么做。是否有一些我可以检查的对象会给我http状态代码或其他什么?

mylinks = Browser.ul(:id, 'my_ul_id').links

mylinks.each do |link|
  link.click

  # need to check for a 200 status or something here! how?

  Browser.back
end

4 个答案:

答案 0 :(得分:5)

我的回答与Tin Man的回答类似。

require 'net/http'
require 'uri'

mylinks = Browser.ul(:id, 'my_ul_id').links

mylinks.each do |link|
  u = URI.parse link.href
  status_code = Net::HTTP.start(u.host,u.port){|http| http.head(u.request_uri).code }
  # testing with rspec
  status_code.should == '200'
end

如果你使用Test :: Unit测试框架,你可以测试如下,我认为

  assert_equal '200',status_code

另一个示例(包括Chuck van der Linden的想法):检查状态代码并在状态不佳时注销URL。

require 'net/http'
require 'uri'

mylinks = Browser.ul(:id, 'my_ul_id').links

mylinks.each do |link|
  u = URI.parse link.href
  status_code = Net::HTTP.start(u.host,u.port){|http| http.head(u.request_uri).code }
  unless status_code == '200'
    File.open('error_log.txt','a+'){|file| file.puts "#{link.href} is #{status_code}" }
  end
end

答案 1 :(得分:4)

没有必要为此使用Watir。 HTTP HEAD请求可让您了解网址是否已解决且速度更快。

Ruby的Net::HTTP可以做到,或者你可以使用Open::URI

使用Open :: URI,您可以请求URI,然后返回页面。因为您并不真正关心页面包含的内容,所以您可以丢弃该部分,只返回是否有内容:

require 'open-uri'

if (open('http://www.example.com').read.any?)
  puts "is"
else
  puts "isn't"
end

优点是Open :: URI解决了HTTP重定向问题。缺点是它返回整页,所以它可能很慢。

Ruby的Net :: HTTP可以有所帮助,因为它可以使用HTTP HEAD请求,这些请求不返回整个页面,只返回标头。这本身并不足以知道实际页面是否可以访问,因为HEAD响应可能会重定向到无法解析的页面,因此您必须遍历重定向,直到您获得重定向,或者您收到错误。 Net :: HTTP文档有一个example可以帮助您入门:

require 'net/http'
require 'uri'

def fetch(uri_str, limit = 10)
  # You should choose better exception.
  raise ArgumentError, 'HTTP redirect too deep' if limit == 0

  response = Net::HTTP.get_response(URI.parse(uri_str))
  case response
  when Net::HTTPSuccess     then response
  when Net::HTTPRedirection then fetch(response['location'], limit - 1)
  else
    response.error!
  end
end

print fetch('http://www.ruby-lang.org')

同样,该示例是返回页面,这可能会减慢您的速度。您可以将get_response替换为request_head,这会返回get_response之类的响应,这应该会有所帮助。

在任何一种情况下,你都需要考虑另一件事。很多网站都使用“meta refreshes”,这会导致浏览器在解析页面后使用备用URL刷新页面。处理这些需要请求页面并解析它,寻找<meta http-equiv="refresh" content="5" />标签。

其他HTTP宝石(如TyphoeusPatron)也可轻松执行HEAD个请求,因此请查看它们。特别是,Typhoeus可以通过其伴侣Hydra处理一些重负荷,让您轻松使用并行请求。


编辑:

require 'typhoeus'

response = Typhoeus::Request.head("http://www.example.com")
response.code # => 302

case response.code
when (200 .. 299)
  #
when (300 .. 399)
  headers = Hash[*response.headers.split(/[\r\n]+/).map{ |h| h.split(' ', 2) }.flatten]
  puts "Redirected to: #{ headers['Location:'] }"
when (400 .. 499)
  #
when (500 .. 599) 
  #
end
# >> Redirected to: http://www.iana.org/domains/example/

万一你没玩过一个,这就是响应的样子。它对于你所看到的那种情况非常有用:

(rdb:1) pp response
#<Typhoeus::Response:0x00000100ac3f68
 @app_connect_time=0.0,
 @body="",
 @code=302,
 @connect_time=0.055054,
 @curl_error_message="No error",
 @curl_return_code=0,
 @effective_url="http://www.example.com",
 @headers=
  "HTTP/1.0 302 Found\r\nLocation: http://www.iana.org/domains/example/\r\nServer: BigIP\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n",
 @http_version=nil,
 @mock=false,
 @name_lookup_time=0.001436,
 @pretransfer_time=0.055058,
 @request=
  :method => :head,
    :url => http://www.example.com,
    :headers => {"User-Agent"=>"Typhoeus - http://github.com/dbalatero/typhoeus/tree/master"},
 @requested_http_method=nil,
 @requested_url=nil,
 @start_time=nil,
 @start_transfer_time=0.109741,
 @status_message=nil,
 @time=0.109822>

如果要检查的网址很多,请参阅Typhoeus中的Hydra example

答案 2 :(得分:2)

关于watir或watir-webdriver是否应提供HTTP返回码信息,存在一些哲学争论。前提是Watir在DOM上模拟的普通“用户”不知道HTTP返回码。我不一定同意这一点,因为我对主要(性能测试等)的用例略有不同......但它就是它的本质。这个主题表达了关于区别的一些看法=&gt; http://groups.google.com/group/watir-general/browse_thread/thread/26486904e89340b7

目前没有简单的方法来确定来自Watir的HTTP响应代码而不使用代理/ Fiddler / HTTPWatch / TCPdump等补充工具,或降级到测试中的脚本编写的net / http级别...我个人喜欢使用firebug与netexport插件可以回顾测试。

答案 3 :(得分:0)

如果您拥有非常多的链接,之前的所有解决方案效率都很低,因为对于每个链接,它将与托管该链接的服务器建立新的HTTP连接。

我编写了一个单行bash命令,它将使用curl命令获取stdin提供的链接列表,并返回与每个链接对应的状态代码列表。这里的关键点是curl在同一个调用中占用了所有链接,它将重用 HTTP连接,这将大大提高速度。

然而,curl会将列表分成256个块,这仍然远远超过1!要确保重用连接,请先对链接进行排序(只需使用sort命令)。

cat <YOUR_LINKS_FILE_ONE_PER_LINE> | xargs curl --head --location -w '---HTTP_STATUS_CODE:%{http_code}\n\n' -s --retry 10 --globoff | grep HTTP_STATUS_CODE | cut -d: -f2 > <RESULTS_FILE>

值得注意的是,上述命令将遵循HTTP重定向,对于临时错误(超时或5xx)重试10次,当然只会获取标题。

更新:添加了--globoff,以便curl不会扩展任何网址,如果它包含{}或[]