- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566434 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175153
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
8 \. f @ x' h: \
Python爬虫 正则表达式应用详解
/ u3 Q+ i4 e0 h0 j
/ R" l, N1 f8 ?" x, E; ]学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
5 n* H" p, M) }: r9 y t; ?+ I/ _
n, w/ |6 W2 i* Y# V* e9 X& ~" F—— 正则表达式应用详解 —— h4 X3 t* y& b
Z- X! ], m6 N
文章目录- B& H& n; X2 M# i( w/ v
7 |2 k: ?% w; wPython爬虫(二十一)
) r/ b- }. u( h( L; E/ A—— 正则表达式应用详解 ——0 F7 _8 z2 `2 |) P" G7 m; E1 _1 H) M
1. 简介
" C; B. G, f( C7 S* O2. 语法
8 `8 g2 g$ Z2 o$ X3. 部分元字符应用详解& d0 w( ^$ \) y* C( `2 u
^
8 I0 l" n; g0 b( l) [: b$( U0 D( P( ^* @1 M1 G
\A1 w: j9 `/ p+ O) [, C
\b
" p$ y" W* O8 [2 j! j, C2 u\B
- ~+ k2 z0 ^5 g1 p, W% R6 g, Z: l3. 正则表达式实例
( s9 x8 M* Z/ Z& J3 q相关文章:
' |: X/ f* h! y( s& `( i& ^( H1.Python的Re库应用详解(正则表达式的库)4 o0 k- }. m7 Q% r
2.Python的Re库与正则表达式的细节解析(正则表达式的库); T# U/ Z7 c# b& S5 I
4 n0 S; V" w2 q! K4 ^8 l1. 简介
* `4 }5 G, ~; E3 S9 V4 P
+ P* ~2 L' p8 K/ w正则表达式:regular expression,也称regex,简称 RE9 N( P0 J% J$ Z4 f
3 L8 H7 e, a9 v+ I c+ ]3 n
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
. r$ J% ]0 C1 P# b4 y; M* {% {
6 |! }" @+ }7 R9 n% r" a: _正则表达式是用来简洁表达一组字符串的表达式( Q9 A4 }% g( k b$ T9 q: z
' P3 a( s: v0 D) n$ a
通用的字符串表达框架7 H4 u# R# ]9 x/ Z0 I8 Z( v4 @
$ t( R% r. o. f8 E
简洁表达一组字符串的表达式
. x0 d" ~3 }. G/ q9 K' y
, m9 [+ o" C: E2 M/ e y: @9 a% ^针对字符串表达“简洁”和“特征”思想的工具. u1 p/ a- [9 e
0 O) X) M) V+ q. j4 V9 G
判断某字符串的特征归属
7 @+ u/ o& }" y, f" h- A3 d# I& L$ Y. o, \! r! G
正则表达式在文本处理中十分常用
) F! Q) q; H5 T" A7 t9 W& b2 P1 b7 T+ A
表达文本类型的特征(病毒、入侵等)+ o3 O5 k$ \6 m! Y' X
% k2 F M4 { X7 V9 m同时查找或替换一组字符串$ |( m9 o: D% H6 y- i7 ^) Y, R
" b v4 }7 [3 x1 B) B
匹配字符串的全部或部分
# K) N% y$ R: s: x; o" y/ A
( y& i% @. ]5 _9 r& b; D正则表达式的使用
2 Q1 c0 J# c4 z- S2 k& _, h( ^2 t" ~: U$ E) m
编译:将符合正则表达式语法的字符串转换成正则式表达特征
) D- j) I) d2 P; q8 J) x/ A7 N1 g8 W6 I
4 s% |, f9 O& R
2. 语法
/ \' `3 L2 _- j& m1 g, L/ ? ^3 [0 Q
正则表达式语法由字符和操作符构成
% A. ^8 d# g) i; F( _* n
/ M) F1 Z, ~/ \9 C( Q有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。6 r- C! }9 [: `! \( w/ a1 P# _2 j
元字符包括:. ^ $ * + ? { } [ ] \ | ( ), J4 N2 G- d5 ^" y `+ A4 J
正则表达式的常用操作符: x Q* O8 j" ~$ v& Y6 M. K
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发4 R5 T' M( l' y
操作符 说明 实例* M: h: L a) ~% B
. 表示任何单个字符(除换行符) 【注1】
7 z, N" L+ i" t* j[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
/ a) i- {# R. C- a+ y: W[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符; F9 H# h Z% e0 m! w6 f
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
# G) n# O. }! C+ o+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等; n) C9 m- V) D- i0 V3 n3 t* {
? 前一个字符0次或1次扩展 abc?表示 ab、abc$ m1 r0 ]+ S: a6 y. }
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def7 x5 N. U/ @, s8 K7 O5 m
{m} 扩展前一个字符m次 ab{2}c 表示 abbc3 B3 l9 R0 c- x. Z0 }, C; ^9 X
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
8 c z. m r" R4 V: G' H. t^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头8 b! q! @& `" ^. }! P# @) R. K
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾
8 s, }4 E# k! ^( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def+ R. C: k) D2 w9 ]0 N7 n
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
: Y/ K' y6 T1 F7 l' A# T6 b\d 匹配十进制数字,等价于[0--9] ' h2 T ]+ P# n# h4 O9 w& E2 Q+ e
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
6 h. N+ g- w0 k% w6 r" Z. D9 U\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v] + C" d8 d j$ H/ P9 r N
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
4 X' a' e& _4 u0 v0 p1 _0 x\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] ! ^. g4 i( g/ ^& G' @) \
\W 于 \w 相反
! z% J9 t- Y2 i! b7 R' ]2 Z- K+ j, ^\b 匹配单词的开始或结束
. ~% |' `1 A7 `7 I1 L. {\B 与 \b 相反 5 g5 W. Y# r* I/ Y3 v, }' [/ ]
\Z 只匹配字符串的结束位置。 & t+ A S5 M: q$ n
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
6 n, {1 P$ Y! a6 u) j8 _
( N! u& h& V, U【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
1 c5 E, p( b( R- a- U# {, ^& C l. _( {2 k( Q0 H
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。& k0 G0 W* S9 ?0 \; r" b, {& ?0 n
7 o& a6 D) m3 Q' r# `; H1 W【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。3 F7 m, N5 [8 t- r- E, @
. X+ f8 V+ Z* W6 H9 a' R; \! H【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
* c, o: U4 T% @- y$ D& Q5 j( I/ B. N+ @4 v
3. 部分元字符应用详解$ v: y. \ v/ D/ U$ n
1 @. l; s2 x( [. i* H$ h. g^+ z5 `" O+ L5 ^- p
6 U0 C4 q1 q0 _+ w
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
1 Q* ~* C% F" V% g# n* d
D: Y9 B% F& k+ L7 s" H( J举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:' x; `. }7 S& S$ t1 G
! o+ d! ]; u" L% Y: d( i8 K& A, rprint(re.search('^From', 'From Here to Eternity')) / B( a! G; a5 H5 W6 f
print(re.search('^From', 'Reciting From Memory'))1 e6 S$ l: K1 p
17 p8 c4 t, R' t/ k
2( C+ E8 ?* v/ ]! o0 m3 |
结果如图:/ ~ T9 @2 s2 i6 A4 K
![]()
I* }, [5 z3 y; T: C# A* W( N8 F
% e3 e) g7 T3 h2 f% ], b$
8 ~. i& a! n/ |
; }. W9 K5 ` H% }; u r' A3 s: l匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
, z1 j: d- C5 B1 b- ?7 s' s# h
& e2 }8 p. s1 p" p4 ~4 lprint(re.search('}$', '{block}'))
0 L4 p# G a( B
2 W6 n; I; O% Y) m" x0 z; Mprint(re.search('}$', '{block} '))1 U/ o1 W& ^6 R& Z
0 |' J# }1 b' c$ U' |& i' Oprint(re.search('}$', '{block}\n'))
9 b5 _' Y: ^$ j; u13 x; R7 t; }) r6 L2 B+ K
2& \6 E2 L9 A. e7 M
3
$ w% O& ]/ z" K3 ?5 B4
O. |) U! Q! j% e k59 F% p2 n9 v5 J* ^7 W
结果如图:+ z0 X4 ^+ S! d$ P- W" w5 l
& j7 Q2 z/ Z4 K* ?
![]()
; M" i1 E* i0 p' F! S( k
- A5 f( p( u3 ^7 ~/ L, m- U/ H' W同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
2 w4 L0 l4 s& f# Z! j3 V5 \( z- s; J1 j" D# C) H! F5 e7 }3 {
\A
2 k( x6 N; L1 Z; G2 d Q
, K3 l) x9 q2 t8 e# i7 j只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。/ N/ F8 A) i% s4 T1 N
/ ^$ `, {% d) Z# y$ m\b
) K( |2 o% f7 o$ P8 |% C; A# ]4 ]! k5 {. K
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。7 h1 H, f: Y0 Y% [# m
: {1 J" G- P( @; {, w
零宽断言相关信息请点击零宽断言查看。" X0 ^ _- ?4 ]
2 G Y8 G. p8 F( Y
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。2 p: d- u6 l; o' t; F
8 l9 L5 k7 T% ~) D& e; dp = re.compile(r'\bclass\b')
$ K9 n( U2 w" dprint(p.search('no class at all'))
1 a6 I1 Z! i$ A1 C7 b' N$ |% r0 |0 R: r/ G
print(p.search('the declassified algorithm'))
+ n/ T; j- Y/ e5 k
, T% ` D% K6 I( k8 ]9 a, Gprint(p.search('one subclass is'))5 m2 M9 d9 h# @& e3 j+ r6 }
1
1 v6 x$ R7 s; F1 l2
, L1 Y* N2 ^: H% I; O7 [3
* ~5 ]9 C$ B8 e. r4 z! F) R- v4# I$ {; w+ J5 Q' h0 y
58 ?3 @; Z& C6 x6 O6 c4 o* {. q
6) o7 s9 f( e& \/ ~ y
结果如图:2 S4 b7 a0 ~# _% t, \: `
1 X# p9 P% B* \5 @# W2 J( d% E
在使用这些特殊的序列的时候,有两点是需要注意的:4 D5 i& T0 j# S( A
: J1 W( c+ y" Y7 h
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。 h& ? y& ]+ F" P- U+ y
相关原理和解决方法点击详情查看。; Q: M/ H" |. S( e% k* V1 `
z. p \, v4 B) y+ K1 k
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。" ^# b9 S* A1 W6 k$ \9 g
. M1 K# T+ D: ?0 \
\B% _. O# _3 T0 d/ [# z+ F
9 K, Q/ p- b$ m% e/ D# S% l
另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
$ |2 Z: L/ E9 d4 m3 g* ]5 g, Z8 T
2 [ m; w) f3 q" o1 a, H5 {! Q3. 正则表达式实例
; T# C6 @8 R S8 w [5 G" n+ d" R8 s8 {& d& s! c
% t8 X6 D. J3 i- [2 P! D2 }) e经典正则表达式实例% H2 [9 X/ D D' @. O8 z# w0 g
![]()
5 N3 }6 G, o9 G$ B匹配IP地址的正则表达式) Y8 ^/ f; K! Z# z+ J
( W0 }/ L; G- \3 F" d
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
1 H/ c, [& }' g. U- z8 U* a6 G2 [" y5 N, o4 Y" r
精确写法8 C# ]- e$ ^" a% \( n
' L. s4 m% Q0 L3 T: M0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]/ m0 I' I5 L# F) L2 l- I% u1 i
(([1-9]?\d|1\d{2}|2[0--4]\d|25[0--5]).){3}([1--9]?\d|1\d{2}|2[0--4]\d|25[0--5])
6 |5 p& ~2 W. t; y( |" E' [原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177$ ]. P( g; \/ G& U) s+ X2 H
# x1 ?% C7 D& o7 T2 f# n) S
+ K8 p S6 y7 Q7 {( z
|
zan
|