- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564574 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174595
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
* l N# }' E1 g- V' APython爬虫 正则表达式应用详解
1 R# u6 D) R- b: h1 N3 H4 Q3 ]+ Z4 o8 k$ \, d
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
' \6 W# j5 g7 V7 C8 h- B. r9 J& ]# |5 s, I0 G( ~# F2 c7 g
—— 正则表达式应用详解 ——
9 m! \. N+ Z9 L; W; F% v
8 }0 z; h$ Y5 Z9 L* V' C9 c文章目录- ]" ]- e4 K6 D9 q; s, @
A% ~4 s# X0 v! [
Python爬虫(二十一)$ p/ V/ ~# l# D# U" J' v
—— 正则表达式应用详解 ——! l. [. B9 E8 ^; |( h
1. 简介" A6 D& v6 ]: h1 E" v
2. 语法( K F& V ^ O$ b8 W4 v# d) l6 Y7 \
3. 部分元字符应用详解
3 n: T( ^' {9 g2 ?, e^8 u9 J5 b1 D) h0 q% a; M K5 h
$. I' Z l( J! I7 J6 R- d
\A% l" \) e }- y, `
\b
) v2 o7 F5 V/ f; ?% ]* {& O! L\B9 q+ p1 K" \: g" Y
3. 正则表达式实例2 r1 ?7 S/ T& Q- y4 R
相关文章:
1 w- s+ k1 n& K4 o+ a+ _1.Python的Re库应用详解(正则表达式的库)
0 \" A- H. V0 T' t% R2.Python的Re库与正则表达式的细节解析(正则表达式的库): [" p- y/ @0 f# ~# S
$ X7 H+ D' V3 U9 H, q2 m0 ~1. 简介
/ T+ Y, m6 R1 }7 O9 O
9 {& f9 u. [! p6 V2 s: F正则表达式:regular expression,也称regex,简称 RE% V. W- D3 h5 }& Y& A
% h* X, N# L3 M% e$ y( D+ ]9 u- F正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
' R* y/ a9 z2 G. Y g- n% W8 D9 t3 g
9 S1 R' p/ w5 [ C' D! i正则表达式是用来简洁表达一组字符串的表达式0 {8 L' _- s4 \/ k" A! X
/ I, ~: l8 W% m" f1 K
通用的字符串表达框架
) {1 j! ^8 u/ V) |4 b* N& }: }3 C6 z6 N! l
简洁表达一组字符串的表达式
9 w1 t6 J. D/ ~8 ?* \' N
: \: x4 l, ]) c: M针对字符串表达“简洁”和“特征”思想的工具
* [& G' h* J4 t9 e% j4 ?+ z! W5 e3 U# V3 b
判断某字符串的特征归属
. Q @' I* G. Y9 p# l! U2 V
1 C1 D5 M/ i% e: a& r/ ? B) Z( `正则表达式在文本处理中十分常用
$ A6 Q3 X4 q4 x1 j9 _7 c- P2 y! s3 t" v5 v; f f* g
表达文本类型的特征(病毒、入侵等)8 w& u( N5 b: f9 u% r
/ U2 n3 X+ V' T+ ^; F
同时查找或替换一组字符串
, @' y \; O+ d0 o" `
6 P A' ~9 L6 @+ E匹配字符串的全部或部分
- ?' d5 ]& p, v& C4 M- Q2 l) O* C" T5 W% a8 w" @
正则表达式的使用* b% x5 P( \# k2 D5 P" [& [
4 T j6 {7 `/ h& \8 f; ]
编译:将符合正则表达式语法的字符串转换成正则式表达特征
1 _2 J9 L- t* U/ Q6 D! c8 i
( B; c0 f/ f' Y H8 e0 i- Y # F6 L; @+ t( `! O1 w$ C
2. 语法
0 l( k- k' x7 S. t* Q+ M$ \) Q; h- }- V
正则表达式语法由字符和操作符构成+ `: A9 G/ j6 C, U+ z& ~
. w" g9 C) _/ g1 Q x' ], e4 ]7 |/ q# p
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
$ z1 S6 \- l; J8 E R% M4 u' D" @元字符包括:. ^ $ * + ? { } [ ] \ | ( )# J. u3 S [1 Y+ f- j
正则表达式的常用操作符
1 v( Q4 M/ Y8 l7 L+ ?. q在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
! J) T: | O* H6 ? \! O操作符 说明 实例3 q; i) C! V5 z) ^
. 表示任何单个字符(除换行符) 【注1】 , p/ `9 R n9 m, H4 N) q+ |- z
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符( c3 @9 p( ? b2 N) c3 f& W
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
$ l' A' W! I7 K, j1 l( @, h" `* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等8 f5 y7 _& e- s, s8 q1 T
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等9 n; A( M; X9 x* m2 G0 S0 V8 b
? 前一个字符0次或1次扩展 abc?表示 ab、abc5 c2 i! ]9 _ g/ D0 ]0 o1 D x
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
3 r$ ^9 t0 b* D{m} 扩展前一个字符m次 ab{2}c 表示 abbc
+ X- X7 \, [* R- }. {* l{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
. d9 }7 O8 x% E: u^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头, I* J" d. h) P& ~
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾
. y: x/ S3 {" T( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def4 v P% x6 Z+ O; m* i+ t' b0 B
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
1 x% j, u: u( A) W X* |" ^' T\d 匹配十进制数字,等价于[0--9] 9 R. n1 j3 Q0 [
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
1 i1 k) V f2 K. N9 J" P% G\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v] 1 a. U4 e' G6 q9 n. }$ \
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v] . S! `1 n3 h8 ~! | v. T
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] * ^4 ]5 T8 k' X# @
\W 于 \w 相反 . T; T' N, d1 t$ j1 W; U
\b 匹配单词的开始或结束 + p/ ]3 C @9 B2 T$ n
\B 与 \b 相反
8 t. N/ C* G: W& U, z/ b\Z 只匹配字符串的结束位置。 5 r6 z2 ]+ [, a) [5 I# p
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。& O; [0 u( ^* ^3 f: }
3 B8 E+ M) F) D5 W【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
- b/ o$ g# t6 d3 K5 D3 G6 ]# A. V* J7 \) L/ b' O
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。0 ^3 d4 R1 v6 F
+ f1 B2 W( g; x$ P4 ^
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
2 W9 E: y: e/ e% c5 I; A( i
+ s2 ^/ r/ t) V5 f【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。& r1 p7 `0 i' a9 p A1 C
/ ^* W# M+ y9 T, f G# m
3. 部分元字符应用详解& O" h4 ]! |2 R9 x2 Y) w
& S/ y0 r' C" U^
* C- w$ g9 h, E3 h' d3 g) a
& _7 S7 Z4 O" E) l' A% W n匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。* p* r3 {3 m* w3 T
" h8 \: o1 Q7 j9 t0 c& V7 U+ j( U9 d举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
9 M% l- @$ I% \* g: v$ R' z% K$ c. X' I: n* k: m4 _
print(re.search('^From', 'From Here to Eternity')) , k ]$ K& |9 Z9 Y$ f8 ]
print(re.search('^From', 'Reciting From Memory'))2 g+ d: U. ?+ U6 _+ R
1
' e8 F3 T& T. f; j$ a2
$ t6 c/ ^) m+ x结果如图:
4 l9 \. Q2 i1 }, Y![]()
6 Q$ b( y) A; M$ n3 ~$ N7 i8 O6 [ r4 F/ Q6 f c v1 I2 N, P
$
! q) ?3 T+ i' M8 _# V2 L& q( q+ K
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
- t/ ]) L' t. z9 f! @
/ x! j, ?$ Q* G/ q* Gprint(re.search('}$', '{block}')) 9 w9 Q# n& N4 ~4 X8 k
4 h% ~7 s& N7 B% f! v
print(re.search('}$', '{block} '))3 F( h( N7 ~! J
. u/ F5 k7 Q* [$ Z& J/ z& Z* nprint(re.search('}$', '{block}\n')) " k8 C1 T5 J L, c/ e* p
14 L4 O/ u1 R1 W2 B0 z% k
2
0 c0 ~+ H9 T& Q q3
2 R; t& E( k' b( E4
6 ~2 J) M: N! G; q9 s* K1 K5 u+ \; |8 |; r' {4 o
结果如图:. A T, F. H: I; k5 q( \( l
# {/ Q G q+ k7 t2 b9 V! }6 ] " G+ H. w0 |' t. R) Q- H
2 R: n0 \1 t9 H9 Y1 b! B同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。8 T2 v" j1 A3 y& |; Q7 _6 Q) j
, a( ?7 Z8 W0 |\A' j3 l1 V) ^7 m! C
7 i3 k$ t% _4 E, J( O只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
1 u) B8 U7 }6 W, v- d- D4 n6 L" Q
2 ~# f* ^# M8 e T% i7 p4 z\b6 ^, P; Y% V0 m& G5 M3 o6 a! f
+ k# B/ Z6 ]6 \4 ], x单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
" R- a R4 _+ f( s" i: H& P% d0 B8 K
零宽断言相关信息请点击零宽断言查看。3 k% W! E! A( n& \- L
. K7 @" f6 `4 Z$ m
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。- b0 R# [! T# ?* J3 w( D
8 \! o- w6 d7 F3 n G# V3 T) |p = re.compile(r'\bclass\b')) P/ S0 L! `9 u6 G
print(p.search('no class at all'))
: }# b, @: Q) a
3 j# C3 Q/ f+ V* R7 Tprint(p.search('the declassified algorithm'))
7 B u! V$ R4 e- z
7 B( Y6 ]" u+ Sprint(p.search('one subclass is'))
3 L3 @0 z6 }' i( T X y12 ]9 v3 k6 G9 a6 A) B6 F
2
2 L& L+ I7 Y) T2 ~3" W, B' Q$ m: j7 V/ _
4
. c m% `3 D' g5
: ^* n+ a/ B0 B7 Q3 V5 h- i6
, V7 R( h9 L2 l7 h6 \6 M2 [, ?结果如图:
$ g. \2 J+ o. o0 u
* m& A* z+ C+ F" I在使用这些特殊的序列的时候,有两点是需要注意的:0 M4 N# n1 l4 F$ }4 ?: C* t
* s* O7 B5 V/ V$ [, z5 ?% e2 j3 |& _第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
0 @) _' n W' M m) @! p相关原理和解决方法点击详情查看。
: L4 S& y. K( S; A! v& U- M
1 I1 s9 y% D; j第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
9 ~4 W: l( P1 P' Z' q( |( d5 f! u; P( C6 L0 z: }6 P1 |
\B1 @5 Q" {6 a- }4 r1 b! F
' R8 Y! v2 ]" t另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
+ i# ^, G$ ^* _& T
1 N6 z& N* w/ x# [3 F. F" ?3. 正则表达式实例0 c; r; {! l8 h6 e* W/ |
+ q V/ [# ` ~8 g, w; T
" S+ L- R9 e' `1 }* r, y! u
经典正则表达式实例
9 M% t4 S: m1 j* V G' W 5 D. k1 O( i6 g* c# N9 J! O* g+ G8 q
匹配IP地址的正则表达式" F& O3 d) v5 G3 n
& R: d; |. m2 ~
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
. h6 c H5 |. E }6 O3 ~( l! l" l6 m0 O# W6 b$ y8 g8 G: \7 u
精确写法/ l7 ?* n) a) i4 y9 e1 x1 B! Z* s
! n C. X$ k, ^: h
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
) Q/ o( x. P9 _% a% ]; @" b( J! N(([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 e3 j9 O" p0 n
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177! k; l6 J: k' w# D9 O! P
- z3 C( M6 _6 [: P+ t' ^$ i; i) u' G4 \) s
|
zan
|