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

使用BeautifulSoup爬取Oddsportal时的缺失值与URL获取错误问题

解决Oddsportal足球爬虫的两个核心问题:日期URL过滤与比分数据抓取

问题1:过滤无关日历URL,获取目标7个日期页面URL

原因

之前的选择器范围太宽泛,抓取了包括月份跳转、年份导航在内的所有日历相关链接,而非仅顶部导航栏的最近7天赛事页面链接。

解决方案

通过精准的CSS选择器限定抓取范围,仅定位顶部日期导航区域内的足球赛事页面链接:

基于BeautifulSoup的实现

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/118.0.0.0 Safari/537.36"
}
base_url = "https://www.oddsportal.com/matches/football/"
response = requests.get(base_url, headers=headers)
soup = BeautifulSoup(response.text, "html.parser")

# 定位顶部日历导航中的日期链接:限制父元素为日历日期容器,且链接指向足球赛事页面
target_links = soup.select("div.calendar__days a[href^='/matches/football/']")
# 去重并提取前7个目标URL
unique_date_urls = list(set([link["href"] for link in target_links]))[:7]
# 拼接完整URL
full_urls = [f"https://www.oddsportal.com{url}" for url in unique_date_urls]

print(f"成功获取{len(full_urls)}个目标日期URL")

基于Selenium的实现

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://www.oddsportal.com/matches/football/")

# 等待日期导航加载完成
wait = WebDriverWait(driver, 10)
date_elements = wait.until(
    EC.presence_of_all_elements_located(
        (By.CSS_SELECTOR, "div.calendar__days a[href^='/matches/football/']")
    )
)

# 提取URL并去重,取前7个
target_urls = list(set([elem.get_attribute("href") for elem in date_elements]))[:7]
print(f"成功获取{len(target_urls)}个目标日期URL")

driver.quit()

关键说明

  • 用div.calendar__days限定抓取范围在顶部日期导航区,排除其他无关日历链接
  • 用[href^='/matches/football/']确保链接指向足球赛事页面,而非其他项目或日历跳转页面
  • 去重处理避免重复抓取当天赛事的链接(当天链接可能同时出现在导航和当前页)

问题2:正确抓取赛事比分数据,填充score列

原因

  1. 比分数据是动态渲染的,静态请求(如requests)无法获取到已加载的内容
  2. 元素选择器错误,未定位到正确的比分容器
  3. 未处理未开赛赛事的空比分情况,导致DataFrame生成nan值

解决方案

使用Selenium等待元素加载完成,精准定位比分容器,并针对未开赛赛事做特殊处理:

import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://www.oddsportal.com/matches/football/")

# 等待赛事列表完全加载
wait = WebDriverWait(driver, 15)
matches = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div.match")))

match_data = []
for match in matches:
    item = {}
    # 获取对阵双方
    item["teams"] = match.find_element(By.CSS_SELECTOR, "div.match__teams").text.strip()
    # 获取比分:处理已开赛和未开赛两种情况
    try:
        score_elem = match.find_element(By.CSS_SELECTOR, "div.match__score")
        score_text = score_elem.text.strip()
        # 未开赛赛事比分为空,标记为"未开赛"
        item["score"] = score_text if score_text else "未开赛"
    except:
        item["score"] = "未开赛"
    match_data.append(item)

# 生成DataFrame并检查空值
df = pd.DataFrame(match_data)
print(f"score列空值数量:{df['score'].isnull().sum()}")

driver.quit()

关键说明

  • 用WebDriverWait等待赛事列表加载完成,避免因元素未渲染导致抓取失败
  • 通过div.match__score定位比分容器(可通过F12检查页面元素确认选择器是否准确)
  • 异常捕获和空值判断处理未开赛赛事,避免生成nan值
  • 若需用BeautifulSoup处理,需先通过Selenium获取渲染后的页面源码,再交给BeautifulSoup解析

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:12:49