使用Python+Requests-HTML爬取赛事动态页面返回空DataFrame求助
问题分析与解决
你的代码出现Empty DataFrame的核心原因有两个:
- CSS选择器写法错误:分数对应的选择器使用了空格(后代选择器语法),但目标元素是同时拥有两个类名的节点,导致无法抓取到分数数据,后续循环因数据缺失无法生成有效DataFrame。
- 反爬与渲染不充分:flashscore存在反爬机制,单纯的页面渲染可能无法正确加载全部内容。
修正后的代码
import schedule import time from requests_html import HTMLSession from collections import defaultdict import pandas as pd def task(): matchlink = 'https://www.flashscore.com' session = HTMLSession() # 添加浏览器请求头,规避基础反爬识别 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' } r = session.get(matchlink, headers=headers) # 延长渲染超时时间并增加等待,确保动态内容加载完成 r.html.render(timeout=30, sleep=5) # 修正CSS选择器:多类名元素用点连接,而非空格 times = r.html.find(".event__time") home_teams = r.html.find(".event__participant.event__participant--home") scoresh = r.html.find(".event__score.event__score--home") away_teams = r.html.find(".event__participant.event__participant--away") scoresa = r.html.find(".event__score.event__score--away") dict_res = defaultdict(list) # 取所有列表的最小长度作为循环上限,避免索引越界 max_len = min(len(times), len(home_teams), len(scoresh), len(away_teams), len(scoresa)) for ind in range(max_len): dict_res['times'].append(times[ind].text) dict_res['home_teams'].append(home_teams[ind].text) dict_res['scoresh'].append(scoresh[ind].text) dict_res['away_teams'].append(away_teams[ind].text) dict_res['scoresa'].append(scoresa[ind].text) df = pd.DataFrame(dict_res) print(df) session.close() schedule.every(1).minutes.do(task) while True: schedule.run_pending() time.sleep(1)
关键修正说明
- 修复选择器:把
".event__score event__score--home"改为".event__score.event__score--home",空格表示"父元素下的后代元素",点表示"同时拥有两个类名的元素",这是你无法抓取分数数据的直接原因。 - 模拟浏览器请求:添加
User-Agent请求头,避免被网站的基础反爬机制拦截。 - 优化渲染逻辑:增加
sleep=5让页面有足够时间加载动态内容,延长timeout避免渲染超时。 - 防止索引越界:取所有数据列表的最小长度作为循环上限,避免因某类元素数量不一致导致报错。
额外注意点
- flashscore的页面结构可能随时更新,需要定期验证CSS选择器的有效性。
- 频繁请求可能触发反爬限制,建议适当延长任务执行间隔,或添加随机延迟。
内容的提问来源于stack exchange,提问作者Marcello Gabrielli
相关产品推荐
相关产品推荐

