用Arduino玩转掌控板(ESP32):B站粉丝计数器-程序员宅基地

技术标签: 串口通信  glassfish  arduino  数据可视化  单片机  

众所周知,掌控板在创客教育中用的非常广泛,它是一块基于 ESP32 的学习开发板。大家对掌控板编程,用的比较多的都是图形化编程的方式,比如 mPython、Mind+ 等。但是,既然掌控板是基于 ESP32 芯片的,所以我们也可以用 Arduino 软件对其编程。所以,有时间的话,我准备给大家分享一系列用 Arduino 代码对掌控板(ESP32)编程的教程:用 Arduino 玩转掌控版(ESP32)系列

本期给大家带来的是:B 粉计数器(B站粉丝计数器)。

# 前言

如果大家有在玩一些自媒体平台的话,比如微信公众号、B站、知乎、抖音等,那么相信大家对自己的粉丝数、阅读数或者播放量等相关的数据会比较关注,但是每次手动去查看又比较麻烦。

那么有没有简单一些的方法呢?在创客技术宅眼里,万物皆可自动化!

今天就以 B 站为例,手把手教大家做一个桌面 B 站粉丝计数器!为什么是 B 站呢?因为 B 站做起来最简单啊……(哭……)

先来看一下效果,我用 Arduino 软件分别将程序上传至掌控板(ESP32)和 NodeMCU(ESP8266),看到的效果基本是一样的。本来还想做个外壳的,无奈被疫情隔离在家,设备不多,只能做个简易版了,大家将就看看吧。

掌控板(ESP32)显示效果


NodeMCU(ESP8266)显示效果

纳尼!粉丝数竟然那么少!丢脸丢脸,还不赶紧三连支持一下喽~

干啥啥不行,骗粉第一名!

下面开始正式教程。

# 获取 B 站 API

首先用谷歌浏览器(推荐)打开 B 站个人主页,如下图所示,重点关注我圈出来的几个地方,分别是:关注数、粉丝数、点赞数、播放分数,这几个数据的含义,大家一看就明白了,就不解释了。另外还要关注右下角的 UID,这是一串数字,在 B 站中就是你的唯一 ID,这个数字很重要,后面会用到。

然后在键盘上按下 F12 或者 Ctrl+Shift+I 进入浏览器调试模式,刷新一下 B 站个人主页,然后就会在 Network(网络)标签页下看到一堆返回的数据,从中我们可以看到数据请求的方法(比如 GET),以及对应的 Domain(网址域名)。这里我们要重点关注几行数据,那就是 Domain 为 api.bilibili.com 的几行,下图中我已经圈出来了。

我们逐一点进去排查,切换到 Response 标签页,在这里我们看到了 2 个熟悉的数据:following(102)和 follower(133),这不正是我们在 B 站个人主页看到的我的关注数(102)和粉丝数(133)么?

我们在切换到 Headers 标签页,看到请求的网址(Request URL)如下,请求方法为 GET。

我们将这个网址复制出来观察一下:

https://api.bilibili.com/x/relation/stat?vmid=224425204&jsonp=jsonp&callback=__jp4

其中有一段 vmid=224425204,这后面的数字,不正是我们前面提到的 UID 么?后面的 jsonp、callback 应该是对应的一些回调函数,我们将这些删除,只保留前面部分:

https://api.bilibili.com/x/relation/stat?vmid=224425204

并将它复制到浏览器地址栏去访问一下,看到什么了?是不是只留下一堆最简单的数据,里面包含了我们的关注数与粉丝数?而且这对数据是 JSON 格式的。

我们将这些数据格式化一下,方便我们查看。这里使用了 VS Code,或者你也可以使用网上其他的 JSON 在线格式化工具,这里不展开了。

同样的方法,我们去查一下播放数和获赞数在哪里可以查到。

相信你很快就找到了,如下图所示,先找到数据位置:

再查看相应的 API 网址:

https://api.bilibili.com/x/space/upstat?mid=224425204&jsonp=jsonp&callback=__jp5

将末尾无关参数删除后:

https://api.bilibili.com/x/space/upstat?mid=224425204

然后再将这个网址在浏览器中打开,我们就看到了熟悉的播放数(view:9047)和获赞数(likes:57)。

在 VS Code 中将数据格式化,方便查看。

# 代码编写

## 联网设置

要去获取 B 站的数据,当然要联网啦。我们在程序的最开头,引入一堆联网相关的头文件。这里有一个比较特殊的地方,就是我们同时引入了 ESP32 和 ESP8266 对应的头文件,这样在编译程序的时候,就会根据所选择的的开发板,自动编译对应部分,而不会报错,做到了一套程序兼容两种开发板(ESP32 和 ESP8266)的目的。

#if defined(ESP32)
  #include <WiFi.h>
  #include <HTTPClient.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
  #include <ESP8266HTTPClient.h>
#else
  #error "Please check your mode setting,it must be esp8266 or esp32."
#endif


#include <Wire.h>


// Wi-Fi
const char *ssid = "wifi_name";
const char *password = "wifi_password";


void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
}


void loop()
{
}

既然要联网,就需要定义你的网络名称和密码,对应修改就行:

const char *ssid = "wifi_name";
const char *password = "wifi_password";

上面连接 Wi-Fi 的程序,就不展开了,基本是标准写法,在 WiFi 这个库里,找一下例程复制一下就行。

## 获取粉丝数

连接上网络之后,就可以去获取粉丝数了,除了上面已经引入的头文件 HTTPClient,这个库文件可以用来获取网站上的数据。我们还需要用到的 ArduinoJson 这个 JSON 解析库,可以用来解析网站返回的 JSON 数据,并且初始化一个 JSON 解析对象 jsonBuffer。

ArduinoJson 目前比较流行的有两个版本:V5 和 V6,V5 比较经典和稳定,V6 比较新。两个版本使用起来稍有差异,博主这里使用的是 V5 版本。

#include <ArduinoJson.h>


DynamicJsonBuffer jsonBuffer(256); // ArduinoJson V5

另外,我们还需要定义 API 的网址、以及初始化粉丝数,单独拎出来是方便大家修改。注意,这里我们网址的访问方式为 http,而不是 https,因为 https 的话,代码会复杂一些。

// bilibili api: follower, view, likes
String UID = "224425204";
String followerUrl = "http://api.bilibili.com/x/relation/stat?vmid=" + UID; // 粉丝数


long follower = 0; // 粉丝数

然后再写一个获取粉丝数的函数 getFollower(String url),只要传入对应的 API 网址,就能利用 HTTPClient 中的 GET 方法,获取相应的数据,然后再用 ArduinoJson 库进行解析。

void getFollower(String url)
{
  HTTPClient http;
  http.begin(url);


  int httpCode = http.GET();
  Serial.printf("[HTTP] GET... code: %d\n", httpCode);


  if (httpCode == 200)
  {
    Serial.println("Get OK");
    String resBuff = http.getString();


    // ---------- ArduinoJson V5 ----------
    JsonObject &root = jsonBuffer.parseObject(resBuff);
    if (!root.success())
    {
      Serial.println("parseObject() failed");
      return;
    }


    follower = root["data"]["follower"];
    Serial.print("Fans: ");
    Serial.println(follower);
  } else {
    Serial.printf("[HTTP] GET... failed, error: %d\n", httpCode);
  }


  http.end();
}

最后再在 setup() 中调用一下,看看效果:

void setup()
{
  // other setup codes ...
  getFollower(followerUrl);
}

打开 Arduino 串口监视器,返回数据正常,说明成功了。

## 获取播放数与获赞数

这个与获取粉丝数的原理一样,不再赘述,直接看代码:

// bilibili api: follower, view, likes
String UID = "224425204";
String followerUrl = "http://api.bilibili.com/x/relation/stat?vmid=" + UID;   // 粉丝数
String viewAndLikesUrl = "http://api.bilibili.com/x/space/upstat?mid=" + UID; // 播放数、点赞数


long follower = 0; // 粉丝数
long view = 0; // 播放数
long likes = 0; // 获赞数


void setup()
{
  // other setup codes ...
  getFollower(followerUrl);
  getViewAndLikes(viewAndLikesUrl);
}


void getViewAndLikes(String url)
{
  HTTPClient http;
  http.begin(url);


  int httpCode = http.GET();
  Serial.printf("[HTTP] GET... code: %d\n", httpCode);


  if (httpCode == 200)
  {
    Serial.println("Get OK");
    String resBuff = http.getString();


    // ---------- ArduinoJson V5 ----------
    JsonObject &root = jsonBuffer.parseObject(resBuff);
    if (!root.success())
    {
      Serial.println("parseObject() failed");
      return;
    }


    likes = root["data"]["likes"];
    view = root["data"]["archive"]["view"];
    Serial.print("Likes: ");
    Serial.println(likes);
    Serial.print("View: ");
    Serial.println(view);
  } else {
    Serial.printf("[HTTP] GET... failed, error: %d\n", httpCode);
  }


  http.end();
}

打开 Arduino 串口监视器,返回数据正常,说明成功了。

## OLED屏:数据显示

获取到数据之后,我们总不能一直在串口监视器里面查看吧,所以我们利用一个 OLED 12864 屏幕,将数据显示到屏幕上。代码如下:

#include <U8g2lib.h>


// 1.3' OLED12864
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
// 0.96' OLED12864
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);


void setup()
{
  // other setup codes ...
  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setFont(u8g2_font_wqy12_t_gb2312b);
  u8g2.setFontPosTop();
  u8g2.clearDisplay();
}


void loop()
{
  u8g2.firstPage();
  do
  {
    display(follower, likes, view);
  } while (u8g2.nextPage());
}


void display(long follower, long likes, long view)
{
  u8g2.clearDisplay();
  u8g2.setCursor(5, 2);
  u8g2.print("B站粉丝计数器");
  u8g2.setCursor(5, 20);
  u8g2.print("粉丝数:" + String(follower));
  u8g2.setCursor(5, 36);
  u8g2.print("获赞数:" + String(likes));
  u8g2.setCursor(5, 52);
  u8g2.print("播放数:" + String(view));
}

这里我们用到了 u8g2 库,它是专门用来控制各种显示屏的。在 setup() 中设置了相应的显示参数,定义了一个显示函数 display(long follower, long likes, long view),可以同时传入相应的数据,并显示出来。然后在 loop() 中调用,看看显示效果。

## 定时器:定时获取数据

有了前面的步骤,我们已经可以正常获取数据并且显示数据了,但是你们可能会问:为什么前面调试时把获取数据的函数放在 setup() 中呢?而不是 loop() 中呢?这样每次程序开机只能读取一次,岂不是太麻烦了?放在 loop() 不就可以不断读取并且更新了么?

不是这样的,如果我们放在 loop() 中,不做其他干预,不断去读取的话,就会由于访问频率太高,触发 B 站的保护机制。不信你就不断刷新 B 站的某个 API 地址试试,相信你一定会看到如下“该页面无法访问”的页面。

无法访问

所以呢,我们就需要定时器,隔一段时间去获取一次数据,而且我们也不是大 V,数据变化不会很快,所以每隔 10 分钟去获取一次数据就绰绰有余了。直接看代码:

#include <Ticker.h>


Ticker timer;
int count = 0;
boolean flag = true;


void setup()
{
  // other setup codes ...
  timer.attach(600, timerCallback); // 每隔10min
}


void loop()
{
  while (flag)
  {
    if (count == 0)
    {
      // display data
      Serial.println("count = 0, display data");
      u8g2.firstPage();
      do
      {
        display(follower, likes, view);
      } while (u8g2.nextPage());
      flag = false;
    } else if (count == 1) {
      // get follower
      Serial.println("count = 1, get follower");
      getFollower(followerUrl);
      flag = false;
    } else if (count == 2) {
      // get view and likes
      Serial.println("count = 2, get view and likes");
      getViewAndLikes(viewAndLikesUrl);
      flag = false;
    }
  }
}


void timerCallback()
{
  count++;
  if (count == 3)
  {
    count = 0;
  }
  flag = true;
}

我们使用了 ESP32 和 ESP8266 自带的定时器库 Ticker。设置一个 count 变量,根据 count = 0、1、2 分别做不同的工作:显示屏刷新数据、读取粉丝数、读取播放数和获赞数。用 flag 变量去标记是否执行相应的功能。这两个参数在定时器回调函数 timerCallback() 每隔 10 分钟就会改变一次,然后就会在 loop() 中触发相应的功能。

至此,B站粉丝计数器就制作完成了,最终效果,大家可以在文章开头看一看。

# 附:掌控板图形程序

# 代码下载

关注本公众号“铁熊玩创客”,回复“B站”获取完整代码,三连支持一下喽。


# 相关推荐

## 51maker 微信公众号

51maker 是由一群教师团队维护的微信公众号,他们来自全国五湖四海,致力于 Scratch 编程及创客入门课程开发,为一线教师提供微视频、课件、教学设计等相关资源,为普及编程 & 创客教育尽一份力量。

## 知识星球能量站

激活课程制作分享,实现知识变现!能量站是一个付费知识社群,聚集了一大批优秀的老师,几乎每天都有优质的创客教育内容分享。可以扫描下方二维码付费加入,这是我的推荐码,你可以获得一定的优惠,当然我也会有一定的回报。


*欢迎转发朋友圈。如需转载,请注明出处和原作者。

扫描二维码

关注铁熊吧

往期精彩内容

创客项目缺少高颜值电路图?看这里就对了

小白也能学会的激光切割创意盒子设计方法

还在羡慕大疆 S1?教你自制麦轮战车

萌宠Pando机器人,不但能卖萌,还能跳太空步

学生获奖作品:戒烟帽

学生获奖作品:体感转向安全帽

掌控+Mixly+Blynk,让你的麦轮战甲嗨炸全场

搞定掌控板Siri语音控制,只要半小时

我知道你在看

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ironpandaaa/article/details/118081090

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签