Skip to content

Commit

Permalink
feat: support downloading video collections (#15)
Browse files Browse the repository at this point in the history
* feat: add download seasons(video collection)

* feat: add download season command

* feat: create additional folder in season mode

* doc: add doc for season mode

* doc: keep trailing whitespace

* chore: improve season error msg
  • Loading branch information
robo-dani committed Mar 23, 2024
1 parent 1923f58 commit cc92402
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ cookies 的获取:

- cookies 转换为json:[在线 cookies 转换](https://uutool.cn/cookie2json/)

### season 模式
下载视频合集
```bash
bilifm season $uid $sid [OPTIONS]
```
- uid, sid 的获取:
打开视频合集网页, 从URL中获取

https://space.bilibili.com/23263470/channel/collectiondetail?sid=1855309

例如上面链接, uid为23263470, sid为1855309. (目前uid可以随意填写)
- Options:
- -o, --directory 选择音频保存地址



## Features

- ~~python 版本限制未知~~
Expand Down
29 changes: 29 additions & 0 deletions src/bilifm/command.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import os

import typer
from typing_extensions import Annotated

from .audio import Audio
from .fav import Fav
from .season import Season
from .user import User

app = typer.Typer()
Expand Down Expand Up @@ -37,3 +41,28 @@ def fav(media_id: str, cookies_path: str):
audio.download()

typer.echo("Download complete")


@app.command()
def season(
uid: str,
sid: str,
directory: Annotated[str, typer.Option("-o", "--directory")] = "",
):
sea = Season(uid, sid)
ret = sea.get_videos()
if not ret:
typer.Exit(1)
return

if directory:
os.chdir(directory)

if not os.path.isdir(sea.name):
os.makedirs(sea.name)
os.chdir(sea.name)

for id in sea.videos:
audio = Audio(id)
audio.download()
typer.echo("Download complete")
58 changes: 58 additions & 0 deletions src/bilifm/season.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""download bilibili season archive, 视频合集下载"""

import typer

from .util import request


class Season:
# api refer https://github.com/SocialSisterYi/bilibili-API-collect/blob/f9ee5c3b99335af6bef0d9d902101c565b3bea00/docs/video/collection.md
season_url: str = (
"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list"
)

def __init__(self, uid: str, sid: str, page_size=30) -> None:
self.uid = uid
self.season_id = sid
self.page_size = page_size
self.videos = []

def get_videos(self):
params = {
"mid": self.uid,
"season_id": self.season_id,
"sort_reverse": False,
"page_num": 1,
"page_size": self.page_size,
}

res = request(
method="get", url=self.season_url, params=params, wbi=True, dm=True
).json()

code = res.get("code", -404)
if code != 0:
# uid 错误好像无影响
if code == "-404":
typer.echo(f"Error: uid {self.uid} or sid {self.season_id} error.")
else:
type.echo("Error: unknown error")
typer.echo(f"code: {res['code']}")
if res.get("message", None):
typer.echo(f"msg: {res['message']}")
return False

self.total = res["data"]["meta"]["total"]
self.name = res["data"]["meta"]["name"]

max_pn = self.total // 50
for i in range(1, max_pn + 2):
params["page_num"] = i

res = request(
method="get", url=self.season_url, params=params, wbi=True, dm=True
).json()
bvids = [d["bvid"] for d in res["data"]["archives"]]
self.videos.extend(bvids)

return True

0 comments on commit cc92402

Please sign in to comment.