【问题标题】:(Rails) Can't get Mechanize to correctly read a web xml file(Rails) 无法让 Mechanize 正确读取 Web xml 文件
【发布时间】:2012-03-09 17:00:28
【问题描述】:

我必须通过身份验证读取可通过 http 访问的 xml 文件。这就是我使用机械化的原因。

我的问题是我无法通过 mechanize 来识别这些 XML 文件,因此我可以对它们使用 .find 或 .search。

这是我首先尝试的 - 在我看来(html 文件)

<% agent = Mechanize.new %>

<% page = agent.get("http://dl.dropbox.com/u/344349/xml.xml") %>

<%= page %>

返回#<Mechanize::File:0x007f9dd602de30>。这是::File 而不是::Page 我不能对此使用 .find 或 .search ,因为undefined method find for #<Mechanize::File:0x007f9dd624cbd0> 会出错

Mechanize 文档说:这是可插入解析器的默认(和基)类。如果 Mechanize 找不到合适的类用于内容类型,则将使用此类。例如,如果你下载一个 JPG,Mechanize 将不知道如何解析它,所以这个类将被实例化。

所以我创建了一个类,如下所述:http://rdoc.info/github/tenderlove/mechanize/master/Mechanize/PluggableParser

My class

class XMLParser < Mechanize::File

attr_reader :xml

def initialize(uri=nil, response=nil, body=nil, code=nil)

super(uri, response, body, code)

@xml = xml.parse(body)

end

end

以及我认为更新后的代码(html 文件)

<% agent = Mechanize.new %>

<% agent.pluggable_parser['text/xml'] = XMLParser %>

<% agent.user_agent_alias = 'Windows Mozilla' %>

<% page = agent.get("http://dl.dropbox.com/u/344349/xml.xml") %>

<%= page %>

甚至

<% agent = Mechanize.new %>

<% agent.pluggable_parser.xml = XMLParser %>

<% page1 = agent.get('http://dl.dropbox.com/u/344349/xml.xml') # => CSVParser %>

<%= page1 %>

仍然返回#<Mechanize::File:0x007f9dd5253b48>

我什至测试了确切的代码 (CSVParser - http://rdoc.info/github/tenderlove/mechanize/master/Mechanize/PluggableParser) 并尝试加载仍被视为 ::File 的 csv 文件。

我做错了什么?

【问题讨论】:

    标签: ruby-on-rails xml ruby-on-rails-3 parsing mechanize


    【解决方案1】:

    好的,我刚才已经为自己解决了这个问题。解决方案分为两部分:

    首先,您匹配的内容类型不正确。如果你运行这一行,在你得到之后,它会告诉你你得到的文档的内容类型是什么:

    page.response['content-type'] # => 'application/xml', not 'text/xml'
    

    当我使用 mechanize 获取您的页面 ('http://dl.dropbox.com/u/344349/xml.xml') 时,我将 'application/xml' 视为内容类型。

    其次,您没有正确使用 PluggableParser。在这里使用 XMLParser 将生成NoMethodError: undefined method 'parse' for nil:NilClass。更改类定义以使用 Nokogiri::XML 代替:

    class XmlParser < Mechanize::File
      attr_reader :xml
      def initialize(uri = nil, response = nil, body = nil, code = nil)
        @xml = Nokogiri::XML(body)
        super uri, response, body, code
      end
    end
    

    然后,将其设置为正确内容类型的解析器:

    mech.pluggable_parser['application/xml'] = XmlParser
    

    要使用它,您将获得与以前相同的页面,然后将页面对象的 xml 属性引用为 Nokogiri::XML::Document 实例,它是 Nokogiri::XML::Node 的子类。幸运的是,Mechanize::Page.search 只是Nokogiri::XML::Node.search 的包装,因此您几乎可以按照您期望的方式进行搜索。像这样:

    page.xml.search 'catalog'
    

    进一步的改进是将 XmlParser.search 映射到 Nokogiri .search 方法:

    # This is the same as what Mechanize::Page does
    class XmlParser < Mechanize::File
      extend Forwardable
      def_delegators  :@xml, :search, :/, :at
    end
    

    这让您可以直接在页面实例上执行搜索:

    page.search 'catalog'
    

    【讨论】:

    • 非常感谢!这是一个救生员!
    【解决方案2】:

    您可以更改解析器以使用 Page 类,喜欢它:

    agent = Mechanize.new
    agent.pluggable_parser.default = Mechanize::Page
    agent.get("http://dl.dropbox.com/u/344349/xml.xml").class # Mechanize::Page
    

    http://mechanize.rubyforge.org/Mechanize/PluggableParser.html

    【讨论】:

      猜你喜欢
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 2018-02-12
      • 2019-03-30
      • 2018-07-24
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多