当一个标签不在另一个标签中时,Beatifulsoup find_all

Beatifulsoup find_all when a tag is not inside another tag

提问人:hit 提问时间:10/27/2022 更新时间:10/27/2022 访问量:41

问:

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'}
html python-3.x beautifulsoup html解析

评论

0赞 Nuri Taş 10/27/2022
预期输出中的第二个和第三个元素没有多个标记吗?输出应包括 和 IIUC?<p>hello</p><h2>Price Return</h2>
0赞 hit 10/27/2022
我不想提取,因为它在 <tr> 标签中,同样用于<p>hello</p><h2>Price Return</h2>

答:

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