jiugg 发表于 2024-4-24 21:44

B站新增关注查询脚本

本帖最后由 jiugg 于 2024-4-24 21:47 编辑

以前开发的脚本
可以生成趋势表
开源供大家参考
注意:频繁过快查询可能导致ip封禁
import http.cookiejar
import math
import time
from tkinter import Button, Radiobutton, Entry, StringVar, Tk, IntVar, Checkbutton, messagebox
import matplotlib.pyplot as plt
import requests

session1 = requests.session()
session1.cookies = http.cookiejar.LWPCookieJar(filename = './config/bzcookie-lxswtt.txt')# 需要加载有效的cookie信息文件,自行研究。
session1.cookies.load(ignore_discard = True)
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                  'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 '
                  'Edg/116.0.1938.69', 'Referer': "https://www.bilibili.com/"
}


def len_str(string):
    count = 0
    for ch in string:
      if ch >= '\u007f':
            count += 1
    return count


def get_follow_info(uid, page):# 获取最新关注用户UID,uid为目标up主的uid,page为查询页码,最大20页,一页50个,因此最多可查最新关注的1000粉丝
    now_time = time.time()
    sub_dic = {}
    sub_list = []
    mid_list = []
    for i in range(1, page):
      url = f'https://api.bilibili.com/x/relation/followers?vmid={uid}&pn={i}'# 拼接url,循环查询目标页数的所有粉丝信息
      resp2 = session1.get(url = url, headers = headers).json()
      if not len(resp2['data']['list']):
            print('粉丝数为0')
            return 0
      if resp2['code'] == 22118:
            print('由于该用户隐私设置,粉丝列表不可见')
            return 0
      sub_list += ['list']]# 将粉丝信息添加到一个列表中
      time.sleep(0.1)
      print(f'{i}/{page - 1}')
      root.update()
    for lists in sub_list:# 从粉丝信息列表提取出有用信息,生成uid列表和关键信息字典
      if (now_time - int(lists['mtime'])) > 24 * 3600 and c2.get():# 实现查询最新24h的粉丝关注情况功能,想要修改时间可以修改数字大小
            break
      mid = lists['mid']
      mid_list.append(str(mid))
      sub_dic = {
            'uname': lists['uname'], 'sub_time': time.strftime('%Y-%m-%d %X', time.localtime(lists['mtime'])), 'mtime': lists['mtime'], 'uid': mid,
            'vip': lists['vip']['vipType']
      }# 保存关键信息,用户昵称,关注时间,uid,会员状态
    with open('mid.txt', 'w', encoding = 'utf-8') as f:# 保存uid列表
      f.write(str(mid_list))
    get_follow_level(mid_list, sub_dic)# 根据uid列表获取每个用户的等级
    sort(mid_list, sub_dic)# 对数据进行统计
    # 绘制涨粉趋势图
    init = sub_dic]['mtime']
    x_key = []
    y_value = []
    num = 1
    mid_list.reverse()
    for mid in mid_list:
      int1 = int(sub_dic['mtime']) - init
      x_key.append(int1 / 3600)
      y_value.append(num)
      num += 1
    x_key = for i in x_key]
    plt.plot(x_key, y_value)
    plt.show()


def get_follow_level(uid_all, all_dic):# 实现获取用户等级功能
    vips = 0
    num = 0
    c = len(uid_all) // 50
    uid_lists = for i in range(len(uid_all) // 50)]# 将uid列表分割为50一组
    if len(uid_all) % 50 != 0:
      uid_lists.append(uid_all)
    for uid in uid_lists:
      strs = ','.join(uid)# 将50一组的uid列表用‘,’合并成一条字符串
      url = f'https://api.vc.bilibili.com/account/v1/user/cards?uids={strs}'# 该api可以批量查询B站用户信息,最大50个,需要用','分割
      dic_temp = requests.get(url = url, headers = headers).json()
      for j in range(len(dic_temp['data'])):
            mid = dic_temp['data']['mid']
            if dic_temp['data']['name'] != '账号已注销':
                all_dic['level'] = dic_temp['data']['level']# 获取用户等级
      for k in range(len(dic_temp['data'])):# 将用户信息打印到控制台中
            num += 1
            width = 36 - len_str(all_dic]['uname'])
            if all_dic]['uname'] != '账号已注销':
                print(
                  f"{num:<4}:{all_dic]['uname']:^{width}}Lv:{all_dic]['level']:<10}{all_dic]['sub_time']:<20}{all_dic]['vip']}")
                if all_dic]['vip']:
                  vips += 1
            else:
                print(f"\033]['uid']:^36}账号已注销!\033[0m")
            time.sleep(0.06)# 设置延时,防止查询过快触发B站风控,尽量不要更改此参数
            root.update()
    with open('sub_dic.txt', 'w', encoding = 'utf-8') as f:# 保存用户信息
      f.write(str(all_dic))
    print(f'有大会员记录的粉丝个数为:{vips}')# 打印开过大会员的粉丝用户个数


def sort(uid_all, all_dic):# 对用户信息进行统计
    sums = {6: 0, 5: 0, 4: 0, 3: 0, 2: 0, 1: 0, 0: 0}
    sum_per = {}
    new_sum = {}
    for uid in uid_all:
      if all_dic['uname'] != '账号已注销':
            key = all_dic['level']
            sums = sums.get(key, 0) + 1
    for key in sums.keys():
      new_sum = sums
      sum_per = round(sums / len(uid_all), 4)
    new_sum['sum'] = len(uid_all)
    keys = list(new_sum.keys())
    print('\033[31m{:=^86}\033[0m'.format("等级统计"))
    print('{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}{:^11}'.format(keys, keys, keys, keys, keys, keys, keys, keys))
    print('\033, sums, sums, sums, sums, sums, sums,
                                                                                 new_sum['sum']))
    print('\033, sum_per, sum_per, sum_per,
                                                                                                sum_per, sum_per, sum_per))


def start():# 开始函数
    if v1.get():# v1为查询粉丝数个数,最大值为1000,
      page = math.ceil(int(v1.get()) / 50) + 1# 将粉丝个数转化成页数
      if page > 21:
            page = 21
    else:
      page = 21
      c2.set(1)# 如果粉丝数输入框为空,则默认查询20页粉丝信息,同时自动勾选24h内的粉丝数
    if c1.get():# c1为单选框变量值,如选择任意,则为0,即查询uid输入框的粉丝信息
      get_follow_info(c1.get(), page)# 查询单选框目标的粉丝信息
    elif v2.get():
      get_follow_info(int(v2.get()), page)# 如果UID输入框不为空,则查询输入框的UID目标的粉丝信息
    else:
      messagebox.showinfo(title = '提示', message = '请输入UID或勾选某个目标')
      return 0


if __name__ == '__main__':
    receiver = [{'name': '恬豆', 'uid': 1660392980}, {'name': '梨安', 'uid': 1900141897}, {'name': '又一', 'uid': 1217754423},
                {'name': '沐霂', 'uid': 1878154667}, {'name': '星瞳', 'uid': 401315430}, {'name': '露早', 'uid': 1669777785},
                {'name': '米诺', 'uid': 1778026586}, {'name': '柚恩', 'uid': 1795147802}, {'name': '莞儿', 'uid': 1875044092},
                {'name': '虞莫', 'uid': 1811071010}, {'name': '思诺', 'uid': 3537115310721781}, {'name': '心宜', 'uid': 3537115310721181},
                {'name': '嘉然', 'uid': 672328094}, {'name': 'asaki', 'uid': 194484313}, {'name': '任意', 'uid': 0}, ]# 初始设置15个选项,可自行更改里面的数据,需注意UID对应关系
    root = Tk()
    root.geometry('360x140')
    root.title("新关注查询")
    c1, c2, v1, v2 = IntVar(), IntVar(), StringVar(), StringVar()
    Entry(root, textvariable = v1, width = 10).grid(row = 2, column = 4, rowspan = 1, columnspan = 1)# 创建查询粉丝个数输入框,最大值1000
    Entry(root, textvariable = v2, width = 50).grid(row = 1, column = 1, rowspan = 1, columnspan = 5)# 创建UID输入框
    for j in range(3):
      for i in range(5):
            rbtn = Radiobutton(root, text = receiver['name'], value = receiver['uid'], variable = c1)
            rbtn.grid(row = 3 + j, column = 1 + i, rowspan = 1, columnspan = 1, sticky = 'S')
    Button(root, height = 1, width = 30, text = '查询', command = start).grid(row = 2, column = 1, rowspan = 1, columnspan = 3)# 按照目标列表创建单选框组件
    Checkbutton(root, text = "24h内", variable = c2, onvalue = 1, offvalue = 0).grid(row = 2, column = 5, sticky = "S")# 创建查询24h新关注的复选框
    root.mainloop()

jiugg 发表于 2024-4-25 21:23

wxl949389 发表于 2024-4-25 10:26可否附一张效果图
效果图:

adm471808 发表于 2024-4-24 23:45

学习学习

fWiZsHh 发表于 2024-4-25 00:15

嘶——,膜拜大佬

xixicoco 发表于 2024-4-25 00:33

脚本写的不错,膜拜

cokeseyo 发表于 2024-4-25 08:51

学习,膜拜大佬

wxl949389 发表于 2024-4-25 10:26

可否附一张效果图{:1_893:}

xjls 发表于 2024-4-25 18:55

厉害,我都不懂这是啥

xuexiaogangi 发表于 2024-4-25 20:38

大神就是大神,我只能看看

eenny820 发表于 2024-4-27 13:01

嘶——,膜拜大佬
页: [1]
查看完整版本: B站新增关注查询脚本