使用DrissionPage与BeautifulSoup中国大学排名(完整代码)

#新星杯·14天创作挑战营·第11期#

一、项目背景与工具选型

1.1 目标说明

本项目通过自动化浏览器工具 DrissionPage 和HTML解析库 BeautifulSoup,抓取软科中国大学排名的2025年数据,并保存为结构化Excel文件。最终成果包含以下字段:

  • 排名

  • 学校名称

  • 省市

  • 类型

  • 总分

  • 办学层次

1.2 工具特性

  • DrissionPage:无需独立安装浏览器驱动,支持智能等待和动态元素操作

  • BeautifulSoup:提供简洁的HTML解析API,适合处理复杂页面结构

  • Pandas:数据清洗与Excel导出的核心工具

1.3目标网站: 

【软科排名】2023年最新软科中国大学排名|中国最好大学排名


二、环境准备

2.1 安装依赖库

pip install DrissionPage beautifulsoup4 pandas openpyxl

2.2 浏览器配置

  • 代码会自动下载Chromium浏览器(约100MB)

  • 若需使用本地Chrome,可设置:

    page = ChromiumPage(browser_path='C:/Program Files/Google/Chrome/Application/chrome.exe')


三、完整代码实现

from DrissionPage import ChromiumPage
from bs4 import BeautifulSoup
import pandas as pd

# 创建浏览器对象(自动下载驱动)
page = ChromiumPage()

# 目标URL(2025年中国大学排名)
url = "https://www.shanghairanking.cn/rankings/bcur/2025"

# 访问页面
page.get(url)
page.wait(5)  # 等待5秒加载动态内容

contents = []  # 数据存储容器

def get_data(page_num):
    """解析当前页数据"""
    html = page.html  # 获取页面HTML源码
    soup = BeautifulSoup(html, "html.parser")
    
    # 定位表格主体
    tbody = soup.find('tbody')
    if not tbody:
        raise ValueError("未找到表格数据")
    
    # 遍历表格行
    for tr in tbody.children:
        if tr.name == 'tr':  # 过滤非<tr>元素
            tds = tr.find_all('td')
            # 数据提取
            contents.append([
                tds[0].text.strip(),  # 排名
                tr.find(class_="name-cn").text.strip(),  # 学校名称
                tds[2].text.strip(),  # 省市
                tds[3].text.strip(),  # 类型
                tds[4].text.strip(),  # 总分
                tds[5].text.strip()   # 办学层次
            ])
    print(f"已爬取第{page_num}页,总计{len(contents)}条数据")

def get_all_pages():
    """翻页抓取全量数据"""
    current_page = 1
    while current_page <= 20:  # 最多抓取20页
        get_data(current_page)
        
        # 定位下一页按钮
        next_btn = page.ele('css:li.ant-pagination-next>a')
        if next_btn:
            next_btn.click()  # 模拟点击
            page.wait(2)      # 等待加载
            current_page += 1
        else:
            break

def save_to_excel(data):
    """保存为Excel文件"""
    columns = ["排名", "学校名称", "省市", "类型", "总分", "办学层次"]
    df = pd.DataFrame(data, columns=columns)
    
    # 数据类型转换
    df["排名"] = df["排名"].astype(int)
    df["总分"] = df["总分"].astype(float)
    df["办学层次"] = pd.to_numeric(df["办学层次"], errors='coerce')
    
    # 导出文件
    df.to_excel("2025中国大学排名.xlsx", index=False)
    print("数据已保存至Excel")

if __name__ == '__main__':
    get_all_pages()
    save_to_excel(contents)
    page.close()  # 关闭浏览器

运行结果: 


四、核心代码解析

4.1 浏览器初始化

page = ChromiumPage()
page.get(url)
page.wait(5)
  • ChromiumPage:启动无头浏览器(默认隐藏界面,添加headless=False可显示)

  • wait(5):强制等待5秒,确保动态内容加载完成

4.2 数据解析逻辑

tbody = soup.find('tbody')
for tr in tbody.children:
    if tr.name == 'tr':
        tds = tr.find_all('td')
  • soup.find('tbody'):定位表格主体

  • tr.name == 'tr':过滤文本节点等非表格行元素

  • find_all('td'):提取每行的单元格数据

4.3 分页控制

next_btn = page.ele('css:li.ant-pagination-next>a')
if next_btn:
    next_btn.click()
  • CSS选择器:定位分页按钮li.ant-pagination-next>a

  • click():模拟用户点击操作

  • page.wait(2):等待新页面加载,避免数据缺失

4.4 数据清洗与导出

df["总分"] = df["总分"].astype(float)
df["办学层次"] = pd.to_numeric(df["办学层次"], errors='coerce')
  • astype:强制转换数据类型,确保数值可计算

  • errors='coerce':将无效值转为NaN,避免导出失败


五、执行效果展示

5.1 控制台输出

已爬取第1页,总计30条数据
已爬取第2页,总计60条数据
...
数据已保存至Excel文件

5.2 Excel文件内容

排名学校名称省市类型总分办学层次
1清华大学北京综合1004.137.5
2北京大学北京综合910.535.0
..................

六、常见问题解决方案

6.1 元素定位失败

现象未找到表格数据
解决方案

  1. 检查页面是否加载完成(延长page.wait()时间)

  2. 验证CSS选择器是否匹配最新页面结构

  3. 添加重试机制:

    from retrying import retry
    @retry(stop_max_attempt_number=3)
    def get_data(page_num):
        # 原有逻辑

6.2 反爬拦截

现象:IP被封禁或出现验证码
应对策略

# 设置随机请求头
page.set.user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')

# 使用代理IP
page.set.proxies({'http': 'http://127.0.0.1:1080'})

# 添加随机延迟
import time, random
time.sleep(random.uniform(1, 5))

6.3 数据错位

现象:字段内容混乱
处理方法

# 添加容错判断
if len(tds) >= 6:
    # 提取数据
else:
    print(f"跳过异常行:{tr}")

七、功能扩展建议

7.1 数据可视化

import matplotlib.pyplot as plt

# 绘制总分分布直方图
df['总分'].hist(bins=20)
plt.title('中国大学总分分布')
plt.xlabel('总分')
plt.ylabel('院校数量')
plt.savefig('score_distribution.png')

7.2 数据库存储

import sqlite3

# 保存到SQLite
conn = sqlite3.connect('university.db')
df.to_sql('rankings', conn, if_exists='replace', index=False)
conn.close()

7.3 自动化邮件推送

import smtplib
from email.mime.multipart import MIMEMultipart

def send_email():
    msg = MIMEMultipart()
    msg['Subject'] = '2025中国大学排名数据'
    with open("2025中国大学排名.xlsx", "rb") as f:
        msg.attach(f.read(), 'application/octet-stream')
    
    server = smtplib.SMTP('smtp.example.com', 587)
    server.login('user@example.com', 'password')
    server.send_message(msg)
    server.quit()

八、最佳实践建议

  1. 遵守爬虫协议:在robots.txt允许范围内抓取(本例URL未禁止爬虫)

  2. 控制请求频率:建议设置time.sleep(3)避免高频访问

  3. 定期维护代码:每月检查一次页面结构变化

  4. 异常监控:集成日志记录模块(如logging


通过本教程,读者可以掌握使用DrissionPage+BeautifulSoup构建高效爬虫的核心技术。完整代码已通过实测,建议在遵守相关法律法规的前提下使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eqwaak00

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值