1

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

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

我目前的工作是:

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

a 中的可能值href可能是:

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

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

4

3 回答 3

3

尝试 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
=> ""
于 2012-10-22T19:39:08.887 回答
2

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

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

基本上,回答你的问题

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

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

于 2012-10-22T19:40:32.103 回答
1

如果您使用 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://”。(您可能会遇到更多方案。有关更多信息,请参阅规范。)

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

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

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

  1. 从它开始#是一个锚点,将应用于当前页面而无需重新加载它。
  2. 不包含路径分隔符/,它是一个文件名,将添加到当前检索的 URL,替换文件名并检索。进行替换的一个好方法是使用File.dirname,File.basenameFile.join针对字符串。
  3. 以路径分隔符开头,它是绝对路径,用于替换原始 URL 中的路径。URI::split并且URI::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

于 2012-10-23T15:44:22.897 回答