Python爬虫泰晤士2024排名,以及问题总结

1.代码

from selenium import webdriver
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import csv
import time

# Edge 驱动路径
EDGE_DRIVER_PATH = "C:\\Program Files (x86)\\Microsoft\\Edge\\edgedriver_win64\\msedgedriver.exe"

# 初始化 Edge 驱动
options = webdriver.EdgeOptions()
options.add_argument("--window-size=1920,1080")  # 设置窗口大小
# options.add_argument("--headless")  # 无界面模式(如需调试界面,可注释此行)

service = EdgeService(EDGE_DRIVER_PATH)
driver = webdriver.Edge(service=service, options=options)

# 输出文件
output_file = "university_rankings_edge.csv"

# 写入表头
with open(output_file, mode='w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file)
    writer.writerow(["排名", "名称", "国家/地区", "全职学生数量", "每位教职员对学生数量", "国际学生", "女生对男生比例"])


# 解析表格数据
def parse_table(html):
    soup = BeautifulSoup(html, "html.parser")
    rows = soup.select("tr.js-row")
    data = []
    for row in rows:
        try:
            rank = row.select_one(".rank").text.strip()
            name = row.select_one(".ranking-institution-title").text.strip()
            country = row.select_one(".location span a").text.strip()
            students = row.select_one(".stats_number_students").text.strip()
            ratio = row.select_one(".stats_student_staff_ratio").text.strip()
            intl_students = row.select_one(".stats_pc_intl_students").text.strip()
            female_male_ratio = row.select_one(".stats_female_male_ratio").text.strip()
            data.append([rank, name, country, students, ratio, intl_students, female_male_ratio])
        except AttributeError:
            continue  # 跳过缺少数据的行
    return data


# 主程序:通过修改路由 URL 翻页抓取
try:
    base_url = "https://www.timeshighereducation.com/cn/world-university-rankings/2024/world-ranking"
    page = 1

    while True:
        # 构造分页 URL
        url = f"{base_url}?page={page}#page={page}"
        print(f"正在抓取第 {page} 页: {url}")

        # 打开目标页面
        driver.get(url)

        # 等待表格加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "tr.js-row")))

        # 获取页面 HTML 并解析
        html = driver.page_source
        table_data = parse_table(html)

        # 如果没有数据,说明到最后一页,退出循环
        if not table_data:
            print("没有更多数据,结束爬取!")
            break

        # 保存数据
        with open(output_file, mode='a', newline='', encoding='utf-8') as file:
            writer = csv.writer(file)
            writer.writerows(table_data)

        print(f"第 {page} 页已保存 {len(table_data)} 条数据")

        # 下一页
        page += 1

        # 延迟避免触发反爬机制
        time.sleep(3)

finally:
    driver.quit()

print("数据爬取完成!")

2.分析

这段代码实现了通过 Selenium 和 BeautifulSoup 从 Times Higher Education 网站抓取世界大学排名数据并保存到 CSV 文件的功能。其主要思路是通过分页访问网站内容,解析表格数据并写入文件。

2.1工具使用

  1.  Selenium 用于模拟浏览器操作,包括加载网页和等待动态内容加载。Edge 浏览器被选为驱动。
  2. BeautifulSoup 用于解析页面 HTML,并提取特定表格内容。
  3. soup.select("tr.js-row") 是使用 BeautifulSoup 提供的 select 方法,通过 CSS选择器 来查找 HTML 文档中所有符合条件的元素。
  4. 通过提取的一行数据之后访问每一行中的类名 
  5.             rank = row.select_one(".rank").text.strip()
                name = row.select_one(".ranking-institution-title").text.strip()
                country = row.select_one(".location span a").text.strip()
                students = row.select_one(".stats_number_students").text.strip()
                ratio = row.select_one(".stats_student_staff_ratio").text.strip()
                intl_students = row.select_one(".stats_pc_intl_students").text.strip()
                female_male_ratio = row.select_one(".stats_female_male_ratio").text.strip()
  6. 获取每一行的子类
  7. 然后是获取表格数据
  8.         # 获取页面 HTML 并解析
            html = driver.page_source
            table_data = parse_table(html)
  9. ​​​​​​也就是图中的这个部分

问题总结

首先是我看到这个网页的时候网页是有方向箭头的按钮触发的,包括我自己也可以通过利用鼠标来进行触发,但是如果我通过,获取这个元素的类获取按钮的时候,运行代码始终触发不了按钮元素以及对应网页的地方。

但是这个地方不像之前的关于排名的网站(这里是软科的排名的下一页按钮)

我爬取这个软件的排名的时候通过下面的代码去读取的,这个代码就可以获得

        if page < total_pages:
            next_button = driver.find_element(By.CSS_SELECTOR, "li.ant-pagination-next")

            # 确认按钮未被禁用
            if "ant-pagination-disabled" not in next_button.get_attribute("class"):
                next_button.click()
                time.sleep(2)  # 等待新页面加载
            else:
                print("Next button is disabled.")
                break

相同的按钮触发方式泰晤士的就无法触发,但好在泰晤士的页面跳转可以通过路由控制

 while True:
        # 构造分页 URL
        url = f"{base_url}?page={page}#page={page}"
        print(f"正在抓取第 {page} 页: {url}")

        # 打开目标页面
        driver.get(url)

        # 等待表格加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "tr.js-row")))

        # 获取页面 HTML 并解析
        html = driver.page_source
        table_data = parse_table(html)

        # 如果没有数据,说明到最后一页,退出循环
        if not table_data:
            print("没有更多数据,结束爬取!")
            break

        # 保存数据
        with open(output_file, mode='a', newline='', encoding='utf-8') as file:
            writer = csv.writer(file)
            writer.writerows(table_data)

        print(f"第 {page} 页已保存 {len(table_data)} 条数据")

        # 下一页
        page += 1

通过这种路由加载的方式就可以读取后页面的数据

注意

我的代码有一些注意的事项,就是本代码读取的数据是从第二页开始的,是刚开始的设计没有优化,另一个问题是代码不会自动停止,当读完所有页面时,页面接着加载回到第一页,所以最后会反复第一页,后面手动停止,并手动截取第一页数据即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值