使用Puppeteer无法抓取并下载网页图片的问题
Puppeteer抓取网页图片无法下载的解决办法
常见问题原因及修复方案
1. 图片URL为相对路径,axios无法直接请求
网页中很多图片的src是相对路径(如/assets/img.jpg),直接用axios请求会因为缺少域名导致失败。需要结合当前页面的URL将相对路径转为绝对URL:
// 获取页面基础URL const baseUrl = page.url(); // 遍历图片时转成绝对URL const absoluteUrl = new URL(evawl, baseUrl).href; arr.push(absoluteUrl);
2. 跨域/反爬拦截导致axios请求失败
直接使用axios请求会丢失页面的Cookie、请求头信息,容易被网站反爬机制拦截。改用Puppeteer自带的page.goto请求图片,继承页面的会话信息:
for (let imageUrl of arr) { try { const response = await page.goto(imageUrl, { waitUntil: 'networkidle0' }); if (!response.ok()) { throw new Error(`HTTP状态码异常:${response.status()}`); } const buffer = await response.buffer(); // 给文件名加时间戳,避免重复覆盖 const imageName = `${Date.now()}_${imageUrl.split('/').pop()}`; const imagePath = path.join(folderpath, imageName); fs.writeFileSync(imagePath, buffer); console.log(`已下载:${imageUrl}`); } catch (err) { console.error(`下载失败 ${imageUrl}:${err.message}`); } }
3. 目录创建失败
原代码中fs.mkdir没有递归创建参数,如果上级目录不存在会报错,修改为支持多级目录创建:
// 同步创建(加recursive参数) fs.mkdirSync(folderpath, { recursive: true }); // 或者用异步方式更贴合async/await写法 await fs.promises.mkdir(folderpath, { recursive: true });
4. 未等待图片完全加载
页面存在懒加载图片时,直接抓取可能只获取到部分图片URL,需要先等待所有图片加载完成:
await page.waitForFunction(() => { return Array.from(document.querySelectorAll('img')).every(img => img.complete); });
完整修复后的代码
const path = require('path'); const fs = require('fs').promises; const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 替换为你的目标网页URL await page.goto('https://example.com', { waitUntil: 'networkidle0' }); // 等待所有图片加载完成 await page.waitForFunction(() => { return Array.from(document.querySelectorAll('img')).every(img => img.complete); }); // 获取所有图片的绝对URL const baseUrl = page.url(); const imageUrls = await page.evaluate((base) => { return Array.from(document.querySelectorAll('img[src]')).map(img => { return new URL(img.getAttribute('src'), base).href; }); }, baseUrl); console.log('抓取到的图片URL列表:', imageUrls); // 创建图片存储目录 const folderpath = path.join(__dirname, 'img'); await fs.mkdir(folderpath, { recursive: true }); // 批量下载图片 for (let imageUrl of imageUrls) { try { const response = await page.goto(imageUrl, { waitUntil: 'networkidle0' }); if (!response.ok()) { throw new Error(`请求失败,状态码:${response.status()}`); } const buffer = await response.buffer(); // 生成唯一文件名,避免重复覆盖 const filename = `${Date.now()}_${imageUrl.split('/').pop()}`; const imagePath = path.join(folderpath, filename); await fs.writeFile(imagePath, buffer); console.log(`已下载:${imageUrl}`); } catch (err) { console.error(`下载失败 ${imageUrl}:${err.message}`); } } await browser.close(); })();
内容的提问来源于stack exchange,提问作者user20957580
相关产品推荐
相关产品推荐

