前言

在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. 编程感悟-建立好代码sop

    1.最近学django和python,发现很多的函数记不住,这时候我百度了一下,发现记不住是程序员的正常情况, 这下心安理得多了,记好笔记和咱的sop吧,会很快. 社会是不是也这样,好多东西也记不住, ...

  2. Ubuntu修改系统时间

    在新版的ubuntu中,使用timedatectl 替换了ntpdate来进行时间管理. 1.查看当前时间状态 查看当前时间状态 timedatectl status : res@ubuntu:~$ ...

  3. 关于Asp.net事件,如何在触发子控件的事件时,同步触发父页面的事件

    对页面引用自定义控件后,通过绑定自定义事件,页面绑定子控件的事件,在子控件做了某些修改动作后,如何同步操作父页面的方法:下面我煮了个栗子,同学们可以来尝一尝试一试 a.aspx 引用 UserCont ...

  4. django安装及简单使用

    1 web应用2 cs和bs架构3 http协议----重点 -特点:1 2 3 4 -请求头: 请求首行 get / http/1.1\r\n key:value\r\n key:value\r\n ...

  5. appium安装问题集锦

    问题一: MacBook-Air:Cellar$ npm -v dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dyl ...

  6. vector作为二维数组

    vector本来就是可以用来代替一维数组的,vector提供了operator[]函数,可以像数组一样的操作,而且还有边界检查,动态改变大小. 这里只介绍用它来代替二维的数组,二维以上的可以依此类推. ...

  7. 1-C++的并发世界

    1.1 何谓并发 并发的两种方式 多核机器上的真正并行 单核机器的任务切换 并发的两种途径 多进程并发 1.1 多进程并发需要通过操作系统进行进程间通信 多线程并发 2.1 多线程并发需要共享内存 1 ...

  8. 《JavaScript 高级程序设计》读书笔记二 使用JavaScript

    一   <script>元素 a.四个属性: async:立即异步加载外部脚本: defer:延迟到文档完全被解析再加载外部脚本: src:外部脚本路径: type:脚本语言的内容类型: ...

  9. apache与tomcat负载集群集成方法配置

    apache与tomcat负载集群集成方法有3种jk.jk_proxy.http_proxy apache:httpd-2.2.17-win32-x86-no_ssl.msi tomcat:apach ...

  10. 816. Ambiguous Coordinates

    We had some 2-dimensional coordinates, like "(1, 3)" or "(2, 0.5)".  Then, we re ...