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

Python Selenium Webdriver无法滚动div内元素获取完整输出

Selenium爬取SubGraph数据截断问题的代码疏漏分析

现存核心疏漏

  • 滚动逻辑完全失效
    • 调用find_elements获取到的是WebElement列表,直接将列表传入execute_script作为参数,JS无法直接解析元素列表执行滚动操作
    • scrollIntoView()仅能实现页面级滚动,将目标元素对齐到视口,无法操作结果区域的内部滚动条。SubGraph页面的返回结果是在独立的CodeMirror容器内滚动,长内容不会随页面滚动加载
  • 等待逻辑不可靠
    • 硬编码的sleep()固定等待完全依赖经验值,网络波动、接口响应慢时会在结果未完全返回时就执行取数,直接导致内容截断;响应快时又会无意义浪费等待时间
  • 取数逻辑存在天然缺陷
    • CodeMirror编辑器默认使用虚拟滚动优化性能,不在容器可视区域的内容行不会被渲染到DOM树中,哪怕元素存在于页面,未渲染的行也无法通过.text属性获取到
  • 窗口配置加剧截断问题
    • 设置的window-size=800,600窗口尺寸过小,结果区域的可视高度有限,单次渲染的内容行数更少,进一步提升了截断概率

修正方案

优先推荐直接拦截接口响应的方式,完全不需要操作DOM、处理滚动,拿到的数据100%完整无截断;如果需要保留DOM操作逻辑,就正确操作结果容器的内部滚动条。

修正后参考代码

from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
import json

def find_datasets():
    datasets_url = []
    s = Service(ChromeDriverManager().install())
    options = Options()
    options.headless = False
    # 调大窗口尺寸,增加结果区域可视范围
    options.add_argument('window-size=1920,1080')
    driver = webdriver.Chrome(service=s, options=options)
    # 开启网络监听,用于捕获接口返回
    driver.execute_cdp_cmd("Network.enable", {})
    resp_result = {}

    # 监听接口响应,直接拿到完整返回数据
    def capture_resp(request_id):
        try:
            resp = driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id})
            # 识别graphql接口返回
            if "pools" in resp.get("body", ""):
                resp_result["data"] = json.loads(resp["body"])
        except:
            pass

    driver.on("Network.responseReceived", lambda r: capture_resp(r["requestId"]))

    driver.get("https://v4.subgraph.polygon.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph/graphql?query=%7B%0A%20%20pools(orderBy%3A%20createdTimestamp%2C%20orderDirection%3A%20desc)%20%7B%0A%20%20%20%20id%0A%20%20%20%20datatoken%20%7B%0A%20%20%20%20%20%20address%0A%20%20%20%20%7D%0A%20%20%20%20publishMarketSwapFee%0A%20%20%20%20liquidityProviderSwapFee%0A%20%20%7D%0A%7D%0A")
    
    wait = WebDriverWait(driver, 20)
    # 等执行按钮可点击再点击,替代固定sleep
    execute_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(@class, 'execute-button')]")))
    execute_btn.click()

    # 等接口返回拿到完整数据
    wait.until(lambda d: "data" in resp_result.keys())
    full_data = resp_result["data"]
    print("完整返回数据:", full_data)

    # 如果一定要从DOM取内容,执行以下滚动逻辑,替代原来的scrollIntoView
    # # 定位结果区域的内部滚动容器
    # result_scroll_container = wait.until(EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'result-window')]//div[contains(@class, 'CodeMirror-scroll')]")))
    # # 持续滚动到底部,直到滚动高度不再变化,确保所有行渲染完成
    # last_height = 0
    # while True:
    #     current_height = driver.execute_script("return arguments[0].scrollHeight", result_scroll_container)
    #     if current_height == last_height:
    #         break
    #     last_height = current_height
    #     driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", result_scroll_container)
    # # 滚动完成后再取文本
    # result_text = driver.find_element(By.XPATH, "//div[contains(@class, 'result-window')]").text
    # print(result_text)

    driver.get_screenshot_as_file("screenshot.png")
    driver.quit()
    return full_data

find_datasets()

如果只是需要拿SubGraph的查询数据,甚至不需要用Selenium模拟浏览器操作,直接构造POST请求调用GraphQL接口即可,代码量更少、效率更高,完全不会遇到DOM渲染、滚动相关的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:45:37