手写了一个方便爬虫的小库:

const url = require('url')
const glib = require('zlib') //默认头部
const _default_headers = {
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'
} //options(url,method,header)--http头部信息 isDebug--是否开启调试状态
module.exports = function(options, isDebug) {
if(typeof options === "string") {
options = {
url: options,
method: 'GET',
headers: {}
}
} else {
options = options || {}
options.method = options.method || 'GET'
options.headers = options.headers || {}
}
options.headers = Object.assign(_default_headers, options.headers) function debug(msg) {
if(isDebug) {
console.log(msg)
}
} return new Promise((resolve, reject) => {
req(options) function req(options) {
//判断是http还是https
let urlObj = url.parse(options.url)
let mod = null
port = 0 if(urlObj.protocol == 'https:') {
mod = require('https')
port = 443
} else {
mod = require('http')
port = 80
} let _req_options = {
hostname: urlObj.hostname,
port,
path: urlObj.path,
method: options.method,
headers: options.headers
}
//开始模拟,爬取信息
let req_obj = mod.request(_req_options, (res) => {
if(res.statusCode!==200) {
//如果是重定向则重新在请求
if(res.statusCode == 301 || res.statusCode === 302) {
options.url = res.headers.location
debug('重定向: '+res.headers.location)
req(options)
} else {
reject(res.statusCode)
}
} else {
//statusCode是200时接受data buffer
let data = []
res.on('data', buffer => {
data.push(buffer)
})
res.on('end', () =>{
let buffer = Buffer.concat(data)
//判断是否传输有误
if (res.headers['content-length'] != buffer.length) {
debug('收到数据有误,正在重新获取')
req(options)
}
//判断是否有用gzip
else if (res.headers['content-encoding'] && res.headers['content-encoding'].includes('gzip')) {
buffer = glib.gunzip(buffer, (err,data) => {
debug('gzip解压完成并成功返回')
resolve(data)
})
} else {
debug('成功返回')
resolve(buffer)
}
})
}
})
req_obj.on('error', err => {
debug('爬虫失败')
reject(err)
})
req_obj.end()
}
})
}

require进来然后传入url或者options,就可以得到爬虫后返回的promise了

举个例子:

我要爬个bilibili的视频:

const url = require('url')
const fs = require('fs') function getVideo(options, headers, fileName) {
if(typeof options === "string") {
options = {
url: options,
method: 'GET',
headers: {},
timeout: 2000
}
} else {
options = options || {}
options.method = options.method || 'GET'
options.headers = options.headers || {}
options.timeout = options.timeout || 2000
}
options.headers = headers return new Promise((resolve, reject) => {
req(options) function req(options) {
//判断是http还是https
let urlObj = url.parse(options.url)
let mod = null
port = 0 if(urlObj.protocol == 'https:') {
mod = require('https')
port = 443
} else {
mod = require('http')
port = 80
} let _req_options = {
hostname: urlObj.hostname,
port,
path: urlObj.path,
method: options.method,
headers: options.headers,
timeout: options.timeout
}
//开始模拟,爬取信息
let req_obj = mod.request(_req_options, (res) => {
// 视频路径
const filePath = `${__dirname}/${fileName}`;
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath)
}
res.on('data', buffer => {
fs.appendFileSync(filePath, buffer)
const size = fs.statSync(filePath).size;
console.log(`已下载${(size / 1024 / 1024).toFixed(2)}MB,完成${(size/res.headers['content-length'] * 100).toFixed(2)}%`)
})
res.on('end', () =>{
resolve()
})
})
req_obj.on('error', err => {
debug('爬虫失败')
reject(err)
})
req_obj.end()
}
})
} // 生成文件名
const fileName = '1.flv'
// 链接
const videoUrl = 'https://cn-sdyt-cu-v-05.acgvideo.com/upgcxcode/66/83/34548366/34548366-1-64.flv?expires=1545405600&platform=pc&ssig=ElhY4A2e-U4R2m8EI1eiGQ&oi=1928611810&nfa=uTIiNt+AQjcYULykM2EttA==&dynamic=1&hfa=2116953847&hfb=Yjk5ZmZjM2M1YzY4ZjAwYTMzMTIzYmIyNWY4ODJkNWI=&trid=45c5fdc464354b71bf599c224b7df8ea&nfb=maPYqpoel5MI3qOUX6YpRA==&nfc=1';
// 头部
const header = {
'Origin': 'https://www.bilibili.com',
'Referer': 'https://www.bilibili.com/video/av21061574',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
} getVideo(videoUrl, header, fileName).then(res => {
console.log('写入成功');
})

node爬虫进阶版的更多相关文章

  1. node爬虫(简版)

    做node爬虫,首先像如何的去做这个爬虫,首先先想下思路,我这里要爬取一个页面的数据,要调取网页的数据,转换成页面格式(html+div)格式,然后提取里面独特的属性值,再把你提取的值,传送给你的页面 ...

  2. Nodejs爬虫进阶教程之异步并发控制

    Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回 ...

  3. webpack4打包nodejs项目进阶版——多页应用模板

    前段时间我写了个打包nodejs项目的文章,点击前往 但是,问题很多.因为之前的项目是个历史遗留项目,重构起来可能会爆炸,当时又比较急所以就写个的适用范围很小的webpack的打包方法. 最近稍微得空 ...

  4. node爬虫的几种简易实现方式

    说到爬虫大家可能会觉得很NB的东西,可以爬小电影,羞羞图,没错就是这样的.在node爬虫方面,我也是个新人,这篇文章主要是给大家分享几种实现node 爬虫的方式.第一种方式,采用node,js中的 s ...

  5. 高效能团队的Java研发规范(进阶版)

    目前大部分团队是使用的阿里巴巴Java开发规范,不过在日常开发中难免遇到覆盖不到的场景,本文在阿里巴巴Java开发规范基础上,补充一些常用的规范,用于提升代码质量及增强代码可读性. 编程规约 1.基础 ...

  6. zip伪加密文件分析(进阶版)

    作者近日偶然获得一misc题,本来以为手到擒来,毕竟这是个大家都讨论烂了的题,详情访问链接http://blog.csdn.net/ETF6996/article/details/51946250.既 ...

  7. 继续node爬虫 — 百行代码自制自动AC机器人日解千题攻占HDOJ

    前言 不说话,先猛戳 Ranklist 看我排名. 这是用 node 自动刷题大概半天的 "战绩",本文就来为大家简单讲解下如何用 node 做一个 "自动AC机&quo ...

  8. Node爬虫

    Node爬虫 参考 http://www.cnblogs.com/edwardstudy/p/4133421.html 所谓的爬虫就是发送请求,并将响应的数据做一些处理 只不过不用浏览器来发送请求 需 ...

  9. python--代码统计(进阶版)

    在上一篇的随笔中发表了代码统计小程序,但是发表后,我发现,以前写的代码怎么办 写了那么多,怎么就从0开始了呢,,,,我还是个孩子啊,不能这么残忍 于是,代码统计进阶版:统计当前目录下所有指定文件类型的 ...

随机推荐

  1. 文章翻译:Recommending items to more than a billion people(面向十亿级用户的推荐系统)

    Web上数据的增长使得在完整的数据集上使用许多机器学习算法变得更加困难.特别是对于个性化推荐问题,数据采样通常不是一种选择,需要对分布式算法设计进行创新,以便我们能够扩展到这些不断增长的数据集. 协同 ...

  2. Walle 2.0 发布系统

    目录 walle 2.0 1.walle原理 1.1.walle原理图 1.2.权限设计模型 2.部署walle 2.1.依赖检查安装 2.2.walle部署 3.Walle使用 3.1.用户配置 3 ...

  3. [CF986F]Oppa Funcan Style Remastered[exgcd+同余最短路]

    题意 给你 \(n\) 和 \(k\) ,问能否用 \(k\) 的所有 \(>1\) 的因子凑出 \(n\) .多组数据,但保证不同的 \(k\) 不超过 50 个. \(n\leq 10^{1 ...

  4. Django实现websocket完成实时通讯、聊天室、在线客服等

    一 什么是Websocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebS ...

  5. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...

  6. LeetCode Container With Most Water (Two Pointers)

    题意 Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai ...

  7. Dive查看docker镜像层信息

    1.主要采用docker运行dive的方式,不然宿主机还要安装go那些挺麻烦的.具体用法可查看官方: https://github.com/wagoodman/dive 2.拉取dive镜像 dock ...

  8. docker-compose编排

    创建并启动容器 docker-compose up -d 备注: -d 后台启动并运行容器 前提是你在执行该命令的时候已经编写好了docker-compose.yml文件,在这个文件的当前目录执行上述 ...

  9. PAT甲题题解-1068. Find More Coins (30)-dp,01背包

    一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...

  10. AD分辨率和精度区别

    最近做了一块板子,当然考虑到元器件的选型了,由于指标中要求精度比较高,所以对于AD的选型很慎重.很多人对于精度和分辨率的概念不清楚,这里我做一下总结,希望大家不要混淆.我们搞电子开发的,经常跟“精度” ...