如何使用Puppeteer访问并操作Chrome下载列表中的元素?
问题原因
Chrome 专属的内部页面(如 chrome://downloads)采用了 Shadow DOM 封装内部元素,标准的 Puppeteer 选择器无法直接穿透 Shadow Root 访问内层节点,这是你调用选择器返回 null 的根本原因。
解决方法
要访问下载列表元素,需要逐层穿透嵌套的 Shadow Root 节点,在页面执行上下文内完成元素查询与交互操作。
修正后可运行代码
'use strict'; const CHROME_BINARY_PATH = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; const puppeteer = require('puppeteer'); (async () => { try { const browser = await puppeteer.launch({ executablePath: CHROME_BINARY_PATH, defaultViewport: null, headless: false, devtools: false, args: [ '--window-size=1920,1080', '--disable-web-security' ], userDataDir: './user_data' }); const page = (await browser.pages())[0]; await page.goto('chrome://downloads/',{ waitUntil: 'networkidle2', timeout: 30000 }); console.log('getting downloads list element'); // 等待Shadow DOM内的下载列表加载完成 await page.waitForFunction(() => { const manager = document.querySelector('downloads-manager'); if (!manager || !manager.shadowRoot) return false; return !!manager.shadowRoot.querySelector('#downloadsList'); }, { timeout: 5000 }); // 获取下载列表节点,也可以直接在evaluate中完成交互 const downloadsList = await page.evaluate(() => { const downloadsManager = document.querySelector('downloads-manager'); const managerShadow = downloadsManager.shadowRoot; return managerShadow.querySelector('#downloadsList'); // 要和列表内的下载项交互的话可以继续往下查: // const downloadItems = managerShadow.querySelectorAll('downloads-item'); // 示例:获取所有下载项的文件名 // return Array.from(downloadItems).map(item => { // const itemShadow = item.shadowRoot; // return itemShadow.querySelector('#file-link').textContent; // }); }); console.log(downloadsList); } catch (e) { console.log('错误:', e); } })();
常见交互示例
- 获取所有下载项的文件名、下载进度、存储路径:在上述evaluate回调中遍历
downloads-item节点,穿透其自身的Shadow Root即可读取对应属性 - 触发删除下载项操作:找到对应
downloads-item的Shadow Root内的#remove按钮,调用click()即可 - 打开下载文件所在文件夹:找到对应
downloads-item的Shadow Root内的#show-in-folder按钮,调用click()即可
内容的提问来源于stack exchange,提问作者regan
相关产品推荐
相关产品推荐

