
本文介绍在selenium中处理动态水平滚动表格时,如何可靠捕获所有列名——通过模拟点击右向滚动按钮并持续监听新增列头,解决因视口限制导致仅获取前14列的问题。
本文介绍在selenium中处理动态水平滚动表格时,如何可靠捕获所有列名——通过模拟点击右向滚动按钮并持续监听新增列头,解决因视口限制导致仅获取前14列的问题。
在使用 Selenium 抓取类似 JODI Data 表格 这类基于 JavaScript 动态渲染的表格时,常见痛点是:列头( 核心思路是:识别滚动控件 → 循环触发右移 → 每次滚动后提取新出现的最右列头 → 直至滚动条宽度为 0(即到达末尾)。 该网站的水平滚动条由 以下是完整、健壮的实现代码(含显式等待与异常防护): ? 关键注意事项: ✅ 最终,该方法可稳定获取 JODI 数据表中全部 180+ 列(覆盖 2002–2024 年月度数据),彻底解决“只能抓前14列”的问题。此模式亦适用于其他采用相同滚动机制的动态表格(如某些金融、统计类 Web 应用)。<th> 元素)并非一次性全部加载,而是随水平滚动逐步呈现。初始 DOM 中仅包含可视区域内的列(如示例中仅显示 Jan2002–Feb2003 共14列),后续列需触发滚动行为后才被注入 DOM。直接 <code>find_elements 无法获取未渲染的列,因此必须主动驱动滚动并增量采集。<td id="hScrollTD"> 内的一组 <code><img> 元素控制,其中:
<img>(索引为 [4])代表当前滚动条滑块的宽度(单位:px),值为 "0" 时表示已滚动到底;<img>(索引为 [5])是“向右滚动”按钮(通常为右箭头图标),点击即可加载下一组列。from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 配置驱动(请替换为你的 chromedriver 路径)
chrome_driver_path = r'C:\Users\user\Downloads\chromedriver-win64\chromedriver-win64\chromedriver.exe'
service = Service(chrome_driver_path)
options = webdriver.ChromeOptions()
options.add_argument('--start-maximized')
# options.add_argument('--headless') # 可选:无头模式
driver = webdriver.Chrome(service=service, options=options)
wait = WebDriverWait(driver, 30)
try:
driver.get('https://www.php.cn/link/612ba8e9bd06486a09b88ffc221c8738')
# 等待首屏列头加载完成
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'th.TVItemColHeader')))
# 初始化:获取初始可见列名
header_texts = [el.text.strip() for el in driver.find_elements(By.CSS_SELECTOR, 'th.TVItemColHeader')]
# 定位滚动条组件
scroll_td = driver.find_element(By.ID, 'hScrollTD')
while True:
# 获取当前滑块宽度(字符串,如 "20")
slider_width = scroll_td.find_element(By.XPATH, './img[4]').get_attribute('width')
if not slider_width or int(slider_width) == 0:
break # 已滚动到底部
# 点击右滚动按钮
scroll_right_btn = scroll_td.find_element(By.XPATH, './img[5]')
scroll_right_btn.click()
# 等待新列头渲染(关键:避免读取过早的空文本)
wait.until(lambda d: len(d.find_elements(By.CSS_SELECTOR, 'th.TVItemColHeader')) > len(header_texts))
# 提取最新一列(即刚滚动进来的最右列)
new_header = driver.find_elements(By.CSS_SELECTOR, 'th.TVItemColHeader')[-1].text.strip()
if new_header: # 去重 & 防空
header_texts.append(new_header)
print(f"✅ 成功获取 {len(header_texts)} 列:")
print(header_texts)
finally:
driver.quit()
WebDriverWait 显式等待:不能依赖 time.sleep(),因为滚动加载耗时波动大;应等待 th.TVItemColHeader 数量增长或新元素可见。[-1](最后一个 <th>),因其代表本次滚动新载入的列,而非全量重扫。<li>
<strong>异常容错</strong>:添加 <code>try/finally 确保驱动关闭;检查 new_header 是否为空,防止插入空白列名。img[4]/img[5] 顺序),需重新定位滚动按钮——建议优先尝试更稳定的 CSS 选择器(如 img[title="Scroll right"]),但本例中 XPath 是目前最直接有效的方式。










