#19 re&jieba模块
前言
在python中,需要对字符串进行大量的操作,有时需要从一个字符串中提取到特定的信息,用切片肯定是不行的,所有这一节记录两个强大的文本处理模块,一个是正则表达式re模块,另一个是中文处理模块jieba,here wo go!
一、re模块
re模块的出现使得python完全支持正则表达式,在学re模块之前,先来认识一下正则表达式
正则表达式使用单个字符串来描述、匹配出特定句法的字符串,在文本编辑中,正则表达式常用来检索、替换那些特定匹配模式的文本。正则表达式使用起来十分繁琐,但是它带来的功能确实无比强大的,掌握正则表达式之后,工作效率将会大幅度提高!
1. 正则表达式基本语法
定位符
正则表达式 描述 示例 ^ 行起始标记 ^import 匹配以import开头的行 $ 行尾标记 import$ 匹配以import结尾的行
限定符
正则表达式 描述 示例 . 匹配任意一个字符 impor.可以匹配到import、imporq、impor1等 + 匹配之前项1次或者多次 import+可以匹配到import、importt、importtt等,但是不能匹配到impor * 匹配之前项0次或者多次 import*可以匹配到impor、import、importt、importtt等 ? 匹配之前项0次或者1次 impor?t可以匹配到impot、import,但是不能匹配到imporrt [] 匹配包含在[字符]的任意字符 impor[tk]可以匹配到import、impork、importk、imporkt [^] 匹配不包含在[^字符]的任意字符 impor[^tk]匹配不到import、impork、importk、imporkt
[ - ] 匹配[字符-字符]中指定范围的任意一个字符 1234[5-7]可以匹配到12345、12346、12357
{n} 匹配之前项n次 [0-9]{5}表示匹配任意一个五位数
{n,} 匹配之前项至少n次 [0-9]{5,}表示匹配任意一个五位以上的数(包含五位数)
{n,m} 匹配之前项n到m次 [0-9]{5,7}表示匹配任意一个五位到七位的数(包含五位数和七位数)
标记符
正则表达式 描述 示例 () 标记一个子表达式的开始和结束位置,供以后使用 ([0-9])表示匹配一个数字,之后可以使用它,比如替换掉它
转义符
正则表达式 描述 \n 匹配一个换行符 \f 匹配一个换页符 \r 匹配一个回车符 \s 匹配任何空白字符 \s 匹配任何非空白字符 \t 匹配一个制表符 \v 匹配一个垂直制表符 \cx 匹配一个control-x,x在a-z和a-z之间
\w 匹配数字字母下划线
\w 不匹配数字字母下划线
\d 匹配数字
\d 不匹配数字
\b 匹配一个单词边界,也就是指单词的结尾
\b 匹配非单词边界
说明:想要匹配出上述特殊字符,需要对其进行转义,例如想要匹配*号,则需要这样写\*
贪婪匹配和非贪婪匹配
贪婪匹配是全匹配,一直匹配到最后一个为止;非贪婪匹配则是匹配到一个就停止
正则表达式 描述 .* 贪婪匹配 .*? 非贪婪匹配 # <a>hello,world!</a> #贪婪匹配:<.*>匹配到<a>hello,world!</a> #非贪婪匹配:<.*?>匹配到<a>
2. re模块
re.match(pattern, string, flags=0) 「从字符串开头匹配一次,匹配成功返回结果,匹配失败返回none;pattern表示匹配模式、string表示原字符串、flags表示标志位,用来控制匹配模式」
in [7]: import re # 导入re模块 in [8]: test = 'qwer1234asdf5678' #初始化一个字符串,用来示例 in [9]: re.match('\w', test) # 从开头匹配一个字母或数字或下划线 out[9]: <_sre.sre_match object; span=(0, 1), match='q'> in [10]: re.match('\w+', test) # 从开头匹配数字或字母或下划线多个 out[10]: <_sre.sre_match object; span=(0, 16), match='qwer1234asdf5678'> in [11]: re.match('\w.', test) # 从开头匹配一个字母或数字或下划线 和 一个任意字符 out[11]: <_sre.sre_match object; span=(0, 2), match='qw'> in [12]: re.match('\w*', test) # 从开头匹配一个字母或数字或下划线 和 其他所有字符 out[12]: <_sre.sre_match object; span=(0, 16), match='qwer1234asdf5678'> in [14]: re.match('\w{5}', test) # 从开头匹配5个字母或数字或下划线 out[14]: <_sre.sre_match object; span=(0, 5), match='qwer1'>
in [15]: re.match('\d',test) # 从开头匹配一个数字 # 匹配失败,返回none(也就是啥也不返回)
re.search(pattern, string, flags=0) 「从整个字符串中匹配一次,匹配成功返回结果,匹配失败返回none;pattern表示匹配模式、string表示原字符串、flags表示标志位,用来控制匹配模式」
in [17]: test out[17]: 'qwer1234asdf5678' in [18]: re.search('\w',test) # 匹配一个字母或数字或下划线 out[18]: <_sre.sre_match object; span=(0, 1), match='q'> in [19]: re.search('\d',test) # 匹配一个数字,即使数字不在开头也可以匹配到 out[19]: <_sre.sre_match object; span=(4, 5), match='1'>
re.findall(pattern, string, flags=0) 「从整个字符串中匹配多次,匹配成功返回所有结果的列表,匹配失败则返回空列表;pattern表示匹配模式、string表示原字符串、flags表示标志位,用来控制匹配模式」
in [25]: test out[25]: 'qwer1234asdf5678' in [26]: re.findall('\d',test) # 将所有数字匹配出来,返回列表 out[26]: ['1', '2', '3', '4', '5', '6', '7', '8']
re.finditer(pattern, string, flags=0) 「与findall类似,只是返回迭代器」
in [27]: test out[27]: 'qwer1234asdf5678' in [28]: re.finditer('\d',test) # 可以看到返回的是迭代器 out[28]: <callable_iterator at 0x1037e4c88> in [29]: for _ in re.finditer('\d',test): ...: print(_) <_sre.sre_match object; span=(4, 5), match='1'> <_sre.sre_match object; span=(5, 6), match='2'> <_sre.sre_match object; span=(6, 7), match='3'> <_sre.sre_match object; span=(7, 8), match='4'> <_sre.sre_match object; span=(12, 13), match='5'> <_sre.sre_match object; span=(13, 14), match='6'> <_sre.sre_match object; span=(14, 15), match='7'> <_sre.sre_match object; span=(15, 16), match='8'>
标志位flags
标志位 描述 re.i 无视大小写 re.l 本地化识别匹配 re.s 使.匹配所有字符,默认情况下.不匹配换行符 re.m 多行匹配,将影响^和$ re.u 根据unicode字符集解析,将影响\w,\w,\b,\b re.x 通过给予更灵活的格式以便将正则表达式写得更易于理解
in [30]: test = 'abcd123qwer567' in [31]: re.findall('[a-z]', test) # 匹配小写字母 out[31]: ['q', 'w', 'e', 'r'] in [33]: re.findall('[a-z]', test, re.i) # 匹配字母,不区分大小写 out[33]: ['a', 'b', 'c', 'd', 'q', 'w', 'e', 'r']
in [34]: re.findall(pattern, string, re.i|re.m|re.s) # 多个标志位的写法
re.compile(pattern, flags=0) 「生成一个pattern对象,用于re.match、re.search、re.findall」
in [36]: test out[36]: 'abcd123qwer567' in [37]: pattern = re.compile('\d') # 生成一个pattern对象 in [38]: re.findall(pattern, test) out[38]: ['1', '2', '3', '5', '6', '7'] in [39]: re.match(pattern, test) in [40]: re.search(pattern, test) out[40]: <_sre.sre_match object; span=(4, 5), match='1'>
re.sub(pattern, repl, string, count=0, flags=0) 「替换匹配的字符串,pattern表示匹配模式、repl表示替换成的字符串,string表示原字符串(被替换字符串)、flags表示标志位,用来控制匹配模式」
in [51]: test = 'adfsa12fsf3456sfs234' in [52]: pattern = '\d' # 匹配非数字 in [53]: re.sub(pattern, '',test) # 将非数字替换为空 out[53]: '123456234' # 结果只留下数字
贪婪匹配与非贪婪匹配
in [56]: test = '<h1>i am <minutesheep></h1>' in [57]: greedy_pattern = re.compile('>(.*)<') # 贪婪匹配模式 in [58]: no_greedy_pattern = re.compile('>(.*?)<') # 非贪婪匹配模式 in [59]: re.findall(greedy_pattern, test) # 贪婪匹配结果,寻找最后一个< out[59]: ['i am <minutesheep>'] in [60]: re.findall(no_greedy_pattern, test) # 非贪婪匹配结果,寻找第一个< out[60]: ['i am ', '']
通常情况下先使用re.compile(非贪婪匹配)生成一个匹配模式,再使用re.findall()返回结果列表进行下一步操作
二、jieba模块
上面的re模块是否让你热血沸腾,正则表达式熟练使用后会给你的工作效率带来飞一般的提高,但如果让其来对一段中文进行分析词语来说,还是欠缺了许多,对于中文分词来说,第三方模块jieba会给你带来意想不到的结果
1. jieba安装
使用pip安装
pip install jieba
2. jieba分词模式
jieba拥有三种分词模式:精确模式、全模式、搜索引擎模式
2.1 精确模式(默认模式)jieba.cut(sentence, cut_all=false, hmm=true) 或者 jieba.lcut(sentence, cut_all=false, hmm=true) 「cut返回生成器,lcut返回列表;sentence表示要分割的句子、cut_all表示是否为全模式、hmm表示是否使用hmm」
in [1]: import jieba # 导入jieba模块 in [3]: test = '正则表达式熟练使用后会给你的工作效率带来飞一般的提高' in [4]: jieba.cut(test) # 精确模式,返回生成器 out[4]: <generator object tokenizer.cut at 0x1059c6990> in [6]: ':'.join(jieba.cut(test)) out[6]: '正则表达式:熟练:使用:后会:给:你:的:工作效率:带来:飞:一般:的:提高' in [7]: jieba.lcut(test) # 返回列表 out[7]: ['正则表达式', '熟练', '使用', '后会', '给', '你', '的', '工作效率', '带来', '飞', '一般', '的', '提高']
2.2 全模式 jieba.cut(sentence, cut_all=true, hmm=true) 或者 jieba.lcut(sentence, cut_all=true, hmm=true)
in [8]: test out[8]: '正则表达式熟练使用后会给你的工作效率带来飞一般的提高' in [9]: jieba.cut(test, cut_all=true) # 使用全模式 out[9]: <generator object tokenizer.cut at 0x1059c02b0> in [10]: ':'.join(jieba.cut(test, cut_all=true)) out[10]: '正则:正则表达式:表达:表达式:达式:熟练:使用:后会:给:你:的:工作:工作效率:效率:带来:飞:一般:般的:提高'
2.3 搜索引擎模式 jieba.cut_for_search(sentence, hmm=true) 或者 jieba.cut_for_search(sentence, hmm=true) 「搜索引擎模式粒度较细」
in [12]: test out[12]: '正则表达式熟练使用后会给你的工作效率带来飞一般的提高' in [13]: jieba.cut_for_search(test) # 使用搜索引擎模式 out[13]: <generator object tokenizer.cut_for_search at 0x10b2acaf0> in [14]: ':'.join(jieba.cut_for_search(test)) out[14]: '正则:表达:达式:表达式:正则表达式:熟练:使用:后会:给:你:的:工作:效率:工作效率:带来:飞:一般:的:提高'
通过上述三种模式可以明显看到分词的不同,根据世纪使用需求来确定使用那种模式吧
3. jieba添加词典
jieba模块中默认使用的词典为jieba.dt,默认的词典有时没有我们要用的词语,只有自己添加或调整词典才能解决
3.1 使用jieba函数增加新词 jieba.add_word(word, freq=none, tag=none) 「word表示新词、freq表示词频、tag表示词性」
in [24]: test out[24]: '正则表达式熟练使用后会给你的工作效率带来飞一般的提高' in [25]: ':'.join(jieba.cut(test, hmm=false)) out[25]: '正则表达式:熟练:使用:后:会:给:你:的:工作效率:带来:飞:一般:的:提高' in [26]: jieba.add_word('后会') # 增加新词:后会 in [27]: ':'.join(jieba.cut(test, hmm=false)) out[27]: '正则表达式:熟练:使用:后会:给:你:的:工作效率:带来:飞:一般:的:提高' # 注意:自己添加新词或者改变词频后,使用hmm可能使新词无用
3.2 删除词语 jieba.del_word(word) 「删除词语」
in [29]: jieba.del_word('后会') # 删除词语:后会
3.3 改变词频 jieba.suggest_freq(segment, tune=false) 「segment表示要修改的词,用元组表示,tune表示是否能被分出来」
in [31]: test out[31]: '正则表达式熟练使用后会给你的工作效率带来飞一般的提高' in [32]: ':'.join(jieba.cut(test)) out[32]: '正则表达式:熟练:使用:后:会:给:你:的:工作效率:带来:飞:一般:的:提高' in [35]: jieba.suggest_freq(('正则','表达式'),true) # 允许(正则、表达式)被分割出来,返回0则证明成功 out[35]: 0 in [36]: ':'.join(jieba.cut(test)) out[36]: '正则:表达式:熟练:使用:后:会:给:你:的:工作效率:带来:飞:一般:的:提高'
3.4 使用文件添加词典 jieba.load_userct(file_name) 「file_name表示要加载的字典文件名」
有时需要添加大量的新词汇,总不能一条一条的敲代码,jieba有一个加载新字典的方法:jieba.load_userct(file_name)
对要加载的字典是有格式要求的,一个词占一行,一行有三个部分(词语、词频、词性),用空格隔开,顺序不可颠倒,其中,词频和词性可以省略
4. 词频分析
4.1 词频分析 jieba.analyse.extract_tags(sentence, topk=20, withweight=false, allowpos=(), withflag=false) 「sentence表示要分析的句子、topk表示返回多少个高频词语(默认为20个)、withweight表示返回词语时是否带权重、allowpos表示仅分析指定词性的词」
import jieba.analyse # 需要单独导入jieba.analyse test = ''' 《红楼梦》,中国古典长篇章回小说,是中国四大小说名著之一。《红楼梦》书内提及的别 名,还有《情僧录》、《风月宝鉴》[1]、《金陵十二钗》、《金玉缘》;故事是从女娲补>天时所剩下的一块石头讲起,因此又名《石头记》。乾隆四十九年甲辰(1784年)梦觉主人 序本题为《红楼梦》(甲辰梦序抄本)。1791年在第一次活字印刷(程甲本)后,《红楼梦》便取代《石头记》成为通行的书名。 原本前80回尚存。全本回数问题有两说:据脂砚斋批语,应少于114回;而据高鹗、程伟元>的版本,为百二十回。后来高鹗、程伟元取得后40回稿,并整理印行,即为目前较通行的120回全本。 程伟元称,自己经过多年收集,重金购得《红楼梦》后四十回残稿,并对不连贯的地方进行补缀。于1791年和1792年印行一百二十回《红楼梦》。一百多年间,《红楼梦》以此流传,受到读者欢迎。 从1969年代开始,胡适“大胆假设、小心求证”,认为后四十回非曹雪芹著,并提出高鹗续书后四十回,且后四十回不如前八十回,程乙本并非红楼梦最佳读本。胡适在甲戌本跋中举例,天香楼事合家皆知,“无不纳罕,都有些疑心”,程乙本竟作“无不纳闷,都有些伤心”,只 有些伤心而已吗?完全扭曲上下文意。 人民文学出版社认为后四十回是无名氏续,高鹗、程伟元整理。另外周汝昌则认为《红楼梦》原著共108回,现存78回,后30回迷失。 《红楼梦》被评为中国古典章回小说的巅峰之作,思想价值和艺术价值极高。在20世纪,《红楼梦》是中国最受重视的一部文学作品之一。因为其不完整,加上作者曹氏已亡故,所述内容又钜细靡遗,结局设定更是超乎寻常,留下许多谜团引人探究,也构成了一门学问——红 学。自胡适作《红楼梦考证》以来,一般认为曹雪芹以其家族的命运投射在《红楼梦》一书。 ''' print(jieba.analyse.extract_tags(test, withweight=true))
# 运行结果:
building prefix dict from the default dictionary ...
loading model from cache /var/folders/n_/mj10v8d10h32_dzzwb8y3hs80000gn/t/jieba.cache
loading model cost 0.800 seconds.
prefix dict has been built succesfully.
[('红楼梦', 0.5276318504898648), ('四十回', 0.297466902509009), ('高鹗', 0.2214637790900901), ('程伟元', 0.21540121626846845), ('胡适', 0.13942106369594595), ('甲辰', 0.1090893529972973), ('程乙本', 0.10770060813423422), ('1791', 0.10770060813423422), ('章回小说', 0.09970688565675676), ('全本', 0.0987048529081081), ('石头记', 0.09738410088828829), ('曹雪芹', 0.09400848422702703), ('印行', 0.0883453431509009), ('认为', 0.06910881164756758), ('伤心', 0.0672914105409009), ('通行', 0.06724799354603603), ('无不', 0.06671542428864866), ('古典', 0.06622546765531531), ('有些', 0.06305848415594595), ('周汝昌', 0.0626156650990991)]
python test.py 1.81s user 0.17s system 99% cpu 1.993 total
5.并行分词
5.1 打开并行分词 jieba.enable_parallel(num) 「num代表并行进程数」
5.2 关闭并行分词 jieba.disable_parallel()
in [1]: import jieba in [2]: jieba.enable_parallel(4) # 开启4个进程 building prefix dict from the default dictionary ... loading model from cache /var/folders/n_/mj10v8d10h32_dzzwb8y3hs80000gn/t/jieba.cache loading model cost 0.793 seconds. prefix dict has been built succesfully. in [4]: jieba.cut('我爱北京*') out[4]: <generator object _pcut at 0x108dfc1a8> in [5]: jieba.disable_parallel() # 关闭并行分词
下一篇: Unity shader实现百叶窗特效
推荐阅读
-
php_curl扩展模块无法正常加载的处理方法_PHP教程
-
zend framework多模块多布局配置
-
查看PHP opcode扩展模块及Web服务
-
PHP之APC缓存详细介绍 apc模块安装_PHP
-
PHP5.3连接Oracle客户端及PDO_OCI模块的安装方法,php5.3pdo_oci_PHP教程
-
apache2.0.39 php4.2.3在windowsXP下模块方式搭建.
-
ThinkPHP的RBAC权限管理模块,该如何处理
-
用php开发一个检测某网站是否在一般运行的小模块
-
[置顶] 详细解释:nginx中ChsHttpLogModule模块配置及各
-
Linux 平台下Oracle 9i/10g/11gR1 IO-Fencing 的hangcheck-timer 模块说