Ruby - net/http - следующие перенаправления
У меня есть URL, и я использую HTTP GET для передачи запроса на страницу. Что происходит с самым последним ароматом (в net/http
) сценарий не выходит за рамки ответа 302. Я пробовал несколько разных решений; HTTPClient, net/http, Rest-Client, Patron...
Мне нужен способ перейти к последней странице, чтобы проверить тег атрибута на этих страницах HTML. Перенаправление происходит из-за того, что мобильный пользовательский агент попадает на страницу, которая перенаправляет на мобильное представление, следовательно, мобильный пользовательский агент в заголовке. Вот мой код, как сегодня:
require 'uri'
require 'net/http'
class Check_Get_Page
def more_http
url = URI.parse('my_url')
req, data = Net::HTTP::Get.new(url.path, {
'User-Agent' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5'
})
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
cookie = res.response['set-cookie']
puts 'Body = ' + res.body
puts 'Message = ' + res.message
puts 'Code = ' + res.code
puts "Cookie \n" + cookie
end
end
m = Check_Get_Page.new
m.more_http
Любые предложения будут ценны!
5 ответов
Чтобы следовать перенаправлениям, вы можете сделать что-то вроде этого ( взято из ruby-doc)
После перенаправления
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
url = URI.parse(uri_str)
req = Net::HTTP::Get.new(url.path, { 'User-Agent' => 'Mozilla/5.0 (etc...)' })
response = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }
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/')
Учитывая URL, который перенаправляет
url = 'http://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fredirect-to%3Furl%3Dhttp%3A%2F%2Fexample.org'
A. Net::HTTP
begin
response = Net::HTTP.get_response(URI.parse(url))
url = response['location']
end while response.is_a?(Net::HTTPRedirection)
Убедитесь, что вы обрабатываете случай, когда существует слишком много перенаправлений.
B. OpenURI
open(url).read
OpenURI::OpenRead#open
по умолчанию выполняет перенаправления, но не ограничивает количество перенаправлений.
Я написал еще один класс для этого на основе приведенных здесь примеров, большое спасибо всем. Я добавил файлы cookie, параметры и исключения и, наконец, получил то, что мне нужно: https://gist.github.com/sekrett/7dd4177d6c87cf8265cd
require 'uri'
require 'net/http'
require 'openssl'
class UrlResolver
def self.resolve(uri_str, agent = 'curl/7.43.0', max_attempts = 10, timeout = 10)
attempts = 0
cookie = nil
until attempts >= max_attempts
attempts += 1
url = URI.parse(uri_str)
http = Net::HTTP.new(url.host, url.port)
http.open_timeout = timeout
http.read_timeout = timeout
path = url.path
path = '/' if path == ''
path += '?' + url.query unless url.query.nil?
params = { 'User-Agent' => agent, 'Accept' => '*/*' }
params['Cookie'] = cookie unless cookie.nil?
request = Net::HTTP::Get.new(path, params)
if url.instance_of?(URI::HTTPS)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
response = http.request(request)
case response
when Net::HTTPSuccess then
break
when Net::HTTPRedirection then
location = response['Location']
cookie = response['Set-Cookie']
new_uri = URI.parse(location)
uri_str = if new_uri.relative?
url + location
else
new_uri.to_s
end
else
raise 'Unexpected response: ' + response.inspect
end
end
raise 'Too many http redirects' if attempts == max_attempts
uri_str
# response.body
end
end
puts UrlResolver.resolve('http://www.ruby-lang.org')
Ссылка, которая работала для меня, находится здесь: http://shadow-file.blogspot.co.uk/2009/03/handling-http-redirection-in-ruby.html
По сравнению с большинством примеров (включая принятый здесь ответ), он более надежен, так как обрабатывает URL-адреса, которые являются просто доменом ( http://example.com/ - необходимо добавить /), обрабатывает SSL конкретно, а также относительные URL-адреса.
Конечно, в большинстве случаев лучше использовать библиотеку типа RESTClient, но иногда необходима низкоуровневая детализация.
Может быть, вы можете использовать гем curb-fu здесь https://github.com/gdi/curb-fu единственное, что нужно, это дополнительный код, чтобы он следовал за редиректом. Я использовал следующее раньше. Надеюсь, поможет.
require 'rubygems'
require 'curb-fu'
module CurbFu
class Request
module Base
def new_meth(url_params, query_params = {})
curb = old_meth url_params, query_params
curb.follow_location = true
curb
end
alias :old_meth :build
alias :build :new_meth
end
end
end
#this should follow the redirect because we instruct
#Curb.follow_location = true
print CurbFu.get('http://<your path>/').body
Если вам не нужно заботиться о деталях при каждом перенаправлении, вы можете использовать библиотеку Mechanize
require 'mechanize'
agent = Mechanize.new
begin
response = @agent.get(url)
rescue Mechanize::ResponseCodeError
// response codes other than 200, 301, or 302
rescue Timeout::Error
rescue Mechanize::RedirectLimitReachedError
rescue StandardError
end
Он вернет целевую страницу. Или вы можете отключить перенаправление следующим образом:
agent.redirect_ok = false
Или вы можете при желании изменить некоторые настройки по запросу
agent.user_agent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Mobile Safari/537.36"