【问题标题】:How to get a full URL given a shortened one passed to Nokogiri?给定一个缩短的 URL 传递给 Nokogiri,如何获得完整的 URL?
【发布时间】:2013-01-15 02:21:13
【问题描述】:

我想用 Nokogiri 遍历一些 HTML 文档。 获取 XML 对象后,我希望 Nokogiri 使用的最后一个 URL 获取文档作为我的 JSON 响应的一部分。

def url = "http://ow.ly/hh8ri"     
doc = Nokogiri::HTML(open(url)
...

Nokogiri 在内部将其重定向到 http://www.mp.rs.gov.br/imprensa/noticias/id30979.html,但我想访问它。

我想知道“doc”对象是否可以访问某些 URL 作为属性或其他东西。 有人知道解决方法吗?

顺便说一句,我想要完整的 URL,因为我正在遍历 HTML 以查找 <img> 标签,有些标签有相对的标签,例如:“/media/image/image.png”,然后我使用以下方法调整一些:

URI.join(url, relative_link_url).to_s

图片网址应为:

http://www.mp.rs.gov.br/media/imprensa/2013/01/30979_260_260__trytr.jpg 

代替:

http://ow.ly/hh8ri/media/imprensa/2013/01/30979_260_260__trytr.jpg

编辑:想法

class Scraper < Nokogiri::HTML::Document
  attr_accessor :url

  class << self

    def new(url)
        html = open(url, ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
        self.parse(html).tap do |d|
            url = URI.parse(url)
            response = Net::HTTP.new(url.host, url.port)
            head = response.start do |r|
              r.head url.path
            end 
            d.url = head['location']
        end
    end
  end
end

【问题讨论】:

  • Nokogiri 对 URL 一无所知,只知道一串 XML 或 HTML 内容,或文件句柄。 OpenURI 返回一个 StringIO,它模仿一个 IO 流,允许 Nokogiri 获取内容。

标签: ruby-on-rails ruby nokogiri mechanize scraper


【解决方案1】:

我最近遇到了完全相同的问题。我所做的是创建一个继承自Nokogiri::HTML::Document 的类,然后只需重写new 类方法来解析文档,然后将url 保存在带有访问器的实例变量中:

require 'nokogiri'
require 'open-uri'

class Webpage < Nokogiri::HTML::Document
  attr_accessor :url

  class << self

    def new(url)
      html = open(url)
      self.parse(html).tap do |d|
        d.url = url
      end
    end
  end
end

然后您可以创建一个新的Webpage,它可以访问您使用Nokogiri::HTML::Document 拥有的所有常规方法:

w = Webpage.new("http://www.google.com")
w.url
#=> "http://www.google.com"
w.at_css('title')
#=> [#<Nokogiri::XML::Element:0x4952f78 name="title" children=[#<Nokogiri::XML::Text:0x4952cb2 "Google">]>]

如果您有一些从图像标签中获得的相对 url,那么您可以通过将 url 访问器的返回值传递给 URI.join 来使其成为绝对 URL:

relative_link_url = "/media/image/image.png"
=> "/media/image/image.png"
URI.join(w.url, relative_link_url).to_s
=> "http://www.google.com/media/image/image.png"

希望对您有所帮助。

附言这个问题的标题非常具有误导性。更多类似“访问 Nokogiri HTML 文档的 URL”的内容会更清晰。

【讨论】:

  • 感谢您的回复!我试过你的代码,但不幸的是它仍然返回缩短的 url 而不是完整的。
  • 您的意思是当您获得src 的img 标签时,它会返回相对网址?它不会改变这一点。它所做的只是让您访问根 url,然后您可以加入它以获取文档中任何链接的完整 url。
  • 我添加了一个例子。看看这是否有意义。
  • 这是有道理的,除非“w.url”是像“bit.ly/234”这样的缩短链接
  • 我不明白。您的意思是要创建带有缩短链接的文档?那是行不通的。如果没有有关根的任何其他信息,则无法从相对 url 生成 URI。你必须在某个地方有一个绝对网址。
【解决方案2】:

使用机械化。网址将始终转换为绝对网址:

require 'mechanize'
agent = Mechanize.new
page = agent.get 'http://ow.ly/hh8ri'
page.images.map{|i| i.url.to_s}
#=> ["http://www.mp.rs.gov.br/images/imprensa/barra_area.gif", "http://www.mp.rs.gov.br/media/imprensa/2013/01/30979_260_260__trytr.jpg"]

【讨论】:

  • 很好,它有效!虽然它适用于绝对图像,但对于我的带有 xpath 和自定义东西的刮板来说,机械化对于其他想法来说太有限了。我不确定我是否同时使用 Mechanize 和 Nokogiri。但很好的答案。我将检查 Mechanize 核心代码,看看我是否可以从中学到一些东西。谢谢!
  • 机械化和 nokogiri 比你知道的更好。例如,mechanize 使用 nokogiri 作为解析器,而相同的开发人员维护这两个库。
  • 嗯。好的。你是对的,也许我会使用机械化。谢谢
【解决方案3】:

因为您的示例使用的是 OpenURI,所以这是要询问的代码,而不是 Nokogiri。 Nokogiri 不知道内容来自哪里。

OpenURI 可以轻松告诉你:

require 'open-uri'

starting_url = 'http://www.example.com'
final_uri = nil

puts "Starting URL: #{ starting_url }"

io = open(starting_url) { |io| final_uri = io.base_uri }
doc = io.read

puts "Final URL: #{ final_uri.to_s }"

哪些输出:

Starting URL: http://www.example.com
Final URL: http://www.iana.org/domains/example

base_uri 记录在 OpenURI::Meta 模块中。

【讨论】:

    猜你喜欢
    • 2017-05-11
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    相关资源
    最近更新 更多