哔哩哔哩自动批量删除抽奖动态解析篇(一)

本文的分析过程可能需要读者了解一点前后端数据交互和逆向分析的思路和基础,由于本人是新手,自己也处于摸索学习阶段,说的不对或者不好的地方敬请谅解。

一、删除动态流程分析

B站每条动态无论是转发他人的动态还是自己原创发布的动态都有一个“id_str”索引值,B站服务器根据该索引进行对动态进行“增删改查(csrf)”,因此我们删除动态的流程大致可以按以下顺序操作:

  1. 获取自己所有动态的索引“id_str”;
  2. 若为转发的动态,每条动态数据里会有一个orig的字典,字典里也有一个id_str记录你转发的原动态索引,下文以“orig_id_str”指代;
  3. 我们根据“orig_id_str”获取原官方抽奖动态的数据信息,其中官方抽奖动态有一个“lottery_time”记录开奖时间,我们以把它与现在的时间作比较,如果早于现在,那说明已开奖,反之则为等待开奖;
  4. 若转发的原动态已经开奖,我们通过调用删除动态的api接口remove结合自己发布的动态“id_str”索引进行删除,由于是删除自己的动态,肯定需要对自己账号信息进行验证,这一点通过网页cookie可以实现

根据上述流程,结合自己在哔哩哔哩的摸索过程,我给自己画了一个思维导图,(思维导图只是记录自己的思路过程,主要自己看,了解自己下一步目标,每个人的思路不同,因此其他人可能看不明白,不喜忽喷)
在这里插入图片描述

二、获取自己发布的动态列表数据接口

1、找到数据api接口

所有网站页面基本都是前端调用服务器端的api接口获取数据进行页面渲染。上文已经说到,每条B站动态都有一个“id_str”索引,我们数一下就能发现每次动态列表加载更新都是12条数据。我们第一步要做的就是获得这个api接口链接。
首先进入自己的动态列表,通过键盘“F12”键查看网页源代码信息,不了解的客户可以自行查询功能介绍,这里不过多赘述。刷新页面,此时我们可以看到有很多网络请求,我们从一众请求中找到服务器响应response中带有12条"id_str"的网络请求
在这里插入图片描述
在这里插入图片描述
通过上述6步操作,你可以获得一段脚本。这里给大家介绍一个网站Convert curl commands to Python, JavaScript and more此网站后续还有用,建议收藏到书签里。
进入网站后将你复制的脚本粘贴进去,你会获得一份可以直接执行的python代码,将代码复制到你的pycharm里运行输出结果就能看到服务器响应返回的12条动态数据,其中就有我们需要的“id_str”索引和转发的原动态的“id_str”索引
在这里插入图片描述
通过pychram执行代码,输出response我们可以看到输出的内容和我们在网页看到的12条动态资料一模一样,说明我们成功了
在这里插入图片描述

2、加载更多动态列表

我们下拉动态栏,重复上述操作,找到新的api接口(可以通过“Ctrl+F”健在网络响应中输入第一次找到的api接口信息“polymer/web-dynamic/v1/feed/space?offset&host_mid”快速找到新的api接口),复制新脚本生成新的python代码,与第一次的代码比较,我们发现第二次代码与第一次代码api接口参数主要以下三点有区别

  • offset
  • w_rid
  • wts

其中接触过数据库的读者可能一眼可以看出offset是数据库分页查找的参数,我们可以通过控制变量法逐一排查哪个参数影响查询结果。事实证明,只有offset会影响分页结果,w_rid与wts不变化也能正常查询,而其中offset的值正是我们首次查询的12条动态中最后一条动态的id_str索引,我们只需要每次更新offset为最新一次查找的12条动态末尾动态的id_str索引值即可查询到全部的动态。

三、代码思路及实现

  1. 获取首次动态列表,获取以下数据,由于id_str与orig_id_str有对应关系,因此建议使用键值对的方式保存每条动态的信息,并将所有动态保存为列表:
    - id_str:需保存
    - orig_id_str:orig中的id_str,记录转发的动态的索引,需保存
    - has_more:判断是否还有更多的动态
    - offset:下次查找的偏移量
  2. 判断has_more是否为True,意味着还有更多动态,更新api接口中的offset参数更新数据,直到has_more为false
#用于生成每个动态对象,带有id_str和orig_str属性,后续代码改进需要更多参数方便添加
class Idstr():
    def __init__(self,id_str,orig_id_str):
        self.id_str = id_str
        self.orig_id_str = orig_id_str

def getid_strList():
    #获取首次动态列表
    response = requests.get(
        f'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?offset&host_mid={host_mid}&timezone_offset=-480&platform=web&features=itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,decorationCard,forwardListHidden,ugcDelete,onlyfansQaCard&web_location=333.999&dm_img_list=[%7B%22x%22:1254,%22y%22:1465,%22z%22:0,%22timestamp%22:69,%22k%22:83,%22type%22:0%7D,%7B%22x%22:1192,%22y%22:-222,%22z%22:6,%22timestamp%22:328,%22k%22:123,%22type%22:0%7D]&dm_img_str=V2ViR0wgMS4wIChPcGVuR0wgRVMgMi4wIENocm9taXVtKQ&dm_cover_img_str=QU5HTEUgKEludGVsLCBJbnRlbChSKSBVSEQgR3JhcGhpY3MgKDB4MDAwMDhBNTYpIERpcmVjdDNEMTEgdnNfNV8wIHBzXzVfMCwgRDNEMTEpR29vZ2xlIEluYy4gKEludGVsKQ&dm_img_inter=%7B%22ds%22:[%7B%22t%22:0,%22c%22:%22%22,%22p%22:[57,19,19],%22s%22:[39,5076,5194]%7D],%22wh%22:[3660,5940,36],%22of%22:[54,108,54]%7D&x-bili-device-req-json=%7B%22platform%22:%22web%22,%22device%22:%22pc%22%7D&x-bili-web-req-json=%7B%22spm_id%22:%22333.999%22%7D&w_rid=8e093107e54b60fd35b846430c892e8e&wts=1726583398',
        cookies=cookies,
        headers=headers,
    ).json()
    data = response['data']
    id_strList = []  #保存动态列表参数值
    flag = True
    while flag:
        items = data['items']
        for item in items:
            if item.get('orig'):#因为抽奖动态都是转发的,我们原创的动态属于非转发,不会有orig数据,在此过滤掉,不做删除
                id_str = item['id_str']
                orig_id_str = item['orig']['id_str']
                new_idstr = Idstr(id_str,orig_id_str)#生成id_str对象
                id_strList.append(new_idstr)#将对象保存进列表
        offset = data['offset']#获取offset的值,以便获得后续的动态链接
        response = requests.get(
        f'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?offset={offset}&host_mid={host_mid}&timezone_offset=-480&platform=web&features=itemOpusStyle,listOnlyfans,opusBigCover,onlyfansVote,decorationCard,forwardListHidden,ugcDelete,onlyfansQaCard&web_location=333.999&dm_img_list=[%7B%22x%22:1254,%22y%22:1465,%22z%22:0,%22timestamp%22:69,%22k%22:83,%22type%22:0%7D,%7B%22x%22:1192,%22y%22:-222,%22z%22:6,%22timestamp%22:328,%22k%22:123,%22type%22:0%7D]&dm_img_str=V2ViR0wgMS4wIChPcGVuR0wgRVMgMi4wIENocm9taXVtKQ&dm_cover_img_str=QU5HTEUgKEludGVsLCBJbnRlbChSKSBVSEQgR3JhcGhpY3MgKDB4MDAwMDhBNTYpIERpcmVjdDNEMTEgdnNfNV8wIHBzXzVfMCwgRDNEMTEpR29vZ2xlIEluYy4gKEludGVsKQ&dm_img_inter=%7B%22ds%22:[%7B%22t%22:0,%22c%22:%22%22,%22p%22:[57,19,19],%22s%22:[39,5076,5194]%7D],%22wh%22:[3660,5940,36],%22of%22:[54,108,54]%7D&x-bili-device-req-json=%7B%22platform%22:%22web%22,%22device%22:%22pc%22%7D&x-bili-web-req-json=%7B%22spm_id%22:%22333.999%22%7D&w_rid=8e093107e54b60fd35b846430c892e8e&wts=1726583398',
            cookies=cookies,
            headers=headers,
        ).json()
        data = response['data']
        if data['has_more']:#判断是否是最后一批动态数据,如果不是,循环继续,直到has_more为false
            continue
        else:
            flag = False #当循环为false时,说明是最后一批动态数据了,我们将本次获得的动态数据加入列表就能退出循环了
            items = data['items']
            for item in items:
                if item.get('orig'):
                    id_str = item['id_str']
                    orig_id_str = item['orig']['id_str']
                    new_idstr = Idstr(id_str, orig_id_str)
                    id_strList.append(new_idstr)
        sleep_time = random.randint(1, 4)#随机生成数字1,2,3,4
        time.sleep(sleep_time)#由于爬虫速度较快,短时间发送大量请求极易被服务器判定为恶意攻击,因此随机停顿1~4秒模拟是人工操作
    return id_strList

由于我们在中间过程通过返回的数据是否含有orig字段数据过滤了自己发原创发布的动态,最后返回的列表id_strList仅为涉及转发的动态列表。到这里我们第一步获取动态列表的数据就完成了。下一节我们对获取的动态列表进行判断,判断原抽奖动态的开奖状态。

哔哩哔哩自动批量删除抽奖动态——使用篇
哔哩哔哩自动批量删除抽奖动态解析篇(一)
哔哩哔哩自动批量删除抽奖动态解析篇(二)
哔哩哔哩自动批量删除抽奖动态解析篇(三)
哔哩哔哩自动批量删除抽奖动态解析篇(四)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值