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

如何在BeautifulSoup爬虫代码中集成XPath实现Oddsportal页面遍历?

解决方案

你不需要折腾BeautifulSoup的xpath支持,你已经在使用Selenium驱动,直接用Selenium自带的xpath选择方法操作元素即可,不需要和BeautifulSoup混用xpath功能。

修改逻辑

  1. 初始化浏览器时添加隐式等待,避免元素未加载就操作引发报错
  2. 定义你需要遍历的xpath列表
  3. 先打开初始页面爬取第一页数据,再逐个点击xpath对应的分页按钮,每次点击完成后爬取当前页面数据
  4. 每次循环都重新查找元素,避免页面刷新后元素失效报错

修改后完整代码

import pandas as pd
from selenium import webdriver
from bs4 import BeautifulSoup as bs
import time

# 初始化浏览器,添加10秒隐式等待
browser = webdriver.Chrome()
browser.implicitly_wait(10)

# 初始页面地址
base_url = "https://www.oddsportal.com/matches/soccer/"

# 定义需要遍历的xpath列表
click_xpaths = [
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[2]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[3]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[4]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[5]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[6]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[7]",
    "/html/body/div[1]/div/div[2]/div[6]/div[1]/div/div[1]/div[2]/div[1]/div[3]/div/div/span/a[8]"
]

class GameData:
    def __init__(self):
        self.country = []

def parse_current_page():
    # 直接读取当前浏览器页面源码,不需要重复发送请求
    df = pd.read_html(browser.page_source, header=0)[0]
    html = browser.page_source
    soup = bs(html, "lxml")
    cont = soup.find('div', {'id': 'wrap'})
    content = cont.find('div', {'id': 'col-content'})
    content = content.find('table', {'class': 'table-main'}, {'id': 'table-matches'})
    main = content.find('th', {'class': 'first2 tl'})
    if main is None:
        return None
    count = main.findAll('a')
    country = count[0].text
    game_data = GameData()
    for row in df.itertuples():
        if not isinstance(row[1], str):
            continue
        elif ':' not in row[1]:
            country = row[1].split('»')[0]
            continue
        game_data.country.append(country)
    return game_data

if __name__ == '__main__':
    results = None
    # 打开初始页面
    browser.get(base_url)
    # 爬取第一页数据
    first_page_data = parse_current_page()
    if first_page_data:
        results = pd.DataFrame(first_page_data.__dict__)
    
    # 遍历所有xpath切换分页爬取
    for xpath in click_xpaths:
        try:
            # 每次循环重新查找元素,避免页面刷新后元素失效
            element = browser.find_element_by_xpath(xpath)
            element.click()
            # 等待页面加载完成,可根据实际网速调整时长
            time.sleep(2)
            # 爬取当前页数据
            current_data = parse_current_page()
            if not current_data:
                continue
            current_df = pd.DataFrame(current_data.__dict__)
            if results is None:
                results = current_df
            else:
                # 高版本pandas用concat替代已废弃的append方法
                results = pd.concat([results, current_df], ignore_index=True)
        except Exception as e:
            print(f"处理xpath {xpath} 时出错: {str(e)}")
            continue
    
    # 爬取完成后可以导出数据
    # results.to_csv("odds_data.csv", index=False, encoding="utf_8_sig")
    browser.quit()

注意事项

  • 如果点击后页面加载慢,可以适当调大time.sleep的时长,或者换成Selenium的显式等待,性能更好
  • 如果站点有反爬机制,频繁点击可能会被限制,可适当增加等待间隔
  • 该方案完全复用了你原有页面解析逻辑,不需要修改原有解析规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 17:06:08