[漏洞] 使用 `user.User.get_dynamics` 方法获取不到任何动态,且抛出 `TypeError: 'NoneType' object is not iterable` 错误
Python 版本: 3.11.2
模块版本: 16.2.0
运行环境: Windows
模块路径: bilibili_api.user
解释器: cpython
报错信息:
Traceback (most recent call last):
File "f:\VS Code File\test\test.py", line 24, in <module>
asyncio.run(main())
File "C:\Users\qwert\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\qwert\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\qwert\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "f:\VS Code File\test\test.py", line 19, in main
info = await u.get_dynamics()
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\qwert\AppData\Roaming\Python\Python311\site-packages\bilibili_api\user.py", line 645, in get_dynamics
for card in data["cards"]:
TypeError: 'NoneType' object is not iterable
报错代码:
import json
import asyncio
from bilibili_api import user, sync, Credential, settings, video
settings.proxy = 'http://127.0.0.1:{port}'
sessdata = '{sessdata}'
bili_jct = '{bili_jct}'
buvid3 = '{buvid3}'
dedeuserid = '{dedeuserid}'
ac_time_value = '{ac_time_value}'
credential: Credential = Credential(sessdata=sessdata, bili_jct=bili_jct, buvid3=buvid3, dedeuserid=dedeuserid, ac_time_value=ac_time_value)
u = user.User(572139515, credential=credential)
async def main():
info = await u.get_dynamics()
with open('test_dynamics.json', 'w', encoding='utf-8') as file:
json.dump(info, file, ensure_ascii=False, indent=4)
asyncio.run(main())
报错代码处敏感信息已替换,实际运行过程中是正确获取了的
试过了两个不同的 uid ,确定两个 UP 都是有着大量动态的,但是仍然会在获取时抛出错误
查看源码发现错误出现在 user.User.get_dynamics() 方法的这里:
async def get_dynamics(self, offset: int = 0, need_top: bool = False) -> dict:
...
# card 字段自动转换成 JSON。
# print(data) # 我添加了 print 代码以检查获取到的 data
if "cards" in data: # > 这里应当是判为 False 的,因为实际上并没有获取到数据,但是在 data 中存在该字段,导致抛出错误
for card in data["cards"]: # > 在 data 中该字段的实际值为 None ,不符合预期
card["card"] = json.loads(card["card"])
card["extend_json"] = json.loads(card["extend_json"])
return data
在添加 print(data) 代码行后,运行上述代码,得到了如下输出:
{'has_more': 0, 'cards': None, 'next_offset': 0}
可以看出,虽然 "card" 字段存在于字典中,但是它的值是 None ,导致 if "cards" in data 语句并没有正确地将这种情况排除掉
现在的问题是:
-
if语句并没有将字段存在但值为None的情况排除,使if内代码段进行了for card in None的操作,导致抛出错误。这个很好修改,只需要将if语句改为if data.get("card", None) is not None就可以了 - 理论上应当获取到数据的情况并没有获取到合法的数据,且获取过程中没有任何错误抛出。这个是出现问题的根本原因,且我并没有在 issues 或
16.2.1的 release 中看到有关的信息(也可能只是我漏看了),不知道是什么情况
看到了 user.User.get_dynamics_new 接口,但是相应的文档并没有被添加到文档中,建议进行相应的修改,以及在 user.User.get_dynamics 接口未能获取到数据时可以自动跳转到 user.User.get_dynamics_new 接口中,而不是需要用户自行修改
看到了
user.User.get_dynamics_new接口,但是相应的文档并没有被添加到文档中,建议进行相应的修改,以及在user.User.get_dynamics接口未能获取到数据时可以自动跳转到user.User.get_dynamics_new接口中,而不是需要用户自行修改
基本上不会提供主动切换
不过倒是有必要添加 @deprecated 相关的说
https://github.com/Nemo2011/bilibili-api/issues/737
这是因为前几天批站改动态api了吧
我试了一下,现在访问动态api需要在请求头里加cookie项,不然就会被风控