107 lines
4.0 KiB
Markdown
107 lines
4.0 KiB
Markdown
# libilibili
|
||
|
||
异步 Rust Bilibili Web/直播 API 库,依据 [feliscafra/Bilibili-Live-API](https://github.com/feliscafra/Bilibili-Live-API) 的接口、鉴权与 WebSocket 文档实现。
|
||
|
||
## 功能
|
||
|
||
- 公开 GET、WBI GET、Cookie GET、带 CSRF 的 Cookie POST,以及 WBI+POST。
|
||
- 从 `/x/web-interface/nav` 自动刷新和缓存 WBI key;参数排序、清洗、percent-encode、MD5 签名均在库内完成。
|
||
- 登录 Cookie 存在内存;状态变更请求自动写入 `csrf` 与 `csrf_token`(取自 `bili_jct`)。
|
||
- 高层分组:直播间/分区/播放/礼物/勋章、视频、空间与关系、评论、搜索。
|
||
- 默认 `websocket` feature:直播弹幕认证、心跳和 JSON/zlib/brotli 协议包解析,并只连接 `*.chat.bilibili.com`。
|
||
- 使用通用请求方法覆盖参考文档中尚未提供快捷封装的低频或易变端点。
|
||
|
||
## 使用
|
||
|
||
```toml
|
||
[dependencies]
|
||
libilibili = "0.1"
|
||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||
```
|
||
|
||
```rust,no_run
|
||
use libilibili::{Client, Credentials};
|
||
|
||
#[tokio::main]
|
||
async fn main() -> Result<(), libilibili::Error> {
|
||
let anonymous = Client::anonymous()?;
|
||
let room = anonymous.live().room_detail(5050).await?; // 自动 WBI
|
||
println!("{room:#}");
|
||
|
||
let auth = Credentials::from_cookie_header("SESSDATA=...; bili_jct=...");
|
||
let client = Client::with_credentials(auth)?;
|
||
client.video().like(170001, true).await?; // 自动 csrf + csrf_token
|
||
Ok(())
|
||
}
|
||
```
|
||
|
||
不需要 WebSocket:
|
||
|
||
```toml
|
||
libilibili = { version = "0.1", default-features = false }
|
||
```
|
||
|
||
## 通用端点调用与鉴权
|
||
|
||
| 鉴权类型 | 方法 |
|
||
| --- | --- |
|
||
| Public GET | `client.get(url, query)` |
|
||
| WBI GET | `client.get_wbi(url, query)` |
|
||
| Cookie POST | `client.post_form(url, form)` |
|
||
| Cookie + WBI POST | `client.post_form_wbi(url, query, form)` |
|
||
|
||
`query`/`form` 是 `Vec<(String, String)>`;响应的 `data` 为泛型,快捷方法默认保留为 `serde_json::Value`,防止上游新增字段时信息丢失。
|
||
|
||
```rust,no_run
|
||
# use libilibili::Client;
|
||
# async fn example(client: Client) -> Result<(), libilibili::Error> {
|
||
let history: serde_json::Value = client.get(
|
||
"https://api.live.bilibili.com/xlive/web-room/v1/dM/gethistory",
|
||
vec![("roomid".into(), "5050".into()), ("room_type".into(), "0".into())],
|
||
).await?;
|
||
# Ok(()) }
|
||
```
|
||
|
||
## 弹幕 WebSocket
|
||
|
||
```rust,no_run
|
||
use libilibili::{Client, Credentials, websocket::LiveWebSocket};
|
||
|
||
# async fn example() -> Result<(), libilibili::Error> {
|
||
let credentials = Credentials::from_cookie_header("SESSDATA=...; bili_jct=...; buvid3=...");
|
||
let client = Client::with_credentials(credentials)?;
|
||
let mut ws = LiveWebSocket::connect(&client, 5050).await?;
|
||
ws.heartbeat().await?; // 应约每 30 秒调用
|
||
while let Some(event) = ws.next_event().await? { println!("{event:?}"); }
|
||
# Ok(()) }
|
||
```
|
||
|
||
## 原始帧抓取
|
||
|
||
`libilibili-capture` 可连接一个已登录的直播间,并将收到的**原始 WebSocket 二进制帧**
|
||
写为 stdout 的 JSON Lines;连接状态与心跳日志只写入 stderr。每条输出含完整
|
||
`frame_base64`,以及未解压协议包的版本、操作码和 `body_base64`,便于离线复现协议
|
||
解析。
|
||
|
||
```sh
|
||
cargo run --bin libilibili-capture -- \
|
||
--cookie 'SESSDATA=...; bili_jct=...; buvid3=...' \
|
||
--room-id 5050 \
|
||
--seconds 120 \
|
||
> frames.jsonl
|
||
```
|
||
|
||
更安全的方式是通过标准输入提供 Cookie:
|
||
|
||
```sh
|
||
printf '%s' "$BILI_COOKIE" | cargo run --bin libilibili-capture -- \
|
||
--cookie-stdin --room-id 5050 --seconds 120 > frames.jsonl
|
||
```
|
||
|
||
Cookie 不会被工具输出,但命令行参数可能被同机其他用户读取;在共享机器上应使用
|
||
`--cookie-stdin`、受限权限的启动器或 secret 管理器注入 Cookie。
|
||
|
||
## 安全边界
|
||
|
||
本库不自动化密码、验证码、二维码或 OAuth 登录,也不尝试绕过风控。通过 Bilibili 正常登录取得会话后,使用环境变量或 secret store 注入 `SESSDATA`/`bili_jct`;绝不要提交或记录这些值。`-352` 代表风控/上下文限制,不等价于接口下线。
|