Ruby Nokogiri文本搜索不使用br标签和其他人

时间:2017-07-10 18:19:35

标签: ruby nokogiri

我在Ruby中使用Nokogiri gem并遇到了一些问题。

我想从网页上抓取地址,并且地址的显示方式没有固定格式。

我有一个邮政编码列表,我希望我的Ruby脚本返回包含邮政编码的节点,以便找到地址的其余部分。

这是我在Ruby中的一些示例HTML内容:

require 'nokogiri'
require 'open-uri'

content1 = '
<div>
    <div>
        <div>Our Address:</div>
        1 North Street
        North Town
        North County
        N21 4DD
    </div>
</div>'

doc = Nokogiri::HTML(content1)
result = doc.search "[text()*='N21 4DD']"
puts result.inspect

这会返回[]

我理解上面的示例是一种以HTML格式显示地址的奇怪方式,但这是我能够展示我遇到的问题的最简单方法。这是另一个不返回任何内容的content变量:

content1 = '
<div>
    <div>Our Address:</div>
    <div>
        1 North Street<br>
        North Town<br>
        North County<br>
        N21 4DD
    </div>
</div>'

我知道Nokogiri可能会遇到上述问题,因为<br>代码应为</br>,但这在网站上很常见。

此示例有效:

content1 = '
<div>
    <div>Our Address:</div>
    <div>
        1 North Street
        North Town
        North County
        N21 4DD
    </div>
</div>'

有人可以解释为什么在上面的前两个content示例中找不到节点,以及如何解决这个问题?

我没有在上面的示例content示例中找到可以找到邮政编码的自定义解决方案 - 这些仅用于演示目的。邮政编码(和地址)可以是html中的任意位置 - bodypdivtdspanli等。

感谢。

2 个答案:

答案 0 :(得分:0)

使用Xpath:

doc.xpath('.//div[contains(.,"N21 4DD")]')

这仍然会返回两个节点,因为有一个嵌套的div。我不确定是否有办法让中间div没有'Our Address'div,因为它位于同一节点。

答案 1 :(得分:0)

让我们看一下第一个以及Nokogiri如何翻译你的“css”(这不是有效的css btw):

Nokogiri::CSS.xpath_for "[text()*='N21 4DD']"
#=> ["//*[contains(child::text(), 'N21 4DD')]"]

好的,所以这里的问题是child :: text()实际上只匹配第一个文本节点,即“我们的地址”div之前的空文本。

doc.search("//*[contains(child::text(), 'N21 4DD')]").length
#=> 0

没有匹配=不好。

现在让我们使用:contains伪:

尝试jquery-style
Nokogiri::CSS.xpath_for ":contains('N21 4DD')"
#=> ["//*[contains(., 'N21 4DD')]"]
doc.search("//*[contains(., 'N21 4DD')]").length
#=> 4

这实际上是正确的,但可能不是你所期望的。

让我们再尝试一下:

doc.search("//*[text()[contains(., 'N21 4DD')]]").length
#=> 1

听起来这就是你要找的东西。只是在子文本节点中包含字符串的div。