使用BeautifulSoup抓取BSCScan数据时无法找到tbody下的tr元素报错
报错根因
这个错误是因为执行soup.find('table', class_='table table-md-text-normal table-hover')时没有匹配到对应的DOM元素,返回了None,后续调用None.find()就触发了属性不存在的报错。
未匹配到元素最核心的原因是BSCScan站点有反爬机制,你直接用默认配置的requests发送请求,站点会返回403拦截页面、人机验证页面而非正常的持仓数据页,返回的HTML里根本没有你要找的表格结构。
其次小概率原因是站点近期更新了前端页面结构,表格的class属性或层级发生了变化。
解决方案
步骤1:添加请求头模拟浏览器访问
首先给requests请求添加User-Agent头,模拟普通浏览器的请求特征,大部分情况可以绕过基础反爬。
步骤2:增加异常校验逻辑
不要直接调用返回对象的方法,先做非空判断,方便定位问题:
- 先打印请求响应状态码
print(r.status_code),如果返回403/404说明请求被拦截或者地址失效 - 先打印返回的HTML前1000字符
print(r.text[:1000]),确认返回内容是否为正常的持仓页面,是否包含人机验证相关的关键词
步骤3:进阶反爬绕过方案
如果加了User-Agent还是被拦截,可以尝试以下操作:
- 手动在浏览器访问目标地址后,复制请求头里的Cookie字段加到requests的headers参数中
- 使用selenium、playwright等自动化浏览器工具模拟真实用户访问,直接读取渲染后的页面DOM
修改后可运行的参考代码:
import requests from bs4 import BeautifulSoup url = 'https://bscscan.com/token/generic-tokenholders2?m=normal&a=0xe56842ed550ff2794f010738554db45e60730371' # 添加模拟浏览器的请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36' } r = requests.get(url, headers=headers) # 先校验请求状态 if r.status_code != 200: print(f"请求被拦截,状态码:{r.status_code}") exit() soup = BeautifulSoup(r.text, 'lxml') t = soup.find('table', class_='table table-md-text-normal table-hover') # 先校验表格是否获取成功 if not t: print("未匹配到目标表格,返回内容异常,大概率触发反爬") exit() trs = t.find('tbody').find_all('tr') for tr in trs[:5]: print(list(tr.stripped_strings))
内容的提问来源于stack exchange,提问作者rbutrnz
相关产品推荐
相关产品推荐

