Python爬虫使用BeautifulSoup如何正确抓取文章全部段落
问题核心根因
- 重复抓取第一个段落的本质:
find()方法的固定行为就是从当前搜索范围内永远返回第一个匹配的元素,不会随循环迭代自动切换到下一个匹配项。你当前在循环内层反复调用find('p'),自然会反复定位到同一个p标签,导致内容重复。 - 触发
AttributeError的本质:find_all()返回的是ResultSet类型的对象(本质是储存多个Tag元素的列表),这个列表本身不具备单个Tag对象的属性和方法,不能像单个元素那样直接链式调用.p去内部找标签,必须先遍历列表里的每一个Tag元素,才能对元素本身执行查找操作。
代码修改步骤
- 第一步:调整查找逻辑的层级
不要在循环内部嵌套重复查找p标签的操作,直接定位包裹所有正文段落的父级div容器,对这个容器执行一次find_all('p'),一次性拿到所有p标签的元素集合。 - 第二步:遍历集合逐个提取文本
拿到p标签的元素集合后,循环遍历集合中的每一个Tag对象,单独提取每个对象的文本内容,同时过滤空内容的占位p标签。
错误写法和正确写法的代码对比:# 你当前使用的错误逻辑 # for article_div in article_root.find_all('div'): # content = article_div.find('p').text # 每次都只取第一个p,造成重复 # 修正后的核心逻辑 # 1. 从正文根容器一次性抓取所有p标签 p_tag_list = article_root.find_all('p') # 2. 逐个提取非空段落文本 clean_paragraphs = [] for p in p_tag_list: para_text = p.get_text(strip=True) if para_text: clean_paragraphs.append(para_text) - 第三步:按需求存储内容
- 存为TXT文件:将清洗后的段落列表用换行符拼接后写入本地文件即可
with open('article_content.txt', 'w', encoding='utf-8') as f: f.write('\n'.join(clean_paragraphs)) - 存为CSV文件:借助标准库csv模块,将每个段落作为单独一行逐行写入即可,不需要额外处理。
- 存为TXT文件:将清洗后的段落列表用换行符拼接后写入本地文件即可
避坑提示
- 严格区分
find()和find_all()的返回类型差异:find()返回单个Tag对象,支持链式属性调用;find_all()返回ResultSet列表,必须遍历后才能对内部的Tag元素执行操作,不能直接在列表对象上调用Tag的方法。 - 提取文本时优先使用
get_text()方法:相比直接访问.text属性,get_text()支持传入参数自动清理首尾空白,遇到空节点场景的容错性更强。 - 如果抓取的内容混入了p标签内嵌的广告、插件文本,可以在提取文本前先判断p标签的class、id属性,过滤掉不符合正文规则的元素。
内容的提问来源于stack exchange,提问作者Johnny Silverhand
相关产品推荐
相关产品推荐

