我有一个小型网络抓取应用程序,它从网络应用程序下载多个文件,其中的 URL 需要访问该页面。
如果我在运行之间保持浏览器实例处于事件状态,则效果很好,但我想在运行之间关闭该实例。当我调用 browser.close()
时,我的下载会停止,因为 chrome 实例在下载完成之前已关闭。
puppeteer 是否提供了一种方法来检查下载是否仍然有效,并等待它们完成?我尝试过 page.waitForNavigation({ waitUntil: "networkidle0"})
和 "networkidle2"
,但这些似乎无限期地等待。
- node.js 8.10
- puppeteer 师1.10.0
最佳答案
更新:
现在是 2022 年。使用 Playwright 来摆脱这个困境。 manage downloads
它还有“更智能”的定位器,每次在 click() 之前都会检查选择器
<小时/>puppeteer 师的旧版本:
我的解决方案是使用chrome自带的chrome://downloads/
页面来管理下载文件。这个解决方案可以很容易地使用chrome自己的功能自动重新启动失败的下载
此示例当前为“单线程”,因为它仅监视下载管理器页面中出现的第一个项目。但是您可以通过迭代该页面中的所有下载项目 (#frb0
~#frbn
) 轻松地将其适应“无限线程”,好吧,请照顾好您的网络: )
dmPage = await browser.newPage()
await dmPage.goto('chrome://downloads/')
await your_download_button.click() // start download
await dmPage.bringToFront() // this is necessary
await dmPage.waitForFunction(
() => {
// monitoring the state of the first download item
// if finish than return true; if fail click
const dm = document.querySelector('downloads-manager').shadowRoot
const firstItem = dm.querySelector('#frb0')
if (firstItem) {
const thatArea = firstItem.shadowRoot.querySelector('.controls')
const atag = thatArea.querySelector('a')
if (atag && atag.textContent === '在文件夹中显示') { // may be 'show in file explorer...'? you can try some ids, classess and do a better job than me lol
return true
}
const btn = thatArea.querySelector('cr-button')
if (btn && btn.textContent === '重试') { // may be 'try again'
btn.click()
}
}
},
{ polling: 'raf', timeout: 0 }, // polling? yes. there is a 'polling: "mutation"' which kind of async
)
console.log('finish')
关于node.js - 如何使用 Puppeteer 等待所有下载完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53471235/