Python基础语法:正则表达式
概念:
从大量的信息中,通过一些表达式提取我们关注的数据。正则表达式就是其中一种进行数据筛选的表达式。
1. 原子:
原子是正则表达式中最基本的组成单位,每个正则表达式至少要包含一个原子,常见的原子类型有:
-
普通字符作为原子
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的 string="I like Python" pat="like" #正则表达式函数 rst=re.search(pat,string) # search(想要搜索的内容,搜索来源的内容) print(rst)
-
非打印字符作为原子
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的 # 非打印字符作为原子 #\n 换行符 \t 制表符 string='''I like Python anaconda ''' # 三个引号中间可以引入换行的内容 pat="\n" rst=re.search(pat,string) print(rst)
-
通用字符作为原子(比如十进制的数)
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的 #通用字符作为原子 ''' 字符 字符代表的含义 \w 字母、数字、下划线 \W 除字母、数字、下划线 \d 十进制数字 \D 除十进制数字 \s 空白字符 \S 除空白字符 ''' string='''I like19 6172 Python''' pat="\w\d\s\d\d" rst=re.search(pat,string) print(rst)
-
原子表
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的 #原子表 ''' []表示,匹配时,从[]里面的选择一个内容即可,里面的原子地位是平等的。 []里面有 ^ 符号时,表示除 [] 里面的原子都要提取 ''' string='''I like Python''' #pat="li[kgjd]e" pat="li[^abc]e" rst=re.search(pat,string) print(rst)
2. 元字符
就是正则表达式中具有一些特殊含义的字符,比如连续重复N次的字符。
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的
#元字符
'''
元字符 代表的内容
. 除换行外任意一个字符
^ 匹配开始位置
$ 匹配结束位置
* 前面原子出现 0\1\多次
? 前面原子出现 0\1次
+ 前面原子刚好出现 1\多次
{n} 前面原子出现恰好 n 次
{n,} 前面原子出现至少 n 次
{n,m} 前面原子出现至少n,至多m次
| 模式选择符或
() 模式单元
'''
string='''Tragedy and delight, hand in hand.'''
pat1="Tra..." # 匹配Tra后面接三个不为换行符的字符
pat2="^Tra..." # 匹配以Tra 开头的后面接两个不为换行符的字符
pat3="han.$" # 匹配以 han 加一个不为换行符的字符结尾
pat4="and.*" # 匹配该语句前面出现 and 加一个不为换行符的字符,且这部分出现了 0\1\多次
pat5="del +" # 匹配该语句前面出现 del ,且del出现了 1\多次
pat6="age{1,2}" # 匹配该语句前面出现 age ,且这部分出现至少1次,至多2次
rst1=re.search(pat1,string)
rst2=re.search(pat2,string)
rst3=re.search(pat3,string)
rst4=re.search(pat4,string)
rst5=re.search(pat5,string)
rst6=re.search(pat6,string)
print(rst1)
print(rst2)
print(rst3)
print(rst4)
print(rst4)
print(rst6)
注意:
-
末尾的 . 也算一个字符,所以 pat3 是匹配不上的。
-
*、?、+ 匹配时不是匹配前面整个部分出现多少次,而是前面整个部分最后一个字符出现的次数。
test* -- 可以匹配 tes、test、testt...... test? -- 可以匹配 tes、test test+ -- 可以匹配 test、testt、testtt......
3. 模式修正符
即可以在不改变正则表达式的情况下,通过模式修正符改变正则表达式的含义,从而实现一些结果的调整等功能。
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的
#模式修正符
'''
模式修正符 代表含义
I 匹配时忽略大小写(重要)
M 多行匹配(重要)
L 本地化识别匹配
U unicode
S 让.匹配包括换行符(重要)
'''
string="Python"
pat="pyt"
rst=re.search(pat,string,re.I) # search(想要搜索的内容,搜索来源的内容,设置模式修正符(格式 re. 模式修正符))
print(rst)
4. 贪婪模式和懒惰模式
贪婪模式的核心点就是尽可能多的匹配,
懒惰模式的核心点就是尽可能少的匹配。
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的
#贪婪模式和懒惰模式
string="poythonyhjskjsa"
pat1="p.*y" # 贪婪模式
pat2="p.*?y" # 懒惰模式,精准
rst1=re.search(pat1,string,re.I)
rst2=re.search(pat2,string,re.I)
print(rst1)
print(rst2)
注意:
在贪婪模式下,因为 * 前面是一个 . 符号,而 . 匹配除换行外任意一个字符,* 前面原子出现 0\1\多次,所以在这意为匹配任意个 不为换行符的字符 。
懒惰模式格式中必有 ? ,在上面例子中 .*?
表示以懒惰模式匹配.*
5. 正则表达式函数
match函数:从头开始匹配
search函数:随意在哪都可以开始匹配
全局匹配函数:只要符合正则表达式的,都会匹配出来,不会匹配完只出现一个结果
全局匹配格式re.compile(正则表达式).findall(数据)
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的
#正则表达式函数
#1、match
string="poythonyhjskjsa"
pat="p.*?y" # 如果是 o.*?y 则匹配不到,为null
rst=re.match(pat,string,re.I)
print(rst)
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的
#3、全局匹配函数
string="hgpoythpnyhjsptjhgjykjsa"
pat="p.*?y"#懒惰模式,精准
#全局匹配格式re.compile(正则表达式).findall(数据)
rst=re.compile(pat).findall(string)
print(rst)
6. 实例
-
匹配.com和.cn网址
import re # 要想使用正则表达式,就要导入这个模块,这个模块时系统自带的 #实例:匹配.com和.cn网址 string="<a href='http://www.baidu.com'>百度首页</a>'" pat="[a-zA-Z]+://[\S]+[.com|.cn]" rst=re.compile(pat).findall(string) print(rst)
解析:因为要匹配网址,网址的格式有很多种,比如ftp开头的、http开头的、https开头的…
为了匹配这个开头的协议:我们先使用一个原子表来匹配,中间放上英文字母
[a-zA-Z]
,因为这个长度不定,所以使用元字符+
号来匹配出现一次或者多次。接着就是固定格式
://
,所以接上这个。后面是域名,域名这个长度不定,可以数字、也可以是字符、还可以是符号,但是中间应该没有空格(域名中间有空格的还真没印象),所以这个使用
\S
,因为域名的长度不定,所以使用元字符
+
号来匹配出现一次或者多次。接下来的结尾分两种
.com
和.cn
,对于这两种,我们使用元字符中的模式选择符来实现,所以为[.com|.cn]
综合起来就是:
[a-zA-Z]+://[\S]+[.com|.cn]
-
匹配电话号码
#实例:匹配电话号码 string="jsghajsdhk021-8928874997678328jhdjskgjkh0773-776257672360kjcxdhkj" pat="\d{4}-\d{7}|\d{3}-\d{8}" rst=re.compile(pat).findall(string) print(rst)
解析:电话号码格式有
xxx-xxxxxxxx
和xxxx-xxxxxxx
两种,所以我们用元字符中的模式选择符来实现。又因为电话号码都是数字,所以我们使用通用符作为原子,即使用
\d
表示十进制数。按照上面的格式,可以表示为:
\d{4}-\d{7}|\d{3}-\d{8}
7. 简单爬虫
直接使用系统自带的urllib库来编写。
案例:爬 CSDN 首页的url
#简单爬虫的编写
import urllib.request
data=urllib.request.urlopen("http://edu.csdn.net").read()
print(data)
ps:这个爬取出来是页面的HTML文件。
案例:自动提取课程页面的QQ群
#自动提取课程页面的QQ群
import urllib.request
import re
data=urllib.request.urlopen("http://edu.csdn.net/huiyiCourse/detail/253").read().decode("utf-8")
pat="<p>(\d*?)</p>"
rst=re.compile(pat).findall(data)
print(rst)
注意:这里有两个细节点:
decode("utf-8")
:urllib读取过来的是二进制文件,需要进行转码,utf-8格式是中文格式,也是常用的格式。- 正则表达式中的小括号:如果不加这小括号则输出的是整个正则表达式匹配到的数据,如果加上小括号,则输出的是小括号里面的内容。
最后:页面都是实时的变化的,可能今天可以用这段代码去提取,但是过了一阵子可能就提取不出来了,我这边按照学习视频里的就不行了,最后需要自己修改才行,所以学习是死的,灵活运用才是真的。