本文由来

在做抽取日常短语中地名(包括省市区县街道社区道路)的工作,待处理的文本都是常用语,本身该工作也只是一个小工程,暂时没有花时间学术研究模型,也不太在意准确率。语言是python,有一些bug和处理方法建议,主要是关于中文句子的正则匹配,记录下来以备不时之需。

汉字正则和取字符问题

  • 问题:需要匹配该句子的规则性很强的部分汉字。例如:我去了长安路买东西。识别路的结果应为“长安路”
str=u'我去长安路买东西'
pattern = re.compile(ur'[去,走,了]{1,2}([\u4e00-\u9fa5]{2,3}路)')
target = re.findall(pattern, str)
for item in target:
print item

注:

  1. [\u4e00-\u9fa5]是中文字符的字符集{2,3}表名该字符集可以重复两到三次,也就是说,介词和路之间限制了只能有两到三个汉子,此情况下,我们认为这是一个路名(极可能是路名,但也可能不是)
  2. str必须是unicode编码,即u'我是待匹配字符串',此时才输出匹配结果。如果读取的是utf-8的文本,正则匹配前读取到的行内容一定要先解码line.decode(utf-8)
  3. 特别地,句子可能是“走了”、“去了”,针对这种情况,我们加入重复花括号{},这样不必在字符集中穷举所有两字词语,只需要穷举可能出现的字,允许1到2次重复就可以了。
  • 抽取汉字:待读取文本本身是utf-8编码,通过python程序读入后,应先解码后编码,才能保证在不乱码的情况下提取对应某个具体的字。python程序读入代码:
file = open('f:/test.txt', 'r')
for (num, line) in enumerate(file):
print "LineNum"+str(num)+" : "+line #行号从0开始
print line[2]  #出现乱码
newstr1=line.decode('utf-8')[0:3].encode('utf-8')
newstr2=line.decode('utf-8')[2].encode('utf-8')
print newstr1   #输出“周末”
print newstr2   #输出“末”
print newstr2=='末' #输出 true

注:

  1. [1:3]代表包括第一个汉字起,到第三个汉字结束,但不包括第三个汉字。如果想全部输出,则写为[0:-1]。
  2. 先把utf-8字符串解码为unicode才能输出对应位(汉字位从1开始)。2.x版本中,字符串有str和unicode两种类型,str有各种编码区别,例如utf-8、utf-16、gbk等等,unicode是没有编码的标准形式。unicode通过编码(encode函数指定编码类型)转化成str,str通过解码(decode函数)转化成unicode。在进行同时包含 str 类型和 unicode 类型的字符串操作时,Python2 一律都把 str 解码(decode)成 unicode 再运算。
  3. 字符串单引号和双引号问题:在表示字符串时,是没有区别的。
    但是如果你的字符串中本身有单引号,那整个字串用双引号就省得将原字串中的单引号转义。如果字串中本身有双引号,那就用单引号扩起整个字串,也是省去转义。

文本读写

  • 读取txt中某一行内容:
# 读取文本中某行内容(文本序号从1开始)

count = linecache.getline('f:/userdict.txt', num)
  • 读取行号和行内容:
#文本序号从0开始

file = open('f:/test.txt', 'r')
for (num, line) in enumerate(file):
     print num,line
  • 循环输出列表内容(包括索引)
def printList(list):
for index,item in enumerate(list):
    print index,"|", item

注意索引是从1开始的

  • 对比当前字符串和词典文本中字符串是否相同的函数(主要参考带注释部分的代码)
def findDirString(str,dict):
file = open('f:/userdict.txt', 'r')
flag=0
for (num, value) in enumerate(file):
    # 输出行号和行内容 (序号从0开始)
    # print "line number", num, "is:", value
    line=value.decode('utf-8')[0:-1].strip();# 对文本解码并去掉字符串前后的空格
    if str.__eq__(line):
        if line[-1] not in [u'省',u'市',u'区',u'县']:
            count = linecache.getline('f:/userdict.txt', num)# 读取文本中某行内容(序号从1开始)
            cla = count.decode('utf-8')[0:-1].strip()[-1]
            flag=1
            dict[str]=cla
            return 1
return 0