Node
+puppteer
实现网络图片爬取
一、项目搭建
1. 初始化项目
npm init -y
2. 安装依赖
npm install -s puppeteer
3. 目录结构
├─node_modules
├─package-lock.json
├─package.json
├─README.md
└─src
├─index.js
├─imgs
└─utils
└─srcToImg.js
二、功能实现
1. 图片DOM元素获取
const puppeteer = require('puppeteer')
const path = require('path')
const srcToImg = require('./utils/srcToImg')
;(async function () {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto('https://image.baidu.com')
await page.focus('#kw')
await page.keyboard.sendCharacter('雷姆 3840*1080')
await page.click('.s_newBtn')
page.on('load', async function() {
const sources = await page.evaluate(async () => {
const images = document.getElementsByClassName('main_img')
return [...images].map(img => img.src)
})
for(let src of sources) {
await srcToImg(src, path.resolve(__dirname, 'imgs'))
}
await browser.close()
})
})()
- 首先引入所需模块
- 使用
puppteer
创建一个browser
对象
- 利用
browser
对象创建一个page
- 跳转到对应网址
- 查询到
input
框的id
,并通过id
获取到该DOM
元素并聚焦
- 模拟键盘输入查询关键字
- 查询到搜索按钮的类名,并通过类名获取到该
DOM
元素,同时触发点击搜索事件
- 监听网页加载完成事件,并在网页加载完成之后,通过
page.evaluate
方法传入回调,该回调可在可在页面实例上下文中执行
- 通过类名获取所有
image
标签,并返回包含所有image
标签的src
属性值的数组
- 遍历数组,调用
srcToImg
方法下载图片到imgs
文件夹下
- 下载完毕后,关闭浏览器页面
2. 图片下载到本地
const http = require('http')
const https = require('https')
const path = require('path')
const { promisify } = require('util')
const { createWriteStream, writeFile } = require('fs')
const myWriteFile = promisify(writeFile)
module.exports = async function(src, dir) {
const reg = /.(jpg|jpeg|png|gif)$/
if (reg.test(src)) {
await urlToImg(src, dir)
} else {
await base64ToImg(src, dir)
}
}
const urlToImg = async (url, dir) => {
const reg = /^https:/
const ext= path.extname(url)
const file = path.join(dir, `${ Date.now() }${ ext }`)
const module= reg.test(url) ? https : http
module.get(url, res => {
res.pipe(createWriteStream(file))
.on('finish', () => {
console.log('写入完成')
})
})
}
const base64ToImg = async (str, dir) => {
const reg = /^data:(.+);base64,(.+)$/
const matches = str.match(reg)
try {
const ext = matches[1].split('/')[1].replace('jpeg', 'jpg')
const file = path.join(dir, `${ Date.now() }.${ ext }`)
await myWriteFile(file, matches[2], 'base64')
} catch (err) {
console.log('非法的base64')
}
}
- 图片有两种类型,一种是图片链接,一种是
base64
编码图片,所以需要通过正则判断并分开处理
- 如果是图片链接,则调用
urlToImg
方法,该方法会根据http
和https
,分别调用该模块的get
方法,获取图片资源,并写入到imgs
文件夹
- 如果是
base64
图片,则调用base64ToImg
方法,该方法会使用正则匹配出base64
图片的前缀和图片数据,并将图片数据写入到imgs
文件夹