本文档详细阐述 Media Parser 的内部架构分层、请求处理生命周期、工厂模式插件化发现机制以及数据响应标准。
项目遵循模块化、高内聚、低耦合的设计原则,自底向上分为以下四层:
flowchart TD
Client["客户端 / Web体验页 / API调用者"]
subgraph WebLayer["1. Web 接入层 (app.py & src/api/)"]
App["Flask App / 路由"]
ParseAPI["POST /api/parse"]
HealthAPI["GET /api/health"]
end
subgraph CoreLayer["2. 调度与解析引擎 (Core Engine)"]
UrlParser["UrlParser (正则提取/平台识别)"]
WebFetcher["WebFetcher (302重定向追踪)"]
Factory["ParserFactory (动态发现与分发)"]
end
subgraph ParserLayer["3. 平台解析器层 (src/parsers/)"]
BaseParser["BaseParser (基类/Session管理)"]
Douyin["DouyinParser"]
Kuaishou["KuaishouParser"]
XHS["XiaohongshuParser"]
Bili["BilibiliParser"]
Others["... 30+ 其它解析器"]
end
subgraph UtilLayer["4. 工具与逆向支持 (utils/ & configs/)"]
Signer["BogusSigner (mini-racer JS执行)"]
Logger["LoggingConfig"]
CommonUtils["make_response 标准化响应"]
end
Client --> App
App --> ParseAPI
ParseAPI --> UrlParser
ParseAPI --> WebFetcher
ParseAPI --> Factory
Factory --> BaseParser
BaseParser --> Douyin
BaseParser --> Kuaishou
BaseParser --> XHS
BaseParser --> Bili
BaseParser --> Others
Douyin --> Signer
ParseAPI --> CommonUtils
media-parser/
├── app.py # 应用入口 (Flask Web 服务与 API 启动)
├── configs/ # 核心配置 (域名平台映射、日志配置等)
├── docs/ # 逆向百科与开发文档体系
│ ├── architecture.md # 系统分层架构与生命周期设计
│ ├── reverse-guide.md # 通用逆向方法论 (抓包/SSR/JS签名提取)
│ ├── testing.md # 完整测试规范与回归手册
│ └── parsers/ # 平台逆向分析手册
├── src/ # 核心业务逻辑
│ ├── api/ # RESTful API 路由 (/api/parse, /api/health)
│ ├── web/ # Demo 体验页与交互蓝图
│ ├── parsers/ # 各平台解析器模块 (核心解析逻辑)
│ └── parser_factory.py # 工厂分发器 (解析器动态发现与自动注册)
├── utils/ # 底层工具库与逆向支持
│ ├── signer/ # JS 签名沙箱引擎 (a_bogus 等算法执行)
│ └── web_fetcher.py # 智能 URL 识别、重定向追踪与请求封装
├── tests/ # 完备的双层测试体系
│ ├── live_parser_samples.json # 平台真实多形态在线样本库
│ ├── manual_verify_parsers.py # 命令行交互式冒烟与健康检查工具
│ └── test_*_parser.py # 各平台 Mock 自动化单元测试
├── static/ & templates/ # Web 演示页面前端静态资源
└── docker-compose.yml # 容器化一键部署编排
当客户端向 /api/parse 发送一段包含分享文案的文本时,完整处理流如下:
sequenceDiagram
autonumber
actor User as 客户端 (Client)
participant API as /api/parse
participant Fetcher as WebFetcher & UrlParser
participant Factory as ParserFactory
participant Parser as Platform Parser (如 DouyinParser)
participant Output as Response Formatter
User->>API: POST {"text": "7.22 复制打开抖音... https://v.douyin.com/xxx/"}
API->>Fetcher: UrlParser.get_url(text) 提取原始链接
API->>Fetcher: WebFetcher.fetch_redirect_url(url) 追踪302重定向
Fetcher-->>API: 返回落地真实URL (Real URL)
API->>Fetcher: UrlParser.get_platform(real_url) 识别平台名称
API->>Factory: ParserFactory.create_parser(platform, real_url)
Factory-->>API: 实例化对应平台解析器
API->>Parser: 执行抓取 (_fetch_with_retry)
Note over Parser: 提取标题、视频直链、图集、LivePhoto、音频等
Parser-->>API: 返回原始抓取字典 content_data
API->>Output: UrlParser.convert_to_https 统一转 HTTPS
API->>Output: make_response(200, '成功', data_dict)
Output-->>User: 返回标准 JSON 结构
为了便于扩展和多人协作,解析器采用 装饰器自动注册 + 模块自动发现机制:
src/parser_factory.py 会在模块载入时利用 pkgutil.iter_modules 自动扫描并动态 import src/parsers/ 下所有除 base_parser 以外的 Python 模块。
新增任何平台解析器时,无需修改任何工厂类核心代码,只需继承 BaseParser 并加上装饰器:
from src.parser_factory import register_parser
from src.parsers.base_parser import BaseParser
@register_parser("示例平台", "示例平台别名")
class ExampleParser(BaseParser):
def __init__(self, real_url):
super().__init__(real_url)
# 初始化与数据提取
def get_real_video_url(self):
return "https://..."所有解析接口均通过 utils/common_utils.py 中的 make_response 返回一致的 JSON 响应体。
{
"code": 200,
"msg": "成功",
"data": {
"platform": "抖音",
"video_id": "7616399587141737704",
"title": "视频文案标题",
"video_url": "https://aweme.snssdk.com/aweme/v1/play/...",
"cover_url": "https://p3-pc.douyinpic.com/...",
"author": {
"nickname": "创作者昵称",
"author_id": "unique_id_123",
"avatar": "https://p3.douyinpic.com/..."
},
"audio_url": "https://sf6-cdn-tos.douyinstatic.com/...",
"image_list": [
{
"url": "https://p3-pc.douyinpic.com/image1.jpeg",
"live_photo_url": "https://aweme.snssdk.com/aweme/v1/play/live_photo.mp4"
}
],
"video_list": []
},
"success": true
}{
"code": 400,
"msg": "未找到有效的分享链接",
"data": null,
"success": false,
"error_code": "URL_NOT_FOUND"
}