[练习分享] Websters1913.com [20240306]

请技术大佬多多指点思路。

编程小白水平有限,这一篇只是自己的制作练手经历与各位有动手愿望的朋友分享,写代码过程中我主要负责提需求,实际代码主要依靠AI协助生成。

iOS+欧陆测试ok,Mdict也ok。附图


mdx、mdd和css已上传。
20240306更新

changelog
20240303v1: 规范化所有词条源文本为3行格式,修复因换行符混乱导致的部分单词分隔粘连的问题。
20240303v2:对下划线单词增加a href跳转
20240304:添加LINK跳转提高查询便捷性(根据GCIDE的ent和hw配对结果再匹配现有词头,大部分原词头是特殊字符,比如AEon跳转至Æon)
20240306:添加:ABBREVIATIONS词头,作为缩写列表(引用自GCIDE)

后续待更新:
Abbreviations, Usage页面缺失
部分词头部分仍使用特殊字符,暂未能通过普通字符搜索,后续匹配再添加跳转

背景
虽然英文能力尚待提高,但阅读到这两篇帖子,还是在想有没有可能自己也试着读读看。

而在阅读的过程中发现这本mdx词典有以下两点未满足需求:

  1. 词典内容本身是很不错,但是原来mdx版式上还是有些许不适应,而websters1913.com阅读体验似乎更好。
  2. 发现某些内容似乎有误,翻看mdx信息得知基于GCIDE 0.48,现在新版是0.53也修复部分既有错误。

原有词典无论是修改css还是mdx都很费劲(不好校对),websters1913网站数据源看起来本身就很不错,于是就萌生了自行重新制作mdx词典的想法。

主要参考的技术帖子
虽然代码本身不一定完全适用,但核心思想适用,也就是bt4baidu大佬提到的寻址+特征识别。过程中碰壁,需要调整思路,就重新用核心思想来思考问题,非常受用。

https://www.pdawiki.com/forum/thread-13219-1-1.html
https://forum.freemdict.com/t/topic/7001
https://forum.freemdict.com/t/topic/9610

使用工具:
编程助手:ChatGPT
平台:WSL + python3.10

制作思路:

  1. 定义词头列表
  2. 按词头列表抓取网页中的特征源码保存
  3. 去重
  4. 合并
  5. 格式调试

调试思路

  1. 先用1个典型单词:跑通单个流程
  2. 再用5个单词:跑通循环流程
  3. 完整词头列表:跑通整体流程

定义词头列表
尝试过以下两种不同方法尽量交叉验证确保词头列表完整

  1. 使用之前版本的mdx提取词头(使用mdx-utils)
  2. gcide提取词头<ent>标签和<hw>标签内的文本(python + 正则表达式)

经验教训:

  1. gcide源文件里面的标签内容存在特殊写法,无法直接使用xml相关来按节点处理,一开始用lxml包来提取标签文本并不顺利,后来根据文本特征重新思考,改用正则表达式来提取<ent>和<hw>反而提高了准确性,再通过在<p>里面配对<source>标签来筛选就搞定了。
  2. 网站的词头文件名本身更多使用特殊字符而不是通用字符,所以提取完和源数据过后,要对照webfont特殊符号做替换去做地址拼接,才能顺利抓到网页。

按词头列表抓取网页中的特征源码保存

  1. 要抓取什么
    这点比较容易,直接浏览器看网页源码,看看在哪个div节点以内包含了所有需要的信息,只保存该节点就好了。
    保存的同时,文件开头和结尾都提前写好代码能满足之后mdx格式转换的相关文本,每个txt文本自身都能满足单个词条记录的格式要求,以防合并后要去找bug就很难定位了。
  2. 怎么抓取
    由于网站不需要登录,也没有反爬,于是使用urllib3,创建PoolManager 对象来发送GET的request。

经验教训:

  1. 文件名检查,避免重复抓取
  2. 一定要有日志文档:要输出抓取成功的log、抓取失败的log、写入失败的log。否则没法监控过程中是否有异常,哪里异常,无法批量修正(靠人手修正真的要疯)

去重
linux对大小写敏感,所以会把And和and认为是两个单词分别保存。
我的做法是把全小写的文件移动到单独目录,然后把文件名输出成第一个单词首字母大写的词头列表,把这一小戳单词重新检查(已存在则跳过)和抓取。

合并
如果文本不多,可以用cat输出合并

cat *.txt > combine.txt

但10万个txt就没法用这个办法了(会提示命令行太长 无法执行),所以用了find来查找、sort来排序、通过xargs来传递给cat来合并,从而规避命令行长度限制。

find ./raw -name "*.txt" -print0 | sort -z | xargs -0 cat > 1913.comb

经验教训
直接使用了网站自身的css,所以没碰到什么css问题。我把css调用,直接写到每个词条的开头。

经验教训:
Linux文件行末标记是\n,但是转换成mdx的时候会无法正确识别,必须改成\r\n才能正常分开词条。

9 个赞

感谢分享制作经验,楼主很谦虚,Linux用得这么溜不小白了比我强:smile:

附图和链接已在主楼更新。如果有bug欢迎反馈(虽然我也不一定懂怎么修好)

这个我之前也稍微做过类似的

格式有些问题:

选择从网站再抓取,除了文本内容本身,还考虑到标签化、现成排版的借用。

GCIDE本身数据就开源,确实可以直接下载。但是这些源数据本身有各种奇怪的问题,我能力有限,解决不了。
比如混入了非编码文本需要手动修,之前读取错误于是我检验了一下源文件,发现B、T、U都有问题。检测代码和输出结果放后面。

websterParser项目的源码我不太读得懂,不知道怎么可以利用来转换GCIDE的源文件,再转mdx。如果有大佬懂的话,能否简单指导一下。

import string

for letter in string.ascii_uppercase:
    try:
        with open(f'gcide-0.53/CIDE.{letter}', 'r', encoding='ascii') as f:
            content = f.read()
            print(f'{letter} Done!')
    except UnicodeDecodeError as e:
        print(f'{letter} Skipped: {e}')
        continue
A Done!
B Skipped: 'ascii' codec can't decode byte 0x92 in position 1554656: ordinal not in range(128)
C Done!
D Done!
E Done!
F Done!
G Done!
H Done!
I Done!
J Done!
K Done!
L Done!
M Done!
N Done!
O Done!
P Done!
Q Done!
R Done!
S Done!
T Skipped: 'ascii' codec can't decode byte 0xe7 in position 224967: ordinal not in range(128)
U Skipped: 'ascii' codec can't decode byte 0xb9 in position 1027603: ordinal not in range(128)
V Done!
W Done!
X Done!
Y Done!
Z Done!

你这个做得很好看啊。请问是基于什么数据做的?输出什么格式呢?

See 后下划线部分可以加个a href跳转

主楼已更新。
匹配<u>标签做正则替换就好,但我发现会有小小的副作用,就是部分跳转由于词典里面没有词头,点击会显示没找到,比如fit里面的fitted

1 个赞

添加LINK跳转提高查询便捷性(根据GCIDE的ent和hw配对结果再匹配现有词头,大部分原词头是特殊字符,比如查AEon现可以跳转至Æon)

这是一个谦虚的高手帖子。佩服!

添加:ABBREVIATIONS词头,作为缩写列表(引用自GCIDE)

1 个赞