Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get_short_url to generate the b23.tv url from the bilibili.com url #720

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bilibili_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .utils.sync import sync
from .utils.credential_refresh import Credential
from .utils.picture import Picture
from .utils.short import get_real_url
from .utils.short import get_real_url, get_short_url
from .utils.parse_link import ResourceType, parse_link
from .utils.aid_bvid_transformer import aid2bvid, bvid2aid
from .utils.danmaku import DmMode, Danmaku, DmFontSize, SpecialDanmaku
Expand Down Expand Up @@ -135,6 +135,7 @@
"game",
"get_aiohttp_session",
"get_real_url",
"get_short_url",
"get_session",
"homepage",
"hot",
Expand Down
140 changes: 135 additions & 5 deletions bilibili_api/utils/short.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,158 @@

一个很简单的处理短链接的模块,主要是读取跳转链接。
"""

from typing import Optional

from .. import settings
from .credential import Credential
from .network import get_session, get_aiohttp_session
from .network import get_session, get_aiohttp_session, get_spi_buvid, HEADERS
from ..exceptions import ApiException, ArgsException

import re
import random
import string


async def acquire_buvid(credential: Optional[Credential] = None) -> str:
"""
从Credential中取出buvid3,若不存在则通过spi获取buvid,若都不存在则随机生成一个的buvid3。

Args:
credential(Credential | None): 凭据类。

Returns:
buvid3的字符串
"""

# return given buvid3 if possible
if credential:
buvid3 = credential.get_cookies()["buvid3"]

if buvid3 is not None:
return buvid3

# use spi to get buvid3
try:
return (await get_spi_buvid())["data"]["b_3"]

except KeyError: # if data or b_3 does not exist by spi
pass

# random generation if spi is not possible
buvid3_pattern = (
"8-4-4-4-17" # current buvid3 char-length pattern, might be changed later
)
parts = buvid3_pattern.split("-")

buvid3_rand_gen = [
"".join(random.choices(string.digits + string.ascii_letters, k=int(part)))
for part in parts
]

return "-".join(buvid3_rand_gen) + "infoc"


async def get_short_url(
oid: Optional[int] = None,
share_content: Optional[str] = None,
share_title: Optional[str] = None,
share_origin: Optional[str] = "vinfo_share",
share_mode: Optional[int] = 3,
share_id: Optional[str] = "public.webview.0.0.pv",
platform: Optional[str] = "android",
mobi_app: Optional[str] = "android",
panel_type: Optional[int] = 1,
# regex_real_url: Optional[bool] = False,
credential: Optional[Credential] = None,
) -> str:
"""
获取目标链接的短链接。支持 bilibili.com 的相关链接。

尽管目标链接可能不存在,但仍然会生成短链接。

相同的目标链接重复调用此方法会获得不同的短链接。

async def get_real_url(short_url: str, credential: Optional[Credential] = None) -> str:
Args:
oid (int | None): 内容 oid。

share_content (str | None): 分享内容。

share_title (str | None): 分享标题。

share_origin (str | None): 分享来源。

share_mode (int | None): 分享模式。

share_id (str | None): 分享 id。

platform (str | None): 平台。

mobi_app (str | None): 移动端应用。

panel_type (int | None): 面板类型。

credential (Credential | None): 凭据类。

Returns:
str: 目标链接的 b23.tv 短链接信息 (不一定为单独 URL)
"""
# 应该具体为检测 oid 类型
# if regex_real_url:
# # validate the starting part of url
# url_start_pattern = re.compile(pattern=r"^https?:\/\/(?:www\.)?bilibili\.com")

# if not re.match(pattern=url_start_pattern, string=share_content):
# raise ArgsException(
# msg=f"提供的 {share_content} 不符合格式。\
# 支持的格式为 bilibili.com 的相关链接并含有 http 或 https 协议。"
# )

post_data = {
"build": 7300400,
"buvid": await acquire_buvid(credential=credential),
"oid": oid,
"share_title": share_title,
"share_content": share_content,
"share_origin": share_origin,
"mobi_app": mobi_app,
"panel_type": panel_type,
"platform": platform,
"share_id": share_id,
"share_mode": share_mode,
}

api_url = "https://api.biliapi.net/x/share/click"

if settings.http_client == settings.HTTPClient.HTTPX:
resp_content = (
await get_session().post(url=api_url, headers=HEADERS, data=post_data)
).json()
else:
resp = await get_aiohttp_session().post(
url=api_url, data=post_data, headers=HEADERS
)
resp_content = await resp.json()

# the 'content' sometimes will not be in the returned content due to build version, real_url, or buvid (rarely)
if "content" not in resp_content["data"]:
raise ApiException(msg="生成短链接失败。")

return resp_content["data"]["content"]


async def get_real_url(short_url: str) -> str:
"""
获取短链接跳转目标,以进行操作。

Args:
short_url(str): 短链接。

credential(Credential \| None): 凭据类。

Returns:
目标链接(如果不是有效的链接会报错)

返回值为原 url 类型
"""
credential = credential if credential else Credential()

try:
if settings.http_client == settings.HTTPClient.HTTPX:
Expand Down
9 changes: 8 additions & 1 deletion docs/b23tv.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

bilibili_api 从 10.0.0 开始支持短链接了(说白了就是支持查看短链目标了)

获取默认链接(长链接)的短链接
``` python
from bilibili_api import get_short_url, sync
print(sync(get_short_url(real_url="https://www.bilibili.com/video/BV18X4y1N7Yh/"))) # optionally pass in Credential
```

获取短链接的对应默认链接(长链接)
``` python
from bilibili_api import get_real_url, sync
print(sync(get_real_url("https://b23.tv/mx00St"))) # https://www.bilibili.com/video/BV1YQ4y127Rd?p=1&share_medium=android&share_plat=android&share_session_id=d6c56bd5-db84-4cc8-9bb7-8f91cd8edfe0&share_source=COPY&share_tag=s_i&timestamp=1629155789&unique_k=mx00St
print(sync(get_real_url(short_url="https://b23.tv/mx00St"))) # https://www.bilibili.com/video/BV1YQ4y127Rd?p=1&share_medium=android&share_plat=android&share_session_id=d6c56bd5-db84-4cc8-9bb7-8f91cd8edfe0&share_source=COPY&share_tag=s_i&timestamp=1629155789&unique_k=mx00St
```
14 changes: 13 additions & 1 deletion docs/modules/bilibili_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,24 @@ BV 号转 AV 号。

---

## async def get_short_url()

| name | type | description |
|------------|---------------------|-------------|
| real_url | str | 真实链接 |
| credential | Optional[Credential] | 凭据类. |

获取bilibili真实链接对应的短链接。

**注意:** 这个函数对于同一个真实链接的每一次调用都会返回不同的短链接。并且,请注意短链接也会包含你的分享信息(因为会redirect)。

**Returns:** b23.tv的短链接

## async def get_real_url()

| name | type | description |
| - | - | - |
| short_url | str | 短链接 |
| credential | Optional[Credential] | 凭据类. |

获取短链接对应的真实链接。

Expand Down