nodejs+express+serverless部署一个查询b站舰长列表的接口

784 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

前几天,一个网友向我提出了这样一个需求:

他是一个up主舰长群的管理,每次有舰长加群的时候他都要审核昵称是否正确,但是B站缺少这样一个页面,要查舰长就需要一页一页的翻,一页总共也没几个舰长,三百多个舰长就要翻半天,有没有什么办法可以让他直接看到舰长列表。

获取数据

解决方法也不难,进入查找舰长的页面,使用浏览器控制台找到这个请求:

image.png

请求的地址是:

https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=[直播间ID]&page=[页码]&ruid=[up主ID]&page_size=[页码]

分析一下返回值的结构,发现舰长列表在data.list中:

image.png

那么问题就简单了,直接循环调用这个接口,每次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("又开始了啊")
})

齐活:

image.png

丢到云托管上去

接口是好了,可以不能一直放在我本地跑,一来是我没有公网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" ]

上传好代码包之后,点击发布,程序就跑起来了,我们可以通过服务设置标签下的域名来访问服务:

自定义域名

如果你手里没有已经备案的域名的话,就跳过这段吧……

刚才的公网域名里有这样一个提示:

image.png

如果是自己用用还好,如果放出去的话肯定有问题,于是需要自定义域名(记得这个域名需要备案),在左侧选择自定义域名,输入自己的域名,如果要开启HTTPS的话还需要上传证书:

点击确定后,列表中就会多一条记录,复制记录中的CNAME地址:

然后去你自己域名的域名解析配置中添加这条CNAME记录(截图里是腾讯云):

这样就可以用自己的域名来访问了:

image.png