1.导入所需的模块

要完成本次任务,我们需要导入requests来获取对应网址的数据,导入re利用正则表达式来截取所需的数据(例如电影名,评分以及评分人数等),导入prettytable来格式化输出,导入csv模块将数据写入csv文件中。具体导入模块代码如下所示:

import requests
import re
import prettytable as pd
import csv

在这里插入图片描述

2.明确链接分页的规律

由于我们使用requests一次只能请求一页的排行榜数据,一页一共有25条电影的数据,而我们要获取Top250的数据,所以一共要获取10页的数据。因为我们要发现其分页的规律,从而来使用循环来自动获取每一页的数据并写入文件。通过点击对应页数的链接,便可以很轻松发现其中的规律,具体每一页的网址链接情况如下所示
在这里插入图片描述

因此,我们可以使用一个for循环便可以实现依次访问每一页的链接数据,具体如下所示:

for i in range(10):
	url = 'https://movie.douban.com/top250?start='+str(25*i)+'&filter='
	headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36'
    }
    response = requests.get(url, headers=headers)

3.编写正则表达式截取所需的信息

正如下图所示,我们需要的是电影名,电影年份,电影评分以及电影评分人数,在对应的网址页面按下F12或者直接右键点击检查打开开发者工具,选择下图所示的图标后,然后点击需要爬取的信息内容,这样我们就可以在众多冗余的代码中找到我们所需要的信息所在的位置。
在这里插入图片描述

找到对应信息所在的位置后,我们就可以根据其层级关系来编写正则表达式获取所需要的内容了。具体编写的正则表达式代码如下所示:

p = re.compile(r'<li>.*?<span class="title">(?P<name>.*?)</span>.*?<br>(?P<year>.*?)&nbsp;'
                   r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>'
                   r'.*?<span>(?P<num>.*?)</span>', re.S)
for it in p.finditer(response.text):
	print(it.group('name'))
	print(it.group('year'))
	print(it.group('score'))
	print(it.group('num'))

这里需要注意,编写正则表达式需要注意大小写,如果不想注意大小写,我们可以设置re.I使得对大小写不敏感,compile()函数的第二个参数是设置一些可选标志修饰符来控制匹配的模式,修饰符被指定为一个可选的标志,多个标志可以通过按位OR(|)来指定,如(re.I)|(re.M)被设置为I和M标志。具体修饰符以及描述如下表所示:

修饰符描述
re.Ire.I 使匹配对大小写不敏感
re.L做本地化识别(locale-aware)匹配
re.Mre.M 多行匹配,影响 ^ 和 $
re.Sre.S 使 . 匹配包括换行在内的所有字符
re.Ure.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

4.使用prettytable格式化输出

这一部分知识锦上添花的作用,并无实际作用,可以作为拓展知识学习,如果不敢兴趣可以直接跳过!这一部分就相当于是把通过正则表达式截取的数据,使用prettytable做到格式化输出,使得输出效果更好,具体操作代码如下所示:

# 格式化输出
    table = pd.PrettyTable()
    # 设置表头
    table.field_names = ['电影名', '年份', '评分', '评分人数']
    for it in p.finditer(response.text):
        # 添加表数据
        table.add_row([it.group('name'), it.group('year').strip(), it.group('score'), it.group('num')])
    print(table)

运行效果如下所示:
在这里插入图片描述

5.保存数据到csv文件

这一部分代码比较简单,就不做过多的赘述,主要就是打开文件代码如下所示:

# 以追加的形式打开文件对象
	f = open('data.csv', mode='a')
    csv_write = csv.writer(f)
    for it in p.finditer(response.text):
        # 将迭代器it转换为字典
        dic = it.groupdict()
        # 对键为year的值去除空格
        dic['year'] = dic['year'].strip()
        # 将字典的values写入data.csv
        csv_write.writerow(dic.values())
    print('写入完成')

这里需要注意,如果写入csv的文件在PyCharm不能正常展示,我们可以去下载一个CSV插件,这里就可以在PyCharm中正常显示数据了。具体操作步骤如下所示:
鼠标选择文件,点击下面的设置
在这里插入图片描述
打开设置,出现下面的界面后,选择插件,在搜索框中输入CSV,在下面出现的插件中选择正确的CSV阅读器,点击安装最后重启即可。
在这里插入图片描述

6.展示完整代码

import requests
import re
import prettytable as pd
import csv
for i in range(10):
    # 评分排行榜的网址
    url = 'https://movie.douban.com/top250?start='+str(25*i)+'&filter='
    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    result = response.text
    p = re.compile(r'<li>.*?<span class="title">(?P<name>.*?)</span>.*?<br>(?P<year>.*?)&nbsp;'
                   r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>'
                   r'.*?<span>(?P<num>.*?)</span>', re.S)
    # 格式化输出
    table = pd.PrettyTable()
    # 设置表头
    table.field_names = ['电影名', '年份', '评分', '评分人数']
    for it in p.finditer(result):
        # 添加表数据
        table.add_row([it.group('name'), it.group('year').strip(), it.group('score'), it.group('num')])
    print(table)
    # 以追加的形式打开文件
    f = open('data.csv', mode='a')
    csv_write = csv.writer(f)
    for it in p.finditer(result):
        # 将迭代器it转换为字典
        dic = it.groupdict()
        dic['year'] = dic['year'].strip()
        csv_write.writerow(dic.values())
    print('写入完成')

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐