如何在页面首次加载前通过Selenium调用CDP的Emulation.setEmulatedMedia模拟prefers-color-scheme特性
如何在页面首次加载前通过Selenium调用CDP的Emulation.setEmulatedMedia模拟prefers-color-scheme特性
我明白你的问题——用Selenium调用Chrome DevTools Protocol的Emulation.setEmulatedMedia设置暗色模式后,第一次加载页面完全没生效,必须刷新才会触发CSS媒体特性和请求头的变化。这确实是个常见的坑,原因是ChromeDriver初始化后会自动加载about:blank页面,这时候你执行的CDP命令只会作用于当前这个空白页,当你导航到目标页面时,这个设置并没有被继承过去。
要在页面首次加载前就让设置生效,你需要在ChromeDriver创建会话的阶段就执行Emulation.setEmulatedMedia命令,而不是等到driver初始化后再操作。具体可以通过ChromeOptions的add_experimental_option("cdp")来实现,这个选项能让你在session启动时就运行指定的CDP命令,相当于提前把全局的模拟规则配置好。
完整代码示例
from selenium import webdriver from selenium.webdriver.chrome.options import Options # 配置ChromeOptions,在会话启动时执行CDP命令 chrome_options = Options() chrome_options.add_experimental_option("cdp", [ ("Emulation.setEmulatedMedia", { "features": [{"name": "prefers-color-scheme", "value": "dark"}] }) ]) # 初始化driver,此时CDP命令已经提前生效 driver = webdriver.Chrome(options=chrome_options) # 直接访问目标页面,首次加载就会应用暗色模式配置 driver.get("https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending") # 此时验证会发现: # - 请求头包含 `SEC-CH-PREFERS-COLOR-SCHEME: dark` # - `matchMedia('(prefers-color-scheme: dark)').matches` 返回 true
备选方案(适配旧版本Selenium/Chrome)
如果你的Selenium或Chrome版本不支持cdp实验选项,也可以尝试先启用Network域,手动设置请求头并配合媒体特性模拟,确保所有配置在页面导航前生效:
from selenium import webdriver driver = webdriver.Chrome() # 先启用Network域,确保请求头设置生效 driver.execute_cdp_cmd("Network.enable", {}) # 设置prefers-color-scheme媒体特性模拟 driver.execute_cdp_cmd("Emulation.setEmulatedMedia", { "features": [{"name": "prefers-color-scheme", "value": "dark"}] }) # 手动设置对应请求头 driver.execute_cdp_cmd("Network.setExtraHTTPHeaders", { "headers": {"Sec-CH-Prefers-Color-Scheme": "dark"} }) # 现在访问目标页面 driver.get("https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending")
简单来说,核心就是要让模拟配置在页面加载前就完成全局生效,而不是只绑定到初始化时的空白页面上,这样首次加载目标页面时就能正确应用暗色模式的模拟规则了。
备注:内容来源于stack exchange,提问作者ambrs
相关产品推荐
相关产品推荐

