目录

第一步:把网页上的排名数据 “搬” 下来

第二步:给数据 “体检”,处理那些 “空着的格子”

第三步:让数据 “说话”—— 可视化图表安排上

四、写在最后


    最近想研究下国内大学的排名情况,翻了好几个网站,数据要么零散要么藏在密密麻麻的表格里,看着头大。正好刚学了点 Python 爬虫和数据分析的知识,索性自己动手试试 —— 从网页上爬取数据,清洗整理后做成图表,没想到过程还挺有意思。今天就把这个小案例分享出来,也算给自己的学习做个小结。

第一步:把网页上的排名数据 “搬” 下来

    目标是高三网上的中国大学排名表(网址是2021中国的大学排名一览表_高三网),表格里有学校名称、总分、全国排名、星级、办学层次这些信息,正是我需要的。

    要把这些数据 “搬” 到本地,得用两个工具:requests负责把网页内容下载下来,BeautifulSoup则专门处理网页里的 HTML 标签,帮我把表格中的数据提取出来。

import requests
from bs4 import BeautifulSoup
import csv

def get_html(url,time=3):  #get请求通用函数,去掉了user-agent简化代码
    try:
        r = requests.get(url, timeout=time)  # 发送请求
        r.encoding = r.apparent_encoding  # 设置返回内容的字符集编码
        r.raise_for_status()  # 返回的状态码不等于200抛出异常
        return r.text  # 返回网页的文本内容
    except Exception as error:
        print(error)

def parser(html): #解析函数
    soup=BeautifulSoup(html,"lxml") #html转换为soup对象
    out_list=[] #解析函数输出数据的列表
    for row in soup.select("table>tbody>tr"): #循环遍历tr
        td_html=row.select("td") #获取td
        row_data=[
            td_html[1].text.strip(), #学校名称
            td_html[2].text.strip(), #总分
            td_html[3].text.strip(), #全国排名
            td_html[4].text.strip(),#星级
            td_html[5].text.strip(),#办学层次
        ]
        out_list.append(row_data) #将解析的每行数据插入到输出列表中
    return out_list

def save_csv(item,path): #数据存储,将list数据写入文件
    with open(path, "w+", newline='',encoding="utf-8") as f: #创建utf8编码文件
        csv_write = csv.writer(f) #创建写入对象
        csv_write.writerows(item) #一次性写入多行

if __name__=="__main__":
    url="http://www.bspider.top/gaosan/"
    html=get_html(url) #获取网页数据
    out_list=parser(html) #解析网页,输出列表数据
    save_csv(out_list,"school.csv") #数据存储

    具体操作时,我先写了个get_html函数发送网络请求,拿到网页的文本内容;然后用parser函数解析这些内容 —— 因为数据都在<table>标签的<tr>(行)和<td>(单元格)里,所以只要循环遍历这些标签,就能把每所学校的信息取出来,存成一个列表;最后用save_csv函数把列表里的数据写入 CSV 文件,这样本地就有了一份结构化的school.csv

    等代码跑完,打开 CSV 文件一看,820 所学校的信息整整齐齐列着,第一步大功告成。

第二步:给数据 “体检”,处理那些 “空着的格子”

    拿到数据后没高兴多久,就发现 “总分” 这一列有不少空值 —— 有的学校可能没公布分数,直接空在那里了。这些空值会影响后面的分析,得处理一下。

    根据学过的方法,我试了四种处理方式:

1、直接删除:用dropna()函数删掉所有包含空值的行,优点是简单直接,适合数据量足够多的情况;

import pandas as pd
df = pd.read_csv("school.csv")
new_df = df.dropna()
print(new_df.to_string())

2、手动填充文字:用fillna("暂无分数信息")把空值换成明确的文字,一眼就能看出哪些学校没数据;

import pandas as pd
df = pd.read_csv("school.csv")
df["总分"] = df["总分"].astype(str)  # 先转为字符串类型
df.fillna("暂无分数信息", inplace=True)
print(df.to_string())

3、用均值填充:计算 “总分” 列的平均值,再用这个平均值填补空值,适合希望保留数值分布的场景;

import pandas as pd
df = pd.read_csv("school.csv")
x = df["总分"].mean()
print("总分的均值为")
print(x)
df["总分"] = df["总分"].fillna(x)  # 直接赋值,不使用inplace
print(df.to_string())

4、用中位数填充:和均值类似,但用中位数(中间位置的数值)更能避免极端值的影响。

    实际操作时,我用pandas库轻松实现了这些功能。比如算均值的时候,一行df["总分"].mean()就搞定了,比手动计算方便太多。

import pandas as pd
df = pd.read_csv("school.csv")
x = df["总分"].median()
print("总分的中位数为")
print(x)
df["总分"] = df["总分"].fillna(x)
print(df.to_string())

第三步:让数据 “说话”—— 可视化图表安排上

    清洗好的数据还是一堆数字,不够直观。820 所学校按星级分了 8 类(从 1 星到 8 星),我想看看每类有多少学校,以及它们各自占比多少,这时候图表就派上用场了。

    我用matplotlib画了三种图:

1、垂直柱形图:x 轴是星级(8 星到 1 星),y 轴是学校数量。一眼就能看出 1 星学校最多(260 所),3 星其次(190 所),8 星最少(只有 8 所);

import matplotlib.pyplot as plt
import numpy as np

x = np.array(["8星","7星","6星","5星","4星","3星","2星","1星"])
y = np.array([8,16,36,59,103,190,148,260])
plt.title("不同星级的学校个数")
plt.rcParams["font.sans-serif"]=["SimHei"]
plt.bar(x,y)
plt.show()

2、水平柱形图:把 x 轴和 y 轴反过来,文字标签看着更清楚,尤其是类别多的时候,不会挤在一起;

import matplotlib.pyplot as plt
import numpy as np

x = np.array(["8星","7星","6星","5星","4星","3星","2星","1星"])
y = np.array([8,16,36,59,103,190,148,260])
plt.title("不同星级的学校个数")
plt.rcParams["font.sans-serif"]=["SimHei"]
plt.barh(x,y)
plt.show()

3、饼图:按比例展示每类星级的占比 —— 比如 1 星学校占 31.7%,3 星占 23.1%,8 星只占 1%,瞬间明白 “高星级” 学校有多稀缺。

import matplotlib.pyplot as plt
import numpy as np

y = np.array([1,2,4.5,7.2,12.5,23.1,18,31.7])
plt.pie(y,labels=["8星","7星","6星","5星","4星","3星","2星","1星"])
plt.title("不同星级的学校个数")
plt.rcParams["font.sans-serif"]=["SimHei"]
plt.show()

    画图时记得加一句plt.rcParams["font.sans-serif"]=["SimHei"],不然中文标题会变成乱码,这点细节很重要。

四、写在最后

    从爬取数据到做出图表,整个过程就像完成了一次 “数据闯关”:用爬虫突破网页的限制,用预处理解决数据的 “小瑕疵”,用可视化让隐藏的规律显形。原来那些看起来复杂的信息,只要找对方法,就能变得清晰易懂。

    如果你也刚学 Python 数据分析,不妨找个自己感兴趣的小主题试试 —— 比如爬取电影评分、球队数据之类的,动手做一遍,比单纯看教程印象深多了。下次有新发现,再跟大家分享~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐