在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 566427 点 威望 12 点 阅读权限 255 积分 175151 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
" T; F' T& u, }2 `5 {7 i$ c# k# { Python爬虫 正则表达式应用详解
: d' o% m' h+ g% M4 ` A( R" J) H + y& a0 b6 P! ^0 \ M- Y9 _2 o% J
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
1 C: c; V4 a, D1 S 5 J$ y/ g/ S2 v# ^# u d# ^4 J4 i* L
—— 正则表达式应用详解 ——
! N4 c( H9 d7 h7 c; _! q/ S
/ I3 m) z* M2 U+ n, M 文章目录
/ D% w% t7 Y d9 N4 a6 k' ]' r8 V . d0 C/ @& A! a: S2 `5 F
Python爬虫(二十一)
' Q6 j& ^3 m' \6 D) s" L —— 正则表达式应用详解 ——
; s( r2 ^. N |3 t 1. 简介+ G- U" p9 L7 s _! ]( ]) S+ {
2. 语法3 h5 g0 J! B7 X, ^% y
3. 部分元字符应用详解
, y, y( r4 u5 m7 U0 g/ h8 s8 z ^
5 n' a5 n: X5 n) h0 [2 S $
0 Q% x* I4 z/ N4 K+ X( D \A+ t$ [$ y9 o9 t4 s% b+ B( M
\b% F) k0 y! m+ F# l9 C; ^$ {
\B
/ |$ m" g3 ^/ r# K! g 3. 正则表达式实例: z, l5 x9 X' m8 x1 y1 b0 W l
相关文章:- P" T; H5 E5 K9 D- h
1.Python的Re库应用详解(正则表达式的库)! D" y) ]+ x( e" n( ?
2.Python的Re库与正则表达式的细节解析(正则表达式的库)
3 | d7 b# p2 \7 y# l( S
' k& f5 Q& y3 @& S. Z' j& Y 1. 简介
' k+ [! r' ]( A9 v$ t8 j( U
3 Z& J; o' W! x! _( r& X C 正则表达式:regular expression,也称regex,简称 RE
- M6 F0 S6 O* B, [* M
! F1 U4 q9 b b! u 正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
- T6 I* ?3 K; w* a/ w5 J7 x9 w
" j/ T% F* r) c+ {6 T' K& U, w 正则表达式是用来简洁表达一组字符串的表达式+ z( W6 \! ?2 J# ]% ~* C
/ f, A& m7 ^8 ^; t9 j
通用的字符串表达框架7 c6 _( ^: A7 }8 F% {0 D
5 V0 `) E0 ]0 b6 l 简洁表达一组字符串的表达式
* r5 q/ F8 B' y% r; r 0 L, c8 X4 C. ~" k
针对字符串表达“简洁”和“特征”思想的工具- f5 Y' u m* B' Y- {0 m7 k
# X, y, ]2 t; K
判断某字符串的特征归属; t9 o+ T. ?1 ]( {; K" ?7 z9 u" S: O
3 u% \! N6 b: T$ j* A 正则表达式在文本处理中十分常用8 M' {! c! S1 c' I! e% B1 T; a
9 p" Z! ?+ v5 f s* _ I$ \ 表达文本类型的特征(病毒、入侵等)/ @3 L9 U, r1 Q
/ y) W& v; x3 R1 e0 q 同时查找或替换一组字符串
3 G Z4 f) s+ Q- R1 e& s: B
3 e4 L+ Z7 {9 f1 m 匹配字符串的全部或部分7 l( R' s# k0 `& H! m9 k
- a& ?2 @. T/ Z+ c5 E 正则表达式的使用! ~4 ?( F9 k4 |
' [* U; X6 W; V+ V; h# ^1 V9 `2 j 编译:将符合正则表达式语法的字符串转换成正则式表达特征
- @3 T8 }2 h$ s$ k- w0 `
; I0 A8 R, q5 u+ h0 a) x
* ^# d: R) V; H 2. 语法& A, v( O0 S& L9 p
4 [% Q9 D* N0 i+ ]' P3 g
正则表达式语法由字符和操作符构成
) X9 `9 a5 X1 G* l( T# H
( I$ G% N$ x( q9 z' E+ F0 \ 有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
$ ^( R5 `( ?, ]/ r3 }9 P' u 元字符包括:. ^ $ * + ? { } [ ] \ | ( )2 A7 |) ]* |$ s, _
正则表达式的常用操作符
$ O0 }& c9 s1 @& o$ {: t; R 在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
' X0 G, T1 A7 s9 L1 k4 g) l 操作符 说明 实例' ?: Q* Z$ S4 y: O: W
. 表示任何单个字符(除换行符) 【注1】 - W* ?2 {' C9 Y) p
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符: u7 m* r2 u, O: N O
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符( x1 o. W, {) ~1 c2 u- i
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等# Y5 N8 [1 _3 H; L, v) Q' }
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等) Y1 o" Q7 a# f( P/ I g& Z6 B/ I1 s4 _
? 前一个字符0次或1次扩展 abc?表示 ab、abc1 u& Z/ K9 w1 b! Q7 j
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def5 A. x( Y* T2 C1 X0 @0 w/ s
{m} 扩展前一个字符m次 ab{2}c 表示 abbc" w: ], s+ \& c4 c* a
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc7 ], F- w0 d3 d1 S6 c
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
# |- U2 t/ J$ C* q1 z$ M $ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾: W% P% j) Y5 _
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def- F0 d5 s9 n4 c7 _$ q/ V# v
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u. B5 Z# M( G: a( C7 |* M5 N
\d 匹配十进制数字,等价于[0--9] 7 _2 n' Z! B1 @( ^" e' L, V
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
: n" y8 y+ F( K+ |; `" U9 U5 F! b \s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
( r' a+ w$ w+ k: d6 _! E \S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v] . K8 ^4 v, H0 p7 c
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] # T7 l& Q5 J4 M0 ^& r: e
\W 于 \w 相反 1 J1 u6 A2 i6 F$ k m" |8 s# e J9 k
\b 匹配单词的开始或结束 0 \' B1 G! i6 d8 @7 ?1 h
\B 与 \b 相反 - w w4 M1 ^+ X: L
\Z 只匹配字符串的结束位置。
+ W7 j" ~. j" [: N 【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
/ ~' {$ q. Z" v6 P+ I' Y% j, }% Y
9 }& U0 ^1 l) b# l 【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
! t- h2 D4 S4 j * }4 u+ [) a, Y9 U
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
# M/ E! w7 r1 ]* M. }
: p% n9 N' Z9 q d 【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。8 I% x7 q5 x% F- E1 }/ A. m
& w/ D6 t/ W# b& w; m) q! g 【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
' k* A6 k5 }. X5 W/ N6 `
* S T8 T6 R4 B9 o6 }2 Y 3. 部分元字符应用详解
# z, a. n; f! Y, H$ g
, P0 g% V7 ^' b2 Q5 ?$ k7 b ^2 ^) C/ E3 j1 H+ }. ~- [" C9 g
8 E1 J3 w8 R2 A$ x* L: @0 G9 c9 M: K
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
% L7 W2 b, W( ^5 _6 P Q* S: S( a; |
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:) I: V3 D( x1 u5 F
- c. g" f6 |! c# C7 V6 z ]
print(re.search('^From', 'From Here to Eternity'))
9 T% Z# l$ ]; ^- w% B7 k8 p( N print(re.search('^From', 'Reciting From Memory'))( c4 P; J5 n! g8 A2 Q# e' z8 }
1
6 f4 {" M; {- l% V+ V0 V; d 27 V Y- u1 I) C
结果如图: i- A; O6 d. y C2 c
. p; o; }; v7 X6 `! ]1 |2 R$ U
. N0 m2 n& x' A# E& ^! Y
$' _! f, N( t& g, u" y
/ C* S7 q6 x( g q 匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
$ B* Y/ L- u8 a
2 n2 _& ?$ a9 ?; w print(re.search('}$', '{block}'))
8 r) \* y$ Q& S+ t) F: I 4 F& y% K5 D0 ^# y
print(re.search('}$', '{block} '))
$ C, s" ^( E# _8 T$ z$ W6 z
4 T5 j9 p( g( d' s5 w* l print(re.search('}$', '{block}\n'))
5 W! v( F% a k 10 {! M$ c- d0 i7 D7 S: U
2
% w3 e" U% g% `" b 3
a3 H- q" b' J% U. Y 4
! W& C& L& ^" h- z9 ~0 `! R 5
, t$ n) G8 p0 K 结果如图:
6 S: x( i; _8 P/ H* `0 ]
7 d+ t _5 s% U. o: x5 I- p
4 F1 o M! o. b) [: q 1 b F/ {& C2 t, o- a! h
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
% O/ ]% D8 D H% E; n
% B$ R) K; _1 J" G4 _6 ^ \A9 G: `3 b+ z/ x& C
, c6 k* p, h% G# l' ~ 只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
Y- L- z X' J2 X
8 Z0 ]! N+ f E x1 P3 u+ Y) C \b" e9 ]8 B0 ]- z' Y, t& L
) c4 T R8 C& f( K; Y5 @! Q" z+ v 单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。1 ?0 K" x# _% d9 B: g
9 f x0 K7 q# m; \- T! k% F9 q 零宽断言相关信息请点击零宽断言查看。9 x5 P/ s+ z% e; \( W
4 l2 e( a- a& I4 l
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
9 p6 I8 f3 g% J/ V" |& t
- K- A3 [; u* Q9 ^ p = re.compile(r'\bclass\b'): s5 N: X5 r& x- a& w) L# |
print(p.search('no class at all'))
8 w @# \4 ~5 T7 h6 ^: c/ p- H$ h
+ h# G, s8 d4 z2 h print(p.search('the declassified algorithm'))# I; }# V( s7 L
$ x' D4 @# U5 N/ Z. V; F7 p
print(p.search('one subclass is'))
4 b' J, z; N t5 B/ t 1# ]1 a1 A: @' @* O; o# K
2
! f0 g& p: w2 L" v7 q2 W 3
, v9 O6 ?- A; V5 z- L 4 b3 P1 p; u7 O2 E' s c7 Z( M
5/ y5 m: a R0 }% o3 |$ o$ D
6; [) Y" p( Q2 x2 ^& p9 S
结果如图:
, l% }) R2 i+ l* T4 Y/ E( Z$ j 8 \& D9 H! O1 e5 k; i
在使用这些特殊的序列的时候,有两点是需要注意的:
* ]% \4 ~0 @7 |# o3 a% n 8 }: T3 e+ W6 P9 o' z
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。/ o' h" y, j6 @& E0 ^" K5 f
相关原理和解决方法点击详情查看。
1 h) P' v1 [8 b3 h& @ 6 s f9 S( Z# g5 V+ c! p' @
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
+ w7 u2 \# I, Z; V& C7 q( k6 }2 H
B7 b# X2 |" g$ B0 f$ \ \B4 Z2 ]2 p* U/ I
8 z. ^/ j0 M, y4 A# _9 E 另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。1 K( v. i( Q8 c& A$ Y4 r: |' Y ]9 |
$ L; L, H8 o8 o+ A d/ i! \* f" L
3. 正则表达式实例
( S& X- r; E" |) U
8 P* p0 K& H$ V' Z: S, B( t* P4 P+ }
. i, B, E W. b( L1 R# F 经典正则表达式实例3 y( I+ ?* p) C
; I8 Z) _- ?2 K3 M' S
匹配IP地址的正则表达式) P! |8 |3 _+ a: o4 X
( P$ s. p" H, f/ a IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确/ K6 b! o: x. o4 C! O
+ U+ u3 W* B' a0 [. V. H 精确写法
6 A) A$ Y2 i4 R
0 D4 |! _9 x2 N! O$ G4 K 0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
5 P* x: q3 ~2 L (([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])
% A8 g! q2 g7 u. k- I$ K2 z 原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
7 J( \) J& v& m5 \2 ^ ; `) J% U+ E: ]7 V% q3 ~9 }0 L
9 i4 Y S7 X1 D8 c0 N. E( c8 m
zan