Python实现单词拼写检查


Posted in Python onApril 25, 2015

这几天在翻旧代码时发现以前写的注释部分有很多单词拼写错误,这些单词错得不算离谱,应该可以用工具自动纠错绝大部分。用 Python 写个拼写检查脚本很容易,如果能很好利用 aspell/ispell 这些现成的小工具就更简单了。

要点

1、输入一个拼写错误的单词,调用 aspell -a 后得到一些候选正确单词,然后用距离编辑进一步?鹧〕龈??返拇省1热缭诵 aspell -a,输入 ‘hella' 后得到如下结果:
hell, Helli, hello, heal, Heall, he'll, hells, Heller, Ella, Hall, Hill, Hull, hall, heel, hill, hula, hull, Helga, Helsa, Bella, Della, Mella, Sella, fella, Halli, Hally, Hilly, Holli, Holly, hallo, hilly, holly, hullo, Hell's, hell's

2、什么是距离编辑(Edit-Distance,也叫 Levenshtein algorithm)呢?就是说给定一个单词,通过多次插入、删除、交换、替换单字符的操作后枚举出所有可能的正确拼写,比如输入 ‘hella',经过多次插入、删除、交换、替换单字符的操作后变成:
‘helkla', ‘hjlla', ‘hylla', ‘hellma', ‘khella', ‘iella', ‘helhla', ‘hellag', ‘hela', ‘vhella', ‘hhella', ‘hell', ‘heglla', ‘hvlla', ‘hellaa', ‘ghella', ‘hellar', ‘heslla', ‘lhella', ‘helpa', ‘hello', …

3、综合上面2个集合的结果,并且考虑到一些理论知识可以提高拼写检查的准确度,比如一般来说写错单词都是无意的或者误打,完全错的单词可能性很小,而且单词的第一个字母一般不会拼错。所以可以在上面集合里去掉第一个字母不符合的单词,比如:'Sella', ‘Mella', khella', ‘iella' 等,这里 VPSee 不删除单词,而把这些单词从队列里取出来放到队列最后(优先级降低),所以实在匹配不了以 h 开头的单词才去匹配那些以其他字母开头的单词。

4、程序中用到了外部工具 aspell,如何在 Python 里捕捉外部程序的输入和输出以便在 Python 程序里处理这些输入和输出呢?Python 2.4 以后引入了 subprocess 模块,可以用 subprocess.Popen 来处理。

5、Google 大牛 Peter Norvig 写了一篇 How to Write a Spelling Corrector 很值得一看,大牛就是大牛,21行 Python 就解决拼写问题,而且还不用外部工具,只需要事先读入一个词典文件。本文程序的 edits1 函数就是从牛人家那里 copy 的。

代码

 

#!/usr/bin/python
# A simple spell checker

import os, sys, subprocess, signal

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def found(word, args, cwd = None, shell = True):
  child = subprocess.Popen(args, 
    shell = shell, 
    stdin = subprocess.PIPE, 
    stdout = subprocess.PIPE, 
    cwd = cwd, 
    universal_newlines = True) 
  child.stdout.readline()
  (stdout, stderr) = child.communicate(word)
  if ": " in stdout:
    # remove \n\n
    stdout = stdout.rstrip("\n")
    # remove left part until :
    left, candidates = stdout.split(": ", 1) 
    candidates = candidates.split(", ")
    # making an error on the first letter of a word is less 
    # probable, so we remove those candidates and append them 
    # to the tail of queue, make them less priority
    for item in candidates:
      if item[0] != word[0]: 
        candidates.remove(item)
        candidates.append(item)
    return candidates
  else:
    return None

# copy from http://norvig.com/spell-correct.html
def edits1(word):
  n = len(word)
  return set([word[0:i]+word[i+1:] for i in range(n)] +           
    [word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] +
    [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] +
    [word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet])

def correct(word):
  candidates1 = found(word, 'aspell -a')
  if not candidates1:
    print "no suggestion"
    return 

  candidates2 = edits1(word)
  candidates = []
  for word in candidates1:
    if word in candidates2:
      candidates.append(word)
  if not candidates:
    print "suggestion: %s" % candidates1[0]
  else:
    print "suggestion: %s" % max(candidates)

def signal_handler(signal, frame):
  sys.exit(0)

if __name__ == '__main__':
  signal.signal(signal.SIGINT, signal_handler)
  while True:
    input = raw_input()
    correct(input)

更简单的方法

当然直接在程序里调用相关模块最简单了,有个叫做 PyEnchant 的库支持拼写检查,安装 PyEnchant 和 Enchant 后就可以直接在 Python 程序里 import 了:

>>> import enchant
>>> d = enchant.Dict("en_US")
>>> d.check("Hello")
True
>>> d.check("Helo")
False
>>> d.suggest("Helo")
['He lo', 'He-lo', 'Hello', 'Helot', 'Help', 'Halo', 'Hell', 'Held', 'Helm', 'Hero', "He'll"]
>>>
Python 相关文章推荐
python基础教程之数字处理(math)模块详解
Mar 25 Python
python进阶教程之动态类型详解
Aug 30 Python
python实现通过pil模块对图片格式进行转换的方法
Mar 24 Python
使用Python的判断语句模拟三目运算
Apr 24 Python
举例讲解Python的Tornado框架实现数据可视化的教程
May 02 Python
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
Jun 28 Python
Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能示例
May 16 Python
python图形用户接口实例详解
Dec 16 Python
详解opencv中画圆circle函数和椭圆ellipse函数
Dec 27 Python
python不使用for计算两组、多个矩形两两间的iou方式
Jan 18 Python
Python编程快速上手——PDF文件操作案例分析
Feb 28 Python
python2.7使用scapy发送syn实例
May 05 Python
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
Apr 25 #Python
使用PDB简单调试Python程序简明指南
Apr 25 #Python
Python脚本判断 Linux 是否运行在虚拟机上
Apr 25 #Python
在Python中使用cookielib和urllib2配合PyQuery抓取网页信息
Apr 25 #Python
使用Python的Tornado框架实现一个一对一聊天的程序
Apr 25 #Python
使用Python发送邮件附件以定时备份MySQL的教程
Apr 25 #Python
安装Python的web.py框架并从hello world开始编程
Apr 25 #Python
You might like
用PHP制作的意见反馈表源码
2007/03/11 PHP
PHP 实用代码收集
2010/01/22 PHP
求PHP数组最大值,最小值的代码
2011/10/31 PHP
自己写了一个php检测文件编码的函数
2014/04/21 PHP
typecho插件编写教程(五):核心代码
2015/05/28 PHP
分享php代码将360浏览器导出的favdb的sqlite数据库文件转换为html
2015/12/09 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
PHP连接MySQL数据库操作代码实例解析
2020/07/11 PHP
js function定义函数使用心得
2010/04/15 Javascript
js中的eventType事件及其浏览器支持性介绍
2013/11/29 Javascript
javascript实现的简单计时器
2015/07/19 Javascript
jQuery实现滚动切换的tab选项卡效果代码
2015/08/26 Javascript
总结JavaScript中布尔操作符||与&&的使用技巧
2015/11/17 Javascript
JS中精巧的自动柯里化实现方法
2017/12/12 Javascript
Bootstrap Table 双击、单击行获取该行及全表内容
2018/08/31 Javascript
微信小程序dom操作的替代思路实例分析
2018/12/06 Javascript
layui树形菜单动态遍历的例子
2019/09/23 Javascript
Python中实现三目运算的方法
2015/06/21 Python
使用Python的urllib和urllib2模块制作爬虫的实例教程
2016/01/20 Python
python3库numpy数组属性的查看方法
2018/04/17 Python
windows下python和pip安装教程
2018/05/25 Python
Flask框架web开发之零基础入门
2018/12/10 Python
python实现给scatter设置颜色渐变条colorbar的方法
2018/12/13 Python
Python tkinter常用操作代码实例
2020/01/03 Python
巴西家用小家电购物网站:Polishop
2016/08/07 全球购物
美国运动鞋和运动服零售商:Footaction
2017/04/07 全球购物
什么是静态路由?什么是动态路由?各自的特点是什么?
2015/09/16 面试题
教师实习自我鉴定
2013/12/11 职场文书
国际经济贸易专业自荐信
2014/06/13 职场文书
合伙经营协议书范本(通用版)
2014/12/03 职场文书
电影复兴之路观后感
2015/06/02 职场文书
汉语拼音教学反思
2016/02/22 职场文书
一文带你理解vue创建一个后台管理系统流程(Vue+Element)
2021/05/18 Vue.js
CSS实现两列布局的N种方法
2021/08/02 HTML / CSS
Java spring定时任务详解
2021/10/05 Java/Android
Java 多线程协作作业之信号同步
2022/05/11 Java/Android