提问人:hit 提问时间:10/27/2022 更新时间:10/27/2022 访问量:41
当一个标签不在另一个标签中时,Beatifulsoup find_all
Beatifulsoup find_all when a tag is not inside another tag
问:
html = """
<html>
<h2>Top Single Name</h2>
<table>
<tr>
<p>hello</p>
</tr>
</table>
<div>
<div>
<h2>Price Return</h2>
</div>
</div>
</html>
"""
当我使用以下代码时
from bs4 import BeautifulSoup
import re
soup = BeautifulSoup(html, 'html.parser')
soup.find_all(['p', 'li', 'dl', 'tr', 'div', re.compile("^h[1-6]$")])
我得到的输出是
[<h2>Top Single Name</h2>,
<tr><p>hello</p></tr>,
<p>hello</p>,
<div>
<div>
<h2>Price Return</h2>
</div>
</div>,
<div>
<h2>Price Return</h2>
</div>,
<h2>Price Return</h2>]
但我需要的只是以下三个要素
[<h2>Top Single Name</h2>,
<tr><p>hello</p></tr>,
<div>
<div>
<h2>Price Return</h2>
</div>
</div>
]
基本上,如果它位于另一个标签内,我不想提取特定标签,有什么方法可以像下面这样进行一些映射并在代码中使用,当键在值内时不要提取
{'re.compile("^h[1-6]$")': 'div', 'div':'div', 'p': 'tr'}
答:
0赞
Driftr95
10/27/2022
#1
基本上,如果特定标签在另一个标签内,我不想提取它
我认为最简单的方法可能是像现在一样使用,然后通过检查列表中是否有祖先/父母来过滤掉嵌套标签find_all
sel = soup.find_all(['p', 'li', 'dl', 'tr', 'div', re.compile("^h[1-6]$")])
sel = [s for s in sel if not [p for p in sel if p in s.parents]]
-- 如果标签的 tagName 在列表中,则结果与获取标签的结果相同,只要他们的父母都没有列出的名称之一:
selTags = ['p', 'li', 'dl', 'tr', 'div'] + [f'h{i}' for i in range(1,7)]
sel = soup.find_all(lambda t: t.name in selTags and not t.find_parent(selTags))
但是,如果您想按地图进行过滤
有什么方法可以让我有一些像下面这样的映射,并在代码中使用,当键在值内时不要提取
你可以使用
parentMap = {'div':'div', 'p': 'tr'}
for i in range(1,7): parentMap[f'h{i}'] = 'div'
# parentMap = {'div': 'div', 'p': 'tr', 'h1': 'div', 'h2': 'div', 'h3': 'div', 'h4': 'div', 'h5': 'div', 'h6': 'div'}
sel = soup.find_all(
lambda t: t.name in
['p', 'li', 'dl', 'tr', 'div']+[f'h{i}' for i in range(1,7)]
and not (
t.name in parentMap and
t.find_parent(parentMap[t.name]) is not None
)
)
在这种情况下,无论哪种方式,您都应该得到相同的结果,但是如果您的 html 包含
<p><tr>I am a row in a paragraph</tr></p>
然后,第一个方法将仅返回外部标记,而最后一个方法将同时返回标记和内部标记 [除非您添加 ]。<p>
<p>
<tr>
'tr': 'p'
parentMap
评论
<p>hello</p>
<h2>Price Return</h2>
<p>hello</p>
<h2>Price Return</h2>