【问题标题】:How to extract URL parameters from a URL with Ruby or Rails?如何使用 Ruby 或 Rails 从 URL 中提取 URL 参数?
【发布时间】:2011-01-30 19:46:04
【问题描述】:

我有一些网址,比如

http://www.example.com/something?param1=value1&param2=value2&param3=value3

我想从这些 URL 中提取参数并将它们放入哈希中。显然,我可以使用正则表达式,但我只是想知道使用 Ruby 或 Rails 是否有更简单的方法来做到这一点。我在 Ruby 模块 URI 中没有找到任何东西,但也许我错过了一些东西。

事实上,我需要一种方法来做到这一点:

extract_parameters_from_url("http://www.example.com/something?param1=value1&param2=value2&param3=value3")
#=> {:param1 => 'value1', :param2 => 'value2', :param3 => 'value3'}

你有什么建议吗?

【问题讨论】:

  • Hash[*string.split('&').collect{|i|i.split('=')}.flatten] 这也可以,但对于这种情况,这可能是最糟糕的选择。但是您仍然可能会发现这个 sn-p 很有趣。 (发表评论,因为我不认为这是一个答案:-))

标签: ruby-on-rails ruby uri url-parameters


【解决方案1】:

在 Ruby 2.7/3 中使用 CGI 可能是一种过时的方法。

这是使用 URI 执行此操作的一种巧妙方法:

uri = URI.parse 'https://duckduckgo.com/?q=ruby+programming+language'
params = Hash[URI.decode_www_form uri.query]
# => {"q"=>"ruby programming language"} 

【讨论】:

    【解决方案2】:

    遗憾的是,URIaddressable 库在尝试从有缺陷的 URL 中提取查询参数时都会中断。例如。这打破了两者:

    http://localhost:4300/webapp/foo/#//controller/action?account=001-001-111&email=john%40email.com
    

    以 Arthur / Levi 的解决方案为基础,使用 url.split("?").try(:last),您可以只获取 URL 的查询参数部分,并使用 Rack::Utils.parse_nested_query 将该参数字符串解析为哈希。

    或全部:

    Rack::Utils.parse_nested_query(url.split("?").try(:last))
    

    在我的示例中返回:

    {"account": "001-001-111", "email": "john@email.com"}
    

    【讨论】:

      【解决方案3】:

      你也可以用这个方法

      
      require 'uri'
      require 'cgi'
      uri = URI("https://example.com/?query=1&q=2&query=5")
      a = CGI::parse(uri.query)
      puts a                   #=> {"query"=>["1", "5"], "q"=>["2"]}
      puts a["query"].to_s     #=> ["1", "5"]
      puts a["query"][0]       #=>  1
      puts a["query"][1]       #=>  5
      puts a["q"][0]           #=>  2
      
      
      

      它安全且容易得多

      【讨论】:

        【解决方案4】:

        我认为您想将任何给定的 URL 字符串转换为 HASH?

        你可以试试http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

        require 'cgi'
        
        CGI::parse('param1=value1&param2=value2&param3=value3')
        

        返回

        {"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
        

        【讨论】:

        • 好的,那是我错过的!与 URI.parse 一起使用时非常完美:CGI.parse(URI.parse("example.com/…) 返回所需的哈希值。感谢您的帮助。
        • 为了清楚起见,@Flackou 想要这个:CGI.parse(URI.parse(url).query)
        • 我没有测试过这个,但是列出的第一个键,包含完整的 url,似乎真的错了。
        • 我实际上不得不使用这个:CGI::parse(URI::parse(url).query)
        【解决方案5】:

        查看addressable gem - Ruby 的 URI 模块的流行替代品,它使查询解析变得容易:

        require "addressable/uri"
        uri = Addressable::URI.parse("http://www.example.com/something?param1=value1&param2=value2&param3=value3")
        uri.query_values['param1']
        => 'value1'
        

        (与 URI 不同,它显然也处理参数编码/解码)

        【讨论】:

        • 遗憾的是,它看起来像 URI 库一样,在 URL 很奇怪的情况下难以解析查询参数。 IE。当urls 为奇数时,两者都找不到查询参数,例如这个:http://localhost:4300/webapp/foo/#//controller/action? 让我使用类似的 hack:Rack::Utils.parse_nested_query(url.split("?").last) 来获取用于解析的查询参数。
        【解决方案6】:

        解决问题的方法不止一种。其他人向您展示了一些技巧。我知道另一个技巧。这是我的尝试:-

        require 'uri'
        url = "http://www.example.com/something?param1=value1&param2=value2&param3=value3"
        uri = URI(url)
        # => #<URI::HTTP:0x89e4898 URL:http://www.example.com/something?param1=value1&param2=value2&param3=value3>
        URI::decode_www_form(uri.query).to_h # if you are in 2.1 or later version of Ruby
        # => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
        Hash[URI::decode_www_form(uri.query)] # if you are below 2.1 version of Ruby
        # => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
        

        阅读::decode_www_form的方法文档。

        【讨论】:

          【解决方案7】:

          对于纯 Ruby 解决方案,将 URI.parseCGI.parse 结合使用(即使不需要 Rails/Rack 等也可以使用):

          CGI.parse(URI.parse(url).query) 
          # =>  {"name1" => ["value1"], "name2" => ["value1", "value2", ...] }
          

          【讨论】:

            【解决方案8】:

            上面的 Levi 答案刚刚改进 -

            Rack::Utils.parse_query URI("http://example.com?par=hello&par2=bye").query
            

            对于像上面的url这样的字符串,它会返回

            { "par" => "hello", "par2" => "bye" } 
            

            【讨论】:

            • 很好的答案。简单,像操作要求的那样处理完整的 URL,结果值是字符串而不是数组,就像其他答案一样。谢谢。
            • 正如我上面评论的那样,对于任何寻找逆向的人来说,它是Rack::Utils.build_query(params)
            • 当心 - 不完全相反,至少在 Ruby 1.8.7 / Rails 2.3 中不是。 foo[]=1&foo[]=2 的查询字符串被正确解析为 { "foo" =>["1","2"] },但 build_query 将其转换为 "foo=1&foo=2",在解析时再次产生 { "foo"=>"2"}。
            • 我花了一分钟才意识到,由于缺少包装参数,这个答案不容易扩展。 Rack::Utils.parse_query(URI("http://example.com?par=hello&amp;par2=bye").query) 产生一个可以进一步修改的哈希。
            【解决方案9】:

            我发现自己在最近的一个项目中也需要同样的东西。 在 Levi 的解决方案的基础上,这里有一种更清洁、更快捷的方法:

            Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
            # => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
            

            【讨论】:

            • 比模拟 Rack 请求更轻量级
            • 很好的发现。如果您有简单的参数(非嵌套)并且对性能敏感,那么 Rack::Utils.parse_query 可能会感兴趣。代码值得一读:github.com/rack/rack/blob/master/lib/rack/utils.rb
            • 谢谢,很有用:)
            • 这很好用,但不适用于具有相同名称的复选框:param1=value1&amp;param1=value2。第二个值胜过第一个。
            • 对于任何寻找逆向的人,它是Rack::Utils.build_nested_query(params)(或Rack::Utils.build_query(params),如果用Rack::Utils.parse_query解析)。
            【解决方案10】:

            在您的控制器中,您应该能够访问名为params 的字典(哈希)。因此,如果您知道每个查询参数的名称是什么,那么只需执行params[:param1] 即可访问它...如果您不知道参数的名称是什么,您可以遍历字典并获取键。

            一些简单的例子here

            【讨论】:

            • 好的,我知道,它在请求 URL 的控制器中运行良好,但是如何为其他任意 URL 做到这一点?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-06-15
            • 2014-12-24
            • 2022-11-13
            • 2021-10-20
            • 2017-01-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多