- 在线时间
- 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年大象老师国赛优 |
- u; b, ]+ H4 p) u' x4 l9 J5 ~Python爬虫 正则表达式应用详解9 m0 f! \7 j U1 s0 ]# @
9 l l& }- k' j/ t) w
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
: A) x' t& ?% Y6 d! a
& T! \0 w. Q u U! R( |+ b! k" m, h—— 正则表达式应用详解 ——
4 E" W7 L! i, B4 I# y9 A1 [% ^* i1 a( {. i
文章目录/ D! s& L. W0 |5 X, y: n
1 D+ f7 ?( ~4 ]9 Y3 Z. o8 n% N4 h0 r
Python爬虫(二十一)
8 X3 Q# g% y! T/ Y8 T) N—— 正则表达式应用详解 ——
. i+ b# v- A/ t- j+ p" T, o1. 简介
/ H4 J4 |- T( b% w2. 语法
% T- A8 X& w5 r7 ~! T3. 部分元字符应用详解2 f$ N2 J8 h7 Y9 p+ R
^; |; `+ f5 F' A
$& i6 d7 M4 x1 r' Z9 r6 v# v- y
\A$ J$ ]! e9 \; F) J+ M
\b2 j/ j0 X' t, I, E
\B
% o2 x% }5 ^' s3. 正则表达式实例
$ H4 ~4 q8 _5 v( i$ y相关文章: ^3 e3 W) s: N+ a% U
1.Python的Re库应用详解(正则表达式的库)
5 g* @. f5 w, d9 h; L2.Python的Re库与正则表达式的细节解析(正则表达式的库)3 Z' Z) }& E# W1 U
# k& |1 ?* I, U6 ]# A
1. 简介. ]5 `7 t2 C, I3 t6 i( X* c
+ X7 ^5 p* t% E6 ^- b0 G
正则表达式:regular expression,也称regex,简称 RE
4 ]2 L7 _$ ^ h) K; V
! w/ t( g8 u* u正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
+ l! `4 @) K& N2 m: x6 d# o
4 H3 ]* o i2 E" `' h* f2 l正则表达式是用来简洁表达一组字符串的表达式
7 l( n$ e; _4 x6 E4 X
1 z9 M; @* H5 [. X y通用的字符串表达框架
& Y: o' p* \$ `8 h% M
% s2 z0 V/ O. C$ S- m& C简洁表达一组字符串的表达式
. k" f& i# |8 m2 H+ Q
% W2 U2 a! w: F. [0 d针对字符串表达“简洁”和“特征”思想的工具
( K$ k( H$ ]3 o3 Z, S- m
7 F- L" W5 k: ?2 ~. t( | v G判断某字符串的特征归属' R* s) o" e. z/ j, m8 v
* d6 P/ e4 L# j3 D# d4 S正则表达式在文本处理中十分常用. I U9 X/ B& x, T
6 |" S; L9 l9 B5 e5 i- c; O1 \表达文本类型的特征(病毒、入侵等)0 v( ?( a$ ?" o. }
8 N5 g3 F& L1 l
同时查找或替换一组字符串8 d/ p+ m' j+ k0 `# x# _+ @
" i2 m( a' Z2 R9 O$ N
匹配字符串的全部或部分: m `+ k2 U7 a0 _0 c
* {$ \2 H- [4 O7 g- a1 G' \0 }9 |
正则表达式的使用
6 n% g* V* V' A0 W5 t" M+ m7 S7 T4 E/ y
编译:将符合正则表达式语法的字符串转换成正则式表达特征. P8 z. D- ?) ?; U5 |! \4 l
/ A) x2 a6 i" E d- n
![]()
4 a) e! b8 q1 [1 k; y2. 语法
( m, b4 p1 T7 t# \
8 w9 w, E% x# r9 t# H8 _8 F' X+ a正则表达式语法由字符和操作符构成, N+ F8 |* o9 n
* B0 ]' Y$ W% i2 v+ e6 o/ {- Y有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
7 Y+ T' }2 C/ f [ k: U元字符包括:. ^ $ * + ? { } [ ] \ | ( )
; G/ f7 I- M/ c9 [ y- [4 B5 u1 A6 M* e4 R正则表达式的常用操作符/ K; _1 y& P2 U, m
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
+ [. P8 U5 G. p; y7 B) b6 L$ O操作符 说明 实例
7 P, m* d* @' P; L; B# Z. 表示任何单个字符(除换行符) 【注1】
7 o" ~/ S/ Y- b$ R+ q[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符2 B4 X: M3 t/ H; R1 C7 w) X, {5 A8 n
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
$ @/ T( _1 V$ [2 F* i* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
$ r+ N, k b! f& L% i+ I+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
4 b! }% j4 }3 N4 P* s? 前一个字符0次或1次扩展 abc?表示 ab、abc7 B7 T' f0 k0 D0 A4 h
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
* P L. ?' N/ Q# `$ ?; _8 o# F{m} 扩展前一个字符m次 ab{2}c 表示 abbc) M4 y# u& m; Z* G3 B
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc5 V% o6 e: _" w
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
2 s5 N( S- S' w5 `3 k+ ]. y$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾2 a) v5 K9 K' F) e
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def4 b r8 w, m( l g1 C
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u6 b6 U- A( U+ l: ]# t6 h! [) Y
\d 匹配十进制数字,等价于[0--9]
) I) t8 j+ u9 q l* ~1 x& X8 K1 U\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] 5 z* y0 i! G# O, b E% z2 w
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
5 \& O5 P6 R6 z3 M1 ^\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
9 p. c2 Z# B4 z. L: e\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] - Y& d; b+ i5 ?# q; e
\W 于 \w 相反
. q$ L7 |7 [% m& l\b 匹配单词的开始或结束 ; F! b$ y5 b: F% E
\B 与 \b 相反
$ F% y6 A5 @0 _" E\Z 只匹配字符串的结束位置。 5 r7 u- ?3 j& V" ]3 J
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
' Y- Z! ]2 `" N$ B1 N. ~; w, Q% l* a
5 j- q) D- s+ H# I/ i* ]" E【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
% T, [2 u0 c4 `3 M+ R5 i: w' B: Q6 v
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。1 Q8 E! y# I; W" a
3 \& O+ k3 C* h7 n$ t( K) U) B
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。+ D$ J9 h' x) j6 ^
# [& w) E, E' t) [3 B【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
1 i2 `' o5 F- W. N& k: c% B" l {6 x( s ]
3. 部分元字符应用详解& D1 a% s. o9 g' n7 d" q- i3 \# U
7 Y' h, p& L5 e- k0 {8 e^5 z9 H- H# y& O8 k+ p3 _
1 {1 p/ a# ^- b" ?$ @( c1 }, r! E
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。& D: Q0 v1 j- V0 x
3 S% [5 z4 P5 L% x( M5 j0 K1 v举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:$ `7 ~$ q8 c B. k! | I" P
4 C6 @( T( s$ {. s' iprint(re.search('^From', 'From Here to Eternity'))
6 g$ j$ _# Z* g/ T9 z7 nprint(re.search('^From', 'Reciting From Memory'))
2 S- X, I: H, d5 d2 A1" B2 {- V; z8 J% }3 c
29 h( X2 P4 ?3 g/ K7 E( O" C/ C/ e0 z
结果如图:
/ A6 a: n* Y5 e9 `7 y/ N![]()
7 g$ c& V8 e1 L: \6 X
- A, P/ I' W$ j/ `' x: S$
& J8 f6 L/ H: E2 j" R7 e
+ ?5 Y8 q. ]' D: P$ N8 t5 d6 M* C1 I匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
; K8 e3 W+ S' O' O
3 y+ V4 Y+ P {% u ~print(re.search('}$', '{block}')) 4 d4 ?' S% t: `" y0 `
# H4 J& b5 _8 [- n, W. r
print(re.search('}$', '{block} '))6 ] X7 t# U( Y; J$ C0 u- z
" O2 G& y8 o+ u7 l. o! s
print(re.search('}$', '{block}\n')) + c; o& X4 n& B6 Y
10 M0 }. ?3 O* D* t( b0 l
2
. z0 W5 K- T3 g( p$ \0 Q5 }" }; G38 |6 K- F( X6 R) i
4 R6 `9 a. E2 K
5+ l4 K! h4 V! V- C3 Z5 @) f' r; k
结果如图:
6 `/ |& C1 U2 b3 _# U/ v
/ }9 F) B! F. w+ {3 K # [, `2 g8 g5 n
2 S" u; m/ U9 I0 a# ~
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。 m+ K( m! n" W7 ?) d: x# w
# R/ ]' B' K' }, B3 j. Y* ]\A
# x2 Q4 H1 h% e/ {( l: Q. n1 T' y( p+ n1 R
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
1 o4 v; R( Z5 z; T
6 |; l0 Z) a: W, ^3 W- ?\b! X* R2 q- j% K
4 N8 Q8 H3 }+ L9 W
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。, s+ V8 ]: J; B$ }( A
0 f& n( ]3 T+ s2 a. ~% O
零宽断言相关信息请点击零宽断言查看。/ s) W; P: }2 g2 y
3 U% F) j! e1 _+ r. G/ j! A
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。# c# x! r3 z) ]$ R" Y
4 W+ Z2 u) @* N" W/ S, L9 ap = re.compile(r'\bclass\b')
* x v$ X! Z* b) Pprint(p.search('no class at all'))
+ J$ q* b! ^6 P" g/ ^& P1 v/ j! C, V# ]6 e4 b
print(p.search('the declassified algorithm')): I2 ?; A4 T# S
* c. |- g w9 H* s$ _9 J& O xprint(p.search('one subclass is'))/ ]5 f* o* `0 o* g( }( R, _4 v+ \
1
" X" P. P& ]& ~2
# M" B9 S( w( Y; |3
7 P- F. V, i: z# x7 l( n, L2 A4
- [7 k% l- t0 A2 C* V5' f8 W% q& p. x1 W) Z2 u
6( e) Z4 O# W1 |
结果如图:+ }2 s# o" V" B( k
/ T! x1 W4 X" X; _" d, w在使用这些特殊的序列的时候,有两点是需要注意的:$ w1 h6 {! j1 X( l
6 ?+ C) d, \. }) U' [( s( w
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
& E( a/ L7 f6 T相关原理和解决方法点击详情查看。/ j. z: b- r D. z& M4 R. }
7 D/ F6 g! Y5 m- A" j& O1 ~, d3 S
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
3 o8 i( j6 M3 E% `$ x, ]" w) r: c0 t# G) Q! K
\B w1 \& d* r5 J, }" M
$ U$ d; p: n2 i' n另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
' O( R5 w- @! T
( s* \/ O! _) I& W5 ?3. 正则表达式实例
5 X7 ]) g8 U2 D# O![]()
- K; Q' J7 n Q5 n9 u' Y; \: P9 {7 x, _0 h4 U4 v1 C2 A; m4 k
经典正则表达式实例
F1 v4 _3 s7 ]$ K. S( m0 n) N+ Y2 f![]()
]1 A/ y$ N6 h8 N7 j, R匹配IP地址的正则表达式( P% t2 S# [& n: Q3 w# u
% i8 Z/ o: h$ wIP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确) c. t$ \: E, e& m+ q
4 w1 S# ~0 s% L! Y# d精确写法
, P$ J! Z8 c4 i$ _; m! h! k) y) U: Y7 d! I5 i+ _. N3 y9 Z
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]5 \" y9 n& \5 M J
(([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])1 e* ^, b8 g" m9 n4 Q3 j' W
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
7 K5 a: D5 s% O; H" B( k8 Y1 ?. {
" @" w; J; i1 Q" _0 M& Q3 x
0 I6 H+ B5 v9 C0 ]7 p- ~( ?) H& Z3 B |
zan
|