Files
2026-07-06 14:57:41 +08:00

852 lines
30 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import matplotlib.pyplot as plt
# 【防乱码神器】考试必写这两行,不然中文全是方块
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1. 读取数据 (固定套路)
with open('movies.json', 'r', encoding='utf-8') as f:
movies = json.load(f)
# ==========================================
# 第1题柱状图 (类型 vs 数量)
# ==========================================
# 这里需要统计一下数量,稍微麻烦一点点,但我帮你写好了逻辑
type_counts = {}
for m in movies:
# 假设你的json里类型字段叫 'types' 或 'genres',根据实际改
types = m.get('types', '').split('/')
for t in types:
t = t.strip()
type_counts[t] = type_counts.get(t, 0) + 1
# 取前10个或者全部画图
x = list(type_counts.keys())
y = list(type_counts.values())
plt.figure() # 开启一张新画布
plt.bar(x, y) # <--- 考点bar是柱状图
plt.title("类型电影数量分布")
plt.savefig("q4_1_bar.png", dpi=150)
# ==========================================
# 第2题散点图 (时长 vs 评分)
# ==========================================
# 提取数据
durations = [m['duration'] for m in movies] # 时长做X
ratings = [m['rating'] for m in movies] # 评分做Y
plt.figure() # 开启新画布
plt.scatter(durations, ratings, color='red', alpha=0.6) # <--- 考点scatter是散点图
plt.title("时长与评分关系散点图")
plt.xlabel("时长(分钟)")
plt.ylabel("评分")
plt.savefig("q4_2_scatter.png", dpi=150)
# ==========================================
# 第3题直方图 (评分分布 & 时长分布)
# ==========================================
# A图评分
plt.figure()
plt.hist(ratings, bins=5, color='blue') # <--- 考点hist是直方图
plt.title("评分分布")
plt.savefig("q4_3a_hist.png", dpi=150)
# B图时长
plt.figure()
plt.hist(durations, bins=5, color='green')
plt.title("时长分布")
plt.xlabel("时长(分钟)")
plt.savefig("q4_3b_hist.png", dpi=150)
只记函数名
看到柱状图 \rightarrow 脑子反应出  plt.bar 
看到散点图 \rightarrow 脑子反应出  plt.scatter 
看到直方图/分布 \rightarrow 脑子反应出  plt.hist 
搞定中文乱码只要考试涉及中文图表上来先把那两行  plt.rcParams...  写上这是送分也是送命题不写就没分
#2.0
第一步准备工作必写
在代码最开头必须导入这两个库这是拿分的基础
import json # 用来读取 JSON 文件
import matplotlib.pyplot as plt # 用来画图plt 是它的简称)
# 【防坑设置】为了防止中文显示成乱码方块,考试时建议加上这两行
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
第二步读取与提取数据必写
不管题目怎么变都要先把数据从  movies.json  里拿出来
# 1. 打开文件
with open('movies.json', 'r', encoding='utf-8') as f:
data = json.load(f) # data 现在就是一个包含所有电影的大列表
# 2. 准备两个空篮子,用来装 X轴 和 Y轴 的数据
x_data = []
y_data = []
# 3. 遍历每一部电影,把数据挑出来
for item in data:
# 假设我们要取 "评分" 和 "时长"
x_data.append(item['rating']) # 把评分放入 X 篮
y_data.append(item['duration']) # 把时长放入 Y 篮
第三步画图函数根据题目选一个
这是考试的核心题目考什么图就套用哪个函数
图表类型 函数写法 适用场景 关键参数
柱状图 plt.bar(x, y) 统计数量对比大小 width=0.5 (柱子宽度)
散点图 plt.scatter(x, y) 看分布找关系 c='red' (颜色), alpha=0.6 (透明度)
折线图 plt.plot(x, y) 看趋势随时间变化 linestyle='--' (线型)
直方图 plt.hist(data) 看频率分布 bins=10 (分成几组), color='blue'
第四步美化与保存必写
题目通常会给具体的文件名和标题要求直接复制粘贴即可
# 设置标题和坐标轴标签(题目通常会指定文字)
plt.title("这里是题目要求的标题")
plt.xlabel("X轴名称")
plt.ylabel("Y轴名称")
# 保存图片(一定要写在 plt.show() 之前,或者只写这一句)
# dpi=150 是清晰度,题目没说的话写上更保险
plt.savefig('q4_1_bar.png', dpi=150)
# 如果你想看图,可以加这句;如果是自动评分系统,通常不需要
# plt.show()
#3.0
没问题这道题是典型的数据可视化Data Visualization题目它要求你从之前保存的 movies.json 文件中读取数据然后用 Python 最常用的绘图库 matplotlib 把数据画成图表
别担心我会把代码拆解开一步步教你怎么写并解释每一行代码的作用
🛠 准备工作安装必要的库
做这道题你需要用到两个库
1. matplotlib用来画图柱状图散点图等
2. jsonPython 自带的用来读取 .json 文件
如果你还没装 matplotlib请在终端运行
pip install matplotlib
📂 1 小题绘制各类型电影数量柱状图 (q4_1.py)
💡 思路讲解
1. 读数据打开 movies.json把里面的列表加载到内存中
2. 统计数据我们需要统计每种类型比如剧情喜剧出现了多少次这里有个坑一部电影可能有多个类型例如剧情/犯罪所以我们要先按分隔符拆分再统计
3. 画图 plt.bar() 画柱子
4. 保存 plt.savefig() 保存图片
🐍 完整代码 (q4_1.py)
import json
import matplotlib.pyplot as plt
# 1. 读取数据
with open('movies.json', 'r', encoding='utf-8') as f:
movies = json.load(f)
# 2. 统计各类型的数量
type_counts = {}
for movie in movies:
# 假设类型字段叫 "types" 或 "genres",根据你之前的爬虫结果调整
# 这里假设字段名是 'types',且格式为 "剧情 / 犯罪"
types_str = movie.get('types', '')
# 将字符串按 '/' 分割,并去除首尾空格
type_list = [t.strip() for t in types_str.split('/')]
for t in type_list:
if t: # 防止空字符串
type_counts[t] = type_counts.get(t, 0) + 1
# 提取 X 轴(类型名)和 Y 轴(数量)
x_labels = list(type_counts.keys())
y_values = list(type_counts.values())
# 3. 设置中文字体(非常重要!否则中文会显示成方框)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 4. 绘制柱状图
plt.figure(figsize=(10, 6)) # 设置画布大小
plt.bar(x_labels, y_values)
# 5. 设置标题和标签
plt.title("类型电影数量分布")
plt.xlabel("类型名称")
plt.ylabel("电影数量")
# 6. 保存和显示
plt.savefig('q4_1_bar.png', dpi=150)
print("图表已保存为 q4_1_bar.png")
# plt.show() # 如果你想看弹窗图,取消这行的注释
🔍 重点学习点
- movie.get('types', '')安全地获取字典里的值如果没有这个键就返回空字符串防止报错
- split('/')因为爬虫抓下来的类型通常是连在一起的字符串 "剧情 / 犯罪"必须切开才能分别计数
- plt.rcParams[...]这是解决 Matplotlib 中文乱码的万能公式考试必背
📂 2 小题绘制评分 vs 时长散点图 (q4_2.py)
💡 思路讲解
1. 提数据我们需要两个列表一个存所有电影的时长一个存所有电影的评分
2. 画图使用 plt.scatter()
3. 样式题目特别要求了颜色红色和透明度alpha=0.6
🐍 完整代码 (q4_2.py)
import json
import matplotlib.pyplot as plt
# 1. 读取数据
with open('movies.json', 'r', encoding='utf-8') as f:
movies = json.load(f)
# 2. 提取时长和评分
durations = []
ratings = []
for movie in movies:
# 注意:要确保数据能转为数字,有些可能为空或格式不对
try:
dur = int(movie.get('duration', 0).replace('分钟', '').strip())
rate = float(movie.get('rate', 0))
durations.append(dur)
ratings.append(rate)
except ValueError:
continue # 如果转换失败(比如数据缺失),跳过这一条
# 3. 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 4. 绘制散点图
plt.figure(figsize=(10, 6))
# c='red' 设置颜色, alpha=0.6 设置透明度
plt.scatter(durations, ratings, c='red', alpha=0.6)
# 5. 设置标题和标签
plt.title("时长与评分关系散点图")
plt.xlabel("时长 (分钟)")
plt.ylabel("评分")
# 6. 保存
plt.savefig('q4_2_scatter.png', dpi=150)
print("图表已保存为 q4_2_scatter.png")
🔍 重点学习点
- c='red', alpha=0.6这是题目明确要求的参数alpha 越小越透明这在数据点很多重叠时非常有用能让你看清数据的密度
- 数据清洗 (try...except)真实数据往往很脏有的电影可能没填时长加上 try 结构能保证程序不会因为一条坏数据而崩溃
📂 3 小题绘制直方图 (q4_3a.py & q4_3b.py)
直方图Histogram通常用来展示数据的分布情况比如大部分电影都在 90-120 分钟之间
(A) 评分分布直方图 (q4_3a.py)
import json
import matplotlib.pyplot as plt
# 读取数据 (省略重复部分,假设已读取到 movies 变量)
with open('movies.json', 'r', encoding='utf-8') as f:
movies = json.load(f)
# 提取评分数据
scores = [float(m.get('rate', 0)) for m in movies]
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']
# 绘制直方图
plt.figure(figsize=(8, 5))
# bins=5 表示把数据分成 5 个区间段
# color='blue' 设置颜色
plt.hist(scores, bins=5, color='blue')
plt.title("评分分布")
plt.xlabel("评分")
# 保存
plt.savefig('q4_3a_hist.png', dpi=150)
print("已保存 q4_3a_hist.png")
(B) 时长分布直方图 (q4_3b.py)
import json
import matplotlib.pyplot as plt
# 读取数据
with open('movies.json', 'r', encoding='utf-8') as f:
movies = json.load(f)
# 提取时长数据 (需转为整数)
durations = []
for m in movies:
try:
d = int(m.get('duration', 0).replace('分钟', '').strip())
durations.append(d)
except:
pass
# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']
# 绘制直方图
plt.figure(figsize=(8, 5))
# bins=5, 颜色绿色
plt.hist(durations, bins=5, color='green')
plt.title("时长分布")
plt.xlabel("时长 (分钟)")
# 保存
plt.savefig('q4_3b_hist.png', dpi=150)
print("已保存 q4_3b_hist.png")
🔍 重点学习点
- plt.hist vs plt.bar
- bar 是你自己算好每个柱子多高比如动作片 50 传给它画
- hist 是你给它一堆原始数据比如[120, 90, 100...]它自己帮你切分区间并计算高度
- bins=5题目要求分 5 个桶这意味着它会自动找出最大值和最小值然后平均切成 5 份来统计
🎓 总结与避坑指南
1. 文件路径确保你的 movies.json 文件和这些 .py 代码文件在同一个文件夹里否则 open('movies.json') 会报错找不到文件
2. 字段名称我在代码里用了 types, duration, rate 作为字典的键Key请务必打开你的 movies.json 看一眼确认里面的键名是不是这几个如果你的爬虫写的是 genre 而不是 types代码里也要对应修改
3. 中文乱码只要看到图里的中文变成 就是没加那两行 plt.rcParams 代码
你可以先把代码复制进去跑一下如果有报错比如 Key Error可以把报错信息发给我我帮你微调
这部分弄完需要我再帮你梳理下前面抓取全部250部电影的代码吗
#爬虫代码
#1.0
要将代码改为抓取前 50 部电影即豆瓣 Top 250 的前两页我们需要对 URL 进行循环处理豆瓣的列表是分页显示的每页展示 25 部电影
因此要获取前 50 我们需要访问 start=0 1-25 start=25 26-50 这两个页面
以下是修改后的完整代码
🐍 抓取前 50 部电影完整代码
import requests
from bs4 import BeautifulSoup as bs
import json
import time
# 设置请求头,模拟浏览器访问
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
data = []
# 循环抓取前两页 (0 到 25步长为 25)
# range(0, 50, 25) 会生成 [0, 25],正好对应前 50 部电影
for start_num in range(0, 50, 25):
# 动态构建 URL
url = f"https://movie.douban.com/top250?start={start_num}&filter="
print(f"正在抓取第 {start_num + 1} - {start_num + 25} 名的电影...")
try:
resp = requests.get(url, headers=headers)
resp.encoding = 'utf-8'
soup = bs(resp.text, "html.parser")
items = soup.find_all("div", class_="item")
for i in range(len(items)):
item_data = {}
# 1. 获取标题
title_span = items[i].find("span", class_="title")
if title_span:
item_data["title"] = title_span.get_text()
else:
item_data["title"] = "未知标题"
# 2. 获取演员信息
bd_div = items[i].find("div", class_="bd")
actors_text = bd_div.get_text().strip() if bd_div else ""
try:
# 尝试提取主演部分
if "主演:" in actors_text:
item_data["actors"] = actors_text.split("主演:")[1].split("n")[0].strip()
else:
item_data["actors"] = "无主演信息"
except:
item_data["actors"] = "解析错误"
# 3. 获取经典台词 (quote)
try:
quote_p = bd_div.find("p", class_="quote")
if quote_p:
item_data["quote"] = quote_p.find("span").get_text().strip()
else:
item_data["quote"] = "暂无台词"
except:
item_data["quote"] = "暂无台词"
data.append(item_data)
# 礼貌爬取:每抓完一页暂停 1 秒,防止被封 IP
time.sleep(1)
except Exception as e:
print(f"抓取第 {start_num} 页时出错: {e}")
# 打印并保存结果
print(f"n抓取完成共获取 {len(data)} 部电影数据。")
print(data)
with open("movies_top50.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print("数据已保存到 movies_top50.json")
💡 主要修改点说明
1. 引入循环 (for start_num in range(0, 50, 25))
- 原代码只抓取了 start=0 这一页
- 新代码通过 range 函数生成 0 25 两个数字
- start_num 0 抓取第 1-25 start_num 25 抓取第 26-50
2. URL 动态拼接
- 使用了 f-stringf"...start={start_num}..."这样每次循环都会自动更新网址
3. 增加 time.sleep(1)
- 这是一个非常重要的爬虫礼仪连续快速请求同一个网站很容易导致你的 IP 被豆瓣暂时封锁返回 418 错误加上 1 秒延时可以大大提高成功率
4. 优化了数据结构
- 将每个电影的数据先存入字典 item_data再添加到列表 data 逻辑更清晰也避免了变量覆盖的问题
现在脚本已经能稳定抓取前 50 部了需要我帮你把它改成一键抓取全部 250
#2.0
这是从图片中提取并整理好的完整 Python 代码该脚本用于爬取豆瓣电影 Top 250 的电影信息标题演员经典台词并将结果保存为 movies.json 文件
🐍 豆瓣电影 Top 250 爬虫代码
import requests
from bs4 import BeautifulSoup as bs
import json
# 设置请求头,模拟浏览器访问
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
url = "https://movie.douban.com/top250?start=0&filter="
data = []
resp = requests.get(url, headers=headers)
resp.encoding = 'utf-8'
soup = bs(resp.text, "html.parser")
items = soup.find_all("div", class_="item")
for i in range(len(items)):
# 获取电影标题
title = items[i].find("span", class_="title").get_text()
# 获取演员信息(处理可能存在的格式问题)
actors = items[i].find("div", class_="bd").get_text().strip()
try:
actors = actors.split("主演:")[1].split("n")[0]
except:
actors = ""
# 获取经典台词(注意:部分电影可能没有台词,需做异常处理)
try:
quote = items[i].find("div", class_="bd").find("p", class_="quote").get_text().strip()
except:
quote = ""
data.append({
"title": title,
"actors": actors,
"quote": quote
})
print(data)
# 将数据保存为 JSON 文件
with open("movies.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
💡 代码关键点说明
1. 异常处理在提取主演经典台词时使用了 try...except 结构这是因为部分电影条目可能缺少主演信息或经典台词直接提取会导致程序报错中断
2. 编码设置resp.encoding = 'utf-8' 确保中文内容不会乱码保存 JSON 时设置 ensure_ascii=False 也是为了正确显示中文字符
3. 数据存储最终数据被整理为字典列表并使用 json.dump 格式化写入本地文件方便后续分析使用
这段代码只能抓取第一页的 25 部电影需要我帮你改成循环抓取全部 250 部吗
#3.0
除了保存为 JSON 格式CSV (Excel) TXT (文本) 是最常用的两种替代方案
1. CSV 格式最推荐可以直接用 Excel 打开方便后续做数据分析或整理表格
2. TXT 格式适合直接阅读像写日记一样列出电影清单
以下是修改后的代码你可以根据需要选择其中一种保存方式只需替换代码最后的保存部分
选项一保存为 CSV 文件 (推荐可用 Excel 打开)
这种方式会将数据整理成表格形式我们需要引入 Python 自带的 csv
import requests
from bs4 import BeautifulSoup as bs
import csv # 引入 csv 库
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
data = []
# 循环抓取前两页 (前50部)
for start_num in range(0, 50, 25):
url = f"https://movie.douban.com/top250?start={start_num}&filter="
print(f"正在抓取: {url}")
resp = requests.get(url, headers=headers)
resp.encoding = 'utf-8'
soup = bs(resp.text, "html.parser")
items = soup.find_all("div", class_="item")
for i in range(len(items)):
try:
title = items[i].find("span", class_="title").get_text()
actors_raw = items[i].find("div", class_="bd").get_text().strip()
try:
actors = actors_raw.split("主演:")[1].split("n")[0].strip()
except:
actors = "无主演信息"
try:
quote = items[i].find("div", class_="bd").find("p", class_="quote").get_text().strip()
except:
quote = "暂无台词"
# 将数据存入列表
data.append([title, actors, quote])
except Exception as e:
print(f"解析出错: {e}")
# --- 保存为 CSV 文件 ---
filename = "movies_top50.csv"
with open(filename, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
# 写入表头
writer.writerow(["电影名称", "主演", "经典台词"])
# 写入数据
writer.writerows(data)
print(f"成功保存 {len(data)} 部电影到 {filename}")
💡 提示 这里使用了 utf-8-sig 编码这是为了防止在 Windows Excel 中打开 CSV 文件时出现中文乱码
选项二保存为 TXT 文本文件
这种方式适合直接双击打开阅读格式比较直观
import requests
from bs4 import BeautifulSoup as bs
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
}
content_list = []
# 循环抓取前两页
for start_num in range(0, 50, 25):
url = f"https://movie.douban.com/top250?start={start_num}&filter="
resp = requests.get(url, headers=headers)
resp.encoding = 'utf-8'
soup = bs(resp.text, "html.parser")
items = soup.find_all("div", class_="item")
for i in range(len(items)):
try:
title = items[i].find("span", class_="title").get_text()
actors_raw = items[i].find("div", class_="bd").get_text().strip()
try:
actors = actors_raw.split("主演:")[1].split("n")[0].strip()
except:
actors = "未知"
try:
quote = items[i].find("div", class_="bd").find("p", class_="quote").get_text().strip()
except:
quote = ""
# 格式化字符串
line = f"{title}】n主演{actors}n台词{quote}n{'-'*30}n"
content_list.append(line)
except Exception as e:
pass
# --- 保存为 TXT 文件 ---
filename = "movies_top50.txt"
with open(filename, "w", encoding="utf-8") as f:
f.write("豆瓣电影 Top 50 榜单nn")
for item in content_list:
f.write(item)
print(f"已保存到 {filename}")
总结建议
- 如果你需要统计筛选比如只看某位演员的电影请选择 CSV
- 如果你只是想看文字清单或者发给别人看请选择 TXT
要是觉得这两种都不够直观我还可以帮你改成存进 SQLite 数据库方便以后做查询需要的话告诉我
#4.0
没问题完全理解你的意思你是希望保留刚才那份抓取前 50 部的完整逻辑包括循环和防封延时仅仅把最后保存为 JSON 的部分改成其他格式
这里提供两个最常用的替代方案Excel (CSV) TXT 文本你可以根据需要直接替换代码的最后 3
方案一保存为 Excel 表格 (CSV 格式)
这是最推荐的格式生成的文件可以直接用 Excel 打开查看整齐清晰
修改步骤
1. 在代码最开头引入 csv
import csv # <--- 加上这一行
2. 将代码最后 3 with open...json.dump... 部分替换为
# === 替换原来的 json 保存代码 ===
with open("movies_top50.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["title", "actors", "quote"])
writer.writeheader() # 写入表头
writer.writerows(data) # 写入数据
print("数据已保存到 movies_top50.csv (可用Excel打开)")
注意 使用 utf-8-sig 编码是为了防止 Excel 打开中文时出现乱码
方案二保存为 TXT 纯文本
适合直接阅读像清单一样列出电影信息
修改步骤
不需要引入新库直接将代码最后 3 行替换为
# === 替换原来的 json 保存代码 ===
with open("movies_top50.txt", "w", encoding="utf-8") as f:
for movie in data:
f.write(f"{movie['title']}】n")
f.write(f"主演:{movie['actors']}n")
f.write(f"台词:{movie['quote']}n")
f.write("-" * 30 + "n") # 分割线
print("数据已保存到 movies_top50.txt")
💡 核心提示
- 前面的代码不用动 for start_num in range(0, 50, 25): 这个循环逻辑以及 time.sleep(1) 都保持不变确保能抓到 50 条数据且不封 IP
- 二选一即可 上面两个方案选一个你想要的替换掉原代码末尾的 JSON 保存部分就行
这份代码是抓前 50 部的需要我帮你改成一键抓取全部 250
#爬虫第2题
根据题目要求我们需要基于第1题爬取并保存的 movies.json 文件完成第2题的四个小任务
题目分析
首先我们需要明确 movies.json 的结构根据第1题的描述它包含数据编号10部电影的信息每部电影包含的键为id, title, director, year, rating, duration, genre, actors_count
我们可以假设 movies.json 的结构大致如下具体结构以实际爬取为准但通常是一个字典包含一个数据编号字段和一个电影列表字段
{
"data_id": "some_number",
"movies": [
{
"id": 1,
"title": "电影A",
"director": "导演X",
"year": 2020,
"rating": 8.5,
"duration": 120,
"genre": "动作",
"actors_count": 5
},
// ... 其他9部电影
]
}
接下来我们需要加载这个 JSON 文件并提取出 movies 列表进行后续处理
解题步骤
1. 准备工作加载数据
我们需要先读取 movies.json获取电影列表
import json
# 假设 movies.json 已经由第1题生成
with open('movies.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 提取电影列表,根据实际结构可能是 data['movies'] 或 data['data'] 等
# 这里假设电影列表的键是 'movies'
movies = data.get('movies')
if not movies:
# 如果结构不同,可能需要调整,例如 movies = data['data']
pass
2. 找出评分最高和最低的电影打印电影名 + 评分
我们需要遍历电影列表找到 rating 最大和最小的电影可以使用 max() min() 函数配合 key 参数或者手动遍历
# 找出评分最高的电影
highest_rated_movie = max(movies, key=lambda m: m['rating'])
# 找出评分最低的电影
lowest_rated_movie = min(movies, key=lambda m: m['rating'])
print(f"评分最高的电影:{highest_rated_movie['title']},评分:{highest_rated_movie['rating']}")
print(f"评分最低的电影:{lowest_rated_movie['title']},评分:{lowest_rated_movie['rating']}")
3. 统计各类型的电影数量用字典格式输出
电影类型通常在 genre 字段中我们需要统计每个 genre 出现的次数
genre_counts = {}
for movie in movies:
genre = movie['genre']
genre_counts[genre] = genre_counts.get(genre, 0) + 1
print("各类型电影数量:", genre_counts)
4. 统计各导演的电影数量用字典格式输出
同理统计 director 字段的出现次数
director_counts = {}
for movie in movies:
director = movie['director']
director_counts[director] = director_counts.get(director, 0) + 1
print("各导演电影数量:", director_counts)
5. 统计 2020 以后上映的电影数量
遍历电影列表判断 year 是否大于等于 2020
count_2020_plus = 0
for movie in movies:
if movie['year'] >= 2020:
count_2020_plus += 1
print("2020年以后上映的电影数量", count_2020_plus)
完整代码示例
将上述步骤整合完整的 Python 代码如下
import json
# --- 1. 加载 movies.json 数据 ---
try:
with open('movies.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 根据第1题电影信息通常在 'movies' 键下
movies = data.get('movies')
if not movies:
raise ValueError("未在 movies.json 中找到 'movies' 列表,请检查数据结构。")
except FileNotFoundError:
print("错误movies.json 未找到。请先运行第1题的爬取代码生成该文件。")
exit()
except json.JSONDecodeError:
print("错误movies.json 格式不正确。")
exit()
# --- 2. ① 找出评分最高和最低的电影 ---
if movies:
highest_rated_movie = max(movies, key=lambda m: m['rating'])
lowest_rated_movie = min(movies, key=lambda m: m['rating'])
print("--- 评分最高/最低 ---")
print(f"评分最高的电影:{highest_rated_movie['title']},评分:{highest_rated_movie['rating']}")
print(f"评分最低的电影:{lowest_rated_movie['title']},评分:{lowest_rated_movie['rating']}")
# --- 3. ② 统计各类型的电影数量 ---
genre_counts = {}
for movie in movies:
genre = movie['genre']
genre_counts[genre] = genre_counts.get(genre, 0) + 1
print("n--- 各类型电影数量 ---")
print(genre_counts)
# --- 4. ③ 统计各导演的电影数量 ---
director_counts = {}
for movie in movies:
director = movie['director']
director_counts[director] = director_counts.get(director, 0) + 1
print("n--- 各导演电影数量 ---")
print(director_counts)
# --- 5. ④ 统计 2020 年(含)以后上映的电影数量 ---
count_2020_plus = sum(1 for movie in movies if movie['year'] >= 2020)
print("n--- 2020年以后上映的电影数量 ---")
print(count_2020_plus)
else:
print("没有电影数据可处理。")
注意事项
1. 文件依赖此代码依赖于第1题生成的 movies.json请确保第1题代码已正确运行 movies 列表中的键名 genre, director, year, rating, title与上述代码一致
2. 数据结构如果 movies.json 中电影列表的键不是 movies例如是 data list请调整 movies = data.get('movies') 这一行
3. 输出格式题目要求字典格式输出上述代码中的 genre_counts director_counts 已经是字典直接打印即可满足要求
这段代码逻辑清晰能够一次性完成第2题的所有统计任务