【问题标题】:work around Ruby's broken URI.parse, follow redirects解决 Ruby 损坏的 URI.parse,遵循重定向
【发布时间】:2012-11-06 19:33:39
【问题描述】:

我正在使用 Ruby 抓取有时会返回我想要关注的重定向的网页。 有很多 Ruby gem 可以做到这一点,但是有一个问题:

Ruby 的 URI.parse 会在一些技术上无效但在 "http://www.google.com/?q=<>" 等浏览器中工作的 URI 上爆炸

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

打开 uri:

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

我可以做些什么来完成这项工作?

【问题讨论】:

  • 对于它的价值,URI.parse 在这种情况下实际上只是符合 RFC 3986 - &lt;&gt; 应该是 URL 编码的。浏览器更宽容。
  • 包含原始&lt;&gt; 的URI 是有效的假设是不正确的。
  • 好的。但是,如果这可行,那就太好了。 (更正了问题)
  • 一个像浏览器地址栏一样宽容的简单 http gem 将是一件好事 - 在许多情况下,url 处理与人们过去习惯的内容相匹配是有效的一天的网络使用量。

标签: ruby-on-rails ruby httparty rest-client faraday


【解决方案1】:

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 对象,因此您可以像

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

最后一部分可能看起来像黑魔法,但你真的需要亲自尝试pp page。它使 HTML 很容易被抓取。

Here 是入门指南和文档。

【讨论】:

    【解决方案2】:

    Typhoeus 工作:

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

    【讨论】:

      【解决方案3】:

      Curb 似乎有效:

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

      【讨论】:

        【解决方案4】:

        这将起作用:

        uri = URI.escape "http://www.google.com/?q=<>"
        
        
        #=> "http://www.google.com/?q=%3C%3E"
        
        
        URI.parse(uri) #=> no error
        

        【讨论】:

        • 是的。但我无法转义 URI,因为它是从其他服务器以 302 响应返回的,并在我使用的任何 HTTP 库内部进行处理。 (请参阅问题中的示例,http://bitly.com/ReeuYv 是一个演示问题的工作 uri)
        猜你喜欢
        • 1970-01-01
        • 2015-03-01
        • 2012-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-28
        • 2013-09-11
        相关资源
        最近更新 更多