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) 收藏 举报
浙公网安备 33010602011771号