Mechanize - 如何在rails中关注或“单击”Meta刷新

时间:2011-02-15 12:00:27

标签: ruby-on-rails ruby mechanize

我对Mechanize有点麻烦。

使用Mechanize提交表单时。我来到一个页面有一个元刷新,没有链接。

我的问题是我如何关注元刷新?

我试图允许元刷新,但后来我收到套接字错误。 示例代码

require 'mechanize'
agent = WWW::Mechanize.new
agent.get("http://euroads.dk")
form = agent.page.forms.first
form.username = "username"
form.password = "password"
form.submit
page = agent.get("http://www.euroads.dk/system/index.php?showpage=login")
agent.page.body

回应:

<html>
 <head>
   <META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=index.php?showpage=m_frontpage\">
 </head>
</html>

然后我尝试:

redirect_url = page.parser.at('META[HTTP-EQUIV=\"Refresh\"]')[
  "0;URL=index.php?showpage=m_frontpage\"][/url=(.+)/, 1]

但我明白了:

NoMethodError: Undefined method '[]' for nil:NilClass

2 个答案:

答案 0 :(得分:4)

在内部,Mechanize使用Nokogiri来处理将HTML解析为DOM。您可以访问Nokogiri文档,这样您就可以使用XPath或CSS访问器在返回的页面中进行挖掘。

这是如何使用Nokogiri获取重定向网址:

require 'nokogiri'

html = <<EOT
<html>
  <head>
    <meta http-equiv="refresh" content="2;url=http://www.example.com/">
    </meta>
  </head>
  <body>
    foo
  </body>
</html>
EOT

doc = Nokogiri::HTML(html)
redirect_url = doc.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1]
redirect_url # => "http://www.example.com/"

doc.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1]细分为:查找at标记的CSS访问者的第一个匹配项(<meta>),http-equiv属性为refresh。获取该标记的content属性,并返回url=后面的字符串。

这是一些典型用途的Mechanize代码。因为您没有提供示例代码,所以您必须使用此代码:

agent = Mechanize.new
page = agent.get('http://www.examples.com/')
redirect_url = page.parser.at('meta[http-equiv="refresh"]')['content'][/url=(.+)/, 1]
page = agent.get(redirect_url)

编辑:at('META[HTTP-EQUIV=\"Refresh\"]')

您的代码具有以上at()。请注意,您正在转义单引号字符串中的双引号。这导致反斜杠后跟字符串中的双引号,这不是我的样本使用的,这是我第一次猜到你为什么会得到错误。 Nokogiri找不到标签,因为没有<meta http-equiv=\"Refresh\"...>

编辑:通过设置:

,Mechanize有一种处理元刷新的内置方式
 agent.follow_meta_refresh = true

它还有parse the meta tag的方法并返回内容。来自文档:

  

解析(内容,uri)

     

从元标记的content属性中解析延迟和网址。当没有指定url时,Parse需要当前页面的uri来推断url。如果给出了一个块,则解析的延迟和url将被传递给它以进行进一步处理。   如果无法解析延迟和url,则返回nil。

# <meta http-equiv="refresh" content="5;url=http://example.com/" />
uri = URI.parse('http://current.com/')

Meta.parse("5;url=http://example.com/", uri)  # => ['5', 'http://example.com/']
Meta.parse("5;url=", uri)                     # => ['5', 'http://current.com/']
Meta.parse("5", uri)                          # => ['5', 'http://current.com/']
Meta.parse("invalid content", uri)            # => nil

答案 1 :(得分:2)

Mechanize treats meta refresh elements just like links without text.因此,您的代码可以像这样简单:

page = agent.get("http://www.euroads.dk/system/index.php?showpage=login")
page.meta_refresh.first.click