Nemo2011 / bilibili-api

哔哩哔哩常用API调用。支持视频、番剧、用户、频道、音频等功能。原仓库地址:https://github.com/MoyuScript/bilibili-api
https://nemo2011.github.io/bilibili-api/
GNU General Public License v3.0
2.19k stars 210 forks source link

【需求】封装下载器 #5

Closed Naville closed 2 years ago

Naville commented 2 years ago

没用过ASync IO, 先放个需求在这。 等整明白了我看看能不能自己实现再PR过来

需求

Nemo2011 commented 2 years ago

Hello! 听说你需要一个封装 API 的下载器。其实我最近也在写下载器,但是还没写完(还在准备阶段) 不过你的需求目前是有解决方案的,不知道你能不能用。 下载器分为两部分,一部分获取链接,一部分下载。

获取链接

获取链接的函数被改成了异步,但是api里有一个sync函数,把异步函数套进去就能实现同步代码了。 举个栗子:

# 异步
async def main():
       # some code here
asyncio.get_event_loop().run_until_complete(main())
# 同步
sync(异步函数)

具体请看这儿->

下载

好巧不巧,最近我也在写一个下载器。通过文件分片下载来提速。和 aria2 的速度差不多。是纯 python 写的,可以试一试。 为什么不用 aria2c ?因为跨平台问题。ffmpeg 还算有 build,但是 aria2 要你自己编译!
安装:pip3 install PyFDown 示例:

from PyFDown import downloader
HEADERS = {
         "User-Agent": "Mozilla/5.0",
         "Referer":"https://bilibili.com" #一定要加,否则无法访问
}
URL = "API 得到的 URL"
downloader(URL, "输出文件", user_headers=HEADERS)

综合示例

from bilibili_api import video, sync
from PyFDown import downloader
HEADERS = {
         "User-Agent": "Mozilla/5.0",
         "Referer":"https://bilibili.com" #一定要加,否则无法访问
}
v = video.Video("BV0000000000")
P = 0 # 分 P 号
url = dict(sync(v.get_download_url(0)))['dash']['video'][0]['baseUrl']
output = "Video.mp4"
downloader(url, output, user_headers=HEADERS)
# 禁止在 IDLE 里运行(运行后果自负)

希望以上的内容可以帮到你。 对了,如果你感兴趣的话,可以去本仓库原作者的一个仓库看看,是一个命令行下载器。可以去看看(用 javascript 写的)。

Naville commented 2 years ago

@Nemo2011 感谢 aria2其实不是问题, 因为各个平台都有预编译包

Naville commented 2 years ago

更大的问题可能是怎么在下载器里优雅的上层无感知的Handle 频率限制

Nemo2011 commented 2 years ago

你是指下载文件时的进程数吗? aria2c限制单一服务器最大进程16个进程,有一个编译版本魔改的到了128。要是想要突破的话,还不如自己改源代码或者直接自己写一个呢。 当然,网上肯定有破解补丁,但是……(懒) 不过有一说一,这个真的很好用。

Naville commented 2 years ago

@Nemo2011 我指的是叔叔的Rate Limit

Nemo2011 commented 2 years ago

下载视频的原理是获取视频缓存地址,不用调用 api,是直链!bilibili的static是第三方存储(反正不是bilibili.com)。再说以前我用过you-get,连下800多个都没问题,速度也不慢。理论上下载时不用考虑叔叔的Rate Limit,最多就是Server disconnect,但是我试过,要达到disconnect至少访问个一分钟,一分钟快速下载器可以把一章的《流言终结者》(40分钟)下载完,你害怕个啥子?运气差的话,如果真正遇到,直接wait+retry不就好了?

Nemo2011 commented 2 years ago

如果有爬取评论的、粉丝的、番剧视频详细星系的,就用代理好了,设置自行查文档。

Nemo2011 commented 2 years ago

如果有问题的可以通知我一下,我会加紧改善的

Naville commented 2 years ago

我试过,要达到disconnect至少访问个一分钟,一分钟快速下载器可以把一章的《流言终结者》(40分钟)下载完,你害怕个啥子?运气差的话,如果真正遇到,直接wait+retry不就好了?

我的意思是比如说DownloadUser() 请求某个Up主的全部投稿,这里的rate limit. 可能得搞个类似代理池的机制在下载器里自动切换, 蛋疼

Nemo2011 commented 2 years ago

应该没有事的。我试了获取一位疯狂的 up 主的所有视频(有大概150000个视频???),最后还是成功了(时间也很短,足够了),差不过5分钟就行了,我也没被封。官方这里也是一页一页加载的(我又翻了加载的 javascript,就是现在用的接口),而且访问一次之后,就能得到视频的分类。每一个视频都有一个 typeid,可以通过 channel 查询 info,查到父类的 channel,而主页视频分类都是以父类的 channel 分的,所以一次获取就能到处使用(就是获取时自动分类)。最后提一个点,我的成功访问150000视频是基于一次访问50个视频的,访问了约3000,结果全是200。rate limit基本不会实现。

Nemo2011 commented 2 years ago

不方便的话可以给一下源码。

Nemo2011 commented 2 years ago

直接访问都不易出现问题

Nemo2011 commented 2 years ago

目前的逻辑就是: