基于Python的中英文分词基础:正则表达式和jieba分词器

  • 前言介绍
  • 英文字符串处理
    • Python中的str
    • 正则表达式
      • Python中的正则表达式模块 re
    • 小练习
      • 字符串中出现频次最多的字母
      • 统计字符出现的频率
  • 中文字符串处理:jieba分词器
    • jieba可以做关键词抽取
      • 基于 TF-IDF 算法的关键词抽取(term frequency–inverse document frequency)
      • 基于 TextRank 算法的关键词抽取
    • jieba做词性标注
    • jieba分词加速:并行分词
    • Tokenize
    • ChineseAnalyzer for Whoosh 搜索引擎
    • 使用命令行分词

前言介绍

这篇博文是我的一次笔记,主要讨论NLP的基础知识:中英文字符串的处理,其中英文部分主要是正则表达式,中文部分是jieba分词器。对于其他常用的扩展包:如NLTK、spacy等将接下来的博文中进行更新。

语料库和词汇知识库对于NLP任务起着极其关键的重要,有时候是建立和改进一个NLP系统的“瓶颈”。对于“语料库和词汇知识库”的基础知识,可以参考宗成庆老师的专著:

《统计自然语言处理》

如果说图像处理技术是智能机器的视觉系统,那么自然语言处理就是智能机器的视觉系统、听觉系统、语言系统;CV注重对一帧一帧的图片或者一段连续的视频进行处理,提取重要信息,而NLP注重对文本、语音(语音识别、语音合成)等信息的理解和生成,不管是语音还是图像中的语言信息最终还是转换为文本进行处理;

如果说语言信息是一种物质的话,那么语音就是包裹物质的外壳,文本是传达物质信息的实际载体;写过爬虫或者从事技术开发的童鞋或多或少都要跟文本信息(字符串)打交道,本博文将简要介绍面向英文和中文字符串的常见处理方法;

英文字符串处理

Python中的str

通过python中的字符串操作(str),可以直接完成一些简单的字符串处理任务,下图采用dir()函数快速了解str对象中的常用内置函数:
下面将挑一些使用频率比较高的内置函数进行演示:

  • 去空格和特殊字符:s.strip() 将字符串头和尾的空格,以及位于头尾的\n \t之类给删掉;
    s.lstrip():从左侧起,去掉左侧括号内的字符,s.rstrip():去掉右边;
In:
s = ' hello, world!'
print(len(s))
a = s.strip()
print(a)
print(len(a))
print(s.lstrip(' hello, '))
print(s.rstrip('!'))Out:
14
hello, world!
13
world!hello, world
  • 连接两个字符串:+
In:
sStr1 = 'strcat'
sStr2 = 'append'
sStr1 += sStr2
print sStr1Out:
strcatappend
  • 查找字符后者子串:str1.index(str2)
# 返回值< 0 为未找到
In:
sStr1 = 'strchr'
sStr2 = 'r'
nPos = sStr1.index(sStr2)
print nPosOut:
2
  • 比较两个字符串:cmp(str1,str2); 返回-1:str1<str2; 1:str1>str2; 0: str1=str1
In:
sStr1 = 'strchr'
sStr2 = 'strch'
print cmp(sStr2,sStr1)
print cmp(sStr1,sStr2)
print cmp(sStr1,sStr1)Out:
-1
1
0
  • 字符串的大小写:str1.upper()str1.lower()
In:
sStr1 = 'JCstrlwr'
sStr1 = sStr1.upper()
print sStr1
sStr1 = sStr1.lower()
print sStr1Out:
JCSTRLWR
jcstrlwr
  • 翻转字符串:str1[::-1]
In:
sStr1 = 'abcdefg'
sStr1 = sStr1[::-1]
print sStr1Out:
gfedcba
  • 查找字符串:str1.find(str2) 返回str2中首字母出现的下标,不存在返回-1
In:
sStr1 = 'abcdefg'
sStr2 = 'cde'
print sStr1.find(sStr2)Out:
2
  • 分割字符串:s.split()
In:
sStr1 = 'ab,cde,fgh,ijk'
sStr2 = ','
sStr1 = sStr1[sStr1.find(sStr2) + 1:]   # 有个小小的递归在这里
print sStr1
#或者
s = 'ab,cde,fgh,ijk'
print(s.split(','))Out:
cde,fgh,ijk
['ab', 'cde', 'fgh', 'ijk']

好了,以上就是常用的字符串操作,下面介绍正则表达式;

正则表达式

对于正则表达式一定不陌生,它描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
对于正则表达式的教程可以参考:

https://www.runoob.com/regexp/regexp-syntax.html

当要匹配 一个/多个/任意个 数字/字母/非数字/非字母/某几个字符/任意字符,想要 贪婪/非贪婪 匹配,想要捕获匹配出来的 第一个/所有 内容的时候,主要以下这张正则表达式的常用语法:

  • 验证正则表达式正确性的工具:

http://regexr.com/

  • 正则表达式的进阶联系地址(表达式长度越短,得分越高):

https://alf.nu/RegexGolf

Python中的正则表达式模块 re

re模块 (import re),

re一般步骤:
• 将正则表达式的字符串形式编译(re.compile)为Pattern实例;
• 使用Pattern实例处理文本并获得匹配结果(一个Match的实例);
• 使用match实例获得信息,进行其他操作;
示例:

import re
# 将正则表达式编译成Pattern对象
pattern = re.compile(r'hello.*\!')   #匹配以hello开始,以!结束的字符串
# 使用Pattern匹配文本,获得匹配结果,无法匹配时将返回None
match = pattern.match('hello,world! How are you?')
if match:# 使用Match获得分组信息print(match.group())Out: Hello, world!

re.compile(strPattern[, flag]):

  • 这个是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。
  • 第二个参数flag是匹配模式,取值可以使用按位或运算符’|‘表示同时生效,比如re.I | re.M。
    flag可选值有:
    re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
    re.M(MULTILINE): 多行模式,改变’^‘和’$‘的行为
    re.S(DOTALL): 点任意匹配模式,改变’.'的行为
    re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
    re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
    re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。

当然,也可以在字符串中指定模式,比如re.compile(‘pattern’, re.I | re.M)等价于re.compile(’(?im)pattern’)

Match
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。
match属性:
string: 匹配时使用的文本。
re: 匹配时使用的Pattern对象。
pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:

  • group([group1, …]):
    获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
  • groups([default]):
    以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
  • groupdict([default]):
    返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
  • start([group]):
    返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
  • end([group]):
    返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
  • span([group]):
    返回(start(group), end(group))。
  • expand(template):
    将匹配到的分组代入template中然后返回。template中可以使用\id或\g、\g引用分组,但不能使用编号0。\id与\g是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符’0’,只能使用\g<1>0。

pattern
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]):
这个方法将从string的pos下标处起尝试匹配pattern:如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。pos和endpos的默认值分别为0和len(string)。
注意:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符’$’。
**search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]): **
这个方法从string的pos下标处起尝试匹配pattern:如果pattern结束时仍可匹配,则返回一个Match对象若无法匹配,则将pos加1后重新尝试匹配,直到pos=endpos时仍无法匹配则返回None。pos和endpos的默认值分别为0和len(string));
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):
搜索string,以列表形式返回全部能匹配的子串。
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。 count用于指定最多替换次数,不指定时全部替换。
subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):
返回 (sub(repl, string[, count]), 替换次数)。

小练习

字符串中出现频次最多的字母

#版本1:利用正则表达式和计数器
import re
from collections import Counterdef get_max_value_v1(text):text = text.lower()result = re.findall('[a-zA-Z]', text)  # 去掉列表中的符号符count = Counter(result)  # Counter({'l': 3, 'o': 2, 'd': 1, 'h': 1, 'r': 1, 'e': 1, 'w': 1})count_list = list(count.values())max_value = max(count_list)max_list = []for k, v in count.items():if v == max_value:max_list.append(k)max_list = sorted(max_list)return max_list[0]
#利用计数器
from collections import Counterdef get_max_value(text):count = Counter([x for x in text.lower() if x.isalpha()])m = max(count.values())return sorted([x for (x, y) in count.items() if y == m])[0]
#version 3
import stringdef get_max_value(text):text = text.lower()return max(string.ascii_lowercase, key=text.count)

统计字符出现的频率

# map函数
#T  h  e     M  i  s  s  i  s  s  i  p  p  i     R  i  v  e  r
#[1, 1, 2, 2, 1, 5, 4, 4, 5, 4, 4, 5, 2, 2, 5, 2, 1, 5, 1, 2, 1]
sentence='The Mississippi River'
def count_chars(s):s=s.lower()count=list(map(s.count,s))return (max(count))
print count_chars(sentence)

中文字符串处理:jieba分词器

jieba是一个非常好用的中文工具,是以分词起家的,但是功能比分词要强大很多。是目前开源软件中,最好用的中文分析库之一。Python环境下需要安装并导入:

import jieba


jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用 for 循环来获得分词后得到的每一个词语(unicode)
jieba.cut 方法接受三个输入参数:

  • 需要分词的字符串
  • cut_all 参数用来控制是否采用全模式
  • HMM 参数用来控制是否使用 HMM 模型(分词效果比较好的,一般都需要隐马尔可夫模型)

jieba.cut_for_search 方法接受两个参数:该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细

  • 需要分词的字符串
  • 是否使用 HMM 模型。
    jieba.lcut 以及 jieba.lcut_for_search 直接返回 list 而不是 generator,用法与上面的一致。

添加用户自定义词典

  • 很多时候我们需要针对自己的场景进行分词,会有一些领域内的专有词汇。

    • 可以用 jieba.load_userdict(file_name) 加载用户字典;
    • 少量的词汇可以自己用下面方法手动添加:
      • add_word(word, freq=None, tag=None) 和 del_word(word) 在程序中动态修改词典
        注意: 这种情况下HMM 需要被设置为False,不然HMM会忽略掉动态修改的信息;
      • suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

jieba可以做关键词抽取

关于TF-IDF和TextRank的理论,将在下一篇博客中给出,这里只关注这两个方法在jieba中的使用;
通常数据量很大的时候,可以选用TextRank提取关键词(TextRank与Google的PageRank类似,通过分析大量的文档获得更加精确的关系);
TF-IDF可以通过优化停用词库和自定义语料库,也可以获得比较好的效果;

基于 TF-IDF 算法的关键词抽取(term frequency–inverse document frequency)

TF: 当前词在当前文档中出现的频率
IDF: 这个词在所有文档中出现的频率,逆向文件频率
用法:

import jieba.analyse
jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
  • sentence 为待提取的文本
  • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
  • withWeight 为是否一并返回关键词权重值,默认值为 False
  • allowPOS 仅包括指定词性的词,默认值为空,即不筛选

关于TF-IDF 算法的关键词抽取补充内容:
1. 关键词提取所使用逆向文件频率(IDF)文本语料库可以切换成自定义语料库的路径

  • 用法: jieba.analyse.set_idf_path(file_name) # file_name为自定义语料库的路径

    • 自定义语料库示例可参考:

      https://github.com/fxsjy/jieba/blob/master/extra_dict/idf.txt.big

    • 用法示例可参考

      https://github.com/fxsjy/jieba/blob/master/test/extract_tags_idfpath.py

2. 关键词提取所使用停止词(Stop Words)文本语料库可以切换成自定义语料库的路径

  • 用法: jieba.analyse.set_stop_words(file_name) # file_name为自定义语料库的路径

    • 自定义语料库示例可参考

      https://github.com/fxsjy/jieba/blob/master/extra_dict/stop_words.txt

    • 用法示例可参考

      https://github.com/fxsjy/jieba/blob/master/test/extract_tags_stop_words.py

3.关键词一并返回关键词权重值示例

  • 用法示例可参考

    https://github.com/fxsjy/jieba/blob/master/test/extract_tags_with_weight.py

基于 TextRank 算法的关键词抽取

# 直接使用,接口相同,注意默认过滤词性:jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v')) # 新建自定义 TextRank 实例jieba.analyse.TextRank()

原始论文: TextRank: Bringing Order into Texts

http://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf

基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图

jieba做词性标注

# 新建自定义分词器,tokenizer 参数可指定内部使用的 jieba.Tokenizer 分词器。
# jieba.posseg.dt 为默认词性标注分词器
jieba.posseg.POSTokenizer(tokenizer=None)
  • 标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法。

  • 具体的词性对照表参见计算所汉语词性标记集

    http://ictclas.nlpir.org/nlpir/html/readme.htm

import jieba.posseg as psegwords = pseg.cut("我爱自然语言处理")for word, flag in words:print('%s %s' % (word, flag))Out:
我 r
爱 v
自然语言 l
处理 v

jieba分词加速:并行分词

原理: 将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升 基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows
用法:

  • jieba.enable_parallel(4) # 开启并行分词模式,参数为并行进程数;
  • jieba.disable_parallel() # 关闭并行分词模式;

实验结果:在 4 核 3.4GHz Linux 机器上,对金庸全集进行精确分词,获得了 1MB/s 的速度,是单进程版的 3.3 倍。
注意: 并行分词仅支持默认分词器 jieba.dt 和 jieba.posseg.dt。

Tokenize

返回词语在原文的起止位置(定位)
注意,输入参数只接受 unicode

ChineseAnalyzer for Whoosh 搜索引擎

from jieba.analyse import ChineseAnalyzer

使用命令行分词

使用示例:python -m jieba news.txt > cut_result.txt

命令行选项(翻译):
使用: python -m jieba [options] filename
结巴命令行界面。
固定参数:
filename 输入文件
可选参数:
-h, --help 显示此帮助信息并退出
-d [DELIM], --delimiter [DELIM]
使用 DELIM 分隔词语,而不是用默认的’ / '。
若不指定 DELIM,则使用一个空格分隔。
-p [DELIM], --pos [DELIM]
启用词性标注;如果指定 DELIM,词语和词性之间
用它分隔,否则用 _ 分隔
-D DICT, --dict DICT 使用 DICT 代替默认词典
-u USER_DICT, --user-dict USER_DICT
使用 USER_DICT 作为附加词典,与默认词典或自定义词典配合使用
-a, --cut-all 全模式分词(不支持词性标注)
-n, --no-hmm 不使用隐含马尔可夫模型
-q, --quiet 不输出载入信息到 STDERR
-V, --version 显示版本信息并退出

如果没有指定文件名,则使用标准输入。
–help 选项输出:
$> python -m jieba --help
Jieba command line interface.

positional arguments:
filename input file

optional arguments:
-h, --help show this help message and exit
-d [DELIM], --delimiter [DELIM]
use DELIM instead of ’ / ’ for word delimiter; or a
space if it is used without DELIM
-p [DELIM], --pos [DELIM]
enable POS tagging; if DELIM is specified, use DELIM
instead of ‘_’ for POS delimiter
-D DICT, --dict DICT use DICT as dictionary
-u USER_DICT, --user-dict USER_DICT
use USER_DICT together with the default dictionary or
DICT (if specified)
-a, --cut-all full pattern cutting (ignored with POS tagging)
-n, --no-hmm don’t use the Hidden Markov Model
-q, --quiet don’t print loading messages to stderr
-V, --version show program’s version number and exit

If no filename specified, use STDIN instead.

最后:这部分内容整理自Julyedu的课程笔记,接下来将整理关键词提取算法;

基于Python的中英文分词基础:正则表达式和jieba分词器相关推荐

  1. 大学计算机基础python学多久_基于Python 的“大学计算机基础”课程教学设计

    基于Python 的"大学计算机基础"课程教学设计 日期:2018-04-11 04:32 摘要 培养非计算机专业大学生的计算思维能力,在"大学计算机基础"课程 ...

  2. 基于python的量化投资基础(Chapter.0)——概述

    量化交易概述 量化交易就是通过数理统计模型方式及计算机程序化发出买卖指令去实现投资理念.实现投资策略的过程,以获取稳定收益为目的的交易方式. 广义的量化投资=基于现代科学方法的理论体系+研究方式+工程 ...

  3. 基于Python的大数据分析基础(九)--- 数据分析

    8 数据分析 8.1 基本统计分析(描述性统计分析) 一般统计某个变量的最小值,第一个四分位值,中值,第三个四分位值,以及最大值 均值(Mean),中位数(Median)和众数(Mode) 其中均值和 ...

  4. python中正则表达式与jieba分词的使用

    这次和大家分享一下主要使用正则表达式匹配文本信息内容的案例,其中还用到了jieba分词词性标注技术,和一些对文本的切片工作.有兴趣学习的可以详细看看,具体内容,应该有点帮助,这是本人一个一个代码敲出来 ...

  5. python布局管理_Python基础=== Tkinter Grid布局管理器详解

    本文转自:https://www.cnblogs.com/ruo-li-suo-yi/p/7425307.html          @ 箬笠蓑衣 Grid(网格)布局管理器会将控件放置到一个二维的表 ...

  6. python分词统计词频_python jieba分词并统计词频后输出结果到Excel和txt文档方法

    前两天,班上同学写论文,需要将很多篇论文题目按照中文的习惯分词并统计每个词出现的频率. 让我帮她实现这个功能,我在网上查了之后发现jieba这个库还挺不错的. 运行环境: 安装python2.7.13 ...

  7. 中文分词的基本原理以及jieba分词的用法

    结巴分词是国内程序员用Python开发的一个中文分词模块,可能是最好的Python中文分词组件? 中文分词的原理 – 1.中文分词(Chinese Word Segmentation) 指的是将一个汉 ...

  8. python大数据分析基础教程_基于Python的大数据分析基础及实战

    第1部分 基 础 篇 第1章 Python语言基础 /2 1.0 引子 /2 1.1 工欲善其事,必先利其器(安装Python) /3 1.2 学跑得先学走(语法基础) /9 1.3 程序结构 /11 ...

  9. BoooLee pyretoolkit -- 一个基于python re模块的在线正则表达式测试工具

    为了学习python re模块正则表达式,寻找了一些正则表达式工具,除了komodo捆绑的rx toolkit外,其他的测试工具都是基于.net或其他引擎的,语法上多少有点出入. 干错自己写一个,用了 ...

最新文章

  1. Qt调用word 例子
  2. 如何在ppt下面加入讲解内容_学术展示系列:学术PPT教程(下)内容 讲解
  3. System.Net.Dns.GetHostByAddress(string) 已经过时
  4. linun——SElinux的简单理解
  5. 树状数组求逆序对_区间和的个数(树状数组)
  6. springboot 参数校验详解
  7. 函数名,闭包,装饰器
  8. java mybatis 动态sql
  9. 【学堂在线数据挖掘:理论方法笔记】第八天(4.2)
  10. 【超图+CESIUM】【基础API使用示例】47、超图|CESIUM - 平行光源设置
  11. 基于Python的指数基金量化投资 - 指数的市盈率和市净率计算
  12. 一起聊聊什么是P问题、NP问题、NPC问题
  13. CSS画心形的三种方法,超级简单
  14. 微信小程序OCR插件使用指南
  15. 中国平安产险总经理易人 吴鹏已获保监会核准
  16. ++a与a++、--a与a--
  17. 试用mmdetection
  18. 微服务架构通讯模式架构分析
  19. virtualbox导入虚拟机(ubuntu)
  20. [日记] 招行的服务就是不错。。。。

热门文章

  1. axure9中继器实现数据动态新增/编辑/删除
  2. 如何通过聊天拉近与客户的距离?谈客户就像谈恋爱,得找对话题
  3. 结构化分析建模的基本步骤
  4. 解说论坛要用什么“花招”来留住用户
  5. php添加超链接到html,总结几种实现超链接html代码
  6. 鸢尾花数据集、月亮数据集二分类可视化分析
  7. 林克的小本本之——记一些基础的linux命令
  8. wamp怎么安装mysql服务器_wamp环境搭建(apache安装,mysql安装,php安装)
  9. mysql 主键重复则覆盖_mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法...
  10. 重庆宽带公网IPv6测试