爬取与数据分析全流程详解

发布于:2025-08-12 ⋅ 阅读:(14) ⋅ 点赞:(0)

在数据科学与计算领域,爬虫技术与数据分析的结合能帮助我们从海量网络信息中提取有价值的内容,并通过可视化手段直观呈现数据规律。本文将以 “中国大学排名” 为例,详细介绍从网页爬取数据到进行数据分析与可视化的完整流程,适合数据分析初学者参考学习。

一、案例背景与任务描述

本次案例的核心目标是爬取高三网发布的中国大学排名一览表,并对爬取的数据进行预处理与可视化分析。具体任务包括:

  1. 数据爬取:从网址 http://www.bspider.top/gaosan/ 爬取学校名称、总分、全国排名、星级排名、办学层级 5 类关键信息,并将数据保存为 CSV 文件。
  2. 数据预处理:处理 CSV 文件中 “总分” 列的缺失值,采用多种方法进行数据清洗。
  3. 数据分析与可视化:通过柱形图、饼图等方式,展示不同星级学校的数量分布及占比情况。

二、数据爬取:从网页到结构化数据

1. 任务分析

网页中的大学排名数据以表格形式呈现(如图 1 所示),表格包含 “名次”“学校名称”“总分”“全国排名”“星级排名”“办学层次” 等列。我们需要通过爬虫技术提取这些结构化数据,并存储为便于后续分析的 CSV 格式。

2. 代码实现

爬虫过程主要分为 3 个核心步骤:发送请求获取网页内容、解析网页提取数据、将数据保存为 CSV 文件。以下是完整代码及详解:

(1)导入必要库
import requests  # 用于发送HTTP请求
from bs4 import BeautifulSoup  # 用于解析HTML网页
import csv  # 用于处理CSV文件
(2)发送请求获取网页内容
def get_html(url, time=3):  # 定义通用的GET请求函数
    try:
        r = requests.get(url, timeout=time)  # 发送GET请求
        r.encoding = r.apparent_encoding  # 自动识别并设置字符编码,避免中文乱码
        r.raise_for_status()  # 若响应状态码不是200,抛出异常
        return r.text  # 返回网页HTML文本
    except Exception as error:
        print(error)  # 打印异常信息
(3)解析网页提取数据
def parser(html):  # 定义解析HTML的函数
    soup = BeautifulSoup(html, "lxml")  # 将HTML文本转换为BeautifulSoup对象,使用lxml解析器
    out_list = []  # 存储提取的数据
    # 遍历表格中的每一行(tr标签)
    for row in soup.select("table>tbody>tr"):
        td_html = row.select("td")  # 获取当前行的所有单元格(td标签)
        # 提取各单元格数据,strip()去除首尾空格
        row_data = [
            td_html[1].text.strip(),  # 学校名称(第2个td)
            td_html[2].text.strip(),  # 总分(第3个td)
            td_html[3].text.strip(),  # 全国排名(第4个td)
            td_html[4].text.strip(),  # 星级排名(第5个td)
            td_html[5].text.strip()   # 办学层次(第6个td)
        ]
        out_list.append(row_data)  # 将一行数据添加到列表
    return out_list
(4)保存数据为 CSV 文件
def save_csv(item, path):  # 定义保存数据到CSV的函数
    # 以UTF-8编码打开文件,newline=""避免空行
    with open(path, "wt", newline="", encoding="utf-8") as f:
        csv_write = csv.writer(f)  # 创建CSV写入对象
        csv_write.writerows(item)  # 一次性写入所有数据
(5)主函数执行流程
if __name__ == "__main__":
    url = "http://www.bspider.top/gaosan/"  # 目标网页URL
    html = get_html(url)  # 获取网页内容
    out_list = parser(html)  # 解析数据
    save_csv(out_list, "school.csv")  # 保存为school.csv

3. 运行结果

执行代码后,会生成名为 school.csv 的文件,部分数据如下:

学校名称,总分,全国排名,星级排名,办学层次
北京大学,100,1,8★,世界一流大学
清华大学,99.81,2,8★,世界一流大学
浙江大学,80.72,4,8★,世界一流大学
复旦大学,79.75,3,8★,世界一流大学
...

三、数据预处理:处理缺失值

爬取的 school.csv 中,“总分” 列存在部分空值(NaN),需要进行清洗。以下介绍 4 种常用的缺失值处理方法:

1. 删除包含空字段的行

使用 dropna() 方法删除所有含空值的行,适合缺失值较少的场景:

import pandas as pd
df = pd.read_csv("school.csv")  # 读取CSV文件
new_df = df.dropna()  # 删除含空值的行
print(new_df.to_string())  # 打印处理后的数据

2. 用指定内容替换空字段

使用 fillna() 方法将空值替换为自定义内容(如 “暂无分数信息”):

import pandas as pd
df = pd.read_csv("school.csv")
df.fillna("暂无分数信息", inplace=True)  # 替换空值,inplace=True表示直接修改原数据
print(df.to_string())

3. 用列的均值替换空单元格

先计算 “总分” 列的均值,再用均值填充空值,适合数据近似正态分布的场景:

import pandas as pd
df = pd.read_csv("school.csv")
x = df["总分"].mean()  # 计算总分均值
print("总分的均值为")
print(x)
df["总分"].fillna(x, inplace=True)  # 用均值填充空值
print(df.to_string())

4. 用列的中位数替换空单元格

中位数受极端值影响较小,适合存在异常值的数据:

import pandas as pd
df = pd.read_csv("school.csv")
x = df["总分"].median()  # 计算总分中位数
print("总分的中位数为")
print(x)
df["总分"].fillna(x, inplace=True)  # 用中位数填充空值
print(df.to_string())

四、数据分析与可视化

本次分析聚焦于 “星级排名” 的分布特征,通过可视化图表直观展示不同星级学校的数量及占比。

1. 柱形图:展示不同星级学校的数量

(1)纵向柱形图
import matplotlib.pyplot as plt
import numpy as np

# 定义x轴(星级)和y轴(数量)数据
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)横向柱形图

将 plt.bar() 改为 plt.barh() 可绘制横向柱形图,更适合类别名称较长的场景:

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()

2. 饼图:展示不同星级学校的占比

饼图适合展示各部分占总体的比例,代码如下:

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])
# 绘制饼图,labels参数设置各部分标签
plt.pie(y, labels=["8星", "7星", "6星", "5星", "4星", "3星", "2星", "1星"])
plt.title("不同星级的学校个数")
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.show()

3. 可视化结果解读

  • 从柱形图可见,1 星学校数量最多(260 所),8 星学校数量最少(8 所),整体呈现 “低星级学校多、高星级学校少” 的分布特征。
  • 从饼图可知,3 星学校占比最高(23.1%),8 星学校占比最低(1%),反映出我国大学层次结构呈金字塔型分布。

五、总结

本文通过 “中国大学排名” 案例,完整演示了从网页爬取数据到数据分析可视化的全流程,涵盖了:

  1. 利用 requests 和 BeautifulSoup 爬取网页表格数据;
  2. 用 pandas 处理缺失值的 4 种常用方法;
  3. 基于 matplotlib 绘制柱形图和饼图进行数据可视化。

通过这些技术,我们可以高效地将非结构化的网络数据转化为结构化信息,并从中挖掘有价值的规律。希望本文能为你的数据分析学习提供实用参考!


网站公告

今日签到

点亮在社区的每一天
去签到