前言

更新日志

2022-5-28 由于发现b站api变更,更新新版本v3.6进行适配
2022-8-1 更新兼容视频动态版本v3.7
2022-9-20 基于ttk库优化UI,发布版本v3.8

简述

记 b站动态评论+视频评论区 抽奖2合1 JS版本发布后,计划了这次的python版本,本来的预期是实现同功能的python版并挂我服务器上免费提供抽奖服务来着。不过写着写着突然发现了之前对API的解析有所漏洞,导致我发现了一个新bug。。。(居然没人提醒我)

旧程序将全部的自发型动态归为type=11,今天测试时发现居然还有type=17和1的情况

于是乎 我就把原来的JS版的也改了,顺便把python的动态评论区抽奖给写了。动态转发也根据Hack Inn大佬之前提供的源码,进行了python3版本的简单适配,因为我懒了0.0
python版本:3.8.5
工程构建:pycharm

代码/exe下载

代码下载:GitHub 码云
exe程序下载:GitHub 码云(温馨提示:请勿随意执行来历不明的程序)

效果图

GUI版-v3.8

GUI版-v3.7

cmd版本

【b站抽奖】Python实现 动态转发、动态评论抽奖,实际程序演示+粗略讲解

使用说明

GUI版本使用方法类似

1、双击运行bat文件

2、输入抽奖类型(数字) 然后“回车”

(1评论 0转发)

3、粘贴入 动态页面的链接 然后“回车”

因为动态又改版了,?后面的东西都不要复制了
注意,链接后的 ?tab=2 也需要复制过来,因为做了动态类型的识别,这也做为关键参数需要检测。

4、输入中奖人数(要是数字) 然后“回车”

因为我没做校验(懒)
直接就运行完成了。会爬取所有评论人的数据到数据库(自动去重)
数据库文件在同一文件夹下“user_data.db
然后会直接抽取中奖用户并打印,复制中奖信息即可。
最后输入数字1,退出程序。

所有评论人员数据查看

评论人员数据存储于同一文件夹的“user_data.db”中

sqlite数据库,我使用 sqlitebrowser打开这个db文件
可以看到我们的user表

点击“浏览数据”,选择我们要查看的user表,即可看到所有用户数据

当然你也可以用网上的 随机数程序生成随机数,然后进行抽奖,问题不大0.0

源码

GUI版本-v3.8

# -*- coding: utf-8 -*-
import json
import time
import random
import urllib.request
import urllib.parse
import sqlite3
import tkinter
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.dialogs import Messagebox
from ttkbootstrap.scrolled import ScrolledText# python版本:3.8.12
# 打包 pyinstaller -F 1.py# 获取抽奖类型
global draw_type
global referer
# 中奖人数
global lucky_num
global dynamic_id
global text_str
# 动态类型
global api_typeapi_type = 11
draw_type = 1
dynamic_id = ""
# 打印文本框
text_str = ''# 数据集合
id_set = set()
name_set = set()
lucky_set = set()headers1 = {'Accept': 'application/json, text/plain, */*','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9','Connection': 'keep-alive','Content-Type': 'text/plain;charset=UTF-8','Referer': 'https://t.bilibili.com','origin': 'https://t.bilibili.com',# 'cookie': 'l=v','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 ''Safari/537.36 Core/1.70.3875.400 QQBrowser/10.8.4492.400 '
}# 字符串是否是数字
def is_number(s):try:float(s)return Trueexcept ValueError:passtry:import unicodedataunicodedata.numeric(s)return Trueexcept (TypeError, ValueError):passreturn False# 配置数据库
def config_db():global con, curglobal text_str# print("开始创建数据库...")text_str = "开始创建数据库...\n"text.insert(END, text_str)text.update()con = sqlite3.connect("user_data.db")cur = con.cursor()# 创建表usersql = "CREATE TABLE IF NOT EXISTS user(mid TEXT PRIMARY KEY,uname TEXT,message TEXT)"cur.execute(sql)# 情况表数据sql = "delete from user"cur.execute(sql)# 获取oid、转发数、评论数函数
def get_oid():global text_strglobal dynamic_idglobal api_typeglobal textif referer[8] == 't':# print('解析为动态页面')text_str = "解析为动态页面\n"text.insert(END, text_str)text.update()else:# print('解析为视频页面')text_str = "解析为视频页面\n"text.insert(END, text_str)text.update()tab_type = "2"# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2# if referer[-6:-1] == "?tab=":#     dynamic_id = referer[23:len(referer) - 6]#     tab_type = referer[-1]# else:#     dynamic_id = referer[23:len(referer)]temp = referer.split('?')temp2 = temp[0].split('/')dynamic_id = temp2[3]# print("dynamic_id=" + dynamic_id)text_str = "dynamic_id=" + dynamic_id + "\n"text.insert(END, text_str)text.update()if len(dynamic_id) == 0:# print("dynamic_id异常,程序终止,请检查您的输入是否有误!")text_str = "dynamic_id异常,程序终止,请检查您的输入是否有误!\n"text.insert(END, text_str)text.update()base_info = {'ret': False}return base_info# payload = {'dynamic_id': dynamic_id}payload = {'timezone_offset': '-480', 'id': dynamic_id}data = urllib.parse.urlencode(payload)# print(data)req = urllib.request.urlopen('https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?%s' % data)# req = urllib.request.urlopen('https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?%s' % data)ret = req.read().decode()# print(ret)json1 = json.loads(ret)oid = json1["data"]["item"]["basic"]["comment_id_str"]repost = json1["data"]["item"]["modules"]["module_stat"]["forward"]["count"]# oid = json1["data"]["card"]["desc"]["rid"]# repost = json1["data"]["card"]["desc"]["repost"]comment = 0# 非视频动态if tab_type == "2":comment = json1["data"]["item"]["modules"]["module_stat"]["comment"]["count"]else:comment = 0# 判断动态类型api_type = json1["data"]["item"]["basic"]["comment_type"]# print("oid=" + str(oid))base_info = {'ret': True, 'oid': oid, 'repost': repost, 'comment': comment}# print(base_info)return base_info# 获取用户信息函数
def get_user_info(base_info):global text_strglobal api_typeglobal text# print("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(END, text_str)text.update()if int(api_type) == 17:# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":base_info["oid"] = referer[23:len(referer) - 6]else:base_info["oid"] = referer[23:len(referer)]end = 0for i in range(int((base_info["comment"] - 1) / 20) + 1):if i == 0:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=0&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))else:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=" + str(i + 1) + "&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))if i == int((base_info["comment"] - 1) / 20):end = 1get_data(url, end)time.sleep(0.5)# 获取数据函数
def get_data(url, end):print(url)global text_strglobal textreq = urllib.request.urlopen(url)ret = req.read().decode()# print(ret)json1 = json.loads(ret)# json1["data"]["replies"]有可能为nullif json1["data"]["replies"] is not None:len1 = len(json1["data"]["replies"])for i in range(len1):mid = json1["data"]["replies"][i]["member"]["mid"]uname = json1["data"]["replies"][i]["member"]["uname"]message = json1["data"]["replies"][i]["content"]["message"]# 数据插入集合# name_set.add(uname)id_set.add(mid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (mid, uname, message))con.commit()# print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(END, text_str)text.update()# print("插入一组数据组")if end == 1:# print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(END, text_str)text.update()# print(name_set)# print(id_set)while len(lucky_set) < int(lucky_num):num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)# print(lucky_set)# id_list = list(id_set)# name_list = list(name_set)# for i in range(int(lucky_num)):#     print("昵称:" + name_list[i] + "  id:" + id_list[i] + "\n")for i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:# print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(END, text_str)text.update()text_str = '\n\n'text.insert(END, text_str)text.update()# 获取转发用户的数据
def get_repost_user_info(base_info):global text_strglobal dynamic_idglobal textprint("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(END, text_str)text.update()# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2# if referer[-6:-1] == "?tab=":#     dynamic_id = referer[23:len(referer) - 6]# else:#     dynamic_id = referer[23:len(referer)]temp = referer.split('?')temp2 = temp[0].split('/')dynamic_id = temp2[3]temp_num = 0# 根据转发数进行循环while temp_num < int(base_info["repost"]):url = "https://api.live.bilibili.com/dynamic_repost/v1/dynamic_repost/view_repost?dynamic_id=" + \str(dynamic_id) + "&offset=" + str(temp_num)req = urllib.request.urlopen(url)ret = req.read().decode()# print(url)# print(ret)json1 = json.loads(ret)len1 = 0if "comments" in ret:len1 = len(json1["data"]["comments"])# print(len1)else:print("可获取的数据结束!\n")text_str = "可获取的数据结束!\n"text.insert(END, text_str)text.update()breakfor i in range(len1):uid = json1["data"]["comments"][i]["uid"]uname = json1["data"]["comments"][i]["uname"]comment = json1["data"]["comments"][i]["comment"]# 数据插入集合# name_set.add(uname)id_set.add(uid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (uid, uname, comment))con.commit()temp_num += 20# print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(END, text_str)text.update()time.sleep(0.5)print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(END, text_str)text.update()while len(lucky_set) < int(lucky_num):num = 0if len(id_set) > 1:num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)else:print('用户数据不足2个,数据异常,程序结束')text_str = "用户数据不足2个,数据异常,程序结束\n"text.insert(END, text_str)text.update()returnfor i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(END, text_str)text.update()text_str = '\n\n'text.insert(END, text_str)text.update()# 单选框点击
def radio_click():global draw_typedraw_type = radio.get()# print("draw_type:" + str(draw_type))# 开始抽奖按钮点击
def start_btn():global refererglobal lucky_numglobal text_strglobal textid_set.clear()name_set.clear()lucky_set.clear()referer = StringVar1.get()if len(StringVar2.get()) != 0:lucky_num = int(StringVar2.get())# print('referer:' + referer)# print('lucky_num:' + str(lucky_num))if not referer.startswith('https://t.bilibili.com'):# print("动态链接地址不正确,请重新输入")text_str = "动态链接地址不正确,请重新输入!!!\n"text.insert(END, text_str)text.update()returnif not is_number(lucky_num):# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(END, text_str)text.update()returnif int(float(lucky_num)) <= 0:# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(END, text_str)text.update()return# 配置数据库config_db()# 获取oid、转发数、评论数base_info = get_oid()if base_info["ret"]:# print("oid=" + str(base_info["oid"]))# print("转发数=" + str(base_info["repost"]))# print("评论数=" + str(base_info["comment"]))text_str = "oid=" + str(base_info["oid"]) + "\n"text_str = text_str + "转发数=" + str(base_info["repost"]) + "\n"text_str = text_str + "评论数=" + str(base_info["comment"]) + "\n"text.insert(END, text_str)text.update()# 根据抽奖类型进行抽奖 1评论 0转发if int(draw_type) == 1:if int(lucky_num) > int(base_info["comment"]):text_str = "请输入正确的中奖人数!!!\n"text.insert(END, text_str)text.update()# 关闭游标cur.close()# 断开数据库连接con.close()return# 获取用户信息并抽取幸运用户get_user_info(base_info)else:if int(lucky_num) > int(base_info["repost"]):text_str = "请输入正确的中奖人数!!!\n"text.insert(END, text_str)text.update()# 关闭游标cur.close()# 断开数据库连接con.close()returnget_repost_user_info(base_info)# 关闭游标cur.close()# 断开数据库连接con.close()app = ttk.Window(title='b站动态抽奖程序', themename='litera', iconphoto='', size=[700, 600], position=None, minsize=None)
root = ttk.Frame(app, padding=10)
style = ttk.Style()tframe = ttk.Frame(root)
tframe.pack(padx=3, fill=X, side=TOP)bframe = ttk.Frame(root)
bframe.pack(padx=7, fill=BOTH, side=BOTTOM)lframe = ttk.Frame(tframe)
lframe.pack(padx=8, side=LEFT, fill=BOTH, expand=YES)rframe = ttk.Frame(tframe, padding=5)
rframe.pack(padx=2, side=RIGHT, fill=BOTH, expand=YES)btframe = ttk.Frame(root)
btframe.pack(fill=BOTH, side=TOP)text = ScrolledText(master=btframe, height=100, width=50, autohide=True, padding=10)
text.pack(side=LEFT, anchor=NW, pady=5, fill=BOTH, expand=YES)input_group = ttk.Labelframe(master=lframe, text="配置输入", padding=10
)
input_group.pack(fill=BOTH, expand=YES)l1 = ttk.Label(input_group, text="动态链接:")
l1.grid(row=0, column=0)load = tkinter.StringVar()StringVar1 = ttk.StringVar()
StringVar1.set("")
entry = ttk.Entry(input_group, width=50, textvariable=StringVar1)
entry.grid(row=0, column=1, padx='4px', pady='5px')
entry.insert(END, "例如:https://t.bilibili.com/123456789012345678")l2 = ttk.Label(input_group, text="中奖人数:")
l2.grid(row=1, column=0)StringVar2 = ttk.StringVar()
StringVar2.set("")
spinbox = ttk.Spinbox(master=input_group, from_=1, to=500, textvariable=StringVar2)
spinbox.grid(row=1, column=1, sticky='w', padx='4px', pady='5px')
spinbox.set(1)rb_group = ttk.Labelframe(rframe, text="抽奖类型", padding=10
)
rb_group.pack(fill=X, pady=10, side=TOP)radio = ttk.IntVar()
radio1 = ttk.Radiobutton(rb_group, text="评论", value=1, variable=radio, command=radio_click)
radio1.pack(side=LEFT, expand=YES, padx=5)
radio1.invoke()radio2 = ttk.Radiobutton(rb_group, text="转发", value=0, variable=radio, command=radio_click)
radio2.pack(side=LEFT, expand=YES, padx=5)cb = ttk.Button(master=rframe,text="开始抽奖",bootstyle=(SUCCESS, TOOLBUTTON),command=start_btn
)
# 调用与按钮关联的命令
# cb.invoke()
cb.pack(fill=X, pady=5)lframe_inner = ttk.Frame(lframe)
lframe_inner.pack(fill=BOTH, expand=YES, padx=10)root.pack(fill=BOTH, expand=YES)
app.mainloop()

GUI版本-v3.7

# -*- coding: utf-8 -*-
import json
import time
import random
import urllib.request
import urllib.parse
import sqlite3
import tkinter
from tkinter import END, messagebox# python版本:3.8.12
# 打包 pyinstaller -F 1.py# 获取抽奖类型
global draw_type
global referer
# 中奖人数
global lucky_num
global dynamic_id
global text_str
# 动态类型
global api_typeapi_type = 11
draw_type = 1
dynamic_id = ""
# 打印文本框
text_str = ''# 数据集合
id_set = set()
name_set = set()
lucky_set = set()headers1 = {'Accept': 'application/json, text/plain, */*','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9','Connection': 'keep-alive','Content-Type': 'text/plain;charset=UTF-8','Referer': 'https://t.bilibili.com','origin': 'https://t.bilibili.com',# 'cookie': 'l=v','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3875.400 QQBrowser/10.8.4492.400'
}# 字符串是否是数字
def is_number(s):try:float(s)return Trueexcept ValueError:passtry:import unicodedataunicodedata.numeric(s)return Trueexcept (TypeError, ValueError):passreturn False# 配置数据库
def config_db():global con, curglobal text_str# print("开始创建数据库...")text_str = "开始创建数据库...\n"text.insert(tkinter.INSERT, text_str)text.update()con = sqlite3.connect("user_data.db")cur = con.cursor()# 创建表usersql = "CREATE TABLE IF NOT EXISTS user(mid TEXT PRIMARY KEY,uname TEXT,message TEXT)"cur.execute(sql)# 情况表数据sql = "delete from user"cur.execute(sql)# 获取oid、转发数、评论数函数
def get_oid():global text_strglobal dynamic_idglobal api_typeif referer[8] == 't':# print('解析为动态页面')text_str = "解析为动态页面\n"text.insert(tkinter.INSERT, text_str)text.update()else:# print('解析为视频页面')text_str = "解析为视频页面\n"text.insert(tkinter.INSERT, text_str)text.update()tab_type = "2"# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2# if referer[-6:-1] == "?tab=":#     dynamic_id = referer[23:len(referer) - 6]#     tab_type = referer[-1]# else:#     dynamic_id = referer[23:len(referer)]temp = referer.split('?')temp2 = temp[0].split('/')dynamic_id = temp2[3]# print("dynamic_id=" + dynamic_id)text_str = "dynamic_id=" + dynamic_id + "\n"text.insert(tkinter.INSERT, text_str)text.update()if len(dynamic_id) == 0:# print("dynamic_id异常,程序终止,请检查您的输入是否有误!")text_str = "dynamic_id异常,程序终止,请检查您的输入是否有误!\n"text.insert(tkinter.INSERT, text_str)text.update()base_info = {'ret': False}return base_info# payload = {'dynamic_id': dynamic_id}payload = { 'timezone_offset': '-480', 'id': dynamic_id}data = urllib.parse.urlencode(payload)# print(data)req = urllib.request.urlopen('https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?%s' % data)# req = urllib.request.urlopen('https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?%s' % data)ret = req.read().decode()# print(ret)json1 = json.loads(ret)oid = json1["data"]["item"]["basic"]["comment_id_str"]repost = json1["data"]["item"]["modules"]["module_stat"]["forward"]["count"]# oid = json1["data"]["card"]["desc"]["rid"]# repost = json1["data"]["card"]["desc"]["repost"]comment = 0# 非视频动态if tab_type == "2":comment = json1["data"]["item"]["modules"]["module_stat"]["comment"]["count"]else:comment = 0# 判断动态类型api_type = json1["data"]["item"]["basic"]["comment_type"]# print("oid=" + str(oid))base_info = {'ret': True, 'oid': oid, 'repost': repost, 'comment': comment}# print(base_info)return base_info# 获取用户信息函数
def get_user_info(base_info):global text_strglobal api_type# print("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(tkinter.INSERT, text_str)text.update()if int(api_type) == 17:# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":base_info["oid"] = referer[23:len(referer) - 6]else:base_info["oid"] = referer[23:len(referer)]end = 0for i in range(int((base_info["comment"] - 1) / 20) + 1):if i == 0:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=0&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))else:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=" + str(i + 1) + "&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))if i == int((base_info["comment"] - 1) / 20):end = 1get_data(url, end)time.sleep(0.5)# 获取数据函数
def get_data(url, end):print(url)global text_strreq = urllib.request.urlopen(url)ret = req.read().decode()# print(ret)json1 = json.loads(ret)# json1["data"]["replies"]有可能为nullif json1["data"]["replies"] is not None:len1 = len(json1["data"]["replies"])for i in range(len1):mid = json1["data"]["replies"][i]["member"]["mid"]uname = json1["data"]["replies"][i]["member"]["uname"]message = json1["data"]["replies"][i]["content"]["message"]# 数据插入集合# name_set.add(uname)id_set.add(mid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (mid, uname, message))con.commit()# print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(tkinter.INSERT, text_str)text.update()# print("插入一组数据组")if end == 1:# print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(tkinter.INSERT, text_str)text.update()# print(name_set)# print(id_set)while len(lucky_set) < int(lucky_num):num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)# print(lucky_set)# id_list = list(id_set)# name_list = list(name_set)# for i in range(int(lucky_num)):#     print("昵称:" + name_list[i] + "  id:" + id_list[i] + "\n")for i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:# print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(tkinter.INSERT, text_str)text.update()text_str = '\n\n'text.insert(tkinter.INSERT, text_str)text.update()# 获取转发用户的数据
def get_repost_user_info(base_info):global text_strglobal dynamic_idprint("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(tkinter.INSERT, text_str)text.update()# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2# if referer[-6:-1] == "?tab=":#     dynamic_id = referer[23:len(referer) - 6]# else:#     dynamic_id = referer[23:len(referer)]temp = referer.split('?')temp2 = temp[0].split('/')dynamic_id = temp2[3]temp_num = 0# 根据转发数进行循环while temp_num < int(base_info["repost"]):url = "https://api.live.bilibili.com/dynamic_repost/v1/dynamic_repost/view_repost?dynamic_id=" + \str(dynamic_id) + "&offset=" + str(temp_num)req = urllib.request.urlopen(url)ret = req.read().decode()# print(url)# print(ret)json1 = json.loads(ret)len1 = 0if "comments" in ret:len1 = len(json1["data"]["comments"])# print(len1)else:print("可获取的数据结束!\n")text_str = "可获取的数据结束!\n"text.insert(tkinter.INSERT, text_str)text.update()breakfor i in range(len1):uid = json1["data"]["comments"][i]["uid"]uname = json1["data"]["comments"][i]["uname"]comment = json1["data"]["comments"][i]["comment"]# 数据插入集合# name_set.add(uname)id_set.add(uid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (uid, uname, comment))con.commit()temp_num += 20# print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(tkinter.INSERT, text_str)text.update()time.sleep(0.5)print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(tkinter.INSERT, text_str)text.update()while len(lucky_set) < int(lucky_num):num = 0if len(id_set) > 1:num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)else:print('用户数据不足2个,数据异常,程序结束')text_str = "用户数据不足2个,数据异常,程序结束\n"text.insert(tkinter.INSERT, text_str)text.update()returnfor i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(tkinter.INSERT, text_str)text.update()text_str = '\n\n'text.insert(tkinter.INSERT, text_str)text.update()# 关于弹窗提示
def about():# 弹出对话框messagebox.showinfo(title='关于', message='欢迎使用 UP:Love丶伊卡洛斯 开发的b站抽奖程序 本程序开源免费\n''请勿使用非本人仓库下载的程序,否则无法保证安全,未知程序谨慎使用\n''本程序目前只支持动态转发、评论的抽奖,视频评论区抽奖有待开发。。。\n''使用注意:因为涉及本地文件的操作,如果失败,则需要\"超级管理员\"权限运行\n''温馨提示:如果以下内容输错,请重新运行程序,异常数据处理懒得做了0.0')# 单选框点击
def radio_click():global draw_typedraw_type = radio.get()# print("draw_type:" + str(draw_type))# 开始抽奖按钮点击
def start_btn():global refererglobal lucky_numglobal text_strid_set.clear()name_set.clear()lucky_set.clear()referer = StringVar1.get()if len(StringVar2.get()) != 0:lucky_num = int(StringVar2.get())# print('referer:' + referer)# print('lucky_num:' + str(lucky_num))if not referer.startswith('https://t.bilibili.com'):# print("动态链接地址不正确,请重新输入")text_str = "动态链接地址不正确,请重新输入!!!\n"text.insert(tkinter.INSERT, text_str)text.update()returnif not is_number(lucky_num):# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(tkinter.INSERT, text_str)text.update()returnif int(float(lucky_num)) <= 0:# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(tkinter.INSERT, text_str)text.update()return# 配置数据库config_db()# 获取oid、转发数、评论数base_info = get_oid()if base_info["ret"]:# print("oid=" + str(base_info["oid"]))# print("转发数=" + str(base_info["repost"]))# print("评论数=" + str(base_info["comment"]))text_str = "oid=" + str(base_info["oid"]) + "\n"text_str = text_str + "转发数=" + str(base_info["repost"]) + "\n"text_str = text_str + "评论数=" + str(base_info["comment"]) + "\n"text.insert(tkinter.INSERT, text_str)text.update()# 根据抽奖类型进行抽奖 1评论 0转发if int(draw_type) == 1:# 获取用户信息并抽取幸运用户get_user_info(base_info)else:get_repost_user_info(base_info)# 关闭游标cur.close()# 断开数据库连接con.close()# 清空输入框按钮点击
def clear_in():e2.delete(0, END)e3.delete(0, END)# 清空输出框按钮点击
def clear_out():text.delete(0.0, tkinter.END)window = tkinter.Tk()
window.title("b站动态抽奖程序")
window.geometry("1000x900+200+100")
# 菜单栏
menu = tkinter.Menu(window)
# Open放在菜单栏中,就是装入容器
menu.add_command(label='关于', command=about)
# 创建菜单栏完成后,配置让菜单栏menu显示出来
window.config(menu=menu)# 创建一个主frame,长在主window窗口上
frame = tkinter.Frame(window)
frame.pack()# 创建第二层框架frame,长在主框架frame上面
# 上
frame_t = tkinter.Frame(frame)
# 下
frame_b = tkinter.Frame(frame)# frame_t.pack(side=tkinter.TOP)
# frame_b.pack(side=tkinter.BOTTOM)
frame_t.grid(row=0, column=0)
frame_b.grid(row=1, column=0)# 创建标签
l1 = tkinter.Label(frame_t, text='抽奖类型:', width=10, font=('microsoft yahei', 16))
l2 = tkinter.Label(frame_t, text='动态链接:', width=10, font=('microsoft yahei', 16))
l3 = tkinter.Label(frame_t, text='中奖人数:', width=10, font=('microsoft yahei', 16))radio = tkinter.IntVar()
radio.set(1)
radio1 = tkinter.Radiobutton(frame_t, text="评论", font=('microsoft yahei', 16), width=10, justify='left', value=1,variable=radio, command=radio_click, padx=1)
radio1.grid(row=0, column=1)
radio2 = tkinter.Radiobutton(frame_t, text="转发", font=('microsoft yahei', 16), width=10, justify='left', value=0,variable=radio, command=radio_click, padx=1)
radio2.grid(row=0, column=2)
button1 = tkinter.Button(frame_t, text="开始抽奖", command=start_btn, font=('microsoft yahei', 12), width=16, height=1)
button1.grid(row=0, column=3)StringVar1 = tkinter.StringVar()
StringVar1.set("")
e2 = tkinter.Entry(frame_t, show=None, width=42, textvariable=StringVar1, font=('microsoft yahei', 16))
StringVar2 = tkinter.StringVar()
StringVar2.set("1")
e3 = tkinter.Entry(frame_t, show=None, width=42, textvariable=StringVar2, font=('microsoft yahei', 16))button2 = tkinter.Button(frame_t, text="清空输入框", command=clear_in, font=('microsoft yahei', 12), width=16, height=1)
button2.grid(row=1, column=2)
button3 = tkinter.Button(frame_t, text="清空输出框", command=clear_out, font=('microsoft yahei', 12), width=16, height=1)
button3.grid(row=2, column=2)l1.grid(row=0, column=0)
l2.grid(row=1, column=0)
e2.grid(row=1, column=1)
l3.grid(row=2, column=0)
e3.grid(row=2, column=1)# 创建滚动条
scroll = tkinter.Scrollbar(frame_b)
text = tkinter.Text(frame_b, font=('microsoft yahei', 14), width=80, height=30)
# side放到窗体的那一侧
scroll.pack(side=tkinter.RIGHT, fill=tkinter.Y)
text.pack(side=tkinter.LEFT, fill=tkinter.Y)
# text.grid(row=3, column=0)
# scroll.grid(row=3, column=1)
# 关联
scroll.config(command=text.yview)
text.config(yscrollcommand=scroll.set)window.mainloop()

GUI版本旧版(已经不适配)

# -*- coding: utf-8 -*-
import json
import time
import random
import urllib.request
import urllib.parse
import sqlite3
import tkinter
from tkinter import END, messagebox# python版本:3.8.12
# 打包 pyinstaller -F 1.py# 获取抽奖类型
global draw_type
global referer
# 中奖人数
global lucky_num
global dynamic_id
global text_str
# 是否带图动态
global have_pichave_pic = 1
draw_type = 1
dynamic_id = ""
# 打印文本框
text_str = ''# 数据集合
id_set = set()
name_set = set()
lucky_set = set()headers1 = {'Accept': 'application/json, text/plain, */*','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9','Connection': 'keep-alive','Content-Type': 'text/plain;charset=UTF-8','Referer': 'https://t.bilibili.com','origin': 'https://t.bilibili.com',# 'cookie': 'l=v','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3875.400 QQBrowser/10.8.4492.400'
}# 字符串是否是数字
def is_number(s):try:float(s)return Trueexcept ValueError:passtry:import unicodedataunicodedata.numeric(s)return Trueexcept (TypeError, ValueError):passreturn False# 配置数据库
def config_db():global con, curglobal text_str# print("开始创建数据库...")text_str = "开始创建数据库...\n"text.insert(tkinter.INSERT, text_str)text.update()con = sqlite3.connect("user_data.db")cur = con.cursor()# 创建表usersql = "CREATE TABLE IF NOT EXISTS user(mid TEXT PRIMARY KEY,uname TEXT,message TEXT)"cur.execute(sql)# 情况表数据sql = "delete from user"cur.execute(sql)# 获取oid、转发数、评论数函数
def get_oid():global text_strglobal dynamic_idif referer[8] == 't':# print('解析为动态页面')text_str = "解析为动态页面\n"text.insert(tkinter.INSERT, text_str)text.update()else:# print('解析为视频页面')text_str = "解析为视频页面\n"text.insert(tkinter.INSERT, text_str)text.update()tab_type = "2"# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":dynamic_id = referer[23:len(referer) - 6]tab_type = referer[-1]else:dynamic_id = referer[23:len(referer)]# print("dynamic_id=" + dynamic_id)text_str = "dynamic_id=" + dynamic_id + "\n"text.insert(tkinter.INSERT, text_str)text.update()if len(dynamic_id) == 0:# print("dynamic_id异常,程序终止,请检查您的输入是否有误!")text_str = "dynamic_id异常,程序终止,请检查您的输入是否有误!\n"text.insert(tkinter.INSERT, text_str)text.update()base_info = {'ret': False}return base_infopayload = {'dynamic_id': dynamic_id}data = urllib.parse.urlencode(payload)req = urllib.request.urlopen('https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?%s' % data)ret = req.read().decode()# print(ret)json1 = json.loads(ret)oid = json1["data"]["card"]["desc"]["rid"]repost = json1["data"]["card"]["desc"]["repost"]comment = 0# 非视频动态if tab_type == "2":comment = json1["data"]["card"]["desc"]["comment"]else:comment = 0# 判断动态类型type = json1["data"]["card"]["desc"]["type"]global have_picif int(type) == 2:have_pic = 1else:have_pic = 0# print("oid=" + str(oid))base_info = {'ret': True, 'oid': oid, 'repost': repost, 'comment': comment}return base_info# 获取用户信息函数
def get_user_info(base_info):global text_str# print("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(tkinter.INSERT, text_str)text.update()if int(have_pic) == 1:api_type = 11else:api_type = 17# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":base_info["oid"] = referer[23:len(referer) - 6]else:base_info["oid"] = referer[23:len(referer)]end = 0for i in range(int((base_info["comment"] - 1) / 20) + 1):if i == 0:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=0&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))else:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=" + str(i + 1) + "&type=" + str(api_type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1))if i == int((base_info["comment"] - 1) / 20):end = 1get_data(url, end)time.sleep(0.5)# 获取数据函数
def get_data(url, end):global text_strreq = urllib.request.urlopen(url)ret = req.read().decode()# print(ret)json1 = json.loads(ret)# json1["data"]["replies"]有可能为nullif json1["data"]["replies"] is not None:len1 = len(json1["data"]["replies"])for i in range(len1):mid = json1["data"]["replies"][i]["member"]["mid"]uname = json1["data"]["replies"][i]["member"]["uname"]message = json1["data"]["replies"][i]["content"]["message"]# 数据插入集合# name_set.add(uname)id_set.add(mid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (mid, uname, message))con.commit()# print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(tkinter.INSERT, text_str)text.update()# print("插入一组数据组")if end == 1:# print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(tkinter.INSERT, text_str)text.update()# print(name_set)# print(id_set)while len(lucky_set) < int(lucky_num):num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)# print(lucky_set)# id_list = list(id_set)# name_list = list(name_set)# for i in range(int(lucky_num)):#     print("昵称:" + name_list[i] + "  id:" + id_list[i] + "\n")for i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:# print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(tkinter.INSERT, text_str)text.update()text_str = '\n\n'text.insert(tkinter.INSERT, text_str)text.update()# 获取转发用户的数据
def get_repost_user_info(base_info):global text_strglobal dynamic_idprint("开始获取用户信息...")text_str = "开始获取用户信息...\n"text.insert(tkinter.INSERT, text_str)text.update()# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":dynamic_id = referer[23:len(referer) - 6]else:dynamic_id = referer[23:len(referer)]temp_num = 0# 根据转发数进行循环while temp_num < int(base_info["repost"]):url = "https://api.live.bilibili.com/dynamic_repost/v1/dynamic_repost/view_repost?dynamic_id=" + \str(dynamic_id) + "&offset=" + str(temp_num)req = urllib.request.urlopen(url)ret = req.read().decode()# print(url)# print(ret)json1 = json.loads(ret)len1 = 0if "comments" in ret:len1 = len(json1["data"]["comments"])# print(len1)else:print("可获取的数据结束!\n")text_str = "可获取的数据结束!\n"text.insert(tkinter.INSERT, text_str)text.update()breakfor i in range(len1):uid = json1["data"]["comments"][i]["uid"]uname = json1["data"]["comments"][i]["uname"]comment = json1["data"]["comments"][i]["comment"]# 数据插入集合# name_set.add(uname)id_set.add(uid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (uid, uname, comment))con.commit()temp_num += 20print("已获取" + str(len(id_set)) + "个用户的数据...")text_str = "已获取" + str(len(id_set)) + "个用户的数据...\n"text.insert(tkinter.INSERT, text_str)text.update()time.sleep(0.5)print("数据获取完毕!\n")text_str = "数据获取完毕!\n"text.insert(tkinter.INSERT, text_str)text.update()while len(lucky_set) < int(lucky_num):num = 0if len(id_set) > 1:num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)else:print('用户数据不足2个,数据异常,程序结束')text_str = "用户数据不足2个,数据异常,程序结束\n"text.insert(tkinter.INSERT, text_str)text.update()returnfor i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))text_str = '\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]) + '\n'text.insert(tkinter.INSERT, text_str)text.update()text_str = '\n\n'text.insert(tkinter.INSERT, text_str)text.update()# 关于弹窗提示
def about():# 弹出对话框messagebox.showinfo(title='关于', message='欢迎使用 UP:Love丶伊卡洛斯 开发的b站抽奖程序 本程序开源免费\n''请勿使用非本人仓库下载的程序,否则无法保证安全,未知程序谨慎使用\n''本程序目前只支持动态转发、评论的抽奖,视频评论区抽奖有待开发。。。\n''使用注意:因为涉及本地文件的操作,如果失败,则需要\"超级管理员\"权限运行\n''温馨提示:如果以下内容输错,请重新运行程序,异常数据处理懒得做了0.0')# 单选框点击
def radio_click():global draw_typedraw_type = radio.get()# print("draw_type:" + str(draw_type))# 开始抽奖按钮点击
def start_btn():global refererglobal lucky_numglobal text_strid_set.clear()name_set.clear()lucky_set.clear()referer = StringVar1.get()if len(StringVar2.get()) != 0:lucky_num = int(StringVar2.get())# print('referer:' + referer)# print('lucky_num:' + str(lucky_num))if not referer.startswith('https://t.bilibili.com'):# print("动态链接地址不正确,请重新输入")text_str = "动态链接地址不正确,请重新输入!!!\n"text.insert(tkinter.INSERT, text_str)text.update()returnif not is_number(lucky_num):# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(tkinter.INSERT, text_str)text.update()returnif int(float(lucky_num)) <= 0:# print("请输入正确的中奖人数")text_str = "请输入正确的中奖人数!!!\n"text.insert(tkinter.INSERT, text_str)text.update()return# 配置数据库config_db()# 获取oid、转发数、评论数base_info = get_oid()if base_info["ret"]:# print("oid=" + str(base_info["oid"]))# print("转发数=" + str(base_info["repost"]))# print("评论数=" + str(base_info["comment"]))text_str = "oid=" + str(base_info["oid"]) + "\n"text_str = text_str + "转发数=" + str(base_info["repost"]) + "\n"text_str = text_str + "评论数=" + str(base_info["comment"]) + "\n"text.insert(tkinter.INSERT, text_str)text.update()# 根据抽奖类型进行抽奖 1评论 0转发if int(draw_type) == 1:# 获取用户信息并抽取幸运用户get_user_info(base_info)else:get_repost_user_info(base_info)# 关闭游标cur.close()# 断开数据库连接con.close()# 清空输入框按钮点击
def clear_in():e2.delete(0, END)e3.delete(0, END)# 清空输出框按钮点击
def clear_out():text.delete(0.0, tkinter.END)window = tkinter.Tk()
window.title("b站动态抽奖程序")
window.geometry("1000x800+200+100")
# 菜单栏
menu = tkinter.Menu(window)
# Open放在菜单栏中,就是装入容器
menu.add_command(label='关于', command=about)
# 创建菜单栏完成后,配置让菜单栏menu显示出来
window.config(menu=menu)# 创建一个主frame,长在主window窗口上
frame = tkinter.Frame(window)
frame.pack()# 创建第二层框架frame,长在主框架frame上面
# 上
frame_t = tkinter.Frame(frame)
# 下
frame_b = tkinter.Frame(frame)# frame_t.pack(side=tkinter.TOP)
# frame_b.pack(side=tkinter.BOTTOM)
frame_t.grid(row=0, column=0)
frame_b.grid(row=1, column=0)# 创建标签
l1 = tkinter.Label(frame_t, text='抽奖类型:', width=10, font=('microsoft yahei', 16))
l2 = tkinter.Label(frame_t, text='动态链接:', width=10, font=('microsoft yahei', 16))
l3 = tkinter.Label(frame_t, text='中奖人数:', width=10, font=('microsoft yahei', 16))radio = tkinter.IntVar()
radio1 = tkinter.Radiobutton(frame_t, text="评论", font=('microsoft yahei', 16), width=10, justify='left', value=1,variable=radio, command=radio_click, padx=1)
radio1.grid(row=0, column=1)
radio2 = tkinter.Radiobutton(frame_t, text="转发", font=('microsoft yahei', 16), width=10, justify='left', value=0,variable=radio, command=radio_click, padx=1)
radio2.grid(row=0, column=2)
button1 = tkinter.Button(frame_t, text="开始抽奖", command=start_btn, font=('microsoft yahei', 12), width=16, height=1)
button1.grid(row=0, column=3)StringVar1 = tkinter.StringVar()
StringVar1.set("")
e2 = tkinter.Entry(frame_t, show=None, width=42, textvariable=StringVar1, font=('microsoft yahei', 16))
StringVar2 = tkinter.StringVar()
StringVar2.set("1")
e3 = tkinter.Entry(frame_t, show=None, width=42, textvariable=StringVar2, font=('microsoft yahei', 16))button2 = tkinter.Button(frame_t, text="清空输入框", command=clear_in, font=('microsoft yahei', 12), width=16, height=1)
button2.grid(row=1, column=2)
button3 = tkinter.Button(frame_t, text="清空输出框", command=clear_out, font=('microsoft yahei', 12), width=16, height=1)
button3.grid(row=2, column=2)l1.grid(row=0, column=0)
l2.grid(row=1, column=0)
e2.grid(row=1, column=1)
l3.grid(row=2, column=0)
e3.grid(row=2, column=1)# 创建滚动条
scroll = tkinter.Scrollbar(frame_b)
text = tkinter.Text(frame_b, font=('microsoft yahei', 14), width=80, height=30)
# side放到窗体的那一侧
scroll.pack(side=tkinter.RIGHT, fill=tkinter.Y)
text.pack(side=tkinter.LEFT, fill=tkinter.Y)
# text.grid(row=3, column=0)
# scroll.grid(row=3, column=1)
# 关联
scroll.config(command=text.yview)
text.config(yscrollcommand=scroll.set)window.mainloop()

cmd版本(已不适配)

# -*- coding: utf-8 -*-
import json
import time
import random
import urllib.request
import urllib.parse
import sqlite3# 打包 venv\Scripts\pyinstaller.exe -F 1.pyprint("*********************************************************************************")
print("***  欢迎使用 UP:Love丶伊卡洛斯 开发的b站抽奖程序 本程序开源免费          ")
print("***  请勿使用非本人仓库下载的程序,否则无法保证安全,未知程序谨慎使用        ")
print("***  本程序目前只支持动态转发、评论的抽奖,视频评论区抽奖有待开发。。。           ")
print("***  使用注意:因为涉及本地文件的操作,如果失败,则需要\"超级管理员\"权限运行   ")
print("***  温馨提示:如果以下内容输错,请重新运行程序,异常数据处理懒得做了0.0     ")
print("*********************************************************************************")# 获取抽奖类型
global draw_type
global referer
global lucky_num
have_pic = 1# 字符串是否是数字
def is_number(s):try:float(s)return Trueexcept ValueError:passtry:import unicodedataunicodedata.numeric(s)return Trueexcept (TypeError, ValueError):passreturn Falsewhile True:draw_type = input("请输入抽奖类型(1评论 0转发):")if draw_type != '0' and draw_type != '1':print("请输入0或1")continuereferer = input("请输入动态链接:")if not referer.startswith('https://t.bilibili.com'):print("动态链接地址不正确,请重新输入")continuelucky_num = input("请输入中奖人数:")if not is_number(lucky_num):print("请输入正确的中奖人数")continueif int(float(lucky_num)) > 0:breakelse:print("请输入正确的中奖人数")id_set = set()
name_set = set()
lucky_set = set()dynamic_id = ""headers1 = {'Accept': 'application/json, text/plain, */*','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.9','Connection': 'keep-alive','Content-Type': 'text/plain;charset=UTF-8','Referer': referer,'origin': 'https://t.bilibili.com',# 'cookie': 'l=v','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3875.400 QQBrowser/10.8.4492.400'
}# 配置数据库
def config_db():global con, curcon = sqlite3.connect("user_data.db")cur = con.cursor()# 创建表usersql = "CREATE TABLE IF NOT EXISTS user(mid TEXT PRIMARY KEY,uname TEXT,message TEXT)"cur.execute(sql)# 情况表数据sql = "delete from user"cur.execute(sql)# 获取oid、转发数、评论数函数
def get_oid(referer):if (referer[8] == 't'):print('解析为动态页面')else:print('解析为视频页面')tab_type = "2"# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":dynamic_id = referer[23:len(referer) - 6]tab_type = referer[-1]else:dynamic_id = referer[23:len(referer)]print("dynamic_id=" + dynamic_id)if len(dynamic_id) == 0:print("dynamic_id异常,程序终止,请检查您的输入是否有误!")base_info = {'ret': False}return base_infopayload = {'dynamic_id': dynamic_id}data = urllib.parse.urlencode(payload)req = urllib.request.urlopen('https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?%s' % data)ret = req.read().decode()# print(ret)json1 = json.loads(ret)oid = json1["data"]["card"]["desc"]["rid"]repost = json1["data"]["card"]["desc"]["repost"]comment = 0# 非视频动态if tab_type == "2":comment = json1["data"]["card"]["desc"]["comment"]else:comment = 0# 判断动态类型type = json1["data"]["card"]["desc"]["type"]global have_picif int(type) == 2:have_pic = 1else:have_pic = 0# print("oid=" + str(oid))base_info = {'ret': True, 'oid': oid, 'repost': repost, 'comment': comment}return base_info# 获取用户信息函数
def get_user_info(referer, base_info):print("开始获取用户信息...")if int(have_pic) == 1:type = 11else:type = 17# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":base_info["oid"] = referer[23:len(referer) - 6]else:base_info["oid"] = referer[23:len(referer)]end = 0for i in range(int((base_info["comment"] - 1) / 20) + 1):if i == 0:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=0&type=" + str(type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1));else:url = "https://api.bilibili.com/x/v2/reply/main?jsonp=jsonp&next=" + str(i + 1) + "&type=" + str(type) + \"&oid=" + str(base_info["oid"]) + "&mode=3&plat=1&_=" + str((int(round(time.time() * 1000)) + 1));if i == int((base_info["comment"] - 1) / 20):end = 1get_data(url, end)time.sleep(0.5)# 获取数据函数
def get_data(url, end):req = urllib.request.urlopen(url)ret = req.read().decode()# print(ret)json1 = json.loads(ret)# json1["data"]["replies"]有可能为nullif json1["data"]["replies"] is not None:len1 = len(json1["data"]["replies"])for i in range(len1):mid = json1["data"]["replies"][i]["member"]["mid"]uname = json1["data"]["replies"][i]["member"]["uname"]message = json1["data"]["replies"][i]["content"]["message"]# 数据插入集合# name_set.add(uname)id_set.add(mid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (mid, uname, message))con.commit()print("已获取" + str(len(id_set)) + "个用户的数据...")# print("插入一组数据组")if end == 1:print("数据获取完毕!\n")# print(name_set)# print(id_set)while len(lucky_set) < int(lucky_num):num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)# print(lucky_set)# id_list = list(id_set)# name_list = list(name_set)# for i in range(int(lucky_num)):#     print("昵称:" + name_list[i] + "  id:" + id_list[i] + "\n")for i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))# 获取转发用户的数据
def get_repost_user_info(referer, base_info):print("开始获取用户信息...")# 用户输入是否是完整复制动态链接,链接尾部 是否是 ?tab=2if referer[-6:-1] == "?tab=":dynamic_id = referer[23:len(referer) - 6]else:dynamic_id = referer[23:len(referer)]temp_num = 0# 根据转发数进行循环while temp_num < int(base_info["repost"]):url = "https://api.live.bilibili.com/dynamic_repost/v1/dynamic_repost/view_repost?dynamic_id=" + \str(dynamic_id) + "&offset=" + str(temp_num);req = urllib.request.urlopen(url)ret = req.read().decode()# print(url)# print(ret)json1 = json.loads(ret)len1 = 0if "comments" in ret:len1 = len(json1["data"]["comments"])# print(len1)else:print("可获取的数据结束!\n")breakfor i in range(len1):uid = json1["data"]["comments"][i]["uid"]uname = json1["data"]["comments"][i]["uname"]comment = json1["data"]["comments"][i]["comment"]# 数据插入集合# name_set.add(uname)id_set.add(uid)# 数据插入数据库sql = "replace into user(mid, uname, message) values (?, ?, ?)"cur.execute(sql, (uid, uname, comment))con.commit()temp_num += 20print("已获取" + str(len(id_set)) + "个用户的数据...")time.sleep(0.5)print("数据获取完毕!\n")while len(lucky_set) < int(lucky_num):num = 0if len(id_set) > 1:num = random.randint(0, (len(id_set) - 1))lucky_set.add(num)else:print('用户数据不足2个,数据异常,程序结束')returnfor i in range(int(lucky_num)):lucky_list = list(lucky_set)# print("lucky_num=" + str(lucky_list[i]))sql = "select * from user limit " + str(lucky_list[i]) + ",1"cur.execute(sql)rows = cur.fetchall()for row in rows:print('\nid:%s  昵称:%s  评论:%s' % (row[0], row[1], row[2]))# 配置数据库
config_db()
# 获取oid、转发数、评论数
base_info = get_oid(referer)if base_info["ret"]:print("oid=" + str(base_info["oid"]))print("转发数=" + str(base_info["repost"]))print("评论数=" + str(base_info["comment"]))# 根据抽奖类型进行抽奖 1评论 0转发if (int(draw_type) == 1):# 获取用户信息并抽取幸运用户get_user_info(referer, base_info)else:get_repost_user_info(referer, base_info)# 关闭游标cur.close()# 断开数据库连接con.close()print("\n程序运行完毕!")quit = 0while quit != "1":quit = input("是否关闭程序(是1,否0):")

python b站动态转发、动态评论区抽奖(已打包成exe,可以下载食用)相关推荐

  1. python实现多张多格式图片转PDF并打包成exe

    目录 主要思路 转PDF初始代码 转PDF最终代码 GUI界面设计代码 打包成可执行文件 完整代码 附录 主要思路 从文件夹中读取图片数据,然后将他们保存为PDF格式. 转PDF初始代码 不长,大概1 ...

  2. 【Python培训基础】一篇文件教你py文件打包成exe

    场景: 如果要将我们编写好的代码给别人使用,如果要他们直接使用我们的代码,就需要安装各种编译软件以及第三方模块,还要对软件操作,编程有一定的了解,这对使用者的要求比较高,不是很方便,为了解决这一问题, ...

  3. Python实现简单的闹钟/倒计时/番茄钟软件并打包成exe

    文章目录 开发背景 程序界面及使用介绍 程序源码 使用Pyinstaller打包成exe 程序下载链接 备注 开发背景 玩电脑总是忘记休息,手机定闹钟太麻烦,在网上也没有搜索到符合我需求的极简软件,故 ...

  4. python写的程序怎么打包成exe_python--- 如何将自己的程序打包成exe ?

    最近用python Tkinter 写了一个看stock的小工具.. .  把它调节成半透明悬浮    你懂得 但是每次总用pycharm 或者调python去加载使用多少有些不便,如何打包成exe成 ...

  5. python打包成exe导入文件_Pyinstaller(python打包为exe文件)

    需求分析: python脚本如果在没有安装python的机器上不能运行,所以将脚本打包成exe文件,降低脚本对环境的依赖性,同时运行更加迅速. 当然打包的脚本似乎不是在所有的win平台下都能使用,wi ...

  6. JS实现b站动态评论区抽奖(含去重)

    目录 新前言 补充 视频演示 旧前言 教程 1.访问页面 2.打开"检查" 3.贴入代码 2.0版本多人抽取 3.0新版本单人抽取(适应b站动态改动) 3.1新版本多人抽取(适应b ...

  7. B站评论区抽奖[python]

    Bili-Luckdog B站评论区抽奖工具 by - ALKEYSHENG 2020.5.21 第三方库requests Blog: i.2017.work Github项目: Bili-Lucky ...

  8. b站“视频评论区”抽奖 讲解(含JS源码)

    目录 新前言 旧前言 视频讲解 正文 1.打开视频页面 2.鼠标右键打开"检查"工具 或 按F12 3.直接贴入代码-v3.1 4.等待翻页到最底部后,运行 go(中奖人数) 抽取 ...

  9. 评论区抽奖程序2.0

    评论区抽奖程序2.0 稍微的加了一点点功能,让程序更加的自动化了 [送书活动] 每周三发文章送书,两本 开奖时间为周五晚上8.00 下周书籍寄出 关注博主,每周抽奖 1. 程序作用 从某CSDN文章的 ...

最新文章

  1. 第七周项目一-一般函数(2)
  2. centos6下的mysql的安装
  3. MySQL优化关联查询
  4. 萤石云平台接入_前端接入监控视频
  5. python识别12306验证码_Python3.4实现的12306最新验证码识别
  6. SEO优化---学会建立高转化率的网站关键词库
  7. 构建前端Mock Server的利器/Json-Server
  8. Sicily 6271
  9. 序列号Serial Number管理
  10. 网络通信编程大作业--深度研究爬虫技术
  11. php怎么更换图片背景颜色,照片换底色红色变白色怎么变 怎么换照片底色
  12. android button 点击没有音效
  13. Excel列宽在哪里设置?Excel怎么设置行高和列宽
  14. wxpython绘制雷达图_Tableau可视化分析【8】解锁雷达图
  15. linux查看ftp客户端限速配置,vsftpd限速设置
  16. 传奇地图事件触发脚本
  17. html为知笔记模板,为知笔记,模板制作.doc
  18. 今日头条用户搜索“室内设计”显示的自媒体粉丝数量及分布情况统计(2020.1.8)
  19. MFC的导航窗格浮窗设计
  20. redis的主从同步及高可用集群

热门文章

  1. web应用商城部署(gpmall)
  2. JaveScript内置对象(JS知识点归纳八)
  3. 如何用计算机做微积分,利用计算知识搜索引擎WolframAlpha做微积分(快速指南).doc...
  4. Triton针对工业系统的形势分析以及检测手段 || 后附今日情报资源
  5. 显示桌面的图标不见了 怎么显示出来
  6. 读书笔记--项亮《推荐系统实践》第一章
  7. lubuntu12.04将64G minSD卡 格式exFAT 转 FAT32
  8. Linux主机地址解析慢,linux无法解析主机地址(could not resolve host)解决办法
  9. 〖全域运营实战白宝书 - 高转化文案速成篇⑤〗- 如何撰写内容型文案?
  10. Unity 仿 了不起修仙模拟器画符