前言

在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=''>

re.findall(pattern, string, flags=0) 「从整个字符串中匹配多次,匹配成功返回所有结果的列表,匹配失败则返回空列表;pattern表示匹配模式、string表示原字符串、flags表示标志位,用来控制匹配模式」

In [25]: test
Out[25]: 'qwer1234asdf5678' In [26]: re.findall('\d',test) # 将所有数字匹配出来,返回列表
Out[26]: ['', '', '', '', '', '', '', '']

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=''>
<_sre.SRE_Match object; span=(5, 6), match=''>
<_sre.SRE_Match object; span=(6, 7), match=''>
<_sre.SRE_Match object; span=(7, 8), match=''>
<_sre.SRE_Match object; span=(12, 13), match=''>
<_sre.SRE_Match object; span=(13, 14), match=''>
<_sre.SRE_Match object; span=(14, 15), match=''>
<_sre.SRE_Match object; span=(15, 16), match=''>

标志位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]: ['', '', '', '', '', ''] In [39]: re.match(pattern, test) In [40]: re.search(pattern, test)
Out[40]: <_sre.SRE_Match object; span=(4, 5), match=''>

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]: '' # 结果只留下数字

贪婪匹配与非贪婪匹配

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 []: import jieba              # 导入jieba模块

In []: test = '正则表达式熟练使用后会给你的工作效率带来飞一般的提高'

In []: jieba.cut(test)           # 精确模式,返回生成器
Out[]: <generator object Tokenizer.cut at 0x1059c6990> In []: ':'.join(jieba.cut(test))
Out[]: '正则表达式:熟练:使用:后会:给:你:的:工作效率:带来:飞:一般:的:提高' In []: jieba.lcut(test) # 返回列表
Out[]: ['正则表达式', '熟练', '使用', '后会', '给', '你', '的', '工作效率', '带来', '飞', '一般', '的', '提高']

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() # 关闭并行分词

#19 re&jieba模块的更多相关文章

  1. 浅析文本挖掘(jieba模块的应用)

    一,文本挖掘 1.1,什么是文本挖掘 文本挖掘是指从大量文本数据中抽取事先未知的,可理解的,最终可用的知识的过程,同时运用这些知识更好的组织信息以便将来参考 1.2,文本挖掘基本流程 收集数据 数据集 ...

  2. Ansible运维自动化工具19个常用模块使用实例【转】

    一.模块列表 1.setup 2.ping 3.file 4.copy 5.command 6.shell 7.script 8.cron 9.yum 10.service 11.group 12.u ...

  3. jieba模块

    jieba模块 下载 pip install jieba 使用 import jieba 精确模式 jieba.cut() 直接打印出的是单个文字 转换成列表-->jieba.lcut() im ...

  4. python从入门到大神---Python的jieba模块简介

    python从入门到大神---Python的jieba模块简介 一.总结 一句话总结: jieba包是分词技术,也就是将一句话分成多个词,有多种分词模型可选 1.分词模块包一般有哪些分词模式(比如py ...

  5. python jieba模块详解

    借鉴于 [jieba 模块文档] 用于自己学习和记录! jieba 模块是一个用于中文分词的模块 此模块支持三种分词模式 精确模式(试图将句子最精确的切开,适合文本分析) 全模式(把句子在所有可以成词 ...

  6. Python的jieba模块简介

    现如今,词云技术遍地都是,分词模块除了jieba也有很多,主要介绍一下jieba的基本使用 import jieba import jieba.posseg as psg from os import ...

  7. Python自动化运维之19、Paramiko模块和堡垒机实战

    paramiko模块 paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实 ...

  8. python基础===jieba模块,Python 中文分词组件

    api参考地址:https://github.com/fxsjy/jieba/blob/master/README.md 安装自行百度 基本用法: import jieba #全模式 word = j ...

  9. 19 Python 正则模块和正则表达式

    什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...

随机推荐

  1. python实现异步调用函数

    import time from concurrent.futures import ThreadPoolExecutor def RunBenchmark(url): print('GET %s' ...

  2. aircrakf

    airmon-ng start wlan0 airodump-ng wlan0mon#find the wifi airodump-ng -w yakoazz -c 1 --bssid BE:5F:F ...

  3. django 如何接收bootstrap-table传送的 ajax数组

    今天在用django传递id的时候,使用 alert(ids)以及console.log("id:",ids),都可以看到是把选中的数据的id打印出来的,用console.log可 ...

  4. 【慕课网实战】三、以慕课网日志分析为例 进入大数据 Spark SQL 的世界

    前置要求: 1)Building Spark using Maven requires Maven 3.3.9 or newer and Java 7+ 2)export MAVEN_OPTS=&qu ...

  5. [solution]JZOJ-5838 旅游路线

    [solution] JZOJ-5838 旅游路线 Time Limits 1000ms,Memory Limits 128MB 题面 Description GZOI队员们到X镇游玩.X镇是一个很特 ...

  6. python中的三种输入方式

    python中的三种输入方式 python2.X python2.x中以下三个函数都支持: raw_input() input() sys.stdin.readline() raw_input( )将 ...

  7. python_flask 基础巩固 (URL_FOR 详解)

    URL_FOR 详解 url_for 通过 视图函数能够返回对应的url,url_for 有两个参数,endpoint(视图 函数)和关键字参数 url_for('my_list',page=2),多 ...

  8. SqlServer 连接 相关。

    sqlserver数据库连接池是一个客户端的东西.和sql server服务器无关. 各种provider默认的连接池大小不同. 比如:Ado.NET 中sqlserver 连接池默认的值是100. ...

  9. kubernets基础

    1.定义和功能. 1.1定义:kubernets解释为舵手或者飞行员,以Borg为主衍生出. 1.2功能:自动装箱,自我修复,水平扩展,服务发现和负载均衡,自动发布和回滚. 密钥和配置管理,存储编排, ...

  10. Promise(一)

    每个Promise对象就是一个值的代理,这个值在Promise创建时可以是未知的.Promise对象允许你为异步事件的成功操作和失败操作分别绑定对应的处理方法,让异步方法可以像同步方法那样返回值,但不 ...