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

如何解决Selenium抓取Notion表格动态行加载不全的问题?

解决方案:处理Notion表格懒加载问题

Notion表格采用懒加载机制,仅当行进入视口才会渲染DOM节点,这是你只能检测到部分行的核心原因。以下是针对该问题的具体修复方案,同时适配400行以上的大表格:

1. 修复总行数获取逻辑

放弃一次性获取全部行的方式,改为循环滚动加载直到无法获取新行:

def get_total_rows(driver: webdriver.Chrome) -> int:
    """通过循环滚动加载所有行,返回最终总行数"""
    print("正在加载所有表格行...")
    scroll_container_xpath = "//div[@role='table']/div[last()]"  # Notion表格的滚动容器
    scroll_container = WebDriverWait(driver, 15).until(
        EC.presence_of_element_located((By.XPATH, scroll_container_xpath))
    )
    
    total_rows = 0
    while True:
        # 获取当前已渲染的行(排除隐藏行)
        current_rows = driver.find_elements(By.XPATH, "//div[@role='row' and not(@aria-hidden='true')]")
        current_count = len(current_rows)
        
        if current_count == total_rows:
            # 行数不再增加,说明已加载全部
            break
        
        total_rows = current_count
        # 滚动到容器底部触发懒加载
        driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", scroll_container)
        # 等待新行加载完成
        time.sleep(2)
    
    print(f"表格总行数:{total_rows}")
    return total_rows

2. 改进行内容提取逻辑

移除硬编码的行号XPATH,改为直接操作行元素,避免索引错位:

from selenium.webdriver.common.action_chains import ActionChains

def extract_content_from_cell(driver: webdriver.Chrome, row_element) -> str:
    """传入行元素,提取对应页面内容"""
    print("处理当前行...")
    
    try:
        # 滚动行到视口中央,确保可交互
        driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", row_element)
        # 悬停行元素触发"Open"按钮显示
        hover = ActionChains(driver).move_to_element(row_element)
        hover.perform()
        print("已悬停在行上")
    except Exception as e:
        print(f"悬停失败:{e}")
        return ""
    
    # 定位并点击当前行的"Open in side peek"按钮
    try:
        open_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, ".//div[@aria-label='Open in side peek']"))
        )
        open_button.click()
        print("已点击打开按钮")
    except Exception as e:
        print(f"打开按钮定位失败:{e}")
        return ""
    
    # 等待侧边栏内容加载
    time.sleep(3)
    
    # 提取页面内容并关闭侧边栏
    try:
        content_element = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.CLASS_NAME, "notion-page-content"))
        )
        page_text = content_element.text
        print("已提取页面内容")
        
        # 关闭侧边栏,避免干扰下一行操作
        close_button = driver.find_element(By.XPATH, "//div[@aria-label='Close']")
        close_button.click()
        time.sleep(1)
        
        return page_text
    except Exception as e:
        print(f"内容提取失败:{e}")
        return ""

3. 主流程调用示例

def main():
    driver = webdriver.Chrome()
    driver.get("https://web3sec.notion.site/b201fe69f84e4050bf3915c6030f0fdf?v=2149cfc2302342ebb6124022c1b1950c")
    driver.maximize_window()
    time.sleep(5)  # 等待页面初始加载完成
    
    # 自动加载所有行并获取总行数
    total_rows = get_total_rows(driver)
    # 排除表头行,只处理数据行
    rows = driver.find_elements(By.XPATH, "//div[@role='row' and not(@aria-hidden='true')]")[1:]
    
    dataset = []
    for idx, row in enumerate(rows):
        print(f"正在处理第{idx+1}/{total_rows-1}行")
        content = extract_content_from_cell(driver, row)
        if content:
            dataset.append(content)
    
    # 保存数据集到本地文件
    with open("notion_dataset.txt", "w", encoding="utf-8") as f:
        f.write("\n---\n".join(dataset))
    
    driver.quit()
    print("数据提取完成")

if __name__ == "__main__":
    main()

关键优化点

  • 滚动容器精准定位:直接操作Notion表格的滚动容器,确保滚动触发懒加载
  • 循环加载检测:通过对比滚动前后的行数,确认所有行已加载完成
  • 行元素直接操作:避免硬编码行号XPATH,彻底解决索引错位问题
  • 侧边栏自动关闭:每次提取后关闭侧边栏,消除对后续操作的干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:44:59