数学建模社区-数学中国

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

作者: 杨利霞    时间: 2020-3-30 11:00
标题: Python爬虫 正则表达式应用详解
% X, c7 m3 [2 c8 P4 a* u
Python爬虫 正则表达式应用详解
; |7 G; `* G$ v7 K% e, v2 m/ k. L( f$ c; k
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。1 c' A6 ]9 ~+ H9 [+ h; x
6 E: C  B0 N0 J6 k) T7 b
—— 正则表达式应用详解 ——
4 _6 o% @# t& @& e9 z9 u4 `' ]$ g1 D. V
文章目录
5 e/ k/ B, _* y1 |) N) ?  c$ k, b, k1 v3 b. q3 p2 C' G) x4 g$ v2 ^0 [4 A% D5 B
Python爬虫(二十一)
" b  E  W& n* u3 ^$ C—— 正则表达式应用详解 ——8 e' P0 B* @6 G
1. 简介, ]* q; D4 M( t7 D( l8 \
2. 语法( R$ Q. f; X5 X+ B" H1 h. a- B& w
3. 部分元字符应用详解
. o; Q; h2 a- \9 W; ?" e^
/ _% A8 I& |- g8 D$
) p" D' J$ Z. o  [\A, x2 |( p) I3 B% c
\b
6 B+ |( x8 S% s5 m) c% l\B
: f' P- x4 B& I- M% p3. 正则表达式实例
7 A! f; R+ S, V( D' o' |相关文章:
2 |" P9 {! ]2 p- B8 z1.Python的Re库应用详解(正则表达式的库)
4 _. O3 {4 F; h( W5 n2.Python的Re库与正则表达式的细节解析(正则表达式的库)
0 y* D7 W# F/ |" G% S* x( n. a
# b* G- ~; T' m& d& x' a1. 简介- \/ R. P( J! G* |/ V

' `% G# @0 ~# l9 F5 v2 R  H! q- I正则表达式:regular expression,也称regex,简称 RE
/ V; s8 X7 D/ E! G7 \6 I
2 h6 I8 E9 M" t# ^5 Y' ~: J正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
  r: X0 }& k; I" `1 ]/ A; g& \. f4 X
正则表达式是用来简洁表达一组字符串的表达式
1 o& t/ b0 a6 J8 B( j+ A% f9 ?* {: M; o" C2 c/ _) \$ h8 ^' L" O
通用的字符串表达框架  B3 T8 T3 L8 u! c) K: H  G4 N* J
$ G. O' `/ u' Q
简洁表达一组字符串的表达式
0 D  G! K8 H% l: ~% [0 n4 w, U# }: {" E2 t$ w4 @
针对字符串表达“简洁”和“特征”思想的工具
; N6 o! G! I, D& }4 k) l6 p
) R1 r- N' g9 X7 @2 L0 F判断某字符串的特征归属/ w$ h1 h# c( ]' `
* {  `# s4 m: V! H# d/ t' p
正则表达式在文本处理中十分常用! s3 h1 T5 W8 {' n& a9 x* I) [. P
* r7 o! L/ R% k/ w. b0 b" K% I+ u
表达文本类型的特征(病毒、入侵等)) W/ K& Y, t: g! l

: [: e; @7 n0 A& [9 q9 `- a% D- s# p同时查找或替换一组字符串- a3 M9 R$ I. \4 [
( B% I  Z8 [" @
匹配字符串的全部或部分
4 f0 Q( Z, O0 a7 O& b2 g0 H" P
( G% P& @% i4 M3 [6 ]; z正则表达式的使用: j0 _, ]& O5 y3 P3 X
. p- D: {8 K/ Y
编译:将符合正则表达式语法的字符串转换成正则式表达特征
% v. y& n. L8 X+ N
. ]5 P( M  C1 J* p5 C7 h
1 K7 Z8 i9 }4 D6 l. N+ T2. 语法9 l8 y2 H+ E0 o! o
$ B( i5 `8 _0 I8 l: z
正则表达式语法由字符和操作符构成( |! a7 N' v( S. `, m+ P% z
$ y1 w+ w. J: I9 B
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。. P, w3 E0 f/ h3 W5 [
元字符包括:. ^ $ * + ? { } [ ] \ | ( ): x6 l" F3 ^; E6 L1 g" |' A
正则表达式的常用操作符
- a4 B6 h6 T  V2 @& i2 @在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发
% j( {. N6 \2 w操作符        说明        实例
1 R4 f% U! ?/ U) @" W. V4 t2 t.        表示任何单个字符(除换行符) 【注1】        7 C  T. ]( i4 m' L
[ ]        字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能        [abc$]表示a、b、c、$,[a--z]表示a到z单个字符7 D5 W4 g& \$ W5 u; a4 ?8 ]
[^ ]        非字符集,对单个字符给出排除范围        [^abc]表示非a或b或c的单个字符, Y% f! x* P, k9 C9 r4 h9 O
*        前一个字符0次或无限次扩展 【注2】        abc* 表示 ab、abc、abcc、abccc等
: f& _' I& }2 x+        前一个字符1次或无限次扩展        abc+ 表示 abc、abcc、abccc等
' ]; V! G: E( B/ r& i?        前一个字符0次或1次扩展        abc?表示 ab、abc
) }  M* o3 z, I1 K3 Z& L. S|        左右表达式任意一个 【注3】        |abc|def 表示 abc、def
' T& V% K5 n. k  E* T( _( @9 z{m}        扩展前一个字符m次        ab{2}c 表示 abbc
! s' O% Y6 B, Y9 u5 I+ c{m,n}        扩展前一个字符m至n次(含n) 【注4】        ab{1,2}c 表示 abc、abbc
+ c7 S! x$ c$ }6 N' I^        匹配字符串开头        ^abc 表示abc且在一个字符串的开头( n8 t* @6 i/ n2 m( ~5 ^! R' t0 O
$        匹配字符串结尾        abc$ 表示abc且在一个字符串的结尾
8 d7 R) N# x7 p* c+ g( )        分组标记,内部只能使用 | 操作符        (abc) 表示abc,(abc|def) 表示 abc、def
/ E! O5 Q& U9 r7 ^! P9 m\        后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\        \d \w \u
7 X- m2 W( U0 P7 z* A+ ^6 l4 E, F\d        匹配十进制数字,等价于[0--9]       
  X# L" k6 k4 @; h0 H\D        与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9]        ( q, M9 G8 y! M* [( v
\s        匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]        & E" h) M6 q  d. F* t
\S        与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]        1 g( [$ x6 w1 |! b! r
\w        单词字符 【注5】 ,等价于[A--Z,a--z,0--9]       
4 z' `# ~4 |8 ^9 z6 _! I( z\W        于 \w 相反       
4 ]8 t3 Y1 Z1 V/ x  k\b        匹配单词的开始或结束       
: N2 J2 H. w8 Z( z6 F) f/ A\B        与 \b 相反        % d+ e6 k  S$ l# E( H* k
\Z        只匹配字符串的结束位置。        ( O3 X# J2 m4 Y+ O
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。3 [; W6 k$ O/ @" J0 A; M
0 I! \; m5 T. A
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;7 |+ v3 S, E% L2 D9 G% e
, U- C* w$ \6 T9 y5 e
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
: w3 v3 Y+ ?- ?% u( q4 B3 r( N- @6 V0 D
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。( t* b# g7 x% }) N' h) y6 R
# _' l) s$ U. T% T5 {: r2 [
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。4 b! z5 V" U, _& u6 Z

- }; H  t8 i9 S3. 部分元字符应用详解0 D$ k7 Y1 W# @3 C
: ^5 B1 w4 a. ]
^4 f8 v4 ?' [, e0 r
& p+ @( G* P: G0 G8 E! I: N
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
7 |6 N$ m) k" d" O9 `) n( n  ?6 I' s8 b6 j9 X- K. G/ E, E
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
1 `# B. S% Q* @4 w( k" [  z3 G7 i" _* \" ?7 V0 A, x8 U
print(re.search('^From', 'From Here to Eternity'))  3 A5 G$ C* O8 v6 L9 s5 f- u) |
print(re.search('^From', 'Reciting From Memory'))$ `& Y2 r% N8 L* K9 u) q
1( I! T; F& v) s, R% F; J
2$ L& U) V; c! g
结果如图:8 d, H3 l4 M5 L! g5 z

! Q2 a0 X) U4 C/ C/ c. P
# \0 e! o+ m( v% y$: s. V1 B3 V9 ~9 V# U; S

" o) }' g; Y' c, |匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
. {  y7 x+ C# y5 i* v
7 e+ e; s& ]/ @5 W/ gprint(re.search('}$', '{block}'))  
: j. f6 M" n& U) V5 q
' V( U$ o9 K6 t  E+ lprint(re.search('}$', '{block} '))) e/ Q. B2 {/ A' K) o

" F$ u5 K8 ?0 _- |5 }( w8 cprint(re.search('}$', '{block}\n'))  
, m0 X0 G2 b; o# w7 S7 B/ f  r2 E1# E3 h5 N4 _# d2 r5 \$ F
2
1 j& i! P/ P, {( }3
7 [$ m$ S! R" I( ^: l4
# I3 Y9 e# j! B1 m( V5
5 `1 R" W) z& a$ y4 k结果如图:
4 i: i; ^. z* q' X$ y0 w2 D$ J8 |
. o% r! z- u$ B, I, q" e
; K/ v7 J/ s7 {5 y! n! _* p+ c! M
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。0 h, I4 j8 K# a' K  X
$ O/ H, k. q# p! [! w) p
\A6 ^& v( V9 \4 A: V+ {; \, J

2 n" a& i- K( X( E只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
7 F2 O  Y4 k* S9 k1 {$ y6 ^' U! C# y# j# X8 L5 N! C# y
\b
3 h# T2 w1 w. T0 r+ q: v2 I& f# l4 e; c+ }5 k; C
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
# N0 H% U5 E0 R' o2 t+ a
6 k; Y3 Z/ t2 F5 j零宽断言相关信息请点击零宽断言查看。
1 Q/ x. T- e) Y
+ \  \0 F9 d4 ^; x* s下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
$ `  f' N/ O7 |% V, s, n1 q+ V2 P2 |: r7 d" U6 y
p = re.compile(r'\bclass\b')0 u- P5 s0 g5 v3 Q$ C3 Q
print(p.search('no class at all'))  7 [" b0 s, }( V
1 x5 {  F! m$ T! H3 q
print(p.search('the declassified algorithm'))3 @5 N) d5 s7 x6 a' K* y
5 U5 O( w; q' S; X
print(p.search('one subclass is'))
7 j# J. W4 x: |- S6 G8 ?/ i# P8 S5 n1/ J4 b! w/ @6 R; m, @4 y9 y
2
7 l) x4 v5 j6 v% s, ]' [3: e, n# c/ A% B  f7 N0 M. \% m
41 ^$ o, L& R2 n" K: x; U: [0 [2 L
5
/ |) L$ z; o& X1 j* n$ Y; F6
/ l* q- W. v7 n! |+ k0 C结果如图:
( i3 @1 ^. \8 H3 A, L/ q8 A3 z: S- \1 E
在使用这些特殊的序列的时候,有两点是需要注意的:7 q! S' Q" e8 I- v! r- e

: [2 ?+ X' ^* v" Y, D: P5 @第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。0 v& D. V% C. R0 j
相关原理和解决方法点击详情查看。
: z4 d, L0 @. N* }/ p) @$ z7 \3 y& x. e6 {) q
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。! [5 R( I6 f# Q) ?% T

+ B% k" o+ S1 X\B
/ A9 i& B% e$ D1 L* t, n
. X: Q  A$ ]" X/ H+ k# ?  f, s另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
" G9 e3 Y( J* D$ h8 ~1 K2 @6 z1 R
* w  ~9 M1 a5 R4 Y* d- f. p& _5 y3. 正则表达式实例
# r6 [" q: d/ L* B% H: F# `0 ^7 Q  Q: I
+ C" v, v8 S2 T4 v
经典正则表达式实例1 A( s' j. Q# G- q/ |

  N6 I# V" d: B# e: `: J( d匹配IP地址的正则表达式' v$ O4 q; G5 x2 V& M

1 t$ s, |+ ]2 R8 |+ F3 RIP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
9 H9 |" e5 Y. F- C5 w: {) k6 |" a6 ^" i8 |
精确写法, [/ E% E. G4 O3 ?

5 w0 H# X" {, y: G8 @3 K0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
. ~9 N! w$ j6 v7 e3 p9 E* z(([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])
; G0 j' l$ b3 D6 ^* @, I原文链接:https://blog.csdn.net/qq_44867435/article/details/1051041772 c1 R9 v) T( v5 z' l: ]

; `5 Z$ d; Q7 c1 |2 e$ U, N) T5 E0 N9 F& L8 ?7 s4 B0 ?3 o





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