- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566430 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175152
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
+ x- J, ~ a4 x+ F j- Z5 z% R
Python爬虫 正则表达式应用详解
3 L9 E, }! [1 U- u) L4 y! f- x
, M+ D$ l/ M% ~ ^学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
8 u) i- b# ?3 J( |% r* p
( G0 X. W; P; _; v6 _/ d& {—— 正则表达式应用详解 ——
3 {5 o Y- Q1 p0 G
9 I% n4 ]3 b7 B文章目录
S, {" V! S |1 z% g% C9 k6 S( i5 W4 o1 w" Q1 E' |
Python爬虫(二十一)' n) ^9 d6 A& w5 o1 H
—— 正则表达式应用详解 ——8 A0 r9 k" j. t9 L c! J5 f
1. 简介
" G5 d* X# `% a+ L. X0 T: R% v1 C2. 语法
! M( I0 s: x0 t7 R- v3. 部分元字符应用详解
+ \9 \. q! J( X8 C: u+ r^7 f/ B2 m! J$ ~& k6 s
$. b: ^2 B! K4 |9 Z5 Y
\A
8 ^# w" y; J6 r9 a\b. c$ k2 W7 j$ \4 S* H
\B2 \0 P2 A C: j
3. 正则表达式实例* u6 Q+ _7 p- G! D$ f& Z
相关文章:: h% s4 P* j; h' J2 |& F9 e2 r
1.Python的Re库应用详解(正则表达式的库)
4 k/ f3 [( g% B- X0 \2.Python的Re库与正则表达式的细节解析(正则表达式的库)5 _% O1 h0 Y$ D9 @) U' Z) _/ `
0 o' Q V/ f* v2 X, l1. 简介
/ S( z5 }/ I I" k& ~. T. q; E% t+ |4 X) }
正则表达式:regular expression,也称regex,简称 RE2 X: W( D) m$ g4 V# P
" z) e" \# a! L, L/ I正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
6 |! t, p% m! h8 s) N" O
5 E e8 W" R+ E) r正则表达式是用来简洁表达一组字符串的表达式
4 x# h: `7 x5 O9 ^ G V5 S. g# |+ D9 M7 B' c
通用的字符串表达框架9 [) ~ L1 @4 K, c' L
, V: K! s$ e* B& ~" B2 q3 j: b
简洁表达一组字符串的表达式+ h) F% ~ G" j8 h& J) u
1 ~' J2 x4 T) L, z4 N' m针对字符串表达“简洁”和“特征”思想的工具
S0 R* b' o* g0 s4 T; Q' Z' {1 d2 T- M, R
判断某字符串的特征归属 {' Y. j0 C# T3 v' P
! C8 L/ I% c8 M/ R, ]
正则表达式在文本处理中十分常用# a4 x) ?: t- [, @8 N
! B/ R; Z6 e! O表达文本类型的特征(病毒、入侵等)
0 B/ H. s$ P) {( ^/ n" b: s- u" U% E$ C& f& R! }
同时查找或替换一组字符串
' Y+ P z6 P3 q6 D
1 I; J- p+ F# p匹配字符串的全部或部分. b, Z* k$ N" b0 `
! h& R4 j! t$ A正则表达式的使用+ K- p8 T5 v! E' A! {) ], E. h
: Z" \. m! |% ]& [编译:将符合正则表达式语法的字符串转换成正则式表达特征
J/ N8 V, C; \- t8 }+ k9 \$ b0 `4 G2 u7 ?5 D5 X
% q+ V9 }$ Q, c7 [8 C
2. 语法- c; K# Q' y) P$ K$ J
b, K/ g1 ?$ [! k
正则表达式语法由字符和操作符构成5 O9 N, f& R5 e0 a5 b
' g7 E, H8 D& A$ b2 `( O有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。4 L1 ?0 b; B% H b
元字符包括:. ^ $ * + ? { } [ ] \ | ( )
& A4 l- r" C' G* C4 W% R, [正则表达式的常用操作符
. [* d$ s7 M* |: F) e- U) v在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发, |2 w+ f5 e" g$ _: v' {0 S
操作符 说明 实例' _1 I; _+ @. J7 e3 y1 L7 u" K
. 表示任何单个字符(除换行符) 【注1】
) R( l+ @. ~& h" R* \8 z) ^[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
$ z3 P" ]+ X3 C. r: A% m" o[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符+ }5 v/ f# ~ d( E, d% x. F3 _
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等, a! \6 @- ?2 \" @- U- Z
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
) @6 P- R3 X$ j4 \; u? 前一个字符0次或1次扩展 abc?表示 ab、abc. d! k- h' X. w* k A# i3 l! g: ^! z
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def, z6 \2 y& O7 O$ b, u
{m} 扩展前一个字符m次 ab{2}c 表示 abbc. V; B a4 f V2 G: k
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc, N+ w6 s. D! z% y6 j7 h
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头+ J8 ~9 Q. [% U6 U
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾
0 C0 O I g7 d1 y) K5 N0 u V( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def/ q$ r" j/ \, W( C" c
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u- T! j) T, y7 n# M/ @
\d 匹配十进制数字,等价于[0--9] 7 d& }+ b J! i) ^# O
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] ) g$ K* |, d1 v" f. n i3 S1 ~- O
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v] ( U3 _6 i2 S5 h' H
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
1 b" P, Q# |% D, U\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
/ `# }/ O& i& I2 N\W 于 \w 相反 2 E9 a. X% I2 K# a, _
\b 匹配单词的开始或结束 & p1 _7 q4 ^4 Z1 \" R& i
\B 与 \b 相反
9 w0 ^' I7 P4 j/ l% Y\Z 只匹配字符串的结束位置。
) ^/ t) D) C" V* X8 M( y9 M0 Y【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
' d/ y- x @. i' y2 d$ Z" X8 ]6 @ U& q6 P( a6 b* G9 H% m0 M
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;, M* u- T3 g& v8 v( y1 m
$ w% |9 [: P& U* D【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。9 G, |5 l4 @( _5 u
R5 r) b% ]* F5 F$ [! ]
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。! K/ d9 I3 m: H1 [7 R
: h1 D+ x$ S& W+ d5 W
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
4 G( s/ }. V$ R2 D. |& i4 o3 E: Z2 K. z4 @* v9 ~) I! N! r s
3. 部分元字符应用详解
% T3 J0 [& L5 I, ~" x5 c* w% M! I# _9 Y
^
* D, C- y2 o D1 V4 I! E
$ c8 q* R" A0 B匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
' l- }7 H3 [) s. W+ }( r9 L0 A( I+ X) w1 I I
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
7 p! G- y4 O; P' F! W
S3 w- k9 r3 N1 j- G6 A1 iprint(re.search('^From', 'From Here to Eternity'))
- V @* r( x" M6 [print(re.search('^From', 'Reciting From Memory'))7 I* P; ^; K- P) q/ M: L) o
1; L+ V! m) W3 h+ X# ?8 I
22 ^, `8 E8 ]# b$ r
结果如图:
& z# @0 J5 d3 ^) e$ y! U 4 s, c0 `# I* O1 D
, o! z& M$ \, |( f; @: m
$
/ L4 i' w# T, Q0 P [( z. G3 A
5 o# V7 Z- ~1 y9 R ?4 F1 t9 n) i匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。5 U: j- L! u& U- A6 f9 l; K6 s9 R
# l+ O: R* ?0 [1 N* o2 C% {print(re.search('}$', '{block}')) 5 N1 l/ r7 \. C j
: X! T' C& ]0 r& Q
print(re.search('}$', '{block} '))0 G+ Z+ g8 E5 O/ ~4 R* x
$ M8 M9 a! O2 Z7 l; z
print(re.search('}$', '{block}\n'))
* e# y) Q. ?# j, ^6 V1
: O6 o: L4 I" F8 U28 T& C# N+ F' o0 j y6 q% j
36 B2 m5 E( v) E
4
) v' j( [. M+ m$ l5
8 t1 s/ e; a* p( M' Z结果如图:7 F% k( U9 C3 |' j$ J% J1 y
; ~7 J3 j7 s- d& p5 L( }6 N2 l+ s; n6 r
![]()
/ _. C; G) ?$ K" N% Y1 Z2 j3 s, U
# L/ ~3 q4 m4 G+ r4 ^ e4 J同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
- |4 q5 k! j7 N
3 d2 T# \4 d0 J0 _9 s0 X% D\A6 Z+ p5 W* q. U1 M" g
( K6 z* B- H& v& z只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
/ A; m9 w D' t! A
5 G* T# l; Y. d1 }3 S\b
! j: M8 H- m1 x" c# W" D2 z% j9 z V" P. N
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。" E+ j& t: M) `
* \( b# i: |, H- d/ r
零宽断言相关信息请点击零宽断言查看。
8 a0 z# Y+ L8 S3 x2 K2 j/ K# R. w2 Z2 }. ~. E( o4 I
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
8 u4 u5 o% Q) ^
1 T: F% E0 X: t# qp = re.compile(r'\bclass\b'): \! T: p E1 F0 i( {$ c2 @) Y
print(p.search('no class at all')) + N* r; n( h5 H) o+ T- Z% z2 o! N
9 G; n: ]* \+ M3 G& xprint(p.search('the declassified algorithm'))1 `4 k3 p* U+ x( z, a# b9 }- w
/ Z$ ?8 L% ~" q! r: Bprint(p.search('one subclass is'))
% q% d5 l& }! i1
- u8 h4 S0 W. J5 b2* X8 I6 H( g. r; {+ V4 {# G
3' X4 I6 Z. E3 V% p
4
! x) D9 |" q2 V8 W50 C5 h" g; b6 d- M7 n& q E- ]
6
0 O. s: m1 {# N' o$ Z结果如图:
! C7 k0 F+ o) d) L6 e2 i
3 c+ Z9 n) d8 t0 [, @ x在使用这些特殊的序列的时候,有两点是需要注意的:
8 D* [, I' f( a) t V1 ]2 L# S
7 u6 `& C3 `' K' G/ Q! ^第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
& w! H8 y* C, F4 m相关原理和解决方法点击详情查看。: j6 u" b' p6 ?% Z
0 H6 a' ~- \7 R, l4 ~7 t
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
( B% s6 f" G% F* F
' s2 R+ {( Z% Q6 ~$ A# y+ C2 T\B5 |0 V h3 M; T/ T2 l/ Q
7 Q; ?% x% s" I另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。9 Y9 a5 u# t/ Q7 G/ |' q _
: |$ ?/ s3 Z$ z3 n) P- G
3. 正则表达式实例( d4 e. r% f5 ^
![]()
$ j5 m( v9 W/ u8 g2 X) K4 s! } o, R4 E$ `2 I5 d
经典正则表达式实例
, b: S4 W4 \# q![]()
1 `* c" R- \: r! x( l匹配IP地址的正则表达式, T6 M! W4 }% h9 Z/ M4 `/ X0 ]. t
7 ?7 S/ d3 v, ]3 ~7 Q! f1 [( a
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确; X, `2 E9 R& A9 \
( v( n! C5 j: u4 U8 F1 P精确写法
9 j* d) {: t3 P2 f0 c" p7 L9 J! J5 h7 z
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
. ^* q3 \3 _6 U; b8 _, F$ |(([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])3 R, ]' u' O3 N& o; J/ W
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
" B7 t) Y4 ^" [/ I. u5 y* ^9 Q+ I/ I* N- E+ A8 ~4 H, i. ~
! o0 R. E2 ~9 F4 z
|
zan
|