# 1212
**Repository Path**: Rthree/1212
## Basic Information
- **Project Name**: 1212
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-28
- **Last Updated**: 2026-09-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 知乎阅读器(ZhihuSaver)
一个基于 **Python + PySide6 + Qt WebEngine** 的桌面知乎阅读器(参考 zreader 的
「阅读 + 归档 + 分类」思路):内嵌浏览器直接浏览知乎,并在页面里**自动注入**一枚
「收藏」按钮,把回答 / 文章 / 想法一键结构化保存到本地,再由 **AI(DeepSeek)**
自动撰写摘要、完成分类。
无需知乎会员,不依赖第三方爬虫 API,所有数据都留在你自己的电脑上。
---
## 功能
| 能力 | 说明 |
| --- | --- |
| 登录门 | 启动先检测知乎登录态:未登录停在登录页,登录成功后自动进入主界面 |
| 账号管理 | 工具栏显示当前账号,可查看账号信息、打开我的主页、退出登录 / 切换账号 |
| 第三方登录 | 微信 / QQ / 微博 登录走独立弹窗窗口(知乎用 `window.open` 打开授权页),授权完成自动回到主界面 |
| 内嵌浏览器 | Chromium 内核,支持多标签、前进/后退、缩放、下载、站内搜索 |
| 自动注入 | 回答 / 文章 / 想法卡片操作栏自动出现「收藏」按钮,无需手动触发 |
| 一键收藏 | 保存标题、作者、作者主页、头像、签名、赞同数、评论数、发布时间、正文 HTML/纯文本、原文链接 |
| AI 摘要 | 收藏时自动调用 DeepSeek 撰写中文摘要(长度可配),预览与导出都会带上 |
| 自动分类 | 依据文章的标签 + 摘要,由 AI 从自定义分类目录中挑选一个最贴切的类别 |
| 分类浏览 | 侧栏按分类筛选,可查看「未分类」,也可手动重新生成摘要 / 分类 |
| 公式支持 | 自动区分**行内公式**与**段间公式**,导出 Markdown 时分别为 `$…$` 与 `$$…$$` |
| 状态同步 | 已收藏的内容按钮显示为绿色「已收藏」,再点一次即取消收藏 |
| 本地收藏库 | SQLite 存储,支持关键字(含摘要 / 分类)、类型、分类筛选与多种排序 |
| 阅读预览 | 侧栏内直接渲染正文,图片自适应宽度,顶部显示 AI 摘要与分类标签 |
| 导出 | 单条 / 批量导出为 **Markdown / HTML / PDF**(HTML、PDF 带 MathJax 公式排版) |
| 登录态保持 | Cookie 与缓存落盘,登录一次长期有效 |
| 动态内容 | MutationObserver + 定时兜底,无限滚动 / 单页跳转后依然能补上按钮 |
---
## 环境要求
* Python 3.9 及以上(开发环境为 3.10.8)
* Windows / macOS / Linux 桌面环境
* 首次运行需要联网下载 Chromium(PySide6 自带,无需额外操作)
## 安装
### Windows 一键脚本(推荐)
直接双击项目根目录下的 **`安装依赖.bat`**,脚本会:
1. 自动查找本机 Python(优先 `py -3`,其次 `python`)
2. 让你选择下载源(清华 / pip 默认配置 / 阿里云)
3. 安装 `requirements.txt` 里的依赖
4. 校验 `PySide6` 与 `QtWebEngineWidgets` 能否正常导入
### 手动安装
```bash
pip install -r requirements.txt
```
或者:
```bash
pip install PySide6
```
## 运行
### Windows 一键脚本
| 文件 | 用途 |
| --- | --- |
| `安装依赖.bat` | 安装 / 修复运行依赖 |
| `启动.bat` | 带控制台启动,出错时窗口不会自动关闭,方便看报错 |
| `静默启动.bat` | 用 `pythonw.exe` 无窗口启动,适合日常使用 |
`启动.bat` 会顺手检查依赖,缺失时自动用清华镜像装上,装完直接进程序。
### 命令行
```bash
python main.py
```
启动后:
1. 程序先检测本地登录凭证,**未登录会停在登录页**,直接内置了知乎官方登录界面
(手机验证码 / 密码 / 扫码都可以)。
2. 登录成功后自动进入主界面,顶部工具栏右侧会显示你的知乎昵称。
3. 打开任意问题页,在某条回答的操作栏里找到 **收藏** 按钮,点击即可。
4. 右侧「收藏夹」面板会立即出现该条内容。
---
## 登录流程
程序通过 **Cookie 里的 `z_c0`** 判定知乎登录态:未登录时这个 Cookie 不存在
(只有 `d_c0`、`_zap` 等非鉴权项),登录成功后由知乎服务端下发。
* **启动分流**:确认已登录 → 直接进主界面;未登录 → 停在登录页。
* **自动进入**:在登录页登录成功后会**无缝切进主界面**——登录页用的那个浏览器视图
会原地变成第一个标签页,不会重新加载、不会闪屏。
* **账号按钮**(工具栏最右):
* 未登录时显示「登录知乎」,点击可登录或「我已登录,重新检测」
* 已登录时显示你的昵称,点击可看账号信息、打开我的主页、跳转知乎收藏夹、
重新获取账号信息、**退出登录 / 切换账号**
* **跳过登录**:登录页右上角有「跳过登录,直接进入」,用于网络异常或想先看看界面的场景。
不登录可以浏览公开内容,但点赞 / 收藏等操作会被知乎拦下。
---
## 快捷键
| 快捷键 | 功能 |
| --- | --- |
| `Ctrl + T` | 新建标签页 |
| `Ctrl + L` | 聚焦地址栏 |
| `Ctrl + B` | 显示 / 隐藏收藏夹侧栏 |
| `Ctrl + F` | 聚焦收藏夹搜索框 |
| `Ctrl + =` / `Ctrl + -` / `Ctrl + 0` | 放大 / 缩小 / 重置缩放 |
| `Ctrl + ,` | 打开 AI 与分类设置 |
| `F5` | 刷新收藏夹列表 |
| `Ctrl + Q` | 退出 |
---
## AI 摘要与自动分类
收藏一条内容后,程序会把标题、已有标签与正文交给 **DeepSeek**,**一次请求**同时得到
摘要、分类(以及可选的标签),再写回本地库并在侧栏展示。
### 配置
菜单「工具 → AI 与分类设置」(或 `Ctrl + ,`):
| 项 | 说明 |
| --- | --- |
| 启用 AI | 总开关,关闭则收藏时不调用任何接口 |
| API Key | 在 [DeepSeek 开放平台](https://platform.deepseek.com/) 申请,形如 `sk-…` |
| 接口地址 | 默认 `https://api.deepseek.com`(OpenAI 兼容协议,可换成自建/代理地址) |
| 模型 | 默认 `deepseek-chat`,也可填 `deepseek-reasoner` |
| 自动生成摘要 | 收藏时自动撰写摘要 |
| 自动分类 | 依据标签 + 摘要,从下面的分类目录里挑一个 |
| 自动补充标签 | 内容本身没有标签时,让 AI 生成 2~5 个关键词 |
| 摘要目标长度 | 60 ~ 500 字 |
| 分类目录 | 可增删,AI 只能从中选择,避免分类发散 |
设置面板里的「测试连接」会用当前参数发一条极短请求,验证 Key 是否可用。
配置保存在数据目录的 `settings.json`。
### 行为细节
* **收藏即处理**:入库成功后自动排入后台队列(QThreadPool,最多 3 并发),
已有摘要 / 分类的内容会跳过,不浪费额度。
* **不覆盖已有结果**:同一条内容再次收藏只更新正文,是否重新分析由你决定。
* **手动重生成**:右键单条 →「AI 重新生成摘要 / 分类」,或底部「AI 重生成」按钮。
* **批量补齐**:菜单「工具 → 为未分析的收藏批量生成摘要 / 分类」。
* **失败不会静默**:状态栏提示错误(如 401 Key 无效、402 余额不足、429 限流)。
> 未配置 API Key 时,程序其余功能(浏览、收藏、分类筛选、导出)完全不受影响。
---
## 导出
| 入口 | 格式 |
| --- | --- |
| 侧栏底部「导出」按钮 / 右键菜单 | 单条 → Markdown / HTML / PDF |
| 菜单「文件 → 导出全部为 Markdown」 | 批量 → 单个 `.md`(带目录) |
| 菜单「文件 → 导出全部为 HTML」 | 批量 → 单个 `.html`(带目录,含摘要与公式) |
| 菜单「文件 → 导出全部为 PDF」 | 批量 → 单个 `.pdf`(每条内容自动分页) |
* **HTML 导出**:样式内嵌,公式通过 MathJax(CDN)排版;若离线导致 MathJax 加载失败,
会自动回退到知乎原始的公式图片,仍然可读。
* **PDF 导出**:复用 QtWebEngine 的 `printToPdf`,无需额外安装 wkhtmltopdf 等工具;
渲染前会等待约 1.8 秒,让 MathJax 与远程图片就绪。导出过程在后台进行,不阻塞界面。
---
## 公式支持
知乎的公式有三种渲染形态(`img.ztext-math` / `span.ztext-math[data-tex]` / KaTeX DOM)。
注入脚本会统一归一化成:
```html
…
…
```
其中 `data-display` 区分 **行内公式** 与 **段间公式**:
| 场景 | 行内公式 | 段间公式 |
| --- | --- | --- |
| 判断依据 | 与文字同行 | KaTeX `katex-display`、父级 `RichText-MathBlock`,或公式独占一个段落 |
| 侧栏预览 / HTML | 与文字同排 | 居中、上下留白 |
| Markdown 导出 | `$E=mc^2$` | `$$\n\int_0^1 x\,dx\n$$` |
`data-tex` 保留原始 TeX,供 Markdown 导出与 MathJax 使用;包裹的 `
` 则是
无 JS / 离线环境下的兜底渲染。
---
## 数据存放位置
默认目录(可用环境变量 `ZHIHU_SAVER_HOME` 覆盖):
| 平台 | 路径 |
| --- | --- |
| Windows | `%APPDATA%\ZhihuSaver` |
| macOS | `~/Library/Application Support/ZhihuSaver` |
| Linux | `~/.local/share/ZhihuSaver` |
目录结构:
```
ZhihuSaver/
├── library.db # 收藏库(SQLite,含 AI 摘要 / 分类字段)
├── settings.json # DeepSeek 接口与分类目录配置
├── app.log # 运行日志(异常、登录状态变化、弹窗事件)
├── webengine/ # Cookie、LocalStorage —— 登录态在这里
├── cache/ # 浏览器缓存
├── downloads/ # 浏览器下载的文件
└── exports/ # 默认导出目录(PDF 渲染的临时文件也在这里)
```
菜单「文件 → 打开数据目录」可直接跳转过去。
> 升级提示:老版本的 `library.db` 会在启动时**自动补齐** `summary` / `category` /
> `has_formula` 列,无需手动迁移。
---
## 项目结构
```
.
├── main.py # 入口
├── requirements.txt
├── README.md
├── 安装依赖.bat # Windows:安装 / 修复依赖
├── 启动.bat # Windows:带控制台启动
├── 静默启动.bat # Windows:无窗口启动
└── app/
├── config.py # 路径与常量(含 AI / 分类默认值)
├── models.py # SavedItem 数据模型(summary / category / has_formula)
├── database.py # SQLite 收藏库(含自动迁移)
├── settings.py # 用户配置(DeepSeek / 分类目录)JSON 读写
├── diagnostics.py # 异常与关键事件日志(app.log)
├── bridge.py # QWebChannel 通信桥(JS <-> Python)
├── injector.py # 组装注入脚本
├── login.py # 知乎登录状态管理(读 z_c0 Cookie)
├── ai.py # DeepSeek 客户端 + 后台异步摘要 / 分类
├── exporter.py # Markdown / HTML 导出(含公式与摘要)
├── pdf.py # HTML -> PDF(QtWebEngine 离屏打印)
├── js/
│ └── inject.js # 页面注入脚本(收藏按钮 + 内容提取 + 公式归一化)
└── ui/
├── main_window.py # 主窗口、标签页、菜单、登录门控、AI / 导出接线
├── login_screen.py # 未登录时的登录门界面
├── browser.py # QWebEngineView / QWebEnginePage / 登录授权弹窗
├── saved_panel.py # 收藏夹侧栏(搜索 / 分类筛选 / 预览 / 导出)
├── settings_dialog.py # AI 与分类设置弹窗
├── delegates.py # 列表绘制委托
└── styles.py # QSS 主题
```
---
## 工作原理
```
QWebEngineProfile(持久化,Cookie / 缓存落盘)
│
├─ 启动时读取 Cookie:有 z_c0 → 已登录 → 直接进主界面
│ 没有 → 停在登录门,内嵌知乎官方登录页
│
│ Cookie 变化由 cookieStore 的 cookieAdded / cookieRemoved 实时感知,
│ 登录成功的瞬间就把登录页里的浏览器视图原地提升为第一个标签页
▼
知乎页面(Chromium)
│
│ ① PySide6 启动时把 inject.js + qwebchannel.js
│ 注册为 QWebEngineScript(DocumentReady / MainWorld)
▼
├─ ② 扫描 .ContentItem.AnswerItem 等卡片
│ 在 .ContentItem-actions 里插入自定义「收藏」按钮
│
├─ ③ MutationObserver 监听 DOM 变化,无限滚动时持续补按钮
│
├─ ④ 拉 /api/v4/me 回传当前账号昵称,供工具栏显示
│
└─ ⑤ 点击收藏 → 从 data-zop / meta[itemprop] / .RichContent 提取结构化数据
(公式先归一化为 .zhs-math[data-tex][data-display])
→ JSON.stringify 后通过 QWebChannel 调用 bridge.saveAnswer()
│
▼
Python 端 Bridge(QObject + @Slot)
│
▼
SQLite 落库 → 发出 itemSaved 信号 → 侧栏刷新
│
▼
MainWindow._auto_analyze()
│ 按设置筛出还缺摘要 / 分类的内容
▼
AiService(QThreadPool 后台线程)
│ DeepSeek /chat/completions(JSON 模式,一次拿全)
▼
db.update_ai() → summaryReady / categoryReady → 侧栏与统计刷新
```
几个关键设计:
* **qwebchannel.js 直接内联进注入脚本**:知乎有 CSP,用 `