拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 史上最全,万字吃透python正则匹配,让你在网络爬虫中自由翱翔

史上最全,万字吃透python正则匹配,让你在网络爬虫中自由翱翔

白鹭 - 2022-03-24 1934 0 0
我们已经可以使用 Requests 库对网站内容进行抓取了,对于一般的图片资料, 音频资料,视频资料等资料我们可以直接通过 Requests 库对其资源的 URL 进行直接请求,但是通常情况下这些资料的 URL 都是存在于 HTML 页面当中,如何从这些 HTML 页面中提取出我们想要的资料呢,这时候就需要使用一些工具了,这里我们先介绍第一种从网页中决议资料的方法, 使用正则表达式提取,
需要注意的是 , 正则表达式并不是 Python 的一部分,正则表达式是用于处理字符串的强大工 具,拥有自己独特的语法以及一个独立的处理弓擎,效率上可能不如 str 自带的方法,但功能十分强大,得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实作支持的语法数量不同;但不用担心,不被支持的语法通常是不常用的部分,如果巳经在其他语言里使用过正则表达式,只需要简单看一看就可以上手了,就个人而言, 主要用它来做一些复杂字符串分析,提取想要的信息,学习原则:够用就行,需要的时候在深入!

1 正则表达式

正则表达式就是用某种模式去匹配一类字符串的公式,主要用来描述字符串匹配的工具,一 句话正则表达式( Regular expression )是一组由字母和符号组成的特殊文本 , 它可以用来从文中找出满足你想要的格式的句子,
在正则表达式中,匹配是最常用的一个词语,它描述了正则表达式动作结果,给定一段文本 或字符串,使用正则表达式从文本或字符串中查找出符合正则表达式的字符串,有可能文本或字符存在不止一个部分满足给定的正则表达式,这时每一个这样的部分被称为一个匹配,

1.1 正则表达式可以做什么?

正则表达式在程序设计语言中存在着广泛的应用,特别是用来处理字符串,如匹配字符串、 查找字符串、替换字符串等,可以说,正则表达式是一段文本或一个公式,它是用来描述用某种模式去匹配一类字符串的公式,并且该公式具有一定的模式,正则表达式就是用某种模式去匹配一类字符串的公式,主要用来描述字符串匹配的工具,
? 验证字符串 ,即验证给定的字符串或子字符串是否符合指定特征,譬如验证是否是合法的 邮件地址、验证是否为合法的 HTTP 地址等
? 查找字符串 ,从给定的文本中查找符合指定特征的字符串,比查找回定字符串更加灵活方 便
? 替换字符串 ,即把给定的字符串中的符合指定特征的子字符串替换为其他字符串,比普通 的替换更强大
? 提取字符串 ,即从给定的字符串中提取符合指定特征的子字符串

1.2 正则表达式基础 * 元字符

学习正则表达式语法,主要就是学习元字符以及它们在正则表达式背景关系中的行为,元字符
包括:普通字符、标准字符、特殊字符、限定字符 ( 又叫量词 ) 、定位字符 ( 也叫边界字符 ) ,下面
分别介绍不同元字符的用法,
元字符是正则表达式最核心和基本的概念,我们必须要记住的是下面这些个元字符,下表是
相关元字符的写法和说明:
5.1: 常见元字符

5.2: 常用的反义代码

5.3: 常见空白元字符

笔记: 注意用来匹配退格字符的 [\b] 元字符是一个特例:它不在类元字符 \s 的覆写范围内,当然也就没有被排除在类元字符\S 的最盖范围外,一般很少用 ! 量词符用来设定某个模式出现的次数,属于必须要会的内容
5.4: 量词 ( 常用限定符 )

1.3 正则表达式 * 贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,以这个表达式为例:a.*b ,它将会匹配最长的以 a 开始,以 b 结束的字符串,如果用它来搜索 aabab 的话,它会匹配整个字符串 aabab ,这被称为贪婪匹配,
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符,前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号? ,这样 .*? 就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复,现在看看懒惰版的例子吧:
a.*?b 匹配最短的,以 a 开始,以 b 结束的字符串,如果把它应用于 aabab 的话,它会匹配 aab(第一到第三个字符)和 ab (第四到第五个字符),

5.5: 贪婪与懒惰

1.4 正则表达式 * 分支条件与分组

正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配, 具体方法是用 | 把不同的规则分隔开,听不明白?没关系,看例子:
0\d{2}-\d{8} 03-7| 这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号, 8 位本地号 ( 010-12345678) ,一种是 4 位区号, 7 位本地号 (0376-2233445)
分组是正则表达式的一项功能 , 我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式 ( 也叫做分组) ,然后你就可以指定这个子表达式的重复次数了 . 可以理解为被小括号包含的子表达式就是一 个分组, 当然也可以进行其他操作,
? 分组语法:
? (exp) :匹配 exp, 捕获 文本到自动命名的组里
? (?<name>exp) : 匹配 exp, 并捕获文本到名称为 name 的组里 , 也可以写成 (?’name’exp)
? (?:exp) : 匹配 exp, 不捕获匹配的文本
? (?#comment) : 这种型别的组不对正则表达式的处理产生任何影响,只是为了提供让人阅读注释

1.5 正则表达式 * 后项参考

使用小括号指定一个子表达式后,匹配这个子表达式的文本可以在表达式或其它程序中作进一步的处理,默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为 1 ,第二个为 2 ,以此类推,
后向参考用于重复搜索前面某个分组匹配的文本,例如,\1 代表分组 1 匹配的文本,难以理解?请看示例:\b(\w+)\b\s+\1\b 可以用来匹配重复的单词,像 go go, kitty kitty ,首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b) ,然后是 1 个或几个空白符(\s+) ,最后是前面匹配的那个单词 (\1)
你也可以自己指定子表达式的组名,要指定一个子表达式的组名,请使用这样的语法:
(?<Word>\w+)( 或者把尖括号换成 也行: (?’Word’\w+)) , 这样就把 \w+ 的组名指定为 Word 了,要反向参考这个分组捕获的内容,你可以使用\k<Word> , 所以上一个例子也可以写成这样: \b(?<Word>\w+)\b\s+\k<Word>\b,

1.6 正则表达式 * 零宽断言

零宽断言是正则表达式的一种方法,用于查找在某些内容 ( 但并不包括这些内容 ) 之前或者之后的东西,也就是说他们像\b ( 匹配一个单词边界,也就是单词和空格间的位置,正则表达式的匹配有两种概念,一种是匹配字符,一种是匹配位置,这里的\b 就是匹配位置,例如, " er\b " 可以匹配"never" 中的 "er" ,但不能匹配 "verb" 中的 "er") ?( 匹配输入字行首 ) $ ( 匹配输入字行尾 ) 那样用于指定一个位置,这个位置应该满足一定的条件 ( 即断言 ) ,因此它们也被称为零宽断言,断言用来宣告一个应该为真的事实,正则表达式中只有当断言为真时才会继续进行匹配,
? 位置指定:
? 零宽先行断言 (?=exp) :匹配文本中的某些位置 , 这些位置的后面能匹配给定的后缀 exp
比如\b\w+(?=ing\b) ,匹配以 ing 结尾的单词的前面部分 ( 除了 ing 以外的部分 )
如果在查找 I’m singing while you’re dancing. 时,它会匹配 sing danc
? 零宽后行断言 (?<=exp) :匹配某些位置 , 该位置的前面能给定的前缀匹配 exp
比如(?<=\bre)\w+\b 会匹配以 re 开头的单词的后半部分 ( 除了 re 以外的部分 )
例如在查找 reading a book 时,它匹配 ading,
? 零宽负向先行断言 (?!exp) : 匹配后面跟的不是 exp 的位置
\d{3}(?!\d) 匹配三位数字,而且这三位数字的后面不能是数字,
? 零宽负向后行断言 (?<!exp) : 匹配前面不是 exp 的位置
(?<![a-z])\d{7} 匹配前面不是小写字母的七位数字

2 Python 中的 Re 模块

使用 re 的步骤为:先将正则表达式的字符串形式编译为 Pattern 实体;然后使用 Pattern 实体处理文本并获得匹配结果(一个 Match 实体);最后使用 Match 实体获得信息,进行其他的操作,
re 模块中常用的方法及其说明如下,
? re 模块常用方法:
? compile 将正则表达式的字符串转化为 Pattern 匹配物件
? match 将输入的字符串从头开始对输入的正则表达式进行匹配,一直向后直至遇到无法
匹配的字符或到达字符串末尾,将立即回传 None ,否则获取匹配结果
? search 将输入的字符串整个扫描,对输入的正则表达式进行匹配,获取匹配结果,否则输 出 None
? spilt 按照能够匹配的字符串作为分隔符,将字符串分割后回传一个串列
? fifindall 搜索整个字符串,回传一个串列包含全部能匹配的子串
? fifinditer fifindall 方法作用类似,以迭代器的形式回传结果
? sub 使用指定内容替换字符串中匹配的每一个子串内容

2.1 re.compile 方法

re 模块中使用 compile 方法将正则表达式的字符串转化为 Pattern 匹配物件, compile 方法的语法格式如下,
re.I 忽略大小写
re.M 多行模式,改变“?”和“ $ ”的行为
re.S “ .”任意匹配模式,改变“.”的行为
re.L 使预定字符类 \w\W\b\B\s\S 取决与当前区域设定
re.U 使预定字符类 \w\W\b\B\s\S\d\D 取决于 unicode 定义的字符属性
re.X 详细模式,该模式下正则表达式可为多行,忽略空白字符并可加入注释
关于 re 模块的常量、函式、例外我们都讲解完毕,但是完全有必要再讲讲正则物件 Pattern ,在 re 模块的函式中有一个重要的函式 compile 函式,这个函式可以预编译回传一个正则物件,此正则物件拥有与 re 模块相同的函式 . 既然是一致的,那到底该用 re 模块还是正则物件 Pattern ? 其实 compile 函式与其他 re 函式 (search split sub 等等 ) 内部呼叫的是同一个函式,最侄训是呼叫正则物件的函式!也就是说下面两种代码写法底层实作其实是一致的:
笔记 re 函式 re.search(pattern, text)
正则物件函式 compile = re.compile(pattern) compile.search(text)
那还有必要使用 compile 函式得到正则物件再去呼叫 search 函式吗?直接呼叫 re.search 是不是就可以?
官方档案推荐:在多次使用某个正则表达式时推荐使用正则物件 Pattern 以增加复用性,因 为通过 re.compile(pattern) 编译后的模块级函式会被快取!
这是超链接,点击跳转 Python 正则表达式 , 这一篇就够了 !- 慕课网的文章-知乎

2.2 re.search 方法

Search 方法将输入的字符串整个扫描,对输入的正则表达式进行匹配,若无可匹配字符,将立即回传 None ,否则获取匹配结果, search 方法的语法格式如下,
re . search ( pattern , string [ , flags ] )
pattern : 接 收 Pattern 实 例 , 表 示 转 换 后 的 正 则 表 达 式 , 无 默 认 值
string
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *