“阳光高考爬虫项目揭秘:增量爬虫与断点续抓的Python实战“

news2024/9/23 15:22:18

阳光高考项目

项目要求

爬取各大高校基本信息和招生简章(招生简章要求存储为pdf格式并且入库)

数据库表设计

image-20240805162050198

  • id
  • task_url
  • status:0(未抓取),1(抓取中),2(抓取完毕),3(错误),4(更新中),5(数据更新成功),6(数据未更新,保持原样),9(暂无),8(暂无)
    • 3:错误,是因为此div下根本没p标签,所以根本等不到导致超时错误await page.waitForXPath(‘//div[@class=“content zszc-content UEditor”]//p’),可以单独处理,总共4个
    • 特殊的能等待到的,有的是多个p标签、有的是多个div标签、有的是表格,都已经做了单独的处理
  • university_name
  • competent_department
  • educational_background
  • title
  • contents

阳光简章1

由于两次页面跳转,会将之前的page对象销毁,无法进行item的循环爬取,所以应先根据item循环抓取task_url和必要数据入库

后续再读取task_url进行爬取

源码:

import asyncio  # 协程
from pyppeteer import launch
from pyppeteer_stealth import stealth  # 消除指纹
from lxml import etree  # xpath解析数据
import pymysql

width, height = 1366, 768  # 设置浏览器宽度和高度

conn = pymysql.connect(user='root', password='123456', db='sunshine')
cursor = conn.cursor()


async def main():
    # 设置启动时是否开启浏览器可视,消除控制条信息
    browser = await launch(headless=False, args=['--disable-infobars'])  # 设置浏览器和添加属性
    # 开启一个页面对象
    page = await browser.newPage()
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 消除指纹
    await stealth(page)  # <-- Here
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 访问第一页
    await page.goto(
        'https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--method-index,ssdm-,yxls-,xlcc-,zgsx-,yxjbz-,start-0.dhtml')
    await page.waitForXPath('//li[@class="ivu-page-item"]/@title')  # 根据xpaath来等待某个节点出现
    # 获取最大页
    max_page_1 = await page.xpath('//li[@class="ivu-page-item"]/@title')
    max_page = await (await max_page_1[-1].getProperty("textContent")).jsonValue()
    # print(max_page)
    for pp in range(int(max_page)):
        print(pp*100)
        await page.goto('https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--method-index,ssdm-,yxls-,xlcc-,zgsx-,yxjbz-,start-{}.dhtml'.format(pp*100))
        # 爬取单页数据
        await asyncio.sleep(2)
        # 等待元素出现 根据CSS选择器的语法等待某个节点出现,跟pyquery语法差不多
        await page.waitForSelector('div.info-box')
        # 拉滚动条
        # arg1: 文档向右滚动的像素数 arg2: 文档向下滚动的像素数
        await page.evaluate('window.scrollBy(200, document.body.scrollHeight)')
        # 等待最后一个商品出现
        await asyncio.sleep(2)

        # 解析单页数据
        div_list = await page.xpath('//div[@class="info-box"]')
        for i in div_list:
            university_name_1 = await i.xpath('div[1]/a')
            competent_department_1 = await i.xpath('a[1]')
            educational_background_1 = await i.xpath('a[2]')
            # 大学名称
            university_name = await (await university_name_1[0].getProperty("textContent")).jsonValue()
            # 接管部门
            competent_department = await (await competent_department_1[0].getProperty("textContent")).jsonValue()
            # 教育背景
            educational_background = await (await educational_background_1[0].getProperty("textContent")).jsonValue()
            educational_background = educational_background.replace('\n', '')
            educational_background = educational_background.replace(' ', '')
            # 简章url
            # zszc-link text-decoration-none no-info
            # zszc-link text-decoration-none
            task_url_1 = await i.xpath('a[@class=\"zszc-link text-decoration-none\" and not(contains(@class, \"no-info\"))]/@href')
            if len(task_url_1) > 0:
                task_url = await (await task_url_1[0].getProperty("textContent")).jsonValue()
                task_url = "https://gaokao.chsi.com.cn{}".format(task_url)
                sql = 'insert into tasks(task_url,status,university_name,competent_department,educational_background)' \
                      ' values(\"{}\", \"0\", \"{}\", \"{}\", \"{}\")'.format(task_url.strip(), university_name.strip(),
                                                              competent_department.strip(), educational_background.strip())
            else:
                task_url = "暂无"
                sql = 'insert into tasks(task_url,status,university_name,competent_department,educational_background)' \
                      ' values(\"{}\", \"9\", \"{}\", \"{}\", \"{}\")'.format(task_url.strip(), university_name.strip(),
                                                              competent_department.strip(), educational_background.strip())
            # strip去空格: xpath获取到的数据左右可能有空格, 占用数据库空间
            # print(1, university_name.strip(), 2, conpetent_department.strip(), 3, educational_background.strip(), 4,
            #       task_url.strip())
            # print(sql)
            cursor.execute(sql)
            conn.commit()
    await asyncio.sleep(100)


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())

阳光简章2

源码:

import asyncio  # 协程
import multiprocessing
import time

from pyppeteer import launch
from pyppeteer_stealth import stealth  # 消除指纹
from lxml import etree  # xpath解析数据
import pymysql
from pymysql.converters import escape_string
import os

width, height = 1366, 768  # 设置浏览器宽度和高度

r = redis.Redis(host="127.0.0.1", port=6379, db=1)

MAX_RETRIES = 3

# 章节页面保存成pdf或者word 并存入数据库
# 多进程或者多协程提高抓取速度
# 断点续抓
# 增量爬虫

async def main():
    conn = pymysql.connect(user='root', password='123456', db='sunshine')
	cursor = conn.cursor()
    # 设置启动时是否开启浏览器可视,消除控制条信息
    global retries
    browser = await launch(headless=True, args=['--disable-infobars'])  # 设置浏览器和添加属性
    # 开启一个页面对象
    page = await browser.newPage()
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 消除指纹
    await stealth(page)  # <-- Here
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 访问某个页面
    allline = get_count()
    for i in range(allline):
        retries = 0  # 重置重试次数
        result = get_task()
        url = result[1]
        id = result[0]
        while retries < MAX_RETRIES:
            await page.goto(url)
            # 智能等待: 不能百分百确定一定有这个链接, 所以错误处理
            try:
                await page.waitForXPath('//a[@class="zszc-zc-title"]/@href')
            except:
                sql = 'update tasks set status=\"8\" where id = {}'.format(id)
                cursor.execute(sql)
                conn.commit()
                continue
            # info_url
            info_url_1 = await page.xpath('//a[@class="zszc-zc-title"]/@href')
            info_url = await (await info_url_1[0].getProperty("textContent")).jsonValue()
            info_url = "https://gaokao.chsi.com.cn{}".format(info_url)
            # 访问info_url
            await page.goto(info_url)
            # 智能等待
            try:
                await page.waitForXPath('//div[@class="content zszc-content UEditor"]//p')
            except Exception:
                retries += 1
                await asyncio.sleep(1)
                continue
            # title
            title = await page.xpath('//h2[@class="zszc-content-title"]')
            title = await (await title[0].getProperty("textContent")).jsonValue()
            # 截图成为pdf
            # 目前只支持无头模式的有头的不行
            if not os.path.isdir('阳光/pdf'):
                os.makedirs('阳光/pdf')
            await page.pdf({'path': '阳光/pdf/{}.pdf'.format(title), 'format': 'a4'})

            # contents
            contents_p = await page.xpath('//div[@class="content zszc-content UEditor"]//p')
            contents_list = '\n'.join([await (await x.getProperty("textContent")).jsonValue() for x in contents_p])
            # 处理表格等特殊情况
            if not contents_list.strip():
                # content_div = await page.xpath('//table')[0].xpath('string(.)')
                # content_list = await (await content_div[0].getProperty("textContent")).jsonValue()
                # print(55555,content_list)
                try:
                    content = etree.HTML(await page.content()).xpath('//table')[0]
                    contents = escape_string(etree.tostring(content, encoding='utf-8').decode())
                except IndexError:
                    pass
                try:
                    contents_div = await page.xpath('//div[@class="content zszc-content UEditor"]//div')
                    contents_list = '\n'.join(
                        [await (await x.getProperty("textContent")).jsonValue() for x in contents_div])
                    contents = escape_string(contents_list)
                except Exception:
                    pass
                # print(555555, content_list)
            else:
                # escape_string: 对文本中单双引号进行转义, 防止单双引号冲突
                contents = escape_string(contents_list)
                # print(title, contents_list)
            print(title)

            # 入库
            sql = 'update tasks set title=\"{}\", contents=\"{}\", status=\"2\" where id={}'.format(title, contents, id)
            cursor.execute(sql)
            conn.commit()
            break
        if retries == 3:
            sql = 'update tasks set status=\"3\" where id={}'.format(id)
            cursor.execute(sql)
            conn.commit()

    # 关闭浏览器
    await browser.close()


# 获取任务数目
def get_count():
    conn = pymysql.connect(user='root', password='123456', db='sunshine')
	cursor = conn.cursor()
    sql = 'select count(*) from tasks where status=\"0\"'
    cursor.execute(sql)
    result = cursor.fetchone()
    print(result)
    return result[0]


# 获取一个任务
def get_task():
    conn = pymysql.connect(user='root', password='123456', db='sunshine')
	cursor = conn.cursor()
    sql = 'select * from tasks where status=\"0\"'
    cursor.execute(sql)
    result = cursor.fetchone()
    sql1 = 'update tasks set status=\"1\" where id={}'.format(result[0])
    cursor.execute(sql1)
    conn.commit()
    return result


# 仅基于异步运行
def run_async():
    asyncio.get_event_loop().run_until_complete(main())


# 多进程运行
def run_mutiprocess():
    pool = multiprocessing.Pool(8)
    for _ in range(8):
        # multiprocessing.Pool 是为同步函数设计的, 如果必须使用 multiprocessing,确保每个进程内有自己的事件循环。
        pool.apply_async(run_async)
    print('Waiting for all subprocesses done...')
    pool.close()
    pool.join()
    print('All subprocesses done.')


async def run_gather():
    tasks = [main() for _ in range(8)]
    await asyncio.gather(*tasks)


# 多协程运行
def run_coroutine():
    asyncio.get_event_loop().run_until_complete(run_gather())


if __name__ == '__main__':
    start_time = time.time()
    # 仅基于异步
    # run_async()
    # 多进程
    run_mutiprocess()
    # 多协程
    # run_coroutine()
    end_time = time.time()
    print("总共耗时: {}".format(end_time - start_time))

多进程

33 min

image-20240805165426200

多协程

项目亮点

上面项目的面试点

status字段有1的必要性

多进程共享资源的问题:
如果没有1,则多进程爬取数据时存在多个进程抢占同一个资源的情况,而程序在爬取此task_url时将status字段设置为1则避免了这种情况的发生

异常处理

一般出现在智能等待(超时错误导致的一系列错误),设立重试机制,达到最大重试次数,将status字段设置为0,后续会重新进行抓取,防止异常发生导致程序终止

完善上面项目

断点续抓

人为中断程序,下次再此运行程序抓取数据能够保证继续抓取

# 完善项目: 断点续抓
async def crawler_resumpt():
    conn = pymysql.connect(user='root', password='123456', db='sunshine')
	cursor = conn.cursor()
    sql = 'select * from tasks where status=\"1\" or status=\"0\" order by id'
    cursor.execute(sql)
    results = cursor.fetchall()
    # 设置启动时是否开启浏览器可视,消除控制条信息
    global retries
    browser = await launch(headless=True, args=['--disable-infobars'])  # 设置浏览器和添加属性
    # 开启一个页面对象
    page = await browser.newPage()
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 消除指纹
    await stealth(page)  # <-- Here
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    for result in results:
        # 访问某个页面
        retries = 0  # 重置重试次数
        url = result[1]
        id = result[0]
        while retries < MAX_RETRIES:
            await page.goto(url)
            # 智能等待: 不能百分百确定一定有这个链接, 所以错误处理
            try:
                await page.waitForXPath('//a[@class="zszc-zc-title"]/@href')
            except:
                sql = 'update tasks set status=\"8\" where id = {}'.format(id)
                cursor.execute(sql)
                conn.commit()
                continue
            # info_url
            info_url_1 = await page.xpath('//a[@class="zszc-zc-title"]/@href')
            info_url = await (await info_url_1[0].getProperty("textContent")).jsonValue()
            info_url = "https://gaokao.chsi.com.cn{}".format(info_url)
            # 访问info_url
            await page.goto(info_url)
            # 智能等待
            try:
                await page.waitForXPath('//div[@class="content zszc-content UEditor"]//p')
            except Exception:
                retries += 1
                await asyncio.sleep(1)
                continue
            # title
            title = await page.xpath('//h2[@class="zszc-content-title"]')
            title = await (await title[0].getProperty("textContent")).jsonValue()
            # 截图成为pdf
            # 目前只支持无头模式的有头的不行
            if not os.path.isdir('阳光/pdf'):
                os.makedirs('阳光/pdf')
            await page.pdf({'path': '阳光/pdf/{}.pdf'.format(title), 'format': 'a4'})

            # contents
            contents_p = await page.xpath('//div[@class="content zszc-content UEditor"]//p')
            contents_list = '\n'.join([await (await x.getProperty("textContent")).jsonValue() for x in contents_p])
            # 处理表格特殊情况
            if not contents_list.strip():
                # content_div = await page.xpath('//table')[0].xpath('string(.)')
                # content_list = await (await content_div[0].getProperty("textContent")).jsonValue()
                # print(55555,content_list)
                content = etree.HTML(await page.content()).xpath('//table')[0]
                contents = escape_string(etree.tostring(content, encoding='utf-8').decode())
                # print(555555, content_list)
            else:
                # escape_string: 对文本中单双引号进行转义, 防止单双引号冲突
                contents = escape_string(contents_list)
                # print(title, contents_list)
            print(title)

            # 入库
            sql = 'update tasks set title=\"{}\", contents=\"{}\", status=\"2\" where id={}'.format(title, contents,
                                                                                                    id)
            cursor.execute(sql)
            conn.commit()
            break
        if retries == 3:
            sql = 'update tasks set status=\"0\" where id={}'.format(id)
            cursor.execute(sql)
            conn.commit()
    # 关闭浏览器
    await browser.close()

增量爬虫,指纹去重

指纹:将抓取数据拼接成字符串,并通过md5或sha1加密形成的密钥字符串即为指纹

将指纹和id存储在redis数据库的无序集合中

后续抓取数据时,构造密钥字符串,根据是否含有此密钥字符串进行去重,若有,则放弃数据更新,若无,则根据id进行数据更新

初始爬虫源码:

# 入库
sql = 'update tasks set title=\"{}\", contents=\"{}\", status=\"2\" where id={}'.format(title, contents, id)
cursor.execute(sql)
conn.commit()
# 指纹入库
data = title + contents
r.sadd("sunshine:key", encryption(data))

增量爬虫源码:

import asyncio  # 协程
import multiprocessing
import time

from pyppeteer import launch
from pyppeteer_stealth import stealth  # 消除指纹
from lxml import etree  # xpath解析数据
import pymysql
from pymysql.converters import escape_string
import os
import redis
import hashlib

width, height = 1366, 768  # 设置浏览器宽度和高度

r = redis.Redis(host="127.0.0.1", port=6379, db=1)

MAX_RETRIES = 3


async def main():
    conn = pymysql.connect(user='root', password='123456', db='sunshine2')
    cursor = conn.cursor()
    # 设置启动时是否开启浏览器可视,消除控制条信息
    global retries, contents
    browser = await launch(headless=True, args=['--disable-infobars'])  # 设置浏览器和添加属性
    # 开启一个页面对象
    page = await browser.newPage()
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 消除指纹
    await stealth(page)  # <-- Here
    # 设置浏览器宽高
    await page.setViewport({'width': width, 'height': height})
    # 访问某个页面
    allline = get_count()
    for i in range(allline):
        retries = 0  # 重置重试次数
        result = get_finished_task()
        url = result[1]
        id = result[0]
        while retries < MAX_RETRIES:
            await page.goto(url)
            # 智能等待: 不能百分百确定一定有这个链接, 所以错误处理
            try:
                await page.waitForXPath('//a[@class="zszc-zc-title"]/@href')
            except:
                sql = 'update tasks set status=\"8\" where id = {}'.format(id)
                cursor.execute(sql)
                conn.commit()
                continue
            # info_url
            info_url_1 = await page.xpath('//a[@class="zszc-zc-title"]/@href')
            info_url = await (await info_url_1[0].getProperty("textContent")).jsonValue()
            info_url = "https://gaokao.chsi.com.cn{}".format(info_url)
            # 访问info_url
            await page.goto(info_url)
            # 智能等待
            try:
                await page.waitForXPath('//div[@class="content zszc-content UEditor"]//p')
            except Exception:
                retries += 1
                await asyncio.sleep(1)
                continue
            # title
            title = await page.xpath('//h2[@class="zszc-content-title"]')
            title = await (await title[0].getProperty("textContent")).jsonValue()
            # 截图成为pdf
            # 目前只支持无头模式的有头的不行
            if not os.path.isdir('阳光/pdf'):
                os.makedirs('阳光/pdf')
            await page.pdf({'path': '阳光/pdf/{}.pdf'.format(title), 'format': 'a4'})

            # contents
            contents_p = await page.xpath('//div[@class="content zszc-content UEditor"]//p')
            contents_list = '\n'.join([await (await x.getProperty("textContent")).jsonValue() for x in contents_p])
            # 处理表格等特殊情况
            if not contents_list.strip():
                # content_div = await page.xpath('//table')[0].xpath('string(.)')
                # content_list = await (await content_div[0].getProperty("textContent")).jsonValue()
                # print(55555,content_list)
                try:
                    content = etree.HTML(await page.content()).xpath('//table')[0]
                    contents = escape_string(etree.tostring(content, encoding='utf-8').decode())
                except IndexError:
                    pass
                try:
                    contents_div = await page.xpath('//div[@class="content zszc-content UEditor"]//div')
                    contents_list = '\n'.join(
                        [await (await x.getProperty("textContent")).jsonValue() for x in contents_div])
                    contents = escape_string(contents_list)
                except Exception:
                    pass
                # print(555555, content_list)
            else:
                # escape_string: 对文本中单双引号进行转义, 防止单双引号冲突
                contents = escape_string(contents_list)
                # print(title, contents_list)
            print(title)

            # 入库
            data = title + contents
            if not is_crawlered(data):
                print("数据更新...")
                sql = 'update tasks set title=\"{}\", contents=\"{}\", status=\"5\" where id={}'.format(title, contents,
                                                                                                        id)
                cursor.execute(sql)
                conn.commit()
            else:
                print("数据已爬取过...")
                sql = 'update tasks set status=\"6\" where id={}'.format(id)
                cursor.execute(sql)
                conn.commit()
            break
        if retries == 3:
            sql = 'update tasks set status=\"3\" where id={}'.format(id)
            cursor.execute(sql)
            conn.commit()

    # 关闭浏览器
    await browser.close()


# 获取任务数目
def get_count():
    conn = pymysql.connect(user='root', password='123456', db='sunshine2')
    cursor = conn.cursor()
    sql = 'select count(*) from tasks where status=\"2\"'
    cursor.execute(sql)
    result = cursor.fetchone()
    print(result)
    return result[0]


# md5加密
def encryption(data):
    md5 = hashlib.md5()
    md5.update(data.encode("utf-8"))
    return md5.hexdigest()


# 获取一个已完成的任务
def get_finished_task():
    conn = pymysql.connect(user='root', password='123456', db='sunshine2')
    cursor = conn.cursor()
    sql = 'select * from tasks where status=\"2\"'
    cursor.execute(sql)
    result = cursor.fetchone()
    sql1 = 'update tasks set status=\"4\" where id={}'.format(result[0])
    cursor.execute(sql1)
    conn.commit()
    return result


# 去重
def is_crawlered(data):
    res = r.sadd("sunshine:key", encryption(data))
    return res == 0


# 仅基于异步运行
def run_async():
    asyncio.get_event_loop().run_until_complete(main())


# 多进程运行
def run_mutiprocess():
    pool = multiprocessing.Pool(8)
    for _ in range(8):
        # multiprocessing.Pool 是为同步函数设计的, 如果必须使用 multiprocessing,确保每个进程内有自己的事件循环。
        pool.apply_async(run_async)
    print('Waiting for all subprocesses done...')
    pool.close()
    pool.join()
    print('All subprocesses done.')


async def run_gather():
    tasks = [main() for _ in range(4)]
    await asyncio.gather(*tasks)


# 多协程运行
def run_coroutine():
    asyncio.get_event_loop().run_until_complete(run_gather())


if __name__ == '__main__':
    start_time = time.time()
    # 仅基于异步
    # run_async()
    # 多进程
    run_mutiprocess()
    # 多协程
    # run_coroutine()
    end_time = time.time()
    print("总共耗时: {}".format(end_time - start_time))

更多精致内容:

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

C语言小练习(叁)

个人练习&#xff1a; 编程题&#xff1a; 1.编写一个函数&#xff0c;通过输入球的半径&#xff0c;返回球的体积&#xff1b; #include <stdio.h> #define pi 3.14 //计算球体积的函数 double v_ball(double r) {return 4.0 / 3.0 * pi * r * r * r; }int main() {d…

InfluxDB Studio 下载,时序数据库Windows图形界面操作

下载地址&#xff1a; https://github.com/CymaticLabs/InfluxDBStudio/releases解压缩后&#xff0c;双击 InfluxDBStudio.exe 运行。 参考 windows下 influxDB 操作工具 InfluxDBStudio 吐槽 现在 CSDN 太恶心了&#xff0c;动不动就让订阅或者积分下载资源。诚然&#…

【Python学习-UI界面】pyqt5页面布局

1、布局分类 序号类别描述1QBoxLayout可将小部件垂直或水平排列。它的派生类有QVBoxLayout&#xff08;用于垂直排列小部件&#xff09;和QHBoxLayout&#xff08;用于水平排列小部件&#xff09;。2QGridLayout对象呈现为行和列排列的单元格网格。该类包含addWidget()方法&am…

艾迈斯欧司朗推出突破性8通道915nm SMT脉冲激光器,开创激光雷达应用新时代

8通道915nm SMT脉冲激光器可增强自动驾驶汽车的远距离激光雷达系统&#xff1b;经过AEC-Q102认证的8通道QFN封装&#xff0c;具有高性能和高效率&#xff0c;采用艾迈斯欧司朗专有的波长稳定技术&#xff1b;基于20多年的脉冲激光器技术经验。 中国 上海&#xff0c;2024年8月8…

JAVA开发学习-day21

JAVA开发学习-day21 1. 删除表单数据 根据ElementUI的官方组件指南&#xff0c;为表单每列的数据添加删除按钮 <el-table :data"tableData" style"width: 100%"><el-table-column prop"id" label"ID" width"180"…

那些你应该掌握的linux命令

一、路径授权 要给 a 用户 b 路径的所有操作权限,可以使用以下命令&#xff1a; sudo chown -R a:a /b sudo chmod -R 770 /b1.sudo chown -R a:a /b chown 命令用于更改文件或目录的所有者和所属组。-R 选项表示递归地应用于目录及其内部的所有文件和子目录。a:a 表示将所有…

24/8/8算法笔记 条件筛选决策树根节点

筛选决策树的根节点是建立决策树过程中的一个重要步骤&#xff0c;主要原因包括&#xff1a; 减少计算量&#xff1a;选择合适的根节点可以减少树的深度&#xff0c;从而减少模型训练和预测时的计算量。 提高模型性能&#xff1a;选择最佳分裂点可以最大化模型的性能&#xff…

更换低版本jdk8后的idea页面怎么换回来

一、问题阐述 一开始我的idea是下面的界面&#xff1a; 这个页面美观&#xff0c;简洁。后来因为工作需要&#xff0c;从jdk17切换到jdk8的时候&#xff0c;页面变了 这个没有前面的好看&#xff0c;怎么回事&#xff1f; 二、解决方案 1、file——setting 2、搜索ui——New UI…

全新博客X主题/简约WordPress主题模板/主题巴巴/免授权版源码+自适应设计

源码简介&#xff1a; 博客X这款超酷的Wordpress主题&#xff0c;是主题巴巴团队打造的设计杰作。想象一下&#xff0c;你的博客首页能展示那些炫酷的幻灯片置顶文章、还有各种精心策划的专题列表&#xff0c;这些内容模块的设计简直吸睛了&#xff0c;能让来访的用户眼前一亮…

JAVA集中学习第四周学习记录(三)

系列文章目录 第一章 JAVA集中学习第一周学习记录(一) 第二章 JAVA集中学习第一周项目实践 第三章 JAVA集中学习第一周学习记录(二) 第四章 JAVA集中学习第一周课后习题 第五章 JAVA集中学习第二周学习记录(一) 第六章 JAVA集中学习第二周项目实践 第七章 JAVA集中学习第二周学…

SSL VPN综合实验

一、实验目的及拓扑 实验目的&#xff1a;构建企业内网和企业分支站点&#xff0c;其中企业内网通过防火墙实现双机热备并且与企业分支固定站点实现站点到站点IPsec VPN互联&#xff0c;与企业分支移动站点实现SSL VPN互联&#xff0c;企业内网各主机可以实现对分支站点内网的…

可观测性(observability)

一、定义 wiki百科的定义 In software engineering, more specifically in distributed computing, observability is the ability to collect data about programs’ execution, modules’ internal states, and the communication among components.[1][2] To improve obser…

8月最新ChatGPT系统源码SparkAi系统,支持AI换脸+智能体GPTs应用+AI绘画+AI视频+文档分析

一、文章序言 人工智能技术正在快速发展&#xff0c;AI语言模型、AI绘画和AI视频已经在多个领域得到了广泛应用。这些技术不仅在科技创新方面表现出色&#xff0c;还在艺术创作、内容生产和商业应用中展示出巨大的潜力。 SparkAi创作系统是一款基于ChatGPT和Midjourney开发的…

矩阵乘法的结合律的证明

矩阵的乘法在矩阵运算中相较于加法更加复杂&#xff0c;对矩阵乘法的运算律的证明也更复杂&#xff0c;但其中对结合律的证明是最难的&#xff0c;因为它涉及到3个矩阵的相乘。本证明不同于其他一些比较粗浅的用方阵去证明或者用三个含很少元素的简单矩阵做一个例证&#xff0c…

App渗透测试(工具使用)

Python工具 在文件中打开终端&#xff0c;执行如下命令进行装库。 python3 -m pip install -r txt文件 执行如下命令扫描 python3 .py -i apk文件

Docker最佳实践(七):安装MinIO文件服务器

大家好&#xff0c;欢迎各位工友。 Minio是一个开源免费的高性能对象存储服务器&#xff0c;专为大规模数据集和高并发访问而设计。它具有出色的读写性能和低延迟&#xff0c;可以满足对数据速度和效率要求较高的应用场景。本篇呢我们就来演示一下如何在Docker中搭建Minio容器&…

MySQL数据库基础:约束

&#x1f48e;我的主页&#xff1a;MySQL &#x1f48e;1. 约束的概述 约束是作用于表中字段的规则&#xff0c;用于限制存储在表中的数据 目的&#xff1a;保证数据库中数据的正确性&#xff0c;有效性和完整性 &#x1f48e;2. 约束的分类 &#x1f48e;2.1 非空约束 非空…

linux之top

要在 Linux 系统上查看 CPU 使用情况&#xff0c;可以使用top命令&#xff1a; 根据您提供的 top 命令的输出&#xff0c;我们可以看到系统的一些基本信息和当前运行的进程。下面是输出的主要部分的解释&#xff1a; 仅供参考&#xff1a; 系统概述: 时间&#xff1a;当前时间…

MATLAB(R和C++)大肠杆菌合成生物机械数学模型

&#x1f3af;要点 &#x1f3af;合成大肠杆菌生物学网络 | &#x1f3af;量化基因型-表型图 | &#x1f3af;化学诱导离散浓度下培养细菌评估整个浓度范围内的表达模式 | &#x1f3af;定性更改合成模型拓扑结构、定量更改相互作用的强度 | &#x1f3af;开发机械数学模型 | …

新增题目同步到ES

文章目录 &#x1f31e; Sun Frame&#xff1a;SpringBoot 的轻量级开发框架&#xff08;个人开源项目推荐&#xff09;&#x1f31f; 亮点功能&#x1f4e6; spring cloud模块概览常用工具 &#x1f517; 更多信息1.创建ES的索引和映射1.创建索引2.创建映射 2.sun-club-infra …