3.正则表达式re
正则表达式是对字符串操作的一种逻辑公式,我们使用正则表达式对字符串进行匹配和过滤
优点:灵活,功能性强,逻辑性强
缺点:上手难,一旦上手,会爱上这个东西
正则匹配在线工具
元字符
元字符才是正则表达式的灵魂.
1.字符组
字符组很简单用[]括起来,在[]中出现的内容会被匹配,列如:[abc] 匹配a或b或c
如果字符组中的内容过多还可以使用 - ,列如:[a-z]匹配a-z之间的字母[0-9]匹配所有的阿拉伯数字
2.简单的元字符
. 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线
\s 匹配任意的空白符 \d 匹配数字 \n 匹配一个换行符 \t 匹配一个制表符 \b 匹配一个单词的结尾 ^ 匹配字符串的开始 $ 匹配字符串的结尾 \W 匹配非字母或数字或下划线 \D 匹配非数字 \S 匹配非空白符 a|b 匹配字符a或字符b () 匹配括号内的表达式,也表示一个组 [...] 匹配字符组中的字符 [^...] 匹配除了字符组中字符的所有字符
3.量词
一次性要匹配多个字符就要使用到量词
* 重复零次或更多次 + 重复一次或更多次 ? 重复零次或一次 {n} 重复n次 {n,} 重复n次或更多次 {n,m} 重复n到m次
4.惰性匹配和贪婪匹配
在量词种*,+,{} 都属于贪婪匹配,就是尽可能多的匹配结果
.*?尽可能少的匹配,表示惰性匹配
.*?x的特殊含义 找到下一个x为止
5.分组
正则表达式使用()进行分组
6.转义
在正则表达式中有许多特殊意义的转义字符,比如\n和\s在匹配一次\n,字符串中要写成\\n,正则表达式中要写成\\\\n这样太麻烦了,就需要用到r'\n'这个概念,正则中就可以使用r'\\n'
匹配邮箱
[a-z0-9-_]+@\w+\.[a-z0-9.]+
匹配手机号
1[3456789][0-9]{9}
匹配生日格式(yyyy-MM-dd)
\d{4}(\_|\-|\/)\d{1,2}\1\d{1,2}
re模块
findall 查找所有,返回list
ret = re.findall("\d","baby电话是137")
print(ret)
search 会进行匹配,但是如果匹配到了结果就会返回这个结果,没有匹配上就返回None
result = re.search("\d","电话号码")
print(result)
# print(result.group())
match 只能从字符串的开头进行匹配
result = re.match("\d+",'137电话号码')
# print(result)
print(result.group())
finditer 和findall差不多,只不过这时返回的是迭代器
ret = re.finditer('\d',"baby123456789")
for i in ret:
print(i.group())#分组
result = re.finditer("姓名:(?P<name>.*?),爱好:(?P<hobby>.*?)","姓名:宝宝,爱好:女,性格:开朗大方")
for el in result:
print(el.group("name"),el.group("hobby"))
search和match的区别:
search查找 ,找到的结果就返回 match从头开始匹配
其他操作
# 正则正常操作
result = re.split("\d+","宝宝110来找你了,你收拾收拾去119报道")
print(result)#['宝宝', '来找你了,你收拾收拾去', '报道']
#用正则替换
s = re.sub("\d+","__Sb__","宝宝110来找你了,你收拾收拾去119报道")
print(s)#宝宝__Sb__来找你了,你收拾收拾去__Sb__报道
s = re.subn("\d+","__Sb__","宝宝110来找你了,你收拾收拾去119报道") #替换了多少次
print(s)#('宝宝__Sb__来找你了,你收拾收拾去__Sb__报道', 2)
code = "for i in range(10):print(i)"
c = compile(code ,"","exec")
exec(c)
reg = re.compile(r"\d+")
lst = reg.findall("宝宝110来找你了,你收拾收拾去119报道")
print(lst)
result = re.findall(r"\d+","宝宝110来找你了,你收拾收拾去119报道")
print(result)
lst = re.findall(r"a(?:\d+)c","a123456c")# 把括号python中的分组变成了原来正则表达式中的分组
print(lst)
findall中的坑
ret = re.findall("www.(baidu|oldboy).com","www.oldboy.com")
print(ret)#['oldboy']
ret = re.findall("www.(?:baidu|oldboy).com","www.oldboy.com")
print(ret)#['www.oldboy.com']
split中的坑
ret = re.split("\d+","alex2wusir3yuan")
print(ret)#['alex', 'wusir', 'yuan']
ret = re.split("(\d+)","alex2wusir3yuan")
print(ret)#['alex', '2', 'wusir', '3', 'yuan']
爬取电影天堂
from urllib.request import urlopen
import re
import json
main_url = "https://www.dytt8.net/"
reg = re.compile(r'\[<a href="/html/gndy/dyzz/index.html">最新电影下载</a>\]<a href=\'(?P<url>.*?)\'>', re.S)
son_reg = re.compile(r'<div id="Zoom">.*?◎片 名(?P<name>.*?)<br />.*?◎主 演(?P<main>.*?)<br />◎简 介.*?<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">', re.S)
# 获取主页面内容
def get_main_page():
main_page = urlopen(main_url).read().decode("gbk")
# 主页面
it = reg.finditer(main_page)
lst = []
for el in it:
d = get_son_page(main_url+el.group("url"))
lst.append(d)
# indent 控制格式
json.dump(lst, open("movie.json", mode="w", encoding="utf-8"), indent=4, ensure_ascii=False)
# 获取子页面内容
def get_son_page(son_url):
content = urlopen(son_url).read().decode("gbk")
it = son_reg.finditer(content)
for el in it:
return {"name":el.group("name").strip(), "main":el.group("main").strip().replace(" ", "").split("<br />"), "download":el.group("download").strip()}
get_main_page()

浙公网安备 33010602011771号