beautifulsoup,找到文本为'price'的th,然后获取下一个th中的价格
我的HTML代码是这样的:
<td>
<table ..>
<tr>
<th ..>price</th>
<th>$99.99</th>
</tr>
</table>
</td>
现在我在当前的表格单元格里,我该怎么获取99.99这个值呢?
到目前为止,我有:
td[3].findChild('th')
但我需要做的是:
找到包含'price'这个文字的 使用pyparsing库,我们可以很方便地在HTML中找到某种标签的模式,比如下面这个: pyparsing的 (Combine的作用有两个:它禁止数字组件之间有空格;并且返回一个合并后的单一标记"99.99",而不是列表 想象一下这个过程是分步骤的……假设有一个 那么这个子树里所有包含文本 这些项目的父节点自然就是: 如果你只想保留那些“名字”(标签)是 接着你想要那些项目的“下一个兄弟节点”(但只限于它们也是 在这里你会发现使用列表推导式的问题:重复的部分太多,因为我们不能把中间结果简单地命名。那我们就换回传统的循环方式……: 编辑:根据提问者的评论,增加了对父节点 我添加了 说到结构,注意我用了两次标签,然后获取下一个 标签的字符串值。
2 个回答
from pyparsing import makeHTMLTags, Combine, Word, nums
th,thEnd = makeHTMLTags("TH")
floatnum = Combine(Word(nums) + "." + Word(nums))
priceEntry = (th + "price" + thEnd +
th + "$" + floatnum("price") + thEnd)
tokens,startloc,endloc = priceEntry.scanString(html).next()
print tokens.price
makeHTMLTags
这个助手函数会返回一对表达式,一个用于开始标签,一个用于结束标签。开始标签的模式不仅仅是把给定的字符串前后加上"<>",它还允许有额外的空格、大小写不敏感,以及标签属性的有无。例如,虽然我指定了"TH"作为表头标签,但它也可以匹配"th"、"Th"、"tH"和"TH"。pyparsing默认会跳过多余的空格,比如标签和"$"之间、"$"和数字价格之间等等,这样我们就不需要到处加上“这里可以有零个或多个空格”的提示了。最后,通过给结果命名为"price"(在priceEntry
的定义中跟在floatum
后面),我们可以很简单地从匹配priceEntry
表达式的完整列表中获取这个特定的值。["99", ".", "99"]
。)x
,它是你正在考虑的子树的根节点,x.findAll(text='price')
'price'
的项目列表就是:[t.parent for t in x.findAll(text='price')]
[t.parent for t in x.findAll(text='price')]
'th'
的项目,那当然可以这样做:[t.parent for t in x.findAll(text='price') if t.parent.name=='th']
'th'
),所以:[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']
th
和“下一个兄弟节点”之间文本的容忍度,以及后者是td
的情况。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
ns.string
,这会在下一个兄弟节点的内容只有文本(没有进一步嵌套的标签)时返回内容——当然,你也可以在这个时候进行更深入的分析,这取决于你应用的需求!)。同样,我想你不会只是用print
,而是会做一些更聪明的事情,但我给你提供了结构。if...: continue
:这样可以减少嵌套,相比于反转if
的条件并缩进后面的所有语句,这样更简单——而“扁平化比嵌套更好”是Python Zen中的一个原则(在交互式提示符下输入import this
可以看到所有原则并思考一下;-)。撰写回答