【问题标题】:How to select from between header elements in Ruby如何从 Ruby 中的标题元素之间进行选择
【发布时间】:2020-02-04 05:30:43
【问题描述】:

我正在编写一个使用 Nokogiri 和 CSS 选择器的 Ruby 脚本。我正在尝试从 HTML 中抓取一些如下所示的数据:

<h2>Title 1</h2>
(Part 1)
<h2>Title 2</h2>
(Part 2)
<h2>Title 3</h2>
(Part 3)

有没有办法仅通过指定代表起点和终点的 h2 元素的文本来从 Part 2 中进行选择?

Part 2 中感兴趣的数据是一个包含 tr 和 td 元素的表,这些元素没有任何 class 或 id 标识符。其他部分也有我不感兴趣的表格。像

page.css('table tr td')

在整个页面上,除了我想要的那个之外,我还会从所有其他表格中进行选择,如果可能的话,我想避免这种情况。

【问题讨论】:

  • 欢迎来到 SO!请参阅“How to Ask”以及链接页面和“mcve”。如果同事把问题递给你,然后走开,你能理解并回答吗?如果没有,你想知道什么?这也是我们需要的那种信息,否则我们必须做出很多假设和猜测。你尝试了什么?为什么它不起作用?
  • CSS 选择器并不能真正胜任这项工作。相反,您最好使用 XPath,它具有更丰富的工具集来查看嵌入文本和同级。

标签: ruby css-selectors nokogiri


【解决方案1】:

我可能会将此作为第一次尝试:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
  <h2>Title 1</h2>
    (Part 1)
  <h2>Title 2</h2>
    <table>
      <tr><td>(Part 2)</td></tr>
    </table>
  <h2>Title 3</h2>
    (Part 3)
EOT

doc.css('h2')[1].next_element.to_html # => "<table>\n      <tr><td>(Part 2)</td></tr>\n    </table>"

或者,我可以将一些任务传递给 CSS 选择器,而不是使用 css('h2')[1]:

doc.at('h2:nth-of-type(2)').next_element
  .to_html # => "<table>\n      <tr><td>(Part 2)</td></tr>\n    </table>"

next_element 是用于查找当前节点之后的节点的技巧。有许多“下一个”和“上一个”方法,因此请仔细阅读它们,因为它们对于这种情况非常有用。

最后,to_html 用于向我们展示 Nokogiri 在更友好的输出中返回的内容。除非需要输出 HTML,否则您不会使用它。

【讨论】:

    【解决方案2】:

    我可能会将此作为第一次尝试:

    require 'nokogiri'
    
    doc = Nokogiri::HTML(<<EOT)
      <h2>Title 1</h2>
        (Part 1)
      <h2>Title 2</h2>
        <table>
          <tr><td>(Part 2)</td></tr>
        </table>
      <h2>Title 3</h2>
        (Part 3)
    EOT
    
    doc.css('h2')[1].next_element
      .to_html # => "<table>\n      <tr><td>(Part 2)</td></tr>\n    </table>"
    

    或者,我可以将一些任务传递给 CSS 选择器,而不是使用 css('h2')[1]:

    doc.at('h2:nth-of-type(2)').next_element
      .to_html # => "<table>\n      <tr><td>(Part 2)</td></tr>\n    </table>"
    

    一旦您有了表格,就很容易从中获取数据。有很多例子如何做到这一点。

    【讨论】:

      【解决方案3】:

      如果您知道这些表将是静态的,并且您需要的数据将始终位于第二个表中。您可以执行以下操作:

      page.css('table')[1].css('tr')[3].css('td')
      

      这将为我们获取页面上的第二个表,访问该表的第 4 行并获取该行的所有值。

      我没有对此进行测试,但如果我需要的表没有类或标识符,我会这样做。

      【讨论】:

        【解决方案4】:

        根据“Is there a CSS selector for elements containing certain text?”,恐怕没有 CSS 选择器对元素文本起作用。先提取“(Part 2)”,然后用Nokogiri选择里面的表格元素怎么样?

        text = "" //your string, or content from a file
        
        part2 = text.scan(/<h2>Title 2<\/h2>\s+(.+)?<h2>/ms).first.first
        
        doc = Nokogiri::HTML(part2)
        
        # continue select table elements from doc
        

        (Part 2) 不能包含任何h2 标签,否则正则表达式应该不同。

        【讨论】:

        • 不要使用正则表达式搜索 HTML。如果 HTML 发生变化,模式很容易被破坏或泄漏。而是使用解析器。
        猜你喜欢
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-04
        • 2011-03-28
        • 1970-01-01
        • 2014-12-04
        相关资源
        最近更新 更多