EasyDict

本地音频播放会拼接 dict_id 然后去 media.db 里面查找?

另外,easydict有没有调试模式?

差不多是的

说的调试模式是哪种调试模式?

输出debug日志;像goldendict-ng等 右键 浏览器开发者模式;

设置-关于软件-配置目录,可以打开配置文件夹,里面的logs文件夹里有日志

此外还可以右键菜单-编辑,直接修改json并保存和实时显示

正常播放了 :+1:

目前phrase的格式有点问题,无法正常显示。推荐把各个phrase单独提取成entry,然后在主词头的json里使用简单的字段"phrases": ["make certain/sure", "make someone/something do something"]即可

[
  {
    "phrase": "make certain/sure",
    "sense": [
      {
        "index": 1,
        "definition": {
          "en": "to take action so that you are certain that something happens , is true , etc.:"
        },
        "example": [
          {
            "en": "I'll just make sure I've turned the oven off.",
            "zh": "我要确认一下是否关掉了烤箱。"
          }
        ]
      }
    ]
  },
  {
    "phrase": "make someone/something do something",
    "sense": [
      {
        "index": 1,
        "definition": {
          "en": "to force someone or something to do something:"
        },
        "example": [
          {
            "en": "You can't make him go if he doesn't want to.",
            "zh": "如果他不想去,你不能强迫他去。"
          }
        ]
      }
    ]
  },
  {
    "phrase": "be made to do something",
    "sense": [
      {
        "index": 1,
        "definition": {
          "en": "to be forced to do something:"
        },
        "example": [
          {
            "en": "The prisoners are made to dig holes and fill them up again.",
            "zh": "囚犯们被强迫挖洞,然后再把它们填上。"
          }
        ]
      }
    ]
  },
  {
    "phrase": "make room/space/way",
    "sense": [
      {
        "index": 1,
        "definition": {
          "en": "If you make room / space /way for something or someone, you move your body or move other things, so that there is space for it or them:"
        },
        "example": [
          {
            "en": "I was wondering if I could make room for a grand piano somewhere in my house ."
          }
        ]
      }
    ]
  },
  {
    "phrase": "make a bed",
    "sense": [
      {
        "index": 1,
        "definition": {
          "en": "to pull up and tidy the covers on a bed after it has been slept in:"
        },
        "example": [
          {
            "en": "She hurried upstairs and quickly made the beds .",
            "zh": "她匆忙上楼,飞快地整理了床铺。"
          }
        ]
      }
    ]
  }
]

这个词典软件真的很优雅

按照要求修改后出来的效果跟你制作的在线词典ODE效果不一样。我这个phrases出现在词头下面,展开后 在phrase上点击不弹出浮动窗口。你制作的phrases出现在尾部,origin之前,点击有弹窗。

是不是phrase的显示 还在改动?

phrases字段不要放在data里,放在json根节点

确实如此,修改后正常了。

Ai总结的一个流程,请指正 @karx

从 HTML 到 .db 完整工作流程指南

一、整体流程概览

HTML 网页
    ↓ [1. 抓取]
原始数据 (JSON)
    ↓ [2. 清洗转换]
标准化数据 (JSONL)
    ↓ [3. 音频处理]
带音频的数据 (JSONL)
    ↓ [4. 构建数据库]
EasyDict 词典 (.db)

二、详细步骤

步骤 1: HTML 抓取 (dictionary_scraper.py)

输入: 网页 URL + 单词列表
输出: entries.jsonl (每行一个 JSON entry)

核心任务:

  1. 发送 HTTP 请求获取 HTML
  2. 使用 BeautifulSoup 解析 DOM 结构
  3. 提取关键信息:
    • 词头 (headword)
    • 音标 (phonetic)
    • 词性 (part of speech)
    • 定义 (definitions)
    • 例句 (examples)
    • 短语 (phrases)
    • 音频 URL

重点:

  • CSS 选择器定位元素
  • 处理多词性(一个单词多个 entry)
  • 短语提取(独立的 phrase-block)
  • 断点续传(progress tracking)

难点:

  • 网站结构变化需要更新选择器
  • 反爬虫机制(需要模拟浏览器 headers)
  • 中文翻译提取(避免混入例句翻译)

步骤 2: 数据清洗与格式转换 (convert_to_EasyDict)

输入: 原始抓取数据
输出: EasyDict 格式的 JSONL

核心任务:

  1. 结构重组:

    原始格式 → EasyDict 格式
    {                    {
      "definitions": []    "sense_group": [
    }                        {"sense": [...]}
                           ]
                         }
    
  2. 字段映射:

    • definitionssense_group.sense
    • phrases → 独立 phrase entries
    • 添加 dict_id, entry_type
  3. 短语处理:

    • 主词条添加顶层 phrases 数组
    • 每个短语创建独立 entry
    • entry_type="phrase"

重点:

  • 保持数据完整性
  • 正确的嵌套结构
  • entry_id 唯一性

难点:

  • 字段位置必须精确(phrases 在顶层,不在 data 中)
  • 多层嵌套结构(sense_group → sense → definition/example)
  • 短语与主词条的关联

步骤 3: 音频 URL 处理 (fix_audio_urls.py)

输入: entries.jsonl
输出: entries_fixed.jsonl + audio_urls.txt

核心任务:

  1. 提取音频 URL 到 _download_url 字段
  2. 保留文件名在 audio_file 字段
  3. 生成下载列表 (audio_urls.txt)

重点:

  • 分离 URL 和文件名
  • 保持 entry 结构不变

难点:

  • 处理不同的 URL 格式
  • 确保文件名唯一性

步骤 4: 数据库构建 (build_dictionary.py)

输入: entries_fixed.jsonl + 音频文件(可选)
输出: dictionary.db + media.db + metadata.json

核心任务:

  1. 创建 SQLite 数据库表:

    CREATE TABLE entries (
      entry_id INTEGER PRIMARY KEY,
      json_data BLOB  -- zstd 压缩的 JSON
    )
    
  2. JSON 压缩(可选):

    • 训练 zstd 字典
    • 压缩每个 entry
    • 存储字典到 config 表
  3. 音频处理:

    • 复制到 audio_temp/
    • 或嵌入到 media.db
  4. 创建索引:

    • headword 索引
    • phonetic 索引(表意文字)

重点:

  • 数据库 schema 必须匹配 EasyDict
  • entry_id 必须是纯数字
  • 压缩可以减小 90% 体积

难点:

  • zstd 字典训练(需要足够样本)
  • 大文件处理(内存管理)
  • 索引优化(搜索性能)

三、关键数据结构

3.1 EasyDict 标准格式

{
  "dict_id": "cambridge_en_zh",
  "entry_id": 123,
  "headword": "make",
  "entry_type": "word",
  "phrases": ["make do", "make up"],  // ← 必须在顶层
  "pronunciation": [
    {
      "region": "UK",
      "notation": "meɪk",
      "audio_file": "make.mp3"
    }
  ],
  "sense_group": [
    {
      "group_name": "verb",
      "sense": [
        {
          "index": 1,
          "definition": {"en": "...", "zh": "..."},
          "example": [{"en": "...", "zh": "..."}]
        }
      ]
    }
  ]
}

3.2 Phrase Entry 格式

{
  "dict_id": "cambridge_en_zh",
  "entry_id": 124,
  "headword": "make do",
  "entry_type": "phrase",  // ← 必须是 "phrase"
  "sense_group": [
    {
      "sense": [
        {
          "index": 1,
          "definition": {"en": "...", "zh": "..."}
        }
      ]
    }
  ]
}

四、重难点总结

4.1 数据抓取重难点

难点 解决方案
CSS 选择器变化 使用多个备选选择器,添加日志
反爬虫 完整模拟浏览器 headers,添加延迟
中文翻译混入例句 精确定位 .def-block > .def
短语提取 独立的 .phrase-block 选择器
断点续传 保存 progress.json,记录已完成单词

4.2 格式转换重难点

难点 解决方案
字段位置错误 phrases 必须在顶层,不在 data
嵌套结构 严格按照 EasyDict 格式:sense_group → sense
entry_id 冲突 使用全局计数器,断点续传时更新
短语关联 主词条 phrases 数组 + 独立 phrase entries
音频字段 audio_file 只保存文件名,URL 在 _download_url

4.3 数据库构建重难点

难点 解决方案
entry_id 格式 必须是纯数字(不能有 dict_id 前缀)
JSON 压缩 使用 zstd + 字典,减小 90% 体积
索引创建 headword + phonetic(表意文字)
音频嵌入 复制到 audio_temp/ 或存入 media.db
元数据 metadata.json 必须包含 id, name, version 等

感觉总结这些没意义啊,readme.md本身已经很精炼了

确实readme已经写得很好了,这个算一点实践总结吧,个人的避坑指南

对了,在线音频是如何处理的?词头和例句的音频url放哪里?还是说只有词典服务器在线音频一个选择?

嗯是的,目前只有词典服务器一个在线音频选择

软件越来越完善了,感谢

更新1.7.5,更加适配电脑端,刚刚发现沙漠长出了火箭

试着转换了一个词典,CECD 2024-07-28,效果还行,尝尝鲜。

下载:CECD2024_EasyDict - FreeMdict Cloud

文件夹名须为 “CECD2024_EasyDict”,与metadata.json、dictionary.db里面的id保持一致。

数据来源:CECD 2024-07-28

赞!!!有意向上传到词典商店里嘛,这样可以方便下载、管理和更新

:grinning_face_with_smiling_eyes:还没纠错,音频也还没转换,等成熟一些了再传到词典商店,如何?