Add your description here
Project description
RiotManifest
riot提供的manifest文件进行解析下载
介绍
目前支持传入 URL 或本地文件路径,解析 manifest 并下载文件。
大部分代码都来自于CommunityDragon/CDTB项目,感谢他们的工作。
当前下载链路默认走全局并发下载(推荐),并支持:
- 按
ChunkID全局去重,避免重复下载与重复解压 - 按 Bundle 聚合与 multi-range 请求,减少 HTTP 往返
- 文件句柄池按偏移写入,降低 open/close 开销
- chunk 解压后哈希校验(
param_index -> hash_type)
默认并发数为 16,可通过 PatcherManifest(..., concurrency_limit=...) 调整,也可在调用 download_files_concurrently 时临时覆盖。
当前主要模块划分:
riotmanifest.core:解析与错误等核心能力(binary_parser/chunk_hash/errors)riotmanifest.downloader:下载调度与写盘句柄池(scheduler/file_pool)riotmanifest.extractor:WAD 按需提取(wad_extractor)riotmanifest.utils:HTTP 客户端等通用工具riotmanifest.game:游戏元数据加载与 Extractor 构造
安装
pip3 install riotmanifest
使用
- 异步并发下载(推荐,默认并发 16)
import asyncio
from riotmanifest import PatcherManifest
async def main():
bundle_url = 'https://lol.dyn.riotcdn.net/channels/public/bundles/'
manifest = PatcherManifest(
r"https://lol.secure.dyn.riotcdn.net/channels/public/releases/CB3A1B2A17ED9AAB.manifest",
path=r'E:\out',
bundle_url=bundle_url)
# 推荐:先按语言与文件名过滤后再下载
files = list(manifest.filter_files(flag='zh_CN', pattern='wad.client'))
# 不传 concurrency_limit 时,使用 manifest 默认并发(16)
await manifest.download_files_concurrently(files)
if __name__ == '__main__':
asyncio.run(main())
-
如果你的网络/磁盘较弱,可把并发改到
8~12; -
如果机器配置较好且网络稳定,可尝试
16~24并发。 -
下载进度与速度监控(时间周期 + 每个 Bundle Job)
import asyncio
from riotmanifest import DownloadProgress, PatcherManifest
def on_progress(progress: DownloadProgress) -> None:
speed_mb = progress.average_speed_bytes_per_sec / (1024 * 1024)
print(
f"[{progress.phase}] "
f"jobs={progress.finished_jobs}/{progress.total_jobs} "
f"bytes={progress.finished_bytes}/{progress.total_bytes} "
f"speed={speed_mb:.2f}MB/s "
f"bundle={progress.bundle_id}"
)
async def main():
manifest = PatcherManifest(
"https://lol.secure.dyn.riotcdn.net/channels/public/releases/CB3A1B2A17ED9AAB.manifest",
path="./out",
)
files = list(manifest.filter_files(flag="zh_CN", pattern="wad.client"))
await manifest.download_files_concurrently(
files,
progress_callback=on_progress,
progress_interval_seconds=1.0, # 每 1 秒发一次 tick,同时保留每个 bundle 事件
)
if __name__ == "__main__":
asyncio.run(main())
性能基线(2026-03-02)
以下结果来自仓库内真实网络集成测试(同一日期,不同样本规模):
RIOT_PERF_RUN=1 uv run pytest -q -s tests/test_manifest_download_speed.py
结果一:常规压力样本(EUW1,默认并发 16,优先筛选 filter_files(flag='zh_CN', pattern='wad.client')):
- manifest:
https://lol.secure.dyn.riotcdn.net/channels/public/releases/BA80B75282F55531.manifest - 样本:
files=92,planned=515.14MB - 吞吐:
63.61MB/s(elapsed=8.098s) - 调度:
jobs=126,ranges=142,unique_chunks=1410
结果二:全量中文 wad.client 传输层对比样本(并发 16):
RIOT_TRANSPORT_BENCH_RUN=1 RIOT_TRANSPORT_MODE=both uv run pytest -q -s tests/test_downloader_transport_compare.py
- manifest:
https://lol.secure.dyn.riotcdn.net/channels/public/releases/BA80B75282F55531.manifest - 样本:
files=212,planned=3605.73MB(全量zh_CN + wad.client) aiohttp吞吐:117.51MB/s(elapsed=30.685s)urllib3吞吐:113.00MB/s(elapsed=31.910s)- 速度比:
urllib3 / aiohttp = 0.962
结论:
-
吞吐会受网络波动明显影响,单次结果有起伏。
-
在当前下载策略(chunk 去重 + bundle job + multi-range)和当前环境下,已可基本跑满带宽。
-
传输层上
aiohttp与urllib3差距不大,当前实测aiohttp略优。 -
WADExtractor
from riotmanifest import PatcherManifest
from riotmanifest.extractor import WADExtractor
manifest = PatcherManifest("DE515F568F4D9C73.manifest", path="")
we = WADExtractor(manifest)
data = we.extract_files(
{
"DATA/FINAL/Champions/Aatrox.wad.client": [
"data/characters/aatrox/skins/skin0.bin",
"data/characters/aatrox/skins/skin1.bin",
"data/characters/aatrox/skins/skin2.bin",
"data/characters/aatrox/skins/skin3.bin",
],
"DATA/FINAL/Champions/Ahri.wad.client": [
"data/characters/Ahri/skins/skin0.bin",
"data/characters/Ahri/skins/skin1.bin",
"data/characters/Ahri/skins/skin2.bin",
"data/characters/Ahri/skins/skin3.bin",
]
}
)
print(len(data))
该方法无需下载完整WAD文件,直接从manifest中计算需要解包的文件位置,直接获取,减少网络请求。
注意事项:
- 该方式适合“少量小文件按需提取”。
- 当单个 WAD 需要提取的目标文件很多时,不建议继续使用按需提取(请求和偏移计算成本会明显上升)。
- 当前提取器已内置小文件批量优化(chunk 受限并发预取),但超出建议数量时会自动跳过预取并告警。
- 大批量提取建议改为:先下载完整 WAD,再本地解包处理。
可按需调整预取参数:
we = WADExtractor(
manifest,
prefetch_chunk_concurrency=6, # 批量提取时的 chunk 预取并发
recommended_max_targets_per_wad=120, # 单个 WAD 的建议目标文件上限
)
可选:直接写入磁盘,避免在调用方持有大量 bytes:
outputs = we.extract_files_to_disk(
{
"DATA/FINAL/Maps/Shipping/Map11/Map11.wad.client": [
"data/maps/shipping/map11/map11.bin",
]
},
output_dir="./out_wad",
)
print(outputs)
- RiotGameData(显式构造 Extractor)
from riotmanifest.game import RiotGameData
rgd = RiotGameData()
rgd.load_game_data(regions=["EUW1"])
# 不再在 load_game_data 中隐式创建 WADExtractor,改为按需显式构造
game_extractor = rgd.build_game_extractor("EUW1", cache_max_entries=256, manifest_path="")
维护者
Virace
感谢
-
@CommunityDragon, CDTB
-
以及JetBrains提供开发环境支持
许可证
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file riotmanifest-2.0.0.tar.gz.
File metadata
- Download URL: riotmanifest-2.0.0.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dece8b649d20c1fc3ff50d36f4544da30a08c0fdc697626b0ab794d47b04d851
|
|
| MD5 |
a0371e331e599408772d83b12973d5d5
|
|
| BLAKE2b-256 |
daccfb34b6f69d6bc4c927136b8c76304bdb5d9b7c1ec0a9f8b70b02f22d484b
|
Provenance
The following attestation bundles were made for riotmanifest-2.0.0.tar.gz:
Publisher:
python-publish.yml on Virace/RiotManifest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
riotmanifest-2.0.0.tar.gz -
Subject digest:
dece8b649d20c1fc3ff50d36f4544da30a08c0fdc697626b0ab794d47b04d851 - Sigstore transparency entry: 1008417997
- Sigstore integration time:
-
Permalink:
Virace/RiotManifest@97ecaa290c1e581ea9264272c902427c77184466 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/Virace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@97ecaa290c1e581ea9264272c902427c77184466 -
Trigger Event:
release
-
Statement type:
File details
Details for the file riotmanifest-2.0.0-py3-none-any.whl.
File metadata
- Download URL: riotmanifest-2.0.0-py3-none-any.whl
- Upload date:
- Size: 47.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0fa828fc0902820ffe62896bc512b7ec12f58381bc760fd9790ee0af6f5da23
|
|
| MD5 |
824f622a77624c7a4ade253ad2b62c15
|
|
| BLAKE2b-256 |
2294bd54c2bf87d36b1838a7cc440472bf48eda8227dc7ba7030bd08673fc7fb
|
Provenance
The following attestation bundles were made for riotmanifest-2.0.0-py3-none-any.whl:
Publisher:
python-publish.yml on Virace/RiotManifest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
riotmanifest-2.0.0-py3-none-any.whl -
Subject digest:
f0fa828fc0902820ffe62896bc512b7ec12f58381bc760fd9790ee0af6f5da23 - Sigstore transparency entry: 1008418003
- Sigstore integration time:
-
Permalink:
Virace/RiotManifest@97ecaa290c1e581ea9264272c902427c77184466 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/Virace
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@97ecaa290c1e581ea9264272c902427c77184466 -
Trigger Event:
release
-
Statement type: