正则表达式
- 正则表达式是用来间接表达一组字符串的表达式
- 通用的字符串表达框架
- 针对字符串表达“简洁”和“特征”思想的工具
- 判断某字符串的特征归属
- 正则表达式在文本处理中十分常用
- 表达文本类型的特征(病毒、入侵等)
- 同时插座或替换一组字符串
- 匹配字符串的全部或部分
1、正则表达式的使用
- 编译:将符号正则表达式语法的字符串转换成正则表达式特征
1)正则表达式的常用操作符
操作符 | 说明 | 实例 |
---|---|---|
. | 表示任何单个字符 | |
[] | 字符集,对单个字符给出取值范围 | [abc]表示a、b、c,[a-z]表示a到z单个字符 |
[^] | 非字符集,对单个字符给出排除范围 | [^abc]表示非a或b或c的单个字符 |
* | 前一个字符0次或无限次扩展 | abc*表示ab、abc、abcc、abccc等 |
+ | 前一个字符1次或无限次扩展 | abc+表示abc、abcc、abccc等 |
? | 前一个字符0次或1次扩展,非贪婪匹配,匹配到第一个就结束 | abc?表示ab、abc |
| | 左右表达式任意一个 | abc |
{m} | 扩展前一个字符m次 | ab{2}c表示abbc |
{m,n} | 扩展前一个字符m至n次(含n) | ab{1,2}c表示abc、abbc |
^ | 匹配字符串开头 | ^abc表示abc且在一个字符串的开头 |
$ | 匹配字符串结尾 | abc$表示且在一个字符串的结尾 |
() | 分组标记,内部只能使用|操作符 | (abc)表示abc,(abc |
\d | 数字,等价于[0-9] | |
\w | 单词字符,匹配数字、字母、下划线等价于[A-Za-z0-9_] |
- 举例:
- 由26个字符组成的字符串:^[A-Za-z]+$
- 由26个字母和数字组成的字符串:^[A-Za-z0-9]+$
- 整数形式的字符串:^-?\d+$
- 正整数形式的字符串:^[0-9][1-9][0-9]$
- 中国境内邮政编码,6位:[1-9]\d{5}
- 匹配中文字符:[\u4e00-\u9fa5]
- 国内电话号码,010-68913536:\d{3}-\d{8}|\d{4}-\d{7}
2、Re库介绍
- Re库是python的标准库,主要用于字符串匹配
- 调用方法:import re
- 正则表达式的表示类型
- raw string类型(原生字符串类型):r’text’
-raw string是不包含转义符的字符串 - sting类型。更繁琐
- raw string类型(原生字符串类型):r’text’
2)Re库主要功能函数
函数 | 说明 |
---|---|
re.serach() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 |
re.split() | 将一个字符串按照正则表达式匹配结果进行分隔,返回列表类型 |
re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象 |
re.sub() | 在一个字符串中替换所有匹配正则表达式的字串,返回替换后的字符串 |
re.compile() | 编译正则表达式,返回一个对象模式 |
3)flags:正则表达式使用时的控制标记
常用标记 | 说明 |
---|---|
re.I re.IGNORECASE | 忽略大小写的匹配模式 |
re.M re.MULLTILINE | 多行模式。改变和$的行为。操作符能够将给定字符串的每行当作匹配开始 |
re.S re.DOTALL | 此模式下’.'的匹配不受限制,可配配任何字符,包括换行符 |
re.X | 忽略正则表达式中的空白和#号的注释 |
4)match object对象的一些常用方法
方法 | 说明 |
---|---|
group() | 返回被re匹配的字符串 |
groups() | 返回一个包含所有小组字符串的元组 |
start() | 返回匹配字符串开始的位置 |
end() | 返回匹配字符串结束的位置 |
span() | 返回一个元组,还元组由匹配字符串开始和结束的位置组成,即(开始位,结束位)注意,左闭右开 |
5)match对象的属性
属性 | 说明 |
---|---|
.string | 待匹配的文本 |
.re | 匹配时使用的pattern对象(正则表达式) |
.pos | 正则表达式搜索文本的开始位置 |
.endpos | 正则表达式搜索文本的结束位置 |
a).re.serach(pattern,string,flags = 0)
- 在一个字符串中搜索匹配正则表达式的第一个位置返回match对象
- pattern:正则表达式的字符串或原生字符串表示
- string:待匹配字符串
- flags:正则表达式使用时的控制标记
import re
match = re.search(r'[1-9]\d{5}','BIT 100081') #匹配邮政编码
if match:
print(match.group(0))
b).re.match(pattern,string,flags = 0)
- 从一个字符串的开始位置起匹配正则表达式,返回match对象
- pattern:正则表达式的字符串或原生字符串表示
- string:待匹配字符串
- flags:正则表达式使用时的控制标记
import re
match = re.match(r'[1-9]\d{5}','100081 BIT') #从开始匹配邮政编码
if match:
print(match.group(0))
c).re.findall(pattern,string,flags = 0)
- 搜索字符串,以列表类型返回全部能匹配的字串
- pattern:正则表达式的字符串或原生字符串表示
- string:待匹配字符串
- flags:正则表达式使用时的控制标记
import re
ls = re.findall(r'[1-9]\d{5}','BIT 100081 TSU100084') #从开始匹配邮政编码
print(ls)
输出:['100081', '100084']
d).re.split(pattern,string,maxsplit= 0 ,flags = 0)
- 将一个字符串按照正则表达式匹配结果进行分隔,返回列表类型
- maxsplit:最大分隔数,剩余部分作为最后一个元素输出
import re
ls = re.split(r'[1-9]\d{5}','BIT 100081 TSU100084') #从开始匹配邮政编码
print(ls)
输出:['BIT ', ' TSU', '']
e).re.finditer(pattern,string,flags=0)
- 搜索字符串,返回一个匹配结果的迭代类型,每个迭代类型元素是match对象
import re
for m in re.finditer(r'[1-9]\d{5}','BIT 100081 TSU100084'):#从开始匹配邮政编码
if m:
print(m.group(0))
输出:
100081
100084
f).re.sub(pattern,repl,string,count = 0,flags=0)
- 在一个字符串中替换所有匹配正则表达式的字串,返回替换后的字符串
- repl:替换匹配字符串的字符串
- count:匹配的最大替换次数
import re
s= re.sub(r'[1-9]\d{5}','zipcode','BIT 100081 TSU100084') #从开始匹配邮政编码
print(s)
输出:BIT zipcode TSUzipcode
g).re.compile(pattern,flags=0)
- 编译正则表达式,返回一个对象模式,用于规则多次使用
pat = re.compile(r"a.b",re.I) #忽略大小写
pat.search('kanBli').group() #方法.group返回一个或多个匹配的字串
输出:'anB'
6)最小匹配操作符
操作符 | 说明 |
---|---|
*? | 前一个字符0次或无限次扩展,最小匹配 |
+? | 前一个字符1次或无限次扩展,最小匹配 |
?? | 前一个字符0次或1次扩展,最小匹配 |
{m,n}? | 前一个字符m次至n(含n)次扩展,最小匹配 |
2、淘宝爬取实例
# 1、https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306
# 2、https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=3&ntoffset=3&p4ppushleft=1%2C48&s=44
# 3、https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=0&ntoffset=6&p4ppushleft=1%2C48&s=88
import requests
import re
kv = {"user-agent":'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'}
cookies = {"thw=cn":"t=254ecf83ad9b49c70d383c71e214fab2;cna=kbBgFFO2dU8CAXFzKR/6/wq5; tg=0;enc=xWaBwIc%2BqZfhPca6P6g4cz34emAsVK3LjzRsT%2FkMfk5Ja31%2BmjMxGvBDJ%2B82Q2pJLJ83dUH5lBPAw%2BpI53L4%2BQ%3D%3D; hng=CN%7Czh-CN%7CCNY%7C156"}
def gethtml(url):
try:
r = requests.get(url,headers = kv,cookies = cookies, timeout = 30)
r.raise_for_status() #如果状态不是200,引发HTTPError异常
r.encoding = r.apparent_encoding
print(r.request.url)
return r.text
except:
return "爬取失败"
def parsePage(ilt,html):
try:
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].split(":")[1])
tiltle = eval(tlt[i].split(":")[1])
ilt.append(([price,tiltle]))
except:
print("解析异常")
def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
print(tplt.format("序号","价格","商品名称"))
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count,g[0],g[1]))
def main():
goods = "书包"
depth = 2 #深度
start_url = "https://s.taobao.com/search?q=" + goods
infoList= []
for i in range(depth):
try:
url = start_url + '&s=' + str(44*i)
html = gethtml(url)
parsePage(infoList,html)
except:
continue
printGoodsList(infoList)
if __name__ == "__main__":
main()