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

Python3使用Selenium无头Chrome时如何获取XHR响应的JSON内容?

实现方案:Selenium Chrome无头模式捕获XHR JSON响应

以下两种方案均可实现直接获取XHR接口的JSON响应,无需解析DOM元素,稳定性和效率远高于原有页面解析方案。


方案1:CDP事件监听(推荐,无需改动现有业务逻辑)

通过Chrome原生的开发者协议(CDP)的Network域监听所有网络请求,筛选目标XHR接口后直接读取响应内容,兼容性好、适配所有场景。

  • 核心逻辑:Selenium 4+版本原生支持调用CDP接口,注册响应接收回调后,可过滤出JSON类型的XHR请求,匹配到目标接口特征后直接拉取响应正文转JSON即可,原有页面操作逻辑无需改动。
  • 依赖要求:Selenium版本≥4.0
  • 代码示例(适配你的现有业务):
import json
import time
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

@staticmethod
def fetch_music_download_url_impl(music_name: str):
    chrome_driver_service = Service(ChromeDriverManager(chrome_type=ChromeType.GOOGLE).install())
    chrome_options = Options()
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--headless=new") # 新版无头模式,和有头模式行为完全一致,兼容性更好
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--remote-debugging-port=9230")
    # 开启性能日志支持CDP事件监听
    caps = DesiredCapabilities.CHROME
    caps['goog:loggingPrefs'] = {'performance': 'ALL'}
    driver = webdriver.Chrome(
        service=chrome_driver_service,
        options=chrome_options,
        desired_capabilities=caps,
        executable_path="/usr/local/bin/chromedriver"
    )
    # 存储捕获到的目标XHR响应
    target_json_responses = []

    # 自定义响应捕获回调
    def capture_xhr_response(event):
        if event['method'] == 'Network.responseReceived':
            resp_info = event['params']['response']
            # 筛选规则可自定义,这里匹配JSON类型且包含listenSong.do特征的接口
            if resp_info['mimeType'] == 'application/json' and 'listenSong.do' in resp_info['url']:
                request_id = event['params']['requestId']
                try:
                    # 拉取响应正文转JSON
                    resp_body = driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': request_id})
                    json_data = json.loads(resp_body['body'])
                    target_json_responses.append(json_data)
                    logger.info(f"捕获到目标XHR响应:{json_data}")
                except Exception as e:
                    logger.warning(f"读取响应失败:{e}")

    try:
        # 启用Network域监听并注册回调
        driver.execute_cdp_cmd('Network.enable', {})
        driver.add_listener('Network.responseReceived', capture_xhr_response)

        # 原有业务操作逻辑不变
        driver.maximize_window()
        driver.get('http://example.cn/music/?page=audioPage&type=migu&name=' + music_name)
        driver.implicitly_wait(5)
        driver.find_element(By.CSS_SELECTOR, ".aplayer-list-download.iconfont.icon-xiazai").click()
        # 等待接口请求完成,可根据实际情况调整等待逻辑,比如判断target_json_responses是否有值
        time.sleep(3)

        # 直接处理JSON数据即可,无需解析DOM
        for json_data in target_json_responses:
            download_url = json_data.get('data', {}).get('downloadUrl')
            if download_url:
                FetchMusic.do_save_music_download_url(download_url)
    except Exception as e:
        logger.error("scrapy impl error", e)
    finally:
        driver.stop_client()
        driver.close()
        driver.quit()
        chrome_driver_service.stop()
  • 注意事项:如果接口返回的是JSONP格式,需要先去掉外层的函数包裹再转JSON;如果要过滤POST请求的参数,可监听Network.requestWillBeSent事件获取请求体。

方案2:直接模拟XHR请求(适合无复杂校验的场景)

如果你抓包拿到目标XHR的请求URL、参数、请求头、Cookie规则,且接口没有复杂的签名、动态Token校验,可以直接用requests库发请求拿JSON,完全不需要启动浏览器,资源占用极低、速度更快。

该方案的前提是能搞定接口的所有校验规则,否则容易返回403、签名错误等异常,仅适合接口规则简单的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 14:15:05