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

使用Selenium爬取CoinMarketCap Uniswap V2数据出现行缺失问题求解

问题原因分析
  • 虚拟滚动机制:CoinMarketCap的交易对表格采用虚拟滚动设计,仅会渲染当前可视区域及附近的数十行DOM节点,滚动出可视区的行会被自动销毁。你当前等待所有加载完成后一次性提取全量元素的逻辑,本身只能拿到当前渲染的部分数据,无法获取全量1853行。
  • 滚动逻辑缺陷:你仅在页面初始化时计算了一次total_height,后续点击「Load More」加载更多数据后页面总高度会持续升高,但你依然使用初始高度值执行滚动,导致无法滚动到最新的页面底部,无法触发中间行的渲染,因此出现行号跳跃的问题。
  • 固定等待不可靠:全使用固定的time.sleep控制等待时长,不同网络环境下页面渲染速度波动大,很容易出现还未等行渲染完成就继续滚动的情况,导致中间行未被捕获就被跳过。
修复方案与完整代码

调整为边滚动边收集数据的逻辑,每次滚动到新区域待行渲染完成后就立刻提取数据存入本地列表,同时自动去重;每次点击「Load More」后重新计算页面高度,直到加载完所有1853行数据为止。

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

driver = webdriver.Chrome(ChromeDriverManager().install())
driver.maximize_window()
driver.get('https://coinmarketcap.com/exchanges/uniswap-v2/')
wait = WebDriverWait(driver, 10)

# 先关闭cookie弹窗
try:
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.cmc-cookie-policy-banner__close'))).click()
except:
    pass

results = []
exist_ranks = set()
target_count = 1853

while len(results) < target_count:
    # 每次滚动前先获取当前页面总高度
    total_height = int(driver.execute_script("return document.body.scrollHeight"))
    # 逐段滚动,每次滚动后提取数据
    for i in range(1, total_height, 200):
        driver.execute_script("window.scrollTo(0, {});".format(i))
        time.sleep(0.5)
        # 提取当前渲染的所有行数据
        try:
            ranks = driver.find_elements(By.CSS_SELECTOR, 'td.cmc-table__cell.cmc-table__cell--sticky.cmc-table__cell--sortable.cmc-table__cell--left.cmc-table__cell--sort-by__rank > div')
            names = driver.find_elements(By.CSS_SELECTOR, 'div.cwwgik-0.bCvAgC')
            pairs = driver.find_elements(By.CSS_SELECTOR, 'div.hmd6df-0.kCRNNr')
            volumes = driver.find_elements(By.CSS_SELECTOR, 'div.cmc-table__column-market-pair-volume-24h')
            vol_percents = driver.find_elements(By.CSS_SELECTOR, 'div.cmc-table__column-market-pair-volume-percent')
            liquidity = driver.find_elements(By.CSS_SELECTOR, 'td.cmc-table__cell.cmc-table__cell--sortable.cmc-table__cell--right.cmc-table__cell--sort-by__quote-usd-effective-liquidity > div')
            fee_types = driver.find_elements(By.CSS_SELECTOR, 'td.cmc-table__cell.cmc-table__cell--sortable.cmc-table__cell--right.cmc-table__cell--sort-by__fee-type > div')
            recency = driver.find_elements(By.CSS_SELECTOR, 'div.ghkc60-0.fLaXDt')
            # 遍历当前行,去重存入结果
            for idx in range(len(ranks)):
                try:
                    rank = ranks[idx].get_attribute("innerText").strip()
                    if not rank or rank in exist_ranks:
                        continue
                    row_data = f"{rank} {names[idx].get_attribute('innerText')}  {pairs[idx].get_attribute('innerText')}  {volumes[idx].get_attribute('innerText')}  {vol_percents[idx].get_attribute('innerText')}  {liquidity[idx].get_attribute('innerText')}  {fee_types[idx].get_attribute('innerText')}  {recency[idx].get_attribute('innerText')}"
                    results.append(row_data)
                    exist_ranks.add(rank)
                    # 达到目标数量直接退出
                    if len(results) >= target_count:
                        break
                except:
                    continue
            if len(results) >= target_count:
                break
        except:
            continue
    if len(results) >= target_count:
        break
    # 点击加载更多
    try:
        load_more_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[text() = "Load More"]')))
        load_more_btn.click()
        time.sleep(2)
    except:
        # 找不到加载更多按钮说明已经到最后一页,退出循环
        break

# 输出结果
print(f"共获取到{len(results)}行数据")
for row in results:
    print(row)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 00:54:00