如何用BeautifulSoup抓取不含指定类名关键词的p标签?
解决抓取不含指定类名关键词的p标签问题
方法一:使用自定义过滤函数(推荐)
逻辑清晰易维护,通过class_参数传入过滤函数,精准筛选符合条件的p标签:
import requests import bs4 url = 'https://www.sp2.upenn.edu/person/amy-hillier/' req = requests.get(url).text soup = bs4.BeautifulSoup(req, 'html.parser') # 定义需要排除的类名关键词集合 exclude_keywords = { 'Header', 'header', 'button', 'Root', 'root', 'logo', 'Title', 'title', 'Foot', 'foot', 'Publish', 'Story', 'story', 'Stories', 'stories', 'Link', 'link', 'color', 'space', 'email', 'address', 'download', 'capital' } def filter_p_classes(class_attr): # 没有class属性的p标签直接保留 if class_attr is None: return True # 拆分class属性为单个类名 classes = class_attr.split() # 检查所有类名都不包含任何排除关键词 for cls in classes: for keyword in exclude_keywords: if keyword in cls: return False return True # 直接筛选所有符合条件的p标签 for p_tag in soup.find_all('p', class_=filter_p_classes): print(p_tag)
方法二:修正CSS选择器写法
CSS选择器的:not()不支持用|做多条件或,需将每个排除关键词单独写成:not([class*="关键词"])的形式叠加使用:
import requests import bs4 url = 'https://www.sp2.upenn.edu/person/amy-hillier/' req = requests.get(url).text soup = bs4.BeautifulSoup(req, 'html.parser') # 构造完整的CSS选择器 selector = ( 'p:not([class*="Header"]):not([class*="header"]):not([class*="button"])' ':not([class*="Root"]):not([class*="root"]):not([class*="logo"])' ':not([class*="Title"]):not([class*="title"]):not([class*="Foot"])' ':not([class*="foot"]):not([class*="Publish"]):not([class*="Story"])' ':not([class*="story"]):not([class*="Stories"]):not([class*="stories"])' ':not([class*="Link"]):not([class*="link"]):not([class*="color"])' ':not([class*="space"]):not([class*="email"]):not([class*="address"])' ':not([class*="download"]):not([class*="capital"])' ) # 使用选择器筛选p标签 for p_tag in soup.select(selector): print(p_tag)
原方法失败原因分析
正则表达式方法错误:
BeautifulSoup中{'class': regex}的匹配逻辑是将正则应用到单个类名(而非整个class属性字符串)。你的正则试图匹配整个属性字符串不含关键词,但实际会被拆分到每个类名单独校验,导致筛选逻辑混乱。CSS选择器方法错误:
CSS选择器中[class*="a|b"]会匹配包含a|b字面字符串的class,而非包含a或b的class。同时:not()不支持多条件或,必须将每个排除条件单独写为:not()规则。
内容的提问来源于stack exchange,提问作者mangarapaul
相关产品推荐
相关产品推荐

