[爬虫练手]整理学校招生信息

news2024/11/29 1:28:40
  • 以下是我要提取信息的网站: http://zsb.hitwh.edu.cn/home/major/index

文章目录

  • 初步尝试(fail)
  • 终于改对了!😭
  • 继续完善

初步尝试(fail)

在这里插入图片描述

  • 用beautifulsoup提取

    import requests
    from bs4 import BeautifulSoup
    import csv
    URL = "http://zsb.hitwh.edu.cn/home/major/index"
    response = requests.get(URL)
    soup = BeautifulSoup(response.content, 'html.parser')
    
    # Extract data from the table
    rows = soup.select('tbody tr')
    data = []
    
    for row in rows:
        # Getting major name
        major_name = row.select_one('.left-td') # .left-td的意思是class为left-td的标签
        if major_name:
            major_name = major_name.get_text(strip=True) # .get_text(strip=True)的意思是获取标签中的文本内容
    
        # Getting category
        category = row.select_one('.text-center') # .text-center的意思是class为text-center的标签
        if category:
            category = category.get_text(strip=True)
    
        # Getting subject requirements
        subjects = row.select('td.text-center') # td.text-center的意思是td标签中class为text-center的标签
        subject_req = [subj.get_text(strip=True) for subj in subjects[1:]] if len(subjects) > 1 else [] # 这行代码的意思是获取subjects中从第二个元素开始的所有元素
    
        # Getting college details
        college_detail = row.select_one('td > a') # td > a的意思是td标签下的a标签
        college_name = college_detail.get_text(strip=True) if college_detail else None
        college_link = college_detail['href'] if college_detail else None
    
        # Getting major details
        major_detail = row.select_one('.right-td > a') # .right-td > a的意思是class为right-td的标签下的a标签
        major_detail_name = major_detail.get_text(strip=True) if major_detail else None
        major_detail_link = major_detail['href'] if major_detail else None
    
        # Appending data to list
        data.append({
            "Major Name": major_name,
            "Category": category,
            "Subject Requirements": subject_req,
            "College Name": college_name,
            "College Link": college_link,
            "Major Detail Name": major_detail_name,
            "Major Detail Link": major_detail_link
        })
    
    with open('major_info.csv', 'w', newline='') as csvfile:
        fieldnames = ['Major Name', 'Category', 'Subject Requirements', 'College Name', 'College Link', 'Major Detail Name', 'Major Detail Link']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames) # DictWriter的意思是将字典写入csv文件
    
        writer.writeheader() # writeheader的意思是写入表头
        for item in data:
            writer.writerow(item)
    
    

    在这里插入图片描述

  • 爬出来的问题在于,学院信息那里跨行的地方没有

终于改对了!😭

  • 当时急着想别的办法,试了xpath啥的 …
  • 但是应该抓住主要矛盾,静下心来分析为什么会有问题!!!
  • 问题就在于
    td 下的 a 标签 ,不能区分下面这个学院和专业!

在这里插入图片描述

  • 那么他们的区别在哪?

    • 一个有rowspan,一个没有😂…
    • 所以只需要微微改动即可!!!!!
  • 就是这个地方
    在这里插入图片描述

继续完善

在这里插入图片描述

  • 如果我想把空缺的地方填满该咋做?

  • 逻辑是每一个tr放到一个row变量里面,然后爬取,那么我们每个row变量长啥样,我存到文件里康康:

	rows = soup.select('tbody tr')
	data = []
	# 把rows[0]存到txt文件中
	with open('major_info.txt', 'w', encoding='utf-8') as f:
	    f.write(str(rows[0]))

在这里插入图片描述

  • 改成前6行rows[:5]
    在这里插入图片描述
    可以看到前三列在第二行确实没再写一次,确实是rowspan了

  • 我们只需要把rowspan里面的值利用好就行

    使用 rowspan 属性来处理在HTML表格中跨多行的字段。当字段在多行中都保持不变时,它会具有 rowspan 属性。

    为了处理 rowspan,我们为每一个可能有 rowspan 的字段维护两个外部变量:一个用来存储当前值,另一个用来追踪剩余的行数。

    每次循环时,我们都会检查是否还有剩余的行数。如果有,我们就使用当前的值并减少剩余的行数。否则,我们就从当前行提取新的值。

    # 导入必要的库
    import requests
    from bs4 import BeautifulSoup
    import csv
    
    # 设置要抓取数据的网址
    URL = "http://zsb.hitwh.edu.cn/home/major/index"
    
    # 使用requests库获取网页内容
    response = requests.get(URL)
    
    # 使用BeautifulSoup解析网页内容,选择使用'html.parser'作为解析器
    soup = BeautifulSoup(response.content, 'html.parser')
    
    # 从HTML中选择所有tbody下的tr标签,这些标签代表了表格中的每一行
    rows = soup.select('tbody tr')
    
    # 初始化一个空列表来存储提取出来的数据
    data = []
    
    # 对于那些带有rowspan属性的字段,我们需要定义一些外部的变量来追踪其值和它们应该持续的行数
    # 这样我们可以在接下来的行中重用这些值
    
    # 专业名称相关变量
    remaining_rows_major_name = 0
    current_major_name = None
    
    # 类别相关变量
    remaining_rows_category = 0
    current_category = None
    
    # 必修课程相关变量
    remaining_rows_subjects = 0
    current_subjects = None
    
    # 学院详情相关变量
    remaining_rows_college_detail = 0
    current_college_name = None
    current_college_link = None
    
    # 遍历每一行,从中提取所需的信息
    for row in rows:
        # 以下部分的逻辑是为了处理带有rowspan属性的字段
        # 如果一个字段的值在多行中都是相同的(由rowspan属性决定),我们只在第一行中提取它
        # 然后在接下来的行中重用这个值,直到达到rowspan指定的行数
    
        # 获取专业名称
        if remaining_rows_major_name > 0:
            major_name = current_major_name
            remaining_rows_major_name -= 1
        else:
            major_name_ele = row.select_one('.left-td')
            if major_name_ele:
                major_name = major_name_ele.get_text(strip=True)
                current_major_name = major_name
                if 'rowspan' in major_name_ele.attrs:
                    remaining_rows_major_name = int(major_name_ele['rowspan']) - 1
    
        # 获取类别
        if remaining_rows_category > 0:
            category = current_category
            remaining_rows_category -= 1
        else:
            category_ele = row.select_one('.text-center')
            if category_ele:
                category = category_ele.get_text(strip=True)
                current_category = category
                if 'rowspan' in category_ele.attrs:
                    remaining_rows_category = int(category_ele['rowspan']) - 1
    
        # 获取必修课程
        if remaining_rows_subjects > 0:
            subject_req = current_subjects
            remaining_rows_subjects -= 1
        else:
            subjects = row.select('td.text-center')
            subject_req = [subj.get_text(strip=True) for subj in subjects[1:]] if len(subjects) > 1 else []
            current_subjects = subject_req
            if subjects and 'rowspan' in subjects[0].attrs:
                remaining_rows_subjects = int(subjects[0]['rowspan']) - 1
    
        # 获取学院详情
        if remaining_rows_college_detail > 0:
            college_name = current_college_name
            college_link = current_college_link
            remaining_rows_college_detail -= 1
        else:
            college_detail = row.select_one('td[rowspan] > a')
            if college_detail:
                college_name = college_detail.get_text(strip=True)
                college_link = college_detail['href']
                current_college_name = college_name
                current_college_link = college_link
                if 'rowspan' in college_detail.find_parent().attrs:
                    remaining_rows_college_detail = int(college_detail.find_parent()['rowspan']) - 1
    
        # 获取专业详情名称和链接
        major_detail = row.select_one('.right-td > a')
        major_detail_name = major_detail.get_text(strip=True) if major_detail else None
        major_detail_link = major_detail['href'] if major_detail else None
    
        # 将提取的数据保存为一个字典,并将其添加到data列表中
        data.append({
            "Major Name": major_name,
            "Category": category,
            "Subject Requirements": subject_req,
            "College Name": college_name,
            "College Link": college_link,
            "Major Detail Name": major_detail_name,
            "Major Detail Link": major_detail_link
        })
    
    # 使用csv模块将data列表写入CSV文件
    with open('major_info3.csv', 'w', newline='') as csvfile:
        fieldnames = ['Major Name', 'Category', 'Subject Requirements',
                      'College Name', 'College Link', 'Major Detail Name', 'Major Detail Link']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
        writer.writeheader()
        for item in data:
            writer.writerow(item)
    
  • 逻辑
    在这里插入图片描述
    这样的话,第一次遇到有rowspan属性,不仅提取了内容(get-text),还记下了循环次数 也就是上图中圈出来的地方,接下来rowspan-1次循环,每循环一次,减少一次remaining次数,并且赋值给major_name

  • nice
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1096261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ctfhub-文件上传-双写后缀

1.首先判断是asp 、jsp、php的网站 发现是php的网站,用哥斯拉生成index.php木马,抓包,将filename"index.php"改为filename"index.pcerhp" 2.用哥斯拉连接 地址为:http://challenge-97f99bc5355c1edb.sandb…

攻防世界数据逆向 2023

https://adworld.xctf.org.cn/contest/list?rwNmOdr1697354606875 目录 请求数据参数加密 cookie加密 响应数据解密 代码 请求数据参数加密 我们可以根据请求的关键字qmze1yzvhyzcyyjr获取到对应的加密地方 可以看到使用了函数_0x1dc70进行了加密 cookie加密 该步骤需…

基础算法:二分查找

目录 1. 二分查找2. 补充:二进制运算2.1 十进制与二进制的相互转换2.1.1 十进制转二进制2.1.2 二进制转十进制 2.2 机器数 真值2.3 原码 补码 反码2.4 二进制的加减乘除2.5 移位运算 1. 二分查找 思想: 有序数组,从中找值 实现:…

Qt 布局(QSplitter 类QDockWidget 类) 总结

一、QSplitter 类(窗口分割) QSplitter类是一个Qt框架提供的基础窗口控件类,用于分割窗口,使得用户可以通过拖动分隔条来调节子窗口的大小。QSplitter在用户界面设计中非常常见,经常用于划分窗口区域,使得程序可以同时显示多个子…

4x4矩阵键盘设计Verilog矩阵式键盘控制,视频/代码

名称:4x4矩阵键盘设计Verilog矩阵式键盘控制 软件:Quartus 语言:Verilog 代码功能: 键盘控制电路设计,设计一个4x4矩阵式键盘控制电路,并实现按键的显示。 演示视频:4x4矩阵键盘设计Verilo…

C与C++之间相互调用的基本方法

​ 在你的C语言代码中,不知能否看到类似下面的代码: 这好像没有什么问题,你应该还会想:“嗯⋯是啊,我们的代码都是这样写的,从来没有因此碰到过什么麻烦啊~”。 你说的没错,如果你的…

load initialize 浅析

load 调用顺序&#xff1a;父类->子类->分类 &#xff08;不会覆盖&#xff09;&#xff1b;多个分类情况下&#xff0c;compile sources <谁在前&#xff0c;先执行谁。多个分类都会被执行>&#xff1b;子类覆盖load方法&#xff0c;父类覆盖了仍然会被调用&…

01-spring源码概述

文章目录 1. Spring两大主要功能2. Bean的生命周期&#xff08;部分生命周期&#xff0c;不包括销毁&#xff09;2.1 两个重要接口及Aware接口2.2 创建对象的过程2.3 Bean的scope作用域2.4 Bean的类型2.5 获得反射对象的三种方式 3. 涉及的接口汇总4. 涉及设计模式 1. Spring两…

axios post 请求发送url 键值对参数

后端post 请求要求在 url 上携带参数&#xff0c;各种百度&#xff0c;最后发现了一种可行的方式&#xff0c;用formData对象构造请求参数&#xff0c;然后用URLSearchParams 把formdata 参数转换成键值对&#xff0c;最后发送 function getList() {const formdata new FormDa…

机器学习在工业机器人领域有哪些应用?

随着人工智能和机器学习的快速发展&#xff0c;工业机器人领域也迎来了新的机遇和挑战。本文综述了机器学习在工业机器人领域的应用&#xff0c;包括机器人视觉、运动控制、路径规划、故障诊断等方面。通过对相关研究和实际应用的分析&#xff0c;总结了机器学习在工业机器人领…

【JVM】JVM类加载机制

JVM类加载机制 加载双亲委派模型 验证准备解析初始化 JVM的类加载机制,就是把类,从硬盘加载到内存中 Java程序,最开始是一个Java文件,编译成.class文件,运行Java程序,JVM就会读取.class文件,把文件的内容,放到内存中,并且构造成.class类对象 加载 这里的加载是整个类加载的一…

ubuntu静态ip地址设置

ifconfig命令显示 手动设置静态ip地址 1、ip地址 IP地址是唯一标识互联网上每个设备的地址&#xff0c;一根网线对应一个ip&#xff0c;一个计算机上可以有多个网卡&#xff0c;所以可以有多个ip地址。 私有地址的范围分别是&#xff1a; A类地址范围&#xff1a;10.0.0…

vue3后台管理框架之路由配置

pnpm install vue-router 在src新建文件夹views和router 1.1基本 路由配置 :hash 路由模式 // 对外配置路由 import Login from @/views/login/index.vue import Home from @/views/home/index.vue import Error from @/views/404/index.vue export cons

循环结构的运用

乘法口诀起源于中国&#xff0c;是古代人进行乘法、除法、开方等运算的基本法则&#xff0c;距今已经有两千多年的历史了&#xff0c;如何运用现代计算机技术快速写出九九乘法表呢&#xff1f; 循环结构可以用来重复执行一条或者多条语句&#xff0c;利用循环结构可以减少源程序…

【JAVA-Day43】Java常用类Calendar解析

Java常用类Calendar解析 Java常用类Calendar解析&#xff0c;科学处理Java日期数据摘要 &#x1f4dd;介绍java.util.Calendar类 &#x1f4c5;什么是java.util.Calendar&#xff1f;为什么需要使用它&#xff1f; Calendar类的基本用法 &#x1f4c6;如何创建一个Calendar对象…

nocos注册中心使用教程

1.下载和安装 进入到官网下载就好了 解压 启动 2.新建提供者模块 2.1新建提供者模块cloudalibaba-provider-payment9001 2.1.1在父项目中新加入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-depend…

<图像处理> 图像插值算法

图像插值算法 图像插值在图像处理中常用于调整图像尺寸或变形&#xff0c;其目标是根据给定像素点周围像素点的信息来预测该像素点的值。 常见的图像插值算法可以分为两类&#xff1a;自适应和非自适应。自适应的方法可以根据插值内容的特点来进行调整&#xff0c;而非自适应…

港科大提出适用于夜间场景语义分割的无监督域自适应新方法

跟大家分享港科大提出的无监督域自适应夜间场景语义分割方法&#xff0c;该方法对夜间的动态目标和小目标做了针对性的优化。 论文标题&#xff1a;Towards Dynamic and Small Objects Refinement for Unsupervised Domain Adaptative Nighttime Semantic Segmentation机构&…

UGUI交互组件ScrollBar

一.ScrollBar的结构 对象说明Scrollbar挂有Image和Scrollbar组件的主体对象Sliding Area表示滑动范围Handle滑块 二.Scrollbar的属性 属性说明Handle Rect控制柄对象的引用Direction拖动控制柄时滚动条值增加的方向Value滚动条的当前值&#xff0c;范围为 0.0 到 1.0Suze控制柄…

【Python搜索算法】深度优先搜索(DFS)算法原理详解与应用,示例+代码

目录 1 基本原理 2 DFS算法流程 3 时间复杂度 4 空间复杂度 5 DFS算法应用案例&#xff1a; 5.1 解决路径查找问题 5.2 解决图的连通性问题 5.3 拓扑排序 5.4 在树结构中进行深度遍历 深度优先搜索&#xff08;DFS&#xff09;是一种重要的图遍历算法&#xff0c;用…