「黑客必备技能」Python正则表达式详解
说在前面
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能。
正则表达式在不同的语言中使用方式不尽相同,不过只要学会了任意一门语言的正则表达式用法,其他语言中大部分也只是换了个函数的名称而已,本质都是一样的。
注:本文摘自 i 春秋社区(bbs.ichunqiu.com),欢迎更多优秀作者去社区投稿,帮助更多萌新们快速掌握新技能。文章阅读用时约10分钟。
原子
原子是正则表达式中最基本的单位,每个正则表达式中至少要包含一个原子。常见的原子类型:
- 普通字符作为原子
- 非打印字符作为原子
- 通用字符作为原子
- 原子表
普通字符作为原子
演示代码:
import re#引用re
string = "shentouyun"#定义整段,普通字符作为原子
pat = "yun"#提取yun
ret = re.search(pat,string)#第一个参数为提取,第二个为整个字段
print(ret)#输出
输出
<_sre.SRE_Match object; span=(7, 10), match='yun'>
非打印字符作为原子
什么是非打印字符,如\n,\t(换行,制表),代表一些操作的字符也可以作为原子
操作代码与小知识
string1 = '''shentouyun
nuibi
'''
pat1 = '\n'
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(10, 11), match='\n'>
小知识
#在这里解释一个基础,我没有提到过
string = '''
shentouyun
nuibi
'''
print(string)
#这段代码里,其特点为string被三引号包裹,并在代码里实现换行其运行结果
shentouyun
nuibi
#实现了一个\n的操作其代码等同于
string ="shentouyun\nnuibi"
print(string)
通用字符作为原子
什么是通用字符?
1. \w匹配任意一个字母数字或下划线;
2. \W匹配除去字母数字或下划线任意一个字符;
3. \d匹配十进制数;
4. \D除十进制以外的任意一个字符;
5. \s匹配一个空白字符;
6. \S除去空白字符。
简单的例子
string1 = "shentouyun3215454biji"
pat1 = '\d\d\d\d'#匹配四个十进制数
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(10, 14), match='3215'>
也可以混合使用
string1 = "shentouyun3215454biji"
pat1 = '\w\d\d\d\d'#匹配一个字母+匹配四个十进制数
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(9, 14), match='n3215'>
没有符合格式的,如空白就不会匹配出来,这里不过多的描述,占用空间。
原子表
[ots]任意的提取一个原子出来,直接任意选择一个原子表原子,如下:
string1 = "shentouyun3215454biji"
pat1 = "shen[otoasdjojds]ou"
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(0, 7), match='shentou'>
只从原子表中选择一个原子,其原子表内原子地位平等。
非原子表
符号^ 英文状态下的shift+6
字符串里出现了非原子表,返回None,其代码如下:
string1 = "shentouyun3215454biji"
pat1 = "shen[^tun]ou"
#shen后面应该是匹配t结果原子表里出了[tun]三个原子外其他的原子都可以匹配
#显然本代码中的原子是无法匹配的
ret=re.search(pat1,string1)
print(ret)
返回如下:
None
如果正常运行非原子表外的字符如string1字符串中截取的shen后面是t,在非原子表上,没有出现t,则返回shent。
string1 = "shentouyun3215454biji"
pat1 = "shen[^asd]"
#为了更加直白我把ou两个字符去掉了
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(0, 5), match='shent'>
元字符
特殊含义的字符
所谓的元字符,就是正则表达式中具有一些特殊含义的字符,比如重复N多次前面的字符。
"."除换行外任意一个字符
代码如下:
string1 = "shentouyun3215454biji"
pat1 = "shen.ou"#这里.匹配除了换行符外的任意字符
ret=re.search(pat1,string1)
print(ret)
运行结果
<_sre.SRE_Match object; span=(0, 7), match='shentou'>
当然你也可以多匹配些,比如多些点点。
string1 = "shentouyun3215454biji"
pat1 = "shen......"
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(0, 10), match='shentouyun'>
开始位置^与结束位置$
string1 = "shentouyun3215454biji"
pat1 = "^s..."
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(0, 4), match='shen'>
因为s是开始,也就是“排头”结束位置也同理。
string1 = "shentouyun3215454biji"
pat1 = "b...$"
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(17, 21), match='biji'>
*""0次1次多次**
string1 = "shentouyun3215454biji"
pat1 = "shen.*"
ret=re.search(pat1,string1)
print(ret)
运行后
<_sre.SRE_Match object; span=(0, 21), match='shentouyun3215454biji'>
为什么会全匹配,看*号的定义为多次,咱们的"."表示除了换行外全匹配,两者一配合。
+号与?号
+匹配多次,正常显示无法匹配0次,演示错误例子。
string1 = "shentouyun3215454biji"
pat1 = "a+"
ret=re.search(pat1,string1)
print(ret)
None
演示正确例子
string1 = "aaaaaaaaaaaa"
pat1 = "a+"
ret=re.search(pat1,string1)
print(ret)
<_sre.SRE_Match object; span=(0, 12), match='aaaaaaaaaaaa'>
问号就更好弄了
问号直接演示错误例子,无法显示多次
string1 = "aaaafsedfsfdffasafadaaaaaaaa"
pat1 = "a?"
ret=re.search(pat1,string1)
print(ret)
<_sre.SRE_Match object; span=(0, 1), match='a'>
{n}与{n,}
string1 = "aaaa"
pat1 = "a{4}"
ret=re.search(pat1,string1)
print(ret)
<_sre.SRE_Match object; span=(0, 4), match='aaaa'>
如果换成3呢
<_sre.SRE_Match object; span=(0, 3), match='aaa'>
打印了三次,成功演示了什么叫做至少,当然你多了不行,改成5试试。
None
{n,m}至少多少次,至多多少次
string1 = "aaaa"
pat1 = "a{3,5}"
ret=re.search(pat1,string1)
print(ret)
<_sre.SRE_Match object; span=(0, 4), match='aaaa'>
模式修正符
所谓的模式修正符,即可以在不改变正则表达式的情况下,通过模式修正符改变正则表达式的含义,从而实现一些匹配结果的调整等功能。
模式修正符有什么?
I忽略大小写
M多行匹配
L本地化识别匹配
U unicode编码
S让,匹配包括换行符
错误代码演示
string = "ShenTouYun"
pat="shen"
ret = re.search(pat,string)
print(ret)
返回None,因为默认有大小写限制,引用一下I就可以了。
string = "ShenTouYun"
pat="shen"
ret = re.search(pat,string,re.I)
print(ret)
运行结果
<_sre.SRE_Match object; span=(0, 4), match='Shen'>
贪婪模式与懒惰模式
贪婪模式的核心点就是尽可能多的匹配
懒惰模式的核心就是尽可能少的匹配
贪婪模式
string = "SheSnTouYunYS"
pat="s.*S"
ret = re.search(pat,string,re.I)
print(ret)
运行结果
<_sre.SRE_Match object; span=(0, 13), match='SheSnTouYunYS'>
贪婪模式与懒惰模式有什么用呢?
看对比
string = "SheSnTouYunYS"
pat="s.*S"#贪婪模式找到最后一个s
pat1="s.*?S"#懒惰模式,特征为?,找到第一个s就不往下找了
ret = re.search(pat,string,re.I)
ret1 = re.search(pat1,string,re.I)
print(ret)
print(ret1)
运行结果
<_sre.SRE_Match object; span=(0, 13), match='SheSnTouYunYS'>
<_sre.SRE_Match object; span=(0, 4), match='SheS'>
正则表达式函数
1、re.match( )函数从头开始匹配
2、re.search( )函数从任何地方开始匹配
3、全局匹配函数
match函数演示
string1 = "a**fewfaaa"
pat1 = "a"
ret=re.match(pat1,string1)
print(ret)
运行结果可匹配
<_sre.SRE_Match object; span=(0, 1), match='a'>
不是第一个开始匹配
string1 = "a**fewfaaa"
pat1 = "d"
ret=re.match(pat1,string1)
print(ret)
运行结果不可匹配
None
全局匹配函数
全局匹配格式
re.compile(正则表达式).findall(数据)
string1 = "a**fewfaaa"
pat1 = "d.*?a"
ret=re.compile(pat1).findall(string1)
print(ret)
结果
['da']
在码文中的一些杂乱代码
import re#引用re
'''
string = "shentouyun"#定义整段,普通字符作为原子
pat = "yun"#提取yun
ret = re.search(pat,string)#第一个参数为提取,第二个为整个字段
print(ret)#输出
match
sub
search
全局匹配
string = "SheSnTouYunYS"
pat="s.*S"#贪婪模式找到最后一个s
pat1="s.*?S"#懒惰模式,特征为?,找到一个y就不往下找了
ret = re.search(pat,string,re.I)
ret1 = re.search(pat1,string,re.I)
print(ret)
print(ret1)
'''
首先预热下,爬取豆瓣首页
导入urllib库下的request
import urllib.request
使用下urlopen打开网站返回HTML
urllib.request.urlopen("https://www.douban.com/")
读一下看看拿到了什么东西,使用read( ),并给douban保存方便再GUI里调用
douban = urllib.request.urlopen("https://www.douban.com/").read()
可以独立尝试,会非常卡。简单点是用len看字节
>>> len(douban)
105653
爬取豆瓣评论
导入正则模块(re)
import re
写了个例子
#豆瓣评论爬取小例子
import urllib.request
import re
douban = urllib.request.urlopen("https://movie.douban.com/subject/27199913/?from=showing").read().decode("UTF-8")
pat = '<span class="short">.*?</span>'
rst = re.compile(pat).findall(douban)
print(rst[0])
引用decode("UTF-8")对其解码为utf-8
正则为
<span class="short">(.*?)</span>
如何写正则与本例的细节
打开网站
https://movie.douban.com/subject/27199913/?from=showing
右键源代码
发现评论格式为
<span class="short">就是山西版本的《两杆大烟枪》或者说《疯狂的石头》,将山西风光和特色与影片融合的很好,虽然还是有所瑕疵,也难逃一些俗套烂大街的剧情和段子,但是还可以。</span>
所有评论被标签包裹,可以进行抓取,使用懒惰模式进行操作。
<span class="short">.*?</span>
"."全匹配,其细节为标签里有双引号,我们再写正则时使用单引号括起来,不要再使用双引号了。
写循环把东西都显示出来
for i in range(0,len(rst)):
print(rst[i])
运行为
>>> ================================ RESTART ================================
>>>
['一直很喜欢这种结构的电影,一圈圈地放出线团,再一段段收回,圆融又宿命。以山西籍为主的演员都挺走心的,生活的鸡飞狗走很是活灵活现,而且骆达华的出场太惊喜。导演说是改编太贵,索性自己写。但要是看过《提着心吊着胆》,会发现许多元素重合度很高,比如生意惨淡的饭店、存在问题的夫妇、警察、笨贼、拜金女、装大款……就连意外之财也是丢在饭店里。电影结尾顾虑较多,但整体完成度与幽默感不差。@平遥,特意买票支持,却来...', '算是一部跟期待打平的作品吧,中规中矩,没有惊艳,王大治倒是真有那么几分长相之外的亮点。故事一圈圈闪回,重复的部分有点多,生怕观众跟不上这个倒叙+插叙的节奏似的。四川话河南话陕西话山西话一锅烩,泱泱大中华式的热闹。想要揭示人心叵测,但终归是浅了一点。【平遥电影节2018.10.19', '这种结构挺好', '审美疲劳,这种太多了,都大同小异。从每组人物的角度,反复讲同一个事。国产电影里的歹徒劫匪都是来搞笑的,都是**,呵呵。', '巧就巧在结构上。']
一直很喜欢这种结构的电影,一圈圈地放出线团,再一段段收回,圆融又宿命。以山西籍为主的演员都挺走心的,生活的鸡飞狗走很是活灵活现,而且骆达华的出场太惊喜。导演说是改编太贵,索性自己写。但要是看过《提着心吊着胆》,会发现许多元素重合度很高,比如生意惨淡的饭店、存在问题的夫妇、警察、笨贼、拜金女、装大款……就连意外之财也是丢在饭店里。电影结尾顾虑较多,但整体完成度与幽默感不差。@平遥,特意买票支持,却来...
算是一部跟期待打平的作品吧,中规中矩,没有惊艳,王大治倒是真有那么几分长相之外的亮点。故事一圈圈闪回,重复的部分有点多,生怕观众跟不上这个倒叙+插叙的节奏似的。四川话河南话陕西话山西话一锅烩,泱泱大中华式的热闹。想要揭示人心叵测,但终归是浅了一点。【平遥电影节2018.10.19
这种结构挺好
审美疲劳,这种太多了,都大同小异。从每组人物的角度,反复讲同一个事。国产电影里的歹徒劫匪都是来搞笑的,都是**,呵呵。
巧就巧在结构上。
>>>
保存到本地
fh = open("G:\\python\\doubanpinglun.txt","w")#打开文件并新建doubanpinglun.txt
open里的路径为本地路径
完整代码如下:
#豆瓣评论爬取小例子
import urllib.request
import re
douban = urllib.request.urlopen("https://movie.douban.com/subject/27199913/?from=showing").read().decode("UTF-8")
pat = '<span class="short">(.*?)</span>'
rst = re.compile(pat).findall(douban)
print(rst)
fh = open("G:\\python\\doubanpinglun.txt","w")#打开文件并新建doubanpinglun.txt
for i in range(0,len(rst)):
print(rst[i])
fh.write(rst[i]+"\n")#写入文件
fh.close()#关闭文件
以上就是今天分享的内容,大家学会了吗?
「黑客必备技能」Python正则表达式详解的更多相关文章
- python 正则表达式详解
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能 ...
- Python正则表达式详解——re库
一.简介 1.1.相关链接 官方文档: Python2:https://docs.python.org/2/library/re.html Python3:https://docs.python.or ...
- Linux 网络分析必备技能:tcpdump 实战详解
大家好,我是肖邦,这是我的第 11 篇原创文章. 今天要分享的是 tcpdump,它是 Linux 系统中特别有用的网络工具,通常用于故障诊断.网络分析,功能非常的强大. 相对于其它 Linux 工具 ...
- Python正则表达式详解
我用双手成就你的梦想 python正则表达式 ^ 匹配开始 $ 匹配行尾 . 匹配出换行符以外的任何单个字符,使用-m选项允许其匹配换行符也是如此 [...] 匹配括号内任何当个字符(也有或的意思) ...
- python正则表达式详解之Match类及其方法
1.Match对象简介 match对象通常是由正则表达式对象的match 方法,search 方法等经过匹配之后而产生.可以直接当做bool值使用,如果匹配则相当于True, 如果不匹配,则返回Non ...
- Java 正则表达式详解_正则表达式
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- Django url配置 正则表达式详解 分组命名匹配 命名URL 别名 和URL反向解析 命名空间模式
Django基础二之URL路由系统 本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11版本 ...
- Linux文本处理三剑客之grep及正则表达式详解
Linux文本处理三剑客之grep及正则表达式详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux文本处理三剑客概述 grep: 全称:"Global se ...
- JavaScript正则表达式详解(一)正则表达式入门
JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...
随机推荐
- Tomcat启动分析(一)-从脚本到main函数分析
当我们在Linux下启动tomcat的时候,通过ps查看其进程信息为,接下来的内容我们就以此进行分析: [tomcat@fdd ~]$ ps -ef |grep java tomcat : tty1 ...
- SparkStreaming整合flume
SparkStreaming整合flume 在实际开发中push会丢数据,因为push是由flume将数据发给程序,程序出错,丢失数据.所以不会使用不做讲解,这里讲解poll,拉去flume的数据,保 ...
- docker网络之(三)
docker4种网络 基于docker run创建容器时,可以使用--net选项指定容器的网络模式:Docker默认有以下4种网络模式: host模式,使用--net=host指定 container ...
- 【洛谷P4589】[TJOI2018]智力竞赛(二分+最小链覆盖)
洛谷 题意: 给出一个\(DAG\),现在要选出\(n+1\)条可相交的链来覆盖,最终使得未被覆盖的点集中,权值最小的点的权值最大. 思路: 显然最终的答案具有单调性,故直接二分答案来判断: 直接将小 ...
- c# WF 第8节 label控件
本节内容: 1: 文本控件 2:实现label的你追我赶实例 1:文本控件 2:实现label的你追我赶实例 步骤1 : 步骤2 : 知识点:
- 微信小程序-自定义方法的抛出与引用
一. 定义方法与抛出(utils/foo.js文件中) function say () { console.log('自定义的say方法')} # 定义方法 module.exports = {sa ...
- 【CF464E】The Classic Problem(主席树+最短路)
点此看题面 大致题意: 给你一张无向图,每条边的边权为\(2^{x_i}\),求\(s\)到\(t\)的最短路. 最短路 最短路,首先考虑\(Dijkstra\).这里用\(SPFA\)似乎不太好,因 ...
- Python源码:字典
一.创建增加修改 1.实现代码 #创建 stu_info = { "xiedi":28, "liuhailin":27,"daiqiao": ...
- P1验证性内容
#include<stdio.h> int main() { printf("201983270555"); return 0; } #include<stdio ...
- Vue学习记录(二)-打包问题
由于项目需要,vue项目在build打包 之后,希望有一个类似wbeconfig的配置文件.方便判断应用所处的环境.进行相应的逻辑处理. 这边暂时记录一下思路,具体请看友情链接. 方案一:从环境变量下 ...