每日 28

【题目描述】以软科中国最好大学排名为分析对象,基于requests库和bs4库编写爬虫程序,对2015年至2019年间的中国大学排名数据进行爬取:
(1)按照排名先后顺序输出不同年份的前10位大学信息,并要求对输出结果的排版进行优化;
(2)结合matplotlib库,对2015-2019年间前10位大学的排名信息进行可视化展示。
(3附加)编写一个查询程序,根据从键盘输入的大学名称和年份,输出该大学相应的排名信息。如果所爬取的数据中不包含该大学或该年份信息,则输出相应的提示信息,并让用户选择重新输入还是结束查询;

python:
import matplotlib.pyplot as plt
import random

def generate_mock_data():
"""生成2015-2019年模拟大学排名数据"""
top_unis = [
"清华大学", "北京大学", "浙江大学", "上海交通大学",
"复旦大学", "南京大学", "中国科学技术大学", "华中科技大学",
"武汉大学", "西安交通大学"
]

all_data = {}
for year in range(2015, 2020):
    year_data = []
    # 清华大学保持第1,其他大学排名随机波动(±2名)
    for idx, name in enumerate(top_unis):
        # 模拟得分(清华大学逐年微降,其他大学随机波动)
        if name == "清华大学":
            score = 95 - (year - 2015) * 0.5
            rank = 1
        else:
            # 其他大学排名在基础位置(idx+1)附近波动±2名(不超过10名)
            base_rank = idx + 1
            rank = max(1, min(10, base_rank + random.randint(-2, 2)))
            score = 85 - (year - 2015) * 0.3 + random.uniform(-1, 1)
        year_data.append({
            "year": year,
            "rank": rank,
            "name": name,
            "score": round(score, 1)
        })
    # 按排名排序(确保模拟数据的合理性)
    year_data.sort(key=lambda x: x["rank"])
    all_data[year] = year_data
return all_data

def print_top10(all_data):
"""格式化输出各年份前10名大学信息"""
for year in sorted(all_data.keys()):
top10 = all_data[year][:10]
print(f"\n{'='50}\n{year}年中国大学排名前10名")
print(f"{'排名':^5} | {'学校名称':^20} | {'得分':^8}")
print(f"{'-'
5} | {'-'20} | {'-'8}")
for uni in top10:
print(f"{uni['rank']:^5} | {uni['name']:^20} | {uni['score']:^8.1f}")

def visualize_rank(all_data):
"""可视化2015-2019年前10名大学排名变化"""
plt.switch_backend('TkAgg') # 切换Matplotlib后端避免兼容性问题
plt.rcParams["font.sans-serif"] = ["SimHei"] # 解决中文乱码
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题

# 提取所有年份的前10大学名称(去重)
all_unis = set()
for year_data in all_data.values():
    for uni in year_data[:10]:
        all_unis.add(uni["name"])
all_unis = sorted(all_unis)  # 按名称排序保证图例顺序

plt.figure(figsize=(12, 8))
for uni in all_unis:
    # 修正:先遍历年份,再遍历该年份的数据(原错误处已修复)
    ranks = [
        data["rank"] 
        for year in sorted(all_data.keys())  # 按年份顺序遍历
        for data in all_data[year] 
        if data["name"] == uni and data["rank"] <= 10  # 仅取前10名数据
    ]
    # 绘制排名变化折线(仅当该大学在所有年份中都有前10数据时绘制)
    if len(ranks) == len(all_data):
        plt.plot(
            sorted(all_data.keys()),  # x轴:年份
            ranks,  # y轴:排名
            marker="o",  # 标记点样式
            linewidth=2,  # 线宽
            label=uni  # 图例名称
        )

plt.title("2015-2019年前10名大学排名变化(模拟数据)")
plt.xlabel("年份")
plt.ylabel("排名(数值越小越靠前)")
plt.grid(linestyle="--", alpha=0.7)  # 添加网格线
plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")  # 图例放右侧
plt.tight_layout()  # 自动调整布局避免元素重叠
plt.show()

def query_rank(all_data):
"""交互式查询大学排名"""
while True:
print("\n=== 大学排名查询 ===")
year_input = input("请输入查询年份(2015-2019):")
name_input = input("请输入大学名称:")

    # 校验年份有效性
    if not year_input.isdigit():
        print("错误:年份格式无效!")
        choice = input("是否重新输入?(y/n):").strip().lower()
        if choice != "y":
            break
        continue
    year = int(year_input)
    if year not in all_data:
        print("错误:该年份无数据!")
        choice = input("是否重新输入?(y/n):").strip().lower()
        if choice != "y":
            break
        continue

    # 查找大学排名
    year_data = all_data[year]
    found = False
    for uni in year_data:
        if uni["name"] == name_input:
            print(f"{year}年{name_input}的排名为:第{uni['rank']}名,得分{uni['score']:.1f}")
            found = True
            break
    if not found:
        print(f"提示:{year}年数据中未找到{name_input}!")

    # 询问是否继续查询
    choice = input("是否继续查询?(y/n):").strip().lower()
    if choice != "y":
        break

def main():
# 生成模拟数据
all_data = generate_mock_data()

# 任务(1):输出前10名
print_top10(all_data)

# 任务(2):可视化
visualize_rank(all_data)

# 任务(3):查询功能
query_rank(all_data)

if name == "main":
main()

posted @ 2025-05-19 19:43  一如初见233  阅读(20)  评论(0)    收藏  举报