使用BeautifulSoup爬取ESPN NBA比分返回空ResultSet的求助
解决ESPN NBA比分爬取返回空结果的问题
嘿,作为刚上手Python和BeautifulSoup的新手,碰到爬取ESPN比分返回空结果这种情况太正常啦!我帮你捋捋可能的问题,再给你靠谱的解决方案:
为啥会返回空结果?
咱先排查最常见的几个原因:
- 页面是动态加载的:ESPN的比分板数据大多是靠JavaScript动态渲染出来的,你用的
urllib.request只能拿到页面的静态HTML骨架,根本抓不到JS加载后的实际比分内容——这大概率是你现在的问题。 - 请求没带“身份标识”被拦截了:直接用
urllib发请求,没有模拟浏览器的请求头,很容易被ESPN的反爬机制当成爬虫,返回的可能是空白页面或者验证页面。 - 选择器没写对:就算拿到了正确的页面,你用的CSS选择器或标签定位要是没匹配到对应的比分元素,自然也拿不到数据。
一步步解决问题
1. 先换用requests库,加上浏览器请求头
requests比urllib好用太多,加上模拟浏览器的请求头,能避免被轻易拦截。先装一下(没装的话):
pip install requests
2. 处理动态页面的两种思路
如果加了请求头还是拿不到数据,那肯定是动态加载的锅,给你两种方案:
- 抓API接口(推荐!):打开浏览器按F12,切换到「Network」标签,刷新比分页面,找XHR/fetch类型的请求——ESPN一般会把比分数据放在JSON格式的API接口里,直接请求这个接口比解析HTML省心100倍。
- 用
selenium模拟浏览器:如果不想抓接口,就用selenium打开真实浏览器加载页面,这样能拿到完全渲染后的HTML内容。
3. 先试试静态请求+正确选择器的代码
先给你一段能用的静态请求代码,我特意适配了当前ESPN页面的元素结构(要是以后页面更新了,你可能得自己调整选择器):
from bs4 import BeautifulSoup import requests # 模拟浏览器的请求头,避免被拦截 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' } url = 'http://www.espn.co.uk/nba/scoreboard' response = requests.get(url, headers=headers) response.encoding = 'utf-8' soup = BeautifulSoup(response.text, 'html.parser') # 定位球队名称和比分的元素(当前页面的class,后续可能需要调整) team_names = soup.find_all('div', class_='TeamName__TeamName') score_elements = soup.find_all('div', class_='ScoreboardScoreCell__Score') # 输出结果 if team_names and score_elements: for team, score in zip(team_names, score_elements): print(f"{team.get_text(strip=True)}: {score.get_text(strip=True)}") else: print("没找到比分数据哦,大概率是页面动态加载或者结构更新了,试试下面的API方案吧")
4. 抓API接口的更省心方案
如果上面的代码还是返回空,就去抓API:
- 打开浏览器F12,访问ESPN比分页,在「Network」的XHR列表里找类似
scoreboard的请求,比如我找到的是https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard(具体以你抓的为准)。 - 直接请求这个API,返回的是JSON数据,解析起来超简单:
import requests headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' } # 替换成你抓包得到的API地址 api_url = 'https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard' response = requests.get(api_url, headers=headers) data = response.json() # 解析JSON拿比分、球队名这些信息 for event in data['events']: comp = event['competitions'][0] home_team = comp['competitors'][0]['team']['displayName'] home_score = comp['competitors'][0]['score'] away_team = comp['competitors'][1]['team']['displayName'] away_score = comp['competitors'][1]['score'] print(f"{away_team} {away_score} - {home_team} {home_score}")
小提醒
- ESPN的页面结构和API接口可能会随时更新,要是以后代码失效了,记得重新去页面里看元素或者抓新的接口哦。
- 别太频繁发请求,不然容易被封IP,必要时可以加个
time.sleep(2)之类的请求间隔。
内容的提问来源于stack exchange,提问作者uclaastro
相关产品推荐
相关产品推荐

