让你明明白白学知识,有代码,有讲解,抄的走,学的会!
我们可能会遇到,需要爬取图片的小需求,以下的案例,是通过node原生API去爬取图片的过程,这个本来是我去爬取一个有防盗链服务的图片,那么,通过构造一个合法的请求头,依旧可以爬取图片
反防盗链,通过构建成一样的http请求, 达到趴取有防盗链的接口/网站 的目的
node反防盗链源码
getRefererImg.js
/*
反防盗链
防盗链的服务 referer.js这个起在 localhost:3004
对 lisi.com这个域名是在白名单的,是被允许的,端口是 3004,下面构造成一样的请求头,即可
*/
const fs = require('fs')
const http = require('http')
const path = require('path')
const opt = {
hostname: 'zhangsan.com',
host: 'zhangsan.com',
port: 3004,
headers: {
// 请求头伪造成能通过的 referer和host,这2个一定要要趴取的网站的一样
Host: 'lisi.com:3004',
Referer: 'lisi.com',
},
path: '/img/a.jpg',
method: 'GET'
}
let req = http.request(opt, (res) => {
let data = ''
// 一定要设置response的编码为binary否则会下载下来的图片打不开
res.setEncoding("binary");
res.on('data', chunk => {
data += chunk
})
res.on('end', () => {
let p = path.join(__dirname, 'public/img/pa.jpg')
// 把二进制写成文件
fs.writeFile(p, data, "binary",err => {
if (err) {
console.log('这里发生错误')
throw err
}
console.log('趴取图片成功')
})
})
})
req.on('error', (err) => {
console.log('发送请求,发生错误')
console.log(err)
})
req.end()
node防盗链源码
下面附上防盗链案例的源码
原理: 利用HTTP中的 host和referer实现图片防盗链
/**
* 本案例演示node+express实现防盗链
* 原生Node也是没问题的,就是要处理静态资源,处理页面请求路由,再判断资源请求头
*
* 使用express 就可以省略对静态资源(图片),页面地址的请求处理
*/
const express = require('express')
const router = express.Router()
const app = express()
const path = require('path')
const url = require('url')
const logger = require('morgan')
const chalk = require('chalk')
const fs = require('fs')
// 白名单地址
const whiteList = ['lisi.com']
const imgExt = ['.jpg', '.jpeg', '.png', '.gif', 'bmp']
// 防盗链中间件
app.use((req, res, next) => {
// 获取到请求头
let headers = req.headers
let referer = headers['referer'] || headers['referered']
console.log(chalk.red("referer-->"+referer))
if (referer) {
// 不是图片资源,直接放行
if (!isImg(req.url)) {
next()
} else {
console.log("请求地址--》",req.url)
// 请求资源存在referer 做防盗链处理
let referHost = url.parse(referer).hostname
let host = req.headers.host.split(":")[0]
console.log(chalk.red('host-->', host, "referHost-->", referHost))
if (referHost !== host) {
// 请求地址在不在白名单里
let isInWhiteList = whiteList.includes(host)
console.log('是否在白名单里面', isInWhiteList)
// 直接放行
if (isInWhiteList) {
next()
} else {
// 图片直接给一个其他的代替
const errorImg = path.join(__dirname, 'public/img/b.jpg')
fs.readFile(errorImg, (err, data) => {
if(err) throw err
res.end(data)
})
}
} else {
// 同一个站点
next()
}
}
} else {
// 直接过, 是本网站的
next()
}
})
app.use(express.static(path.join(__dirname, 'public')))
app.use(router)
app.use(logger('dev'))
app.listen(3004, () => {
console.log(`http://localhost:3004`)
})
// 判断是不是图片
function isImg (url) {
let ext = path.parse(url).ext
if (!ext) return false
return imgExt.includes(ext)
}
这个案例是本地映射的域名,window下怎么添加本地自定义域名?
我们在本地的机器上添加2个自定义域名,我们知道,域名是会被解析成IP的,所以,我们将自定义域名指向127.0.0.1就可以
具体操作
1、 window路径地址: 打开 C:\Windows\System32\drivers\etc 中的hosts文件,如果没有,就创建一个
2、没有hosts文件的,直接 cmd 创建一个 使用: type nul>hosts 命令
3、在hosts文件中添加2个自定义域名
127.0.0.1 zhangsan.com
127.0.0.1 lisi.com
4、 可能会遇到配置本地域名以后, 能通过 ping zhangsan.com 但是不能通过浏览器访问, 使用以下方式
- cmd控制台 执行 ipconfig /flushdns 刷新dns
- 重启浏览器