我正在尝试使用Hpricot和Ruby解析HTML文件,但我在提取“自由浮动”文本时遇到问题,该文本未包含在<p></p>
等标记中。
require 'hpricot'
text = <<SOME_TEXT
<a href="http://www.somelink.com/foo/bar.html">Testing:</a><br />
line 1<br />
line 2<br />
line 3<br />
line 4<br />
line 5<br />
<b>Here's some more text</b>
SOME_TEXT
parsed = Hpricot(text)
parsed = parsed.search('//a[@href="http://www.somelink.com/foo/bar.html"]').first.following_siblings
puts parsed
我希望结果是
<br />
line 1<br />
line 2<br />
line 3<br />
line 4<br />
line 5<br />
<b>Here's some more text</b>
但我得到了
<br />
<br />
<br />
<br />
<br />
<br />
<b>Here's some more text</b>
如何让Hpricot返回第1行,第2行等?
答案 0 :(得分:1)
您的第一步是阅读following_siblings文档:
查找跟随当前元素的兄弟元素。与其他“兄弟”方法一样,此清除文本和注释节点。
然后你应该使用Hpricot源来概括following_siblings
如何工作以获得像following_siblings
那样的东西,但不会过滤掉非容器节点:
parsed = Hpricot(text)
link = parsed.search('//a[@href="http://www.somelink.com/foo/bar.html"]').first
link_sibs = link.parent.children
what_you_want = link_sibs[link_sibs.index(link) + 1 ... link_sibs.length]
puts what_you_want
与following_siblings
而不是parent.children
相当parent.containers
。访问您使用的库的源代码非常方便,应该鼓励学习它。
答案 1 :(得分:0)
自从我使用Hpricot已经有一段时间了,但是我记得有些事情可能有所帮助:
快速获取所有文字的方法:
irb(main):023:0> print parsed.inner_text
Testing:
line 1
line 2
line 3
line 4
line 5
Here's some more text
缺点是你也将文本嵌入标签中。
同样,我们可以搜索所有'text()'
个节点:
irb(main):033:0> puts (parsed / 'text()')
Testing:
line 1
[...]
line 5
所以,我们可以这样做:
irb(main):036:0> puts (parsed / 'text()')[2 .. -3]
line 1
line 2
line 3
line 4
line 5
或:
irb(main):037:0> (parsed / 'text()')[2 .. -3]
=> #<Hpricot::Elements["\n line 1", " \n line 2", "\n line 3", "\n line 4", "\n line 5", "\n "]>
或:
irb(main):039:0> (parsed / 'text()')[2 .. -3].map{ |t| t.inner_text.strip }
=> ["line 1", "line 2", "line 3", "line 4", "line 5", ""]
从网页抓取数据/文本的主要想法是查找可用于浏览页面的地标。我们通常可以从<div>
或<p>
标记内抓取文字。如果页面没有给你标记,你必须使用其他技巧;可能会查找一系列文本节点,后跟<br>
个节点,或者<a>
标记后面的五行,并且具有某个href
属性。这是处理HTML的乐趣和挑战。
在我的脑海里,有一种唠叨的想法,有一种更优雅的方式来做到这一点,但这似乎是有效的。在Hpricot Challenge page上挖掘有关挖掘内容主题的变体。