- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565362 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174831
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
6 f) [* M5 I. \8 H5 N2 C2 t
Python爬虫 正则表达式应用详解
$ Q" H. q6 o( ~' i2 O) j& y X8 w. t. |5 o7 b
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
9 I; }' Q$ x8 d: l* G5 s: L: ]! E( o0 D* W' [) R" K& C9 Z
—— 正则表达式应用详解 ——, ~' H f6 d2 Z
$ m. g" | q0 p. E/ m+ E
文章目录
' Y5 V. e' K/ E6 m- G1 O$ _ F. a" ]+ H3 c
Python爬虫(二十一)
# C; L: @0 ~5 l( e1 G—— 正则表达式应用详解 ——
1 G9 y, W* V- p3 O" s1. 简介
& Q3 z. k* I4 @2. 语法
! h) n( H3 A: M: G0 f) z" v) P3. 部分元字符应用详解4 u( m4 y1 {" h6 g
^% K5 e" O& F0 Z6 _5 r
$
( { o5 O# Y7 L/ _: N3 x\A) I; D' J% K0 {- J- {7 I7 Y
\b
$ T1 {. [, H( C9 G+ U8 _$ M\B9 e! u! C* t5 n; `% v
3. 正则表达式实例
2 @+ ` {& g+ j2 E. W" ]相关文章:/ _# [) y$ g( |% V% |) c
1.Python的Re库应用详解(正则表达式的库)" a; e, v/ s0 |1 |6 m' f' }
2.Python的Re库与正则表达式的细节解析(正则表达式的库)
* M( r+ O' u5 J) z7 J- x; G% q- [) |9 }8 P$ C2 l# q% t! H
1. 简介
3 ~% I7 {3 k* E/ n7 U! g1 c- e5 Q6 \- o' P* a6 D9 B1 |
正则表达式:regular expression,也称regex,简称 RE4 }/ i& ^- N7 b- v1 O+ L4 ?
" W7 j; g0 v8 ^0 I* R
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。8 v3 Q8 ]- F/ l1 O
- P! V F9 F$ a$ T
正则表达式是用来简洁表达一组字符串的表达式0 C: O2 n" K* u* x* q
9 E/ G# K( S, `) K( J+ Q7 B' x# n; |9 R, l
通用的字符串表达框架
' ~4 Y4 K5 e! O* @: j4 S9 ~8 A, o/ F" v. d: P& L* }# D
简洁表达一组字符串的表达式
% G% G/ ^8 H+ j9 l
, z+ C" r( ?" w1 d4 w E1 b( K针对字符串表达“简洁”和“特征”思想的工具
+ s; Q) n5 d( Q1 [- @+ M
' Y! X1 b! W: t6 F8 A% c3 B判断某字符串的特征归属& [$ m2 c+ ?$ N1 l' d
- I% K% U6 |: g& {4 |5 ~4 Q" \
正则表达式在文本处理中十分常用
- B: ~6 z5 s& a
( h$ f, M$ F9 O0 t* ~6 }7 O表达文本类型的特征(病毒、入侵等)
5 n" U; y/ m+ H4 T: R4 D7 Y
2 @5 E- k# X. v& T" D同时查找或替换一组字符串
( x( f9 R3 y$ y9 A% U w9 |1 v" f$ M, }/ v6 P0 ~( o
匹配字符串的全部或部分
9 c$ Z: W. t2 j: F! Y3 h" O" Y7 Q& W% O% K7 r
正则表达式的使用
* U3 }- P/ }' z. `3 u$ x, E# d7 x0 f* L0 {$ D F1 {5 v4 @4 e* ]' h
编译:将符合正则表达式语法的字符串转换成正则式表达特征
& M _" ?* Q) v C2 w- v
2 ~/ o' e& u/ Z3 V 8 I8 \1 Z" F& s$ A- _
2. 语法/ z' ?) y, _; P- C& W" N
* z9 W. [, x; g; [7 c5 d' h' u j
正则表达式语法由字符和操作符构成6 K' F- h* `/ x" Q3 d0 J
( w9 Q! N- i6 d$ S- w9 T
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。
' j; ~+ `: u& W& c7 a" z3 L! d元字符包括:. ^ $ * + ? { } [ ] \ | ( )* q# b) P9 j8 e" q# D
正则表达式的常用操作符# e$ O* R3 f) l0 D# q5 e6 F7 q
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发+ S% O1 h9 x4 @" ~
操作符 说明 实例9 R3 @' Z( Q2 y: A, e! s
. 表示任何单个字符(除换行符) 【注1】 6 o9 Y5 B4 l* ]" o
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符, z' ~) g7 x6 E
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
# c$ c$ `7 O+ S* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等8 M1 F) C3 f* D* }* w
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等* ?2 M- h I3 ]
? 前一个字符0次或1次扩展 abc?表示 ab、abc" o3 f1 ^3 \5 |
| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
- N7 B' C" D# L' p7 Z% E{m} 扩展前一个字符m次 ab{2}c 表示 abbc
& j& [; ?1 W `: i0 H: d{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
) [9 { ^- \. E9 [/ a B9 @2 ^^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头: A" Y. ]" U% O
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾0 e- N2 ~7 d S3 t9 E8 E
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
9 [* }4 f* d0 v6 V$ z) M: b% m2 s9 o\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u
' x C7 F& p& i% d+ \\d 匹配十进制数字,等价于[0--9]
# I, P8 f8 P0 d2 L\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] ! f: e3 i+ d' [6 J. }
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v] * d& f/ }' e6 o' `; m( R5 x
\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v]
+ k( \/ A# R" i, g% j' ` x\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
, m" b( J5 O+ E$ D: h; c\W 于 \w 相反
) G/ W* t3 D, T5 L, b h" W\b 匹配单词的开始或结束
' @8 F9 ?# ^+ W# X4 u; s' f7 l0 B\B 与 \b 相反 4 [0 ]# O6 A7 D6 [* J! E' M
\Z 只匹配字符串的结束位置。 + H( v0 X! ]- X j) L0 h0 B
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。' P' z0 j0 F8 V7 c3 ?" ] J. J
( A; j4 H8 s$ |3 o! c( D
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;: B' A! v0 e2 S! V6 ]0 U, @) c
8 d2 `0 R4 N' i【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。$ c" K5 C- o/ _
2 p# g: `1 ^0 [8 M$ j- S
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
! t6 K2 y2 X" Y+ C% F: b
! b, C0 W% [1 D. S% K" w【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
: t4 w# ]2 N$ j, \
3 j! t# B7 P1 p5 C* \( c/ \( K3. 部分元字符应用详解
3 D9 n& h% G: e4 Y. ~9 h4 Z2 r* W( }* g
^
3 A& c& W9 P: Y$ M- k, x9 ~1 B
! {9 _" E5 C' G! W匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。
- e4 e+ B9 V' C/ \* S A' F( \3 f+ U0 H, m- t
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
$ ~1 ?" ?$ d' [, l0 @: ]$ B9 G1 {& [0 o! M& ~: Y% R6 T
print(re.search('^From', 'From Here to Eternity')) 7 F& H: Q5 g3 }% `3 G
print(re.search('^From', 'Reciting From Memory'))
' o+ b% u( r- u p$ a% C14 a `! D/ d% m3 S. _
2. P" r8 l4 [9 i- ]5 Z, W! _7 p
结果如图:3 ?* T) N$ B1 u3 L- J1 q
![]()
( g3 O4 ?8 U. m
& [1 ~9 e% m$ P# n" s) j' K7 [$
- C& N( N, ]8 R2 S' E7 k6 m/ [4 s7 @8 k2 }
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。5 M2 T* y9 w9 a, [4 `/ n5 U- k
1 @% |. J6 G' g9 a2 M! O7 e6 y0 r# Y) {
print(re.search('}$', '{block}')) ) E5 d4 g1 e- G8 D$ y* T5 o
5 H0 ^& @7 x: d' L& I; T; t. ~: ?print(re.search('}$', '{block} '))7 c4 H% n- Q1 a
; I- {! ?6 A) P! B( oprint(re.search('}$', '{block}\n')) 1 a+ d/ J) f/ O1 C* [- p
1) Q$ O/ |2 ~$ C" ]3 ~
2
* `2 B% N1 F4 ^! \0 R9 V) ]! i39 a6 a' p. G; V; f7 J- A$ l5 [
4
: ]0 @$ i6 o( h4 H5# I: k3 [* O4 R9 C' q& I) W
结果如图:) a" {" b, s+ ~( g( h3 d
( }# `- T0 O3 k
# h- | H2 A6 ~5 }3 f) r- m
! P0 @2 e" a3 |7 P同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
! W& `# Z5 l! L! L4 b: Z" j1 P2 O6 W. |4 G& B3 \
\A
$ J' s( Z- P$ n+ p8 i: {9 b5 p4 V5 z& ~6 ]3 J1 f
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
) Y% A, b# E* z6 B# U W8 ]/ A
/ L$ f v7 p2 H- P2 q) i; ~\b
: j4 o" V& r' f$ l
4 f. o5 r# |4 J8 E3 l% f* h单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
% W. m3 e/ h( ` ]+ c- a
* P; F' a. F5 L零宽断言相关信息请点击零宽断言查看。
: C5 A; Z# T3 ]7 ?# W: ^- y' e6 [; d0 J" {* |) V3 T6 O8 P
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
4 s* n2 y$ R- S/ L* I/ F( f. b* Y+ {' ?$ @" |1 e; T
p = re.compile(r'\bclass\b')
7 q7 s$ j% M* w* Rprint(p.search('no class at all'))
7 D2 m9 k, O: R- G5 P5 h- U7 P- j- `/ [4 S9 S2 B
print(p.search('the declassified algorithm'))
8 k+ v; `4 I" h
1 e+ r. W9 D- l. ]/ f$ _print(p.search('one subclass is'))
# {& c2 |5 M$ `' w; u% q1
/ [9 }. F% ^0 n4 ~( _2
q6 _& i# S& @3
9 i E# c* i& H" ~ Q3 H6 K4
, v( ^! T8 ]2 E1 t. K; v/ ]5% |& M$ n# b- A: }+ M
6
# O V! \, R, {0 Z$ |+ v$ N结果如图:
# G7 U1 j/ B* A5 u: y2 O: i
5 S% z1 M' k) P: K8 _6 w在使用这些特殊的序列的时候,有两点是需要注意的:7 m9 x4 R8 ]. ~+ @6 F1 @3 ^
" n, k+ _$ F( e! W/ B$ f" ~第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
4 ^# {6 S- O. h" ^$ F/ ]* d" y9 h相关原理和解决方法点击详情查看。' w, e4 B& c/ R3 A$ l' ~( `; w
; w4 @, C2 I7 K! W7 V( c
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
7 X9 b7 {$ d# j! s E4 G- Z$ J6 A" d+ f1 O7 C1 C
\B9 z! k" a1 k7 b; O
; ^; }# |0 v0 }! g9 y2 t另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
- t7 h6 B4 z$ n4 z) a( K: A# c; ?: j
3. 正则表达式实例$ S2 Y( w5 Q* z0 q9 S+ G! }( c. G
![]()
6 v9 W% d# q% x6 D3 @: y/ w; W' A, S
经典正则表达式实例, B; l Y, V% n6 I* p/ }
![]()
$ v& ]/ q6 |2 F$ D匹配IP地址的正则表达式
! `2 {) Z! u: b/ Z) Y, P4 j; e, j+ Y
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确
( O. Z8 \; ? N9 ]
8 g N# e! E2 m- i' g精确写法
0 l) x# K S$ j5 [+ Y; G; Q& A( P. X4 a: b9 @" e$ o
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]' R, h" h" x/ T
(([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])- N( o2 G* |8 C! v( W: L
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177' y* Z& w7 o! |
( X; q. Y% n7 ?8 C1 S: q' g
4 b- g+ a# g7 L3 a9 ^& b' d, w
|
zan
|