Node.js爬虫实战:百度图片爬取

2023-12-05

说在前面

网络爬虫是一种自动化工具,能够模拟人类在互联网上浏览和提取信息的行为。它的应用范围广泛,包括数据采集、信息监控、搜索引擎优化等方面。而在数据抓取和处理中,获取图片资源往往是一个常见的需求。
本文将介绍如何使用Node.js和相关库构建一个简单而高效的网络爬虫工具,帮助你从百度图片搜索结果中抓取并下载图片。我们将使用Node.js中的axios库发起HTTP请求,并利用cheerio库解析返回的JSON数据。通过这个示例项目,你将学会如何编写一个完整的图片下载工具,可以根据不同的需求进行定制和扩展。
需要注意的是,网络爬虫在使用过程中需要遵守法律法规,尊重网站的隐私政策和使用条款。在进行数据抓取时,请确保遵守相关规定并尊重他人的权益。

代码实现

1、抓取百度图片搜索结果

我们将介绍如何使用Node.js和相关库构造一个搜索URL并从百度图片搜索结果中抓取所需的信息。具体步骤如下:

(1)构造搜索URL并发起请求

在百度图片搜索页中,我们可以通过修改URL参数来实现不同的搜索结果显示。我们将利用这一点,构造一个新的URL,包含我们需要搜索的关键字和其他必要参数。

在Node.js中,我们可以使用axios库发送HTTP请求,并设置请求头、请求参数等信息。以下代码展示如何构造一个简单的搜索请求:

const axios = require('axios');

const searchKeyword = '银魂'; // 搜索的关键词
const searchUrl = `https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord=${encodeURI(searchKeyword)}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&s=&se=&tab=&width=&height=&face=&istype=&qc=&nc=&fr=&pn=0&rn=30&gsm=1e&1512323757549=`;

axios.get(searchUrl, {
  headers: {
    Referer: 'https://image.baidu.com/',
    Host: 'image.baidu.com',
  }
})
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

在上述代码中,我们首先定义了一个变量searchKeyword,表示需要搜索的关键词。然后,我们使用字符串模板构造了一个新的搜索URL,其中包含了所有必要的参数。其中,关键词需要进行URL编码,以便在请求中正确传递。

接着,我们使用axios库发起GET请求,并设置请求头中的Referer和Host参数。这是因为百度图片搜索需要检查Referer和Host参数,以防止爬虫程序直接访问搜索页面。

(2)解析返回的JSON数据,提取所需的图片链接

当我们发送请求后,服务器会返回一个JSON格式的数据响应。我们需要解析这个响应,提取出其中的图片链接信息。

在Node.js中,我们可以使用cheerio库对HTML或XML文档进行解析。以下代码展示如何解析百度图片搜索结果中的JSON数据:

const cheerio = require('cheerio');

axios.get(searchUrl, {
  headers: {
    Referer: 'https://image.baidu.com/',
    Host: 'image.baidu.com',
  }
})
  .then(response => {
    const $ = cheerio.load(response.data);
    const imgList = $('img');
    const imgUrlList = [];

    imgList.each((index, img) => {
      const imgUrl = $(img).attr('src');
      if (imgUrl) {
        imgUrlList.push(imgUrl);
      }
    });

    console.log(imgUrlList);
  })
  .catch(error => {
    console.error(error);
  });

在上述代码中,我们首先使用cheerio的load()方法将返回的数据转换为一个可操作的DOM对象。接着,我们使用cheerio的选择器语法$(‘img’)获取所有的图片标签,并遍历每个标签,提取出其中的src属性。最后,将所有有效的图片链接保存到一个数组中,并输出到控制台。

通过以上方法,我们可以快速而准确地从百度图片搜索结果中抓取所需的图像链接。

2、使用Node.js下载图片

我们将介绍如何利用Node.js从网络上下载图片,并将其保存到本地文件系统中。具体步骤如下:

(1)发送HTTP请求,获取图片数据

在Node.js中,我们可以使用http或https模块发送HTTP请求,并获取服务器响应。以下代码展示如何使用http模块获取百度图片搜索结果中的第一张图片:

const http = require('http');
const fs = require('fs');

const imgUrl = 'https://imgsa.baidu.com/forum/pic/item/6a600c338744ebf8d97f9aa8d0f9d72a6059a771.jpg';

http.get(imgUrl, response => {
  let imgData = '';
  response.setEncoding('binary');

  response.on('data', chunk => {
    imgData += chunk;
  });

  response.on('end', () => {
    fs.writeFile('image.jpg', imgData, 'binary', error => {
      if (error) {
        console.error(error);
      } else {
        console.log('Image saved');
      }
    });
  });
})
  .on('error', error => {
    console.error(error);
  });

在上述代码中,我们首先定义了一个变量imgUrl,表示需要下载的图片链接。接着,我们使用http模块发起GET请求,并设置响应编码方式为binary,以便正确处理图片数据。

当响应数据开始返回时,我们监听data事件,并将返回的数据拼接到imgData字符串中。当响应结束时,我们使用fs模块的writeFile()方法将图片数据保存到本地文件系统中。在保存文件时,必须将编码方式设置为binary,以便正确写入图片数据。

(2)批量下载多张图片

通过上述代码,我们可以下载单张图片并保存到本地文件系统中。但是,在实际的爬虫应用中,我们通常需要批量下载多张图片。以下代码展示如何使用Promise.all()方法和async/await语法,同时下载多张图片并等待所有下载完成:

const http = require('http');
const fs = require('fs');

const imgUrls = [...]; // 保存需要下载的多张图片链接

const downloadImage = imgUrl => {
  return new Promise((resolve, reject) => {
    http.get(imgUrl, response => {
      let imgData = '';
      response.setEncoding('binary');

      response.on('data', chunk => {
        imgData += chunk;
      });

      response.on('end', () => {
        const fileName = imgUrl.substring(imgUrl.lastIndexOf('/') + 1);
        fs.writeFile(fileName, imgData, 'binary', error => {
          if (error) {
            reject(error);
          } else {
            resolve(`Image ${fileName} saved`);
          }
        });
      });
    })
      .on('error', error => {
        reject(error);
      });
  });
};

(async () => {
  try {
    const result = await Promise.all(imgUrls.map(downloadImage));
    console.log(result);
  } catch (error) {
    console.error(error);
  }
})();

在上述代码中,我们首先定义了一个数组imgUrls,其中保存了需要下载的多张图片链接。接着,我们定义了一个名为downloadImage的函数,用于下载单张图片并返回Promise对象。

在函数中,我们使用http模块发送GET请求,并将响应数据拼接到imgData字符串中。当响应结束时,我们从图片链接中提取出文件名,然后使用fs模块的writeFile()方法保存图片数据到本地文件系统中。在保存文件时,如果发生错误,则会将Promise状态设置为rejected;否则,将Promise状态设置为resolved,并返回一个成功信息。

最后,我们使用async/await语法和Promise.all()方法,同时下载多张图片,并等待所有图片下载完成。在下载过程中,我们可以监听Promise的状态变化,并输出下载进度或错误信息。

3、实现一个简单的图片下载工具

const http = require('http');
const https = require('https');
const fs = require('fs');
const path = require('path');

/**
 * 下载图片
 * @param {string} url 图片链接
 * @param {string} dest 保存路径
 */
function downloadImage(url, dest) {
  const protocol = url.startsWith('https') ? https : http;

  return new Promise((resolve, reject) => {
    protocol.get(url, response => {
      if (response.statusCode !== 200) {
        reject(new Error(`Failed to download image (${response.statusCode})`));
        return;
      }

      const ext = path.extname(url);
      const fileName = `${Date.now().toString()}${ext}`;

      const filePath = path.join(dest, fileName);
      const fileStream = fs.createWriteStream(filePath);

      response.pipe(fileStream);

      fileStream.on('error', error => {
        reject(error);
      });

      fileStream.on('finish', () => {
        resolve(filePath);
      });
    })
      .on('error', error => {
        reject(error);
      });
  });
}

// Example usage
(async () => {
  try {
    const url = 'https://example.com/image.jpg';
    const dest = './images';

    const filePath = await downloadImage(url, dest);
    console.log(`Image downloaded: ${filePath}`);
  } catch (error) {
    console.error(error);
  }
})();

上述代码中,我们定义了一个downloadImage()函数,用于下载图片。该函数接受两个参数:图片链接和保存路径。在函数内部,我们首先判断图片链接的协议(http或https),然后使用相应的模块(http或https)发送GET请求。

当响应数据开始返回时,我们首先判断响应状态码。如果状态码不为200,则认为下载失败,并将Promise状态设置为rejected;否则,从图片链接中提取出文件扩展名(例如.jpg),并使用当前时间戳生成新的文件名。

接着,我们使用path.join()方法拼接保存路径和文件名,创建一个可写入流,并将响应数据导入该流中。在写入过程中,我们监听错误事件,并在发生错误时将Promise状态设置为rejected;在写入完成时,将Promise状态设置为resolved,并返回文件路径。

最后,我们使用async/await语法调用downloadImage()函数,下载一张图片,并输出下载进度或错误信息。

示例与效果展示

完整代码

const axios = require("axios");
const cheerio = require("cheerio");
const fs = require("fs");

async function getSearchResults(searchQuery, page = 1) {
  const searchUrl = `https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&query=${encodeURIComponent(
    searchQuery
  )}&word=${encodeURIComponent(searchQuery)}&pn=${page}`;
  try {
    const response = await axios.get(searchUrl);
    const imageData = response.data;

    // 在这里处理API返回的图片数据
    processImageData(imageData, page);
  } catch (error) {
    console.error("Error:", error);
  }
}

const downloadImage = async (imageUrl, filename) => {
  const imagePath = `./images/${filename}`;
  const writer = fs.createWriteStream(imagePath);

  const response = await axios({
    url: imageUrl,
    method: "GET",
    responseType: "stream",
  });

  response.data.pipe(writer);

  return new Promise((resolve, reject) => {
    writer.on("finish", resolve);
    writer.on("error", reject);
  });
};

const processImageData = async (imageData, page) => {
  const imageLinks = [];

  // 解析图片数据并提取图片链接
  for (const result of imageData.data) {
    if (result.middleURL) {
      imageLinks.push(result.middleURL);
    }
  }

  // 下载图片
  for (let i = 0; i < imageLinks.length; i++) {
    const imageUrl = imageLinks[i];
    const filename = `image_${page + i}.jpg`;
    await downloadImage(imageUrl, filename);
    console.log(`Downloaded: ${filename}`);
  }
};

getSearchResults("银魂", 1);

下载图片

1701616991360.jpg

1701616933150.jpg

公众号

关注公众号『 前端也能这么有趣 』,获取更多新鲜内容。

说在后面

???? 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 ???? ,平时也喜欢写些东西,既为自己记录 ????,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 ????,写错的地方望指出,定会认真改进 ????,偶尔也会在自己的公众号『 前端也能这么有趣 』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 ????。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js爬虫实战:百度图片爬取 的相关文章

随机推荐

  • 轻量应用服务器小程序部署可以吗?

    轻量应用服务器是指提供了一定的并发能力 等功能的云服务器 它可以实现对网站 小程序提供高效 安全的技术支持 而小程序则是一种新的开放能力 不仅具有出色的使用体验 还可以在微信内被便捷地获取 为用户提供便利的服务 原文地址 轻量应用服务器小程
  • 浅析Hotspot的经典7种垃圾收集器原理特点与组合搭配

    浅析Hotspot的经典7种垃圾收集器原理特点与组合搭配 HotSpot共有7种垃圾收集器 3个新生代垃圾收集器 3个老年代垃圾收集器 以及G1 一共构成7种可供选择的垃圾收集器组合 新生代与老年代垃圾收集器之间形成6种组合 每个新生代垃圾
  • WebGL笔记:图形缩放的原理和实现

    缩放 1 原理 缩放可以理解为对向量长度的改变 或者对向量坐标分量的同步缩放 如下图 比如 让向量OA 收缩到点B的位置 也就是从OA变成OB 缩放了一半 2 公式 已知 点A的位置是 ax ay az 点A基于原点內缩了一半 求 点A內缩
  • Tomcat 配合虚拟线程,一种新的编程体验

    Java 21 在今年早些时候的 9 月 19 日就正式发布 并开始正式引入虚拟线程 但是作为 Java 开发生态中老大哥 Spring 并没有立即跟进 而是在等待了两个月后的 11 月 29 日 伴随着 Spring Boot 3 2 版
  • leetcode:468. 验证IP地址

    验证IP地址 中等 249 相关企业 给定一个字符串 queryIP 如果是有效的 IPv4 地址 返回 IPv4 如果是有效的 IPv6 地址 返回 IPv6 如果不是上述类型的 IP 地址 返回 Neither 有效的IPv4地址 是
  • 《许犁庭与柔性世界》第三十章 出云,乘雷与君影

    再次回到校园 伴随着老师舒缓的节奏 徜徉在大大小小 深浅不一的草垛间 头顶碧空如洗 脚底金蕊盖霜 四周稻色黄莽 远处绿黛青芒 境与心会 便欲驭风跨蜿虹 1 若不是老师一把拉住 许犁庭估计会一头撞到前方那澹烟笼罩的巨树上 呵呵 第一次进入伊拉
  • 如何更好地平衡工作和生活?从实际出发

    在当今快节奏的生活中 平衡工作和生活的重要性越来越受到人们的关注 工作和生活是相辅相成的 只有通过良好的平衡 我们才能在工作和生活中获得最佳的状态和体验 然而 如何更好地平衡工作和生活呢 下面将介绍一些实用的方法 一 制定合理的时间表 制定
  • 某音订单接口在电商行业中的重要性及实践应用

    一 引言 随着移动互联网的快速发展 短视频平台抖音已经成为人们日常生活中不可或缺的一部分 越来越多的商家开始利用抖音平台推广和销售商品 从而实现商业变现 在这个过程中 抖音订单接口起到了至关重要的作用 本文将详细探讨抖音订单接口在电商行业中
  • 利用FileZilla下载PHOENIX高分辨率光谱

    下载PHOENIX光谱 在诸如CCF SED拟合中经常需要下载模板光谱 因此有一些大牛提供了相关的光谱库供大家使用 例如 Gottingen Spectral Libary by PHOENIX 论文 A new extensive lib
  • Node.js爬虫实战:搜狗图片爬取

    说在前面 当我们在网上寻找图片时 经常会遇到需要批量下载搜索结果中的图片的情况 而搜狗作为中国颇具影响力的搜索引擎之一 其图片搜索功能提供了丰富多样的图片资源 在这种情况下 我们希望能够通过编程的方式 批量下载搜狗图片搜索结果中的图片 以便
  • 数字化转型的引擎:企业与消费者同步变革

    数字化转型的引擎 企业与消费者同步变革 随着科技的飞速发展 数字化转型已成为企业生存和发展的必然选择 在这个过程中 企业和消费者都面临着巨大的变革和挑战 本文将探讨数字化转型的推动力 以及企业和消费者如何应对这些变革 一 数字化转型的推动力
  • VLAN实验

    题目要求 1 PC1和PC3所在接口为Access接口 2 PC2 4 5 6处于同一网段 其中PC2可以访问PC4 5 6 PC4可以访问PC5 但不能访问PC6 PC5不能访问PC6 3 PC1 3与PC2 4 5 6不在同一网段 4
  • 编译tzdata提示内存越界 malloc(): memory corruption /bin/sh: line 1: 32317 Aborted

    编译tzdata时 遇到如下所示的错误提示 awk v outfile main zi f ziguard awk africa antarctica asia australasia europe northamerica southam
  • 图片转表格软件有哪些?进来马上给你揭晓

    在整理资料的时候 你或多或少都会遇到一些图片格式的表格 需要你手动输入文字信息进行整理 然而 如果数据多的话 很容易出错 并且很浪费时间和精力 为了解决这个问题 你可以借助一些工具 来帮助你更高效地处理这种情况 这些工具通常可以将图片中的表
  • Ubuntu20.04使用SVN(Rabbitvcs)

    原文 https blog csdn net u014552102 article details 129914787 1 安装Rabbitvcs sudo apt get install rabbitvcs nautilus sudo r
  • WebGL笔记:js中矩阵库的使用

    矩阵库 手写矩阵 其实很麻烦 可以将其模块化 市面上已经有许多开源的矩阵库 比如 WebGL 编程指南 里的 cuon matrix js three js 的 Matrix3 和 Matrix4 对象 three js的 Matrix4
  • WebGL笔记:矩阵缩放的数学原理和实现

    矩阵缩放的数学原理 和平移一样 以同样的原理 也可以理解缩放矩阵 让向量OA基于原点进行缩放 x方向上缩放 sx y方向上缩放 sy z方向上缩放 sz 最终得到向量OB 矩阵缩放的应用 比如我要让顶点在x轴向缩放2 y轴向缩放3 轴向缩放
  • VBA字典与数组第八讲:数组及数组公式结果的制约性和集合性

    VBA数组与字典方案 教程 10144533 是我推出的第三套教程 目前已经是第二版修订了 这套教程定位于中级 字典是VBA的精华 我要求学员必学 7 1 3 9教程和手册掌握后 可以解决大多数工作中遇到的实际问题 这套字典教程共两册 一共
  • linux下gdb的使用以及dump转存文件的生成使用

    1 gdb Linux 调试器 gdb的使用 Linux之gdb的使用 gdb调试工具 如何在多线程 多进程以及正在运行的程序下调试 2 dump文件 c linux dump定位错误 Linux下更改 coredump文件生成路径 lin
  • Node.js爬虫实战:百度图片爬取

    说在前面 网络爬虫是一种自动化工具 能够模拟人类在互联网上浏览和提取信息的行为 它的应用范围广泛 包括数据采集 信息监控 搜索引擎优化等方面 而在数据抓取和处理中 获取图片资源往往是一个常见的需求 本文将介绍如何使用Node js和相关库构