Web Scraping 以提取大学排名数据并保存至 CSV 文件的实践

在数据驱动的世界中,网络抓取(Web Scraping)是获取和分析互联网数据的重要工具。本文将展示一个使用 Python 进行网络抓取的实际案例——从某大学排名网站提取数据并将其保存为 CSV 文件。

项目概述

在这个示例中,我们从一个大学排名网站上抓取了有关大学排名的详细信息。我们将重点介绍以下步骤:

  1. 抓取主页面数据:提取所有学科的标题和子标题。
  2. 提取详细页面数据:从每个子页面提取大学的排名信息。
  3. 保存数据:将抓取到的数据保存为 CSV 文件,便于进一步分析。
代码实现
1. 抓取主页面数据

首先,我们需要抓取主页面以获取所有学科的基本信息。这些信息包括主标题和子标题的 URL。

import requests
from lxml import html
import time

# 基础 URL
base_url = "https://www.shanghairanking.cn/rankings/bcsr/2023"

def fetch_subjects_list():
    session = requests.Session()
    retry = 3
    while retry > 0:
        try:
            response = session.get(base_url, timeout=10)
            response.raise_for_status()
            tree = html.fromstring(response.content)

            subjects = []
            subject_items = tree.xpath('//div[@class="subject-item"]')
            for subject in subject_items:
                main_code = subject.xpath('.//span[@class="subject-code"]/text()')[0].strip()
                main_title = subject.xpath('.//div[@class="subject-title"]/text()')[0].strip()
                main_full_title = f'{main_code}{main_title}'

                sub_items = subject.xpath('.//div[@class="subject-list"]//a')
                for item in sub_items:
                    sub_code = item.xpath('.//span[1]/text()')[0].strip()
                    sub_title = item.xpath('.//span[2]/text()')[0].strip()
                    sub_full_title = f'{sub_code}{sub_title}'
                    sub_url = f"{base_url}/{sub_code}"

                    subjects.append({
                        'main_full_title': main_full_title,
                        'sub_full_title': sub_full_title,
                        'sub_url': sub_url
                    })
            return subjects
        except requests.RequestException as e:
            print(f"Error fetching main page: {e}")
            retry -= 1
            time.sleep(5)  # 等待5秒后重试
    raise Exception("Failed to fetch the main page after multiple attempts.")
2. 提取详细页面数据

接下来,我们需要从每个子页面提取详细的大学排名数据。我们将提取的信息包括大学名称、2023年排名、2022年排名、Logo链接以及总分等。

def extract_data_from_details_page(details_html_content):
    tree = html.fromstring(details_html_content)
    rows = tree.xpath('//tr')

    data = []
    for row in rows:
        try:
            ranking_2023 = row.xpath('.//td/div[@class="ranking"]/text()')
            ranking_2022 = row.xpath('.//td/span[@data-v-6c038bb7=""]/text()')
            overall_rank = row.xpath('.//td[contains(text(), "前")]/text()')
            univ_name = row.xpath('.//td//span[@class="name-cn"]/text()')
            logo_url = row.xpath('.//td//div[@class="logo"]/img/@src')
            total_score = row.xpath('.//td[last()]/text()')  # 更新 XPath 以提取总分

            if not univ_name:
                continue

            data.append({
                '2023年排名': ranking_2023[0].strip() if ranking_2023 else 'N/A',
                '2022年排名': ranking_2022[0].strip() if ranking_2022 else 'N/A',
                '全部层次': overall_rank[0].strip() if overall_rank else 'N/A',
                '大学名称': univ_name[0].strip() if univ_name else 'N/A',
                'Logo链接': logo_url[0].strip() if logo_url else 'N/A',
                '总分': total_score[0].strip() if total_score else 'N/A'
            })
        except Exception as e:
            print(f"Error extracting data from row: {e}")
            continue

    return data
3. 保存数据至 CSV 文件

最后,我们将提取的数据保存为 CSV 文件,以便后续的分析和使用。

import csv

def save_to_csv(data):
    with open('detailed_subjects.csv', 'w', newline='', encoding='utf-8') as csvfile:
        fieldnames = ['序号', '一级分类', '二级分类', '2023年排名', '2022年排名', '全部层次', '大学名称', 'Logo链接', '总分']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

        writer.writeheader()
        for index, row in enumerate(data, start=1):
            row['序号'] = index
            writer.writerow(row)
    print("数据已成功保存到 detailed_subjects.csv")

 

4. 主程序

主程序协调以上步骤,抓取数据并保存至 CSV 文件。

def main():
    all_data = []
    subjects = fetch_subjects_list()

    for subject in subjects:
        sub_title = subject['sub_full_title']
        sub_url = subject['sub_url']
        print(f"Fetching data from: {sub_url}")

        session = requests.Session()
        retry = 3
        while retry > 0:
            try:
                response = session.get(sub_url, timeout=10)
                response.raise_for_status()
                details_html_content = response.content

                # 提取数据
                university_data = extract_data_from_details_page(details_html_content)
                for data in university_data:
                    full_data = {
                        '一级分类': subject['main_full_title'],
                        '二级分类': subject['sub_full_title'],
                        **data
                    }
                    all_data.append(full_data)
                break  # 如果成功,跳出重试循环
            except requests.RequestException as e:
                print(f"Error fetching details page {sub_url}: {e}")
                retry -= 1
                time.sleep(5)  # 等待5秒后重试
        else:
            print(f"Failed to fetch data for {sub_url} after multiple attempts")

    # 保存数据到 CSV
    save_to_csv(all_data)

if __name__ == "__main__":
    main()

 

总结

通过以上步骤,我们成功地从一个大学排名网站抓取了数据并将其保存到 CSV 文件中。这种方法可以灵活地应用于各种数据抓取任务,为数据分析提供了可靠的数据来源。希望这个示例对你有帮助,也期待你在实际应用中根据需要做出调整和优化。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值