好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 闪电、犯贱 于 2026-1-5 22:05 编辑
因为这个程序较为简单,个人也比较懒,所以程序分开写的,比较粗糙,主要提供大致思路,勿喷,功能测试可用
以下是更新的删除动态操作方法
类似于获取评论并保存json,通过https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?offset=&host_mid=B站uid 会获取到你动态的全部信息,同样右键另存为json格式
打开软件用同样的方法,在编写过程中,dyn_type=1为转发他人动态,dyn_type=8 为自己视频动态,其余请自行观察,在本程序中,只删除转发他人动态功能
软件成品:
通过网盘分享的文件:delshare.exe(删除b站转发动态功能)
链接: https://pan.baidu.com/s/1h-1ToFqRP1CeP0K8VwoWuA?pwd=9euv 提取码: 9euv
源码放在原程序源码下方
![]()
最近aicu进行了风控,所以站内有一个B站评论一键清除软件暂时无法使用 ,所以偷巧利用类似的逻辑写了一个python软件
AICU官方网站:https://www.aicu.cc/ (如果出现删除成功但是AICU还是可以查询到是正常的,因为AICU的数据库并不是实时的,点击评论链接没有跳转到详细评论链接就是删除成功了)
一、在浏览器通过https://api.aicu.cc/api/v3/search/getreply?uid=(输入自己的B站ID)&pn=1&ps=500&mode=0
获取到数据,右键另存为Json,这里每次只可以获取500条
二、通过B站获取cookie,登录网页版B站中F12 随便找一个网络活动点进去找到cookie复制即可
运行程序输入即可
注意:数据运行依赖AICU的数据进行,AICU数据更新存在延迟,有可能删了AICU还有,有可能新发的评论AICU没有识别到
这只是一个思路,关于删除弹幕等,具体操作一致,可以自行更改api进行操作
软件成品链接:
通过网盘分享的文件:delreply.exe(删除B站所有评论功能)
链接: https://pan.baidu.com/s/19zNfEL1liYVIz6QPOJrtHw?pwd=w8wp 提取码: w8wp
[Python] 纯文本查看 复制代码 import json
import requests
import re
from http.cookies import SimpleCookie
# -------------------------- 配置区 --------------------------
# JSON文件路径(将通过input获取)
JSON_FILE_PATH = ""
# B站删除评论API地址
DEL_REPLY_URL = "https://api.bilibili.com/x/v2/reply/del"
# B站Cookie字符串(将通过input获取)
COOKIE_STR = ""
# 请求超时时间(秒)
TIMEOUT = 10
# 请求间隔(秒,避免高频请求被风控)
REQUEST_INTERVAL = 1
# -------------------------------------------------------------
def parse_cookie(cookie_str: str) -> dict:
"""解析Cookie字符串为字典格式"""
cookie = SimpleCookie()
cookie.load(cookie_str)
parsed_cookies = {}
for key, morsel in cookie.items():
parsed_cookies[key] = morsel.value
return parsed_cookies
def load_reply_data(file_path: str) -> list:
"""加载JSON文件,提取所有评论的oid、rpid、type"""
try:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
# 校验JSON结构
if not data.get("code") == 0 or not data.get("data") or not data["data"].get("replies"):
raise ValueError("JSON文件结构异常,未找到有效评论数据")
# 提取核心字段
reply_list = []
for reply in data["data"]["replies"]:
oid = reply.get("dyn", {}).get("oid")
rpid = reply.get("rpid")
type_id = reply.get("dyn", {}).get("type", 1) # 默认type=1
if not oid or not rpid:
print(f"⚠️ 跳过无效评论:缺少oid/rpid {reply}")
continue
reply_list.append({
"oid": oid,
"rpid": rpid,
"type": type_id
})
print(f"✅ 成功加载 {len(reply_list)} 条评论数据")
return reply_list
except FileNotFoundError:
print(f"❌ 未找到文件:{file_path}")
return []
except json.JSONDecodeError:
print(f"❌ JSON文件解析失败,请检查文件格式")
return []
except Exception as e:
print(f"❌ 加载评论数据失败:{str(e)}")
return []
def delete_single_reply(session: requests.Session, oid: str, rpid: str, type_id: int, csrf: str) -> dict:
"""发送单条评论删除请求"""
data = {
"oid": oid,
"type": type_id,
"rpid": rpid,
"csrf": csrf
}
headers = {
"Origin": "https://www.bilibili.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded",
"Referer": f"https://www.bilibili.com/video/BVxxxxxx/" # 可替换为实际视频链接
}
try:
response = session.post(
url=DEL_REPLY_URL,
headers=headers,
data=data,
timeout=TIMEOUT,
allow_redirects=False
)
result = {
"success": response.status_code == 200,
"status_code": response.status_code,
"response": response.json() if response.status_code == 200 else response.text,
"oid": oid,
"rpid": rpid
}
return result
except requests.exceptions.Timeout:
return {"success": False, "error": "请求超时", "oid": oid, "rpid": rpid}
except requests.exceptions.ConnectionError:
return {"success": False, "error": "连接错误", "oid": oid, "rpid": rpid}
except Exception as e:
return {"success": False, "error": str(e), "oid": oid, "rpid": rpid}
def batch_delete_replies():
"""批量删除评论主函数"""
# 1. 解析Cookie并获取csrf
parsed_cookies = parse_cookie(COOKIE_STR)
csrf_token = parsed_cookies.get("bili_jct")
if not csrf_token:
print("❌ 未从Cookie中提取到bili_jct,请检查Cookie有效性")
return
# 2. 加载评论数据
reply_list = load_reply_data(JSON_FILE_PATH)
if not reply_list:
return
# 3. 创建会话(复用Cookie)
session = requests.Session()
session.cookies.update(parsed_cookies)
# 4. 批量发送删除请求
success_count = 0
fail_count = 0
fail_details = []
print("\n🚀 开始批量删除评论...")
for idx, reply in enumerate(reply_list, 1):
print(f"\n[{idx}/{len(reply_list)}] 处理评论 rpid={reply['rpid']} oid={reply['oid']}")
# 发送删除请求
result = delete_single_reply(
session=session,
oid=reply["oid"],
rpid=reply["rpid"],
type_id=reply["type"],
csrf=csrf_token
)
# 结果统计
if result["success"]:
success_count += 1
print(f"✅ 删除成功:{result['response']}")
else:
fail_count += 1
fail_details.append(result)
print(f"❌ 删除失败:{result.get('error') or result['response']}")
# 添加请求间隔(避免风控)
import time
time.sleep(REQUEST_INTERVAL)
# 5. 输出最终统计
print("\n" + "="*50)
print(f"📊 批量删除完成!")
print(f"总处理数:{len(reply_list)}")
print(f"成功数:{success_count}")
print(f"失败数:{fail_count}")
if fail_details:
print(f"\n❌ 失败详情:")
for fail in fail_details:
print(f" rpid={fail['rpid']} oid={fail['oid']} 原因:{fail.get('error') or fail['response']}")
if __name__ == "__main__":
# 获取用户输入
print("="*50)
print("B站评论批量删除工具")
print("="*50)
json_file = input("\n请输入JSON文件路径(默认:reply.json):").strip() or "reply.json"
cookie_str = input("\n请输入B站Cookie字符串(包含SESSDATA、bili_jct等字段):").strip()
if not cookie_str:
print("\n❌ Cookie不能为空!")
print("📌 获取方式:浏览器打开B站→F12→网络→随便找一个请求→请求头→复制Cookie字段")
else:
# 赋值给全局变量
JSON_FILE_PATH = json_file
COOKIE_STR = cookie_str
batch_delete_replies()
动态删除功能源码:
[Python] 纯文本查看 复制代码 import json
import requests
import time
from http.cookies import SimpleCookie
from typing import List, Dict, Any
# -------------------------- 复用原有Cookie核心逻辑(从删除评论代码中提取) --------------------------
def parse_cookie(cookie_str: str) -> dict:
"""解析Cookie字符串为字典格式(原删除评论代码直接复用)"""
cookie = SimpleCookie()
cookie.load(cookie_str)
parsed_cookies = {}
for key, morsel in cookie.items():
parsed_cookies[key] = morsel.value
return parsed_cookies
def get_user_valid_cookie() -> str:
"""获取并校验用户输入的B站Cookie(原删除评论代码的输入逻辑)"""
print("\n📌 Cookie获取方式:浏览器打开B站→F12→网络→随便找一个请求→请求头→复制Cookie完整字段")
cookie_str = input("请输入B站Cookie字符串(包含SESSDATA、bili_jct):").strip()
# 第一步:校验Cookie是否为空
if not cookie_str:
print("❌ 错误:Cookie字符串不能为空!")
return ""
# 第二步:解析Cookie并校验核心字段(bili_jct=csrf令牌,SESSDATA=登录状态)
parsed_cookies = parse_cookie(cookie_str)
missing_fields = []
if not parsed_cookies.get("bili_jct"):
missing_fields.append("bili_jct(CSRF令牌)")
if not parsed_cookies.get("SESSDATA"):
missing_fields.append("SESSDATA(登录状态)")
if missing_fields:
print(f"❌ 错误:Cookie缺少核心字段,无法完成登录验证:{', '.join(missing_fields)}")
return ""
print("✅ Cookie解析成功,包含有效登录字段和CSRF令牌")
return cookie_str
# -------------------------- 原有动态删除核心逻辑(保留不变,仅适配Cookie) --------------------------
def extract_params_from_json(data: Any, results: List[Dict[str, Any]]) -> None:
"""
递归遍历JSON数据,提取包含dyn_id_str、dyn_type、rid_str的params字段
仅筛选出 dyn_type=1 的数据(符合批量删除要求)
"""
# 如果是字典,遍历所有键值对
if isinstance(data, dict):
# 检查当前字典是否包含目标params结构
if "params" in data:
params = data["params"]
# 严格校验:包含三个必填字段 + dyn_type=1
if (isinstance(params, dict) and
all(key in params for key in ["dyn_id_str", "dyn_type", "rid_str"]) and
params["dyn_type"] == 1): # 仅保留需要删除的dyn_type=1类型
results.append({
"dyn_id_str": params["dyn_id_str"],
"dyn_type": params["dyn_type"],
"rid_str": params["rid_str"]
})
# 递归遍历字典的每个值,支持任意层级JSON结构
for value in data.values():
extract_params_from_json(value, results)
# 如果是列表,遍历每个元素继续递归
elif isinstance(data, list):
for item in data:
extract_params_from_json(item, results)
def load_target_params(json_file_path: str) -> List[Dict[str, Any]]:
"""
读取JSON文件,加载并筛选出符合条件的删除参数(dyn_type=1)
"""
extracted_params = []
try:
# 读取并解析JSON文件
with open(json_file_path, 'r', encoding='utf-8') as f:
json_data = json.load(f)
# 递归提取符合条件的params
extract_params_from_json(json_data, extracted_params)
print(f"✅ 成功从JSON文件提取到 {len(extracted_params)} 条待删除动态数据(dyn_type=1)")
return extracted_params
except FileNotFoundError:
print(f"❌ 错误:文件 {json_file_path} 未找到,请检查路径是否正确")
return []
except json.JSONDecodeError:
print(f"❌ 错误:文件 {json_file_path} 不是有效的JSON格式,请检查文件内容")
return []
except Exception as e:
print(f"❌ 未知错误:{str(e)}")
return []
def batch_delete_bilibili_dynamics(
target_params: List[Dict[str, Any]],
cookie_str: str,
platform: str = "web"
) -> None:
"""
批量调用B站删除动态API,执行删除操作(整合Cookie会话,解决未登录问题)
"""
if not target_params:
print("🚫 无待删除的动态数据,无需执行删除操作")
return
# 1. 解析Cookie,提取CSRF令牌(bili_jct)
parsed_cookies = parse_cookie(cookie_str)
csrf_token = parsed_cookies.get("bili_jct")
# 2. B站删除动态API地址
delete_api_url = "https://api.bilibili.com/x/dynamic/feed/operate/remove"
# 3. 请求头(模拟浏览器请求,提高成功率)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://t.bilibili.com/",
"Content-Type": "application/json;charset=UTF-8"
}
# 4. 创建Requests会话,复用Cookie(保持登录状态,解决未登录问题)
session = requests.Session()
session.cookies.update(parsed_cookies) # 注入Cookie,维持登录态
session.headers.update(headers) # 复用请求头
# 5. 遍历所有待删除参数,逐个执行删除请求
success_count = 0
fail_count = 0
fail_records = []
for idx, params in enumerate(target_params, 1):
try:
# 构造URL参数(platform + csrf)
url_params = {
"platform": platform,
"csrf": csrf_token
}
# 构造请求载荷(JSON格式,对应动态唯一参数)
request_payload = {
"dyn_id_str": params["dyn_id_str"],
"dyn_type": params["dyn_type"],
"rid_str": params["rid_str"]
}
# 发送POST请求(使用会话发送,携带登录Cookie)
response = session.post(
url=delete_api_url,
params=url_params,
json=request_payload,
timeout=10
)
# 解析响应结果,判断是否删除成功
response_json = response.json()
if response_json.get("code") == 0:
success_count += 1
print(f"[{idx}/{len(target_params)}] 成功删除动态:dyn_id_str={params['dyn_id_str']}")
else:
fail_count += 1
error_msg = response_json.get("message", "未知错误")
fail_records.append((params["dyn_id_str"], error_msg))
print(f"[{idx}/{len(target_params)}] 失败删除动态:dyn_id_str={params['dyn_id_str']},错误信息:{error_msg}")
except requests.exceptions.Timeout:
fail_count += 1
fail_records.append((params["dyn_id_str"], "请求超时"))
print(f"[{idx}/{len(target_params)}] 失败删除动态:dyn_id_str={params['dyn_id_str']},错误信息:请求超时")
except requests.exceptions.ConnectionError:
fail_count += 1
fail_records.append((params["dyn_id_str"], "网络连接错误"))
print(f"[{idx}/{len(target_params)}] 失败删除动态:dyn_id_str={params['dyn_id_str']},错误信息:网络连接错误")
except Exception as e:
fail_count += 1
fail_records.append((params["dyn_id_str"], str(e)))
print(f"[{idx}/{len(target_params)}] 失败删除动态:dyn_id_str={params['dyn_id_str']},错误信息:{str(e)}")
# 增加请求间隔(避免高频调用触发B站风控,保护账号安全)
time.sleep(1)
# 输出批量删除总结
print("\n" + "="*50)
print(f"批量删除操作完成!总计:{len(target_params)} 条,成功:{success_count} 条,失败:{fail_count} 条")
if fail_records:
print("\n失败详情:")
for dyn_id, msg in fail_records:
print(f" dyn_id_str={dyn_id}:{msg}")
# -------------------------- 主入口(整合所有流程) --------------------------
if __name__ == "__main__":
print("="*50)
print("B站动态批量删除工具(已整合登录Cookie验证)")
print("="*50)
# 步骤1:获取用户输入的JSON文件路径
JSON_FILE_PATH = input("\n请输入JSON文件路径(默认:all.json):").strip() or "all.json"
# 步骤2:获取并校验用户输入的Cookie(解决未登录问题)
valid_cookie = get_user_valid_cookie()
if not valid_cookie:
print("🚫 缺少有效Cookie,程序终止运行")
exit(1)
# 步骤3:加载待删除的动态参数(仅dyn_type=1)
to_delete_params = load_target_params(JSON_FILE_PATH)
# 步骤4:执行批量删除操作(携带有效Cookie,维持登录态)
batch_delete_bilibili_dynamics(to_delete_params, valid_cookie) |
免费评分
-
查看全部评分
|