前提:最近一直在看node,平时碎觉喜欢听盗墓笔记啥的有声小说,然后突然就就想试着写个爬虫自己下载下来,虽然有点多此一举,但是就当学习练练手了,在这里记录一下!

没有express基础的,请先行了解

确定需求

  • 1,拿到xmly的数据,分析api
  • 2,用node开发接口
  • 3,构建前端页面

一,前端页面构建

技术:vue-cli,iview,axios
ps:因为准备以后开发其他的demo都放到一起,用一个server去转发接口,所以准备搭建一个vue项目,方便以后加入其他的demo,如果你只是为了实现本文的功能,前端页面大可不必搭我这套,可以自选方法实现,具体实现效果如下图

二,拿到xmly的数据,分析api,用node发起请求拿到数据

2.1 找到xmly音频的真实链接

打开喜马拉雅的PC官网,随意选一个免费的小说点进去,打开浏览器控制后台,观察http请求,如下图

通过分析http请求,我们可以拿到api,在经过你不咋严密的观察后,你可以很容易分析出一些关键的字段

首先,我们先从请求参数分析,看下图:

可以看出albumId是识别每一本小说的唯一标识,这个字段我们将来就用于查询数据,后面的pageNum,pageSize很容观察出是用来做分页的。

接下来看响应的字段,在又经过你不咋严密的观察后,你会很容易的发现,下图的字段,肯定就是每条音频的详细api了

展开之后,在最后一次经过你不咋严密的观察后,你会发现很巧,你要的数据都在这里

想我这种英语四级都没过的人都看出来了,src:音频真实链接,tranckName:音频每集的名字,albumName:小说名

2.2 用node写一个简单的爬虫,抓取数据

需要用到的模块如下图:

superagent是nodejs里一个非常方便的客户端请求代理模块,他很大的特色就是链式调用,这里我用到superagent向https://www.ximalaya.com/revision/play/album发送get请求,拼上之前我们提到的请求参数

app.get('/', function (req, res, next) {let _res = res;let params = {albumId:'123131',pageNum:'1',sort:'-1',pageSize:'30'}let param = qs.stringify(params)superagent.get('https://www.ximalaya.com/revision/play/album?' + param).then(res => {_res.send(res.body.data.tracksAudioPlay)}).catch(err => {_res.send(err)})
})app.listen(5050,function(){console.log('正在监听5050端口')
})

启动node服务,在浏览器上输入http://localhost:5050/,应该就可以看到你请求到数据了,如下图:

OK,到现在我们的数据已经拿到了,喝杯茶水泡点枸杞休息一下,然后继续~

三,用node开发接口

3.1 确定我们的接口需求:

  1. /getXmlyList:实现通过albumId查询,获取音频的list,传给前端
  2. /downloadSingle:实现批量下载,将下载结果返回给前端

3.2 创建app.js 编写node服务:

//app.js
const express = require('express')
const querystring=require('querystring');
const path = require('path');
const api = require('./route/api')let app = express();//使用router中间件
app.use('/xmly',api)
//路由
app.get('/', function (req, res, next) {res.sendFile(path.join(__dirname + '/html/index.html'));
});
//监听端口
app.listen(5050,function(){console.log('正在监听5050端口')
})

3.3 创建route/api.js 编写api:

3.3.1 /getXmlyList 接口:
//获取数据列表
router.get('/getXmlyList',(req,res) => {let _res = res;let params = {albumId:req.query.albumId,//get请求的参数在req.query里pageNum:'1',sort:'-1',pageSize:'30'}let param = qs.stringify(params)//这里使用superagent代理发送get请求喜马拉雅的接口获取数据superagent.get('https://www.ximalaya.com/revision/play/album?' + param).then(res => {//这里请求成功将数据响应给前端_res.json({status: 1,msg: 'success',list: res.body.data.tracksAudioPlay})}).catch(err => {//响应获取数据失败_res.json({status: -1,msg: 'error'})})
});
3.3.2 /downloadSingle 接口:

1.使用fs.createWriteStream()写入文件:

var downLoadMp3 = function(dir,name,filePath){request(dir).pipe(fs.createWriteStream( filePath + name +'.mp3')).on('close',function(){console.log('saved' + name)})
}

2.使用async异步批量下载:

将文件下载在根目录的./mp3路径下

关于async的map操作,详见:async_demo/map.js,对集合中的每一个元素,执行某个异步操作,得到结果。所有的结果将汇总到最终的callback里。与forEach的区别是,forEach只关心操作不管最后的值,而map关心的最后产生的值。

  1. 并行执行。async.map同时对集合中所有元素进行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的任务的结果,未执行完的占个空位
  2. 顺序执行。async.mapSeries对集合中的元素一个一个执行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的结果,未执行的被忽略。
router.get('/downloadSingle',function(req, res, next){let mp3List = JSON.parse(req.query.paramJson)//检查是否存在./mp3路径如果不存在创建./mp3目录后再下载,如存在直接下载fs.exists('./mp3', function (exists) {// console.log(exists ? "it's there" : "no file!");if(!exists) {//创建./mp3目录fs.mkdir('./mp3',0777, function (err) {if (err) {throw err;}else {//使用async异步批量下载async.mapSeries(mp3List,function(item, callback){setTimeout(function(){downLoadMp3(item.dir,item.name,'./mp3/')callback(null, item);},400);}, function(err, results){res.json({status: 1,msg: 'saved!'})});}});}else {async.mapSeries(mp3List,function(item, callback){setTimeout(function(){downLoadMp3(item.dir,item.name,'./mp3/')callback(null, item);},400);}, function(err, results){res.json({status: 1,msg: 'saved!'})});}});});var downLoadMp3 = function(dir,name,filePath){request(dir).pipe(fs.createWriteStream( filePath + name +'.mp3')).on('close',function(){console.log('saved' + name)})
}

完整api.js代码如下:

const express = require('express');
const superagent = require('superagent');
const qs = require('querystring');
const router = express.Router();
const path = require('path')
const fs = require('fs')
const request = require('request')
const async = require('async')//获取数据列表
router.get('/getXmlyList',(req,res) => {let _res = res;console.log(req.query)let params = {albumId:req.query.albumId,pageNum:'1',sort:'-1',pageSize:'300'}let param = qs.stringify(params)superagent.get('https://www.ximalaya.com/revision/play/album?' + param).then(res => {// _res.send(res.body.data.tracksAudioPlay);// console.log(typeof res.body)_res.json({status: 1,msg: 'success',list: res.body.data.tracksAudioPlay})}).catch(err => {res.json({status: -1,msg: 'error'})})
});//下载音频
router.get('/downloadSingle',function(req, res, next){let mp3List = JSON.parse(req.query.paramJson)fs.exists('./mp3', function (exists) {// console.log(exists ? "it's there" : "no file!");if(!exists) {fs.mkdir('./mp3',0777, function (err) {if (err) {throw err;}else {async.mapSeries(mp3List,function(item, callback){setTimeout(function(){downLoadMp3(item.dir,item.name,'./mp3/')callback(null, item);},400);}, function(err, results){res.json({status: 1,msg: 'saved!'})});}});}else {async.mapSeries(mp3List,function(item, callback){setTimeout(function(){downLoadMp3(item.dir,item.name,'./mp3/')callback(null, item);},400);}, function(err, results){res.json({status: 1,msg: 'saved!'})});}});});var downLoadMp3 = function(dir,name,filePath){request(dir).pipe(fs.createWriteStream( filePath + name +'.mp3')).on('close',function(){console.log('saved' + name)})
}module.exports = router;

到此为止我们的node接口也解决了~,代码不多仔细分析分析相信所有人都能看懂的,接下来就启动node服务,然后在前端请求node写的接口就可以啦

源码链接戳此处
如有不足,欢迎指正~

node.js 实现简单爬虫批量下载喜马拉雅音频相关推荐

  1. 新一配:perl循环调用python爬虫批量下载喜马拉雅音频

    新一配:perl循环调用python爬虫批量下载喜马拉雅音频 手机下载喜马拉雅音频后,获得的音频文件虽然可以转成mp3格式,但其文件名却是一长串字符串,无法辨别是哪一集,网上找了各种工具,都有局限性, ...

  2. 【爬虫实战项目】Python爬虫批量下载评书音频并保存本地(附源码)

    前言 今天给大家介绍的是Python爬虫批量下载评书音频并保存本地,在这里给需要的小伙伴们代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是这 ...

  3. Node.js实现简单爬虫 讲解

    一.什么是爬虫 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定规则,自动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模 ...

  4. 简单python网络爬虫批量下载视频

    寒假闲来无事,决定尝试一下用python写一个小网络爬虫批量下载视频. 由于是第一次写网络爬虫,可以说是两眼一抹黑,整个程序都是自己一点点试出来的,所以程序本身肯定有一些漏洞和缺陷,如果有建议请批评指 ...

  5. python爬虫下载链接_【Python项目】简单爬虫批量获取资源网站的下载链接

    简单爬虫批量获取资源网站的下载链接 1 由来 自己在收集剧集资源的时候,这些网站的下载链接还要手动一个一个复制到百度云离线下载里,稍微懂了一点编程就不想做这种无意义的劳动了.于是就写了一个这样的一个小 ...

  6. Node.js实现简易爬虫

    为什么选择利用node来写爬虫呢?就是因为cheerio这个库,全兼容jQuery语法,熟悉的话用起来真真是爽 依赖选择 cheerio: Node.js 版的jQuery http:封装了一个HTP ...

  7. python爬虫批量下载“简谱”

    python讨论qq群:996113038 导语: 上次发过一篇关于"python打造电子琴"的文章,从阅读量来看,我们公众号的粉丝里面还是有很多对音乐感兴趣的朋友的.于是,今天我 ...

  8. Node.js实现网络爬虫

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.必要工具安装 二.爬取前操作 三.爬取新闻数据 四.建立个人网页展示爬取内容 总结 前言 网络爬虫是按照一定规则自 ...

  9. Node.js的完全卸载与下载安装及各种npm、nvm、nrm配置(保姆式教程---提供全套安装包)---node.js的安装与配置(0)

    Node.js的完全卸载与下载安装及各种npm.nvm.nrm配置(保姆式教程-提供全套安装包)-node.js的安装与配置(0) node的卸载 1.打开控制面板 我的电脑右键--->属性-- ...

最新文章

  1. 基于c语言优先级病房呼叫_C语言
  2. 自定义UISearchBar外观
  3. CentOS7防火墙服务(Firewalld)关闭实战
  4. SAP RETAIL WA01 创建分配表报错 - Plant 0000000039 Confirmation date not maintained.-
  5. macOs下全局安装npm包的设置问题
  6. PHP 页面编码声明方法详解(header或meta)
  7. 人的执念真的是非常的可怕
  8. [转]Visual Studio 项目类型 GUID 清单
  9. linux编程参数列表,Linux编程 14 文件权限(用户列表passwd,用户控制shadow,useradd模板与useradd命令参数介绍)...
  10. angualr Material Icons
  11. Flutter实战一Flutter聊天应用(二十)
  12. linux系统编程 -- 僵尸进程 孤儿进程
  13. [译] Commit 提交指南
  14. SpringNet整合NHibernate相关配置
  15. DIY LDAC蓝牙接收器(二)硬件调试篇
  16. hdu 5857 Median(模拟)
  17. win10MATLAB如何完全卸载,怎么完全卸载cad_win10彻底卸载cad的图文步骤-系统城
  18. Maven项目配置依赖时报错:Duplicated tag: ‘plugins‘...不会解决
  19. Python练习题024:分数相加
  20. mfc通过ado链接oracle,VS2013环境下MFC通过ADO连接Oracle数据库 四步搞定

热门文章

  1. Android App 性能优化之图片优化
  2. 网线有网,路由器连接之后没网,解决办法
  3. matlab 山脊 提取,ArcGIS中利用水文分析提取山脊线山谷线
  4. 如何制作自己的网站?
  5. 初中计算机表格处理教案,中学信息技术教案《制作excel表格》
  6. JBE、JNBE、JA、JL指令详解(从原理上)
  7. 关于GitHub Education(GitHub教育认证)认证
  8. python 根据x的值和函数y=20+x2,计算y_new,算出y_new和y的差,记为delta_y。¶绘制x和delt_y的点图,并计算y的方差。有关方差的计算参阅数学资料。
  9. #编写一个函数,实现接受一个字符串,分别统计大写字母、小写字母、数字、其他字符的个数,并且返回结果
  10. Python小工具:批量给视频加水印