Loading

re模块

1.re模块

python中专门操作正则表达式的模块

 1.1findall()

将匹配到的所有数据放入列表中

缺点是占内存,一个10G的文件,匹配到8G,那么内存就会被占满,所以一般不用,或者数据很少如下时才使用

正则表达式在python看来就是一个字符串

import re
#找到所有匹配到的结果放入列表中
#返回匹配到的元素放到一个列表中,默认为贪婪模式
print(re.findall(r"[a-z]+","asd2fbs4dfa"))
['asd', 'fbs', 'dfa']
findall()的优先级,默认findall优先把匹配结果组里内容返回
import re

ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
#findall正则里面引入分组的目的就是过滤掉虽然匹配到了,但是不想要的数据,所以findall优先显示分组数据,不是分组内数据不显示
ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['www.oldboy.com']

1.2search()

找到一个就返回,返回的是一个对象,需要调用group()可以获得值

一个坑就是,如果没有找到,调用group就会报错,所以要用if判断一下

import re
ret = re.search("[a-z]+", "asd2fbs3dfa")
print(ret)
if ret:
    print(ret.group())

虽然group()返回一个结果,但是这个结果里面也可能包含不想要的数据

拿到的对象调用group()拿到匹配到的所有结果,而往往匹配到的信息中包含了想要的信息和不想要的信息

把想要的信息用分组包围,然后ret.group(1)拿到第一个分组结果,

因此可以看出,分组在正则里面是对多个规则组合在一起进行约束

分组在python中其实是用来在匹配的数据里面含有不想要的数据的时候,用分组来提取想要的数据

默认group()传的是0是拿到所有的匹配结果,加入1是从匹配结果里面拿到第一个分组里面的内容

import re
s= "<a>https://www.baidu.com</a>"
#将a标签中间的内容匹配出来
#想要的包含在了不想要的里面
ret = re.search(">(.+)<",s)
#0是所有的结果,是默认值,1则是分组的第一个
print(ret.group())#>https://www.baidu.com< 
print(ret.group(1))#https://www.baidu.com
#这里也引出了爬虫里面的技巧,.*?x将不想要的信息,全部用.*?来匹配,直至找到想要的信息前,用精确的字符x定位到,然后后面就是分组信息,然后把想要的数据提取出来

1.3match()

必须从头开始匹配,相当于正则表达式中隐藏了开头的$,最好别用,就用search(),在里面显示的加$表示从头匹配

1.4使用正则处理字符串,用的不多

import re
s= "lsjdfj3lkj1s3lf"
#按正则切割字符串放入列表
#如果正则加了分组,那么就会把切掉的内容放回原来的地方
ret = re.split("\d",s)
print(ret)
ret = re.split("(\d)",s)
print("加了分组",ret)
#sub使用正则替换,默认替换所有,count控制替换个数
ret = re.sub("\d","你好",s,count=1)
print(ret)
##subn,贴心的给你结果,和替换了几次
ret = re.subn("\d","你好",s,count=1)
print(ret) 
ret=re.split("\d+","eva3egon4yuan")
print(ret) #结果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。

1.5compile()

用户多了之后每次调用都需要将正则表达式编译一次,因为正则定了之后就基本不会变化了,所以可以一次编译,多次被调用

com_pattern = re.compile(r"\d+?")
#编译之后的结果,可以调用re模块中的方法
#因为直接调用re模块中的方法,是调用方法的时候编译,compile只是将编译提前了而已 ret
= com_pattern.findall("198h2o34n2) print(ret)

1.6finditer()返回一个迭代器,装有查询结果

每一个迭代的元素就是search的结果

#####finditer节省空间,不会像findall一样将所有结果一次性放入内存
import re
#对findall的优化,几千万的结果,慢慢放入内存,是一个迭代器
ret = re.finditer("\d+","laj1232134lsjf234")
print(ret)
for i in ret:
   print(i)
print(i.group())
#######输出结果
<callable_iterator object at 0x0000022CB4F80828>
<re.Match object; span=(3, 10), match='1232134'>
1232134
<re.Match object; span=(14, 17), match='234'>
234

findall拆解步骤

1.先finditer拿到迭代器

2.遍历迭代器,拿到元素,每个元素调用search()方法拿到Match对象

3.然后调用group()拿到需要的数据,放入列表中.

而我们下面的其他方法只不过是进行了拆解

1.7分组命名

为分组起一个名字,下次group的时候直接就可以用名字作为标识,而不是索引了

ret = re.search(">(?P<test>.+)<",s)
print("test",ret.group("test"))
#使用了分组之后就可以判断标签是否匹配
#前面的分组是一个名字,和后面的分组匹配到的值不一致就会是None
s="<a>https://www.baidu.com</b>"
#第一个分组起名为test,后面可以直接使用这个分组的名字,标识和前面的匹配结果必须相同,不相同就是没有匹配上 pattern = "<(?P<test>\w+)>(.+)</(?P=test)>" ret = re.search(pattern,s) print("分组命名,判断标签匹配",ret)

 2.爬虫实例

爬虫基本步骤:

1.发出请求:自带urllib模块,后期用requests更加方便,文件头等字段更加形象的模拟浏览器行为

2.获得响应:

3.提取数据:re模块加正则

4.存储数据:文件操作,或者数据库操作

 1 import requests
 2 import re
 3 import json
 4 
 5 #从网页获取数据
 6 def get_response(url):
 7     resp = requests.get(url)
 8     return resp.text
 9 
10 def parse_data(data):
11     pattern = '<div class="item">.*?<em.*?>(?P<id>\d+).*?<span.*?>(?P<title>.*?)</span>.*?<span class="rating_num".*?>(?P<score>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>'
12     compiled = re.compile(pattern,re.S)
13     result = compiled.finditer(data)
14     for i in result:
15         #循环一次拿到一个网页里面的所有电影信息,存放到一个字典中
16         #一个网页会产生10个字典
17         yield {
18             "id":i.group("id"),
19             "title":i.group("title"),
20             "score":i.group("score"),
21             "comment_num":i.group("comment_num")
22         }
23 
24 #构造url
25 def main(num):
26     url = "https://movie.douban.com/top250?start=%s&filter="%num
27     data = get_response(url)
28     #拿到一个网页10个字典信息
29     msgs = parse_data(data)
30     with open("top250.info","a",encoding="utf8") as f:
31         for msg in msgs:
32             print(msg)
33             str_msg = json.dumps(msg,ensure_ascii=False)
34             f.write(str_msg+"\n")
35 
36 if __name__ == "__main__":
37     count = 0
38     for i in range(10):
39         main(count)
40         count+=25
View Code

 

posted @ 2019-09-30 15:31  浅忆尘  阅读(82)  评论(0)    收藏  举报