如何使用Node Puppeteer下载PDF文件?获取缓冲数据仅得哈希值
解决Puppeteer下载PDF时获取到哈希值的问题
我之前也碰到过这个问题!那个类似3a42112c-8d3e-474e-af0f-2e482520bc25的哈希串,其实是浏览器生成的Blob URL——当PDF文件被加载到浏览器内存中时,浏览器会用这种临时URL来指向它,而不是直接暴露原始的文件链接。下面给你两种靠谱的解决方法:
方法一:直接拦截PDF请求获取原始内容
这种方法最直接,通过拦截页面的请求和响应,直接拿到PDF的二进制数据并保存,完全绕开Blob URL的问题。
const puppeteer = require('puppeteer'); const fs = require('fs'); (async () => { const browser = await puppeteer.launch({ headless: 'new' }); // 用新版无头模式更稳定 const page = await browser.newPage(); // 开启请求拦截 await page.setRequestInterception(true); // 过滤请求,允许必要的资源加载 page.on('request', (request) => { const allowedTypes = ['document', 'stylesheet', 'script', 'other']; if (allowedTypes.includes(request.resourceType())) { request.continue(); } else { request.abort(); } }); // 监听响应,捕获PDF文件 page.on('response', async (response) => { const url = response.url(); // 判断是否是PDF且响应成功 if (url.endsWith('.pdf') && response.ok()) { const pdfBuffer = await response.buffer(); fs.writeFileSync('downloaded.pdf', pdfBuffer); console.log('PDF已成功保存到本地'); } }); // 导航到目标页面(如果是直接访问PDF链接也可以) await page.goto('https://example.com/page-containing-pdf', { waitUntil: 'networkidle2' }); await browser.close(); })();
关键说明:
page.setRequestInterception(true)开启请求拦截后,我们可以精准筛选需要处理的资源;- 在
response事件中,通过URL后缀判断是否为PDF文件,调用response.buffer()直接获取二进制数据; - 建议使用
networkidle2作为等待条件,确保页面资源加载完成。
方法二:处理Blob URL提取文件内容
如果你的场景是点击按钮后页面跳转到Blob URL(比如blob:http://example.com/[哈希]),可以通过页面上下文的fetch API读取Blob内容并返回。
const puppeteer = require('puppeteer'); const fs = require('fs'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 导航到包含PDF下载按钮的页面 await page.goto('https://example.com/pdf-download-page', { waitUntil: 'domcontentloaded' }); // 点击下载按钮(替换成你实际的选择器) await page.click('#download-pdf-btn'); // 等待页面跳转到Blob URL await page.waitForNavigation({ waitUntil: 'load' }); // 在页面上下文内读取Blob内容 const pdfBuffer = await page.evaluate(async () => { const currentUrl = window.location.href; if (!currentUrl.startsWith('blob:')) { throw new Error('当前页面URL不是Blob格式'); } // 发起请求获取Blob const response = await fetch(currentUrl); const blob = await response.blob(); // 转换为Uint8Array,Puppeteer会自动将其转为Node.js的Buffer return new Uint8Array(await blob.arrayBuffer()); }); // 保存PDF文件 fs.writeFileSync('blob-downloaded.pdf', pdfBuffer); console.log('从Blob URL提取的PDF已保存'); await browser.close(); })();
注意事项:
- 如果网站有反爬机制,记得设置合理的
user-agent,比如await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'); - 若PDF是在iframe中加载的,需要先切换到对应的iframe:
const iframe = page.frames().find(frame => frame.url().includes('pdf'));,再在iframe上下文中执行操作。
内容的提问来源于stack exchange,提问作者Dovydas Jakubauskas
相关产品推荐
相关产品推荐

