基于BeautifulSoup的Stack Overflow爬虫运行失效 触发NoneType无text属性报错
爬虫NoneType报错与重复输出的原因与修正方案
核心问题定位
- 选择器范围过宽是触发
'NoneType' has no attribute 'text'报错的最主要原因。代码中使用.find('div', id='questions').find_all('div')逻辑,会递归抓取该容器下所有嵌套层级的div节点,而非仅匹配单条问题的外层结构块。这些嵌套在问题块内部的子节点(如标签容器、投票模块、链接模块)本身不包含<h3>标题节点、也没有独立的tags容器,代码尝试访问summary.h3或summary.find("div", class_="tags")时会返回None,后续调用.text属性就会触发类型报错。 - 请求方法使用错误。Stack Overflow问题列表是纯静态页面,正常应使用GET方法请求,当前代码用POST方法发请求,虽然平台会做基础兜底响应,但返回的页面可能存在不完整、结构偏差的问题,会进一步放大解析异常。
- 重复输出的原因和选择器过宽直接相关。因为抓取了全层级的div节点,同一条问题的外层块、块内部嵌套的关联节点都能匹配到h3标题,遍历到这些节点时就会重复输出同一条问题内容。
修正实现
修正方向为收窄选择器范围、使用正确的请求方法、优化取值逻辑避免硬依赖节点存在:
import requests from bs4 import BeautifulSoup url = 'https://stackoverflow.com/questions?tab=newest&page=' # 配置基础请求头,避免被平台反爬策略拦截 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } # 静态页面使用GET方法请求 r = requests.get(url, headers=headers) soup = BeautifulSoup(r.text, 'lxml') # 直接匹配单条问题的外层独立块,避免抓取嵌套子div question_blocks = soup.find('div', id='questions').find_all('div', class_='question-summary') for summary in question_blocks: # 节点存在性判断,跳过结构异常的块 title_node = summary.h3 tag_node = summary.find('div', class_='tags') if not title_node or not tag_node: continue print(f'Question: {title_node.text.strip()}') # 直接读取标签下的a节点文本,替代字符串切割逻辑 tag_list = [tag.text.strip() for tag in tag_node.find_all('a')] print(f'Tags: {", ".join(tag_list)}')
说明:BeautifulSoup返回的解析对象不存在“无故出现空节点”的情况,所有被匹配到的节点都是符合查找规则的普通DOM节点。报错的本质是查找节点的规则过宽,把不符合单条问题结构的内部子div也纳入了遍历范围,才会出现访问属性时拿到None的问题。
内容的提问来源于stack exchange,提问作者Crabby Fish
相关产品推荐
相关产品推荐

