- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565361 点
- 威望
- 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年大象老师国赛优 |
4 V7 L" r/ q, {, x# VPython爬虫 正则表达式应用详解
& F8 ]. K( u3 T! [
1 o- Y& t" @1 M4 M6 [学习Python爬虫过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。
: J8 @) r+ S2 |/ f+ l& K) P% K5 M ~: X
—— 正则表达式应用详解 ——3 j; F3 Y) l+ J @0 E
; N* _3 k/ o: n) z. _
文章目录
" s+ q! a9 e" l* E3 x, ]! E) w/ j& n. O0 E
Python爬虫(二十一)
! S6 \, F: b* h$ e6 j—— 正则表达式应用详解 ——/ M" W* Q L5 H
1. 简介/ x+ y- k0 b% E/ R
2. 语法
6 M [& |' N8 ~; Y! B/ A5 `) z3. 部分元字符应用详解
- c) q- F6 o+ V/ v1 ]5 {! N& n2 x^. ^5 \" O; e9 z! i* V/ B2 n& Z! |
$; ^ y' Y. e) s! D
\A4 e! P+ ]# E8 Y0 C8 |( i' t
\b# y, m" \ @3 o, q4 m' ` E% n
\B
0 U' `; k7 {& w7 {3. 正则表达式实例. p E# O/ x" \, m5 _# h7 p
相关文章:
6 _% W" m. y& d1.Python的Re库应用详解(正则表达式的库)
% I$ m6 Z6 @/ f2.Python的Re库与正则表达式的细节解析(正则表达式的库)
6 j( s+ M( H" z3 i7 U, K# f% B& Q5 I: _: K1 s, X) o
1. 简介
% V9 n) D7 T9 B# q9 p) O9 O* f* U( D' w. T7 S: T/ ?
正则表达式:regular expression,也称regex,简称 RE
6 ^8 h* s9 K& [
& c2 B" L: M& G0 L8 W+ Y* {正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。
: D8 n0 N+ S* e# G; m
1 f( ~+ ] r# F+ l2 |! b3 t- Y正则表达式是用来简洁表达一组字符串的表达式
. a, F5 s+ ?1 A& ^. @
+ p- F0 h2 U+ e# K7 j9 W( s通用的字符串表达框架& Q, e8 X6 A7 ^: A. y/ A: s5 n
) h& r% c5 W% ~简洁表达一组字符串的表达式
" G& S6 |( T' c5 ^2 X% X7 I( l" g1 _9 Q
针对字符串表达“简洁”和“特征”思想的工具0 e+ I" j0 I3 D! ?! G
2 V/ S! k7 ]5 f. Y判断某字符串的特征归属
1 s U5 j% D0 J0 M/ C: T. q& p; l
' R# n2 A6 a+ Z6 I/ i$ i% o/ \正则表达式在文本处理中十分常用' a" H4 s/ W! S
2 d9 ^+ d+ y- Y& F( Y表达文本类型的特征(病毒、入侵等)
1 \- X& l5 Q8 X3 W- L$ {" c$ v9 [# y2 p9 s0 m2 {
同时查找或替换一组字符串( e* q$ H* e2 W* K$ o4 l
3 A9 g+ ^* K' w! D" c/ v$ q* g
匹配字符串的全部或部分
2 H6 Y- X* y# [6 R3 ]# _- H7 c+ L+ `7 |: s7 g
正则表达式的使用) m) y+ A) k9 n: ~# i+ A* B
0 _4 Y7 F4 m) m; K
编译:将符合正则表达式语法的字符串转换成正则式表达特征
7 V6 L- G+ a0 {' B
1 X \) s/ }( }+ c![]()
% p/ s2 M; I2 {2. 语法7 u- U8 S% j: X! e \" I
3 L4 Y6 H \1 n# z" [正则表达式语法由字符和操作符构成8 \% ?4 y Q+ ?2 N
0 I: ?, k2 R4 k% V+ I/ k1 `6 {/ I; V有一些符号不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等功能,被称为元字符 (metacharacter)。! t2 I" T- K- H8 n' q# n9 o" k7 a9 G% w
元字符包括:. ^ $ * + ? { } [ ] \ | ( )+ A3 Z- x8 {2 e3 a) m: ~
正则表达式的常用操作符
' Y7 j8 {) ]5 g0 C' A U在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”也不会被触发1 `6 F6 c* C0 t- q2 h* @
操作符 说明 实例
6 d* l( Z) O* ^& C/ [: N) a. 表示任何单个字符(除换行符) 【注1】
& B; o! q5 m4 u$ Z; |[ ] 字符集,对单个字符给出取值范围,元字符在方括号中不会触发功能 [abc$]表示a、b、c、$,[a--z]表示a到z单个字符6 b9 E% ^2 g# x
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符' R* C: u A; I" {' y5 H& W
* 前一个字符0次或无限次扩展 【注2】 abc* 表示 ab、abc、abcc、abccc等 i2 Y6 V' |- h q8 k0 w5 W a$ H
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc、abccc等' W% q% k I5 w
? 前一个字符0次或1次扩展 abc?表示 ab、abc
# M6 q1 ]/ k& J' q| 左右表达式任意一个 【注3】 |abc|def 表示 abc、def. M+ t! _* w2 c! A
{m} 扩展前一个字符m次 ab{2}c 表示 abbc
# T2 L3 _3 |/ \* n{m,n} 扩展前一个字符m至n次(含n) 【注4】 ab{1,2}c 表示 abc、abbc
5 S% W4 D$ i) U; K+ M; a7 U^ 匹配字符串开头 ^abc 表示abc且在一个字符串的开头
( i2 D/ Z; t$ Q# |$ 匹配字符串结尾 abc$ 表示abc且在一个字符串的结尾" ~9 q5 F5 a9 o1 z
( ) 分组标记,内部只能使用 | 操作符 (abc) 表示abc,(abc|def) 表示 abc、def
/ p R& V+ |5 u. d6 g\ 后边跟元字符去除特殊功能,跟普通字符实现特殊功能,如需消除反斜杠的特殊功能只需在前面再加一个反斜杠\\ \d \w \u1 Y9 |. d: }, t
\d 匹配十进制数字,等价于[0--9]
( F6 ]9 e6 ]5 U4 o\D 与 \d 相反,匹配非十进制数字的字符,相当于 [^0-9] 0 Q3 }/ Y% a. r6 W6 w0 X
\s 匹配空白字符(包含空格、换行符、制表符等),等价于 [ \t\n\r\f\v]
; a1 C0 r7 D- L, T! P4 N _" Z\S 与 \s 相反,匹配非空白字符,等价于 [^ \t\n\r\f\v] + H' y4 _7 t2 X$ }; ~
\w 单词字符 【注5】 ,等价于[A--Z,a--z,0--9] * p$ S, | S6 L7 h
\W 于 \w 相反
' b7 g% g: A9 P5 h# m\b 匹配单词的开始或结束
; ^( ]7 b1 ?( o+ ~2 K\B 与 \b 相反
7 T0 s. S r' t% b7 Y6 V( N, W\Z 只匹配字符串的结束位置。
& P, v% `/ e; b1 q4 l6 C! _【注1】:如果设置了 re.DOTALL 标志,. 将匹配包括换行符在内的任何字符。; V, A( Q: \& n, H8 E1 |* \/ Z
8 |( ]$ A1 m7 x
【注2】:由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符重复个数不超过 20 亿个;- Y+ L+ E& F; g7 M2 U# T# a
# @: ] J* T8 P. r, Y+ z; U【注3】:为了能够更加合理的工作,| 的优先级非常低。例如 banana|orange 应该匹配banana 或 orange,而不是匹配 banan,然后一个 ‘a’ 或 ‘o’。同样,我们使用 \| 来匹配 |字符本身;或者包含在一个字符类中,像这样 [|]。
0 P2 }5 |9 @0 N( V% t' E- Y: N' L& R* o2 A1 d
【注4】:可以省略 m 或者 n,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。# m F9 Y! r( N
- L6 A. O& ?% I4 R. T2 i
【注5】:\w 匹配任何字符。如果正则表达式以字节的形式表示,这相当于字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。# C% a" o2 g2 u8 A, Z
+ n8 e( j" I- M3 A1 {% f* I3. 部分元字符应用详解4 X! b. j8 s) r% `9 m* ~ p6 m: u5 k
& z+ a7 O8 D# v Z
^
: e( s& G) M( r( m& m' w$ i; y% e6 I& {
匹配字符串的起始位置。如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。在 MULTILINE 中,每当遇到换行符就会立刻进行匹配。& l/ X: s$ H" H: A
Q! P4 {4 P' f, ]0 z( e# s4 O
举个例子,如果你只希望匹配位于字符串开头的单词 From,那么你的正则表达式可以写为 ^From:
" O4 `; c7 \: B+ C, Y' h* F4 x
' l* J/ `) [' m" q @print(re.search('^From', 'From Here to Eternity')) - J! J' D& j& r1 |
print(re.search('^From', 'Reciting From Memory')): r5 @" K; @6 {: p
1* v1 j2 N3 s% m$ ^; ^
22 c! w j0 W7 B* t- o* G
结果如图:+ e6 S8 ^6 Y( R* J: w) ?
' Z* _' s. P5 H: w' Y' P; u
5 B1 Z1 W! y% S- g, g! \ }; q
$
% J T9 v* E& s
4 c; o! I# P% r6 X1 N; c/ b5 K匹配字符串的结束位置,每当遇到换行符也会离开进行匹配。
' B, C4 f. Y5 B1 R3 `$ [
4 }) v& ^* M0 q$ R( r% L i( jprint(re.search('}$', '{block}'))
& s# q. K! D3 y* M5 N- ?4 x
: d8 x( z, L$ O- jprint(re.search('}$', '{block} '))
4 F" i3 |( e: G% o$ C% e
1 C$ K# j6 Q8 \print(re.search('}$', '{block}\n'))
8 t- S% }1 ]& N1
! u9 h6 Q4 q& B* J7 _28 E( M' a# N- E, @- V6 C% r
3$ M+ z/ ?. n3 y; @1 D# |
42 M( U" s' x8 d
51 ^; U2 \0 S# w
结果如图:
6 U/ @# D( g1 _
, w9 f+ N% G& `' f5 A$ H- b* T 1 U6 ?6 G5 W/ Z& O: i
" J0 v1 d$ }( I; \
同样,我们使用 $ 来匹配 $字符本身;或者包含在一个字符类中,像这样 [$]。
% s( \/ c2 Y7 v$ f5 G6 R* F( `) N- V7 D# v9 K, v9 ~
\A% v2 D+ G/ q& N7 O
2 X8 I) B9 G: U& K# ?/ K; c
只匹配字符串的起始位置。如果没有设置 MULTILINE 标志的时候,\A 和 ^ 的功能是一样的;但如果设置了 MULTILINE 标志,则会有一些不同:\A 还是匹配字符串的起始位置,但 ^ 会对字符串中的每一行都进行匹配。
4 ]3 B" Y; t9 e9 d1 c4 G W. N
+ f0 X$ l2 H# f" U. Q6 _\b
, Y/ O6 b4 T/ ^& L( _
. }; {5 z! ?. E7 B1 U: z* ?单词边界,这是一个只匹配单词的开始和结尾的零宽断言。“单词”定义为一个字母数字的序列,所以单词的结束指的是空格或者非字母数字的字符。, B5 k( Z; y S3 n& D
# B. X y: T, I7 a' S零宽断言相关信息请点击零宽断言查看。7 K% h) v7 p, }8 g6 o
3 C! z9 {2 o0 W" o1 s5 t8 b
下边例子中,class 只有在出现一个完整的单词 class 时才匹配;如果出现在别的单词中,并不会匹配。
6 _0 _, P% W9 f; \4 {2 n& ?) j% X3 y
p = re.compile(r'\bclass\b')
% h# k% i/ V. j# g pprint(p.search('no class at all'))
8 l, V8 m( {' g" P; ], ?1 T, g, U8 x& ~$ y' o0 `- @0 c% Q. O
print(p.search('the declassified algorithm'))0 n) V. }2 ?) p, d i8 s2 |
( e+ b2 x: ^, U$ ]
print(p.search('one subclass is'))& V9 t* A9 ?" `
1+ F7 e3 m5 `$ \. \
2& A9 I# A, m( e1 R. ]
32 {& T! s/ [. S5 p1 V9 ^1 }- \6 M
4
& o8 ]. ?" ], I* q) @2 T' ? y. \5
! U% Z# r/ J6 ?! w9 y9 d8 Y+ {6! q) N" B) J3 }. s: C& N0 p3 h
结果如图:" s' e, F7 ^$ C( W. z: s5 m- h
( h" E& ?# i0 ^9 T在使用这些特殊的序列的时候,有两点是需要注意的:
, P6 _& y; p$ c4 @1 L
1 K; y+ Y, s/ C: u5 f6 [第一点是,Python 的字符串跟正则表达式在有些字符上是有冲突的。比如说在 Python 中,\b 表示的是退格符(ASCII 码值是 8)。所以,你如果不使用原始字符串,Python 会将 \b 转换成退格符处理,这样就肯定跟你的预期不一样了。
0 s5 n0 ~$ R0 S相关原理和解决方法点击详情查看。
% e' w+ c4 [1 A
/ |1 ~) _# o. x% r% d' U1 k. S9 u第二点需要注意的是,在字符类中不能使用这个断言。跟 Python 一样,在字符类中,\b 只是用来表示退格符。
6 i, \5 N3 z/ w& P. c$ g& }) B/ q: f; J; ~ @ z, K
\B) x" A: X: f a6 W$ v+ e
6 u: ]( M5 @& I# g* K$ Z9 m7 ~另一个零宽断言,与 \b 的含义相反,\B 表示非单词边界的位置。
: L, ~% C; K0 m- o4 @; D
+ v, e/ Y; T* N$ ?% r% ]$ C: n3. 正则表达式实例2 [8 x# u/ |% I' A( E J
![]()
' [% k; g+ w$ k4 a7 {( O' N* g* Z! E% {* s* |9 Y
经典正则表达式实例9 S7 D3 w9 g/ | }% o0 K$ O
![]()
) p! d# b& |' G8 S6 E% G匹配IP地址的正则表达式8 X( }* a0 Y# q( y4 Z1 U4 n/ O
5 |) |1 |& }' f2 `/ [% bIP地址字符串形式的正则表达式(IP地址分分4段,每段0-255) \d+.\d+.\d+.\d+ \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 不精确& w( u$ u }* Z: {4 ^; ?0 G, S
% c& ^8 O! _) e8 ~% m精确写法+ G6 H( t8 i9 ?( }/ P
' U' E0 o0 }# [# C
0--99: [1--9]?\d 100--199: 1\d{2} 200--249: 2[0--4]\d 250--255: 25[0--5]$ V! M3 y+ @4 U, {& S( H9 E
(([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])- Y1 P" _; r! c1 ]3 L% L8 ]" d6 k
原文链接:https://blog.csdn.net/qq_44867435/article/details/105104177
4 `# u6 d; ^& A W% n* b5 @$ a* m; i+ s- p1 E
* r" G" L- Z0 @: y q8 m |
zan
|