# Ape
**Repository Path**: showlotus/ape
## Basic Information
- **Project Name**: Ape
- **Description**: 51Ape音乐资源爬取,在线地址: https://showlotus.gitee.io/ape
- **Primary Language**: JavaScript
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-01-19
- **Last Updated**: 2021-05-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
- 接口: 根据最后的时间戳不同,随机获取一些歌手的主页地址
- http://www.51ape.com/skin/ape/php/changeul_2.php?_=1610772872499
- 由于歌手主页地址大部分都是姓名的拼音,遂想到一个将汉字转为拼音的插件 [pinyin.js](https://www.npmjs.com/package/pinyin),不过用 `npm` 安装总是失败(俺也不知道为啥)
- 用 `Node` 中的 `http` 模块,发送 `get` 请求,可以得到页面源代码
```js
http.get(url, res => {
if (res.statusCode !== 200) { // 判断状态码
return
}
var html = ''
res.on('data', data => {
html += data
})
res.on('end', () => {
fs.writeFile('target.html', html, err => {
if (err) console.error('error')
console.log('文件创建成功')
})
})
}).on('error', err => {
console.log('errorMessage: ' + err)
})
```
- 得到源代码后,用正则匹配链接地址和歌名,太慢了,了解到一个字符串库 [string.js](https://www.cnblogs.com/qianxiaox/p/13744763.html),主要用到 `S(str).between(left, right)` 这个方法
```js
let str = `专辑《范特西》.flac`
let res = S(str).between(`50K+ 缩短到 10K+,速度直接起飞,芜湖!
- 接着就是歌手列表,这个网站对于歌曲多的歌手,会单独设置一个页面,并且在列表页会用加粗字体显示,而对于有些歌曲少的歌手,只是弹出一个对话框。(最后,随便测了几个,发现歌少的也加粗,歌多的反而不加粗,emmmmm)。但是,还是向后端发送了一个请求,可以直接获取到干净利索地数据,不用格式化了。( `qx` 是歌手名关键字)
- http://www.51ape.com/skin/ape/php/qx_2.php?qx=Accardo
- 对于英文名的歌手,之间保留原名称,若中间有空格则用 `+` 号代替
- 对于中文名的歌手,原网站是将其转为了 `UTF-8` 格式的 `URL` 编码
- 这部分的正则怎么写都有问题(因为用了 `.*` 匹配中间的字符,导致正则尽可能匹配更多的,用 `.{0,n}` 即可,`n` 的取值为要匹配中间字符长度的大约2倍左右),于是就换了种方法,因为这段代码直接是一个 `ul` 包裹起来的,遂就用 `` 作为分隔点,再用 `S(str).between()`,真香!
- 本来想着,有一个搜索页面,根据用户搜索的歌手,发送对应的 `http` 请求,然后将返回结果,再进行页面优化展示。后来,因为这些脚本是在 `node` 环境中执行的,在浏览器中行不通。所以,只能将这些数据保存为 `JSON` 格式,再根据用户需求,对 `JSON` 进行检索,返回对应数据。
- 先完成歌手列表页,信息的抓取,并做标记,有单独页面的和没有单独页面的
- 存完了所有歌手信息,简单实现一下搜索功能
- 用 `CSS` 变量添了一个深色主题,紧跟潮流。想着调用一下当前所在地日落日出的时间API,设置相应的主题,不过搜了好多,没找到这个库,那就先放一放。(一个根据经纬度计算日出日落时间的算法)
- 待办:根据日出日落时间,设置相应的主题
- 需要给歌手搜索那块,加一个模糊搜索,选中歌手后,下方展示他的一些歌曲,这就得需要组件了和 `Vue`了。
- 要展示搜索歌手的歌曲信息,还是用老办法,先存下来,再取出来。为了取的时候方便,需要对每个歌手的歌曲列表单独设立一个文件,并用歌手的标识 `id` 作为文件名(之前,存歌手信息的时候忘记加标识 `id`,刚好这下给补上),歌手就有 `1400+` ,若是把所有歌曲都放到一个 `JSON` 文件里,太过庞大,读取的时候也会比较麻烦,单独存储的优势还是很明显的。
- 又遇到了老生常谈的问题,异步数据,只能打印,无法输出。干脆就直接在得到的时候,存入文件中。这一步执行脚本的时候,要用 `node`,切忌用 `nodemon`,否则会陷入死循环。
- 遗漏:
- 0-99 (7) : 9,26,29,31,56,62,64
- 100-199 (19):
- 200-299 (9)
- 300-399 (13)
- 400-499 (3)
- 500-599 (10)
- 600-699 (38)
- 700-799 (1)
- 800-899 (45)
- 900-999 (10)
- 1000-1099 (4)
- 1100-1199 (36)
- 1200-1299 (19)
- 1300-1404 (7)
- 总计:221 - 错误率:16%( 221 / 1404 ),还能接受。总计跑了2个小时,这些遗漏的只能单独添加了(估计又得耗一天)。
- 补齐那些缺少的,因为都有 `id` 作为唯一标记,按 `id` 对文件夹里的所有文件进行遍历,若无法读取到文件,则说明,该文件缺失,遂进行后续添加处理,两遍跑下来,就还剩 `47` 了。然后缩小区间,再遍历,最后终于找到了那几个老鼠屎。中间有个小插曲,因为对那些歌曲数排名前几的感兴趣,于是就到原网页看了看,发现 `谭咏麟` 老哥的歌曲页最高到了24页,emmmmm,因为之前设置的最高页数为20页,这下好了,翻车了,只能删了,重新获取,还好就这个一个翻车,问题不大。
- 一路执行下来,除了个别的要么地址有些古怪,要么就是个空页面(新建一个空的 `JSON` 文件),正则抓取不到,其它都成功了,对自己的正则还是很有信心滴,嘻嘻。`1404` 个 `JSON` 文件,终于告一段落,该开始开展下一部分工作了。
- 搜索歌手展示歌曲跳转到网盘链接这块,想了两种方法
1. 鼠标滑入,弹出文字提示框,有一个直达网盘的链接和可点击复制的网盘密码
2. 鼠标直接点击后跳转到网盘页面,并在点击时触发复制密码
最后选了第二种,有很大原因是 `elementUI-tooltip` 出现和消失的动效不好看,好看才是王道!
- 其实,可以直接将歌曲源地址作为跳转的链接,不过那样,用户还是会访问到源网站。我想的是用户能完全抛弃源网站,不依赖它做其他事情。这也就意味着,要将每个歌曲地址页面再进行解析,得到网盘地址和密码,又要大干一场。
- 歌曲太多时,会出现滚动条,单纯地设置父容器 **`overflow: hidden`** 会显得太过生硬。于是就在上下边界各加了一个,向上/向下(纵向渐变)的渐变条,主要是通过:1. 设置主体内容的上下边距(边距<=渐变条高度),为渐变条腾出空间;2. 两个渐变条占据对应的位置,这两个渐变条可以通过父容器的两个伪类 `::before` 和 `::after` 实现,分别设置两个 `div` 也行。
- 点击链接复制密码,因为选中然后复制操作只能用 ``/``/`