Python检测生僻字的实现方法

 更新时间:2016年10月23日 16:27:17   投稿:daisy  
最近在工作中碰到一个需求,要求检测字段是否包含生僻字以及一些非法字符如 ~!@#$%^&*。通过网上的查找资料解决了,现在将解决的过程和示例代码分享给大家,有需要的可以参考借鉴。下面来一起看看吧。

解决思路

首先想到的就是利用 python 的正则表达式来匹配非法字符,然后找出非法记录。然而理想总是丰满的,现实却是残酷的。在实现的过程中,才发现自己对于字符编码、以及 python 内部字符串表示的相关知识的缺乏。在这期间,踩过了不少坑,到最后虽然还有些模糊的地方,但总算有一个总体清晰的了解。在此记录下心得,避免以后在同一个地方跌倒。

以下的测试环境是 ArcGIS 10.3 自带的 python 2.7.8 环境,不保证其他 python 环境也适用。

python 正则表达式

python 中的正则功能由内嵌的 re 函数库提供,主要用到 3 个函数。re.compile() 提供可重用的正则表达式,match() search() 函数返回匹配结果,两者之间的区别在于: match() 从指定位置开始匹配,search() 会从指定位置向后搜索直到找到匹配字符串。例如下面的代码中,match_result 从第一个字符 f 开始匹配,匹配失败返回空值;search_result 从 f 开始向后搜索,直到找到第一个匹配的字符 a, 然后通过 group() 函数输出匹配结果为字符 a。

import re

pattern = re.compile('[abc]')
match_result = pattern.match('fabc')
if match_result:
 print match_result.group()

search_result = pattern.search('fabc')
if search_result:
 print search_result.group()

以上的实现方式需要先编译一个 pattern,然后再进行匹配。实际上,我们可以直接利用 re.match(pattern, string) 函数来实现相同的功能。但是直接匹配的方式没有先编译再匹配的方式灵活,首先是正则表达式没办法重用,如果大量数据进行同一模式匹配,意味着每次都需要内部编译,造成性能损失;另外,re.match() 函数没有 pattern.match() 功能强大,后者可以指定从哪个位置开始匹配。

编码问题

了解 python 正则的基本功能后,剩下的事情就是找到一个合适的正则表达式来匹配生僻字和非法字符。非法字符很简单,采用以下 pattern 就可以实现匹配:

pattern = re.compile(r'[~!@#$%^&* ]')

然而对于生僻字的匹配,着实难倒了我。首先是对于生僻字的定义,什么样的字算生僻字?经过咨询项目经理,规定非 GB2312 的字符属于生僻字。接下来的问题是,如何匹配 GB2312 字符?

经过查询,GB2312 的范围是 [\xA1-\xF7][\xA1-\xFE] ,其中汉字区的范围是 [\xB0-\xF7][\xA1-\xFE] 。因此,添加生僻字匹配后的表达式为:

pattern = re.compile(r'[~!@#$%^&* ]|[^\xA1-\xF7][^\xA1-\xFE]')

问题似乎是顺理得当地解决了,然而我还是 too simple too naive 。由于要判断的字符串都是从图层文件读取的,arcpy 贴心地将读取的字符编码为 unicode 格式。因此,我需要找出 GB2312 字符集在 unicode 中的编码范围。但现实是,GB2312 字符集在 unicode 中的分布并不是连续的,使用正则表示这个范围必定是非常复杂的。使用正则表达式匹配生僻字的构想,似乎陷入了死胡同。

解决方案

既然提供的字符串是 unicode 格式,那么我可不可以将其转换为 GB2312 再进行匹配呢?实际上是不行,因为 unicode 字符集要远大于 GB2312 字符集,因此 GB2312 => unicode 总是可以实现的,而反过来 unicode => GB2312 不一定能成功。

这突然为我提供了另外一种思路,假设一个字符串的 unicode => GB2312 转换会失败,那么是不是恰恰说明了它不属于 GB2312 字符集?所以,我使用 unicode_string.encode('GB2312') 函数尝试转换字符串,捕获 UnicodeEncodeError 异常来识别生僻字。

最终的代码如下:

import re

def is_rare_name(string):
 pattern = re.compile(u"[~!@#$%^&* ]")
 match = pattern.search(string)
 if match:
 return True

 try:
    string.encode("gb2312")
  except UnicodeEncodeError:
   return True

  return False

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

相关文章

  • Python的math模块中的常用数学函数整理

    Python的math模块中的常用数学函数整理

    这篇文章主要介绍了Python的math模块中的常用数学函数整理,同时对运算符的运算优先级作了一个罗列,需要的朋友可以参考下
    2016-02-02
  • python实现数据图表

    python实现数据图表

    plotly是现代平台的敏捷商业智能和数据科学库,它作为一款开源的绘图库,可以应用于Python、R、MATLAB、Excel、JavaScript和jupyter等多种语言,主要使用的js进行图形绘制,实现过程中主要就是调用plotly的函数接口,底层实现完全被隐藏,便于初学者的掌握。
    2017-07-07
  • python中kmeans聚类实现代码

    python中kmeans聚类实现代码

    这篇文章主要为大家详细介绍了python中kmeans聚类的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Pygame代码 制作一个贪吃蛇小游戏

    Pygame代码 制作一个贪吃蛇小游戏

    这篇文章主要介绍了100行Pygame代码 制作一个贪吃蛇小游戏,相信我们大家都玩过贪吃蛇游戏,今天我们就从头一起来写一个贪吃蛇小游戏,只需要100多行的代码就完成了,需要的朋友可以参考一下
    2021-12-12
  • python实现趣味图片字符化

    python实现趣味图片字符化

    这篇文章主要为大家详细介绍了python实现趣味图片字符化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • Python matplotlib绘图时指定图像大小及放大图像详解

    Python matplotlib绘图时指定图像大小及放大图像详解

    Matplotlib是一个面向对象的绘图库,我们绘制的图像中,每条曲线,每个边框等等都对应一个对象,下面这篇文章主要给大家介绍了关于Python matplotlib绘图时指定图像大小及放大图像的相关资料,需要的朋友可以参考下
    2022-05-05
  • 使用python制作一个解压缩软件

    使用python制作一个解压缩软件

    这篇文章主要介绍了python制作一个解压缩软件的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • python中extend功能用法举例

    python中extend功能用法举例

    这篇文章主要给大家介绍了关于python中extend功能的相关资料,Python中的extend()方法是一种非常有用的列表操作,它可以将一个列表中的元素添加到另一个列表的末尾,需要的朋友可以参考下
    2023-08-08
  • 使用Python进行时间序列分析的8种绘图类型

    使用Python进行时间序列分析的8种绘图类型

    时间序列数据是按时间顺序按固定时间间隔排列的观测值的集合,每个观察对应于一个特定的时间点,并且可以以各种频率(例如,每天、每月、每年)记录数据,本文介绍了几种类型的绘图,可帮助您使用 Python 进行时间序列分析,并提供使用可免费访问的数据集的详细示例
    2023-09-09
  • 在Django框架中伪造捕捉到的URLconf值的方法

    在Django框架中伪造捕捉到的URLconf值的方法

    这篇文章主要介绍了在Django框架中伪造捕捉到的URLconf值的方法,Django是Python各色人气框架中最为著名的一个,需要的朋友可以参考下
    2015-07-07

最新评论