使用Puppeteer获取会话生成URL对应的PDF缓冲区技术问询
嘿,我来帮你搞定用Puppeteer抓取这个网站PDF的问题!针对这个网站两次请求的逻辑(先拿GUID再取PDF),我们有两种靠谱的实现方式,直接上干货:
方案一:直接模拟两次请求(高效推荐)
这种方式不用折腾页面跳转,直接复刻网站的请求逻辑,速度更快:
const puppeteer = require('puppeteer'); const fs = require('fs'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 先访问站点初始化会话(有些网站会校验会话Cookie,这步不能省) await page.goto('http://epicdocs.planningni.gov.uk/'); // 第一步:获取会话GUID const targetGuid = await page.evaluate(async () => { const res = await fetch('http://epicdocs.planningni.gov.uk/ViewDocument.pa?uri=4157826&ext=PDF'); const pageContent = await res.text(); // 用正则匹配页面里的GUID(适配网站返回的HTML结构) const guidMatch = pageContent.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i); return guidMatch ? guidMatch[0] : null; }); if (!targetGuid) { console.error('糟了,没拿到GUID!'); await browser.close(); return; } console.log('成功拿到GUID:', targetGuid); // 第二步:用GUID获取PDF缓冲区 const pdfBuffer = await page.evaluate(async (guid) => { const pdfRes = await fetch(`http://epicdocs.planningni.gov.uk/ViewDocument.aspx?guid=${guid}`); if (!pdfRes.ok) throw new Error('获取PDF失败'); const blob = await pdfRes.blob(); const arrayBuffer = await blob.arrayBuffer(); return Buffer.from(arrayBuffer); }, targetGuid); // 把缓冲区写入本地文件 fs.writeFileSync('target-document.pdf', pdfBuffer); console.log('PDF已保存!'); await browser.close(); })();
方案二:模拟点击+监听请求(贴近真实操作)
如果你想完全模拟用户点击链接的流程,可以监听新标签页的请求,拦截PDF返回:
const puppeteer = require('puppeteer'); const fs = require('fs'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 打开包含文档链接的页面(替换成实际页面地址) await page.goto('你要访问的包含文档链接的页面URL'); // 监听新标签页创建事件 browser.on('targetcreated', async (target) => { if (target.type() === 'page') { const newTab = await target.page(); // 监听新标签页的请求完成事件,捕获PDF请求 newTab.on('requestfinished', async (request) => { const requestUrl = request.url(); if (requestUrl.includes('ViewDocument.aspx?guid=')) { const pdfResponse = await request.response(); const pdfBuffer = await pdfResponse.buffer(); // 保存PDF fs.writeFileSync('clicked-document.pdf', pdfBuffer); console.log('通过点击链接拿到PDF啦!'); await browser.close(); } }); } }); // 点击文档链接(替换成实际的元素选择器,比如a[href*="ViewDocument.pa"]) await page.click('文档链接的CSS选择器'); })();
几个要注意的细节:
- 一定要先访问站点初始化会话,不然网站可能会拒绝你的请求(Cookie校验)。
- 如果正则匹配GUID失败,打开第一个请求的返回页面看看,可能需要调整正则或者用DOM解析(比如
document.querySelector找包含GUID的元素)。 - 要是遇到反爬,可以给Puppeteer设置
--no-sandbox、添加自定义userAgent,或者在请求之间加个await page.waitForTimeout(1000)延迟一下。
内容的提问来源于stack exchange,提问作者Luigi
相关产品推荐
相关产品推荐

