首页 > 其他分享 > Spider理论系列-Re(正则表达式)

Spider理论系列-Re(正则表达式)

时间:2023-02-11 22:33:26浏览次数:44  
标签:字符 匹配 re 正则表达式 res Spider Re 字符串

正则是抓取网页数据的入门技能之一,正则可以全局通配你想要的数据,就比如:​​Spider实战系列-抓取《一人之下第三季》_浅辄的技术博客_51CTO博客​​这篇文章里,我想要通过源码来抓取url,但是xpath试过了抓不到,这时就可以使用正则表达式来抓取。

base_m3u8_url = re.search(

'<iframe id="mplay" name="mplay" src="/js/player/\?url=(.*?)" '

'allowfullscreen="allowfullscreen" mozallowfullscreen="mozallowfullscreen" msallowfullscreen="msallowfullscreen" oallowfullscreen="oallowfullscreen" webkitallowfullscreen="webkitallowfullscreen" frameBorder="no" width="100%" scrolling="no" height="100%">',data).group(1)

m3u8_url = base_m3u8_url.split('&')[0]

一.正则基础

1.为什么使用正则

需求

判断一个字符串是否为手机号

解决

编写一个函数,给函数一个字符串,如果是手机号,则返回True,否则返回False

伪代码

def isPhone(phone):
#长度为11
#全部是数字字符
#以1开头
pass
if isPhone("13517925431"):
print("是手机号")
else:
print("不是手机号")

注意

如果使用正则会让这个问题变得简单

2.正则与re模块简介

概述: 正则表达式,又称规则表达式

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern)

正则匹配是一个 模糊的匹配(不是精确匹配)

re:python自1.5版本开始增加了re模块,该模块提供了perl风格的正则表达式模式,re模块是python语言拥有了所有正则表达式的功能

  • 如下四个方法经常使用
  • match()
  • search()
  • findall()
  • finditer()

二、正则表达式

1、匹配单个字符与数字

匹配

说明

.

匹配除换行符以外的任意字符,当flags被设置为re.S时,可以匹配包含换行符以内的所有字符

[]

里面是字符集合,匹配[]里任意一个字符

[0123456789]

匹配任意一个数字字符

[0-9]

匹配任意一个数字字符

[a-z]

匹配任意一个小写英文字母字符

[A-Z]

匹配任意一个大写英文字母字符

[A-Za-z]

匹配任意一个英文字母字符

[A-Za-z0-9]

匹配任意一个数字或英文字母字符

[^lee]

[]里的^称为脱字符,表示非,匹配不在[]内的任意一个字符

^[lee]

以[]中内的某一个字符作为开头

\d

匹配任意一个数字字符,相当于[0-9]

\D

匹配任意一个非数字字符,相当于​​[^0-9]​

\w

匹配字母、下划线、数字中的任意一个字符,相当于[0-9A-Za-z_]

\W

匹配非字母、下划线、数字中的任意一个字符,相当于​​[^0-9A-Za-z_]​

\s

匹配空白符(空格、换页、换行、回车、制表),相当于[ \f\n\r\t]

\S

匹配非空白符(空格、换页、换行、回车、制表),相当于​​[^ \f\n\r\t]​

2、匹配锚字符

锚字符:用来判定是否按照规定开始或者结尾

匹配

说明

^

行首匹配,和[]里的^不是一个意思

$

行尾匹配

^a匹配一个小写字母a必须作为开头

加上就是完全匹配

3、限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。

匹配

说明

(xyz)

匹配括号内的xyz,作为一个整体去匹配一个单元子存储

x?

匹配0个或者1个x,非贪婪匹配

x*

匹配0个或任意多个x

x+

匹配至少一个x

x{n}

确定匹配n个x,n是非负数

x{n,}

至少匹配n个x

x{n,m}

匹配至少n个最多m个x

x|y

|表示或的意思,匹配x或y

不能单独使用需要配合正则表达式

三、re模块中常用函数

通用flags(修正符)


说明

re.I

是匹配对大小写不敏感

re.S

使.匹配包括换行符在内的所有字符

通用函数

  • 获取匹配结果
  • 使用group()方法 获取到匹配的值
  • groups() 返回一个包含所有小组字符串的元组(也就是自存储的值),从 1 到 所含的小组号。

1、match()函数

  • 原型
def match(pattern, string, flags=0)
  • 功能
    匹配成功返回 匹配的对象
    匹配失败 返回 None
  • 获取匹配结果
  • 使用group()方法 获取到匹配的值
  • groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
  • 注意:从第一位开始匹配 只匹配一次
  • 参数

参数

说明

pattern

匹配的正则表达式(一种字符串的模式)

string

要匹配的字符串

flags

标识位,用于控制正则表达式的匹配方式

  • 代码
import re

res = re.match('\d{2}','123')
print(res.group())

#给当前匹配到的结果起别名
s = '3G4HFD567'
re.match("(?P<value>\d+)",s)
print(x.group(0))
print(x.group('value'))

2、searce()函数

  • 原型
def search(pattern, string, flags=0)
  • 功能
    扫描整个字符串string,并返回第一个pattern模式成功的匹配
    匹配失败 返回 None
  • 参数

参数

说明

pattern

匹配的正则表达式(一种字符串的模式)

string

要匹配的字符串

flags

标识位,用于控制正则表达式的匹配方式

  • 注意:
    只要字符串包含就可以
    只匹配一次
  • 示例
import re

res = re.search('[a-z]', '131A3ab889s')
print(res)
print(res.group()
  • 注意
    与search的区别
    相同点:
    都只匹配一次
    不同点:
  • search是在要匹配的字符串中 包含正则表达式的内容就可以
  • match 必须第一位就开始匹配 否则匹配失败

3、findall()函数(返回列表)

  • 原型
def findall(pattern, string, flags=0)
  • 功能
    扫描整个字符串string,并返回所有匹配的pattern模式结果的字符串列表
  • 参数

参数

说明

pattern

匹配的正则表达式(一种字符串的模式)

string

要匹配的字符串

flags

标识位,用于控制正则表达式的匹配方式

  • 示例

myStr = """
<a href="http://www.baidu.com">百度</a>
<A href="http://www.taobao.com">淘宝</A>
<a href="http://www.id97.com">电
影网站</a>
<i>我是倾斜1</i>
<i>我是倾斜2</i>
<em>我是倾斜2</em>
"""
# html里是不区分大小写
# (1)给正则里面匹配的 加上圆括号 会将括号里面的内容进行 单独的返回
res = re.findall("(<a href=\"http://www\.(.*?)\.com\">(.*?)</a>)",myStr) #[('<a href="http://www.baidu.com">百度</a>', 'baidu', '百度')]

# 括号的区别
res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr) #['<a href="http://www.baidu.com">百度</a>']

#(2) 不区分大小写的匹配
res = re.findall("<a href=\"http://www\..*?\.com\">.*?</a>",myStr,re.I) #['<a href="http://www.baidu.com">百度</a>', '<A href="http://www.taobao.com">淘宝</A>']
res = re.findall("<[aA] href=\"http://www\..*?\.com\">.*?</[aA]>",myStr) #['<a href="http://www.baidu.com">百度</a>']
# (3) 使.支持换行匹配
res = re.findall("<a href="http://www..?.com">.?</a>",myStr,re.S) #
# (4) 支持换行 支持不区分大小写匹配
res = re.findall("<a href="http://www..?.com">.?</a>",myStr,re.S|re.I) #
print(res)

4、finditer()函数

  • 原型
def finditer(pattern, string, flags=0)
  • 功能
    与findall()类似,返回一个迭代器
  • 参数

参数

说明

pattern

匹配的正则表达式(一种字符串的模式)

string

要匹配的字符串

flags

标识位,用于控制正则表达式的匹配方式

  • 代码
import re

res = re.finditer('\w', '12hsakda1')
print(res)
print(next(res))

for i in res:
print(i)

5、split()函数

  • 作用:切割字符串
  • 原型:
def split(patter, string, maxsplit=0, flags=0)
  • 参数
    pattern 正则表达式
    string 要拆分的字符串
    maxsplit 最大拆分次数 默认拆分全部
    flags 修正符
  • 示例
import re
myStr = "asdas\rd&a\ts12d\n*a3sd@a_1sd"
#通过特殊字符 对其进行拆分 成列表
res = re.split("[^a-z]",myStr)
res = re.split("\W",myStr)

6、修正符

  • 作用
    对正则进行修正
  • 使用
    search/match/findall/finditer 等函数 flags参数的使用
  • 修正符
    re.I 不区分大小写匹配
    re.S 使.可以匹配换行符 匹配任意字符
  • 使用
    re.I
print(re.findall('[a-z]','AaBb'))
print(re.findall('[a-z]','AaBb', flags=re.I))

re.S

print(re.findall('<b>.*?</b>','<b>b标签</b>'))
print(re.findall('<b>.*?</b>','<b>b标\n签</b>', flags=re.S))

四、正则高级

1、分组&起名称

  • 概念
    处理简单的判断是否匹配之外,正则表达式还有提取子串的功能,用()表示的就是要提取的分组
  • 代码
#给当前匹配到的结果起别名
s = '3G4HFD567'
re.match("(?P<value>\d+)",s)
print(x.group(0))
print(x.group('value'))
  • 说明
  • 正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来
  • group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串

2、编译

  • 概念
    当在python中使用正则表达式时,re模块会做两件事,一件是编译正则表达式,如果表达式的字符串本身不合法,会报错。另一件是用编译好的正则表达式提取匹配字符串
  • 编译优点
    如果一个正则表达式要使用几千遍,每一次都会编译,出于效率的考虑进行正则表达式的编译,就不需要每次都编译了,节省了编译的时间,从而提升效率
  • compile()函数
  • 原型
def compile(pattern, flags=0)
  • 作用
    将pattern模式编译成正则对象
  • 参数

参数

说明

pattern

匹配的正则表达式(一种字符串的模式)

flags

标识位,用于控制正则表达式的匹配方式

  • flags


说明

re.I

是匹配对大小写不敏感

re.S

使.匹配包括换行符在内的所有字符

  • 返回值
    编译好的正则对象
  • 示例
import re

re_phone = re.compile(r"(0\d{2,3}-\d{7,8})")
print(re_phone, type(re_phone))
  • 编译后其他方法的使用
    原型
def match(self, string, pos=0, endpos=-1)
def search(self, string, pos=0, endpos=-1)
def findall(self, string, pos=0, endpos=-1)
def finditer(self, string, pos=0, endpos=-1)

参数

参数

说明

string

待匹配的字符串

pos

从string字符串pos下标开始

endpos

结束下标

示例

s1 = "lucky's phone is 010-88888888"
s2 = "kaige's phone is 010-99999999"
ret1 = re_phone.search(s1)
print(ret1, ret1.group(1))
ret2 = re_phone.search(s2)
print(ret2, ret2.group(1))

3、贪婪与非贪婪(重点)

  • 贪婪模式
    贪婪概念:匹配尽可能多的字符
  • .+ 匹配换行符以外的字符至少一次
  • .* 匹配换行符以外的字符任意次

实例

res = re.search('<b>.+</b>', '<b></b><b>b标签</b>')
res = re.search('<b>.*</b>', '<b>b标签</b><b>b标签</b><b>b标签</b><b>b标签</b>')
  • 非贪婪模式
    非贪婪概念:尽可能少的匹配称为非贪婪匹配,*?、+?即可
  • .+? 匹配换行符以外的字符至少一次 拒绝贪婪
  • .*? 匹配换行符以外的字符任意次 拒绝贪婪

实例

res = re.search('<b>.+?</b>', '<b>b标签</b><b>b标签</b>')
res = re.search('<b>.*?</b>', '<b>b标签</b><b>b标签</b><b>b标签</b><b>b标签</b>')

写在最后

其实正则用了这么久,最常用的还是非贪婪模式的(.*?)

标签:字符,匹配,re,正则表达式,res,Spider,Re,字符串
From: https://blog.51cto.com/u_15915681/6050993

相关文章

  • 7.4 FreeBSD Port帮你轻松使用源代码
    Unix系列操作系统FreeBSD中,存在一种名为Ports的机制。该机制能够结合当前运行的硬件环境来编译应用的源代码,进而得到可以运行的本地代码系统。如果目标应用的源代码没有在......
  • Avalonia 11.0.0-preview5中的一些更新
    在升级到11.0.0-preview5的过程中,有以下几个破坏性更新需要手动调整。首先需要先确保项目内所有Avalonia相关的依赖都升级到了11.0.0preview5https://github.com/Aval......
  • pillow ImageFont.truetype OSError: cannot open resource
     fromPILimportImageFont,ImageDraw#导入中文字体,指定字体大小font=ImageFont.truetype('SimHei.ttf',50) OSErrorTrace......
  • c++ 可以检测线程是否销毁的thread_guard
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+1e2,Q=N;usingll=longlong;intn,q;lla[N];intsta[N];structq_t{ intl,r;}que[Q......
  • LeetCode 22 -- Generate Parentheses
    ProblemGiven\(n\)pairsofparentheses,writeafunctiontogenerateallcombinationsofwell-formedparentheses.Example1Input:n=3Output:["((()))","(......
  • Literature分类的序
    Literature分类的序Datetime:2023-02-05T20:27:34+08:00Categories:LiteratureLocation:BeihangUniversity创建了一个分类,叫Literature。我尽量使用英文作为分......
  • Stream流(JDK8)
    Stream流为JDK8新增特性,为数组、集合等批量数据提供了一套函数式操作方法,简化数组和集合操作的API。这个Stream的流不同于​​java.io​​的InputStream和OutputStream,它代......
  • 018_基于 SpringBoot 的 SSMP 整合案例(表现层开发,基于Restful进行表现层接口开发)
      分页这部分在service层的代码(只看最后一个方法和最后一个方法实现就行)   ......
  • Vue和React的区别
    Vue:Vue是一个用于Web构建的UI的渐进式框架。"渐进式框架"和"自底向上增量开发的设计"是Vue开发的两个概念。特点:易用,使用成本低;灵活,生态系统完善。React:React主张函数......
  • Redis key命名规范
    Rediskey命名规范一、实现目标简洁,高效,可维护二、键值设计规约1Rediskey命名风格【推荐】Rediskey命名需具有可读性以及可管理性,不该使用含义不清的key以......