const fs = require('fs');
const path = require('path');
const axios = require('axios');
const cheerio = require('cheerio');
// 网站题目列表
const titles = [
"1. 题目1",
"2. 题目2",
"3. 题目3",
];
// 基础URL
const baseUrl = 'https://xxx.xxx.com';
// 创建图片下载目录
const imageDir = path.join(__dirname, 'images');
if (!fs.existsSync(imageDir)) {
fs.mkdirSync(imageDir, { recursive: true });
}
// 下载图片的函数
async function downloadImage(url, filename) {
console.log('开始下载图片:', url);
try {
const response = await axios({
method: 'GET',
url: url,
responseType: 'stream'
});
const writer = fs.createWriteStream(path.join(imageDir, filename));
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
} catch (error) {
console.error(`下载图片失败: ${url}`, error.message);
}
}
// 获取页面中的图片URL
async function getImagesFromPage(url) {
try {
const response = await axios.get(url);
console.log(response,'response');
const $ = cheerio.load(response.data);
const images = [];
$('img').each((index, element) => {
const src = $(element).attr('src');
console.log('图片地址',src);
if (src) {
// 处理相对路径和绝对路径
images.push('https:' + src);
}
});
return images;
} catch (error) {
console.error(`获取页面图片失败: ${url}`, error.message);
return [];
}
}
// 主函数
async function main() {
console.log('开始下载图片...');
for (let i = 0; i < titles.length; i++) {
const title = titles[i];
const encodedTitle = encodeURIComponent(title);
const pageUrl = `${baseUrl}/${encodedTitle}.html`;
console.log(`正在处理第 ${i+1}/${titles.length} 个页面: ${title}`);
try {
// 获取页面中的图片
const imageUrls = await getImagesFromPage(pageUrl);
console.log('imageUrls',imageUrls);
if (imageUrls.length === 0) {
console.log(` - 页面中没有找到图片`);
continue;
}
console.log(` - 发现 ${imageUrls.length} 张图片`);
// 为每个页面创建子目录
// 下载每张图片
for (let j = 0; j < imageUrls.length; j++) {
const imageUrl = imageUrls[j];
const filename = path.basename(imageUrl);
console.log(` 下载图片: ${filename}`);
await downloadImage(imageUrl, filename);
}
} catch (error) {
console.error(`处理页面失败: ${pageUrl}`, error.message);
}
}
console.log('图片下载完成!');
}
// 运行主函数
main().catch(console.error);
这段 JavaScript 代码是一个 Node.js 脚本,用于 批量从指定网页中抓取并下载图片。它使用了 axios(发送 HTTP 请求)、cheerio(类似 jQuery 的 HTML 解析库)和 Node.js 内置的 fs、path 模块来完成任务。
下面逐部分详细解释其功能和逻辑:
🔧 1. 引入依赖模块
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const cheerio = require('cheerio');
fs:用于文件系统操作(如创建目录、写入文件)。path:处理文件路径(跨平台兼容)。axios:发起 HTTP 请求(获取网页内容、下载图片)。cheerio:在服务器端解析 HTML,提供类似 jQuery 的 API 来操作 DOM。
✅ 注意:你需要先安装这些依赖:
npm install axios cheerio
📋 2. 配置数据
const titles = [
"1. 题目1",
"2. 题目2",
"3. 题目3",
];
const baseUrl = 'https://xxx.xxx.com';
titles:要抓取的页面“标题”列表(实际用作 URL 路径的一部分)。baseUrl:网站的根域名(示例中为占位符xxx.xxx.com,需替换为真实地址)。
📁 3. 创建图片保存目录
const imageDir = path.join(__dirname, 'images');
if (!fs.existsSync(imageDir)) {
fs.mkdirSync(imageDir, { recursive: true });
}
- 在当前脚本所在目录下创建一个名为
images的文件夹,用于存放下载的图片。 { recursive: true }确保即使父目录不存在也能创建。
🖼️ 4. 下载单张图片函数
async function downloadImage(url, filename) {
console.log('开始下载图片:', url);
try {
const response = await axios({
method: 'GET',
url: url,
responseType: 'stream'
});
const writer = fs.createWriteStream(path.join(imageDir, filename));
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
} catch (error) {
console.error(`下载图片失败: ${url}`, error.message);
}
}
- 使用 流式下载(
responseType: 'stream'),避免大图占用过多内存。 - 将响应数据通过
.pipe()直接写入本地文件。 - 返回一个 Promise,确保
await能正确等待下载完成。
🕵️ 5. 从网页提取图片 URL
async function getImagesFromPage(url) {
try {
const response = await axios.get(url);
const $ = cheerio.load(response.data);
const images = [];
$('img').each((index, element) => {
const src = $(element).attr('src');
if (src) {
// 处理相对路径和绝对路径
images.push('https:' + src);
}
});
return images;
} catch (error) {
console.error(`获取页面图片失败: ${url}`, error.message);
return [];
}
}
- 用
axios.get获取网页 HTML。 - 用
cheerio.load解析 HTML,然后遍历所有<img>标签。 - 提取每个
src属性,并强制加上https:前缀。
🚀 6. 主流程函数 main()
async function main() {
console.log('开始下载图片...');
for (let i = 0; i < titles.length; i++) {
const title = titles[i];
const encodedTitle = encodeURIComponent(title);
const pageUrl = `${baseUrl}/${encodedTitle}.html`;
console.log(`正在处理第 ${i+1}/${titles.length} 个页面: ${title}`);
try {
const imageUrls = await getImagesFromPage(pageUrl);
if (imageUrls.length === 0) {
console.log(` - 页面中没有找到图片`);
continue;
}
console.log(` - 发现 ${imageUrls.length} 张图片`);
// 下载每张图片
for (let j = 0; j < imageUrls.length; j++) {
const imageUrl = imageUrls[j];
const filename = path.basename(imageUrl);
await downloadImage(imageUrl, filename);
}
} catch (error) {
console.error(`处理页面失败: ${pageUrl}`, error.message);
}
}
console.log('图片下载完成!');
}
- 遍历
titles数组,为每个标题生成对应的页面 URL。 - 对每个页面:
- 抓取 HTML;
- 提取所有
<img src="...">; - 逐个下载图片,文件名取自 URL 最后一段(如
a.jpg)。
▶️ 7. 启动脚本
main().catch(console.error);
- 调用主函数,并捕获顶层异常防止崩溃。
✅ 总结:这段代码的作用
自动访问多个网页 → 提取所有
<img>标签的图片链接 → 下载这些图片到本地images文件夹。
适用场景
- 批量下载某个网站题库/文章中的配图。
- 网站内容备份(仅图片)。
- 爬虫入门练习。