Python中BS4 find_all()语句中的过滤功能问题

时间:2018-07-08 18:07:17

标签: python function beautifulsoup tags filtering

我正在抓取HTML网页。我在Mac(Sierra)上使用BeautifulSoup lib(4.6.0)和Python(3.7)。

除其他外,我看到了一堆具有类属性的'div'标签。一些'div'标签带有多个类属性值。现在我想根据标签名称和类属性值进行过滤,例如我想找到具有class ='a'但没有class ='b'的'div'标签(是的,有些div标签带有class ='a b')。

要获取这些标签,我尝试使用BS4文档(https://www.crummy.com/software/BeautifulSoup/bs4/doc/#a-function)中提到的过滤功能。我的印象是find_all()将bs4标签元素传递给该函数,并且在该函数内您可以执行对BS4标签元素的任何操作。这似乎是不正确的。我得到一个字符串,显然所有我的BS4标签元素操作都引发了异常。

两个问题:

  1. find_all()到底传递给函数什么?如何使用自变量?
  2. 除功能外,如何才能实现所需的功能?

1 个答案:

答案 0 :(得分:0)

  

给我的印象是find_all()将bs4标签元素传递给该函数,并且在该函数内您可以执行对BS4标签元素的任何操作。

您的印象是正确的。从bs4文档(重点是我的):

  

...定义一个将元素作为其唯一参数的函数。

因此,文档中的每个元素都将传递给filter函数,如果该函数为该元素返回True,则该元素将包含在.find_all()返回的元素列表中。实际上,这只能用作最后的选择,因为它可能会占用大量性能。我不完全确定为什么要获取字符串,一种可能是您正在将函数传递给class_=参数,该参数确实传递了字符串,但不能不看代码就不能说。

我认为您应该做的是使用.find_all()获取所有具有类“ a”的<div>,然后使用它们过滤掉那些仅包含没有类“ b”的那些自己的方法,像这样:

divs = soup.find_all('div', class_='a')
filtered_divs = [ div for div in divs if 'b' not in div.attrs['class'].split(' ') ]

但是,如果您确实想使用过滤器功能,看起来就像

class_a_not_b(e):
    if 'class' not in e.attrs: return False
    return 'a' in e.attrs['class'].split(' ') and 'b' not in e.attrs['class'].split(' ')

divs = soup.find_all(class_a_not_b)