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

使用BeautifulSoup爬取Oddsportal西甲赔率时遇选择器语法错误求助

解决Oddsportal西甲赔率抓取的错误问题

嘿,我来帮你搞定这个抓取赔率时遇到的错误!

先说说你遇到的核心问题

你看到的soupsieve.util.SelectorSyntaxError是因为你的CSS选择器里混进了不可见的控制字符(\x1b,也就是ESC转义字符),导致选择器解析器直接罢工了。从错误提示的标记位置能看出来,这个隐藏字符藏在选择器里,让#tournamentTable td[xodd]变成了非法语法。

另外还有个隐性坑:Oddsportal的赔率数据大多是JavaScript动态加载的,就算你修复了选择器,用requests只能拿到静态HTML,大概率还是拿不到你想要的10行3列赔率数据。

一步步修复方案

1. 先把选择器的脏字符清掉

先重新写个干净的选择器,避免隐藏字符的干扰,你可以用两种方式来筛选带xodd属性的td:

第一种,修复后的CSS选择器写法:

import requests
from bs4 import BeautifulSoup as bs

url = 'https://www.oddsportal.com/soccer/spain/laliga'
r = requests.get(url, 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'})
soup = bs(r.content, 'lxml')

# 用干净的选择器筛选,同时清理文本空格
odds = [b.text.strip() for b in soup.select('#tournamentTable td[xodd]')]
print(odds)

第二种,用find_all加属性筛选,比CSS选择器更不容易出语法问题:

table = soup.find('table', id='tournamentTable')
if table:
    odds = [td.text.strip() for td in table.find_all('td', attrs={'xodd': True})]
    print(odds)
else:
    print("没找到目标赛事表格哦")

2. 解决动态加载的核心问题

上面的代码能解决语法错误,但大概率拿不到完整赔率,因为静态HTML里没有这些动态渲染的数据。这时候得用selenium模拟浏览器加载页面,才能拿到渲染后的完整内容:

首先安装selenium:

pip install selenium

然后下载对应你Chrome浏览器版本的ChromeDriver(注意版本要匹配),然后用下面的代码:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup as bs
import time

# 配置无头浏览器(不弹出窗口)
chrome_options = Options()
chrome_options.add_argument('--headless=new')
chrome_options.add_argument('--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')

# 启动浏览器
driver = webdriver.Chrome(options=chrome_options)
url = 'https://www.oddsportal.com/soccer/spain/laliga'
driver.get(url)

# 给页面一点加载时间,避免数据还没渲染完
time.sleep(3)

# 获取完整的渲染后页面源码
soup = bs(driver.page_source, 'lxml')

# 提取并整理成10行3列的格式
table = soup.find('table', id='tournamentTable')
if table:
    odds_cells = table.find_all('td', attrs={'xodd': True})
    # 每3个td为一组(胜、平、负赔率)
    odds_groups = [odds_cells[i:i+3] for i in range(0, len(odds_cells), 3)]
    # 取前10组数据
    for idx, group in enumerate(odds_groups[:10]):
        print(f"赛事{idx+1}:{' | '.join([cell.text.strip() for cell in group])}")
else:
    print("未找到赛事表格,可能页面结构变了或者被反爬拦截了")

# 记得关闭浏览器
driver.quit()

3. 一些避坑提示

  • ChromeDriver的版本必须和你的Chrome浏览器版本完全匹配,不然会启动失败。
  • Oddsportal有反爬机制,别太频繁请求页面,加个time.sleep()很有必要。
  • 网站的HTML结构可能会不定期更新,如果之后又拿不到数据,记得重新检查页面元素的属性和结构。

内容的提问来源于stack exchange,提问作者Lander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:55:52