Python利用re正则表达式抓取豆瓣电影Top250排行榜
利用request和re来抓取电影排行榜的电影名称,电影年份,电影评分以及评价人数并写为.csv格式文件
先来介绍一下re模块中的几个简单常用的方法
re模块
几个简单功能
1. findall
# findall :匹配字符串中所有符合正则的内容
import re
result = 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())
>>>123456
print(result3.group())
>>>123456#不会继续往后找
4.match
#match 从头开始匹配,相当于默认在正则表达式前面加了"^"
result3 = re.match(r"\d+", "你好我的电话是123456,他的电话是654321")
print(result3.group()) #报错,数据为空
5.预加载正则表达式
在需要多次使用正则表达式时,为了提高执行效率,可以对正则表达式进行预加载。
#预加载正则表达式
obj = re.compile(r"正则表达式")
#使用方式
result = obj.finditer("你好我的电话是123456,他的电话是654321")
for i in result2:#从迭代器中取数据
print(i.group()) #使用group()方法直接输出match到的数据
步骤
-
拿到页面源代码——>requests
-
通过re以及正则来提取有效信息——>re
代码
import requests #导入请求包
import re #正则
url = "https://movie.douban.com/top250"
#添加User-Agent
headers = {
"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 = re.compile(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中某个参数的变化,而且是有规律的变化,以本例来看,第二页的网址为“https://movie.douban.com/top250?start=25&filter=”,第三页的网址为“https://movie.douban.com/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"https://movie.douban.com/top250?start={index}&filter=" #将页面按数据拼接到url中
#添加User-Agent
headers = {
"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 = re.compile(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()
效果:
完成!