Python循环爬取运动员页面时如何提前检测表格以规避解析报错
落地实现方案
前置特征校验(零解析开销预判)
不用等Pandas解析跑起来触发异常,拿到页面返回的HTML文本后,先匹配BJJHeroes生涯数据表格的固定结构锚点:该网站的战绩统计块有专属的文本标识,只要页面文本里不存在这类标识,就说明没有有效生涯数据,直接跳过后续解析逻辑,根本不会触发解析报错。
- 核心判断逻辑示例:
# 收到页面响应后先做特征扫描,完全不碰解析流程 page_content = response.text target_markers = ["W/L ratio", "career-stats", "fight-history"] # 所有标记一个都没命中,直接跳过当前循环 if not any(marker in page_content for marker in target_markers): continue
这个判断比跑完整的Pandas解析快一个数量级,完全可以在循环里逐页跑,不会拖慢爬取速度。
兜底异常捕获
就算做了前置校验,也难免碰到页面结构临时调整、个别表格标记不匹配的情况,把pd.read_html的调用放在独立的try-except块里,专门捕获Pandas抛出的ValueError: No tables found异常,碰到这类情况直接给对应运动员存空值,不会中断整个爬取循环。
- 参考写法:
try: page_tables = pd.read_html(page_content) # 二次过滤,把页面里其他无关的杂表排除掉,只留目标生涯数据 valid_tables = [t for t in page_tables if "Win" in str(t.columns) or "W/L" in str(t.columns)] stats_result = valid_tables[0] if valid_tables else None except ValueError: # 无表格的页面直接记空值,不抛错 stats_result = None
- 顺带修正现有代码的几个硬伤,不然后续跑还是会出问题:
- 变量名错位:最开始解析全站名单用的是
all_athletes,后面循环里却用table_heroes取名单数据,实际table_heroes根本没初始化,跑起来直接报NameError。 - 缩进逻辑错误:现在的
if request.status_code ==200判断没有放在循环内部,实际是整个循环跑完之后,只对最后一个请求的页面做一次解析,完全不是逐运动员处理的逻辑。 - 重复发请求:每个运动员的URL第一次没带自定义headers就发了一次请求,后面状态码判断里又带headers发了第二次,相当于每个页面请求两次,平白增加被封IP的概率。
- 变量名错位:最开始解析全站名单用的是
源头减少无效请求
最开始解析全站运动员名单列表的时候,可以顺带筛选:名单页里带战绩详情链接的条目才是有生涯数据的,直接把无链接的条目过滤掉,能从源头上少发60%-70%的无数据页面请求,根本不用逐页判断有没有表格。
内容的提问来源于stack exchange,提问作者micheldc55
相关产品推荐
相关产品推荐

