Использование Watir для проверки плохих ссылок - PullRequest
5 голосов
/ 12 апреля 2011

У меня есть неупорядоченный список ссылок, которые я сохраняю в стороне, и я хочу щелкнуть каждую ссылку и убедиться, что она идет на реальную страницу и не имеет 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 ]

5 голосов
/ 12 апреля 2011

Мой ответ аналогичен идее Железного Человека.

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

другой пример (включая идею Чака ван дер Линдена): проверьте код состояния и выйдите из 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
4 голосов
/ 12 апреля 2011

Для этого не нужно использовать Watir.Запрос HTTP HEAD даст вам представление о том, разрешается ли URL-адрес и будет ли он быстрее.

Ruby's 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's Net :: HTTP может несколько помочь, потому что он может использовать HTTP HEAD запросы, которые не возвращают всю страницу, только заголовок,Этого само по себе недостаточно, чтобы знать, достижима ли настоящая страница, потому что ответ HEAD может перенаправить на страницу, которая не разрешается, поэтому вы должны циклически перебирать перенаправления, пока вы либо не получить перенаправление, или вы получите ошибку.Документы Net :: HTTP содержат пример , с которого можно начать:

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-гемы, такие как Typhoeus и Patron , также могут легко выполнять HEAD запросов, поэтому взгляните на них.В частности, Typhoeus может обрабатывать некоторые тяжелые нагрузки через своего компаньона Hydra, что позволяет легко использовать параллельные запросы.


EDIT:

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>

Если вам нужно проверить множество URL-адресов, см. Пример Hydra , который является частью Typhoeus.

2 голосов
/ 12 апреля 2011

Есть философские споры о том, должен ли watir или watir-webdriver предоставлять информацию о коде возврата HTTP.Предполагается, что обычный «пользователь», имитирующий Ватира в DOM, не знает кодов возврата HTTP.Я не обязательно согласен с этим, поскольку у меня немного другой сценарий использования, возможно, основной (тестирование производительности и т. Д.) ... но это именно так.Этот поток выражает некоторые мнения о различии => http://groups.google.com/group/watir-general/browse_thread/thread/26486904e89340b7

В настоящее время нет простого способа определить коды ответов HTTP от Watir без использования дополнительных инструментов, таких как прокси / Fiddler / HTTPWatch / TCPdump, или перехода на сеть/ http уровень сценариев mid test ... Мне лично нравится использовать firebug с плагином netexport для ретроспективного взгляда на тесты.

0 голосов
/ 07 июля 2012

Все предыдущие решения неэффективны, если у вас очень большое количество ссылок, потому что для каждой из них будет установлено новое 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, повторить 10 раз для временных ошибок (тайм-ауты или 5xx) и, конечно, будет только получать заголовки.

Обновление: добавлено --globoff, чтобы curl не расширял ни один URL, если он содержит {} или []

...