python中的正则表达式、XPath表达式

python中的正则表达式 & XPath表达式


正则表达式(regular expression)(regex)

正则表达式regex是一种进行数据筛选的表达式。
python中使用regex的方式是import re

regex学习
在线regex测试匹配


regex函数

  1. re.search(pattern, str, 模式修正符):从str中找出与pattern匹配的表达式,可以从任意位置开始匹配,但是只会提取1个结果
  2. re.match(pattern, str, 模式修正符):不同于searchmatch只能从头开始匹配
  3. re.compile(pattern).findall(str):全局匹配,从str中找出与pattern匹配的表达式,可以从任意位置开始匹配,且会提取所有结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re

str = "awyywxywdy"
pat = "w.y"
search_rst = re.search(pat,str) # 任何位置开始匹配,但只有一个结果
match_rst = re.match(pat,str) # 从头开始匹配,只有一个结果
compile_rst = re.compile(pat).findall(str) # 任何位置开始匹配,提取全部结果
print(search_rst)
print(match_rst)
print(compile_rst)

# 运行结果:
# <re.Match object; span=(1, 4), match='wyy'>
# None
# ['wyy', 'wxy', 'wdy']

原子

原子是regex中的基本组成单位,每个regex至少包含一个原子。
常见的原子类型:

  1. 普通字符
  2. 非打印字符:如\n换行符、\t制表符
  3. 通用字符:如\w匹配任意一个字母/数字/下划线\W匹配非字母/数字/下划线外的任意字符、\d匹配任意一个十进制数字\D匹配非十进制数字外的任意字符、\s匹配任意一个空白字符、\S匹配非空白字符外的任意字符
  4. 原子表:将多个原子组合成一个表,匹配表中任意一个字符即可,如[xyz]表示匹配x/y/z中的任意一个字符。

^在原子表中表示“非”的意思,如[^xyz]表示非x/y/z外的任意字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import re

# 1.普通字符作为原子
string1 = "wuyingyingwoaini"
pat1 = "ai"
rst1 = re.search(pat1, string1)
print(rst1)

# 2.非打印字符作为原子:如\n换行符、\t制表符
string2 = '''wuyingying
woaini'''
pat2 = "\n"
rst2 = re.search(pat2, string2)
print(rst2)

# 3.通用字符作为原子
string3 = '''wuyingying 521
woaini'''
pat3 = "\w\s\d\d\d"
rst3 = re.search(pat3, string3)
print(rst3)

# 3.原子表作为原子:将多个原子组成一个表,匹配表中任意原子即可
string4 = 'wuyingying521woaini'
pat4 = "wu[xyz]ing"
rst4 = re.search(pat4, string4)
print(rst4)

# 结果为:
# <re.Match object; span=(12, 14), match='ai'>
# <re.Match object; span=(10, 11), match='\n'>
# <re.Match object; span=(9, 14), match='g 521'>
# <re.Match object; span=(0, 6), match='wuying'>

元字符

元字符是regex中一些具有特殊含义的字符,比如重复N次前面的字符。常见的有:

1
2
3
4
5
6
7
8
9
10
11
12
13
.       # 匹配除换行以外的任意字符
^ # 在原子表中代表“非”,在原子表外代表匹配开始位置
# 如:^a表示以a开始的字符串,所以abc可以匹配到,而bca则无法被匹配到
$ # 匹配结束位置
# 如:a$表示以a结尾的字符串,所以bca可以匹配到,而abc无法被匹配到
* # 前面的原子重复出现出现0/1/多次
? # 前面的原子重复出现0/1次
+ # 前面的原子重复出现1/多次
{n} # 前面的原子出现n次
{n,} # 前面的原子至少出现n次
{n,m} # 前面的原子出现n-m次
| # 或
() # 模式单元

模式修正符

1
2
3
4
5
re.I       # 忽略大小写
re.M # 多行匹配
re.L # 本地化识别匹配
re.U # Unicode
re.S # 让元字符“.”匹配包括换行符

如:

1
2
3
4
string = "Python"
pat = "pyt"
re.search(pat, string) # 无法匹配
re.search(pat, string, re.I) # 使用模式修正符I忽略大小写后,匹配成功

贪婪模式/懒惰模式

贪婪模式:尽可能多地匹配。
懒惰模式:尽可能少地匹配,比较精准,通过关键字?进行匹配。

怎么判断?是”懒惰模式”标识还是”重复0/1次”?
如果问号前面有表示重复次数的元字符,如*/+,那么它一定是”懒惰模式”的标识。

默认情况下是贪婪模式。

1
2
3
4
5
import re

string = "woainiaini"
pat1 = "w.*i" # 默认贪婪模式,匹配到的是woainiaini,尽可能多
pat2 = "w.*?i" # 使用?可以以懒惰模式匹配,匹配到的是woaini,尽可能少

【Demo】:SQL改造

  • 正则表达式:DROP TABLE IF EXISTS (\w)+;

    \w匹配任意字母/数字/下划线

  • ()表示一个单元*

  • +表示前面的单元出现1/n次*
    匹配:DROP TABLE IF EXISTS csc_menu;

  • 正则表达式:(AUTO_INCREMENT=\d+ DEFAULT CHARSET=(utf8mb4|utf8)( )*)| DEFAULT CHARSET=(utf8mb4|utf8)( )*

    \d匹配任意10进制数字

  • |表示“或”*

  • `表示前面的单元出现0/1/n次**; 匹配:AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 `


XPath表达式

XPath表达式和正则表达式regex的区别:
XPath效率比regex高,但只能处理html格式的数据,功能不如regex强大。
应该优先选用XPath,只有XPath无法满足需求才考虑regex。

现有HTML如下:

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<title>待提取文本</title>
</head>

<body>
<div key="value"></div>
<div></div>
<div></div>
</body>
</html>

XPath的基本语法有:

  1. 使用/表示逐层提取:/html/head/title
  2. 使用text()表示提取标签下的文本:/html/head/title/text()
  3. 使用//tagName表示提取所有名为tagName的标签,如提取所有div标签://div
  4. 使用@paramName表示提取名为paramName的属性,如//a[@name="itemlist-picture]"/@title
  5. 使用//tagName[@key='value']表示提取所有属性为key="value"的名为tagName的标签,如提取特定的div标签://div[@key='value']

Scrapy框架中,通过response.xpath(...).extract()即可执行XPath表达式。
urllib中,通过如下方法操作XPath:

1
2
3
4
5
from lxml import etree

# wb_data是拿到的HTML字符串
html = etree.HTML(wb_data)
html_data = html.xpath("...") #通过XPath筛选
-------------本文结束感谢您的阅读-------------

本文标题:python中的正则表达式、XPath表达式

文章作者:DragonBaby308

发布时间:2019年06月28日 - 18:41

最后更新:2019年11月19日 - 00:30

原始链接:http://www.dragonbaby308.com/regex/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

急事可以使用右下角的DaoVoice,我绑定了微信会立即回复,否则还是推荐Valine留言喔( ఠൠఠ )ノ
0%