Welcome To Jeremy's Blog --------------------------            JeremyYu

1.4 数据解析 -- 正则基础


1.正则表达式介绍

  正则表达式是处理字符串的强大工具,它有自己特定的语法结构. 在爬虫中正则表达式能帮助我们实现什么呢? 当我们通过程序向服务器发起请求, 并且获取到响应后, 获得到的文本内容只有一部分是我们的需要的, 而且这部分内容并不能通过其他的解析库进行解析, 比如这部分内容并不在标签中, 而是在js中, 这是我们就可以用正则表达式进行匹配, 获取我们的目标数据.

  可能上面这种情况, 我们还有其他的解决思路, 但正则也是一种解决问题的方式.

  注意:正则表达式是一种通用的工具, 它不是Python独有的

返回顶部


2.常用的匹配规则

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

返回顶部


3.Python 的re模块与正则表达式相配合

re模块介绍:

(1).re.match(pattern, string, flags=0)

 1 # 1.向match方法中传入正则表达式以及要匹配的字符串, match方法会尝试从字符串的其实位置匹配正则表达式, 如果匹配成功, 就返回匹配成功的结果, 这个结果是一个对象, 如果匹配不成功则返回None.
 2 
 3 # 2.必要参数:
 4         pattern:正则表达式
 5         string:待匹配字符串
 6 
 7 # 3.match返回对象的方法:
 8         match返回的对象使用group进行取值:object.group()
 9         match返回的对象使用span查看子串在原字符串中的位置:object.span()
10         (span()返回的是子串的第一个字符在原字符串中的索引和子串最后一个字符在原字符串中的索引+1)
11 
12 # 4.注意: match()方法只从字符串的开头第一个字符进行匹配, 如果开头字符没匹配成功, 就返回None    
 1 import re
 2 
 3 text ='hello world'
 4 result = re.match('h.*?o')
 5 print("匹配的对象:", result)
 6 print('取出的值:', sult.group())
 7 print('子串位置:', result.span())
 8 
 9 # 输出结果:
10   匹配的对象:<_sre.SRE_Match object; span=(0,5), match='hello'>
11   取出的值: hello
12   子串位置:(0,5)

返回顶部

(2).re.search(pattern, string, flags=0)

 1 # 1.在匹配时,search()方法会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回None。
 2 
 3 # 2.必要参数:
 4     pattern:正则表达式
 5     string:待匹配字符串
 6 
 7 # 3.返回结果:
 8     match返回的对象使用group进行取值:object.group()
 9     match返回的对象使用span查看子串在原字符串中的位置:object.span()
10     span()返回的是子串的第一个字符在原字符串中的索引和子串最后一个字符在原字符串中的索引+1)
 1 import re
 2 
 3 text ='llo worlld'
 4 result = re.match('ll', text)
 5 print("匹配的对象:", result)
 6 print('取出的值:', sult.group())
 7 print('子串位置:', result.span())
 8 
 9 # 输出结果:
10     匹配的对象:<class'_sre.SRE_Match'>
11     取出的值: ll
12     子串位置:(2,4)

返回顶部

(3).re.findall(pattern, string, flags=0)

 1 # 1.在匹配时,findall()会搜索整个字符串,然后返回匹配到的所有内容
 2 
 3 # 2.必要参数:
 4     pattern:正则表达式
 5     string:待匹配字符串
 6 
 7 # 3.返回结果:
 8 findall()的返回值是一个列表,列表中的元素就是匹配到的所有子串
 9 text ='llo worlld'
10 result = re.findall('ll', text)
11 print(result)
12 
13 # 输出结果:
14     ['ll','ll']

返回顶部


4.re.compile()的使用

 1 # 1.方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用. 主要针对较为复杂的正则表达式, 当编译后赋值给一个变量, 每次使用直接使用该变量.
 2 
 3 # 示例代码:
 4 import re
 5 par = re.compile('hello.*?world')
 6 text ='skdflej0kdjfo hello123world sfewfsdfd'
 7 result = re.findall(par, text)
 8 print(result)
 9 
10 # 输出结果:
11     ['hello123world']

返回顶部


5.正则与re模块注意项与小技巧

(1).贪婪匹配与非贪婪匹配

 1 # 1.在匹配的过程中,使用了像量词*,+等,*代表匹配0个或无数个,+代表匹配1个或无数个.这是就涉及到了匹配的数量问题.所以需要引出贪婪匹配与非贪婪匹配的概念.
 2   -贪婪匹配:尽可能的多匹配
 3   -非贪婪匹配:尽可能的少匹配,在量词后加?
 4   (注意:默认贪婪匹配)
 5 
 6 # 2.示例:
 7 import re
 8 text ='skdfjkhelloAoA123worlloAoAdd'
 9 res1 = re.findall('ll.*?A', text)
10 print('非贪婪匹配:', res1)
11 res2 = re.findall('ll.*A', text)
12 print('贪婪匹配:', res2)
13 
14 # 输出结果:
15     非贪婪匹配:['lloA','lloA']
16     贪婪匹配:['lloAoA123worlloAoA']

返回顶部

(2).命名与分组

 1 # 1.在进行正则进行匹配时,将表达式中的指定部分用括号括起来,就形成了分组,分组的好处体现在使用re模块是会优先显示分组内容
 2 
 3 # 2.示例:要提取a标签中的文本内容
 4 import re
 5 tag ='<a href="https://www.baidu.com">跳转至百度</a>'
 6 res = re.findall('<a.*">(.*?)</a>', tag)
 7 print(res)
 8 
 9 # 输出结果:
10     ['跳转至百度']

返回顶部

(3).转义

 1 # 1.在书写正则表达式时,表达式中包含了*一类的特殊字符,它们都有特殊的意义,对匹配结果起到一定的影响作用,但如果我们要匹配的内容中包含了这些该怎么办呢?这是就用到了转义.转义实在相应的字符前加一个.
 2 
 3 # 2.示例:匹配路径E盘下coding路径下的所有文件'
 4 import re
 5 s = r'这里有两个路径E:\coding\reg.py, E:\test\spider.py, E:\coding\hello.py'
 6 path = re.findall(r'E:\\.*?py', s)
 7 print(path)
 8 
 9 # 输出结果:
10     ['E:\\coding\\reg.py', 'E:\\coding\\hello.py']

返回顶部

(4).re修饰符

 1 # 1.介绍:
 2     在之前用到的re模块方法中都会有一个flag参数没有提到,这个flag就是用来承载修饰符的.
 3     修饰符的作用是影响匹配的结果,对匹配方式做一定的修饰,比如在正则表达式中'.'代表匹配除换行符之外的任意字符,当遇到换行符,像.*?就不能匹配了.这时需要使用re.S进行修饰,就可以多行匹配了.
 4 
 5 # 2.修饰符:
 6     re.I:使匹配对大小写不敏感
 7     re.L:做本地化识别(locale-aware)匹配
 8     re.M:多行匹配,影响^和$
 9     re.S:使.匹配包括换行在内的所有字符
10     re.U:根据Unicode字符集解析字符。这个标志影响\w、\W、 \b和\B
11     re.X:该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

返回顶部

 1 # 示例: 匹配文本中的所有a标签内的文本
 2 import re
 3 html_text ='''
 4 <p><a href="#">N
 5 O.1</a></p>
 6 <p><a href="#">N
 7 O.2</a></p>
 8 <p><a href="#">N
 9 O.3</a></p>
10 <p><a href="#">N
11 O.4</a></p>
12 '''
13 result = re.findall('.*?#">(.*?)</.*?', html_text, re.S)
14 for i in result:
15 print(i.replace("\n\t",""))# 匹配结果中带有\n\t, 需要对匹配结果进行处理
16 
17 # 输出结果为:
18       NO.1
19       NO.2
20       NO.3
21       NO.4

返回顶部

posted on 2018-03-11 22:20  Jeremy_Yu  阅读(104)  评论(0)    收藏  举报

导航