作者:htqdw | 来源:互联网 | 2023-06-01 17:30
如果把BeautifulSopu比喻成通过线索一步步接近目标的侦探的话,那么正则表达式就是牛逼哄哄的“天眼系统”,只要提供一些目标的特征,无论搜索范围多大,只要存在那么一两个符合特
如果把BeautifulSopu比喻成通过线索一步步接近目标的侦探的话,那么正则表达式就是牛逼哄哄的“天眼系统”,只要提供一些目标的特征,无论搜索范围多大,只要存在那么一两个符合特征的目标,全都会被它直接逮住。
特性
牛逼王
- BS的爸爸,我告诉你个秘密,其实BeautifulSoup也是用正则实现的,而且它find_all的参数里还能接收正则呢
- 信息精确定位,BeautifulSoup用的是节点定位,可能会出现多个符合条件的节点(却没有目标信息);正则是直接针对目标信息,以字符为单位匹配,一次筛选出正确结果(前提是写好正则)
- 能获取信息的部分,有时候完整的信息不是你想要的,你只想取它的某一部分,正则能搞定,BS只能先获取完整信息再分离。
- 用途大着呢,不要以为正则只能爬虫,前后端都少不了正则,你填个信息判断是否合法这都是正则,总之学到赚到啊
劝退大王+
这么强大的方法是不是看到都心动了,不过强大是有代价的,较难上手很难精通这两根大棒一下子锤走了不少初学者。当时学的我是这样的:
如果有足够的自信和毅力不被正则击倒,那就来吧。(屁,学正则还不是迟早的事!)
re 模块
python 自带模块,直接导入即可。有匹配,替换等方法。
思考了许久后笔者觉得还是先讲表达式(规则)好,因为某些方法的理解是要了解表达式的。
下文的规则是完全版的,花了很久写成,分享给读者,顺便当成自己的网上笔记。
如果你学正则只是单单用来爬虫的话,你只要熟悉“字符匹配”,“分组&或&转义”,“预定字符集”,“数量词”,“非贪婪模式”和(?:)取消分组,了解(或干脆不学)“边界匹配”,“特殊构造”就行了。
如果你觉得正则是你未来工作的刚需的话,推荐熟悉所有规则。
匹配规则(pattern)
规则其实是一个原字符串如r’表达式’/r”表达式”,较正式的叫法是模式字符串。最后再说一句,匹配以单个字符为单位(除括号能把多个字符打包成分组(整体)来匹配)
表达式本质是字符串,不要单引(双引)号里套单引(双引)号,会出错。
字符匹配
- 任一字符(空格也算)——就是匹配这个字符,某些字符因为在正则中有特殊用途需前加反斜杠转义如 [ { . | ( ) ^ * + ? $
- .——英文句号,匹配除换行符\n外的任意单个字符
- []——匹配中括号里的任一字符,与–结合还能表示范围内的任一字符,中括号内的字符除\外会自动转义,还有小心多个中括号嵌套错误
- [^]——中括号最前面加^,与[ ]反义,匹配一个不在中括号里的字符,也可以用横杠-
r'[abcd]'#匹配一个a或b或c或d
r'[0-9]'#匹配一个0至9的数,-的作用域是左右各一个字符
r'[a-z]' r'[A-Z]'#分别匹配a到z或A到Z的一个字母
r'[12-89]'#注意因为是单字符匹配,匹配的是1,2到8的数,9(即1到9的一个数),不是12到89的数
r'[{.|()^*+?$\\]'#匹配 { . | ( ) ^ * + ? $ \中任一个,\要转义
r'[^a-zA-Z]'#匹配一个不是字母的字符
分组&或&转义
预定字符集
数量词(接在字符或子组后)
非贪婪模式
- 在数量词后接?,对前面的数量词开启非贪婪模式,意思就是在能匹配的前提下尽可能少的重复匹配。
- 正则默认开启贪婪模式
r'<.+>'#默认贪婪,对于''能匹配到''整条,因为.贪婪地把尖括号也匹配掉了
r'<.+?>'#非贪婪,对于''能匹配到''和''
边界匹配
特殊构造(不作为分组,不被findall捕获)
方法&参数
相比于繁杂的规则,方法则要简单多了,常用的就这几个:
- re.search(pattern,string,flags=0),返回第一个匹配的match对象(内含匹配字符串的信息)
- re.findall(pattern,string,flags=0),返回所有匹配分组的字符串组成的列表,没设置分组相当于整个表达式就是一个分组
- #如果表达式有多个分组,会返回复杂的列表,因此findall中的表达式通常只有一个分组
re.finditer(pattern,string,flags=0),同findall功能,但是返回的是迭代器
re.findall(r'\d+(abc)\d+','1abc1,2abc2')#分组为(abc),findall只捕捉被数字包起来的abc返回列表['abc','abc']
re.findall(r'((?:ab){2}\d)\d','abab11,abab22')#整个表达式匹配abab加一个两位数,(?:)取消了ab的分组,findall只捕捉abab加一个数,返回列表['abab1','abab2']
- pattern = re.compile(pattern,flags=0),把规则打包返回(如多次使用该规则),相当与pattern和flag的合体,当成pattern使用可免去设置flags
- re.sub(pattern,repl,string,count=0,flags)把匹配到的部分用指定字符串repl替换,count设置替换次数,默认为零替换所有
参数:
match对象方法
列出常用方法,下面的match是对象
- match.group(id/name)id是分组序号(1~99),name是分组的自定名字,返回指定分组的字符串;不传参数数是返回整条匹配字符串
- match.start(id/name),match.end(id/name),match.span(id/name),分别返回指定分组字符串在整个字符串中的开始位置,结束位置,范围。
地狱之旅到这就结束了,不仅是读者的,还是我的,お疲れ
文章过长,可能存在某些瑕疵和错误,欢迎提出
累成苟,最近而且要忙于学习,又被P大学事件恶心了一下,接下来的产能会下降,估计一个星期多一点更一次
正则慢慢学就行,正则的使用后面会有实例让大家熟悉