从网络上抓取 URL

Ter*_* Li 0 ruby regex url hpricot web-scraping

<a href="http://www.utoronto.ca/gdrs/" title="Rehabilitation Science"> Rehabilitation Science</a>
Run Code Online (Sandbox Code Playgroud)

对于上面的例子,我想同时获取部门名称“康复科学”及其主页网址“http://www.utoronto.ca/gdrs/”。

有人可以建议一些可以为我完成这项工作的智能正则表达式吗?

the*_*Man 5

根本没有理由使用正则表达式来执行此操作。这是使用Nokogiri的解决方案,它是常见的 Ruby HTML/XML 解析器:

html = <<EOT
<p><a href="http://www.example.com/foo">foo</a></p>
<p><a href='http://www.example.com/foo1'>foo1</p></a>
<p><a href=http://www.example.com/foo2>foo2</a></p>
<p><a href = http://www.example.com/bar>bar</p>
<p><a 
  href="http://www.example.com/foobar"
  >foobar</a></p>
  <p><a 
    href="http://www.example.com/foobar2"
    >foobar2</p>
EOT

require 'nokogiri'

doc = Nokogiri::HTML(html)

links = Hash[
  *doc.search('a').map { |a| 
      [
        a['href'],
        a.content
      ]
    }.flatten
  ]

require 'pp'
pp links
# >> {"http://www.example.com/foo"=>"foo",
# >>  "http://www.example.com/foo1"=>"foo1",
# >>  "http://www.example.com/foo2"=>"foo2",
# >>  "http://www.example.com/bar"=>"bar",
# >>  "http://www.example.com/foobar"=>"foobar",
# >>  "http://www.example.com/foobar2"=>"foobar2"}
Run Code Online (Sandbox Code Playgroud)

这将返回 URL 的哈希值作为键,以标签的相关内容<a>作为值。这意味着您将只捕获唯一的 URL,并丢弃重复的 URL。如果您希望所有 URL 使用:

links = doc.search('a').map { |a| 
    [
      a['href'],
      a.content
    ]
  }
Run Code Online (Sandbox Code Playgroud)

结果是:

# >> [["http://www.example.com/foo", "foo"],
# >>  ["http://www.example.com/foo1", "foo1"],
# >>  ["http://www.example.com/foo2", "foo2"],
# >>  ["http://www.example.com/bar", "bar"],
# >>  ["http://www.example.com/foobar", "foobar"],
# >>  ["http://www.example.com/foobar2", "foobar2"]]
Run Code Online (Sandbox Code Playgroud)

我使用 CSS 访问器'a'来定位标签。'a[href]'如果我只想抓取链接,忽略锚点,我可以使用。

正则表达式在处理 HTML 和 XML 时非常脆弱,因为标记格式过于自由;它们的格式可能会有所不同,但仍保持有效,尤其是 HTML,其“正确性”可能会有很大差异。如果您不拥有正在解析的文件的生成,那么您的代码将受到使用正则表达式时生成它的人的支配;文件中的简单更改可能会严重破坏模式,从而导致持续的维护麻烦。

解析器因为实际上了解文件的内部结构,所以可以承受这些更改。请注意,我故意创建了一些格式错误的 HTML,但代码并不关心。比较解析器版本与正则表达式解决方案的简单性,并考虑长期可维护性。