Python中的大规模拼写检查

6 投票
3 回答
5354 浏览
提问于 2025-04-16 02:35

让我来分享一下我的情况,虽然我没找到其他人在做类似的事情,但肯定有人在做。我现在正在做一个Python项目,需要检查大约16000个单词的拼写。这个单词的数量还会继续增加,真是让人头疼。目前,我是从Mongo数据库中提取单词,然后逐个检查拼写,使用的是pyenchant库。我已经先把所有单词从Mongo中提取出来,这样就不会因为数据库的速度而拖慢我的进度。现在,我大约需要20分钟来处理这16000个单词,显然这个时间太长了。我有几个想法和问题:

  1. 显然,我可以利用多线程或者某种并行处理的方法。即使我把这些单词分成4份,假设性能达到最佳,我也大约需要5分钟。

  2. 有没有办法知道pyenchant底层使用的是哪个拼写库?Enchant的官网似乎暗示它在拼写检查时会使用所有可用的拼写库和字典。如果是这样的话,那我可能每个单词都要经过三到四个拼写字典的检查。这可能就是我遇到的问题,但我很难证明这一点。即使真是这样,我的选择真的就是卸载其他库吗?这听起来不太好。

所以,有没有什么办法让我在这个过程中提高一点性能?我可以把任务分成并行处理,但我还是希望在这样做之前,能让核心部分的速度快一点。

补充:抱歉,没喝咖啡就发帖了……如果一个单词拼写错误,Enchant会给我生成一个建议列表。看起来我在这个处理过程中花费了大部分时间就是在这里。

3 个回答

1

也许有个更好的办法就是先压缩文档,因为这样可以去掉重复的单词,实际上你只需要检查这些单词一次。我之所以建议这样做,是因为这可能比自己写一个独特的单词查找工具要快。

压缩后的版本应该在文件中有对独特单词的引用,你可能需要查一下这些引用是怎么结构的。

然后你可以检查所有的独特单词。我希望你不是用单独的SQL查询来检查它们,应该把字典以树的形式加载到内存中,然后用这个字典来检查单词。

完成这些后,只需解压缩一下,嘿,搞定了,所有的单词都检查过了。这应该是个相对快速的解决方案。

或者,如果检查拼写真的像评论里说的那么快,那你可能根本不需要经过整个压缩过程,这说明可能是实现上有问题。

2

我会使用一种叫做彼得·诺维格风格的拼写检查器。我已经写了一篇完整的文章来介绍这个。

http://blog.mattalcock.com/2012/12/5/python-spell-checker/

这里有一段代码,它会查看要检查的单词可能的修改。

def edits1(word):
    s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
    deletes    = [a + b[1:] for a, b in s if b]
    transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)>1]
    replaces   = [a + c + b[1:] for a, b in s for c in alphabet if b]
    inserts    = [a + c + b     for a, b in s for c in alphabet]
    return set(deletes + transposes + replaces + inserts)

你应该用这段代码快速遍历你不断增长的单词数据文件,以进行检查。想了解更多信息,可以查看完整的文章:

http://blog.mattalcock.com/2012/12/5/python-spell-checker/

5

我想大家都同意,这里性能瓶颈在于 Enchant;对于这个大小的数据集,检查一个单词是否拼写正确几乎是瞬间完成的。那么,为什么不这样做呢:

  1. 在内存中建立一个正确拼写单词的集合,可以使用 Enchant 的字典,或者自己找一些(比如 OpenOffice 的字典)。

    可选地,可以把文档中的单词去重,比如放进一个 set 里。这样做可能不会节省太多时间。

  2. 检查每个单词是否在这个集合里。这一步很快,因为只是查找集合中的内容。(大概是 O(log N),其中 N 是单词的数量?假设 set 是通过哈希分桶并进行二分查找的……有 Python 大牛可以纠正我。)

  3. 如果不在集合里,那么再请 Enchant 推荐一个单词。这一步必然会比较慢。

这个方法假设你大部分单词都是拼写正确的;如果不是,你就得想点别的办法了。

撰写回答