数据解析-正则表达式
正则表达式
正则编写规则简介
字符 | 含义 |
---|---|
. | 匹配除换行符以外的任意字符 |
| | A|B表示:匹配正则表达式条件A或B |
^ | 匹配字符串的开始(在集合[]里表示"非")的意思 |
$ | 匹配字符串的结束 |
{n} | 重复n次 |
{,n} | 重复小于n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
* | 重复零次或更多次,等价于{0,} |
+ | 重复一次或更多次,等价于{1,} |
? | 重复零次或一次,等价于{0,1} |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
[…] | 字符类,匹配所包含的任意一个字符 注1 : 连字符-如果出现在字符串中同表示字符范围描述(A-Z);如果如果出现在首位则仅作为普通字符 注2 : 特殊字符仅有反斜线保持特殊含义 .用于转义字符. 其它特殊字符如*,+,?,等均作为普通字符匹配 注3 : 脱字符^如果出现在首位则表示匹配不包含其中的任意字符;如栗出现在字符串中间就仅作为普通字符匹配 |
[^x] | 匹配除了x以外的任意字符 |
[^aou] | 匹配除了aou这几个字母以外的任意字符如 f,g,h |
\ | 1.将一个普通字符变成特殊字符,例知:\d表示匹配所有十进制数字 2.解除元字符的特殊功能,例.崇示匹配点号本身 3.引用序号对应的子组所匹配的字符串 4.详见下方列举 举例:匹配2.4 2\.4 |
\序号 | 1.引用序号对应的子组所匹配的字符串,子组的序号从1开始计算 2.如果序号是以0开头,或者3个数字的长度度。那么不会被用于引用对应的子组,而是用于匹配八进制数字所表示的ASCII码值对应的字符 |
\A | 匹配输入字符串的开始位置 |
\Z | 匹配输入字符串的结束位置 |
\b | 匹配单词的开始或结束 |
\B | 匹配不是单词开头或结束的位置 |
\d | 匹配数字 |
\D | 匹配任意非数字的字符 |
\s | 匹配任意的空白符 |
\S | 匹配任意不是空白符的字符如:1,* ,) |
\w | 匹配字母或数字或下划线或汉字 |
\W | 匹配任意不是字母,数字,下划线,汉字的字符,如 +,-,* |
规则补充
优先级
说明
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
re.M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
re.S(DOTALL): 点任意匹配模式,改变'.'的行为
re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
简单案例
def day5_re_findall():
# 贪婪模式 从开头匹配到结尾
example_str = """addddnmaaam2252.5
999n9999mN
"""
# *贪婪模式 *?非贪婪
# pattern = re.compile('a(.*)m') # 贪婪 ['dddddmaaa']
# pattern = re.compile('a(.*?)m') # 非贪婪['ddddd', 'aa']
# 转义字符 \ 匹配 2.5
# pattern = re.compile('2.5') # ['225', '2.5']
# pattern = re.compile('2\.5') # ['2.5']
# 匹配除了换行符之外的所有 .
# pattern = re.compile('a(.*)n',re.I) # 忽略大小写 ['dddd']
# pattern = re.compile('a(.*)n',re.S) # 忽略换行 ['ddddnmaaam2252.5\n 999']
# pattern = re.compile('a(.*)n',re.I|re.S) # 忽略大小写 且忽略换行 ['ddddnmaaam2252.5\n 999n9999m']
#中括号的使用
example_str = '2239982'
pattern = re.compile('[123]') # ['2', '2', '3', '2']
pattern = re.compile('[7-9]') # ['9', '9', '8']
# findall 方法 结果是列表
result = pattern.findall(example_str)
print(result)
实例补充
# 网页内多行匹配,将.换为(?:.|\n)
excerp = re.sub(r'文件下载((?:.|\n)*?)附件','',excerp)
re库相关函数
# match 从头开始匹配 匹配一次
# search 从任意位置匹配 匹配一次
# findall 查找符合正则的内容
# sub 替换
# split 分割
def day5_re_fun_show():
example_str = 'abc123'
pattern = re.compile('\d+')
# match 从头开始匹配 匹配一次
result = pattern.match(example_str) # None
# search 从任意位置匹配 匹配一次
result = pattern.search(example_str) # match='123'
# findall 查找符合正则的内容
result = pattern.findall(example_str) # ['123']
# sub 替换
result = pattern.sub('@',example_str) # abc@
# split 分割
result = pattern.split(example_str) # ['abc', '']
#字符串替换
result = re.sub('替换前','替换后',result)
正则实例
解析百度新闻的新闻标题和链接
def day6_re_example():
url = 'https://news.baidu.com/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0',
}
response = requests.get(url, headers=headers)
data = response.content.decode()
# 效果一般
pattern = re.compile('<a href="(.*?)" target="_blank" mon=".*?">([\u4e00-\u9fa5 ,]+)</a>')
result = pattern.findall(data)
print(result)
for item in result:
print(item)
with open('baidu.html', 'w', encoding='utf-8') as f:
f.write(response.content.decode())
pass