Skip to content

Commit

Permalink
fix: video.VideoDownloadURLDataDetecter for bangumi
Browse files Browse the repository at this point in the history
feat: add BiliAPIClient.download
  • Loading branch information
Nemo2011 committed Jan 29, 2025
1 parent 76a1c10 commit 1e7a13d
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 86 deletions.
15 changes: 14 additions & 1 deletion bilibili_api/clients/AioHTTPClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def set_proxy(self, proxy: str = "") -> None:
self.__use_args = True
self.__args["proxy"] = proxy

def set_timeout(self, timeout: float=0) -> None:
def set_timeout(self, timeout: float = 0) -> None:
self.__use_args = True
self.__args["timeout"] = timeout

Expand Down Expand Up @@ -167,6 +167,18 @@ async def request(
)
return bili_api_resp

async def download(
self, url: str = "", headers: dict = {}, out: str = "", intro: str = "下载"
) -> None:
async with self.__session.get(url=url, headers=headers) as resp:
bts = 0
tot = resp.headers.get("content-length")
with open(out, "wb") as file:
async for chunk in resp.content.iter_chunks():
bts += file.write(chunk[0])
print(f"{intro} - {out} [{bts}/{tot}]", end="\r")
print()

async def ws_create(
self, url: str = "", params: dict = {}, headers: dict = {}
) -> int:
Expand Down Expand Up @@ -229,6 +241,7 @@ async def close(self):
set_verify_ssl.__doc__ = BiliAPIClient.set_verify_ssl.__doc__
set_trust_env.__doc__ = BiliAPIClient.set_trust_env.__doc__
request.__doc__ = BiliAPIClient.request.__doc__
download.__doc__ = BiliAPIClient.download.__doc__
ws_create.__doc__ = BiliAPIClient.ws_create.__doc__
ws_recv.__doc__ = BiliAPIClient.ws_recv.__doc__
ws_send.__doc__ = BiliAPIClient.ws_send.__doc__
Expand Down
13 changes: 13 additions & 0 deletions bilibili_api/clients/CurlCFFIClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ async def request(
)
return bili_api_resp

async def download(
self, url: str = "", headers: dict = {}, out: str = "", intro: str = "下载"
) -> None:
req = await self.__session.get(url=url, headers=headers, stream=True)
bts = 0
tot = req.headers.get("content-length")
with open(out, "wb") as file:
async for chunk in req.aiter_content():
bts += file.write(chunk)
print(f"{intro} - {out} [{bts}/{tot}]", end="\r")
print()

async def ws_create(
self, url: str = "", params: dict = {}, headers: dict = {}
) -> int:
Expand Down Expand Up @@ -229,6 +241,7 @@ async def close(self) -> None:
set_verify_ssl.__doc__ = BiliAPIClient.set_verify_ssl.__doc__
set_trust_env.__doc__ = BiliAPIClient.set_trust_env.__doc__
request.__doc__ = BiliAPIClient.request.__doc__
download.__doc__ = BiliAPIClient.download.__doc__
ws_create.__doc__ = BiliAPIClient.ws_create.__doc__
ws_recv.__doc__ = BiliAPIClient.ws_recv.__doc__
ws_send.__doc__ = BiliAPIClient.ws_send.__doc__
Expand Down
15 changes: 14 additions & 1 deletion bilibili_api/clients/HTTPXClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async def request(
files=files,
headers=headers,
cookies=cookies,
follow_redirects=allow_redirects
follow_redirects=allow_redirects,
)
resp_header_items = resp.headers.multi_items()
resp_headers = {}
Expand Down Expand Up @@ -137,6 +137,18 @@ async def request(
)
return bili_api_resp

async def download(
self, url: str = "", headers: dict = {}, out: str = "", intro: str = "下载"
) -> None:
resp = await self.__session.get(url=url, headers=headers)
bts = 0
tot = resp.headers.get("content-length")
with open(out, "wb") as file:
async for chunk in resp.aiter_bytes():
bts += file.write(chunk)
print(f"{intro} - {out} [{bts}/{tot}]", end="\r")
print()

async def ws_create(self, *args, **kwargs) -> None:
"""
httpx 库暂未实现 WebSocket。相关讨论:<https://github.com/encode/httpx/issues/304>
Expand Down Expand Up @@ -179,4 +191,5 @@ async def close(self) -> None:
set_verify_ssl.__doc__ = BiliAPIClient.set_verify_ssl.__doc__
set_trust_env.__doc__ = BiliAPIClient.set_trust_env.__doc__
request.__doc__ = BiliAPIClient.request.__doc__
download.__doc__ = BiliAPIClient.download.__doc__
close.__doc__ = BiliAPIClient.close.__doc__
42 changes: 25 additions & 17 deletions bilibili_api/utils/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@
from Cryptodome.Hash import SHA256
from Cryptodome.PublicKey import RSA

from ..exceptions import (ArgsException, CookiesRefreshException,
CredentialNoAcTimeValueException,
CredentialNoBiliJctException,
CredentialNoBuvid3Exception,
CredentialNoDedeUserIDException,
CredentialNoSessdataException, ExClimbWuzhiException,
ResponseCodeException, WbiRetryTimesExceedException)
from ..exceptions import (
ArgsException,
CookiesRefreshException,
CredentialNoAcTimeValueException,
CredentialNoBiliJctException,
CredentialNoBuvid3Exception,
CredentialNoDedeUserIDException,
CredentialNoSessdataException,
ExClimbWuzhiException,
ResponseCodeException,
WbiRetryTimesExceedException,
)
from .AsyncEvent import AsyncEvent
from .utils import get_api, raise_for_statement

Expand Down Expand Up @@ -529,17 +534,18 @@ async def request(
@abstractmethod
async def download(
self, url: str = "", out: str = "", intro: str = "下载"
self, url: str = "", headers: dict = {}, out: str = "", intro: str = "下载"
) -> None:
"""
下载文件
模块自带 clients 实现效果:`intro - out [bytes/total]`
Args:
url (str, optional): 请求地址. Defaults to "".
out (str, optional): 文件地址. Defaults to "".
intro (str, optional): 下载信息. Defaults to "".
url (str, optional) : 请求地址. Defaults to "".
out (str, optional) : 文件地址. Defaults to "".
headers (dict, optional): 请求头. Defaults to {}.
intro (str, optional) : 下载信息. Defaults to "".
"""
raise NotImplementedError
Expand Down Expand Up @@ -710,17 +716,18 @@ async def request(

@abstractmethod
async def download(
self, url: str = "", out: str = "", intro: str = "下载"
self, url: str = "", headers: dict = {}, out: str = "", intro: str = "下载"
) -> None:
"""
下载文件
模块自带 clients 实现效果:`intro - out [bytes/total]`
Args:
url (str, optional): 请求地址. Defaults to "".
out (str, optional): 文件地址. Defaults to "".
intro (str, optional): 下载信息. Defaults to "".
url (str, optional) : 请求地址. Defaults to "".
out (str, optional) : 文件地址. Defaults to "".
headers (dict, optional): 请求头. Defaults to {}.
intro (str, optional) : 下载信息. Defaults to "".
"""
raise NotImplementedError

Expand Down Expand Up @@ -848,7 +855,9 @@ def get_client() -> BiliAPIClient:
BiliAPIClient: 请求客户端
"""
if selected_client == "":
raise ArgsException("尚未安装第三方请求库或未注册自定义第三方请求库。\n$ pip3 install (curl_cffi==0.8.1.b9|httpx|aiohttp)")
raise ArgsException(
"尚未安装第三方请求库或未注册自定义第三方请求库。\n$ pip3 install (curl_cffi==0.8.1.b9|httpx|aiohttp)"
)
global session_pool
pool = session_pool.get(selected_client)
if pool is None:
Expand Down Expand Up @@ -903,7 +912,6 @@ def get_registered_clients() -> Dict[str, Type[BiliAPIClient]]:

@atexit.register
def __clean() -> None:

"""
程序退出清理操作。
"""
Expand Down
2 changes: 2 additions & 0 deletions bilibili_api/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -2185,6 +2185,8 @@ def __init__(self, data: dict):
data (dict): `Video.get_download_url` 返回的结果
"""
self.__data = data
if self.__data.get("video_info"): # bangumi
self.__data = self.__data["video_info"]

def check_video_and_audio_stream(self) -> bool:
"""
Expand Down
26 changes: 4 additions & 22 deletions docs/examples/bangumi.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ sync(main())
``` python
import asyncio

import curl_cffi.requests
from bilibili_api import bangumi, video, Credential, HEADERS, get_session
import curl_cffi
from bilibili_api import bangumi, video, Credential, HEADERS, get_client
import os

SESSDATA = ""
Expand All @@ -73,22 +71,6 @@ FFMPEG_PATH = "ffmpeg"
MEDIA_ID = 23679586


async def download_url(url: str, out: str, info: str):
# 下载函数
sess: curl_cffi.requests.AsyncSession = get_session() # 此处使用 curl_cffi
resp = await sess.get(url, stream=True, headers=HEADERS)
length = resp.headers.get("content-length")
with open(out, "wb") as f:
process = 0
async for chunk in resp.aiter_content():
if not chunk:
break
process += len(chunk)
print(f"下载 {info} {process} / {length}", end="\r")
f.write(chunk)
print()


async def main():
if not os.path.exists(str(MEDIA_ID)):
os.mkdir(str(MEDIA_ID))
Expand Down Expand Up @@ -118,8 +100,8 @@ async def download_episode(ep: bangumi.Episode, out: str):
# 有 MP4 流 / FLV 流两种可能
if detecter.check_video_and_audio_stream():
# MP4 流下载
await download_url(streams[0].url, "video_temp.m4s", "视频流")
await download_url(streams[1].url, "audio_temp.m4s", "音频流")
await get_client().download(streams[0].url, HEADERS, "video_temp.m4s", "视频流")
await get_client().download(streams[1].url, HEADERS, "audio_temp.m4s", "音频流")
# 混流
os.system(
f"{FFMPEG_PATH} -i video_temp.m4s -i audio_temp.m4s -vcodec copy -acodec copy {out}"
Expand All @@ -129,7 +111,7 @@ async def download_episode(ep: bangumi.Episode, out: str):
os.remove("audio_temp.m4s")
else:
# FLV 流下载
await download_url(streams[0].url, "flv_temp.flv", "FLV 音视频流")
await get_client().download(streams[0].url, HEADERS, "flv_temp.flv", "FLV 音视频流")
# 转换文件格式
os.system(f"{FFMPEG_PATH} -i flv_temp.flv {out}")
# 删除临时文件
Expand Down
30 changes: 6 additions & 24 deletions docs/examples/festival.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
``` python
import asyncio

import curl_cffi.requests
from bilibili_api import festival, video, Credential, HEADERS, get_session
import curl_cffi
from bilibili_api import festival, video, Credential, HEADERS, get_client
import os

SESSDATA = ""
Expand All @@ -18,22 +16,6 @@ FFMPEG_PATH = "ffmpeg"
FES_ID = "bnj2025"


async def download_url(url: str, out: str, info: str):
# 下载函数
sess: curl_cffi.requests.AsyncSession = get_session() # 此处使用 curl_cffi
resp = await sess.get(url, stream=True, headers=HEADERS)
length = resp.headers.get("content-length")
with open(out, "wb") as f:
process = 0
async for chunk in resp.aiter_content():
if not chunk:
break
process += len(chunk)
print(f"下载 {info} {process} / {length}", end="\r")
f.write(chunk)
print()


async def main():
if not os.path.exists(FES_ID):
os.mkdir(FES_ID)
Expand Down Expand Up @@ -70,20 +52,20 @@ async def download_video(v: video.Video, out: str):
# 有 MP4 流 / FLV 流两种可能
if detecter.check_video_and_audio_stream():
# MP4 流下载
await download_url(streams[0].url, "video_temp.m4s", "视频流")
await download_url(streams[1].url, "audio_temp.m4s", "音频流")
await get_client().download(streams[0].url, HEADERS, "video_temp.m4s", "视频流")
await get_client().download(streams[1].url, HEADERS, "audio_temp.m4s", "音频流")
# 混流
os.system(
f"{FFMPEG_PATH} -i video_temp.m4s -i audio_temp.m4s -vcodec copy -acodec copy {out}"
f"{FFMPEG_PATH} -i video_temp.m4s -i audio_temp.m4s -vcodec copy -acodec copy \"{out}\""
)
# 删除临时文件
os.remove("video_temp.m4s")
os.remove("audio_temp.m4s")
else:
# FLV 流下载
await download_url(streams[0].url, "flv_temp.flv", "FLV 音视频流")
await get_client().download(streams[0].url, HEADERS, "flv_temp.flv", "FLV 音视频流")
# 转换文件格式
os.system(f"{FFMPEG_PATH} -i flv_temp.flv {out}")
os.system(f"{FFMPEG_PATH} -i flv_temp.flv \"{out}\"")
# 删除临时文件
os.remove("flv_temp.flv")

Expand Down
25 changes: 4 additions & 21 deletions docs/examples/video.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ for dm in dms:
```python
import asyncio

import curl_cffi.requests
from bilibili_api import video, Credential, HEADERS, get_session
import curl_cffi
from bilibili_api import video, Credential, HEADERS, get_client
import os

SESSDATA = ""
Expand All @@ -104,21 +102,6 @@ BUVID3 = ""
# FFMPEG 路径,查看:http://ffmpeg.org/
FFMPEG_PATH = "ffmpeg"

async def download_url(url: str, out: str, info: str):
# 下载函数
sess: curl_cffi.requests.AsyncSession = get_session() # 此处使用 curl_cffi
resp = await sess.get(url, stream=True, headers=HEADERS)
length = resp.headers.get('content-length')
with open(out, 'wb') as f:
process = 0
async for chunk in resp.aiter_content():
if not chunk:
break
process += len(chunk)
print(f'下载 {info} {process} / {length}', end="\r")
f.write(chunk)
print()

async def main():
# 实例化 Credential 类
credential = Credential(sessdata=SESSDATA, bili_jct=BILI_JCT, buvid3=BUVID3)
Expand All @@ -132,15 +115,15 @@ async def main():
# 有 MP4 流 / FLV 流两种可能
if detecter.check_flv_stream() == True:
# FLV 流下载
await download_url(streams[0].url, "flv_temp.flv", "FLV 音视频流")
await get_client().download(streams[0].url, HEADERS, "flv_temp.flv", "下载 FLV 音视频流")
# 转换文件格式
os.system(f'{FFMPEG_PATH} -i flv_temp.flv video.mp4')
# 删除临时文件
os.remove("flv_temp.flv")
else:
# MP4 流下载
await download_url(streams[0].url, "video_temp.m4s", "视频流")
await download_url(streams[1].url, "audio_temp.m4s", "音频流")
await get_client().download(streams[0].url, HEADERS, "video_temp.m4s", "下载视频流")
await get_client().download(streams[1].url, HEADERS, "audio_temp.m4s", "下载音频流")
# 混流
os.system(f'{FFMPEG_PATH} -i video_temp.m4s -i audio_temp.m4s -vcodec copy -acodec copy video.mp4')
# 删除临时文件
Expand Down

0 comments on commit 1e7a13d

Please sign in to comment.