携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情
前几天,一个网友向我提出了这样一个需求:
他是一个up主舰长群的管理,每次有舰长加群的时候他都要审核昵称是否正确,但是B站缺少这样一个页面,要查舰长就需要一页一页的翻,一页总共也没几个舰长,三百多个舰长就要翻半天,有没有什么办法可以让他直接看到舰长列表。
获取数据
解决方法也不难,进入查找舰长的页面,使用浏览器控制台找到这个请求:
请求的地址是:
https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=[直播间ID]&page=[页码]&ruid=[up主ID]&page_size=[页码]
分析一下返回值的结构,发现舰长列表在data.list
中:
那么问题就简单了,直接循环调用这个接口,每次page
加一,直到取不到数据为止,最后再加上一点对前三名舰长的处理,将获取的数据做成一个表格就是这样的代码:
'use strict';
var axios = require('axios');
async function getGuard() {
var allGuardList = [];
function getGuardPerPage(roomid, ruid, page = 1) {
return new Promise(resolve => {
var config = {
method: 'get',
url: `https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=${roomid}&page=${page}&ruid=${ruid}&page_size=29`,
headers: {
'authority': 'api.live.bilibili.com',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6',
'cache-control': 'max-age=0',
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
};
axios(config)
.then(function (response) {
var guardList = response.data.data.list;
var newList = guardList.map(item => {
return {
username: item.username,
uid: item.uid
}
});
if (page == 1) {
var top3List = response.data.data.top3;
var newTop3List = top3List.map(item => {
return {
username: item.username,
uid: item.uid
}
});
allGuardList.unshift(...newTop3List);
}
if (newList.length) {
setTimeout(() => {
allGuardList.push(...newList);
var newPage = page + 1;
getGuardPerPage(roomid, ruid, newPage).then(resolve)
}, 200 * Math.random());
}
else {
resolve(allGuardList);
}
})
.catch(function (error) {
console.log(error);
});
})
}
var result = await getGuardPerPage(22696653, 698029620, 1)
var html = "";
html += `总数:${result.length}(B站接口说不定会经常变,偶尔核对一下总数,数量不对找我)<br>
<table>`
result.forEach(item => {
html += `<tr><td>${item.uid}</td><td>${item.username}</td></tr>`
});
html += `</table>`
return html;
}
module.exports = getGuard;
Express写接口
获取了数据之后,下一步写个接口,最简单而且最常用(其实是我只会用)的就是express了。
首先新建一个文件夹,初始化npm并安装express:
npm init -y #传入这个-y参数就不用填那些作者之类的信息了,懒人专用
npm i express --save
之后做个简单的引入(包括刚才导出的方法):
const express = require("express");
const app = express();
const getGuard = require("./feature/getGuard");
然后写一个简单的接口:
app.get('/lanyin_guard', async function (req, res) {
var guard = await getGuard();
res.send(guard);
})
最后简单的打开一个端口:
app.listen(9527, function () {
console.log("又开始了啊")
})
齐活:
丢到云托管上去
接口是好了,可以不能一直放在我本地跑,一来是我没有公网IP(垃圾某动运营商),二来我总不能一直开着电脑。但是光为了这么个小功能买个服务器又不划算,因此,serverless云托管成为了一个不错的选择。
serverless云托管是一种无服务器运行代码的方式,你把自己的代码托管上去之后,自己设定触发条件(定时、HTTP请求等),根据程序运行期间的CPU和内存消耗来计算费用,比买个服务器划算很多(而且各大厂商还有白嫖),我选择了微信云托管(可以白嫖三个月),注册完成进入控制台后,选择模板部署-新建服务-记得勾选公网访问:
之后在新建的服务里点击发布:
选择手动上传代码包,端口写刚才代码里打开监听的:
注意:要使用云托管的话还要在同级目录下放一个Dockerfile文件,主要是用来描述这个服务使用什么样的容器的:
# 镜像名 可以去这个网站找https://hub.docker.com/_/node
FROM node:12-slim
# 新建并进入文件夹
WORKDIR /usr/src/app
# 复制package.json和package-lock.json文件
COPY package*.json ./
# 安装依赖
RUN npm install --only=production
# 将本地代码复制到容器的目录(也就是刚才新建的)
COPY . ./
# 开启服务,忘了说了这个要在package.json里写
# "scripts": {
# "start": "node index.js"
# }
# 或者这里也可以直接写CMD ["node", "index.js"]
CMD [ "npm", "start" ]
上传好代码包之后,点击发布,程序就跑起来了,我们可以通过服务设置标签下的域名来访问服务:
自定义域名
如果你手里没有已经备案的域名的话,就跳过这段吧……
刚才的公网域名里有这样一个提示:
如果是自己用用还好,如果放出去的话肯定有问题,于是需要自定义域名(记得这个域名需要备案),在左侧选择自定义域名,输入自己的域名,如果要开启HTTPS的话还需要上传证书:
点击确定后,列表中就会多一条记录,复制记录中的CNAME地址:
然后去你自己域名的域名解析配置中添加这条CNAME记录(截图里是腾讯云):
这样就可以用自己的域名来访问了: