You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用requests+bs4/json爬取Bovada MLB数据遇内容不一致问题

解决Bovada MLB赛事数据爬取的问题

我来帮你拆解一下你遇到的问题,然后一步步解决它:

为什么requests返回的HTML和浏览器显示不一致?

这是因为Bovada这类网站用了JavaScript动态渲染内容。当你用requests.get()请求页面时,它只会获取服务器返回的静态HTML,不会执行页面里的JavaScript代码——而浏览器会自动执行JS,动态加载赛事数据、赔率这些内容,所以你在浏览器开发者工具里看到的完整内容,requests根本拿不到。

另外,你尝试用view-source:https://...作为请求URL是完全错误的,view-source:是浏览器的内置功能协议,不是一个可通过HTTP请求的地址,requests自然无法获取到数据。


正确的爬取步骤

1. 找到数据的实际来源

你提到页面底部有iframe和包含目标数据的JSON,那我们先从iframe入手:首先请求主页面,找到iframe的真实URL,然后直接请求这个iframe页面,因为里面才是承载数据的地方。

2. 代码实现(分步解析)

第一步:请求主页面,提取iframe链接

import requests
from bs4 import BeautifulSoup
import json

# 模拟浏览器的请求头,避免被网站识别为爬虫
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'
}

main_url = 'https://sports.bovada.lv/baseball/mlb/game-lines-market-group'
response = requests.get(main_url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')

# 找到页面中的iframe(你可以根据实际页面的iframe属性调整,比如id、class)
iframe = soup.find('iframe')
if not iframe:
    print("没找到包含数据的iframe,可能网站结构变了")
else:
    # 拼接完整的iframe URL(如果src是相对路径的话)
    iframe_src = iframe['src']
    if not iframe_src.startswith('http'):
        iframe_src = 'https://sports.bovada.lv' + iframe_src

第二步:请求iframe页面,提取JSON数据

请求iframe页面后,数据通常会藏在某个<script>标签里的JSON结构中,我们需要定位并提取:

# 请求iframe页面
iframe_response = requests.get(iframe_src, headers=headers)
iframe_soup = BeautifulSoup(iframe_response.text, 'lxml')

# 遍历所有script标签,寻找包含目标数据的内容
for script in iframe_soup.find_all('script'):
    script_content = script.text.strip()
    # 用你提到的'itemList'作为关键词定位
    if 'itemList' in script_content:
        # 清理JSON字符串(去掉前面的变量赋值和后面的多余符号)
        json_start = script_content.find('{')
        json_end = script_content.rfind('}') + 1
        json_str = script_content[json_start:json_end]
        
        # 解析JSON
        try:
            data = json.loads(json_str)
            item_list = data.get('itemList', [])
            
            # 提取你需要的字段(这里的键名需要根据实际JSON结构调整)
            for game in item_list:
                # 球队信息
                team_home = game.get('homeTeam', {}).get('name')
                team_away = game.get('awayTeam', {}).get('name')
                # 投手信息
                pitcher_home = game.get('homePitcher', {}).get('name')
                pitcher_away = game.get('awayPitcher', {}).get('name')
                # 赔率
                odds_home = game.get('homeOdds')
                odds_away = game.get('awayOdds')
                # 总得分
                total_score = game.get('total', {}).get('overUnder')
                
                # 打印结果(或者保存到文件/数据库)
                print(f"赛事:{team_away} vs {team_home}")
                print(f"投手:{pitcher_away} | {pitcher_home}")
                print(f"赔率:客队 {odds_away} | 主队 {odds_home}")
                print(f"总得分:{total_score}\n")
        except json.JSONDecodeError as e:
            print(f"解析JSON出错:{e}")
        break

3. 备选方案:直接找API接口

如果iframe的方法不好用,你可以用浏览器的开发者工具(F12打开),切换到Network标签,刷新页面后,筛选XHR或Fetch请求,找包含mlb、game-lines这类关键词的请求——这些就是网站直接获取数据的API接口。

找到API URL后,直接用requests.get()请求这个URL(带上同样的headers),就能直接拿到结构化的JSON数据,比解析HTML更高效。


注意事项

  • 反爬机制:博彩网站通常有反爬措施,不要频繁请求,建议加time.sleep()控制间隔;如果遇到403/503错误,可能需要添加Cookie到headers里(从浏览器复制当前会话的Cookie)。
  • 网站结构变化:这类网站的页面结构和API可能会随时更新,代码需要根据实际情况调整字段名或定位逻辑。

内容的提问来源于stack exchange,提问作者Michael T Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:27:55