cuteaddanina

再看,再看,就把你吃掉

 

python作业--中国大学排名数据分析与可视化

题目:
8-1 【Python0025】中国大学排名数据分析与可视化
分数 10
全屏浏览
作者 doublebest
单位 石家庄铁道大学

【题目描述】以软科中国最好大学排名为分析对象,基于requests库和bs4库编写爬虫程序,对2015年至2019年间的中国大学排名数据进行爬取:

(1)按照排名先后顺序输出不同年份的前10位大学信息,并要求对输出结果的排版进行优化;

(2)结合matplotlib库,对2015-2019年间前10位大学的排名信息进行可视化展示。

(3附加)编写一个查询程序,根据从键盘输入的大学名称和年份,输出该大学相应的排名信息。如果所爬取的数据中不包含该大学或该年份信息,则输出相应的提示信息,并让用户选择重新输入还是结束查询;

【练习要求】请给出源代码程序和运行测试结果,源代码程序要求添加必要的注释。

代码:

 

from urllib.request import urlopen
from urllib.error import URLError
from bs4 import BeautifulSoup
import pandas as pd
import plotly.graph_objects as go

import kaleido
import plotly.express as px

from bs4 import BeautifulSoup
import requests
import pandas as pd
import plotly.graph_objects as go

import plotly.io as pio
pio.renderers.default = 'notebook'  # 或 'browser'


class UniversityRankingAnalyzer:
    def __init__(self):
        self.years = range(2015, 2020)  # 2015-2019年
        self.base_url = "https://www.shanghairanking.cn/rankings/bcur/{year}11"  # 使用软科排名URL
        self.rankings = {}

        # 使用requests爬取数据
        self.crawl_data_with_requests()

        # 展示前10名大学
        self.display_top_10()

        # 可视化排名变化
        self.visualize_with_plotly()

    def crawl_data_with_requests(self):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
        }
        for year in self.years:
            try:
                url = self.base_url.format(year=year)
                response = requests.get(url, headers=headers)
                response.encoding = 'utf-8'  # 关键修复:强制UTF-8解码
                soup = BeautifulSoup(response.text, 'html.parser')

                table = soup.find('table', {'class': 'rk-table'})  # 根据实际HTML调整
                rows = table.find_all('tr')[1:]  # 跳过表头

                year_data = []
                for row in rows:
                    cols = row.find_all('td')
                    rank = cols[0].text.strip()
                    name = cols[1].text.strip().split('\n')[0]  # 提取纯净中文名
                    score = cols[2].text.strip()
                    year_data.append({
                        '排名': rank,
                        '大学名称': name,
                        '总分': score
                    })

                self.rankings[year] = year_data
                print(f"成功爬取{year}年数据")
            except Exception as e:
                print(f"爬取{year}年数据时出错: {e}")

    def display_top_10(self):
        """展示各年份前10名大学信息"""
        for year in self.years:
            if year in self.rankings and len(self.rankings[year]) >= 10:
                print(f"\n{year}年中国大学排名前10位:")
                print("-" * 60)
                print(f"{'排名':<5}{'大学名称':<20}{'总分':<10}")
                print("-" * 60)
                for uni in self.rankings[year][:10]:
                    print(f"{uni['排名']:<5}{uni['大学名称']:<20}{uni['总分']:<10}")
                print("-" * 60)

    def visualize_with_plotly(self):
        """使用Plotly可视化前10名大学排名变化"""
        # 收集所有年份中至少一次排名前10的大学
        top_universities = set()
        for year in self.years:
            if year in self.rankings:
                for uni in self.rankings[year][:10]:
                    top_universities.add(uni['大学名称'])

        # 构建排名变化数据 {大学: [2015排名, 2016排名, ...]}
        ranking_changes = {}
        for uni in top_universities:
            ranking_changes[uni] = []
            for year in self.years:
                found = False
                if year in self.rankings:
                    for idx, item in enumerate(self.rankings[year]):
                        if item['大学名称'] == uni:
                            ranking_changes[uni].append(int(item['排名']))  # 确保排名是整数
                            found = True
                            break
                if not found:
                    ranking_changes[uni].append(None)

        # 仅显示至少一次排名前5的大学(避免图表拥挤)
        top_5_universities = [
            uni for uni in ranking_changes
            if any(rank <= 5 for rank in ranking_changes[uni] if rank is not None)
        ]

        # 创建图表
        fig = go.Figure()
        for uni in top_5_universities:
            fig.add_trace(go.Scatter(
                x=list(self.years),
                y=ranking_changes[uni],
                name=uni,
                mode='lines+markers',
                line=dict(width=2),
                marker=dict(size=8)
            ))

        # 设置图表布局(排名越小越靠上)
        fig.update_yaxes(autorange="reversed", title_text="排名", tickmode='linear', dtick=1)
        fig.update_layout(
            title='2015-2019年中国大学排名变化 (前5名大学)',
            xaxis_title='年份',
            showlegend=True,
            width=1000,
            height=600
        )

        # 显示图表(或保存)
        fig.show(renderer="browser")
        # fig.write_html("university_rankings.html")  # 可选:保存为HTML

    def query_interface(self):
        """提供查询接口"""
        print("\n大学排名查询系统 (2015-2019年)")
        print("输入'退出'可结束查询")

        while True:
            university = input("\n请输入大学名称: ").strip()
            if university == '退出':
                print("感谢使用查询系统,再见!")
                break

            year = input("请输入查询年份(2015-2019): ").strip()
            try:
                year = int(year)
                if year not in self.years:
                    print("错误: 年份必须在2015-2019之间")
                    continue
            except ValueError:
                print("错误: 请输入有效的年份数字")
                continue

            # 查询数据
            found = False
            if year in self.rankings:
                for item in self.rankings[year]:
                    if item['大学名称'] == university:
                        print("\n查询结果:")
                        print("-" * 40)
                        print(f"年份: {year}")
                        print(f"大学名称: {university}")
                        print(f"排名: {item['排名']}")
                        print(f"总分: {item['总分']}")
                        print("-" * 40)
                        found = True
                        break

            if not found:
                print(f"\n未找到{year}年'{university}'的排名信息")

                choice = input("是否继续查询? (y/n): ").strip().lower()
                if choice != 'y':
                    print("感谢使用查询系统,再见!")
                    break


# 运行程序
if __name__ == "__main__":
    analyzer = UniversityRankingAnalyzer()

运行截图:

posted on 2025-05-23 00:05  Adda...nina  阅读(36)  评论(0)    收藏  举报

导航