обойти неработающий Ruby URI.parse, следуйте перенаправлениям

Я использую Ruby для очистки веб-страниц, которые иногда возвращают перенаправления, которым я хочу следовать. Есть много драгоценных камней Ruby, которые делают это, но есть проблема:

Ruby URI.parse взрывается на некоторых URI, которые технически недействительны, но работают в таких браузерах, как "http://www.google.com/?q=<>"

URI.parse("http://www.google.com/?q=<>")               #=> error

require 'addressable/uri'
Addressable::URI.parse("http://www.google.com/?q=<>")  #=> works

Все клиентские библиотеки HTTP, которые я пробовал (HttParty, Faraday, RestClient), ломаются, когда сталкиваются с таким URI в перенаправлении (это на ruby ​​​​1.9.3)

отдых-клиент:

require 'rest-client'
RestClient.get("http://bitly.com/ReeuYv") #=> explodes

Фарадей:

require 'faraday'
require 'faraday_middleware'
Faraday.use(FaradayMiddleware::FollowRedirects)
Faraday.get("http://bitly.com/ReeuYv")    #=> explodes

httpвечеринка:

require 'httparty'
HTTParty.get("http://bitly.com/ReeuYv")   # => explodes

открытый-ури:

require 'open-uri'
open("http://bitly.com/ReeuYv")           # => explodes

Что я могу сделать, чтобы это сработало?


person levinalex    schedule 06.11.2012    source источник
comment
Что бы это ни стоило, URI.parse на самом деле просто соответствует RFC 3986 в этом случае. - < и > должны быть закодированы в URL. Браузеры просто более снисходительны.   -  person Thilo    schedule 06.11.2012
comment
Предположение, что URI, содержащий необработанный <>, является допустимым, неверно.   -  person Mark Thomas    schedule 06.11.2012
comment
хорошо. но все же, было бы неплохо, если бы это сработало. (поправил вопрос)   -  person levinalex    schedule 07.11.2012
comment
Было бы хорошо, если бы существовал простой http-жемчуг, столь же прощающий, как адресная строка браузера - существует множество ситуаций, когда допустимо, чтобы обработка URL-адресов соответствовала тому, к чему люди привыкли в повседневном использовании Интернета.   -  person robomc    schedule 11.10.2013


Ответы (4)


Mechanize — моя любимая жемчужина веб-скрейпинга.

Библиотека Mechanize используется для автоматизации взаимодействия с веб-сайтами. Mechanize автоматически сохраняет и отправляет файлы cookie, выполняет перенаправления и может переходить по ссылкам и отправлять формы. Поля формы могут быть заполнены и отправлены. Mechanize также отслеживает сайты, которые вы посетили, как историю.

require 'mechanize'
agent = Mechanize.new
page = agent.get('http://bitly.com/ReeuYv')
puts page.uri.to_s
=> http://www.google.com/?q=%3C%3E

Он использует nokogiri для анализа html, поэтому каждый объект Mechanize::Page можно рассматривать как объект nokogiri, поэтому вы можете получить биты html, например

puts page.form('f').q
=> <>

Последняя часть может показаться черной магией, но вам действительно нужно попробовать pp page самостоятельно. Это делает HTML таким простым для очистки.

Вот руководство по началу работы и документация.

person sunnyrjuneja    schedule 06.11.2012

Typhoeus работает:

require 'typhoeus'
Typhoeus::VERSION #=> "0.5.0.rc" 
Typhoeus.get("http://bitly.com/ReeuYv", followlocation: true).body
person levinalex    schedule 06.11.2012

Curb работает:

require 'curb'
Curl.get("http://bitly.com/ReeuYv") { |c| 
  c.follow_location = true 
}.body_str  #=>  works
person levinalex    schedule 06.11.2012

Это будет работать:

uri = URI.escape "http://www.google.com/?q=<>"


#=> "http://www.google.com/?q=%3C%3E"


URI.parse(uri) #=> no error
person Mark Thomas    schedule 06.11.2012
comment
Да. Но я не могу избежать URI, потому что он возвращается в ответе 302 с какого-то другого сервера и обрабатывается глубоко внутри той HTTP-библиотеки, которую я использую. (см. примеры в вопросе, http://bitly.com/ReeuYv — рабочий uri, демонстрирующий проблему) - person levinalex; 07.11.2012