BeautifulSoup:查找类名:AND + NOT

sto*_*ney 6 html python beautifulsoup

我在 HTML 中有两组不同的 div 标签:

<div class="ABC BCD CDE123">

<div class="ABC BCD CDE234">

<div class="ABC BCD CDE345">
Run Code Online (Sandbox Code Playgroud)

<div class="ABC XYZ BCD">
Run Code Online (Sandbox Code Playgroud)

我想选择其中包含 ABC 和 BCD 的所有标签,但不包含 BeautifullSoup4 的 XYZ 类。

我已经知道这种方法:

soup.find_all('div', class_=['ABC','BCD'])
Run Code Online (Sandbox Code Playgroud)

其搜索为OR (因此 ABC 或 BCD 必须存在)。

我也知道这里的这种方法:

def myfunction(theclass):
    return theclass is not None and len(theclass)=5
soup.find_all('div', class_=myfunction)
Run Code Online (Sandbox Code Playgroud)

这将返回类名长度为 5 的所有 div

然后我尝试用这个来解决我的问题:

soup.find_all('div', class_ = lambda x: x and 'ABC' and 'BCD' in x.split() and x and 'XYZ' not in x.split())
Run Code Online (Sandbox Code Playgroud)

但这不起作用。所以我尝试用这种方法来调试它:

def myfunction(theclass):
    print theclass
    return True
soup.find_all('div', class_=myfunction)
Run Code Online (Sandbox Code Playgroud)

问题似乎是来自这样的标签:

<div class="ABC BCD CDE123">
Run Code Online (Sandbox Code Playgroud)

只有“ABC”被移交给myfunction,所以theclass = 'ABC' 这不是theclass ='ABC BCD CDE123'我所期望的。这也是我猜测 lambda 函数失败的原因。

任何关于如何根据我的要求过滤标签的线索:

我想选择其中包含 ABC 和 BCD 的所有标签,但不包含 BeautifullSoup4 的 XYZ 类。

Sau*_*dey 2

这可以使用SET来完成。获取 ABC 和 BCD 类的所有结果列表。将结果包含在 python SET 中。对 XYZ 应用相同的方法。您现在将有两套,一套用于 ABC 和 BCD,另一套用于 XYZ。将两个集合相减

要在搜索列表中使用 ABC 和 BCD,请使用select函数而不是find_all

from bs4 import BeautifulSoup

data = '''
<div class="ABC BCD CDE123"></div>
<div class="ABC BCD CDE234"></div>
<div class="ABC BCD CDE345"></div>
<div class="ABC XYZ BCD"></div>
<div class="ABC XYZ AAC"></div>
<div class="ABC AAC"></div>
'''

soup = BeautifulSoup(data)
ABC_BCD = set(soup.select('div.ABC.BCD'))
XYZ     = set(soup.select('div.XYZ'))
result = ABC_BCD - XYZ
for element in result:
    print element
Run Code Online (Sandbox Code Playgroud)

输出

<div class="ABC BCD CDE234"></div>
<div class="ABC BCD CDE123"></div>
<div class="ABC BCD CDE345"></div>
Run Code Online (Sandbox Code Playgroud)

使用 find_all 使用相同的代码

ABC_BCD = set(soup.find_all('div', class_=['ABC','BCD']))
XYZ     = set(soup.find_all('div', class_=['XYZ']))
result = ABC-BCD
for element in result:
    print element
Run Code Online (Sandbox Code Playgroud)

输出是

<div class="ABC BCD CDE234"></div>
<div class="ABC AAC"></div> #This is what we dont need
<div class="ABC BCD CDE123"></div>
<div class="ABC BCD CDE345"></div>
Run Code Online (Sandbox Code Playgroud)