【问题标题】:How to identify path/file/url in href如何在 href 中识别路径/文件/url
【发布时间】:2012-10-12 16:11:18
【问题描述】:

我正在尝试使用 Nokogiri 获取 <a> HTML 标签中的 href 值。

我想确定它们是路径、文件、URL,还是<div> id。

我目前的工作是:

hrefvalue = []
html.css('a').each do |atag|
        hrefvalue << atag['href']
end

href 中的可能值可能是:

somefile.html
http://www.someurl.com/somepath/somepath
/some/path/here
#previous

是否有一种机制来识别该值是有效的完整 URL、文件、路径还是其他?

【问题讨论】:

  • div ID 是 CSS 标签,而不是 URL,因此您无需检查这些标签。

标签: html ruby html-parsing nokogiri


【解决方案1】:

尝试 URI:

require 'uri'

URI.parse('somefile.html').path
=> "somefile.html"

URI.parse('http://www.someurl.com/somepath/somepath').path
=> "/somepath/somepath"

URI.parse('/some/path/here').path
=> "/some/path/here"

URI.parse('#previous').path
=> ""

【讨论】:

    【解决方案2】:

    Nokogiri 经常与 ruby​​ 的 URI 或 open-uri 一起使用,因此如果您遇到这种情况,您将可以访问它的方法。您可以使用它来尝试解析 URI(使用 URI.parse)。您通常也可以使用URI.join(base_uri, retrieved_href) 来构造完整的 url,前提是您已经存储了 base_uri。

    (编辑/旁注:有关使用 URI.join 的更多详细信息可在此处获得:https://stackoverflow.com/a/4864170/624590;请注意 URI.join 将字符串作为参数,而不是 URI 对象,因此在必要时强制执行)

    基本上,回答你的问题

    是否有一种机制来识别该值是否为有效的完整值 url,或文件,或路径或其他?

    如果 retrieved_href 和 base_uri 格式正确,并且 retrieved_href == 连接对,则它是绝对路径。否则它是相对的(同样,假设输入格式良好)。

    【讨论】:

    • Nokogiri 不使用 OpenURI。如果将文件句柄传递给"parsing" 方法,Nokogiri 将从该句柄中读取。如果你给它一个字符串,它会解析那个字符串。 OpenURI 的open 方法返回类似于文件句柄的东西。
    • 哎呀,你说得对,我写的很烂。我的意思是更多地暗示“人们通常使用 OpenURI 和 nokogiri 来检索要解析的 xml/html”,但回想起来,这并不是一个好的假设。
    【解决方案3】:

    如果您使用 URI 来解析 href 值,然后对结果应用一些启发式方法,您可以找出您想知道的内容。这基本上是浏览器在发送对页面或资源的请求时必须执行的操作。

    使用您的示例字符串:

    %w[
      somefile.html
      http://www.someurl.com/somepath/somepath
      /some/path/here
      #previous
    ].each do |u|
      puts URI.parse(u).class
    end
    

    结果:

    URI::Generic
    URI::HTTP
    URI::Generic
    URI::Generic
    

    URI 识别为真正的 HTTP URI 的唯一一个是“http://www.someurl.com/somepath/somepath”。所有其他人都缺少方案“http://”。 (您可能会遇到更多方案。有关更多信息,请参阅specification。)

    在通用 URI 中,您可以使用一些规则对它们进行排序,以便在必须打开它们时知道如何做出反应。

    如果您通过抓取页面收集 HREF 字符串,则可以假设如果相关 URI 不提供相同的方案和主机是安全的。因此,如果您最初加载了“http://www.someurl.com/index.html”,则可以使用“http://www.someurl.com/”作为进一步请求的基础。

    从那里,查看字符串内部以确定它们是锚点、绝对路径还是相对路径。如果是字符串:

    1. # 开头,它是一个锚点,无需重新加载即可应用于当前页面。
    2. 不包含路径分隔符/,它是一个文件名,将添加到当前检索的URL,替换文件名,然后检索。进行替换的一个好方法是对字符串使用 File.dirnameFile.basenameFile.join
    3. 以路径分隔符开头,它是绝对路径,用于替换原始 URL 中的路径。 URI::splitURI::join 是你的朋友。
    4. 不以路径分隔符开头,它是一个相对路径,与 #2 类似,会添加到当前 URI。

    关于:

    hrefvalue = []
    html.css('a').each do |atag|
            hrefvalue << atag['href']
    end
    

    我会改用这个:

    hrefvalue = html.search('a').map { |a| a['href'] }
    

    但那只是我。

    最后一点:URI 存在一些年龄问题,需要更新。这是一个有用的库,但是,对于重型 URI 撕裂,我强烈建议使用 Addressable/URI

    【讨论】:

    • 抓取随机网页时出现问题,永远不知道我会得到什么输出。但是,嘿,search() 方法看起来更方便。谢谢你
    • 没错,每一页都不一样。甚至一个站点中的页面也可能完全不同,因此,要成功地抓取或分析页面,您通常必须非常了解页面的内部布局。我曾经为我的工作编写爬虫程序和分析器,还做过一些大型网站,我已经数不清有多少次我就一些财富 50 强网站的设计向老板咆哮了。
    猜你喜欢
    • 2015-12-23
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多