- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566467 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175163
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
6 e& Y" f1 M2 \
Python爬虫 正则表达式应用详解
, ^/ a4 q* A' P# ~0 d' D+ @, A$ A" p7 |# O! D6 Z; t
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。" U0 t v8 ^+ C: R6 i/ {1 w
" _. t; J9 N1 K# j$ Q9 M
—— 正则表达式应用详解 ——
1 P8 J9 E* m2 t9 ?* |
" g0 m T* F& h. a: f7 a- t文章目录
- L- g# I9 q1 Z! n. V- S9 h
/ Z& |2 B p% Z; \; ~Python爬虫(二十一)/ w3 m! U, L/ d+ q2 \
—— 正则表达式应用详解 ——
/ c3 L; h+ l6 G- z1. 简介$ @8 v H2 ]" {2 M6 Q! M
2. 语法) T- ]6 p" s9 N0 ~, H
3. 部分元字符应用详解, G6 F- l8 O. H
^, l+ I1 {! I- ~+ B& { g' d
$
, X- V5 H) J; t! S* p' u$ F\A5 I; \* f' H% N9 U$ L
\b' D9 B$ R9 B9 a
\B
) k8 L* e2 W; b, V- d" M! d9 S% s4 s3. 正则表达式实例
; A( M7 ]4 e4 K6 e) o相关文章:
, }2 @2 ]2 Z. W$ ~1.Python的Re库应用详解(正则表达式的库)
8 [" M& l: Q; ?- B6 F8 X2.Python的Re库与正则表达式的细节解析(正则表达式的库)) U7 l4 o: }4 X! V* q# A; Y5 I% y+ a
" \9 C* h# _. }1. 简介% _) L7 S `/ Q# `, ^
8 p$ `9 P. y8 a* n* R- d3 c- I6 J
正则表达式:regular expression,也称regex,简称 RE
/ M5 K7 w) v( T/ ~6 P) ~7 v, f" Y" |+ k/ Z+ q7 \7 @& a
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。; U6 @# [* _9 r) \# U
5 h+ L9 U, }% G2 e$ { r. F1 g
正则表达式是用来简洁表达一组字符串的表达式# \ m; w/ Y3 I/ |7 @: d. ^$ u. u
7 `. W* @. @0 ^9 N/ _' X& v通用的字符串表达框架% d6 G- k( m3 z
* v8 s7 ]# ~0 R0 _6 J3 `简洁表达一组字符串的表达式
* y7 E1 C6 o1 }
: G: S7 h6 o3 o针对字符串表达“简洁”和“特征”思想的工具6 _/ J8 @$ U5 `
: ~, B' k( V: y8 j- f
判断某字符串的特征归属7 u% f! V$ @! w$ H* u- r& }! q- ~4 {
% `% ^" U* B: ?/ W正则表达式在文本处理中十分常用
5 L, R1 l; j& G7 c6 F. D! B
5 A7 s& a6 g" ^+ O$ W% p! G/ R表达文本类型的特征(病毒、入侵等)9 P' \( u7 ~! B2 T
& c3 |+ J. e* z
同时查找或替换一组字符串
3 [+ U, k$ n4 L7 U2 Z
9 [% x# F' t8 F匹配字符串的全部或部分
4 N: D; n3 ]. Q1 a- L
0 ]8 f2 Q) ~6 m" d1 t3 Z1 T5 E+ R. g- L正则表达式的使用
) m% f6 W/ ^2 R9 E# v. k
. C* v# h6 i5 W! B; x- i, X编译:将符合正则表达式语法的字符串转换成正则式表达特征) z- K. x# c; ?
3 x3 b4 y$ ~" d* ]; q![]()
]* a# Q) F1 D$ ?5 ^2. 语法
) V. p) |& [1 c, W+ l/ K r. I% N9 }
/ v6 r$ ] `1 ^# j7 k' C正则表达式语法由字符和操作符构成
$ N- _0 Y4 f) I6 r# H) a! o- b3 P# ?$ ~! N$ @
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。; A/ O. \; a/ D3 A2 e
元字符包括:. ^ $ * + ? { } [ ] \ | ( )
% E' R* ^4 l; G+ ?; i正则表达式的常用操作符
# i( N$ m( |0 z1 O) @' T在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
2 ^ o F: Z2 M2 a1 K操作符 说明 实例
( M1 F% d( m6 T2 i. O. 表示任何单个字符(除换行符) 【注1】
' ?* i, F) E7 ?/ N1 {) D$ J[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
& T2 y0 e3 m! Q; E3 n2 j9 e[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符0 ^8 R2 I0 H; Y& u& f' S
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等; y7 |$ a5 u' i( S* Z/ L& Z- P$ p* w: h
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等3 M- _9 O8 _1 B. c& n
? 前一个字符0次或1次扩展 abc?表示 ab、abc- A3 G3 A. F8 S; a P+ A
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def9 K; e; H$ d- x9 S
{m} 扩展前一个字符m次 ab{2}c 表示 abbc9 w9 q$ S0 M3 J3 ]0 o
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
6 ]( r: a" q: C* Q B# ?0 C^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
% L5 d" [; C5 J( v2 B$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾& s9 A. a0 j. c: k) g7 k w
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def* i& X' B5 P) T* H8 z
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
% A% u1 X0 {0 k: o1 o\d 匹配十进制数字,等价于[0--9]
9 R! ^( h; u9 g* Y) b' o) x\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
Z+ Z. r; Y* ~& ^0 r* L, @\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
, p0 C0 {" z( u3 `0 V\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
: Z. I( f# K" D' S\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
; e( {* v* j3 d! V9 Y! I$ R$ r5 [$ \\W 于 \w 相反 5 V; V7 L; I5 F( ]0 g
\b 匹配单词的开始或结束 6 D W8 W1 I# J* H9 s0 O
\B 与 \b 相反
9 ?/ h4 A) R2 I- r4 l\Z 只匹配字符串的结束位置。 3 r& G# C8 y4 ]3 N4 s
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
+ r. y4 c, E8 I$ _. ~8 N/ `
" s3 o, N4 Z2 b( a3 y W8 B【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;7 A' M7 N) N0 K9 S* f4 [, d+ D
: h1 P( }7 Q. N! ^# p% i7 B% I/ `& ?
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
8 H P, K }' s j$ Z/ @2 I, {9 P9 M0 \% a6 u$ s
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。 r" `$ N |9 i$ n0 m* b
' P% h# ~- C& w+ t. B1 R【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。* G4 H, K; |2 [4 i1 T9 M+ @4 ]
3 ]% l# s$ w9 V7 _+ }7 ?* i6 _
3. 部分元字符应用详解$ d+ W- o! J1 Y4 M( M" V
/ V/ z# n! e7 a^
; I8 X8 h+ j% u, i
) `: D8 { X! \+ D! H @匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。: R( Z- u$ C) t2 ?' z7 p
' d: Q3 }% g& | a7 S举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:/ z# v C3 B3 m2 s2 L. ~
" k" W# F7 y8 q' W# g7 fprint(re.search('^From', 'From Here to Eternity'))
5 e) S5 G2 `- l5 B: b/ Hprint(re.search('^From', 'Reciting From Memory'))
; M6 S# C q4 K1
+ D( d2 I6 |. l: N* {* ~2
5 X8 D2 i4 y/ f7 `3 Y( C7 r结果如图:
7 \4 Q& f: s& P' ] $ A! V( s: y: ]1 p2 s
) ^) Q6 D. r ~" ?+ w7 k7 C( i2 y
$
/ z& C, t5 ^( m- m. n2 Z. j) Y. j* L. m1 Q& U, z+ e
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
+ a, o) Q4 K6 H7 u7 F: ~; M' q& ~ E w6 x; ^
print(re.search('}$', '{block}'))
/ y: _+ B H2 A+ g+ l, [
; _. R: z# g- v) o7 ~+ iprint(re.search('}$', '{block} '))) f+ Q# K) P1 K& _) |
I+ a8 F$ f5 ^3 gprint(re.search('}$', '{block}\n'))
( i5 C8 Z* W( E7 }1
7 j6 O; P- Y3 @5 M2
% G/ l3 t8 b7 _) e. D5 {# i3
& d6 p6 S- Q9 z9 w2 S7 g" n49 b: e& t9 ]# F
5' N& @4 e% c6 u9 T
结果如图:& I( {6 M, \4 [
+ \. v" x. P' N$ m! x) s![]()
. F4 c! e) a+ e2 a+ l, a* L) i
! j% l1 g4 J A/ ~) ^同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
% ]5 v* F2 ]/ ?3 ^/ u B, o) D- k5 c# H' ~
\A
( g$ ~! _2 w3 a3 Z5 o* l4 \5 h2 @% z
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。8 D: _, s7 v8 l! c) C7 a2 E
# {& X, E" m( b" }' i5 G\b
+ e$ F/ u: a3 A; k6 ]5 @ W# J- p) I0 T& l' T3 m
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。! u+ [/ r# N/ y$ I
5 T$ v8 l- z9 W5 O1 S+ a# R( P
零宽断言相关信息请点击零宽断言查看。
0 o( t* @, m/ @8 ]9 Q3 V4 q3 M1 d! y: Q9 [* s5 L. V' E8 |( I
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
, @* X$ ]1 c7 Y q$ Z. x
2 s8 d' x! ]" Dp = re.compile(r'\bclass\b')/ b: O2 H, _ m* {3 D: S" k; o8 F% Q
print(p.search('no class at all')) * H' |; C( c1 q: l5 {" v
; m8 A( {# r: v3 \; h
print(p.search('the declassified algorithm'))
$ o* c5 g5 Q6 g8 s# n: V4 \" }( }- Z' B7 X: S& g$ P: }6 p
print(p.search('one subclass is'))
6 [$ e! ?, [& N: k; y1. r$ B2 Z4 {* J4 n
2
5 `6 {$ T* V" E+ d3
; a6 M& o0 s! {% a. q& T% v b4! X: z) Q/ a5 j. Z7 s- |& V
5
- x* B1 w$ W I/ F9 l( E6
- ]/ `3 V. V! Q- U* ?+ u结果如图:
2 o& [/ o- J {$ V, n+ |" Y4 o) U; E
在使用这些特殊的序列的时候,有两点是需要注意的:
, U2 ^+ J9 i n! p4 V
" E* [& N9 {8 L( G J( J$ \3 S; T+ p. s第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
# z) N# v, Z( \- E$ v8 T% n相关原理和解决方法点击详情查看。1 e2 ^/ i& I- B% k" `4 }9 ~
$ N+ S/ C+ B4 l/ t E第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
# Z; J8 U& z X9 F) Y5 A
0 s! q+ Z$ Q+ q9 Z\B0 G: ~9 l* b, r8 P F
3 U: N2 r9 U7 x! k! h( c+ Z
另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
0 f; E3 i& k5 G4 O7 f; W
1 S! |- t5 R1 [& E" n P& o3. 正则表达式实例
! R: y! _! y, r8 M8 D$ ^![]()
$ j: W6 w& Y4 Y2 t$ x: i2 v2 F" k% \9 m7 J. ]
经典正则表达式实例0 r+ u3 } S( R) B1 r
![]()
4 f$ A+ y, S0 Q7 v4 `- c* H: k, ]匹配IP地址的正则表达式
5 J2 ^* i# c1 M- ^' J8 Y* p0 E$ S! e, [. h5 p: L* |
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确) \5 l/ n# I- k) H7 U% n. {6 N8 J
# c- {0 `( E0 g* L4 J
精确写法
! m) W: ]- ^ ^% _) D
! ^+ o+ W! {' x. V0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]" _, k/ Y5 y' m% I( [3 W. s
(([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])
) L1 X6 r/ e0 d5 c/ F) l3 n原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
1 i- l- f) c$ R* r" Q" G; Z& D1 t7 L5 e: L5 a# v! [
" ?4 m! o" h' n' J; H* K$ a |
zan
|