【问题标题】:selecting second child in beautiful soup with soup.select?在美丽的汤汤中选择第二个孩子。选择?
【发布时间】:2014-09-03 10:04:22
【问题描述】:

我有:

<h2 id='names'>Names</h2>
<p>John</p>
<p>Peter</p>

如果我已经有 h2 标签,那么现在让 Peter 到达这里的最简单方法是什么?现在我试过了:

soup.select("#names > p:nth-child(1)")

但在这里我得到 nth-child NotImplementedError:

NotImplementedError: Only the following pseudo-classes are implemented: nth-of-type.

所以我不确定这里发生了什么。第二种选择是只获取所有 'p' 标记子项并硬选择 [1],但是存在索引超出范围的危险,这需要使用 try/except 包围每次获取 Peter 的尝试这有点傻。

有什么方法可以用soup.select() 函数选择nth-child?

编辑: 用 nth-of-type 替换 nth-child 似乎可以解决问题,所以正确的行是:

soup.select("#names > p:nth-of-type(1)")

不确定为什么它不接受 nth-child,但似乎 nth-child 和 nth-of-type 都返回相同的结果。

【问题讨论】:

    标签: python web-scraping beautifulsoup


    【解决方案1】:

    美汤4.7.0(2019年初发布)now supports大部分选择器,包括:nth-child

    从 4.7.0 版开始,Beautiful Soup 通过 SoupSieve 项目支持大多数 CSS4 选择器。如果你通过pip安装了Beautiful Soup,SoupSieve 是同时安装的,所以你不需要做任何额外的事情。

    所以,如果你升级你的版本:

    pip install bs4 -U
    

    您将能够使用几乎所有您需要的选择器,包括nth-child

    也就是说,请注意在您的输入 HTML 中,#names h2 标记实际上没有任何子标记:

    <h2 id='names'>Names</h2>
    <p>John</p>
    <p>Peter</p>
    

    这里只有3个元素,都是兄弟,所以

    #names > p:nth-child(1)
    

    即使在 CSS 或 Javascript 中也不行。

    如果#names 元素将&lt;p&gt;s 作为子元素,那么您的选择器将在一定程度上起作用:

    html = '''
    <div id='names'>
        <p>John</p>
        <p>Peter</p>
    </div>
    '''
    soup = BeautifulSoup(html, 'html.parser')
    soup.select("#names > p:nth-child(1)")
    

    输出:

    [<p>John</p>]
    

    当然,John &lt;p&gt;#names 父级的第一个子级。如果你想要Peter,请使用:nth-child(2)

    如果元素都是相邻的兄弟,可以使用+选择下一个兄弟:

    html = '''
    <h2 id='names'>Names</h2>
    <p>John</p>
    <p>Peter</p>
    '''
    soup = BeautifulSoup(html, 'html.parser')
    soup.select("#names + p + p")
    

    输出:

    [<p>Peter</p>]
    

    【讨论】:

    • 正确的语法是 "nth-of-type" / "nth-of-child" 无论版本如何,您的语法都不起作用
    • 我知道我在发布答案之前测试了所有的 sn-ps。我又试了一次,sn-ps 都对我有用。没有nth-of-child 这样的东西。 nth-child 是一个合适的选择器并且可以工作(参见CSS docs),nth-of-type 也是如此。
    • 如果它不存在,为什么它在您发布的第一个链接的第一个示例中是正确的?你在自相矛盾
    • 我没有看到它在任何地方列出... i.stack.imgur.com/ZQJeH.png nth-of-child 不存在。 (相比之下,标准 CSS 选择器 nth-childnth-of-type 确实存在)
    【解决方案2】:

    将您的编辑添加为答案,以便其他人更容易找到它:

    使用nth-of-type 代替nth-child

    soup.select("#names > p:nth-of-type(1)")
    

    【讨论】:

      【解决方案3】:

      'nth-of-child' 根本没有在 beautifulsoup4 中实现(在撰写本文时),beautifulsoup 代码库中根本没有代码可以做到这一点。作者明确添加了“NotImplementedError”来解释这一点,here is the code

      鉴于您在问题中引用的 html,您不是在寻找 h2#names 的孩子。

      你真正要找的是第二个相邻的兄弟,我不是 css 选择专家,但我发现这行得通。

      soup.select("#names + p + p")
      

      【讨论】:

      • 它确实有效,但是我用 nth-of-type 而不是 nth-child 做的,这似乎也能解决问题。
      猜你喜欢
      • 2023-04-03
      • 2021-07-14
      • 2020-12-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-09
      相关资源
      最近更新 更多