按实现思路,分步骤完成爬取工作:
1.获取页面源代码
url = "https://movie.douban.com/top250"
head = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'}
resp = requests.get(url, headers=head)
resp.encoding = 'utf-8'
2.开展正则匹配工作[难点]
本次计划获得的信息包括:电影名称、上映年份、打分、评分人数。
上述4项信息在页面源代码的哪个位置呢?来分析一下:
蓝色框体部分是一部电影在页面上的完整信息,我们想要提取的内容出现在了红框区域。
下面就要开始拼接正则表达式了!
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)'
r'</span>.*?<br>(?P<year>.*?) .*?'
r'<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?'
r'<span>(?P<num>.*?)人评价</span>')
然后直接运行:
result = obj.finditer(resp.text)
继续打印,会发现没抓到内容。主要原因在于正则表达式中“.”的匹配逻辑:除了换行符以外的一切东西都可以,除了换行符!
但是页面源代码里面是有换行符的,所以就走不通了。
好在python早就预判了这个问题,在obj.compile中增加re.S,就可以让“.”匹配到换行符。
代码修改如下:
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)'
r'</span>.*?<br>(?P<year>.*?) .*?'
r'<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?'
r'<span>(?P<num>.*?)人评价</span>', re.S)
result = obj.finditer(resp.text)
现在没问题了!
3.问题数据处理
直接对result进行输出,会发现“年份”信息里存了很多空格,得想办法删掉。
for item in result:
dic = item.groupdict()
dic['year'] = dic['year'].strip()
使用.strip()可以把左右两端的空格都删除。
4.拿到其它页面的信息
再次打印,这回没问题了。
等等,为什么只有25部电影的信息?
——因为目前抓取的只是第一页,只有最前面25部啊。
想解决也非常简单。切换到下一页后,可以发现网址变成了:
https://movie.douban.com/top250?start=25&filter=
页数就藏在“start=25”中。只要写个小函数,把10个网页遍历一遍就可以了:
for i in range(1, 11):
page = (i - 1) * 25
url = f"https://movie.douban.com/top250?start={page}&filter="
5.把获取的信息存到文件中
这一步也很简单,创建一个txt,把每页提取并清理好的数据写入进去就可以了:
f = open('top250.txt','w',encoding='utf-8')
......
for item in result:
dic = item.groupdict()
dic['year'] = dic['year'].strip() # 去掉年份左右两端的空白
f.write(str(dic)+'\n')
f.close()