在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 564568 点 威望 12 点 阅读权限 255 积分 174593 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
) h! w. b' G* n2 J* p1 ]1 E' d Python爬虫 正则表达式应用详解
4 ` P6 z2 K: n4 v/ H5 { 1 L8 Q, A2 f, P: T
学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
. L% ?! d2 Z" C9 C 4 Z& u4 A, I! a/ L. Z
—— 正则表达式应用详解 ——
: Z) T" c' m7 q! r, o9 w1 d4 ~ 4 f' V4 r% k) y1 E
文章目录4 p2 ^4 K2 b5 S3 R3 a
7 E2 ?: F( s; W2 ]
Python爬虫(二十一)* T) Y \; _$ K9 o" _# A
—— 正则表达式应用详解 ——
% z" ~$ r. u+ u$ T# a f) v$ a) x 1. 简介+ F& ~& e) m- p w
2. 语法
0 U8 g/ z" ^$ F+ [& I9 l' { 3. 部分元字符应用详解
% k1 p9 n/ W" u. \+ J0 m2 M ^
: w9 H- f/ \- b3 I- x+ T$ ~- f* ` $
$ z7 m% c! _. @- i* p \A- I9 a, L' M8 w* s% L& y& C i
\b- v7 I9 }3 O/ T8 |
\B6 A, B) S- ^ l# g) a% s8 s1 R
3. 正则表达式实例
5 Z0 n) ]# y& Y+ r& Y 相关文章:) G! ?7 a' L" o* y. s% F; i) D6 S% ?
1.Python的Re库应用详解(正则表达式的库)
3 p5 ?1 m6 O8 f) K) p7 t/ h- J* ^ 2.Python的Re库与正则表达式的细节解析(正则表达式的库)% ?& N& p2 w& k/ K+ \- }: [
( b8 p! O( M2 j( M( Y* j4 t# j 1. 简介9 F* _. I7 e: O) D
! S# l6 l4 S% n! S( u; u. ~; x& M
正则表达式:regular expression,也称regex,简称 RE y( k9 l4 j" F; s
7 d8 O$ `" V; g8 m% M+ X9 |4 K 正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。; [# W b, G5 x. W; l. L) @
% i! w4 A1 c+ o: I! D8 k 正则表达式是用来简洁表达一组字符串的表达式
% w; S" U9 k# b : c1 u5 @4 l' F! S: b0 D
通用的字符串表达框架 o6 j$ o7 l) k% [* y. I
' ~. I- e }' K1 g3 `% ^) f+ l8 P 简洁表达一组字符串的表达式
# [8 _1 F; w+ H% N5 t- Z3 W: k& v
: x0 |$ b3 E [1 J) ` 针对字符串表达“简洁”和“特征”思想的工具) g) R" W0 x, i3 M$ ~5 {
" v# y0 W7 ^7 p0 |5 {) V. Y4 P
判断某字符串的特征归属0 h. S% a0 N0 I. K/ n" x
; g N& O$ B/ x W/ k 正则表达式在文本处理中十分常用
1 Y" g% s6 S7 f; k/ D3 C0 x
6 D. Z. p. h5 J 表达文本类型的特征(病毒、入侵等)1 h" x3 `4 p% |7 ]8 k+ U
: W, L8 o* j) b' N! k, Z
同时查找或替换一组字符串& d3 f7 T* ^; O& n! A
, y$ I! G1 E1 w4 G9 m5 a4 v 匹配字符串的全部或部分
4 t/ e) h9 Y- Q1 q& E6 u; _3 |
X4 G* q2 z# @* K/ L 正则表达式的使用" w Z2 ^ `' X& v& X+ L
/ j2 `' H0 A Z4 o& O
编译:将符合正则表达式语法的字符串转换成正则式表达特征
1 z5 Y/ V z1 H8 F
5 b- Z, L4 o- Z' T! c* h; B
) v' t3 r. B5 |3 L3 H 2. 语法
" k* S1 w& {8 ]2 P
' n( z$ P$ S8 [ 正则表达式语法由字符和操作符构成+ Z* u. E) E- V) A5 C
8 ]. p4 ~4 D$ ^0 W
有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。' x. R% R# B, t
元字符包括:. ^ $ * + ? { } [ ] \ | ( )% u1 N# \6 E$ @& }" L8 h( V
正则表达式的常用操作符4 m/ |" A" c& ?1 x# f# k* G2 s
在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发% J' N& n5 }+ y* G; v( { ]8 `
操作符 说明 实例: ^% g; Z% A2 Y, w9 l' C$ I
. 表示任何单个字符(除换行符) 【注1】 5 G2 Z( W1 a( _" D' z
[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符
+ N6 P5 Y( ~6 ?7 y' [; p [^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
, t: }+ p1 z/ f% h* L. @ * 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等
; u' s' A% ^& t& h + 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等
5 ]) ]: s0 Q) n) _: _% _; ]& o/ k ? 前一个字符0次或1次扩展 abc?表示 ab、abc
. X, i C7 x" z) X) E4 E# Z$ z | 左右表达式任意一个 【注3】 |abc|def 表示 abc、def0 W; c5 c$ O# ?3 E: |
{m} 扩展前一个字符m次 ab{2}c 表示 abbc0 z0 M; k9 t3 t9 U7 Y# Y
{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc \) x* v; z; K" o ~3 O+ ?
^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
5 O' H0 }% r0 J& H $ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾) `0 H3 S0 |5 `, x+ O% I# @- ?. i
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
; }$ t0 {0 Z+ D) p \ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u: l% _$ [) E. c$ \+ E4 y$ `( E
\d 匹配十进制数字,等价于[0--9] ; v4 F J+ w+ {5 X
\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] . V g. b8 R/ ~. a" |) t+ ]; [
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
g# A( U% u, {0 u8 T3 E& F \S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v] `2 t0 o# O' \" I
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9]
! R1 L3 b4 G$ O \W 于 \w 相反
" F/ b5 j( P$ Z3 c* F( n/ g& | \b 匹配单词的开始或结束 / }2 g& G& u5 G. a: L' o
\B 与 \b 相反 ; f# N C/ h3 N$ l- t
\Z 只匹配字符串的结束位置。 ( C, {' Z! f; v0 f
【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。
3 g, }/ z! d ]" G* u% B5 j2 R# [
2 j* p5 M' G9 k4 c6 ] d& I 【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;
2 W; M2 }* N" Q- r
# r+ {8 [5 {! A. ` 【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。+ H! A& }) H4 P& ~0 y' O
* P6 R4 i* v6 i; l- h# ~
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。" D V! U( s& p3 k$ A3 G2 w
) R7 w7 y" D5 v1 M3 M7 U
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
+ v, a# Z- V2 }/ n& b4 K/ Y
: G! b( E6 z/ _, G! s3 G 3. 部分元字符应用详解, J( U x- ^" W3 E9 Z
1 A" ^" n6 j! \+ s" D
^
$ }5 i) ` d) }# I# d5 k2 g* l3 |
7 d" O) j9 \1 C( ] 匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。" Q' G& ^5 @, ]3 P0 |+ h
* m% ?' V0 x3 E' r4 | 举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:8 |, w% U+ R- W) l' V# r! P
, F) D, I. x( M/ P& k
print(re.search('^From', 'From Here to Eternity'))
/ ]+ }" n# D+ D) ` print(re.search('^From', 'Reciting From Memory'))& `. M$ ^, W9 `0 k! A
1% A9 o( J3 K, M$ u8 S
2 Q E- j+ \1 y9 T
结果如图:9 ]- e- K$ c: I- q7 c2 e
' V! w2 m! \* X5 s2 h% k5 Y ' l) S) l, f4 J8 U
$) C3 W* u% Y2 F+ W/ d
6 y/ U6 |9 N2 T
匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
6 G& X' j2 e9 B% ^" _1 h
# {4 U% O* {. L' x# y. C* O print(re.search('}$', '{block}')) 0 E6 ~! B. v) |" P K' o! I( s) k n
$ ]8 {9 C1 E4 ?* z* d" x0 Q
print(re.search('}$', '{block} ')). B$ O) ^% B q5 v& @
$ l) P: x2 n2 ?& v4 \$ { print(re.search('}$', '{block}\n')) # w8 F0 _* H" @ L P% [5 c- Y
1: l) `" i% d5 n% p E
2
- u/ t9 u9 k# c8 Q7 r e: E. M 3
3 J B9 b- J, l 4& m0 X- G; B$ q( l( t' @7 W3 R4 ?
5% q$ `2 D9 U: V/ e7 d1 N- \+ W* p; |
结果如图:9 b5 @7 N) x- a$ n% s, k' i
3 {2 z+ q- ^# `
3 }2 a1 H( J6 }- h" J
; |: x' y3 ?8 _ U3 |+ W t% g6 |6 A" F
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。0 I; ?0 C- a/ b
+ q2 \6 u6 _+ g% z; b- x \A
+ R p. p" p. E( ]2 f* Z 8 z. I+ h8 u2 S$ p1 w
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
7 I5 l3 Z3 b, N- S
6 V$ l# q. b( a+ W6 W) B5 g- r( b \b
4 N+ v# I, k6 X 1 u1 l _1 i" L8 n1 ]2 {
单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。
" L e) C. _/ ^( f, G & _' D$ {! X+ S" `: U, w; m
零宽断言相关信息请点击零宽断言查看。
# L# \5 E- ?! @, a0 E
2 S) h0 E) p4 n3 w3 V' P 下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
. U9 I* [! ~! i) |2 } 8 D T; }7 W. i; s4 N
p = re.compile(r'\bclass\b')
* i, u7 s$ C: S2 ?" ?' _ print(p.search('no class at all'))
( ]9 Q( R3 g% e- H6 T, n5 W* ^ ( g9 e) y3 E; Z* R! |( r
print(p.search('the declassified algorithm'))
" ~4 B4 s1 n) v' r0 n0 a
1 o p4 g5 u* Y# X print(p.search('one subclass is'))5 H% {0 j6 x. @& F3 P9 A
11 b+ U$ u2 w$ L0 J
2
4 y1 ~0 \) f! N 3
$ |3 M, O8 p. W 4( A/ U( a7 s* q0 x( s+ a
5# Z+ B3 A+ x4 z& v; y0 c' V
6
3 s4 Y3 K$ p. o! F W \( U 结果如图:8 p$ @2 a3 ~- ]- t p F
* i7 O) B: u9 @! k
在使用这些特殊的序列的时候,有两点是需要注意的:
( Y: ~/ O) L3 w & O! x9 q# E8 e) z& }) @+ f$ Y
第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。# r, b) @9 j) W
相关原理和解决方法点击详情查看。- ^ I; h% c; w6 O; I
& P9 I% W) F; H/ f
第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
" D* t% H: B' i# v * y) o- }/ g/ X( F
\B
* {$ T0 _1 p7 |3 S 1 h( B* u1 O- O9 } b. Y
另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
: U, \) b, N$ \ L, ? 8 b. h/ _) ~& o* ~) t" V' w" W" n
3. 正则表达式实例: S7 R1 _5 I. q; s0 G7 h% _
8 Y% L/ y, ]4 L
: ?# s, z% y" W3 ^- V 经典正则表达式实例
n( Y6 o9 A& ]( i& Z! ^% i & D' b7 a- V+ p: ~
匹配IP地址的正则表达式
' {! `4 s$ w7 d i' w5 u7 K8 F 3 `4 I* X6 ] Q" c
IP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确9 L; k7 F$ R' }& T) v+ V( v
( E/ s9 D0 T' K: U0 M3 y% ?- n
精确写法
/ s4 z. ?" {- k( A3 Y
, M% O3 M6 [0 S: |1 w, Y 0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]" M* E1 G/ h! X' ]
(([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])
8 @* R+ w6 }, G2 P. [/ d3 C5 j* ` 原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177( ?3 R5 U1 A( L, ~
. j6 b* b1 K+ P4 J; _
& s- c0 M0 S) N, N9 b @& e, ^
zan