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

  1. const url = require('url')
  2. const glib = require('zlib')
  3.  
  4. //默认头部
  5. const _default_headers = {
  6. 'Accept-Encoding': 'gzip, deflate, br',
  7. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'
  8. }
  9.  
  10. //options(url,method,header)--http头部信息 isDebug--是否开启调试状态
  11. module.exports = function(options, isDebug) {
  12. if(typeof options === "string") {
  13. options = {
  14. url: options,
  15. method: 'GET',
  16. headers: {}
  17. }
  18. } else {
  19. options = options || {}
  20. options.method = options.method || 'GET'
  21. options.headers = options.headers || {}
  22. }
  23. options.headers = Object.assign(_default_headers, options.headers)
  24.  
  25. function debug(msg) {
  26. if(isDebug) {
  27. console.log(msg)
  28. }
  29. }
  30.  
  31. return new Promise((resolve, reject) => {
  32. req(options)
  33.  
  34. function req(options) {
  35. //判断是http还是https
  36. let urlObj = url.parse(options.url)
  37. let mod = null
  38. port = 0
  39.  
  40. if(urlObj.protocol == 'https:') {
  41. mod = require('https')
  42. port = 443
  43. } else {
  44. mod = require('http')
  45. port = 80
  46. }
  47.  
  48. let _req_options = {
  49. hostname: urlObj.hostname,
  50. port,
  51. path: urlObj.path,
  52. method: options.method,
  53. headers: options.headers
  54. }
  55. //开始模拟,爬取信息
  56. let req_obj = mod.request(_req_options, (res) => {
  57. if(res.statusCode!==200) {
  58. //如果是重定向则重新在请求
  59. if(res.statusCode == 301 || res.statusCode === 302) {
  60. options.url = res.headers.location
  61. debug('重定向: '+res.headers.location)
  62. req(options)
  63. } else {
  64. reject(res.statusCode)
  65. }
  66. } else {
  67. //statusCode是200时接受data buffer
  68. let data = []
  69. res.on('data', buffer => {
  70. data.push(buffer)
  71. })
  72. res.on('end', () =>{
  73. let buffer = Buffer.concat(data)
  74. //判断是否传输有误
  75. if (res.headers['content-length'] != buffer.length) {
  76. debug('收到数据有误,正在重新获取')
  77. req(options)
  78. }
  79. //判断是否有用gzip
  80. else if (res.headers['content-encoding'] && res.headers['content-encoding'].includes('gzip')) {
  81. buffer = glib.gunzip(buffer, (err,data) => {
  82. debug('gzip解压完成并成功返回')
  83. resolve(data)
  84. })
  85. } else {
  86. debug('成功返回')
  87. resolve(buffer)
  88. }
  89. })
  90. }
  91. })
  92. req_obj.on('error', err => {
  93. debug('爬虫失败')
  94. reject(err)
  95. })
  96. req_obj.end()
  97. }
  98. })
  99. }

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

举个例子:

我要爬个bilibili的视频:

  1. const url = require('url')
  2. const fs = require('fs')
  3.  
  4. function getVideo(options, headers, fileName) {
  5. if(typeof options === "string") {
  6. options = {
  7. url: options,
  8. method: 'GET',
  9. headers: {},
  10. timeout: 2000
  11. }
  12. } else {
  13. options = options || {}
  14. options.method = options.method || 'GET'
  15. options.headers = options.headers || {}
  16. options.timeout = options.timeout || 2000
  17. }
  18. options.headers = headers
  19.  
  20. return new Promise((resolve, reject) => {
  21. req(options)
  22.  
  23. function req(options) {
  24. //判断是http还是https
  25. let urlObj = url.parse(options.url)
  26. let mod = null
  27. port = 0
  28.  
  29. if(urlObj.protocol == 'https:') {
  30. mod = require('https')
  31. port = 443
  32. } else {
  33. mod = require('http')
  34. port = 80
  35. }
  36.  
  37. let _req_options = {
  38. hostname: urlObj.hostname,
  39. port,
  40. path: urlObj.path,
  41. method: options.method,
  42. headers: options.headers,
  43. timeout: options.timeout
  44. }
  45. //开始模拟,爬取信息
  46. let req_obj = mod.request(_req_options, (res) => {
  47. // 视频路径
  48. const filePath = `${__dirname}/${fileName}`;
  49. if (fs.existsSync(filePath)) {
  50. fs.unlinkSync(filePath)
  51. }
  52. res.on('data', buffer => {
  53. fs.appendFileSync(filePath, buffer)
  54. const size = fs.statSync(filePath).size;
  55. console.log(`已下载${(size / 1024 / 1024).toFixed(2)}MB,完成${(size/res.headers['content-length'] * 100).toFixed(2)}%`)
  56. })
  57. res.on('end', () =>{
  58. resolve()
  59. })
  60. })
  61. req_obj.on('error', err => {
  62. debug('爬虫失败')
  63. reject(err)
  64. })
  65. req_obj.end()
  66. }
  67. })
  68. }
  69.  
  70. // 生成文件名
  71. const fileName = '1.flv'
  72. // 链接
  73. 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';
  74. // 头部
  75. const header = {
  76. 'Origin': 'https://www.bilibili.com',
  77. 'Referer': 'https://www.bilibili.com/video/av21061574',
  78. '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',
  79. }
  80.  
  81. getVideo(videoUrl, header, fileName).then(res => {
  82. console.log('写入成功');
  83. })

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. [Zlib]_[初级]_[使用zlib库压缩和解压STL string]

    场景 1.一般在使用文本json传输数据, 数据量特别大时,传输的过程就特别耗时, 因为带宽或者socket的缓存是有限制的, 数据量越大, 传输时间就越长. 网站一般使用gzip来压缩成二进制. 说 ...

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

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

  3. PowerShell 操作 Azure SQL Active Geo-Replication

    前文中我们比较全面的介绍了 Azure SQL Database Active Geo-Replication 的主要特点和优势.接下来我们将从自动化的角度介绍如何通过 PowerShell 在项目中 ...

  4. Stm32l151+mpu6050+uart读取数据调试

    新近买了一个MPU6050模块,如上图,这个模块上的三块黑色分别是:稳压芯片662K,STM8s003f3p6,MPU6050. 根据此模块的说明书,可以使用USB转TTL将模块与上位机连接,通过卖家 ...

  5. Loadrunner 面试常见问题

    三大组件: 脚本生成器,录制和调试脚本 . 控制台,设置运行和资源场景 结果分析器,将测试结果数据以不同的图表呈现,便于性能分析 工作原理: 录制:根据不同协议,记录下客户端和服务器二者之间的对话,生 ...

  6. LintCode——第K大元素

    第K大元素:在数组num中找到第k大的元素(可以交换数组中的元素的位置) 样例: 数组 [9,3,2,4,8],第三大的元素是 4 数组 [1,2,3,4,5],第一大的元素是 5,第二大的元素是 4 ...

  7. 从零系列--开发npm包(一)

    一.目的 主要是纪录和回顾自己开发的一些步骤以及遇到的一些问题和解决方案 二.准备工作 1.IDE 选择 VS Code 2.安装node 环境 (https://nodejs.org/zh-cn/) ...

  8. 高可用Kubernetes集群-14. 部署Kubernetes集群性能监控平台

    参考文档: Github介绍:https://github.com/kubernetes/heapster Github yaml文件: https://github.com/kubernetes/h ...

  9. Beta阶段展示博客

    Beta阶段展示博客 1. 团队成员的简介和个人博客地址 刘畅 博客园ID:森高Slontia 身份:PM 个人介绍: 弹丸粉 || 小说创作爱好者 || 撸猫狂魔(x || 生命的价值在于创造 (我 ...

  10. jmeter学习(1)基础支持+安装部署

    1. Apache jmeter 是100%的java桌面应用程序 支持的协议有:WEB-HTTP/HTTPS   , SOAP,   FTP,  JDBC,  LDAP, MAIL, MongoDB ...