爬虫项目:爬取中国大学的排名并进行可视化,小白也能学会!

在B站上学的一个小项目

用来新手爬虫可视化练练手挺适合

爬取站点【软科排名】2024年最新软科中国大学排名|中国最好大学排名 (shanghairanking.cn)

爬取内容:大学排名,大学名称,大学省份位置,大学类型,大学评分

如想要好的体验,进入我的博客

别总想着白嫖呀,点个赞行不

import requests
from bs4 import BeautifulSoup
import csv
import matplotlib.pyplot as plt


def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)#使用get请求url,且设置请求的超时时间为30秒
        r.raise_for_status()#检查访问是否成功
        r.encoding = r.apparent_encoding#根据响应内容的类型设置正确的编码,确保后续处理时不会出现编码错误
        html = r.text#将响应的 HTML 内容(文本格式)赋值给变量 html

        # 将html内容写入文件,检查爬取情况
        filename = '测试html.text'
        with open(filename, 'w', encoding='utf-8') as f:
            f.write(html)

        return html

    except:
        print("爬取失败")
        return None


def fillUnivList(ulist, html):#这个函数作用是对爬取数据的筛选,建议按f12打开爬取网页元素构成以便于理解爬虫步骤
    soup = BeautifulSoup(html, 'html.parser')#使用 BeautifulSoup 库解析传入的 HTML 文本,创建一个 soup 对象,方便后续进行 HTML 元素的查找。
    table = soup.find('table', class_='rk-table')#在 soup 对象中查找第一个 <table> 标签,且其类名为 rk-table。将找到的表格赋值给变量 table。
    #table: 这是我们要查找的 HTML 标签类型。在这里,我们在寻找一个 <table> 标签。
    #class_='rk-table': 这是一个过滤条件,表示我们只想找到具有特定类名(rk-table)的 <table> 标签。class_ 是一个参数,用于指定 HTML 元素的类属性。
    if table is None:
        print("未找到排名表格")
        return
    tbody = table.find('tbody')#将tboy标签里的内容全部存入变量tbody中
    #print(tbody) #检查数据内容用的,便于理解操作效果
    if tbody is None:
        print("未找到<tbody>标签")
        return
    data = tbody.find_all('tr')#在 <tbody> 中查找所有的 <tr> 标签(表格行),并将其赋值给变量 data。
    #print(data) #测试 查看数据
    for tr in data:
        tds = tr.find_all('td')
        if len(tds) < 5:  # 爬取5行td的内容
            continue
        td_2 = tds[2].text.strip() if tds[2].text else ""#这边的if else判断tds[2]是否为空,如果为空就赋予引号的值
        #总而言之:从列表tds中获取第三个元素的文本内容,并去掉该文本两端的空白字符。
        td_3 = tds[3].text.strip() if tds[3].text else ""
        #print(tds[1]) #观察里面的内容,并对其中的内容进行筛选
        ulist.append([tds[0].string.strip(), tds[1].find('span').string.strip(),
                      td_2, td_3, tds[4].string.strip()])
        #tds[1].find('span').string.strip() 的意思是:
        # 从 tds 列表中获取第二个 <td> 元素,找到该元素内的第一个 <span> 标签,获取该标签中的文本内容,并去掉文本前后的空白字符。


def printUnivList(ulist, num):#将爬取的内容存入.csv文件
    file_name = "大学排行.csv"
    with open(file_name, 'w', newline='', encoding='utf-8') as f:#创建或覆盖一个名为 "大学排行.csv" 的文件,使用 UTF-8 编码以支持中文字符。
        writer = csv.writer(f)#使用 csv.writer 创建一个写入器,并写入表头。
        writer.writerow(["排名", "大学名称", "省市", "类型", "总分"])
        for i in range(num):#写入数据并打印数据用于检查
            u = ulist[i]
            writer.writerow(u)
            print(f"排名:{u[0]}\t大学名称:{u[1]}\t省市:{u[2]}\t类型:{u[3]}\t总分:{u[4]}")

# 折线图
def drawLineChart(ulist):
    ranks = [(u[0]) for u in ulist]#ranks:从 ulist 中提取每个大学的排名
    scores = [float(u[4]) for u in ulist]#scores:从 ulist 中提取每个大学的总分,并将其转换为浮点数
    names = [u[1] for u in ulist]#names:从 ulist 中提取大学的名称


    plt.rcParams['font.sans-serif'] = ['SimHei']#设置字体为 SimHei,以支持中文显示。
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.figure(figsize=(12, 8)) #设置图像的大小为12x8英寸
    plt.plot(names, scores)#绘制以 ranks 为横坐标、scores 为纵坐标的折线图。

    plt.xlabel('大学名称')
    plt.ylabel('总分')
    plt.title('大学排行榜折线图')

    for i in range(len(names)):#在每个点上加上排名
        plt.text(names[i], scores[i], ranks[i], ha='center', va='bottom', multialignment='center')

    plt.xticks(rotation='vertical')  # 将x轴的字体改为竖向显示

    plt.savefig('大学排行榜折线图.pdf', format='pdf', bbox_inches='tight')  # bbox_inches='tight' 可以去除多余的空白

    plt.show()

# 饼图
def generatePieChart(ulist, num):
    provinces = {}
    for i in range(num):
        province = ulist[i][2]
        if province in provinces:
            provinces[province] += 1
        else:
            provinces[province] = 1

    labels = provinces.keys()
    sizes = provinces.values()
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.figure(figsize=(8, 6))
    plt.pie(sizes, labels=labels, autopct='%1.1f%%')
    plt.axis('equal')
    plt.title('大学排行前30名的省份分布')
    plt.show()

    # plt.rcParams['font.sans-serif'] = ['SimHei']


# 柱形图
def printUnivList2(ulist, num):
    ranks = []
    scores = []
    names = []

    for i in range(num):
        u = ulist[i]
        ranks.append(int(u[0]))
        scores.append(float(u[4]))
        names.append(u[1])

    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.bar(ranks, scores)
    plt.xlabel('排名')
    plt.ylabel('总分')
    plt.title('大学排名')

    for i in range(len(ranks)):
        # 在每个柱形图上方显示大学名称,并将其旋转45度
        plt.text(ranks[i], scores[i], names[i], ha='center', va='bottom', fontsize=3, rotation=45)

    plt.show()


# 散点图
def generateScatterPlot(ulist, num):
    scores = [float(ulist[i][4]) for i in range(num)]
    ranks = [i + 1 for i in range(num)]
    names = [ulist[i][1] for i in range(num)]
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.figure(figsize=(12, 8))
    plt.scatter(ranks, scores)
    plt.title('大学排名与总分的关系')
    plt.xlabel('排名')
    plt.ylabel('总分')

    for i, name in enumerate(names):
        plt.annotate(name, (ranks[i], scores[i]), xytext=(5, 5), textcoords='offset points', fontsize=8, rotation=45)

    plt.show()


# 箱形图
def generateBoxPlot(ulist, num):
    scores = [float(ulist[i][4]) for i in range(num)]
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.figure(figsize=(8, 6))
    plt.boxplot(scores)
    plt.title('大学总分箱形图')
    plt.ylabel('总分')
    plt.show()


# 环形图
def generateDonutChart(ulist, num):
    provinces = {}
    for i in range(num):
        province = ulist[i][2]
        if province in provinces:
            provinces[province] += 1
        else:
            provinces[province] = 1

    labels = provinces.keys()
    sizes = provinces.values()
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.figure(dpi=300)  # 设置图像分辨率为300
    plt.figure(figsize=(8, 6))
    _, _, autotexts = plt.pie(sizes, labels=labels, autopct='%1.1f%%', wedgeprops=dict(width=0.8))
    plt.setp(autotexts, size=8)
    plt.title('大学排行前30名的省份分布(环形图)')
    plt.axis('equal')
    plt.show()


def main():
    ulist = []
    url = 'https://www.shanghairanking.cn/rankings/bcur/202411.html'
    html = getHTMLText(url)
    if html is not None:
        fillUnivList(ulist, html)
        printUnivList(ulist, 30)
        printUnivList2(ulist, 30)  # 柱形图
        drawLineChart(ulist)  # 折线图
        generatePieChart(ulist, 30)  # 饼图
        generateScatterPlot(ulist, 30)  # 调用生成散点图的函数
        generateBoxPlot(ulist, 30)  # 调用生成箱形图的函数
        generateDonutChart(ulist, 30)  # 调用生成环形图的函数


main()
### 如何使用Python编写爬虫抓取中国大学排名数据 要实现通过Python编写爬虫以获取中国大学排名数据,可以参考以下方法和步骤。以下是关于如何使用`requests`库和`BeautifulSoup`库来完成这一任务的详细说明[^1]。 首先,需要安装必要的库。可以通过运行以下命令安装这些库: ```bash pip install requests beautifulsoup4 ``` 接下来,可以使用以下代码示例来抓取解析目标网站上的中国大学排名数据[^4]。 ```python import requests from bs4 import BeautifulSoup # 定义目标URL url = "https://example.com/university-rankings" # 替换为实际的目标网站链接 # 发送HTTP请求 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' } response = requests.get(url, headers=headers) # 检查请求是否成功 if response.status_code == 200: # 解析HTML内容 soup = BeautifulSoup(response.text, 'html.parser') # 查找排名信息(根据实际HTML结构调整选择器) rankings = [] for item in soup.select('.ranking-item'): # 根据实际HTML结构调整CSS选择器 rank = item.select_one('.ranking').text.strip() if item.select_one('.ranking') else '' university_name = item.select_one('.university-name').text.strip() if item.select_one('.university-name') else '' score = item.select_one('.score').text.strip() if item.select_one('.score') else '' rankings.append({ 'rank': rank, 'university_name': university_name, 'score': score }) # 打印结果 for ranking in rankings: print(f"Rank: {ranking['rank']}, University: {ranking['university_name']}, Score: {ranking['score']}") else: print(f"Failed to retrieve data: {response.status_code}") ``` 在上述代码中,使用了`requests`库发送HTTP请求,通过`BeautifulSoup`库解析HTML文档。通过调整CSS选择器(如`.ranking-item`、`.ranking`等),可以根据目标网站的实际HTML结构提取所需数据。 此外,还可以利用`pandas`库将抓取的数据存储到CSV文件中,以便后续进行数据分析和可视化[^1]。 ```python import pandas as pd # 将数据转换为DataFrame df = pd.DataFrame(rankings) # 保存到CSV文件 df.to_csv('university_rankings.csv', index=False, encoding='utf-8-sig') ``` ### 注意事项 在编写爬虫时,需遵守目标网站的`robots.txt`文件规则,避免对服务器造成过大的访问压力。同时,确保遵循相关法律法规,合法合规地使用爬取的数据[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值