<a href="http://www.utoronto.ca/gdrs/" title="Rehabilitation Science"> Rehabilitation Science</a>
对于上面的示例,我想同时获得部门名称“康复科学”及其主页网址“http://www.utoronto.ca/gdrs/”。
有人可以建议一些能为我做这个工作的智能正则表达式吗?
答案 0 :(得分:4)
没有理由使用正则表达式来完成此操作。这是使用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"}
这会将URL的哈希值作为键返回,并将<a>
标记的相关内容作为值。这意味着您只会捕获唯一的URL,从而丢失重复的内容。如果您希望所有网址都使用:
links = doc.search('a').map { |a|
[
a['href'],
a.content
]
}
导致:
# >> [["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"]]
我使用CSS访问器'a'
来定位标签。如果我只想抓住链接,忽略锚点,我可以使用'a[href]'
。
在处理HTML和XML时,正则表达式非常脆弱,因为标记格式过于自由;它们的格式可以保持有效,特别是HTML,它的“正确性”可能会有很大差异。如果您不拥有正在解析的文件的生成,那么您的代码将受到使用正则表达式时生成它的人的摆布;文件中的简单更改可能会严重破坏模式,从而导致持续的维护问题。
解析器,因为它实际上了解文件的内部结构,可以承受这些更改。请注意,我故意创建了一些格式错误的HTML,但代码并不关心。比较解析器版本与正则表达式解决方案的简单性,并考虑长期可维护性。
答案 1 :(得分:1)
我建议使用像@mrk建议的HTML解析器。然后取得结果你回来并通过正则表达式搜索者。我喜欢用Rubular。这将向您显示正则表达式捕获的内容,您可以避免获得不需要的结果。我发现使用正则表达式/ http [^“] + / work会在这样的情况下工作,因为即使没有”www。“它也会抓取整个url并且你避免捕获引号。
答案 2 :(得分:1)
如果你正在建造蜘蛛,那么Ruby's Mechanize是一个很好的选择。要获取页面并提取链接:
require 'rubygems'
require 'mechanize'
agent = Mechanize.new
page = agent.get "http://google.com/"
page.links.each do |link|
puts link.href
puts link.text
end
文档和指南(我链接到的)列出了很多你可能想要做的事情。使用正则表达式来解析HTML(或XML)是非常棘手且容易出错的。使用完整的解析器(正如其他人建议的那样)将节省您的工作量并使您的代码更加健壮。
答案 3 :(得分:0)
试图不要过于复杂:
#<a .*?href="([^"]*)".*>([^<]+)</a>#i
答案 4 :(得分:0)
这是我的Ruby方法:
require 'open-uri'
class HTMLScraper
def initialize(page)
@src = page
open(@src) do |x|
@html = x.read
end
end
def parseLinks
links = @html.scan(/<a\s+href\s*=\s*"([^"]+)"[^>]*>\s*([^<]+)\s*<\/a>/ui)
puts "Link(s) Found:"
i = 0
while i < links.length
puts "\t#{links[i]}"
i += 1
end
end
end
url = "http://stackoverflow.com/questions"
test = HTMLScraper.new(url)
test.parseLinks
这将为您提供一个数组数组,其中每个(内部)数组的第一项是url,第二项是标题。希望这有助于并注意正则表达式上的u
开关,这是为了避免编码问题。