在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 558716 点 威望 12 点 阅读权限 255 积分 172988 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 18 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
! S6 K: W( |! t# J6 h% u1 u i
Python爬虫 正则表达式应用详解 2 a: y1 X* x: N# N; x( m
9 ~: a" @7 Y. ^8 y 学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。( U- ^; w% E" g' A# R
& S6 @) ^" y- J) b/ D. i2 G
—— 正则表达式应用详解 ——5 v) a0 ]7 W1 `: d2 p$ S0 {
0 Z8 t1 u O3 |; Q* E" H' _( b
文章目录5 ]5 r8 ?% V4 S
$ v( p3 K: o; @% D8 M' A9 O( j6 x Python爬虫(二十一); B' @! v+ p) S5 S& _
—— 正则表达式应用详解 ——" Y: d4 Q; C5 K+ u/ `/ y- u
1. 简介( c- s/ [* \1 d+ r" R
2. 语法
4 Z& T: \' d$ S+ {( c0 g 3. 部分元字符应用详解# }" K- }7 r7 c! b$ U5 k! S3 Y/ H4 r
^7 Z3 u5 m8 b0 r
$
N& A% x8 h; n* Z# Z4 M6 h \A( F4 ^/ L# l- l+ H6 ~- Y5 ~8 w1 a5 J
\b. H3 I- m" [% {5 J9 ]
\B0 Y( R5 f% I. o. t8 K
3. 正则表达式实例& v% `% Q0 b5 X4 N( O2 W
相关文章:" V% v1 R8 Q9 w5 \6 o7 r- H
1.Python的Re库应用详解(正则表达式的库)
! f% c2 |; \! z. B+ c- O 2.Python的Re库与正则表达式的细节解析(正则表达式的库)7 O1 ~* S& r7 |/ k5 s
( ~4 _3 [# m8 M, d 1. 简介& J4 a% H7 ~ A) c: ?" M
$ W' L0 q, _* ?, e1 H 正则表达式:regular expression,也称regex,简称 RE
* Q4 E$ I% R: e2 X' b+ ` 7 n% k9 N7 y& r
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
) |9 y* r0 O: N5 `% U
& d4 m* c4 w8 |6 T 正则表达式是用来简洁表达一组字符串的表达式' P# J$ N: n3 I* I, H$ y8 G
* H' ~" }1 r8 `& _* t
通用的字符串表达框架% C% M0 X9 q/ g$ L; t6 |3 c
! G0 p5 Z- A5 Z; i0 H% ` 简洁表达一组字符串的表达式6 O9 j' x5 l3 B4 @. ?0 D
8 ? k1 O6 O! j4 V' _3 t7 a6 I# W+ E 针对字符串表达“简洁”和“特征”思想的工具% [/ J, d# P" a; U+ H
9 V( I+ b; F* a& Z. b; x1 Y 判断某字符串的特征归属
- g# f7 ?7 D4 J; c% K2 A# m V W; |* n 9 ]' |! u2 q$ H* O
正则表达式在文本处理中十分常用* b7 T8 o( t" E" l# d
% q5 N! [ M1 R/ i$ v( |- o; P8 s 表达文本类型的特征(病毒、入侵等), N! B6 }' t3 ^4 `& i$ j
& f, C2 W6 d8 w4 j- }$ k
同时查找或替换一组字符串
. o$ Q) P/ S5 W7 f
& g1 u b# z# x- W9 q' j G, ^ } 匹配字符串的全部或部分
' P! R7 c& @7 B ( a% E4 ]% q+ }6 G, t2 ^8 D
正则表达式的使用
" ^4 T: z {; E5 A5 x ( A; r1 |5 f! X, p: L# `
编译:将符合正则表达式语法的字符串转换成正则式表达特征# |: |: m/ x' V* I8 C- {) X0 k
, ^' l* d2 E: @" n" t# t+ B/ [
7 p, W, ]8 ?6 S; K' p& j
2. 语法
: [' D; t- k/ x: `8 F4 G! I A* v: W) Z1 {. O! k
正则表达式语法由字符和操作符构成1 s( Y) Q) L D# B2 X: e
+ M8 v, B- @% D3 n: v+ P& \: w
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。" u2 ?$ M2 D& z6 V* u5 [4 o
元字符包括:. ^ $ * + ? { } [ ] \ | ( )5 t' ?' T5 w7 U% B+ O: K, p
正则表达式的常用操作符 j, i2 t1 W) [) V
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发5 s7 u5 @: Z) V5 z% u" P# l
操作符 说明 实例$ Q$ O' u' @% x6 D
. 表示任何单个字符(除换行符) 【注1】 7 W! \$ }( \9 C# B+ \4 m
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
$ p( o `! Y6 K/ w [^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
$ e) h" Y5 C1 m8 [ * 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
8 g0 b3 Q: `# ~ + 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
6 k1 u- m$ K* {4 k" _/ ~, O ? 前一个字符0次或1次扩展 abc?表示 ab、abc
# P" P( |' o$ y1 P% A | 左右表达式任意一个 【注3】 |abc|def 表示 abc、def
5 ^/ s; b! o4 F- }& Q {m} 扩展前一个字符m次 ab{2}c 表示 abbc
" W, [) X& X% a4 x0 c. v' I4 c {m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc; x3 d! r% L" n+ h! ^1 W% a1 T
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头0 j# j7 k2 {+ ]+ B$ M6 ]; ?
$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾" L9 o: {$ s+ p
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
! E* P& i# T# m' c \ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u: ]5 [7 V$ `' y- H
\d 匹配十进制数字,等价于[0--9] 2 e/ k. @8 a" K: A1 N: T
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] 2 J2 ?# B+ h. o" K/ i5 x$ c) O
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
4 f9 B, S5 A1 A7 r @* I: q \S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v] : o5 E4 n% {2 W( a+ K4 ]4 J
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] . t$ `/ r3 e) \$ j' Z0 F7 u. }
\W 于 \w 相反
! q w# |/ i1 N; O7 r0 z2 U# l: D' x \b 匹配单词的开始或结束
: i0 l8 l) n. k+ p4 R3 C \B 与 \b 相反 1 Z5 ~4 p( W; ?0 f- v% a
\Z 只匹配字符串的结束位置。 / D5 s' I7 T' m# J
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。+ Z8 T( V% F* C- ]; E- D4 Z1 j* R
3 u4 h0 [, Q5 C, U5 k 【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
9 a+ ^! @3 w2 W6 }2 l! P 3 L; h- u) o9 d2 l# S
【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。3 x- T3 z7 j7 i3 u! X
% x2 h- E: ?- H0 ]; f 【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
0 Z8 q1 ?7 F2 Y' n0 f
. a9 f; t' f3 Z/ B5 Z" Q 【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
2 q4 t3 Z7 I* g; J ; Q5 @* Y6 X( k/ P5 ~) s/ P: _
3. 部分元字符应用详解" t9 K( l/ v; h4 f6 w5 G9 }
8 D2 l s1 h4 V) h) e8 [ ^
* i2 [& @/ ^( L 4 D. h, f; s9 s& @" S& V
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。4 L6 ]6 B6 K$ ]4 H1 l9 T3 ^
; x9 }. t3 }) ]6 B& r, x+ ?7 i j+ D
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:+ e# j5 P& W* V! k2 D
! e4 l) [: K5 ]) w print(re.search('^From', 'From Here to Eternity'))
/ w8 |: l$ x4 u! C. ]8 I# k print(re.search('^From', 'Reciting From Memory'))
' J% E# f$ s; }$ M7 W" ] 1, `+ m7 i1 E; u+ y
2
4 n/ \% k2 T" y1 E. D 结果如图:+ \5 Q) X- X6 ^% U7 d r: k# a; {
. o. {; F) c9 s' {% L
% ], T3 e3 Q6 a! G6 g/ X" n
$/ b. h9 L& r! g4 W4 H! u1 @3 T
1 T) F0 b+ W. _/ O1 ~
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
1 J$ h. P- y* d5 i & O6 `8 d) Y6 r0 t& o1 ?
print(re.search('}$', '{block}')) , @1 k7 s( p2 {. d
' ` y' X( j3 h9 Q5 v# l. w* a) Z& s
print(re.search('}$', '{block} '))5 c. M9 ?- z9 y4 h1 q
- j: n8 f/ m' B# h( t) H. `
print(re.search('}$', '{block}\n'))
' O5 `: D0 A7 j3 a, u 1- L, @9 A7 C( v8 E8 x0 ? r$ f6 L5 v
2
) L- u% ]. a; g8 [! P- L 3, p( L0 H* \6 {7 t5 m& b5 @
4
1 [+ j5 ?' M7 g' r1 U6 |+ u 53 X7 X/ O9 h. y, O. b
结果如图:0 Z& r$ ^7 o' h
" M( m2 K' D4 Y( R3 B1 T; w" v& A
k4 V7 e7 ~3 G
w* n2 D1 s* Q* f 同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
) Z+ V+ d9 ~; e4 `7 k5 _- l . Y3 V9 Q2 f" m ^6 A: g5 }* v
\A
/ _: r! a/ y. U% P' _ 0 Y; H) Q; s& S
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
8 V2 s" j1 E c4 Y: K) x 8 Q M" B* [6 ~8 m- l$ X4 }
\b
5 Z$ V9 Z% z; A ' D5 _! \# v2 p9 T" m& D
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
) {1 u5 n8 L4 d; c$ Q- v+ m
( n$ O8 S( {5 u; ^0 j W8 W 零宽断言相关信息请点击零宽断言查看。
8 x$ R: V8 a5 A6 [' a* \
8 | m. ^% `5 Q' k 下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
* w: b( z& L' z; [. S; r3 W# r # j' @, i7 k- ]) u7 ?
p = re.compile(r'\bclass\b')
0 z) O2 A3 B4 w, }2 i, q1 } print(p.search('no class at all'))
8 C, w8 p* ]9 W
K$ @; w ]: `6 c. k1 F/ f% y print(p.search('the declassified algorithm'))! \: e) c3 d5 O7 E( _& y! V
( z2 L) l$ ~8 n, H4 M* s print(p.search('one subclass is'))! e3 q0 X3 F) i3 p3 p+ P8 I
1* j$ H! N3 S# e+ s0 h6 e" ^
2) W4 U+ H9 U0 U# y; X
3
x, q& _; A" g* r Q 4
8 y2 y3 x9 `, x; {6 {8 t# l 5
" R2 P4 O% r# Q 6( `+ R4 p9 l% L- U
结果如图:/ L3 m+ ]* m/ O; V/ Y
( ]6 b- ?; g" {5 N: K& z2 l
在使用这些特殊的序列的时候,有两点是需要注意的:2 D" U: S' u- M$ Q4 ?; I% Y
! K% R% Z: ~7 F! f" K0 k 第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。# k: {4 @* T! d: c( {
相关原理和解决方法点击详情查看。
, v( z6 T4 F; Z! S3 R& X ! {0 V3 e7 z) @, t# K& n
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
& ~; c2 ^: g, \ {9 U1 h
6 q% B5 a: u4 W2 l& {1 h \B
' d E8 S& @4 d
5 f9 H+ k& |/ d2 u" h 另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。0 C7 ]$ w u& V" O+ M
1 w+ Z) r. { F 3. 正则表达式实例: J" ?, o Y6 O& J" s
9 t: G, M/ K" V* D% d8 J
/ {2 E W5 a0 }5 Z& L 经典正则表达式实例4 t5 C) I f# N
6 c3 D8 k! c0 Q$ z+ c 匹配IP地址的正则表达式
4 N2 X4 w/ m3 C " ^9 G% z" ~! B& D
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确5 \2 L1 m; O7 J m) p. B
4 v+ k6 k, `+ m) M1 f5 ~ 精确写法. K1 u6 I- u, p3 _5 {) z& }
9 b# }( X$ X1 ~7 g$ V9 _6 i 0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]
% k% U6 g2 g7 a5 @9 k" y. m( T I2 v# c5 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])
4 X; {9 V6 J& h 原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
0 c+ v+ B! z. d; n& [3 s
: }7 L R' a- x4 }5 P# }% V 2 f$ t; g" {, U- a3 m& l8 r
zan