#正则
() [] [^] 表达式组 字符组 非字符组,只约束一个字符
"""
例:
[0-9]#匹配一个数字
[a-zA-Z]#匹配一个字母,可以放多个范围
"""
#元字符
. 匹配换行符外的任意字符
\w 匹配字母、数字、下划线
\s 匹配任意空白符
\d 匹配数字
\W \S \D 非
\t \n
\b 单词结尾,如 c\b,匹配c结尾的单词
^a a$ a|b 字符串的开始 字符串的结尾 a或b
#量词
{n} {n,m} {n,} 重复n次 重复n到m次 重复n或多次
? * + 零次或一次 零次或多次 一次或多次
# 例:
"""
1、
s = '李逵和李鬼和李莲英'
正则: 李[^和]+
匹配结果: 李逵 李鬼 李莲英
2、身份证号 15或18位,15位纯数字,第一位不能是0;18位末尾是数字或X
正则:^[1-9]\d{16}[0-9X]|[1~9]\d{14}$ 或 [1-9]\d{14}{\d{2}[\dX]}?
"""
# 转义字符匹配特殊字符
r('\*')
#re模块
import re
# 基本查找方式
"""
re.findall()
re.search()
re.match()
re.finditer()
"""
# re.findall(pattern, string, flags=0) 列表返回所有匹配项 pattern:正则表达式 string:待匹配字符串
ret = re.findall('\d+', 'one111two2three3four4')
print(ret) # ['111', '2', '3', '4']
# *** findall() 默认只显示分组匹配内容, 如下
ret = re.findall('www\.(baidu|cctv)\.com', 'www.baidu.com')
print(ret) # ['baidu']
ret = re.findall('www\.(baidu|cctv)\.com', 'www.cctv.com')
print(ret) # ['cctv']
# 取消分组优先需要在分组内容最前面加 ?:
ret = re.findall('www\.(?:baidu|cctv)\.com', 'www.baidu.com')
print(ret) # ['www.baidu.com']
ret = re.findall('www\.(?:baidu|cctv)\.com', 'www.cctv.com')
print(ret) # ['www.cctv.com']
#re.search(pattern, string, flags=0)#返回匹配对象,获取对象值需要用.group() 且只返回一个匹配项
ret2 = re.search('\d+', 'one1two2three3four4')
print(ret2) # <re.Match object; span=(3, 4), match='1'>
print(ret2.group()) # 1
ret3 = re.search('\d+', 'onetwothreefour')
print(ret3) # None 如没有匹配到,返回对象为空
# re.match(pattern, string, flags=0) 从头开始匹配返回匹配对象,获取对象值需要用.group() 且只匹配一项,类似正则前加^
ret4 = re.match('\d+', 'one1two2three3four4')
# ret4 = re.match('\d+', '11one1two2three3four4')
print(ret4) # None
if ret4: # 防止未匹配到结果对象时,对None执行group报错
print(ret4.group())
# re.finditer(pattern, string, flags=0) 返回匹配结果的迭代器,节省内存
ret9 = re.finditer('\d', 'a1b2c333d4')
print(ret9) # <callable_iterator object at 0x7fb8cd88fee0>
print(next(ret9)) # <re.Match object; span=(1, 2), match='1'>
print(next(ret9).group()) # 2
print(next(ret9).group()) # 3
print([i.group() for i in ret9]) # ['3', '3', '4']
#分割&替换
"""
re.sub()
re.split()
re.subn()
"""
# re.split() 根据正则表达式切片, 切片规则如在字符首位会产生''
ret5 = re.split('\d+', '1a2b3c4')
print(ret5) # ['', 'a', 'b', 'c', '']
# *** re.split() 对pattern是分组时会保留分隔符
ret5 = re.split('(\d+)', '1a2b3c4')
print(ret5) # ['', '1', 'a', '2', 'b', '3', 'c', '4', '']
# re.sub(pattern, repl, string, count=0, flags=0) 将 string 字符串中满足 pattern 正则要求的字符替换成 repl
ret6 = re.sub('\d', '*', '1a2b3c4') # 把数字替换成*
print(ret6) # *a*b*c*
# re.subn(pattern, repl, string, count=0, flags=0) 同sub类似,但返回元组(替换后的结构, 替换次数)
ret7 = re.subn('\d', '*', '1a2b3c4')
print(ret7) # ('*a*b*c*', 4)
# re.compile(pattern, flags=0) 将正则表达式编译成一个正则表达式对象 适用于相同正则多次使用场景,节省时间
obj = re.compile('\d{3}')
print(obj, type(obj)) # re.compile('\\d{3}') <class 're.Pattern'>
ret8 = obj.search('1a2bc3333')
if ret8:
print(ret8.group()) # 333
#分组
# 每对小括号是一个分组,\1 匹配的是所获取的第1个()匹配的内容
ret10 = re.search(r'<(\w+)>(\w+)</\1>', '<html>hello</html>')
# ret10 = re.search(r'<(\w+)>(\w+)</\1>', '<html>hello</html2>') # 后面改为html2 与第一个()内容不一致,无法匹配导致输出报错
print(ret10.group()) # <html>hello</html>
print(ret10.group(0)) # <html>hello</html> 0和没有参数相同,默认为0,返回整个正则匹配结果
print(ret10.group(1)) # html
print(ret10.group(2)) # hello
# (?P<分组名>pattern) 分组命名
# (?P=分组名) 分组名使用
# *** 使用分组名同 \1 使用相同,分组名匹配内容必须一致
ret11 = re.search(r'<(?P<tag>\w+)>(\w+)</(?P=tag)>', '<html>hello</html>')
print(ret11) # <re.Match object; span=(0, 18), match='<html>hello</html>'>
print(ret11.group()) # <html>hello</html>
print(ret11.group('tag')) # html
# 实际常用来找对称,例
ret12 = re.search('(?P<tag1>.{1,3}).*(?P=tag1)', '**abc**')
# ret12 = re.search('(?P<tag1>.{1,3}).*(?P=tag1)', 'a*abc**')# a*a a
print(ret12.group()) # **abc**
print(ret12.group('tag1')) # **
""" ? 的不同使用场景
1、量词 零次或1次
2、量词之后,惰性匹配(默认贪婪匹配)
3、分组命名:(?P<name>正则表达式); 引用:(?P=name)
4、findall/split 取消分组优先: (?:正则)
"""
#例: 匹配给定字符串的整数
msg = '1-2*(60+(-4.35)/5)-4*3'
ret13 = re.findall('\d+\.\d+|(\d+)', msg) # 利用findall分组优先规则,匹配到的小数不显示
ret13.remove('')
print('ret13', ret13)
# 匹配邮箱
mail_obj = re.compile('\w*@\w*.com')
# 匹配日期
date_obj = re.compile('^[1-9]\d{0,3}-(0?[1-9]|1[0-2])-([1-2][0-9]|30|31)')
# 匹配小数
float_obj = re.compile(r'-?\d+.\d+')
ret14 = re.findall(float_obj, '22.34')
print(ret14)
#
import queue # 队列
q = queue.Queue() # 创建队列
q.put(1) # 写入队列
q.put('a')
print(q) # <queue.Queue object at 0x7fd99499d100> 不打印队列内容
print(q.get()) # 1 先进先出
from collections import namedtuple # 具名元组
from collections import defaultdict # 解决当给字典中某个key写入值时,如果字典没有这个key会报错,使用defaultdict则会默认插入该key
from collections import OrderedDict # 创建有序字典
from collections import deque # 双向队列
from collections import Counter # 统计一个 python 列表、字符串、元组等可迭代对象中每个元素出现的次数,并返回一个字典
dq = deque()
dq.append(1) # 右向追加
dq.append(2)
dq.appendleft('a') # 左向追加
dq.appendleft('b')
print(dq) # deque(['b', 'a', 1, 2]) deque队列可直接查看
print(dq.pop()) # 2
print(dq.popleft()) # b
# namedtuple(typename, field_names, *, rename=False) typename:元组名称 field_names:元组中元素的名称 rename:元素名称中含有 python 的关键字,则必须设置为 rename=True
cust = namedtuple('cust', ['year', 'month', 'day'])
t1 = cust('2022', '08', '18')
print(t1.year) # 2022
print(t1.day) # 18
dict1 = defaultdict(list) # 设置字典默认value,list默认列表,str默认空字符串,int默认 0
print(dict1) # defaultdict(<class 'list'>, {})
print(dict1['test']) # []
print(dict1) # defaultdict(<class 'list'>, {'test': []})
dict1['test'] = 2
print(dict1) # defaultdict(<class 'list'>, {'test': 2})
# 还可用匿名函数指定默认值
dict2 = defaultdict(lambda: 5)
print(dict2) # defaultdict(<function <lambda> at 0x7fddbb88aee0>, {})
print(dict2['test']) # 5
print(dict2) # defaultdict(<function <lambda> at 0x7fddbb88aee0>, {'test': 5})
# OrderedDict
Odic = OrderedDict({'a': 2, 'b': 1})
print(Odic) # OrderedDict([('a', 1), ('b', 2)]) 顺序固定
dic3 = {'b': 2, 'a': 1}
print(dic3)
# Counter
a = [1, 2, 1, 3, 4, 5, 2]
print(Counter(a)) # Counter({1: 2, 2: 2, 3: 1, 4: 1, 5: 1})
#
# 爬虫尝试
import re
import requests
def get_page(url):
response = requests.post(url)
return response.text
def parse_page(msg):
com = re.compile('<a\starget=\"_top\"\s+title=\"Python\d?\s+(?P<title>.+?)\"\s+href=')
ret = re.finditer(com, msg)
# ret = re.findall(com, msg)
return ret
def main():
url = 'https://www.runoob.com/python3/python-urllib.html'
re_page = get_page(url)
ret = parse_page(re_page)
with open('1.log', mode='a+', encoding='utf-8') as sa:
for i in ret:
# sa.write('目录:'+i+'\n')
sa.write('目录:' + i.group('title') + '\n')
main()