140 lines
6.5 KiB
Markdown
140 lines
6.5 KiB
Markdown
# 低端影视 (DDYS Client)
|
||
|
||
原生 SwiftUI 客户端,用于浏览 [ddys.io](https://ddys.io) 影视资源,支持 macOS / iPadOS / iOS。
|
||
|
||
## 功能
|
||
|
||
- **首页推荐** — 热门推荐横向滚动 + 最新更新网格展示
|
||
- **分类浏览** — 电影、电视剧、综艺、动漫四大板块,支持排序 / 类型 / 地区 / 年份筛选
|
||
- **全局搜索** — 首页搜索栏,回车触发,支持分页加载更多
|
||
- **详情页** — 海报、评分、年份、地区、类型标签、剧情简介、导演、主演
|
||
- **在线播放** — HLS (m3u8) 原生播放,多播放源切换,剧集选择
|
||
- **播放器** — macOS 独立窗口(可调整大小、全屏),iOS 全屏播放,支持倍速、画中画
|
||
- **观看进度** — 自动保存 / 恢复播放进度
|
||
- **图片缓存** — 双层缓存(NSCache 内存 + URLCache 磁盘),切换页面秒加载
|
||
- **数据缓存** — Tab 切换保留数据,5 分钟 TTL 自动刷新
|
||
- **认证支持** — WebView 登录 或 手动 Cookie 输入
|
||
|
||
## 技术栈
|
||
|
||
| 项目 | 选型 |
|
||
|------|------|
|
||
| UI 框架 | SwiftUI (iOS 17+ / macOS 14+) |
|
||
| HTML 解析 | [SwiftSoup](https://github.com/scinfu/SwiftSoup) 2.6.1 (本地包,零外部依赖) |
|
||
| 视频播放 | AVKit (AVPlayerView / AVPlayerViewController) |
|
||
| 网络请求 | URLSession |
|
||
| 数据解析 | JSON-LD + SwiftSoup CSS 选择器 |
|
||
| 持久化 | UserDefaults |
|
||
| 导航 | NavigationSplitView (Mac/iPad) / TabView (iPhone) |
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
DDYSClient/
|
||
├── App/ # 入口 & 根视图
|
||
├── Models/ # 数据模型 (ContentItem, Episode, StreamSource...)
|
||
├── Services/ # 网络层 & 业务服务
|
||
│ ├── APIClient.swift # URLSession 请求封装
|
||
│ ├── HTMLParser.swift # SwiftSoup 解析列表/详情/分页
|
||
│ ├── CookieManager.swift # Cookie 存储与注入
|
||
│ ├── ContentCache.swift # 数据缓存 (5min TTL)
|
||
│ └── WatchProgressStore.swift # 观看进度持久化
|
||
├── ViewModels/ # MVVM ViewModel (@Observable)
|
||
├── Views/
|
||
│ ├── Navigation/ # 平台自适应导航
|
||
│ ├── Home/ # 首页 + 搜索
|
||
│ ├── Browse/ # 分类浏览 + 筛选
|
||
│ ├── Detail/ # 详情页 + 剧集列表
|
||
│ ├── Player/ # 视频播放器
|
||
│ ├── Common/ # 通用组件 (CachedAsyncImage)
|
||
│ ├── Auth/ # 认证 (WebView / Cookie 输入)
|
||
│ ├── Search/ # 搜索页
|
||
│ └── Settings/ # 设置页
|
||
└── Utilities/ # 通用扩展
|
||
```
|
||
|
||
## 数据获取原理
|
||
|
||
ddys.io 是一个服务端渲染 (SSR) 的网站,没有提供公开的 REST API(仅有少量内部接口)。本客户端通过**模拟浏览器请求网页 + 解析 HTML** 的方式获取数据,整体流程如下:
|
||
|
||
### 1. 列表页 & 分类浏览
|
||
|
||
客户端直接以 GET 请求访问网站的 HTML 页面(如 `/movie`、`/series/page/2`),携带浏览器 User-Agent 和 Referer 头以通过服务端校验。返回的 HTML 经 SwiftSoup 解析,通过 CSS 选择器(如 `.movie-card`、`h3 a`、`.badge-top-right`)提取标题、海报、评分、年份等结构化数据。分页信息从页面底部的 `.pagination-active` 和 `.pagination-btn` 元素中解析得到。
|
||
|
||
### 2. 详情页
|
||
|
||
详情页同样请求对应路径的 HTML(如 `/movie/slug`)。页面内嵌了 `<script type="application/ld+json">` 结构化数据,包含导演、演员、类型、评分、简介等信息,客户端优先从 JSON-LD 提取。对于 JSON-LD 中缺失的字段(如地区、播放源),再 fallback 到 HTML 元素解析。
|
||
|
||
### 3. 播放源 & 剧集
|
||
|
||
播放源信息嵌入在详情页 HTML 的 `<button onclick="switchSource(...)">` 属性中,通过正则表达式提取源 ID、视频地址和格式。剧集列表以 `集名$url#集名$url` 的格式编码在 URL 字符串中,按 `#` 和 `$` 分隔解析出每集的名称和 m3u8 播放地址。视频播放直接使用 AVKit 原生 HLS 支持。
|
||
|
||
### 4. 搜索
|
||
|
||
搜索通过 GET 请求 `/search?q=关键词&type=all` 实现(网站前端使用 POST 表单提交后 302 重定向到此 GET 地址)。返回的 HTML 结构与列表页一致,复用同一套解析逻辑。
|
||
|
||
### 5. 认证
|
||
|
||
网站使用 Cloudflare Turnstile 验证码保护,原生客户端无法自动完成验证。因此提供两种方式:通过内嵌 WKWebView 让用户在网页中完成登录后自动提取 Cookie,或由用户从浏览器手动复制 Cookie 粘贴到应用中。Cookie 注入到 URLSession 的 HTTPCookieStorage 后,后续所有请求自动携带认证信息。
|
||
|
||
```
|
||
┌─────────┐ GET HTML ┌──────────┐ SwiftSoup ┌──────────┐
|
||
│ Client │ ───────────────→ │ ddys.io │ ──────────────→ │ Models │
|
||
│ (App) │ ← HTML response │ (SSR) │ CSS解析/正则 │ (Swift) │
|
||
└─────────┘ └──────────┘ JSON-LD提取 └──────────┘
|
||
│ │
|
||
│ m3u8 URL │
|
||
└──────────────────────────────────────→ AVPlayer (HLS播放) │
|
||
```
|
||
|
||
## 构建 & 运行
|
||
|
||
### 环境要求
|
||
|
||
- macOS 14.0+
|
||
- Swift 5.9+
|
||
- Xcode 15+ (或 Swift 命令行工具)
|
||
|
||
### 命令行构建
|
||
|
||
```bash
|
||
# Debug
|
||
swift build
|
||
|
||
# Release
|
||
swift build -c release
|
||
```
|
||
|
||
### 打包为 .app
|
||
|
||
```bash
|
||
# 构建 Release
|
||
swift build -c release
|
||
|
||
# 复制到 app bundle
|
||
cp "$(swift build -c release --show-bin-path)/DDYSClient" /path/to/DDYSClient.app/Contents/MacOS/DDYSClient
|
||
```
|
||
|
||
### 安装
|
||
|
||
```bash
|
||
cp -R DDYSClient.app /Applications/低端影视.app
|
||
```
|
||
|
||
## 使用说明
|
||
|
||
1. 启动应用后首页自动加载热门推荐和最新更新
|
||
2. 通过左侧边栏切换 电影 / 电视剧 / 综艺 / 动漫
|
||
3. 使用顶部筛选栏按 排序 / 类型 / 地区 / 年份 过滤内容
|
||
4. 首页搜索栏输入关键词,按回车搜索
|
||
5. 点击卡片进入详情页,点击「立即播放」打开播放器窗口
|
||
6. 如需登录,在 设置 → 认证 中通过 WebView 或手动输入 Cookie
|
||
|
||
## 依赖
|
||
|
||
- [SwiftSoup 2.6.1](https://github.com/scinfu/SwiftSoup/tree/2.6.1) — HTML 解析 (本地包,无网络依赖)
|
||
|
||
## License
|
||
|
||
MIT
|