Python利用re正则表达式抓取豆瓣电影Top250排行榜
利用request和re来抓取电影排行榜的电影名称,电影年份,电影评分以及评价人数并写为.csv格式文件
先来介绍一下re模块中的几个简单常用的方法
re模块
几个简单功能
1. findall
# findall :匹配字符串中所有符合正则的内容import reresult = re.findall(r"\d+", "你好我的电话是123456,他的电话是654321")print(result)>>>['123456', '654321']
2. finditer
# finditer :匹配字符串中所有的内容(返回迭代器)result2 = re.finditer(r"\d+", "你好我的电话是123456,他的电话是654321")for i in result2:#从迭代器中取数据print(i) >>><re.Match object; span=(7, 13), match='123456'>>>><re.Match object; span=(19, 25), match='654321'>for i in result2:#从迭代器中取数据print(i.group()) #使用group()方法直接输出match到的数据>>>123456>>>654321
3.search
#search 只要找到一个结果就返回match对象,需要使用group()方法取数据result3 = re.search(r"\d+", "你好我的电话是123456,他的电话是654321")print(result3.group())>>>123456print(result3.group())>>>123456#不会继续往后找
4.match
#match 从头开始匹配,相当于默认在正则表达式前面加了"^"result3 = re.match(r"\d+", "你好我的电话是123456,他的电话是654321")print(result3.group()) #报错,数据为空
5.预加载正则表达式
在需要多次使用正则表达式时,为了提高执行效率,可以对正则表达式进行预加载。
#预加载正则表达式obj = pile(r"正则表达式")#使用方式result = obj.finditer("你好我的电话是123456,他的电话是654321")for i in result2:#从迭代器中取数据print(i.group()) #使用group()方法直接输出match到的数据
步骤
拿到页面源代码——>requests
通过re以及正则来提取有效信息——>re
代码
import requests #导入请求包import re #正则url = "/top250"#添加User-Agentheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"}resp = requests.get(url, headers=headers) #获取响应数据page_content = resp.text #提取源代码#解析数据obj = pile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>.*?<p class="">.*?<br>.*?(?P<year>.*?) .*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?<span>(?P<people>.*?)人评价</span>', re.S) #书写正则表达式(关键在于寻找定位标签) result = obj.finditer(page_content)#利用正则来提取数据,将电影名称存放在name组,年份存在year组,评分存在score组,评价人数存在people组(返回迭代器)for i in result:print(i.group("name"))print(i.group("year").strip())#去除year的多余空格print(i.group("score"))print(i.group("people"))print("Over!")
改进
上面的例子我们抓取到了该页面上的数据,但是无法获得下一页的数据。在对下一页的网页地址观察发现,页数的跳转其实就url中某个参数的变化,而且是有规律的变化,以本例来看,第二页的网址为“/top250?start=25&filter=”,第三页的网址为“/top250?start=50&filter=”.就是start=后面的参数发生变化,而且每跳转一页,参数加25.
随后我们可以将参数设为一个变量,并且在抓取完每一个页面后值叠加25,跳转到下一页。接下来以抓取10页为例,并将数据写为.csv格式文件
import requests #导入请求包import re #正则import csv #导入scv模块用于数据读写index = 0#页面跳转参数f = open("data.csv", mode="a", newline='') #新建并打开名为data.csv的文件用于写入数据while index <= 250: #将页面限定为前十页url = f"/top250?start={index}&filter=" #将页面按数据拼接到url中#添加User-Agentheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"}resp = requests.get(url, headers=headers) #获取响应page_content = resp.text #提取源代码obj = pile(r'<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)'r'</span>.*?<p class="">.*?<br>.*?(?P<year>.*?) .*?<span class="rating_num" property="v:average"'r'>(?P<score>.*?)</span>.*?<span>(?P<people>.*?)人评价</span>', re.S) #书写正则表达式(关键在于寻找定位标签) result = obj.finditer(page_content)#利用正则来提取数据,将电影名称存放在name组,年份存在year组,评分存在score组,评价人数存在people组(返回迭代器)csvwriter = csv.writer(f)for i in result:dic = i.groupdict()#将result中的数据转为字典格式dic['year'] = dic['year'].strip() #去除year的多余空格csvwriter.writerow(dic.values()) #数据写入index = index + 25#参数值叠加,实现页面跳转print(f"over!{index/25}")f.close()
效果:
完成!