爬虫实训案例:中国大学排名

近一个月左右的时间学习爬虫,在用所积累的知识爬取了《中国大学排名》这个网站,爬取的内容虽然只是可见的文本,但对于初学者来说是一个很好的练习。在爬取的过程中,通过请求数据、解析内容、提取文本、存储数据等几个重要的内容入手,不过在存储数据后的数据排版方面并不是很完善(优化),希望阅读本文章的学者大大给些存储后的数据排版方面的指点:中文对齐的问题

文章目录

  • 前言🌟
  • 一、🍉从网络上获取大学排名网页内容— getHTMLText()
  • 二、🍉提取网页内容中信息到合适的数据结构— fillUnivList()
  • 三、🍉将数据保存至电脑文件夹中— Store_as_file()
  • 四、🍉主函数
  • 总结🌟


前言🌟

本次案例主要涉及bs4库中的BeautifulSoup内容、requests的使用和存储数据等知识。

在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、🍉从网络上获取大学排名网页内容— getHTMLText()

  1. 爬取的网址:https://www.shanghairanking.cn/rankings/bcur/202411
  2. 判断是否可以爬取
    在该网站的根目录下查看robots.txt文件是否可以爬取内容,这里显示没有搜索到该内容
    在这里插入图片描述

3.利用request库爬取

def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()  # 判断请求是否成功:如果不是200,产生异常requests.HTTPError
        r.encoding = r.apparent_encoding  # http header中猜测的响应内容编码方式 设置为 内容中分析出的响应内容编码方式(备选编码方式)
        return r.text
    except:
        return "请求失败"

二、🍉提取网页内容中信息到合适的数据结构— fillUnivList()

  1. 分析网页
    我们要爬取的是”排名“,”学校名称“,”省市“,”类型“,”总分“,”办学层次“等信息,如图:
  • 先是分析整体信息,需要爬取的文本信息都存放在.html网页中的<tbody></tbody>中的<tr>标签下.
    在这里插入图片描述
  • ”学校名称”在<div class="univname" data-v-90b0d2ac>标签下<a>标签中。
    在这里插入图片描述
    特征:<a>的父亲<div>标签的属性都是class="link-container"和style="width:200px
    在这里插入图片描述
  • 而”省市“,”类型“,”总分“,”办学层次“等,都是直接在<tr>标签的子代中,所以可以直接获取相关数据存放至列表中在这里插入图片描述
  1. 解析数据
    获取主要爬取的数据,存放至列表中并返回
def fillUnivList(ulist, html):
    soup = BeautifulSoup(html, 'html.parser')  # 设置BeautifulSoup解析器为'html.parser'
    soup.prettify()  # 整理解析的网页
    
    # 创建列表
    tds_name = []
    name_types = []
    tds_location = []
    tds_type = []
    tds_total = []
    tds_level = []
    try:
        # 遍历tbody的下行遍历
        for tr in soup.tbody.children:
            # 检测tr标签的类型的类型,如果tr标签的类型不是bs4库定义的tag类型,将过滤掉
            if isinstance(tr, bs4.element.Tag):  # 检查变量tr是否为BeautifulSoup库中Tag类的实例的一个条件判断语句
                # tds=str(list(tr('td')[2])[0]).strip()
                # 学校名称
                td_name = tr('td')[1]
                td_div_names = td_name.find_all('div', attrs={"style": "width:200px", "class": "link-container"})
                for div_tag in td_div_names:
                    # 另一种写法
                    # name_part = div_tag.find('a').get_text(strip=True).split('\n', 1)[0]
                    a = str(div_tag.find_all('a')[0].string).strip().split('\n')[0]
                    tds_name.append(a)
                # 学校类型
                td_name_type = tr('td')[1] \
                    .find_all('div', attrs={"class": "univname"})[0] \
                    .find_all('p', attrs={"class": "tags"})[0].get_text(strip=True)
                # 位置
                td_location = tr('td')[2].get_text(strip=True)
                # 类型
                td_type = tr('td')[3].get_text(strip=True)
                # 总分
                td_total = tr('td')[4].get_text(strip=True)
                # 办学层次
                td_level = tr('td')[5].get_text(strip=True)
                # 将各个数据添加至列表
                name_types.append(td_name_type)
                tds_location.append(td_location)
                tds_type.append(td_type)
                tds_total.append(td_total)
                tds_level.append(td_level)
                # break
        # 中文名字列表
        name_cns = tds_name[::2]
        # 英文名字列表
        name_ens = tds_name[1::2]
        i=1
        # 遍历列表大学信息,存放至空列表university中,使用zip打包,zip打包后的数据是元组
        for name_cn, name_en, name_type, location, type, total, level in \
                zip(name_cns, name_ens, name_types, tds_location, tds_type, tds_total, tds_level):
            university_data = {
                '序号':i,
                '学校名称': name_cn + " " + name_en + " " + name_type,
                '省市': location,
                '类型': type,
                '总分': total,
                '办学层次': level
            }
            i+=1
            ulist.append(university_data)
        return ulist
    except:
        return "爬取失败"

三、🍉将数据保存至电脑文件夹中— Store_as_file()

这里直接给出代码块,因为完全没有真的优化处理好爬取后的数据(还是很杂乱)

def Store_as_file(path,datas):
    # 打开文件准备写入
    with open(path, 'w', encoding='utf-8') as file:
        # 写入表头,方便阅读
        file.write("{:^10}\t{:<110}\t{:<10}\t{:<10}\t{:<10}\t{:>10}\n".format("序号","学校名称","省市","类型","总分","办学层次"))
        t="\t"*10
        # file.write(f"序号\t学校名称\t\t省市\t\t类型\t\t总分\t\t办学层次\n")
        # 遍历列表,将每个字典的内容写入文件
        for university in datas:
            # 使用制表符分隔各个字段,保证对齐
            line = "{序号:^10}\t{学校名称:<110}\t{省市:<10}\t{类型:<10}\t{总分:<10}\t{办学层次:>10}\n".format(**university)
            file.write(line)

    print(f"数据已成功保存至'{path}'")

四、🍉主函数

  1. 代码块:主函数的书写
def main():
    university = []
    num = int(input("请输入大学排名的年份:"))
    url=f"https://www.shanghairanking.cn/rankings/bcur/{num}11"
    html=getHTMLText(url)
    datas=fillUnivList(university,html)
    path=input("请输入存放内容的位置:")
    Store_as_file(path,datas)
  1. 最终效果:当然,我是确实不知道怎么更改,还望读者帮忙提供点意见

在这里插入图片描述

总结🌟

总代码块:导入requests库bs4库和bs4库中的BeautifulSoup

import requests
from bs4 import BeautifulSoup
import bs4

def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()  # 判断请求是否成功:如果不是200,产生异常requests.HTTPError
        r.encoding = r.apparent_encoding  # http header中猜测的响应内容编码方式 设置为 内容中分析出的响应内容编码方式(备选编码方式)
        return r.text
    except:
        return "请求失败"

def fillUnivList(ulist, html):
    soup = BeautifulSoup(html, 'html.parser')  # 设置BeautifulSoup解析器为'html.parser'
    soup.prettify()  # 整理解析的网页

    # 创建列表
    tds_name = []
    name_types = []
    tds_location = []
    tds_type = []
    tds_total = []
    tds_level = []
    try:
        # 遍历tbody的下行遍历
        for tr in soup.tbody.children:
            # 检测tr标签的类型的类型,如果tr标签的类型不是bs4库定义的tag类型,将过滤掉
            if isinstance(tr, bs4.element.Tag):  # 检查变量tr是否为BeautifulSoup库中Tag类的实例的一个条件判断语句
                # tds=str(list(tr('td')[2])[0]).strip()
                # 学校名称
                td_name = tr('td')[1]
                td_div_names = td_name.find_all('div', attrs={"style": "width:200px", "class": "link-container"})
                for div_tag in td_div_names:
                    # 另一种写法
                    # name_part = div_tag.find('a').get_text(strip=True).split('\n', 1)[0]
                    a = str(div_tag.find_all('a')[0].string).strip().split('\n')[0]
                    tds_name.append(a)
                # 学校类型
                td_name_type = tr('td')[1] \
                    .find_all('div', attrs={"class": "univname"})[0] \
                    .find_all('p', attrs={"class": "tags"})[0].get_text(strip=True)
                # 位置
                td_location = tr('td')[2].get_text(strip=True)
                # 类型
                td_type = tr('td')[3].get_text(strip=True)
                # 总分
                td_total = tr('td')[4].get_text(strip=True)
                # 办学层次
                td_level = tr('td')[5].get_text(strip=True)
                # 将各个数据添加至列表
                name_types.append(td_name_type)
                tds_location.append(td_location)
                tds_type.append(td_type)
                tds_total.append(td_total)
                tds_level.append(td_level)
                # break
        # 中文名字列表
        name_cns = tds_name[::2]
        # 英文名字列表
        name_ens = tds_name[1::2]
        i=1
        # 遍历列表大学信息,存放至空列表university中,使用zip打包,zip打包后的数据是元组
        for name_cn, name_en, name_type, location, type, total, level in \
                zip(name_cns, name_ens, name_types, tds_location, tds_type, tds_total, tds_level):
            university_data = {
                '序号':i,
                '学校名称': name_cn + " " + name_en + " " + name_type,
                '省市': location,
                '类型': type,
                '总分': total,
                '办学层次': level
            }
            i+=1
            ulist.append(university_data)
        return ulist
    except:
        return "爬取失败"

def Store_as_file(path,datas):
    # 打开文件准备写入
    with open(path, 'w', encoding='utf-8') as file:
        # 写入表头,方便阅读
        file.write("{:^10}\t{:<110}\t{:<10}\t{:<10}\t{:<10}\t{:>10}\n".format("序号","学校名称","省市","类型","总分","办学层次"))
        t="\t"*10
        # file.write(f"序号\t学校名称\t\t省市\t\t类型\t\t总分\t\t办学层次\n")
        # 遍历列表,将每个字典的内容写入文件
        for university in datas:
            # 使用制表符分隔各个字段,保证对齐
            line = "{序号:^10}\t{学校名称:<110}\t{省市:<10}\t{类型:<10}\t{总分:<10}\t{办学层次:>10}\n".format(**university)
            file.write(line)

    print(f"数据已成功保存至'{path}'")

def main():
    university = []
    num = int(input("请输入大学排名的年份:"))
    url=f"https://www.shanghairanking.cn/rankings/bcur/{num}11"
    html=getHTMLText(url)
    datas=fillUnivList(university,html)
    path=input("请输入存放内容的位置:")
    Store_as_file(path,datas)

if __name__ == '__main__':
    main()

最后还是想哆嗦一下,希望读者大大,和爬虫感兴趣的多找我讨论讨论,给出点建议和学习上的交流👑👑 👏👏

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot基于Web前端技术的java养老院管理系统_utbl7

3.普通用户模块包括&#xff1a;普通会员的注册、养老院客房查询、养老院留言查询、预约老人基本信息登记、选择房间、用户缴费的功能。 4.数据信息能够及时进行动态更新&#xff0c;增删&#xff0c;用户搜素方便&#xff0c;使用户可以直接浏览相关信息&#xff0c;要考虑便于…

Unity Render Streaming 云渲染 外网访问

初版&#xff1a; 日期&#xff1a;2024.5.20 前言&#xff1a;临时思路整理&#xff0c;后期会详细补充 环境&#xff1a; 1. 阿里云服务器 需要安装好nodejs 、npm 2. windows电脑&#xff0c;需安装好 nodejs 、npm 3.Unity 2021.3.15f1 4.Unity Render Streaming …

SpringBoot 实现私钥解密 前端的公钥加密内容

目录 一、前端公钥加密 二、后端私钥解密 一、前端公钥加密 Nextjs 前端实现RSA公钥加密 JSEncrypt加载问题解决-CSDN博客 二、后端私钥解密 import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.…

SQLiteOpenHelper数据库帮助器

SQLiteOpenHelper数据库帮助器是Android提供的数据库辅助工具。 1、继承SQLiteOpenHelper类&#xff0c;需要重写onCreate和onUpgrade两个方法 案例&#xff1a;实现增删改查 package com.example.databases_text;import android.app.PictureInPictureParams; import androi…

第九节 设计 Starter 不能忽视的细节

我们要定义一个生产可用的 Starter &#xff0c;还有几个细节&#xff0c;我们必须要关注。这些细节可以很好的帮助我们写出更优秀的 Starter 一、maven 包依赖 每一个 Starter&#xff0c;可以理解为一个 Jar&#xff0c;这个 Jar 包&#xff0c;如果被其他应用引用&#xf…

go-zero 实战(5)

引入Prometheus 用 Prometheus 监控应用 1. 用 docker 启动 Prometheus 编辑配置位置&#xff0c;我将 prometheus.yaml 和 targets.json 文件放在了 /opt/prometheus/conf目录下 prometheus.yaml global:scrape_interval: 15s # 抓取间隔evaluation_interval: 15s # 评估…

HarmonyOS interface router scale pageTransition SlideEffect.Left ArkTS ArkUI

&#x1f3ac;️create Component export default struct TitleBar {build(){Row(){Text(transition).fontSize(30fp).fontColor(Color.White)}.width(100%).height(8%).backgroundColor(#4169E1).padding({left:10})}}&#x1f39e;️interface export interface IList{ti…

大数据学习之安装并配置maven环境

什么是Maven Maven字面意&#xff1a;专家、内行Maven是一款自动化构建工具&#xff0c;专注服务于Java平台的项目构建和依赖管理。依赖管理&#xff1a;jar之间的依赖关系&#xff0c;jar包管理问题统称为依赖管理项目构建&#xff1a;项目构建不等同于项目创建 项目构建是一…

本地idea连接虚拟机linux中的docker进行打包镜像上传--maven的dockerfile-maven-plugin插件

项目名必须是英文,-,.,_,这些数字,idea需要管理员运行,因为idea控制台mvn命令需要管理员权限才能运行(maven需配置环境变量)改linux中的Docker服务文件,使用2375 进行非加密通信,然后加载重启 2.1 #修改Docker服务文件 vi /lib/systemd/system/docker.service ​ # 通常使…

TI C2000 FLASH 模拟 EEPROM

简述 FLASH和EEPROM同为非易失存储器,互有优势。 FLASH Flash是非易失性存储器(NVM)的一种形式。相对于EEPROM,Flash具有更高的存储密度和更快的写入速度。Flash内部被分为多个扇区,每个扇区都可以单独擦除和写入。但是寿命相比EEPROM较短,以TI芯片为例,flash擦写次数在…

go 微服务框架 kratos 日志库使用方法及原理探究

一、Kratos 日志设计理念 kratos 日志库相关的官方文档&#xff1a;日志 | Kratos Kratos的日志库主要有如下特性&#xff1a; Logger用于对接各种日志库或日志平台&#xff0c;可以用现成的或者自己实现Helper是在您的项目代码中实际需要调用的&#xff0c;用于在业务代码里…

正点原子LWIP学习笔记(三)PHY芯片简介

PHY芯片简介 一、PHY芯片简介&#xff08;了解&#xff09;二、LAN8720A与YT8512C简介&#xff08;熟悉&#xff09;三、PHY地址的设置&#xff08;掌握&#xff09;四、RMII模式选择&#xff08;熟悉&#xff09;五、PHY寄存器简介&#xff08;熟悉&#xff09; 一、PHY芯片简…

AIGC绘画设计基础-建筑设计应用

一、AI及AIGC 对于AI大家都不陌生&#xff0c;但是AIGC这个概念好多人其实不大清楚。“AI”是指人工智能技术本身&#xff0c;而“AIGC”是指基于人工智能技术而生成的内容。 生成式人工智能——AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;&…

Java类和对象(五)—— 抽象类、接口、Object类和内部类

抽象类 在继承体系下&#xff0c;父类有些方法可能是要被重写的&#xff0c;如果我们事先就知道某些方法需要重写的话&#xff0c;我们可以不用在父类里面具体实现这个方法&#xff0c;这时候我们会用到抽象方法&#xff0c;这时候我们会用到关键字abstract关键字来修饰 publ…

Thinkphp内核开发盲盒商城源码v2.0 对接易支付/阿里云短信/七牛云存储

源码简介 这套系统是我从以前客户手里拿到的,100完整可用,今天测试防红链接失效了,需要修改防红API即可!前端页面展示我就不放了,懂的都懂 优点是Thinkphp开发的&#xff0c;二开容易。 源码图片 资源获取&#xff1a;Thinkphp内核开发盲盒商城源码v2.0 对接易支付/阿里云短…

有些错误,常犯常新、常新常犯:记录一个使用element-plus的tooltip组件的错误

使用element-plus的tooltip组件&#xff0c;最开始的写法是这样的&#xff1a; <el-tooltipclass"box-item"effect"dark"content"tooltip content" ><el-button v-if"isDisabled" :underline"false" type"pr…

【实战】SpringBoot整合Websocket、Redis实现Websocket集群负载均衡

文章目录 前言技术积累什么是Websocket什么是Redis发布订阅Redis发布订阅与消息队列的区别 实战演示SpringBoot整合WebsoketWebsoket集群负载均衡 实战测试IDEA启动两台服务端配置nginx负载均衡浏览器访问模拟对话 前言 相信很多同学都用过websocket来实现服务端主动向客户端推…

Web前端一套全部清晰 ⑨ day5 CSS.4 标准流、浮动、Flex布局

我走我的路&#xff0c;有人拦也走&#xff0c;没人陪也走 —— 24.5.24 一、标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如:块元素独占一行&#xff0c;行内元素可以一行显示多个。 二、浮动 作用: 让块级元素水平排列。 属性名:floa…

瑞米派Ubuntu系统移植指南-米尔RemiPi

1.概述 Linux系统平台上有许多开源的系统构建框架&#xff0c;这些框架方便了开发者进行嵌入式系统的构建和定制化开发&#xff0c;目前比较常见的有Buildroot, Yocto, OpenEmbedded等等。 同时更多的传统的桌面系统也加入到嵌入式环境体系中&#xff0c;如Ubuntu&#xff0c…

启动docker报错:Failed to listen on Docker Socket for the API.

说明&#xff1a; 1、安装部署docker完成后&#xff0c;启动docker报错&#xff1a;Failed to listen on Docker Socket for the API&#xff0c;如下图所示&#xff1a; 2、将SocketGroupdocker更改成&#xff1a;SocketGrouproot即可 一、解决方法&#xff1a; 1、执行命令…