feat: 改进变更配对算法,更新项目文档

## 主要变更

### wiki_sync.py
- 新增 `calculate_similarity()` 函数,使用 difflib.SequenceMatcher 计算文本相似度
- 改进 `group_changes_by_line()` 函数,基于内容相似度(阈值0.5)进行智能配对
- 修复了将不相关行错误配对为 replaced 的问题

### 文档更新
- README.md: 说明通过 Claude Code 和 /wiki-sync-translate skill 使用
- CLAUDE.md: Claude Code 配置和使用示例
- SKILL.md: 添加配对算法说明

### 其他
- 新增 requirements.txt: requests, python-dotenv
- 删除旧的 sync.py 和 target.txt

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
wdjwxh 2026-03-22 15:12:21 +08:00
parent 73cc023b1a
commit 1968f7fd3c
7 changed files with 196 additions and 1848 deletions

View File

@ -80,6 +80,14 @@ scripts/wiki_sync.py --title "<页面名称>" --since <上次同步时间> --run
- `added`: 新增,`new_line` 表示插入位置
- `removed`: 删除,`old_line` 表示要删除的行
**配对算法说明:**
从 v2 版本开始,脚本使用**内容相似度**来判断 `removed``added` 是否应该配对为 `replaced`
- 相似度阈值设为 0.550%
- 只有当 removed 和 added 的内容相似度 ≥ 0.5 时,才会被配对
- 这避免了将完全不同内容的行错误配对
**注意:** 如果 `old_line``new_line` 差距很大但内容相似如行号从171变到193这通常意味着中间有其他行被插入或删除需要仔细检查变更是否真的相关。
### Step 4: 更新中文文档
**核心原则:行号必须完全一致,使用增量修改减少 token 消耗**

View File

@ -180,9 +180,26 @@ def parse_diff_to_changes(diff_text):
return changes
def group_changes_by_line(changes):
def calculate_similarity(text1, text2):
"""
计算两段文本的相似度0-1
使用 difflib.SequenceMatcher
"""
if not text1 or not text2:
return 0.0
# 去除首尾空白后比较
t1 = text1.strip()
t2 = text2.strip()
return difflib.SequenceMatcher(None, t1, t2).ratio()
def group_changes_by_line(changes, similarity_threshold=0.5):
"""
将变更按行号分组将连续的删除和添加合并为替换操作
改进使用内容相似度来判断 removed added 是否应该配对
- 如果 removed added 的内容相似度 >= threshold才配对为 replaced
- 否则分别标记为 removed added
"""
# 先收集所有的删除和添加
removed_by_line = {} # old_line -> content
@ -194,27 +211,40 @@ def group_changes_by_line(changes):
elif c["type"] == "added":
added_by_line[c["new_line"]] = c["new_content"]
# 尝试将删除和添加配对
# 使用贪心算法,基于内容相似度进行配对
grouped = []
used_added = set()
used_removed = set()
for old_line, old_content in sorted(removed_by_line.items()):
# 找一个未使用的添加行来配对
paired = False
for new_line, new_content in sorted(added_by_line.items()):
# 第一步:找出所有高相似度的配对
pairings = []
for old_line, old_content in removed_by_line.items():
for new_line, new_content in added_by_line.items():
if new_line not in used_added:
similarity = calculate_similarity(old_content, new_content)
if similarity >= similarity_threshold:
pairings.append((similarity, old_line, new_line, old_content, new_content))
# 按相似度降序排序,优先处理最相似的配对
pairings.sort(key=lambda x: x[0], reverse=True)
# 第二步:贪心配对
for similarity, old_line, new_line, old_content, new_content in pairings:
if old_line not in used_removed and new_line not in used_added:
grouped.append({
"type": "replaced",
"old_line": old_line,
"new_line": new_line,
"old_content": old_content,
"new_content": new_content
"new_content": new_content,
"_similarity": round(similarity, 2) # 调试用,可选
})
used_removed.add(old_line)
used_added.add(new_line)
paired = True
break
if not paired:
# 第三步:处理未配对的 removed
for old_line, old_content in sorted(removed_by_line.items()):
if old_line not in used_removed:
grouped.append({
"type": "removed",
"old_line": old_line,
@ -223,7 +253,7 @@ def group_changes_by_line(changes):
"new_content": None
})
# 添加未配对的新增行
# 第四步:处理未配对的 added
for new_line, new_content in sorted(added_by_line.items()):
if new_line not in used_added:
grouped.append({

View File

@ -0,0 +1,55 @@
# PD2 Wiki Sync Tool - Claude Code 配置
## 项目概述
Project Diablo 2 Wiki 中英文同步工具。
## 环境要求
### Python 虚拟环境
**必须**先激活虚拟环境再运行任何 Python 脚本:
```bash
source venv/bin/activate
```
### 依赖
```bash
pip install -r requirements.txt
```
## 使用方式
本工具通过 Claude Code 的 Skill 方式使用,不提供命令行直接调用。
### 基本用法
启动 Claude Code 后,使用 `/wiki-sync-translate` 命令:
```
/wiki-sync-translate <描述你想要同步的内容>
```
### 使用示例
| 场景 | 命令示例 |
|------|---------|
| 同步所有变更 | `/wiki-sync-translate 同步从2026-01-02以来的所有变更` |
| 同步单个页面 | `/wiki-sync-translate 同步 Maps 页面` |
| 同步特定时间范围的页面 | `/wiki-sync-translate 同步从2026-01-01开始的 General Changes 页面` |
| 同步最近变更 | `/wiki-sync-translate 同步最近一周的所有变更` |
## Skill 位置
`.claude/skills/wiki-sync-translate/`
## 输出目录
`wiki_sync_output/<时间戳>/`
## 注意事项
- 中文 Wiki 行号必须与英文完全对应
- 变更配对使用内容相似度算法(阈值 0.5

296
README.md
View File

@ -1,257 +1,119 @@
# Wiki Sync Tool - Enhanced Version
# PD2 Wiki Sync Tool
一个用于同步和跟踪 MediaWiki 网站变更的 Python 工具,支持双语对比和精确的行号定位
Project Diablo 2 Wiki 中英文同步工具,用于同步英文 Wiki 变更到中文翻译文档
## 功能特点
## 前置要求
- 🔄 自动同步 MediaWiki 网站的最新更改
- 📝 生成带语法高亮的 HTML diff 文件,清晰展示变更内容
- 💾 保存页面完整内容供离线查阅
- ⏰ 支持增量同步,只获取上次同步后的新变更
- 🔍 支持按时间点或特定页面进行同步
- 📁 智能文件组织,区分新页面和变更页面
- 🌐 **新增**:自动同步中文翻译版本
- 🎯 **新增**:精确的行号映射,点击英文行自动定位到中文对应行
- 📊 **新增**:生成精美的双语对比网页
- 🎨 **新增**现代化的UI设计支持同步滚动和高亮显示
- 🧭 **新增**:导航浮窗功能,快速跳转到变更点
- 🗂️ **新增**:分类存储,主文件和参考文件分开管理
### 1. 安装 Claude Code
## 安装
1. 确保你已经安装了 Python 3.6+
2. 克隆此仓库:
```bash
git clone <repository-url>
cd wiki-sync-tool
```
3. 安装依赖:
```bash
pip install requests python-dotenv
```
## 配置
创建一个 `.env` 文件并配置你的 MediaWiki API 地址:
```env
# 英文版 Project Diablo 2 Wiki API 地址
WIKI_API_URL_EN=https://wiki.projectdiablo2.com/w/api.php
# 中文版 Project Diablo 2 Wiki API 地址
WIKI_API_URL_CN=https://wiki.projectdiablo2.cn/w/api.php
```
或者复制提供的示例配置文件:
本工具需要通过 [Claude Code](https://github.com/anthropics/claude-code) 来使用。
```bash
cp .env.example .env
# 安装 Claude Code
npm install -g @anthropic-ai/claude-code
```
### 2. 克隆仓库
```bash
git clone <repository-url>
cd sync-pd2-wiki
```
### 3. 创建虚拟环境并安装依赖
```bash
python -m venv venv
source venv/bin/activate # Linux/macOS
# 或
.\venv\Scripts\activate # Windows
pip install -r requirements.txt
```
## 使用方法
### 基本全量同步
### 启动 Claude Code
同步自上次运行以来的所有更改:
在项目目录下运行
```bash
python sync.py --run
claude
```
首次运行时,会同步过去 24 小时内的更改。
### 使用 Skill 同步 Wiki
### 指定时间起点同步
在 Claude Code 中使用 `/wiki-sync-translate` 命令:
从指定时间开始同步:
#### 示例 1同步特定时间的所有页面变更
```bash
python sync.py --since 2025-11-28T00:00:00Z --run
```
/wiki-sync-translate 帮我同步从2026-01-02以来的所有变更
```
### 同步特定页面
#### 示例 2同步特定页面
只同步特定页面的最新更改:
```bash
python sync.py --title "Amazon Basin" --run
```
/wiki-sync-translate 同步 Maps 页面的变更
```
### 同步特定页面并更新时间戳
#### 示例 3同步特定时间范围的单个页面
同步特定页面并在完成后更新全局时间戳:
```bash
python sync.py --title "Amazon Basin" --update-timestamp --run
```
/wiki-sync-translate 同步从2026-01-01开始的 General Changes 页面
```
### 查看帮助
#### 示例 4同步最近的变更
```bash
python sync.py --help
```
/wiki-sync-translate 同步最近一周的所有变更
```
## 输出文件
每次运行都会在 `wiki_sync_output` 目录下创建一个以时间戳命名的子目录,并按照以下结构组织文件
同步完成后,文件会保存在 `wiki_sync_output/<时间戳>/` 目录
```
wiki_sync_output/[时间戳]/
├── new_pages/ # 新创建的页面目录
│ └── [页面名].full.txt # 只保存页面的完整内容
wiki_sync_output/20260322_145110/
├── new_pages/ # 新创建的页面
│ └── [页面名].full.txt # 英文完整内容
└── changed_pages/ # 有变更的页面目录
├── [页面名].full.txt # 页面的最新完整内容
├── [页面名].cn.txt # 对应的中文翻译内容
├── [页面名].comparison.html # 双语对比页面(带导航功能)
└── files/ # 参考文件目录
├── [页面名].diff.html # 官方 MediaWiki diff HTML
├── [页面名].diff.txt # 文本格式的 diff
└── [页面名].old.txt # 历史版本内容
```
### 文件说明
**主要文件(日常使用)**
- `.full.txt` - 页面的完整内容(新页面和变更页面都有)
- `.cn.txt` - 中文翻译内容(仅变更页面)
- `.comparison.html` - 双语对比网页(仅变更页面)
**参考文件(技术细节)**
- `.diff.html` - MediaWiki原生HTML diff
- `.diff.txt` - 文本格式的diff类似git diff
- `.old.txt` - 页面的历史版本内容
### 双语对比网页特性
生成的双语对比网页具有以下高级功能:
1. **导航浮窗** 🧭
- 左侧浮窗显示所有变更点的导航列表
- 点击导航项可快速跳转到对应位置
- 滚动页面时自动高亮当前可见的变更
- 支持使用 Ctrl+1~9 快速跳转到对应编号的变更
2. **精确行号映射**
- 英文diff中的每一行都标注了对应的中文行号
- 点击英文任意行,自动高亮并滚动到对应的中文行
3. **交互式体验**
- 鼠标悬停时预览对应的中文行
- 点击时高亮显示对应关系
- 平滑滚动动画效果
4. **视觉设计**
- 现代化的UI设计
- 标准的diff配色绿色新增、红色删除、灰色未变更
- 响应式布局,支持移动端查看
5. **字符级diff高亮**
- 显示精确到字符级别的变更差异
- 新增内容使用绿色背景高亮
- 删除内容使用红色背景高亮
### Diff 文件示例
文本diff格式示例
```
--- old_version
+++ new_version
@@ -10,7 +10,7 @@
This is line 10
-This line will be removed
+This line will be added
This is line 12
```
HTML diff特性
- 绿色背景表示新增内容
- 红色背景表示删除内容
- 左侧彩色竖线标识变更类型
- +/- 标记清晰显示变更位置
- 删除内容带有删除线效果
## 技术细节
### 智能文件组织策略
工具根据页面是否为新建来组织文件:
- **新页面**判断依据是diff文本以"新创建页面"开头
- 只保存 `.full.txt` 文件
- 不生成中英对比(因为不存在变更)
- **变更页面**
- 保存主要文件在 `changed_pages` 目录
- 将技术细节文件放在 `files` 子目录
### 行号解析机制
工具使用自定义的diff解析器能够精确提取
- Hunk头部的行号范围信息
- 每一行变更对应的旧版本和新版本行号
- 增删改上下文行的准确位置
### 导航系统实现
1. **动态生成导航项**
- 扫描所有 `.change-block` 元素
- 自动提取变更类型(新增/替换/删除)
- 生成预览文本和行号信息
2. **模板字符串修复**
- 使用正确的 `"${changeId}"` 语法
- 确保选择器能够正确匹配DOM元素
### 中文页面搜索策略
1. 首先尝试精确匹配页面标题
2. 如果失败,则进行模糊搜索
3. 支持标题中的空格和特殊字符处理
### 使用说明
**查看新页面**
- 进入 `new_pages` 目录
- 查看对应的 `.full.txt` 文件获取页面完整内容
**处理变更页面**
- 主要查看 `changed_pages` 目录下的文件
- 使用 `.comparison.html` 进行双语对比和导航
- 查阅 `.cn.txt` 获取中文翻译参考
- 参考 `.full.txt` 获取最新的英文内容
**技术细节参考**
- 查看 `files` 目录了解详细的变更信息
- 包含官方diff、文本diff和历史版本
### 目录组织示例
```
wiki_sync_output/
├── 20251211_221150/
│ ├── new_pages/ # 新创建的页面
│ │ └── New_Page-20251211_220123-12345.full.txt
│ │
│ └── changed_pages/ # 有变更的页面
│ ├── To Do-20251211_124712-21941.full.txt
│ ├── To Do-20251211_124712-21941.cn.txt
│ ├── To Do-20251211_124712-21941.comparison.html
│ │
│ └── files/ # 参考文件
│ ├── To Do-20251211_124712-21941.diff.html
│ ├── To Do-20251211_124712-21941.diff.txt
│ └── To Do-20251211_124712-21941.old.txt
├── changed_pages/ # 有变更的页面
│ ├── [页面名].full.txt # 英文最新版本
│ ├── [页面名].cn.txt # 中文原文
│ ├── [页面名].comparison.json # 结构化变更信息
│ └── [页面名].old.txt # 英文历史版本
└── 20251211_193512/
└── ...
└── result_pages/ # 更新后的中文文档
└── [页面名].cn.txt # 可直接复制到 Wiki
```
## 许可证
## 变更配对算法
MIT License
工具使用**内容相似度算法**来判断变更是否应该配对:
## 贡献
- 相似度阈值0.550%
- 只有内容相似度 ≥ 50% 的行才会被配对为 `replaced`
- 这避免了将完全不同内容的行错误配对
欢迎提交 Issue 和 Pull Request。
## 目录结构
```
sync-pd2-wiki/
├── .claude/
│ └── skills/
│ └── wiki-sync-translate/
│ ├── SKILL.md # Skill 定义
│ └── scripts/
│ └── wiki_sync.py # 同步脚本
├── wiki_sync_output/ # 同步输出
├── references/ # 参考文件
├── requirements.txt # Python 依赖
├── CLAUDE.md # Claude Code 配置
└── README.md # 本文件
```
## License
MIT

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
requests>=2.28.0
python-dotenv>=1.0.0

1601
sync.py

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
根据READMEsync.py中会获取wiki.projectdiablo2.com的变更并拉下原文的全量文件。现在需要增加以下功能
1. 获取英文wiki的最新页面full(已实现)获取其上个版本的全量full(用上一步中的old_revid拉取).
2. 如果该网页是新增现有逻辑则只保存最新文件full即可。
3. 如果该wiki是变更则用历史版本的full文件和最新的文件进行diff得到diff文件。此处用模仿git diff的Python或库进行。得到diff文件。
4. 对于该页面标题去另一网站wiki.projectdiablo2.cn搜索并拉下原文这是同步的翻译后的中文网站。需要注意的在两个网站的页面ID不会一致但页面title是保持一致的同时绝大部分页面经过了翻译。
5. 保存一个网页生成diff文件的网页展示页面设计美观精致使用现代化的CSS/JS。将页面竖向分成两栏左边为英文源码的两个版本DIFF右侧为同样行号的中文源码。 注意行号是保持一致的。绝大多数页面的中文的行号是完全一致的可以放心对比。diff的展示同样要有标准的红色、绿色等.