什么是正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑。

正则并不是python独有的,其他语言也都有正则
python中的正则,封装了re模块

python正则的详细讲解

常用的匹配模式

\w      匹配字母数字及下划线
\W 匹配f非字母数字下划线
\s 匹配任意空白字符,等价于[\t\n\r\f]
\S 匹配任意非空字符
\d 匹配任意数字
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果存在换行,只匹配换行前的结束字符串
\z 匹配字符串结束
\G 匹配最后匹配完成的位置
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配任意字符,除了换行符,re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
[....] 用来表示一组字符,单独列出:[amk]匹配a,m或k
[^...] 不在[]中的字符:[^abc]匹配除了a,b,c之外的字符
* 匹配0个或多个的表达式
+ 匹配1个或者多个的表达式
? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
{n} 精确匹配n前面的表示
{m,m} 匹配n到m次由前面的正则表达式定义片段,贪婪模式
a|b 匹配a或者b
() 匹配括号内的表达式,也表示一个组

re.match()

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配的话,match()就会返回None
语法格式:
re.match(pattern,string,flags=0)

最常规的匹配

import re

content= "hello 123 4567 World_This is a regex Demo"
result = re.match('^hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)
print(result)
print(result.group())
print(result.span())

结果如下:

result.group()获取匹配的结果
result.span()获去匹配字符串的长度范围
泛匹配

其实相对来说上面的方式并不是非常方便,其实可以将上述的正则规则进行更改

import re

content= "hello 123 4567 World_This is a regex Demo"
result = re.match("^hello.*Demo$",content)
print(result)
print(result.group())
print(result.span())

这段代码的结果和上面常规匹配的结果是一样的,但是写起来会方便很多

匹配目标

如果为了匹配字符串中具体的目标,则需要通过()括起来,例子如下:

import re
content= "hello 1234567 World_This is a regex Demo"
result = re.match('^hello\s(\d+)\sWorld.*Demo$',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

结果如下:

这里需要说一下的是通过re.group()获得结果后,如果正则表达式中有括号,则re.group(1)获取的就是第一个括号中匹配的结果

贪婪匹配

先看下面代码:

import re

content= "hello 1234567 World_This is a regex Demo"
result= re.match('^hello.*(\d+).*Demo',content)
print(result)
print(result.group(1))

这段代码的结果是

从结果中可以看出只匹配到了7,并没有匹配到1234567,出现这种情况的原因是前面的.* 给匹配掉了, .*在这里会尽可能的匹配多的内容,也就是我们所说的贪婪匹配,

如果我们想要匹配到1234567则需要将正则表达式改为:

result= re.match('^he.*?(\d+).*Demo',content)

这样结果就可以匹配到1234567

匹配模式

很多时候匹配的内容是存在换行的问题的,这个时候的就需要用到匹配模式re.S来匹配换行的内容

import re

content = """hello 123456 world_this
my name is zhaofan
""" result =re.match('^he.*?(\d+).*?zhaofan$',content,re.S)
print(result)
print(result.group())
print(result.group(1))

结果如下

转义

当我们要匹配的内容中存在特殊字符的时候,就需要用到转移符号\,例子如下:

import re

content= "price is $5.00"

result = re.match('price is \$5\.00',content)
print(result)
print(result.group())

对上面的一个小结:
尽量使用泛匹配,使用括号得到匹配目标,尽量使用非贪婪模式,有换行符就用re.S
强调re.match是从字符串的起始位置匹配一个模式

re.search

re.search扫描整个字符串返回第一个成功匹配的结果

import re

content = "extra things hello 123455 world_this is a Re Extra things"

result = re.search("hello.*?(\d+).*?Re",content)
print(result)
print(result.group())
print(result.group(1))

结果如下:

其实这个时候我们就不需要在写^以及$,因为search是扫描整个字符串

注意:所以为了匹配方便,我们会更多的用search,不用match,match必须匹配头部,所以很多时候不是特别方便

匹配演练

例子1:

import re

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>''' result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S)
print(result)
print(result.groups())
print(result.group(1))
print(result.group(2))

结果为:

re.findall

搜索字符串,以列表的形式返回全部能匹配的子串

代码例子如下:

import re

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>''' results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)
print(results)
print(type(results))
for result in results:
print(result)
print(result[0], result[1], result[2])

结果如下:

例子2:

import re

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2">一路上有你</li>
<li data-view="7">
<a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>
<li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
<li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3" singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>''' results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)
print(results)
for result in results:
print(result[1])

结果如下:

其实这里我们就可以看出

\s*? 这种用法其实就是为了解决有的有换行,有的没有换行的问题

(<a.*?>)? 这种用法是因为html中有的有a标签,有的没有的,?表示匹配一个或0个,正好可以用于匹配

re.sub

替换字符串中每一个匹配的子串后返回替换后的字符串

re.sub(正则表达式,替换成的字符串,原字符串)

例子1

import re

content = "Extra things hello 123455 World_this is a regex Demo extra things"

content = re.sub('\d+','',content)
print(content)

结果会讲数字替换为为空:

例子2,在有些情况下我们替换字符的时候,还想获取我们匹配的字符串,然后在后面添加一些内容,可以通过下面方式实现:

import re

content = "Extra things hello 123455 World_this is a regex Demo extra things"

content = re.sub('(\d+)',r'\1 7890',content)
print(content)

结果如下:

这里需要注意的一个问题是\1是获取第一个匹配的结果,为了防止转义字符的问题,我们需要在前面加上r

re.compile

将正则表达式编译成正则表达式对象,方便复用该正则表达式

import re
content= """hello 12345 world_this
123 fan
""" pattern =re.compile("hello.*fan",re.S) result = re.match(pattern,content)
print(result)
print(result.group())

正则的综合练习

获取豆瓣网书籍的页面的书籍信息,通过正则实现

import requests
import re
content = requests.get('https://book.douban.com/').text
pattern = re.compile('<li.*?cover.*?href="(.*?)".*?title="(.*?)".*?more-meta.*?author">(.*?)</span>.*?year">(.*?)</span>.*?</li>', re.S)
results = re.findall(pattern, content)
print(results) for result in results:
url,name,author,date = result
author = re.sub('\s','',author)
date = re.sub('\s','',date)
print(url,name,author,date)

结果如下:

Python之爬虫(七)正则的基本使用的更多相关文章

  1. 第三百七十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapyd部署scrapy项目

    第三百七十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapyd部署scrapy项目 scrapyd模块是专门用于部署scrapy项目的,可以部署和管理scrapy项目 下载地址:h ...

  2. 第三百七十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现我的搜索以及热门搜索

    第三百七十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现我的搜索以及热门 我的搜素简单实现原理我们可以用js来实现,首先用js获取到 ...

  3. 第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页

    第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页 逻辑处理函数 计算搜索耗时 在开始搜索前:start_time ...

  4. 自学Python六 爬虫基础必不可少的正则

    要想做爬虫,不可避免的要用到正则表达式,如果是简单的字符串处理,类似于split,substring等等就足够了,可是涉及到比较复杂的匹配,当然是正则的天下,不过正则好像好烦人的样子,那么如何做呢,熟 ...

  5. 《精通python网络爬虫》笔记

    <精通python网络爬虫>韦玮 著 目录结构 第一章 什么是网络爬虫 第二章 爬虫技能概览 第三章 爬虫实现原理与实现技术 第四章 Urllib库与URLError异常处理 第五章 正则 ...

  6. Python 网络爬虫干货总结

    Python 网络爬虫干货总结 爬取 对于爬取来说,我们需要学会使用不同的方法来应对不同情景下的数据抓取任务. 爬取的目标绝大多数情况下要么是网页,要么是 App,所以这里就分为这两个大类别来进行了介 ...

  7. Python逆向爬虫之scrapy框架,非常详细

    爬虫系列目录 目录 Python逆向爬虫之scrapy框架,非常详细 一.爬虫入门 1.1 定义需求 1.2 需求分析 1.2.1 下载某个页面上所有的图片 1.2.2 分页 1.2.3 进行下载图片 ...

  8. Python简单爬虫入门二

    接着上一次爬虫我们继续研究BeautifulSoup Python简单爬虫入门一 上一次我们爬虫我们已经成功的爬下了网页的源代码,那么这一次我们将继续来写怎么抓去具体想要的元素 首先回顾以下我们Bea ...

  9. [Python] 网络爬虫和正则表达式学习总结

    以前在学校做科研都是直接利用网上共享的一些数据,就像我们经常说的dataset.beachmark等等.但是,对于实际的工业需求来说,爬取网络的数据是必须的并且是首要的.最近在国内一家互联网公司实习, ...

  10. python简易爬虫来实现自动图片下载

    菜鸟新人刚刚入住博客园,先发个之前写的简易爬虫的实现吧,水平有限请轻喷. 估计利用python实现爬虫的程序网上已经有太多了,不过新人用来练手学习python确实是个不错的选择.本人借鉴网上的部分实现 ...

随机推荐

  1. (二)JPA实体类主键生成策略

    在JPA中,配置实体类的主键的生成策略使用 @GeneratedValue @Id @Column(name = "id") @GeneratedValue(strategy = ...

  2. CocosCreator实现微信排行榜

    1. 概述 不管是在现实生活还是当今游戏中,各式各样的排名层出不穷.如果我们做好一款游戏,却没有实现排行榜,一定是不完美的.排行榜不仅是玩家了解自己实力的途径,也是游戏运营刺激用户留存的一种途径.在微 ...

  3. VS Code项目中通过npm包的方式共享代码片段的方案实现

    VS Code项目中通过npm包的方式共享代码片段的方案实现 上周在 "VS Code项目中共享自定义的代码片段方案" 的文章中提到过一个共享代码片段的方案,上周经过调研后并没有发 ...

  4. 求求你,别问了,Java字符串是不可变的

    最近,又有好几个小伙伴问我这个问题:"二哥,为什么 Java 的 String 要设计成不可变的啊?"说实话,这也是一道非常经典的面试题,面试官超喜欢问.我之前写过这方面的文章,现 ...

  5. 视频的清晰度 1080p 720p 2k 4k是什么意思?

    在bilibili上看了一些个视频,发现它视频的清晰度有很多种选法.诸如720p,1080p,2k,4k,以及我看直播时经常遇见的蓝光,超清.它们的含义分别是什么呢?为了搞清楚这个问题,也为了以后的观 ...

  6. java中int和Integer的区别?为什么有了int还要有设计Integer?

    参考https://blog.csdn.net/chenliguan/article/details/53888018 https://blog.csdn.net/myme95/article/det ...

  7. linux kernel update

    linux内核升级 最近HW行动,报出来的linux系统内核漏洞,环境中全部是2.6.32-431.el6.x86_64的主机,需要全部升级到754版本,这也是第一次进行内核升级操作. 先找了一台和生 ...

  8. Python多核编程mpi4py实践及并行计算-环境搭建篇

    1.安装python,这个没什好说的,直接装就行 2.做并行计算.数据挖掘,机器学习等一般都要用的numpy,这个在Windows版本上安装有点问题,安装比较麻烦,建议在linux上搭建环境 3.安装 ...

  9. mysql定时备份任务

    简介 在生产环境上,为了避免数据的丢失,通常情况下都会定时的对数据库进行备份.而Linux的crontab指令则可以帮助我们实现对数据库定时进行备份.首先我们来简单了解crontab指令,如果你会了请 ...

  10. Day10-微信小程序实战-交友小程序-添加好友功能之创建并更新message信息

    1.首先要在 添加好友 这个按钮上添加一个事件,也就是在detail.wxml的添加好友这个按钮的哪里,添加一个点击事件 handleAddFriend 并且添加好友还要考虑,现在是已登陆状态还是未登 ...