Python批量获取高校基本信息

news/2024/7/7 23:19:22

文章目录

  • 前言
  • 一、需求
  • 二、分析
  • 三、处理
  • 四、运行效果


前言

为了更好的掌握数据处理的能力,因而开启Python网络爬虫系列小项目文章。

  1. 小项目小需求驱动,每篇文章会使用两种以上的方式(Xpath、Bs4、PyQuery、正则等)获取想要的数据。
  2. 博客系列完结后,将会总结各种方式。

一、需求

  • 获取高校数据

    • 高校排行(软科综合、校友会综合、武书连)
    • 基本信息(博士点、硕士点、创建时间、占地面积、学校地址)
  • 多种数据存储方式

    • 本地文件存储

    • redis

    • MongoDB

二、分析

F12 打开抓包工具,刷新https://www.gaokao.cn/school/search接口页面

在这里插入图片描述

name.json 接口包含所有的高校id

在这里插入图片描述

进入学校详情页,获取到info.json接口信息

在这里插入图片描述

数据可以直接通过请求接口即可返回
已获取学校id(一共2820个数据,可以用上协程异步访问提高获取的数据的速度)
已获取学校信息的接口https://static-gkcx.gaokao.cn/www/2.0/json/live/v2/school/102/info.json(只需要修改下学校id即可访问其它学校信息)

三、处理

编写获取大学id的接口


import requests
import json
HEADERS = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"}

# 获取大学school_id
def get_school_id():
    url= "https://static-data.gaokao.cn/www/2.0/school/name.json"
    res = requests.request("GET",url=url,headers=HEADERS)
    res.encoding = "utf-8"
    # 转为json格式
    data = json.loads(res.text)
    return data

获取一次以后,本地可以进行处理提取学校id

import re
def get_id():
    f = open("name.txt", "r", encoding="utf-8")
    f1 = f.read()
    deal = re.compile(r"'school_id': '(?P<id>.*?)'",re.S)
    result = deal.findall(f1)
    # print(len(result))
    f.close()
    return  result

编写访问学校信息的接口请求


def get_school_info_1():
    url = "https://static-data.gaokao.cn/www/2.0/school/3419/info.json"
    res = requests.request("GET",url=url,headers=HEADERS)
    res.encoding = "utf-8"
    # 转为json格式
    data = json.loads(res.text)
    return data

协程异步访问接口请求(本地文件存储)

import asyncio
import aiohttp
import aiofiles


# 获取学校详细信息
async def get_school_info(url,sem):
    try:
        async with sem:
            async with aiohttp.ClientSession() as session:
                # 发送请求
                async with session.get(url) as res:
                    # 读取数据
                    content = await res.text(encoding="utf-8")
                    data = json.loads(content)
                    # 高校排行- 软科综合/校友会排名/武书连/US世界
                    school_info = {}
                    school_info["学校名称"] = data["data"]["name"]
                    school_info["软科综合"] = data["data"]["ruanke_rank"]
                    school_info["武书连"] = data["data"]["wsl_rank"]
                    school_info["校友会"] = data["data"]["xyh_rank"]
                    school_info["US世界"] = data["data"]["us_rank"]
                    # 博士点/硕士点/国家重点学科
                    school_info["博士点"] = data["data"]["num_doctor"]
                    school_info["硕士点"] = data["data"]["num_master"]
                    school_info["国家重点学科"] = data["data"]["num_subject"]
                    # 创建时间/占地面积/学校地址
                    school_info["创建时间"] = data["data"]["create_date"]
                    school_info["占地面积"] = data["data"]["area"]
                    school_info["学校地址"] = data["data"]["address"]
                    # 写入文件
                    async with aiofiles.open("school_info.txt",mode="a") as f:
                        await f.write(f"{str(school_info)}\n")
                        print("一条数据下载完毕!")
    except Exception as e:
        print(e)
 
 async def main(list_id):
    # 添加信号量控制速度
    sem = asyncio.Semaphore(100)
    tasks = []
    for i in list_id:
        # https://static-data.gaokao.cn/www/2.0/school/3419/info.json
        url = f"https://static-data.gaokao.cn/www/2.0/school/{i}/info.json"
        # 创建任务
        task = asyncio.create_task(get_school_info(url,sem))
        tasks.append(task)
    await asyncio.wait(tasks)



if __name__ == '__main__':
    # 本地获取id
    id_list = get_id()
  	asyncio.run(main(id_list))

写入Redis数据库,
如有报错DataError: Invalid input of type: ‘NoneType’. Convert to a byte, string or number first.
解决方法,降低redis版本 pip install redis==2.10.6

# 获取学校详细信息
async def get_school_info(url,sem):
    try:
        async with sem:
            async with aiohttp.ClientSession() as session:
                # 发送请求
                async with session.get(url) as res:
                    # 读取数据
                    content = await res.text(encoding="utf-8")
                    data = json.loads(content,encoding="utf-8")
                    # 高校排行- 软科综合/校友会排名/武书连/US世界
                    school_info = {}
                    school_name = data["data"]["name"]
                    school_info["软科综合"] = data["data"]["ruanke_rank"]
                    school_info["武书连"] = data["data"]["wsl_rank"]
                    school_info["校友会"] = data["data"]["xyh_rank"]
                    school_info["US世界"] = data["data"]["us_rank"]
                    # 博士点/硕士点/国家重点学科
                    school_info["博士点"] = data["data"]["num_doctor"]
                    school_info["硕士点"] = data["data"]["num_master"]
                    school_info["国家重点学科"] = data["data"]["num_subject"]
                    # 创建时间/占地面积/学校地址
                    school_info["创建时间"] = data["data"]["create_date"]
                    school_info["占地面积"] = data["data"]["area"]
                    school_info["学校地址"] = data["data"]["address"]
                    # 写入redis文件中
                    r = connect_redis()
                    r.hset("school",school_name,json.dumps(school_info))
                    print("一条数据写入成功")
    except Exception as e:
        print(e)
  
  # 连接Redis数据库
def connect_redis():
    pool  = redis.ConnectionPool(host="127.0.0.1", port=6379,db=3)
    r = redis.Redis(connection_pool=pool)
    return r

写入MongoDB数据库



import pymongo
from pymongo import MongoClient
# MongoDB数据库初始化
def get_db(database,user=None,pwd=None):
    client = MongoClient(host="localhost",port=27017)
    db = client[database]
    # 有账号密码即验证
    if user:
        db.authenticate(user,pwd)
    return db

# 增加多条数据
def insert_data_many(collection, data):
    db = get_db("school")
    result = db[collection].insert_many(data)
    return result

async def get_s
chool_info(url,sem):
    try:
        async with sem:
            async with aiohttp.ClientSession() as session:
                # 发送请求
                async with session.get(url) as res:
                    # 读取数据
                    content = await res.text(encoding="utf-8")
                    data = json.loads(content,encoding="utf-8")
                    # 高校排行- 软科综合/校友会排名/武书连/US世界
                    school_info = {}
                    school_info["学校名称"] = data["data"]["name"]
                    school_info["软科综合"] = data["data"]["ruanke_rank"]
                    school_info["武书连"] = data["data"]["wsl_rank"]
                    school_info["校友会"] = data["data"]["xyh_rank"]
                    school_info["US世界"] = data["data"]["us_rank"]
                    # 博士点/硕士点/国家重点学科
                    school_info["博士点"] = data["data"]["num_doctor"]
                    school_info["硕士点"] = data["data"]["num_master"]
                    school_info["国家重点学科"] = data["data"]["num_subject"]
                    # 创建时间/占地面积/学校地址
                    school_info["创建时间"] = data["data"]["create_date"]
                    school_info["占地面积"] = data["data"]["area"]
                    school_info["学校地址"] = data["data"]["address"]
                    insert_data_many("school",[school_info])
                    print("一条数据写入成功")
    except Exception as e:
        print(e)
        

四、运行效果

通过Redis可视化工具查看写入的2821条数据

在这里插入图片描述

MongoDB可视化工具查询数据

在这里插入图片描述

本地读取数据

请添加图片描述

完整源码文件附在在知识星球
我正在「Python^self-study」和朋友们讨论有趣的话题,你⼀起来吧?
https://t.zsxq.com/076uG3kOn


http://lihuaxi.xjx100.cn/news/115917.html

相关文章

反射是什么

什么是反射 反射机制是&#xff1a;在运行状态中&#xff0c;对于任意一个类&#xff0c;对象&#xff0c;都能够知道所有属性和方法&#xff0c;并且能修改它。 反射机制允许程序在运行时取得任何一个已知名称的class的内部信息 类名 用途 Class 类 代表类的实体&#xf…

【C++】【LeetCode】【二叉树的前序、中序、后序遍历】【递归+非递归】

目录 一、二叉树的前序遍历 递归解法 非递归解法 二、二叉树的中序遍历 递归解法 非递归解法 三、二叉树的后序遍历 递归解法 非递归解法 默认情况下&#xff0c;一个线程的栈空间大小为8MB&#xff0c;当递归的深度太深&#xff0c;我们的程序就容易崩溃 如果递归的…

《机器学习实战》6.支持向量机(SVM)

本章涉及到的向相关代码和数据 SVM有很多种实现方法&#xff0c;但是这里学习最流行的一种&#xff0c;即序列最小化&#xff08;SMO&#xff09;算法。在此之后&#xff0c;将介绍如何使用一种称为核函数的方式奖SVM拓展到更多数据集上 1 基于最大间隔分隔数据 优点&#xf…

固定资产管理系统给企业带来的价值?

一套好用的固定资产管理系统不仅能帮助企业提升95%的盘点效率&#xff0c;提升35%的固定资产利用率&#xff0c;还能降低企业固定资产的重复采购率&#xff0c;从而帮企业节省开支&#xff0c;降低企业的整体运营成本。 易点易动为企业提供固定资产全生命周期管理平台。凭借多…

数据库练习题

写在前面 这篇文章是一些关于数据库的练习题&#xff0c;所用的数据库为学生课程数据库&#xff0c;其中有三张表分别为学生表&#xff08;student&#xff09;、课程表&#xff08;course&#xff09;、成绩表&#xff08;sc&#xff09;。学生表有6列&#xff0c;分别为学号&…

asp.net员工管理系统VS开发sqlserver数据库web结构c#编程计算机网页项目

一、源码特点 ASP.NET员工管理系统是一套完善的计算机web设计系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 。 asp.net员工管理系统VS开发sqlserv…

git cherry-pick 报错 fatal: bad object [commitID]

背景 项目不同模块的功能建立了不同的分支进行开发&#xff0c;后期要将这部分代码从附属分支往主分支上合并&#xff0c;合并过程中出现这个问题&#xff0c;特此纪要&#xff01; 问题 git cherry-pick [commitID]时报错&#xff1f; 错误图录&#xff1a; 说明 cherry-pick做…

[ Linux ] 一篇带你搞懂进程控制(看完可实现一个简易的shell)

本文前半部分和上篇文章相同&#xff0c;之所以加进来是因为这两篇文章均是进程控制部分内容。如果大家已经看过前两部分内容&#xff0c;可直接从2.1起看&#xff01; 目录 0.进程创建 fork()之后&#xff0c;操作系统做了什么&#xff1f; 写时拷贝 fork调用失败的原因 …