数学建模社区-数学中国
标题:
Python爬虫 正则表达式应用详解
[打印本页]
作者:
杨利霞
时间:
2020-3-30 11:00
标题:
Python爬虫 正则表达式应用详解
$ ^( t4 B q4 a; Y' i' H3 Z1 d
Python爬虫 正则表达式应用详解
+ e- t$ f. O! c7 ?2 }# U3 ^3 S
/ C1 v% ^' J1 D% ^
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
* A9 I! t4 F, f v# S. S
2 ~4 N4 J& [4 y. W; x
—— 正则表达式应用详解 ——
3 }9 p' I4 ? Z3 u, C5 R
6 Y- ~* P/ Y) g+ X# k4 z
文章目录
" g. y2 N- D1 [- g5 Z- k8 h6 ?/ z' x2 D
5 _. o9 Y; v: c7 U( j. r
Python爬虫(二十一)
( V- }2 [3 X1 Z4 j2 `3 ~: K
—— 正则表达式应用详解 ——
3 j0 U j$ f# u$ R1 _: @
1. 简介
) i. s6 k2 w" @; |; @: z( I
2. 语法
+ }9 p6 x" |. r, o, I5 L" Q* T
3. 部分元字符应用详解
/ U: ^4 g v* W, V7 V* P
^
' j% @6 X2 n. [. o6 Q& i
$
3 t, o9 h2 I9 k3 u' L
\A
4 D/ f( D, d3 S
\b
2 E4 q3 e# c6 e0 {8 O7 V
\B
$ K" ^0 {2 b3 s$ o
3. 正则表达式实例
/ ^4 [. ]# t5 y
相关文章:
' ]. Q* \) h7 M+ x
1.Python的Re库应用详解(正则表达式的库)
1 c3 N* C- q% X0 W' v* O
2.Python的Re库与正则表达式的细节解析(正则表达式的库)
6 s+ Z/ v% |! w' J4 K# X. [, R
8 f1 H! p+ E7 {) r- j# @6 P
1. 简介
) i2 v, Q4 g3 ~8 A3 }$ H- w8 _
- Q' L# E$ ]3 c9 h* _2 a
正则表达式:regular expression,也称regex,简称 RE
8 s, \. |3 {- Y# N6 i; D
5 D- P/ t" C9 F3 ?
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
! w9 P1 N* B8 n3 g
, h, U9 t2 W9 r" N1 p' G3 \+ W6 v0 Z
正则表达式是用来简洁表达一组字符串的表达式
% b. j8 q9 v1 P( T6 n7 T/ L( R
) f# k5 g' y @
通用的字符串表达框架
, F- v9 E8 y P4 j) e5 o
* q0 I. j4 k/ A1 n
简洁表达一组字符串的表达式
" L9 K9 J" ?: H
- S% q; O2 R f+ o/ t
针对字符串表达“简洁”和“特征”思想的工具
3 ]/ W) ~- S+ m0 }& {+ i8 j1 c; t
- x- A5 q# ], f) p
判断某字符串的特征归属
) o: U7 n. \' v! H# ~
- c- x" ?" Z' k8 |; a
正则表达式在文本处理中十分常用
/ Q# e' n p8 g4 ~0 T2 \
: B9 K7 A& M6 l: C* O3 P: |
表达文本类型的特征(病毒、入侵等)
% ?/ ]# q( V/ W" x( Y
) u5 M/ U) D- g; F/ V: S
同时查找或替换一组字符串
7 {9 e" m8 x9 j
' w0 u7 n, `$ L6 T }) s
匹配字符串的全部或部分
* o, t- e" S& Q" Y6 o1 L1 W, L
! A: w! b% p# |2 e2 G: k
正则表达式的使用
: G. E/ S! {: o L/ P! I
2 y: G7 X' j5 j" z- D8 R0 D" D
编译:将符合正则表达式语法的字符串转换成正则式表达特征
( e) `2 e$ `9 i( z: e7 t, v
' F9 U. [% h$ f
+ @+ _$ m. v I
2. 语法
/ B0 l3 E' n$ l. T8 W) z
" U L$ o1 |8 m" K, U
正则表达式语法由字符和操作符构成
6 x, F& w: v5 I( G/ [7 B
: b2 d( c6 U {2 ^: i& N. H& M" a% M
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
- f- E4 ?, |# W Z* M2 \
元字符包括:. ^ $ * + ? { } [ ] \ | ( )
, _+ ^4 E! s- i9 ?- o
正则表达式的常用操作符
9 Z: I1 a8 [# j" G& C5 h9 A, i
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
; }! |! U2 y# _2 T1 @
操作符 说明 实例
9 [% }: |6 x6 ?5 m+ y
. 表示任何单个字符(除换行符) 【注1】
% r: l% c5 j/ c4 |
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
1 c3 e [- B+ ]/ o6 ?, z
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
( C6 i7 V+ u3 `, p
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
; H* Y- O) J) W- m# j+ u
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
2 ~% W$ J- ]# C! Q0 I9 G
? 前一个字符0次或1次扩展 abc?表示 ab、abc
7 A. T" e* p& S$ G& Y
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
9 q7 e/ u" M$ h% o$ Q: a- u6 r
{m} 扩展前一个字符m次 ab{2}c 表示 abbc
6 D+ M9 ]- P) D8 `+ \1 K$ e: h
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
1 |* q$ @/ K' f$ Y6 @# H/ _6 \
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
, o0 ]2 [$ v' p! o
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾
) ~" F+ m9 U/ d/ Y% |$ `# u& H. ~! J
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
& }& P4 b% L# o y/ ~
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
) i D) T) V3 ?) v# r# x" i
\d 匹配十进制数字,等价于[0--9]
5 [; t( L9 P7 ]2 Y r9 Z+ [
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
' U6 |! a7 ~. ?# S; e v; q
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
6 k; k9 f1 }! F; s" }; q
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
( c: Y' z+ @& h, y, U6 X4 B
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
6 h$ f8 |9 f* }1 ]! a
\W 于 \w 相反
9 a: B5 b, M; O7 j- U% N' t
\b 匹配单词的开始或结束
2 c/ W( L5 w$ i2 q e3 ^
\B 与 \b 相反
" ?9 m4 }9 J q- d* G* L& q7 ?
\Z 只匹配字符串的结束位置。
. U. e7 V3 h% I% q
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
, h1 M, f! d( P I. F
5 n$ a9 D# Y( U" {
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
! s/ @" a1 Q, a0 j5 b& D
8 \5 S& d1 L- z% f* d& H: ~1 Q
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
6 b$ t+ j& L$ c" n( V6 w
: d" E2 E/ i1 y( U
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
) R& V ^( [9 E. p9 L t
# J9 |& r; J, m0 q" n9 y" h, k
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
$ \+ {' T2 c9 {$ J- w
- X) g2 o! D+ g& A* Q+ v5 D6 u- {% @% G
3. 部分元字符应用详解
1 A1 n2 ^$ H0 q* s; l# R' i
1 g9 A. o; t/ R0 N7 H" m5 N
^
7 z& x2 k# e% G8 J3 n% j3 T2 M
9 [4 c! u/ O" ^+ Z7 O: D( s4 T+ k
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
3 D+ a$ @; j9 {8 `- w, d
! l1 ~6 \2 X5 S0 Y0 c1 t3 k
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
1 a, h( I; `. w, ?$ A8 }3 P) J
8 ?' a2 T" k' S4 g% B
print(re.search('^From', 'From Here to Eternity'))
. H9 h7 L; c' A
print(re.search('^From', 'Reciting From Memory'))
) L5 E4 t* v5 q
1
8 R+ L0 }1 D$ g( E4 Q- z
2
4 ^" W8 X/ G+ H/ k6 x
结果如图:
8 B; L/ Q/ U2 R8 H7 N5 s ~# Y
4 I0 o) q9 s8 U' t
( R0 d$ D2 i3 b9 _, H
$
+ T1 M/ o4 {4 q/ |. \$ o
0 |! @! r- l: Y% \. V3 S% B
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
. Y, e4 ?, i: W0 F
$ i2 E# ?! O: h
print(re.search('}$', '{block}'))
3 p0 I" o/ o6 n/ J( P
# m8 e3 h0 t: W- m S- G, a
print(re.search('}$', '{block} '))
9 g, ?3 j6 H8 l( c7 Z
, K( ]) _+ z8 Z& D* x- F# p$ q3 D
print(re.search('}$', '{block}\n'))
7 t$ I8 o" s+ a4 c5 o. @
1
1 @4 V" y" X- G0 y
2
2 d* \8 D) t1 ]; R. X) f2 P
3
2 E. t, e7 N' ~" c7 W; R# h
4
o" c1 F+ A3 W; C( H
5
' t5 u. e6 T% ]8 ]2 c8 E! f
结果如图:
/ w" I+ c/ K* d5 ?: ]& |1 h: k) M
% y i5 E4 ~9 l. o
6 P7 K6 {4 l8 b% V- W
- I, M/ Q- d$ W8 V% B5 @
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
- d: ?9 y4 H k" A7 |+ ?$ G6 F
7 F) F& _4 G* h4 n% D4 S" ]1 e
\A
- I9 _& l7 ] E2 L. Z2 u
8 }) m4 l) m0 P y M0 r/ Z
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
" N8 V& d! a% Y) {# ?
b& Q* h5 Z6 U6 @! @& M
\b
8 W4 q5 {" N; U/ r# O' j3 i
; Y# e& E; O' S, L
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
8 M0 O% r! B! e# Z' s2 G7 S$ L
. r' y( f: F3 W& D* P! t2 {6 A
零宽断言相关信息请点击零宽断言查看。
# {5 V" G- M- S% M1 B
( d- u; b5 r. d8 b4 P
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
& D" _% K! Z+ L$ M" {% [! G
1 V" N; E4 z4 A
p = re.compile(r'\bclass\b')
0 K( a; z' _9 @$ q$ u. }* h5 ~0 X
print(p.search('no class at all'))
9 [8 U* g& k$ J2 k. o5 k8 b
' _! C4 J# ?" e( F. v
print(p.search('the declassified algorithm'))
, h1 J" |! c+ Z! w
- m9 s& ^5 N4 w K
print(p.search('one subclass is'))
& q* u7 [% L3 `# d! ?3 }+ f7 p: T
1
k" [5 w: ~) f) \5 p( m; e C
2
. f1 v$ N5 E) v- q% s& P- l6 B1 H
3
3 ?& B. c. _# J
4
( W! G+ x! I! W0 ^9 b6 R
5
) \1 h: J* i5 ^' V
6
$ r. W; D: G0 x- k# T& D
结果如图:
?& N, K7 v2 {, ^ i) F, T& q$ I
& ]# V3 W- b: O& [
在使用这些特殊的序列的时候,有两点是需要注意的:
3 Y& I* J y. H N
$ R" T3 T) F5 q
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
" Y3 V% K5 I- s6 y) ]- v+ ^+ N+ P4 a
相关原理和解决方法点击详情查看。
$ W( _, N, }0 }) n( m
$ r& U; B. {; m( G9 @: O1 _
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
- m2 o3 x: B/ \' Q* }
) G% K6 ?" R7 y( V
\B
E1 z. [6 E0 r( S
, d& W7 N; i5 X
另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
. s3 n- ]: H1 f( s5 |
" P3 ~/ C2 k8 I4 A4 N
3. 正则表达式实例
/ H+ |# G+ U( R* y7 H3 \
# k6 z6 p s/ e- v$ H
# {- _: J0 C/ `$ a2 j, b$ y
经典正则表达式实例
0 L- R7 s: ]; S& t- i( ^7 @5 A
! w1 _. P5 d8 B5 ^: b
匹配IP地址的正则表达式
8 O! f# B/ P* M! n
! [, F2 T- k) ?4 C9 `/ b8 X
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
6 S% _# K. {, m H
- X( o' B7 ]6 K3 r) v, U: x( ?; u7 k7 X
精确写法
1 A- _" M3 S" K; w# e- u1 B
2 |* y6 C% Q( m$ j
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
4 g; m% c5 z0 H0 p2 u8 v! ]- A
(([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])
! P2 F2 c) Y' x/ W8 b
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
1 v' F+ [+ y/ J
& t: y' E: w, b! L
s- s- J0 I' Z' w+ G1 }
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5