beautifulsoup,找到文本'价格',然后从下一个获得价格

Bla*_*man 5 python beautifulsoup

我的HTML看起来像:

<td>
   <table ..>
      <tr>
         <th ..>price</th>
         <th>$99.99</th>
      </tr>
   </table>
</td>
Run Code Online (Sandbox Code Playgroud)

所以我在当前的表格单元格中,如何获得99.99的值?

我到目前为止:

td[3].findChild('th')
Run Code Online (Sandbox Code Playgroud)

但我需要这样做:

找到文本'price',然后得到下一个标签的字符串值.

Ale*_*lli 8

在"步骤"中考虑一下......假设有些x是您正在考虑的子树的根,

x.findAll(text='price')
Run Code Online (Sandbox Code Playgroud)

是包含文本的子树中所有项目的列表'price'.那些物品的父母当然会是:

[t.parent for t in x.findAll(text='price')]
Run Code Online (Sandbox Code Playgroud)

如果你只想保留那些"名称"(标签)的人'th',那么当然

[t.parent for t in x.findAll(text='price') if t.parent.name=='th']
Run Code Online (Sandbox Code Playgroud)

而且你想要那些"下一个兄弟姐妹"(但只有当它们也是'th's)时,所以

[t.parent.nextSibling for t in x.findAll(text='price')
 if t.parent.name=='th' and t.parent.nextSibling and t.parent.nextSibling.name=='th']
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到使用列表推导的问题:重复次数过多,因为我们无法将中间结果分配给简单名称.因此,让我们切换到一个好的旧循环...:

编辑:为父th和"下一个兄弟" 之间的文本字符串添加容差,以及td根据OP的注释对后者的容忍度.

for t in x.findAll(text='price'):
  p = t.parent
  if p.name != 'th': continue
  ns = p.nextSibling
  if ns and not ns.name: ns = ns.nextSibling
  if not ns or ns.name not in ('td', 'th'): continue
  print ns.string
Run Code Online (Sandbox Code Playgroud)

我已经补充说ns.string,这将给出下一个兄弟的内容,当且仅当它们只是文本(没有进一步的嵌套标签)时 - 当然你可以在此时进一步分析,取决于你的应用程序的需求! - ).同样地,我想你不会只做print更聪明的事情,但我会给你结构.

谈到结构,请注意我使用两次if...: continue:与反转if条件和缩小循环中的所有后续语句的替代方法相比,这减少了嵌套- 并且"扁平比嵌套好"是其中的一个koans Python的禅(import this在互动的提示下,看到他们所有并打坐;-).