目的:运用正则表达式解决问题
思路:
1、运用request模块获取到豆瓣电影页面的代码
2、编写正则表达式,提取页面数据
3、保存数据
第一步:导包
import requests import re
第二步:指定url
url = "https://movie.douban.com/top250"
第三步:进行UA伪装(此处代码没打全,要全部复制的)
headers = { 'User-Agent': 'Mozilla/5.0' }
第四步:请求发送
response = requests .get(url=url,headers=header) pageSource = response.text
第五步:编写正则表达式(使用的是预加载:即提前把正则对象加载完毕)
#使用re模块中的compile函数
#re.S 可以让正则中的 . 匹配换行符
由爬取的代码可知:每个电影的是封装在<div class="item">这个盒子里面的,下图只截取其中一个电影的具体代码。数据抓取我们只需要电影名称、导演、评分、年代和评分、评分人数。
①从<div class="item">到<span class="title">中间的信息是不需要的,所以我们使用非贪婪表达式:.*? 表示,即代码中的:
<div class="item">.*?<span class="title">
② <span class="title">肖申克的救赎</span>,中间的肖申克的救赎是我们所需要的,故我们使用: .*?将内容囊括后,因为需要将数据完整提取出来就必须用小括号括起来,并单独起名字,形式为: # (?P<名字>正则),即代码中的:
<span class="title">(?P<name>.*?)</span>
③ 后续就和前两步的道理一致,具体代码如下:
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</span>'
r'.*?<p class="">.*?导演:(?P<dao>.*?) .*?<br>'
r'(?P<year>.*?) .*?<span class="rating_num" property="v:average">'
r'(?P<score>.*?)</span>'
r'.*?<span>(?P<num>.*?)人评价</span>',re.S)
注意:正则中的代码还是复制粘贴原网站的好
第六步:进行正则匹配(直接把加载好的正则进行使用)
result = obj.finditer(pageSource) for item in result: name = item.group("name") dao = item.group("dao") year = item.group("year").strip() #去掉字符串左右两端的空白 score = item.group("score") num = item.group("num")
第七步:保存文件
fp = open("抓取豆瓣电影Top250.csv", mode='w', encoding="UTF-8") fp.write(f"{name},{dao},{ year},{score},{num}\n")
第八步:进行翻页提取数据
点击第2页会发现,顶部的网址发生改变,如下图:
页面1 :start = 0
页面2 :start = 25
页面3 :start = 50
即页面1获取1-25个电影数据(1*25),页面2获取从26-50个页面数据(2*25),页面3获取从51-75(3*25),每一页获取25个电影数据,代码:start=page * 25,使用for循环,获取每一页25个电影数据,将每一页获取到的电影数据存放在一个文件中就大功告成咯~,所以这时的url需要进行重新赋值,代码如下:
for page in range(250):
url = (f"https://movie.douban.com/top250?start={page * 25}&filter=")
print(f'第{page+1}页获取成功')
完整代码如下:
import requests
import re
if __name__ == '__main__':
fp = open("抓取豆瓣电影Top250.csv", mode='w', encoding="UTF-8")
url = "https://movie.douban.com/top250"
header = {
'User-Agent' : "Mozilla/5.0 #此处代码没打完整
}
for page in range(250):
url = (f"https://movie.douban.com/top250?start={page * 25}&filter=")
print(f'第{page+1}页获取成功')
response = requests .get(url=url,headers=header)
pageSource = response.text
#编写正则表达式
#re.S 可以让正则中的 . 匹配换行符
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</span>'
r'.*?<p class="">.*?导演:(?P<dao>.*?) .*?<br>'
r'(?P<year>.*?) .*?<span class="rating_num" property="v:average">'
r'(?P<score>.*?)</span>'
r'.*?<span>(?P<num>.*?)人评价</span>',re.S)
#进行正则匹配
result = obj.finditer(pageSource)
for item in result:
name = item.group("name")
dao = item.group("dao")
year = item.group("year").strip() #去掉字符串左右两端的空白
score = item.group("score")
num = item.group("num")
#保存文件
fp.write(f"{name},{dao},{ year},{score},{num}\n")
fp.close()
response.close()
print("豆瓣Top250提取完毕")