数学建模社区-数学中国

标题: Python爬虫 正则表达式应用详解 [打印本页]

作者: 杨利霞    时间: 2020-3-30 11:00
标题: Python爬虫 正则表达式应用详解
6 H* o2 A9 d+ e8 b
Python爬虫 正则表达式应用详解
& a4 |" E1 K9 f, U5 h2 ]7 a% X1 w( Q5 n
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
1 L4 o/ y' Z, u" Q' e2 B0 b  q8 x( K3 z' l* [
—— 正则表达式应用详解 ——
* V6 Q2 o  y% j( `3 p! j9 k: p' _& o8 U$ O% `7 F+ p. ^/ \. s& j
文章目录
: K5 e+ X7 K9 f6 t! w0 W, ~
4 N+ G4 Q: g5 P. q' SPython爬虫(二十一)' Z# C) H! [2 Q" C. g5 h  o
—— 正则表达式应用详解 ——
! q% h& }, E* z6 `1. 简介
# Y; r8 q6 B4 `, H( M# e1 ]2. 语法' i, V; E/ q9 Q; v- M
3. 部分元字符应用详解# Q  \: Y9 G' G. b& p- _, y3 R" T) e
^
2 |8 |  S* Z- x+ J7 T$ `2 A6 {0 B) a$, \1 s1 r4 V$ C* R$ |
\A5 x1 S3 V* ~6 Y  W
\b
9 ]" J  m6 n1 f7 ?- s\B
3 @8 I0 S* U: }; R+ S" e: B3. 正则表达式实例' L- w( x, R1 Z0 U" r7 m% q+ [
相关文章:
" \* m* w% Z# ?; G1.Python的Re库应用详解(正则表达式的库)# ]3 H7 [% t/ C
2.Python的Re库与正则表达式的细节解析(正则表达式的库)8 n* i5 _+ X- l
( m8 v1 B) w/ k# `  w- H& y
1. 简介( O6 X  v0 E7 R  T: N/ J

$ _/ M$ o$ ?* |' `8 a% R正则表达式:regular expression,也称regex,简称 RE2 t' z5 H# [# [1 V; B" ~7 x9 F; g
* y! y( W1 j+ X  H
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
. P$ L% `, B( H* M+ L% B3 u/ H# H( ]: {. r: j- w' Y7 i4 V0 @
正则表达式是用来简洁表达一组字符串的表达式. Y; h9 I( H! p8 J2 m3 N) n

! f' ]7 l( x; J& m) o6 b. ?3 Z3 B通用的字符串表达框架/ r. e& U& o" m+ @9 ]% K3 S
$ m* [; ?" ]$ ~+ X
简洁表达一组字符串的表达式
" U7 q5 U( Q/ o: k. k: A$ W" N7 R# L) w
针对字符串表达“简洁”和“特征”思想的工具! q% i: a4 p3 E0 U3 q) \
- B4 o3 k8 W% V
判断某字符串的特征归属
1 U" _4 h+ Q% q4 E+ j# ^9 {, X3 o8 @( q1 \+ B* g3 _- K
正则表达式在文本处理中十分常用. \" X( C, R4 G4 i7 ~4 h  b
- W5 K( Y7 G9 s1 f7 d
表达文本类型的特征(病毒、入侵等)) o3 |% H2 r3 b: l4 B# T
- d2 f8 i6 N1 M6 Q: t
同时查找或替换一组字符串9 X7 a2 q& X/ ]% d" }

( N; N$ {) s* a5 N/ ]) i. R匹配字符串的全部或部分2 @! ]+ T/ R2 A, f
0 {# h% v5 E+ K' S  n) ]
正则表达式的使用1 y2 {" U& g- j% p
( H$ _2 i; i& `& @
编译:将符合正则表达式语法的字符串转换成正则式表达特征
7 x6 O* z; p5 p6 B0 b2 }
% y: x, c9 W  `8 W+ J/ m% w8 n  D+ H8 f9 V$ A
2. 语法
+ ?/ j, s3 b1 V+ f8 v- h5 ?8 \5 r" ]0 v7 Z* t  A3 s2 \/ p  ^( D) M
正则表达式语法由字符和操作符构成
* [( l1 z/ p8 c! Z( x0 G3 X, C# H
( u/ p5 Y5 F$ D- q7 a7 g有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
8 B- i5 M$ Y8 i1 w# N元字符包括:. ^ $ * + ? { } [ ] \ | ( )$ W6 }, ]$ E( u% X
正则表达式的常用操作符& ?2 P7 C2 L. {; z: ^: ~( |3 t
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发( S( o. T, X' ~* J5 q
操作符        说明        实例- \! v# y; ^% Z  @6 j6 D) @
.        表示任何单个字符(除换行符) 【注1】        8 s; p1 G3 j+ O, Q) ^( a" X7 a
[ ]        字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能        [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
  d3 B3 ?5 p1 N( k[^ ]        非字符集,对单个字符给出排除范围        [^abc]表示非a或b或c的单个字符
9 ^6 @. z/ U# I9 G+ F*        前一个字符0次或无限次扩展 【注2】        abc* 表示 ab、abc、abcc、abccc等
, T0 u  D, d- N, y: p3 k# U- K+        前一个字符1次或无限次扩展        abc+ 表示 abc、abcc、abccc等
. p" r+ X: P; |+ ~! m: |. G* X?        前一个字符0次或1次扩展        abc?表示 ab、abc
/ L4 ]' E3 l/ m: V+ M|        左右表达式任意一个 【注3】        |abc|def 表示 abc、def, A/ n, U& M/ a8 I" W
{m}        扩展前一个字符m次        ab{2}c 表示 abbc
8 f2 @, o; C) E  k6 }6 o{m,n}        扩展前一个字符m至n次(含n) 【注4】        ab{1,2}c 表示 abc、abbc2 r: B: a( M9 l; j' ]
^        匹配字符串开头        ^abc 表示abc且在一个字符串的开头
: N' E" V8 b( |$ Y$        匹配字符串结尾        abc$ 表示abc且在一个字符串的结尾
& |' `% u6 w% t) o( )        分组标记,内部只能使用 | 操作符        (abc) 表示abc,(abc|def) 表示 abc、def
" [/ X, O% ~; E9 L( |2 E: H\        后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\        \d \w \u
! x& Q: i" M8 x$ B9 t# J\d        匹配十进制数字,等价于[0--9]       
1 o7 @, n8 G; _8 T5 S- ^5 U\D        与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]       
2 m4 B' W  N- z4 T\s        匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]        0 {4 J, `& P: C2 r! @: }, F3 H
\S        与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]        ' d  B8 ^1 c& E6 A
\w        单词字符 【注5】 ,等价于[A--Z,a--z,0--9]        * Z2 g8 b# \) |, A3 q
\W        于 \w 相反       
- l# i0 d) o) R  X\b        匹配单词的开始或结束       
6 G% V7 [; _( x\B        与 \b 相反        * m6 v+ A. B3 O9 k6 i+ _
\Z        只匹配字符串的结束位置。        ; `* ~, K6 R) r9 J
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
, d/ w0 X9 H, F9 }3 ~- C
6 S/ z  n. r% H  V8 S) j【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
0 J( e1 E1 O2 |: @! J  O$ V. o% p" J! X' V. A8 B$ x
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
7 O% w6 F3 Q1 x! S# r; [/ c2 C1 F* e. O: x4 u8 k" t5 ^. K. v
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。* z6 j0 d, U9 V  \& p
4 {" O$ u: W+ c
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。8 {5 v/ B1 U; l# X5 z
. a! }* g% X$ X# {* q7 f% U
3. 部分元字符应用详解
% k( N3 U! u+ [) w- y/ v
7 N, u# a, _2 d! K" I; f3 ?^- y0 z" n5 T4 B" @+ w) o0 \
: x0 I5 Z5 K# a1 u) j) A8 B2 e
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
! V3 P5 b% u& ]
. y. [8 h- @( q& J举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:$ N% e1 @0 O$ ^
: R! O+ k9 i$ B5 b' U9 u7 i
print(re.search('^From', 'From Here to Eternity'))  
+ B' t! ^+ ]: i2 Q, e, u2 G) o; Jprint(re.search('^From', 'Reciting From Memory')). c$ U$ o/ i8 |& N! j. v4 v8 l
1  [. u7 L; \  z$ e# Q" W
2
" i8 U6 m! A5 n% w- p( v# k3 Z0 P( D结果如图:2 g* w% V( p& S# N$ i: w8 [# K6 i5 C( s

2 W  [: _4 Y. n+ I/ Q8 X! v+ n/ `% l) ?8 c
$# H# b3 w& P2 ], u1 {, t
6 U  t- D* a3 a) k
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
3 V2 F4 X; E9 S# d4 N7 z) n& g* k2 J  b
print(re.search('}$', '{block}'))  3 k5 `6 R5 ?* z3 _; V2 `' x5 w
' Z% G' c2 B# @3 t5 d
print(re.search('}$', '{block} '))
. \) M1 w1 \' ^* \$ {* P0 v3 J+ x( ?1 p9 u+ s( K
print(re.search('}$', '{block}\n'))  / _/ T; W2 e2 w& H8 K8 N" c
1: c: W' K- F! N
2' ^8 Z/ Y' R$ W- \- M# U- S
35 D+ ?( k, B' i
4
. B0 T  b  B' P7 e# Q51 q2 r. b# r4 ~; e% W6 ?0 s7 @
结果如图:+ k& j! r4 V" E

+ y7 s9 I$ V5 W+ |( B$ c& ~* V
% Z! p9 m, D1 U8 o& T
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
( ]1 a# ]6 c4 J- O3 c/ r* c; ?0 A' S  k1 W( L* e* y
\A
* o. H" x  b. h" d6 ?: E' s
- v$ v, g$ d- o& l/ ]2 ~只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
8 R7 q2 z/ `) `1 Z9 c1 ~2 r8 ]
9 o  i/ {( |; V0 H; C9 O$ d\b
6 p: Z. T0 Y& ?* T: l& {
2 r, T; @7 ?  Q0 c7 Q) S单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
/ r' l7 J  x6 @4 b% p" O
2 [0 J( F  x5 G3 v) [8 A零宽断言相关信息请点击零宽断言查看。
: v. B' w& y( d1 F9 g+ ~
0 l: s* J. P% `: o下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。/ u- B" Y5 w3 g" V. r
5 g' m% n8 s5 ]% R" c
p = re.compile(r'\bclass\b'). \" {1 v) O  o) N- |4 r
print(p.search('no class at all'))  
( M5 E; ?$ i0 f6 J# z* W
8 {, e; K, h% ^3 I, cprint(p.search('the declassified algorithm'))5 A9 P  a# b0 J6 w5 m$ k2 z4 |

0 F* H' l  p2 I9 b1 {' t( ^+ Tprint(p.search('one subclass is'))
$ ]4 j1 u2 J0 Z6 g1; G0 u- A5 Y4 \: R6 F
2" `$ v5 b9 E; v- w2 y1 W  i8 i8 S
3; d7 I' t/ p4 i% b- z/ a1 K
45 \3 G2 i1 x. v5 N2 J& R
52 H- ?& q. i3 x  Q% U
6
4 q/ `' D2 x! U结果如图:( G4 Q4 o. F: ?

; Z: d" {2 S  B# U在使用这些特殊的序列的时候,有两点是需要注意的:
* r! C# q7 _0 t+ a% z* V8 g) I! b& l/ W) \" E# N
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
' I8 V/ K2 i4 ]: {7 {: w相关原理和解决方法点击详情查看。
& q. |& ?! G: l' @+ y1 Y7 P3 X) f" ^# s5 f' Q
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
( B5 C: q8 p7 m  q
" m# P/ j2 J: _6 w7 a- t) d4 b5 x\B
0 z- |6 M3 s0 E, M
( r0 w- z8 ]( Q4 H# u另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
5 ?- N, p/ J+ o2 K# R; o. t3 b, Z. U' F
3. 正则表达式实例+ L. n% y2 D! M) r
! c0 D# ~& a* o
0 x0 s8 L' j8 V- Z5 j/ J
经典正则表达式实例
2 Y  \* q3 g  u. ]: W$ f: c0 ?* m) s6 x0 D- e
匹配IP地址的正则表达式
& c0 _* w* ~7 e) E* |5 g$ P" D2 ?( ^$ w! K
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
$ H. G4 `8 o/ g* a' m9 r
7 g; {2 a0 B! @) q精确写法4 a' X/ s9 C3 m2 ^0 B  K. m

, l1 H3 B$ }3 l' l5 k0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]0 \( l" r0 F) A- x+ G; \
(([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])
' u1 I6 `. F7 D* Q2 e1 M原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
! F. t4 s; Z' x
3 ]7 ~. Z; V: T/ n) `: z  W; X4 z- A4 Y' V8 h8 f& L





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5