【小白学爬虫连载(3)】--正则表达式详细介绍

欢迎大家关注公众号【哈希大数据】
小白学爬虫系列(2)中介绍了如何用Requests获取网页内容,可是HTML文档中的内容比较繁杂,如何提取出我们需要的信息呢?本篇文章为大家介绍一个用于文本信息提取的强有力的工具——正则表达式
一、什么是正则表达式
正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个字符串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某种条件的子串等。——菜鸟教程
正则表达式在文本处理中十分常用,可以用于查找、替换、匹配一组字符串。接下来介绍几个正则表达式经典的实例:

正则表达式

由实例可以看出正则表达式的语由字符和操作符构成,正则表达式的常用操作符如下表所示:

操作符

二、Re库正则表达式表示介绍
正则表达式不是Python独有的,Python中re标准库,提供正则表达式的各种处理,接下来我们初步认识一下这个库。
首先re库可采用string和raw string(原生字符串)两种类型表示正则表达式,建议大家使用原生字符串。什么是原生字符串呢?在一般字符串'abc\tdef'前面加一个r,便成为了原生字符串。它的作用是使转义符\不起作用,字符串原样输出。比如:

s1 = r'abc\tdef'
print(s)
abc def
print(s1)
abc\tdef

原生字符串s1并没有把\t识别为制表符。同时大家要特别注意的是由于正则表达式使用反斜杠来转义特殊字符,而python自身处理字符串时,反斜杠也是用于转义字符,这样就产生了一个双重转换的问题。这个地方稍微有些复杂,不想深究可跳过下面不同字体的部分,大家只需注意当正则表达式包含转义符时使用原生字符串表示正则表达式就好。
接下来以匹配字符串s = 'abc-123'为例讲解。

s = 'abc\-123'
s1 = re.match('abc\\\\-123', s)
print("s1匹配结果:{}".format(s1.group()))
s1匹配结果:abc\-123
s2 = re.match(r'abc\\-123', s)
print("s2匹配结果:{}".format(s2.group()))
s2匹配结果:abc\-123

很明显我们需要注意两个地方,我们用'abc\\-123'和r'abc\-123'都能完成的对字符串s的匹配,字符串'abc\\-123'匹配过程中如下:首先因为它不是原始字符串,字符串转义函数会对其转义得到正则表达式'abc\-123',然后正则表达式'abc\-123'又会被正则表达式转义函数转义为字符串'abc-123',完成了对字符串s的匹配。原生字符串r'abc\-123'匹配过程如下,由于是原生字符串所以不会被转义,直接打到正则表达式'abc\-123',然后正则表达式'abc\-123'又会被正则表达式转义函数转义为字符串'abc-123'。所以两种情况都可以匹配成功。这里面提到字符串转义和正则表达式转义它们两个是有不同的,因为正则表达式的特殊字符和字符串特殊字符存在不同之处,如 * 在正则表达式中代表匹配前面的子表达式0次或多次,而在在字符串中不是特殊字符。你可以尝试理解下面这种情况,看看自己是否真正理解了上述过程:

s = '*abc123'
s1 = re.match('\*abc123', s)
print("s1匹配结果:{}".format(s1.group()))
s1匹配结果:*abc123
s2 = re.match('\\*abc123', s)
print("s2匹配结果:{}".format(s2.group()))
s2匹配结果:*abc123

三、Re库主要函数介绍

函数

re.match(pattern, string, flags=0)样例:

print(re.match('www', 'www.mingmenyun.com').group()) # 在起始位置匹配
print(re.match('com', 'www.mingmenyun.com')) # 不在起始位置匹配

运行结果为:
www
None
re.search(pattern, string, flags=0)样例:

print(re.search('www', 'www.mingmenyun.com').group()) # 在起始位置匹配
print(re.search('com', 'www.mingmenyun.com').group()) # 不在起始位置匹配
print(re.search('我爱你', 'Python我爱你,爬虫我爱你').group()) # 不在起始位置匹配

运行结果:
www
com
我爱你
re.findall(pattern, string, flags=0)样例:

print(re.findall('我爱你', 'Python我爱你,爬虫我爱你'))

运行结果:
['我爱你', '我爱你']
re.sub(pattern, repl, string, count=0)
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
样例:

print(re.sub(r'\d', '', "大河12向东流34,天上332的星星1参23北5斗"))

运行结果:
大河向东流,天上的星星参北斗
re.compile(pattern, flags=0)样例:

regex = re.compile('我爱你')
print(regex.findall('Python我爱你,爬虫我爱你'))

运行结果:
['我爱你', '我爱你']
re.match与re.search的区别:
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
re.search与re.findall的区别:
re.search只返回找到的第一个匹配,而re.findall返回所有匹配的的结果。
三、匹配目标获取与匹配模式
获取匹配目标:
样例:

s = 'Hello my QQ is 1428941524,welcome to contect me!'
result = re.match('^Hello.*\s(\d+),.*me!$', s)
print(result.group(1))
print(result.span())

运行结果:
1428941524
(0, 48)
如样例所示用()将想提取的信息括起来,group(1)代表第一个小括号内的内容,group(2)代表第二个...,这样便能提取出我们想要的信息啦。
匹配模式:
样例:

s = '''Hello
my QQ is 1428941524,welcome to contect me!'''
result = re.match('^Hello.*\s(\d+),.*me!$', s, re.S)
print(result.group(1))
print(result.span())

运行结果:
1428941524
(0, 48)
该样例与获取目标样例的不同之处在于,字符串s变为了多和字符串,中间出现了换行,match函数中多了re.S。此时不加它的话程序出错。re.S就是定义匹配模式的,类似的匹配模式如下表所示:

4.png

四、贪婪匹配与非贪婪匹配
贪婪匹配:
样例:

s = '''Hello 
my QQ is 1428941524,welcome to contect me!'''
result = re.match('^Hello.*(\d+).*me!$', s, re.S)
print(result.group(1))

运行结果:
4
结果只匹配到了4,142894152都被.匹配到了,.会尽可能多的匹配字符这就是贪婪匹配,由于后面有\d所以至少要匹配到一个数字,这是咱们不愿意看到的,有什么解决办法吗?当然有下面介绍非贪婪匹配。
非贪婪匹配:
样例:

s = '''Hello
my QQ is 1428941524,welcome to contect me!'''
result = re.match('^Hello.*?(\d+).*me!$', s, re.S)
print(result.group(1))

运行结果:
1428941524
非贪婪模式与贪婪模式的不同之处就在于在.*后加了一个?,非贪婪模式又称为最小匹配模式,就是说它会匹配到尽可能少的字符。
小结
本篇文章主要介绍了以下几点内容:

  • 什么是正则表达式,正则表达式的常用操作符

  • Re库正则表达式表示方式介绍,这里面有个比较难理解的地方是字符串与正则表达式的双重转换

  • Re库主要函数介绍,这里主要介绍了re.match()、re.search()、re.findall()、re.sub()、re.compile()

  • 匹配目标获取与匹配模式

  • 贪婪匹配与非贪婪匹配
    本次分享到此结束,目前我们已经学了requests库下载目标网站源码,正则表达提取文本信息,下次将分享如何使用chrome浏览器对想要爬取的网站进行分析。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,200评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,526评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,321评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,601评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,446评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,345评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,753评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,405评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,712评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,743评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,529评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,369评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,770评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,026评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,301评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,732评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,927评论 2 336

推荐阅读更多精彩内容