Ruby Mechanize获取具有指定文本的元素

时间:2013-09-27 10:38:23

标签: css ruby mechanize

我正在尝试使用mechanize来解析网站的内容,而我却陷入困境。我要解析的内容位于li标记内,但并不总是以相同的顺序排列。

让我们假设我们有以下内容,其中li标签的顺序并不总是相同,有些甚至可能根本不存在。

<div class="details">
  <ul>
    <li><span>title 1</span> ": here are the details"</li>
    <li><span>title 2</span> ": here are the details"</li>
    <li><span>title 3</span> ": here are the details"</li>
    <li><span>title 4</span> ": here are the details"</li>
  </ul>
</div>

我想要的是仅获取li文字所在的span详细信息,例如title 3。我所做的是以下内容,它为我提供了第一个li

的详细信息
puts page.at('.details').at('span', :text => "title 3").at("+ *").text

有没有办法用机械化做我想做的事情,还是我还应该用其他方法?

4 个答案:

答案 0 :(得分:18)

page.search(".details").at("span:contains('title 3')").parent.text

说明: 使用 at ,您可以使用css或xpath选择器。为了使您的方法更具可读性和类似性,此答案使用css选择器,但问题是CSS无法基于文本执行选择。感谢Nokogiri,您可以使用JQuery选择器,因此允许包含方法。

选择获取span元素,因此如果要获取li元素parent,可以使用 parent 方法,然后轻松获取文本。

答案 1 :(得分:2)

由于您希望使用Mechanize(我看到其中一条评论建议使用Nokogiri),您应该知道Mechanize是建立在Nokogiri上的,因此您实际上可以使用任何/所有Nokogiri功能通过Mechanize。

通过http://mechanize.rubyforge.org/Mechanize.html

上的文档向您展示
  

Mechanize.html_parser = Nokogiri :: XML

所以你可以使用XPath和mechanize page.search方法完成这个。

  

page.search(“// div [@ class ='details'] / ul / li [span ='title 3']”)。text

这应该能够为您提供您正在寻找的li元素的文本。 (未经验证.text,但XPath确实有效)

您可以在此处测试XPath:http://www.xpathtester.com/saved/51c5142c-dbef-4206-8fbc-1ba567373fb2

答案 2 :(得分:1)

清洁css方法:

page.at('.details li:has(span[text()="title 3"])')

答案 3 :(得分:0)

根据评论,我认为你正在寻找类似下面的内容。

  

正如我所说的那样,问题在于它给了我第一个li而我想要的那个有文本标题3

require 'nokogiri'

doc = Nokogiri::HTML.parse <<-eotl
<div class="details">
  <ul>
    <li><span>title 1</span> ": here are the details"</li>
    <li><span>title 2</span> ": here are the details"</li>
    <li><span>title 3</span> ": here are the details"</li>
    <li><span>title 4</span> ": here are the details"</li>
  </ul>
</div>
eotl

node = doc.at_xpath("//div[@class='details']//span[contains(.,'title 3')]/..")
node.name # => "li"
puts node.to_html  
# <li>
# <span>title 3</span> ": here are the details"</li>
puts node.children
#<span>title 3</span>
# ": here are the details"