如何获取Python无法解析的网球预订网站动态表格数据?
解决网球预订网站数据爬取及转DataFrame的方案
一、核心问题分析
该网站的预订表格数据是通过JavaScript动态渲染生成的,普通requests无法获取渲染后的DOM结构;若使用Selenium时未等待元素完全加载,也会拿不到目标<div class="booking-sheet clearfix">内的完整数据。
二、具体实现方案(Selenium+BeautifulSoup)
1. 等待元素加载并获取渲染后的页面源码
必须用显式等待确保目标元素完全渲染后再提取,避免强制等待的低效问题:
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 from bs4 import BeautifulSoup import pandas as pd # 初始化Chrome浏览器(需提前配置对应版本的ChromeDriver) driver = webdriver.Chrome() driver.get("https://clubspark.lta.org.uk/StJohnsParkLondon/Booking/BookByDate") # 显式等待目标div加载完成,最长等待10秒 try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "booking-sheet")) ) # 获取完全渲染后的页面源码 page_source = driver.page_source finally: driver.quit() # 解析页面源码 soup = BeautifulSoup(page_source, "html.parser") booking_div = soup.find("div", class_="booking-sheet clearfix")
2. 提取数据并构造DataFrame
遍历目标div内的子元素,提取时间段、场地、预订状态等信息:
# 提取顶部的场地名称 courts = [court.text.strip() for court in booking_div.find_all("div", class_="booking-sheet-header-column")] # 提取所有时间段行 time_rows = booking_div.find_all("div", class_="booking-sheet-row") data = [] for row in time_rows: # 获取当前时间段 time_slot = row.find("div", class_="booking-sheet-row-time").text.strip() # 获取该行所有场地的预订状态 booking_cells = row.find_all("div", class_=["booking-sheet-cell", "booking-sheet-cell-booked"]) for idx, cell in enumerate(booking_cells): # 判断预订状态 status = "已预订" if "booking-sheet-cell-booked" in cell.get("class", []) else "可预订" # 提取预订详情(如预订人信息) detail = cell.find("div", class_="booking-sheet-cell-details") detail_text = detail.text.strip() if detail else "" data.append({ "时间段": time_slot, "场地": courts[idx] if idx < len(courts) else f"场地{idx+1}", "状态": status, "详情": detail_text }) # 转换为DataFrame df = pd.DataFrame(data) print(df.head())
三、优化方案(直接调用API)
打开浏览器开发者工具的Network面板,刷新页面后筛选XHR请求,找到加载预订数据的接口(通常命名含Booking或GetBookings),直接用requests请求该接口获取JSON数据,再转为DataFrame,这种方式比渲染页面更高效:
import requests import pandas as pd # 替换为实际找到的API接口URL api_url = "https://clubspark.lta.org.uk/xxx/GetBookings" 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", # 可能需要添加其他请求头(如Cookie、Referer等,从Network面板复制) } response = requests.get(api_url, headers=headers) booking_data = response.json() # 根据返回的JSON结构提取数据并构造DataFrame df = pd.DataFrame(booking_data["xxx"])
四、注意事项
- 若网站需登录才能查看数据,需在Selenium中模拟登录流程:定位用户名/密码输入框,输入后点击登录按钮,再跳转至预订页面。
- 若遇到验证码,需手动处理或遵守网站规则,避免使用违规打码工具。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

