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

快速抓取目标站点表格技术求助:优化Selenium方案或替代高效方法

高效抓取动态渲染表格的解决方案

针对你需要抓取15000个动态渲染表格的需求,直接用Selenium+Pandas确实会因为频繁启动浏览器而效率极低。下面提供几个更高效的方案,按优先级排序:

1. 直接调用后端API(最优解,速度提升100+倍)

之所以requests/Scrapy抓不到表格,是因为页面的表格数据是通过AJAX动态加载的,初始HTML里根本没有表格内容,#后面的是前端路由参数,实际数据来自后端API接口。

操作步骤:

  • 打开Chrome DevTools(F12),切换到「Network」标签页
  • 刷新目标页面,筛选「Fetch/XHR」类型的请求
  • 寻找返回JSON格式数据的请求,里面应该包含你需要的表格内容(通常会有results、table之类的关键字段)
  • 复制该API的请求URL和请求头(尤其是User-Agent、Cookie等可能的验证字段),直接用requests批量请求

示例代码:

假设找到的API地址是https://greyhoundbet.racingpost.com/api/dog-results,参数和原URL一致:

import requests
import pandas as pd
from concurrent.futures import ThreadPoolExecutor

API_URL = "https://greyhoundbet.racingpost.com/api/dog-results"
HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
    # 可以从DevTools里复制实际的Cookie、Referer等字段
}

def fetch_table(params):
    try:
        response = requests.get(API_URL, headers=HEADERS, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()
        # 假设表格数据在data['tableData']里,根据实际结构调整
        df = pd.DataFrame(data['tableData'])
        return df
    except Exception as e:
        print(f"Failed to fetch {params}: {e}")
        return None

# 假设你有15000个参数列表,每个参数对应一个页面的race_id、dog_id等
params_list = [
    {"race_id": "1807732", "dog_id": "539402", "r_date": "2021-01-01", "track_id": "4", "r_time": "13:24"},
    # 更多参数...
]

# 用线程池批量请求,提升效率
with ThreadPoolExecutor(max_workers=20) as executor:
    results = list(executor.map(fetch_table, params_list))

# 合并所有结果并保存
final_df = pd.concat([df for df in results if df is not None], ignore_index=True)
final_df.to_csv('all_tables.csv', encoding='utf-8', index=False)

2. 优化Selenium的使用(如果必须用浏览器)

如果找不到API,只能用浏览器渲染,那可以通过以下方式大幅提升速度:

优化点:

  • 使用无头模式,避免浏览器界面渲染开销
  • 复用浏览器实例,不要每次请求都启动新Chrome进程
  • 用显式等待替换固定time.sleep(8),只等表格加载完成就继续
  • 禁用图片、CSS、非必要JS,减少页面加载时间

优化后的代码:

import pandas as pd
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# 配置Chrome选项,启用无头模式并禁用不必要的加载
options = webdriver.ChromeOptions()
options.add_argument('--headless=new')  # 新版无头模式,更接近真实浏览器
options.add_argument('--disable-gpu')
options.add_argument('--disable-images')
options.add_argument('--disable-css')
options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36')
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)

# 初始化一次浏览器,复用实例
wd = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
wd.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

def extract(url):
    try:
        wd.get(url)
        # 显式等待表格加载完成,最多等5秒(比固定8秒快)
        WebDriverWait(wd, 5).until(
            EC.presence_of_element_located((By.ID, 'sortableTable'))
        )
        all_tables = pd.read_html(wd.page_source, attrs={'id': 'sortableTable'})
        return pd.concat(all_tables)
    except Exception as e:
        print(f"Failed to extract {url}: {e}")
        return None

# 假设你有15000个URL列表
url_list = [
    "https://greyhoundbet.racingpost.com/#results-dog/race_id=1807732&dog_id=539402&r_date=2021-01-01&track_id=4&r_time=13:24",
    # 更多URL...
]

# 批量处理
results = []
for url in url_list:
    df = extract(url)
    if df is not None:
        results.append(df)

# 合并保存
final_df = pd.concat(results, ignore_index=True)
final_df.to_csv('all_tables.csv', encoding='utf-8', index=False)

# 最后关闭浏览器
wd.quit()

3. 用Playwright替代Selenium(更现代的浏览器自动化工具)

Playwright是微软开发的自动化工具,速度比Selenium快,API更简洁,自带自动等待功能,支持多浏览器。

示例代码:

import pandas as pd
from playwright.sync_api import sync_playwright
from concurrent.futures import ThreadPoolExecutor

def extract_table(url):
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
        page.route("**/*.png", lambda route: route.abort())  # 阻止图片加载
        page.route("**/*.css", lambda route: route.abort())  # 阻止CSS加载
        page.goto(url, wait_until="domcontentloaded")
        # 自动等待表格出现
        page.wait_for_selector("#sortableTable")
        html = page.content()
        browser.close()
        all_tables = pd.read_html(html, attrs={'id': 'sortableTable'})
        return pd.concat(all_tables)

# 批量处理(Playwright也支持异步,效率更高)
url_list = [
    "https://greyhoundbet.racingpost.com/#results-dog/race_id=1807732&dog_id=539402&r_date=2021-01-01&track_id=4&r_time=13:24",
    # 更多URL...
]

with ThreadPoolExecutor(max_workers=10) as executor:
    results = list(executor.map(extract_table, url_list))

final_df = pd.concat([df for df in results if df is not None], ignore_index=True)
final_df.to_csv('all_tables.csv', encoding='utf-8', index=False)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:32:36