
项目实训MemeMind——Blog5开启第二个任务——从获取单一数据到批量采集w_rid加密参数逆向分析本地模拟各参数实践爬取bilibili评论区多页开启第二个任务——从获取单一数据到批量采集本篇博客承接上篇博客内容对bilibili评论区分页加密机制进行分析破解从而实现对全部页面的自动化爬取。w_rid加密参数逆向分析通过开发者工具搜索定位加密位置同样的先通过下滑页面获取多页评论区数据包然后在开发者工具中搜索关键字w_rid利用搜索结果跳转结合代码结构定位对应代码内容。断点调试分析为疑似加密的代码位置都打上断点继续下滑页面加载新评论触发断点此时即可移除其他断点专门研究这一个复制对应内容at(v a)在控制台中得到返回的对应参数分析代码逻辑得出其中的v变量来自上一行的l.join函数at(va)加密后得到的是’6e60aef78d98a353fec329053f68bdcd’而v是字符串故va显然是一个字符串拼接操作拼接后的字符串作为参入传递给了at()函数由at()函数返回了加密后的参数v是由l列表决定的所以这里的at(v a)就是path中的w_rid值而a通过控制台打印得到这是一个固定值列表l通过控制台打印发现它其实就是除了w_rid以外的其他参数内容如果正常去解析应该去把这个at()函数找出来本地调试但固定值a是32位由0-9,a-f组成的参数很有可能就是md5加密测试验证va经过md5加密后确实就得到和at(v a)一样的结果所以这里就明确了确实是md5加密本地模拟各参数本地实现md5加密模拟# w_rid加密参数l[mode3,oid116527344983616,pagination_str%7B%22offset%22%3A%22%22%7D,plat1,seek_rpid,type1,web_location1315875,wts1781351468]v.join(l)stringvea1db124af3c7062474693fa704f4ff8MD5hashlib.md5()MD5.update(string.encode(utf-8))w_ridMD5.hexdigest()print(w_rid)找到下一页的参数获取下一页参数NextPagejson_data[data][cursor][pagination_reply][next_offset]next_offsetjson.dumps(NextPage)获取当前时间戳wtsint(time.time())最终得到完整翻页参数爬取多页评论实践爬取bilibili评论区多页代码的优化全部函数编写完成后我向TRAE给出以下提示词这份代码要实现对视频网站评论区的按页爬取在尽可能不改动原有代码的基础上优化完善代码结构和逻辑即可以对原有代码的部分进行剪切和粘贴但几乎不引入新代码和修改原有代码TRAE给出代码...# 初始化offset修复原代码初始值问题offset0# 爬取20页保留原逻辑...TRAE错误的理解把offset理解为了数值变量初始化为0导致参数读取错误运行时报错我手动修改后发现仍然只读取了第一页的评论,多次优化提示词后发现ai打着安全性和稳定性的旗号越改越臃肿问题却原封不动地没有得到有效解决我只好静下心来理性分析先修改了offset参数相关内容并添加了各个参数导入时打印参数内容作为侦错日志最后果然发现是offset在循环中传递的问题初始默认值的offset为 ,也就是内容为的字符串但是在通过next_offset json_data[data][cursor][pagination_reply][next_offset]获取时得到的是纯字符串也就是说在pagination_str {offset:%s} % offset传递参数时得到的仅仅是:加上纯字符串缺少需要的参数格式:字符串所以我将offset初始值调整为 的空字符串传入而获取则改为pagination_str {offset:%s} % offset确保每次自带有且仅有一个 果然这样就顺利爬取到了第二页的评论新的问题出现当我设置爬取20页时编译器在第14页报错next_offset json_data[data][cursor][pagination_reply][next_offset]没有正常执行我很快意识到这是评论提前爬取完成了于是向TRAE给出以下提示词为当前代码实现自动判断爬取结束功能TRAE给出代码...# 无下一页则终止ifnotpagination_str:print(已无更多评论爬取结束)break...再次运行后报错情形并未发生任何变化我想大概是判断指标出了问题于是先根据限定爬取第一页的结果得出一页的评论大概有20条左右再利用bilibili自身的交互系统筛选出评论数量刚好位于20条到30条之间的视频作为爬虫对象并通过下滑和网络抓包比对两次页面数据抓包的不同最终给出提示词我发现评论没有下一页的标志是[‘data’][‘cursor’]中没有[‘pagination_reply’]利用这一点在原代码的基础上实现判断终止循环并输出已爬取所有评论TRAE给出代码...cursorjson_data[data][cursor]# 检测 cursor 里是否有 pagination_reply 键ifpagination_replynotincursor:returnNone...可是运行后这个判断没有生效最后一页时还是会报错next_offset那一行有问题我又仔细检查了几遍抓包结果发现其实是存在[pagination_reply]的只是最后一页时其内容为{}不过直接判断字符串 {}似乎不是一个好主意我想到了利用TRAE给出的框架改写为...# 最后一页判断if(next_offsetnotinjson_data[data][cursor][pagination_reply]):return最后...if(offset最后):print(\n已检测到无下一页所有评论爬取完毕)break...运行后成功爬取到了完整内容并无报错功能拓展现在已经能爬取指定视频的全部评论了但这一定适配所有视频吗我从bilibili热度榜上随手点击了好几个视频逐一抓包分析它们参数的区别发现其实就是oid的区别于是我修改函数结构将oid从常量转化为参数变量...defGetW(wts,NextPage,oid):...defGetContent(offset,oid):...最终实现了任意视频的评论区全部爬取