正则表达式是处理字符串的强大工具,它有自己的特定语法结构,有了它,实现字符串的检索、替换、匹配 验证都不在话下。
当然、对于爬虫而言,有了它,从HTML中提取信息就变得非常方便。
1.正则表达式介绍
开源中国的一个网站:http://tool.oschina.com/regex
写好正则表达式之后,就可以拿他去一个长的字符串里面匹配查找了。不论这个字符串里面有什么,只要匹配符合我们所写的规则,统统可以查找出来,对于网页而言,如果想找出网页源代码里有多少URL用匹配URL的正则表达式去匹配即可。
常用匹配规则:
1. \w 匹配字母、数字及下划线
2.\W 匹配不是字母、数字及下划线
3.\s 匹配任意空白字符、等价于[\t\n\r\f]
4.\S 匹配任意非空字符
5.\d 匹配任意数字,等价于[0-9]
6.\D 匹配任意非数字的字符
7.\A匹配字符串的开头 (初次看不知道用法)
8.\Z 匹配字符串结尾,如果存在换行、只匹配到换行前的结束字符串。
9.\z 匹配字符串的结尾,如果存在换行,同时还会匹配换行符。
10. \G 匹配最后匹配完成的位置(初次看见不知具体用法)
11. \n 匹配一个换行符
12.\t 匹配一个制表符
13.^ 匹配一行字符串的开头(与\A \Z之类区别是)
14.$ 匹配一行字符串的结尾
15. . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。(不懂)
16.[...] 用来表示一组字符,单独列出,比如[amk]匹配a、m、或k
17.[^...]不在字符串中
18. * 匹配 0个或多个表达式
19.+匹配一个或多个表达式
20.? 匹配0个或1个前面的正则表达式定义的片段,非贪婪方式
21.{n}精确匹配n个前面的表达式
22.{n,m} 匹配n到m次前面正则表达式定义的片段,贪婪方式。
23.a|b 匹配a或b
24. ( ) 匹配括号内的表达式,也表示一个组
看完晕晕,可能要多写写正则表达式。
正则表达式在其他编程语言中基本都有,但是Python的re库提供了整个正则表达式的实现,利用这个库,可以在Python中使用正则表达式。在Python中写正则表达式基本都使用这个库。
2.match()
常用匹配方法 match() 向他传入要匹配的字符串以及正则表达式,就可以检测这个字符串是否匹配字符串。match()方法会尝试从字符串的其实位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配就返回None;示例:
import re
content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result =re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)
print(result)
print(result.group())
print(result.span())

匹配目标
刚才我们用match()方法可以得到匹配到的字符串内容,但是如果想从字符串中提取一部分内容,我们应该怎么做呢?
可以使用()括号将向提取的字符串括起来。()实际上标记了一个子表达式的开始和结束位置,被标记的每一个子表达式会依次对应每一个分组,调用group()方法传入分组的索引既可获取提取的结果。示例如下:
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result =re.match('^Hello\s(\d+)\sWorld',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())
可以看到,我们成功得到了12345467。这里用的是group(1),它与group()有所不同,后者会输出完整的匹配结果,而前者会输出第一个被()包围的匹配结果。假如正则表达式后面还有()包括的内容,那么可以依次用group(2),group(3)等来获取。
通用匹配
刚才我们写的正则表达式都比较复杂。 万能匹配.* 点可以匹配任意字符(除换行符) 星代表匹配的字符无限次,所以他们组合在一起就可以匹配任意字符串了。
import re
content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
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('^He.*(\d+).*Demo$',content)
print(result)
print(result.group())
print(result.group(1))
这里我们依然想获取中间的数字,所以依然写的是(\d+)。而数字两侧由于内容比较乱,所以省略使用.* 通用匹配 ,但运行的时候得到的结果是7
原因:这里涉及的一个贪婪匹配与非贪婪匹配的问题。在贪婪匹配下,.*会匹配尽可能多的字符。这里尽可能就把123456匹配了,留下了7让\d+满足条件。
这里我们使用非贪婪匹配就可以,而非贪婪匹配的写法: .*?
import re
content = 'Hello 1234567 World_This is a Regex Demo'
result =re.match('^He.*?(\d+).*Demo$',content)
print(result)
print(result.group())
print(result.group(1))
此时就可以成功获取1234567了。
修饰符(换行符 空格 制表符 )
正则表达式可以包含一些标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。
.匹配的是换行符之外的任意字符,当遇到换行符的时候,.*就不能匹配了,所以导致匹配失败。这里只需要加一个修饰符 re.S在match()函数content之后即可 ,HTML网页中经常换行,所以这个使用频率很高。
一些修饰符:
1.re.I 使用匹配对大小写不敏感
2.re.L 做本地识别匹配
3.re.M 多行匹配,影响^和$
4.re.S使.匹配包括换行在内的所有字符。
5.re.U 根据Unicode字符集解析字符 这个标志影响 \w \W \b \B
6.re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
转义匹配
我们知道正则表达式定义和许多匹配模式,如.匹配除换行符以外的任意字符,但是如果目标字符串里就包含. 怎么办呢?
这时就需要转义匹配 了:当遇到用于正则匹配模式的特殊字符时,在前面加反斜线转义一下即可。
3.search()
前面提到的match()方法是从字符串的开头开始匹配的,一旦开头匹配不了,那么整个匹配就失败了。
import re
content = 'Extra strings Hello 123456789 World_This is a Regex Demo Extra strings'
result =re.search('Hello.*?(\d+).*Demo',content)
print(result)
这样的运行结果是None
如果使用search()方法 ,再看运行结果
因此为了匹配方便,我们经常使用的是search()
4.findall()
前面我们介绍了search()方法的用法 ,它可以返回匹配正则表达式的第一个内容,但是如果想要获取匹配正则表达式的所有内容,就可以借助findall()方法。
返回的列表中的每个元素都是元组类型,我们对应的索引依次取出即可。
5.sub ()
除了正则表达式提取信息外,有时候还需要借助它来修改文本。比如,想把一串文本中所有数字都去掉,如果只用字符串的replace()方法,那就太繁琐了们这样可以使用sub()方法。示例如下:
import re
content = '54aK54yr5oiR54ix5L2g'
content = re.sub('\d+','',content)
print(content)
sub('<a.*?>|</a>','',html ) 这样就去掉了 链接
6.compile
前面所讲的方法都是用来处理字符串的方法,最后再介绍一下compile()方法 ,这个方法可以将正则字符串编译成正则表达式对象,一遍在后面的匹配中复用。
import re
content1 = '2016-12-15 12:00'
content2 = '2016-12-17 12:55'
content3 = '2016-12-22 13:21'
pattern = re.compile('\d{2}:\d{2}')
result1 =re.sub(pattern,'',content1)
result2 =re.sub(pattern,'',content2)
result3 =re.sub(pattern,'',content3)
print(result1,result2,result3)
这里有三个日期,我们想分别将三个日期的时间去掉,这时可以借助sub()方法。该方法的第一个参数是正则表达式,但是这里没必要重复写3个同样的正则表达式,此时可以借助compile()方法将正则表达式编译成一个正则表达式对象,以便复用。
正则表达式的基本用法介绍完毕,之后的应用在实例中体现。