数学建模社区-数学中国
标题:
Python爬虫 正则表达式应用详解
[打印本页]
作者:
杨利霞
时间:
2020-3-30 11:00
标题:
Python爬虫 正则表达式应用详解
# r7 T4 i6 \' x
Python爬虫 正则表达式应用详解
; T; l p) x; r5 W* a4 i2 _
, r- @& }4 r. t) A( o
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
0 H; s! }$ c# ?% _
% h5 R' D) n7 m5 d. J. U- m
—— 正则表达式应用详解 ——
+ m& u, Y2 G+ g
4 X# G3 j- \# o2 F9 Z3 _9 x9 S
文章目录
" f% O0 j/ H( W8 i
: \7 u: o. g) y, a W- Z
Python爬虫(二十一)
% k# t) A8 J: K6 I" x' J1 q1 ~- R
—— 正则表达式应用详解 ——
2 a! ?) S1 g' { A! s
1. 简介
& l1 q* A5 N. }( U( `# x2 j& \, Z' M
2. 语法
% f' Y H- q) }( c
3. 部分元字符应用详解
! _! ^, B+ r9 ~ E$ p2 D
^
7 q, g! S4 Q( O# B- C$ A4 p
$
9 J6 T% _& N" P. [/ }
\A
8 R" s/ Y$ r2 p5 ^0 a+ N
\b
- M: k- y7 Z! i
\B
* k; r, c5 x+ o1 @ _, {) |
3. 正则表达式实例
. f/ d% o" n' D6 A9 k+ [8 S: ~
相关文章:
4 q1 N4 D- M$ N. B6 ?# q
1.Python的Re库应用详解(正则表达式的库)
+ U: K) s/ W& B! `. j& a
2.Python的Re库与正则表达式的细节解析(正则表达式的库)
( ~5 q3 T# q8 p$ |: Z- r
6 @# G7 W% M0 o
1. 简介
6 _$ ~# z- h* _/ t- f$ @
, t3 P" l! f$ u0 r
正则表达式:regular expression,也称regex,简称 RE
7 G% M* b2 j! Z% T
( d5 p* y E: r8 u+ O
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
: g5 @: t, c2 v, w5 t3 S
5 ?2 |) c5 ?4 ]7 c9 i
正则表达式是用来简洁表达一组字符串的表达式
% X, i$ G0 U/ c1 Z3 ^' H! Q& ^+ U: Y
C. n( ?6 q$ U- x
通用的字符串表达框架
9 X; O. [4 {) [+ e! O
. Q! {9 l y! ^5 K3 w
简洁表达一组字符串的表达式
7 g. Y" N- V! c o3 H
$ n' a( T+ r/ \' Y6 B# o: p
针对字符串表达“简洁”和“特征”思想的工具
$ a& B6 k! J1 G
0 C( D5 t# S9 I% ]0 P# g
判断某字符串的特征归属
5 f: q6 p) d' [" L
+ n. u" N0 Q: |
正则表达式在文本处理中十分常用
) g/ [0 E& N! R6 ]5 q- W& ^! e
+ W+ w2 {% | t
表达文本类型的特征(病毒、入侵等)
) H7 d* T3 _0 j$ b* _
! m& X8 C! J# ?+ D' ^
同时查找或替换一组字符串
$ H9 s. J4 f S+ G
4 \ D& F0 W7 q/ x
匹配字符串的全部或部分
9 j' `# s: }! n
% P+ E) w, Y }0 }% `
正则表达式的使用
( q$ [! c0 L/ e7 E5 |
. ?) G7 r9 i2 d7 A6 e: c4 Q, H
编译:将符合正则表达式语法的字符串转换成正则式表达特征
# j6 f; E/ i0 v8 _1 u8 g2 _
3 M" G. d& t6 {9 z5 [
0 n8 n5 `+ d0 L! l
2. 语法
3 O4 i, d1 M e5 T6 h
; A$ B6 k% }, V% k6 |5 e* d& ], ^
正则表达式语法由字符和操作符构成
9 D, o N4 N1 \
/ q( i+ b+ y) Y
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
3 J* |( z0 x6 o$ u
元字符包括:. ^ $ * + ? { } [ ] \ | ( )
* ~% n+ N- e/ p8 v% p6 T
正则表达式的常用操作符
- `& l! i4 R9 F" _6 {4 H7 O
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
0 E/ F/ Y9 n5 x8 W G# T9 E
操作符 说明 实例
9 n; b( p$ g& `
. 表示任何单个字符(除换行符) 【注1】
: l, o8 O% C2 E1 T& i0 E, {
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
2 G: j! u- c$ P |
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
0 e: r7 K8 s! h: w% g
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
3 M. t, y, b5 N# ~% V# e) x
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
+ u4 Q& _) W; k3 R. G1 G& Y
? 前一个字符0次或1次扩展 abc?表示 ab、abc
. D# Q! ]+ o9 L) I
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
. U( m8 s7 v( X& h) o8 v
{m} 扩展前一个字符m次 ab{2}c 表示 abbc
0 W5 c9 o/ Z9 X2 D7 d& k$ A
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
! F q( S( k% j0 g! A- @/ L! D
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
' E; F! `( C0 e; M
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾
, e- L; H8 t$ s5 X9 ~7 z4 b& A$ c" U1 g
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
( G6 J- c8 Y0 z- [0 m% p
\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
9 T& g3 t; U8 e, ?0 U/ E
\d 匹配十进制数字,等价于[0--9]
7 K5 F- H3 b& _; F
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]
9 J# |2 [; g; H0 \& e3 `
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
0 e! F$ e" G5 x( G5 ~- V6 m
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
q: P( Z* q3 W/ R- `
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
! n: ]5 [' |$ U6 v5 Y0 u- r
\W 于 \w 相反
x h7 c9 U4 \% P
\b 匹配单词的开始或结束
/ A* R2 ~& d7 I
\B 与 \b 相反
7 J0 }9 T& e3 `1 m) \9 l! ?
\Z 只匹配字符串的结束位置。
- X% \; U% k8 o* K$ _$ R0 g
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
2 [) U0 t# d4 C4 M% i7 k5 b
/ I) u: ?6 w8 q/ S+ }/ j
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
7 ?' O6 a Y! P
& S1 |9 n6 _; G
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
; ]7 i% y) q0 b2 V& S* R: S7 M
r- t" J4 f6 B h- C
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
+ s; g; @ K" p8 e1 [7 f
& l9 F$ Y% w9 j0 G
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
) C. N5 @: X9 z4 X9 u9 F' @/ [
; t e! e# j6 H5 ?- ?$ R1 K
3. 部分元字符应用详解
# A8 [# A0 O, I8 E
8 G0 r+ l% M8 j2 k2 p6 f
^
0 j* P5 r* U; r; P7 C! x% L
6 h; {6 ^1 F! G# K. n
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
/ O2 m9 K! @( I; C0 q
6 w; ?) @' h6 Z3 p. d
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
+ S8 T; |/ v2 @
* @6 d- j1 N. q5 d
print(re.search('^From', 'From Here to Eternity'))
7 r5 \- c! v, `3 Q+ c
print(re.search('^From', 'Reciting From Memory'))
3 T! E) M, V/ A# c
1
! [- J4 W" `& q. m5 |- E. I
2
; K" W4 G/ v) J2 `& I' K- T/ Q
结果如图:
3 Y7 y0 Q& {+ A2 z/ P# j* T
1 @, ~$ j' d T& H; l- C" k8 W# [6 d
8 Y Y0 F N/ v6 V. W& d" M/ _
$
1 N' i. ?* T" Y. p# m8 W
+ V* _8 Y" ^1 a: O; l# p2 L; R
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
) L" g+ N. S% K" m
2 m2 z% `" c, h! ~
print(re.search('}$', '{block}'))
. F. s, D# c# X
8 R& J. a4 f+ O( i; ^
print(re.search('}$', '{block} '))
5 k- g" |5 ~9 I8 Q' V& z
. Q0 j" g7 b" V0 I1 e, @
print(re.search('}$', '{block}\n'))
/ u0 j2 M: K& e: i) n3 j) P+ e( R
1
* o; i2 D1 I; J2 [; A& w
2
: J- N8 U( r9 [* W
3
- i: f9 G, s1 l7 z$ F
4
/ I: G4 ]% _/ Y9 G
5
* D; G6 v# ]% Q! G$ i% t; }" X
结果如图:
# `6 u& i' ~! c- f0 C* y
( K* s, b5 w9 \$ }; H
; e! o- o6 c& f. H% K
. u) ?. q6 a& W% l
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
8 j) _6 l; ?( d; [
) l- _# E: q( \$ Y# b
\A
/ A- M, L* {& h# P
$ Z; d% T& H: t! m/ i
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
; ~$ B& e6 A" h/ Z* O ~
" q7 F8 Z8 o# K5 e8 T0 }
\b
0 S+ Y z9 a1 B2 ~9 r
7 s0 W: e: v- u1 N3 p# d+ k% V
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
; p# P5 W# u! j9 P8 B( M: u
0 h( Q, c: n1 }7 E3 T- ^; ?
零宽断言相关信息请点击零宽断言查看。
' D% t1 H2 S4 p
+ C4 i+ w' n5 p) Y( K x Q
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
: }# o( B0 w. O
! `7 n; _! P! v8 z
p = re.compile(r'\bclass\b')
" h" q0 p: s5 o i* D
print(p.search('no class at all'))
9 F4 a3 Z1 ^ `
' L9 t- B! h1 C, g U
print(p.search('the declassified algorithm'))
6 u& v) L1 {0 v( \' I/ T
7 f7 {5 V% C& I' R. L9 J0 ]
print(p.search('one subclass is'))
/ }: x, Z0 _& Y6 m
1
$ S% T# S* T5 K3 f0 N" d/ X) i! I
2
. b9 V+ E. g, ~
3
* T( {3 e9 y3 W; x Y
4
7 x1 W; b1 V+ X1 x9 b( V
5
! a5 A. |+ _, O; |8 T
6
# D8 U* z, w! Q' ]2 m8 @, |
结果如图:
0 F T t" }+ M. X% J! p
& r, a9 z+ k6 @: Z) F% @+ n9 P8 ~- L X' l
在使用这些特殊的序列的时候,有两点是需要注意的:
7 z; e# d" G$ d
; u* G/ P9 C" I. }. v+ G5 Y# o
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
% s" q( u. i' ^0 @) w; S2 M
相关原理和解决方法点击详情查看。
o9 [+ U0 Q" l. I% n; E! z
" E; n" b, m9 |' ~: `+ E5 E4 A
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
% R4 d! b. Z0 X5 o
' `2 `, u! V9 \3 K. F1 h2 |( c, p
\B
, z7 e9 R' s" k* j, X2 W" |* V3 f. B; p
, I7 Z) M N- d- u) G& t
另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
; A& ?" j7 U3 X V
' e. L8 M# J2 R
3. 正则表达式实例
1 P& N* Z, p- m5 F3 \8 y- l; l
/ e9 [4 y. b' `. E/ X
# k& @( T _4 I* x" B
经典正则表达式实例
! l" s# K% Q! K' {4 Y
: ]4 d7 w) G! W+ Z: R
匹配IP地址的正则表达式
7 y, |. V% |: M$ ?6 Q' x5 |
4 l4 o, z6 y; R: A
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
& J. q9 T2 v ?4 g5 ^8 [
% f/ Q* u) _( v7 L* l3 s
精确写法
0 J) m( l& y9 Z
! L4 t% e4 Q/ j# w
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
/ Q' w9 p! B7 R7 B$ B
(([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])
" l, l% t [; A! Y/ c
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
& `$ v; i* R& f' E
) [+ Y4 @. b% V H+ D: L& H+ B
3 b: J, r7 U7 W" V O
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5