python 爬虫 入门 四、线程,进程,协程

news2024/11/27 20:26:14

线程和进程大部分人估计都知道,但协程就不一定了。

一、进程

        进程是操作系统分配资源和调度的基本单位,一个程序开始运行时,操作系统会给他分配一块独立的内存空间并分配一个PCB作为唯一标识。初始化内存空间后进程进入就绪态,PCB插入就绪队列。轮到该进程时,操作系统会给进程分配CPU时间片,让进程进入运行态。时间片用完后,重新返回就绪队列,等待下一次分配。如果运行途中,进程遇到了阻塞事件,就会让出CPU给其他就绪进程,自己则进入阻塞队列,待阻塞结束后,重新返回就绪队列。

进程的状态(网图)

 特征:

  • 动态性:进程是程序的一次执行过程,有生命期。
  • 并发性:多个进程实体同存于内存中,能并发执行。
  • 独立性:进程是资源分配的基本单位,拥有独立的内存空间和系统资源。
  • 异步性:进程以各自独立、不可预知的速度向前推进。
  • 结构特性:每个进程由程序段、数据段和一个进程控制块(PCB)三部分组成。

 使用:

        进程用的比较少,线程协程用的多,因为进程之间的切换需要的资源太多了,比较慢,而且因为内存独立而不好通信。

        今天试试这个网站泰坦陨落2steam版新手常见问题解决方法汇总 新手入门指南_逗游网一个游戏攻略,我们要尝试获取每一页红框中的内容,总共9页。

        先来看看数据在不在页面源代码中,使用 Ctrl+U进入页面源代码,再Ctrl+F查找文字内容。发现页面源代码里有,这表明内容非脚本生成的,少了一大截麻烦。

        老样子,通过抓包找到请求,就知道了url和请求方法,根据p不同的取值(1~9)即可切换不同的页面。现在我们可以开始写代码了。

初始代码

         先来个无并行的,只记录请求部分时间。最后结果存在word文档里面。之后只展示控制台输出,word输出没什么差别。

import time
from io import BytesIO

import requests
from bs4 import BeautifulSoup
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Inches, RGBColor


def out_word(bs_datas, out_path):  # 将bs_datas内容保存,out_path为保存文件名
    # 创建Word文档
    doc = Document()
    # 遍历HTML内容
    for bs_data in bs_datas:
        if bs_data is None:
            continue
        for section in bs_data.find_all('p'):
            section_all = section.find_all()  # 获取部分中所有元素
            section_all.insert(0, section)  # 列表第一个插入
            section_text = section_all[-1].string  # 最后一个应该是无嵌套的纯文本
            if section_text is None or section_text.strip() == "":  # 空的看看是不是图片
                if section_all[-1].name == "img":
                    paragraph = doc.add_paragraph()  # 添加一个新的段落
                    run = paragraph.add_run()
                    # 下载图片
                    img_url = section_all[-1]['src']
                    img_response = requests.get(img_url)  # 下载图片
                    img_stream = BytesIO(img_response.content)
                    # 将图片添加到Word文档中
                    run.add_picture(img_stream, Inches(5))  # 调整图片宽度
                else:
                    continue
            else:  # 有文本,写下来
                paragraph = doc.add_paragraph()  # 添加一个新的段落
                run = paragraph.add_run('\t' + section_text.strip())  # 获取标签文本,前面空格
            for part in section_all:  # 遍历每个部分,给段落添加属性
                if part.name == 'strong':  # 粗体
                    run.bold = True  # 设置为粗体
                elif 'align' in part.attrs:  # 有对齐方式,这估计只有图片有个居中对齐,不过都写上吧
                    align = part['align'].upper()
                    if align == 'LEFT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                    elif align == 'RIGHT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
                    elif align == 'CENTER':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
                    elif align == 'JUSTIFY':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
                    else:
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                elif part.name == 'span' and 'style' in part.attrs:  # 有颜色
                    style = part['style']
                    if style.startswith('color:'):
                        color_str = style.split(':')[1]
                        # 将颜色字符串转换为 RGB 分量
                        r, g, b = int(color_str[1:3], 16), int(color_str[3:5], 16), int(color_str[5:7], 16)
                        # 创建一个 RGBColor 对象
                        color = RGBColor(r, g, b)
                        run.font.color.rgb = color  # 上色
    # 保存Word文档
    doc.save(out_path + '.docx')


def get_text(bs_datas, url, i):  # 获取p=i页内容(bs4)存在bs_datas[i-1]
    params = {
        "p": str(i)
    }
    with requests.get(url=url, headers=headers, params=params) as resp:
        resp.encoding = "utf-8"  # 当页面乱码改这里
        bs = BeautifulSoup(resp.text, "html.parser")
        data = bs.find("div", class_="CH396071PsfiiY01QjM3f")
        bs_datas[i - 1] = data
        print(f"页面{i}结束")


url = "https://www.doyo.cn/article/396071"
headers = {
    # 用户代理,某些网站验证用户代理,微微改一下,如果提示要验证码之类的,使用它
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 "
                  "Safari/537.36 Edg/126.0.0.0",
}
bs_datas = [None] * 9
now_time = time.time()  # 记录访问时间
for i in range(1, 10):
    get_text(bs_datas, url, i)
# get_text(bs_datas, url, 1)
print("用时:", time.time() - now_time)
print(bs_datas)
out_word(bs_datas, 'output')

 

控制台部分输出

 

word文档部分结果

 进程改装代码

平常使用时,我们可以通过multiprocessing.Pool创建进程池或者multiprocessing.Process创建进程。先来两段代码展示一下进程池和进程的使用

进程池,进程池像是工具箱,会自动分配和回收进程。

import time
from multiprocessing import Pool
import os


def task(m,n):
    for i in range(m,n):
        print(f"进程: {os.getpid()} 输出:{i}")
        # time.sleep(0)   # 睡一下,让出cpu(为了更好展示并发性)

if __name__ == "__main__":
    ranges = [(10,100)]*10
    with Pool(processes=3) as pool:  # 使用3个进程
        pool.starmap(task, ranges)   # 有10个任务

进程完成任务后被分配到新任务
三个进程一起完成任务

 

进程,注意你启动进程后,只是把它放到了就绪队列,具体什么时候运行要看什么时候轮到它。

import time
from multiprocessing import Process
import os


def task(m,n):
    for i in range(m,n):
        print(f"进程: {os.getpid()} 输出:{i}")
        # time.sleep(0)   # 睡一下,让出cpu(为了更好展示并发性)


if __name__ == "__main__":
    processes = []
    for i in range(3):
        p = Process(target=task, args=(100,1000))
        processes.append(p)
    for p in processes: # 启动所有进程
        p.start()
    for p in processes: # join等待进程结束后才会继续运行。
        p.join()

    print("全部进程结束")

两种方式都会出现下面这种现象,进程a和进程有几率交叉输出,这就是并发的表现 

         下面是用进程改装的代码,(图片请求591了,可能是刷太多次不让看了?所以加了个200判断,不影响。)切实能快一点。

import time
from io import BytesIO
from multiprocessing import Pool

import requests
from bs4 import BeautifulSoup
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Inches, RGBColor


def out_word(bs_datas, out_path):  # 将bs_datas内容保存,out_path为保存文件名
    # 创建Word文档
    doc = Document()
    # 遍历HTML内容
    for bs_data in bs_datas:
        if bs_data is None:
            continue
        for section in bs_data.find_all('p'):
            section_all = section.find_all()  # 获取部分中所有元素
            section_all.insert(0, section)  # 列表第一个插入
            section_text = section_all[-1].string  # 最后一个应该是无嵌套的纯文本
            if section_text is None or section_text.strip() == "":  # 空的看看是不是图片
                if section_all[-1].name == "img":
                    paragraph = doc.add_paragraph()  # 添加一个新的段落
                    run = paragraph.add_run()
                    # 下载图片
                    img_url = section_all[-1]['src']
                    img_response = requests.get(img_url)
                    if not img_response ==200:
                        continue# 下载图片
                    img_stream = BytesIO(img_response.content)
                    # 将图片添加到Word文档中
                    run.add_picture(img_stream, Inches(5))  # 调整图片宽度
                else:
                    continue
            else:  # 有文本,写下来
                paragraph = doc.add_paragraph()  # 添加一个新的段落
                run = paragraph.add_run('\t' + section_text.strip())  # 获取标签文本,前面空格
            for part in section_all:  # 遍历每个部分,给段落添加属性
                if part.name == 'strong':  # 粗体
                    run.bold = True  # 设置为粗体
                elif 'align' in part.attrs:  # 有对齐方式,这估计只有图片有个居中对齐,不过都写上吧
                    align = part['align'].upper()
                    if align == 'LEFT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                    elif align == 'RIGHT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
                    elif align == 'CENTER':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
                    elif align == 'JUSTIFY':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
                    else:
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                elif part.name == 'span' and 'style' in part.attrs:  # 有颜色
                    style = part['style']
                    if style.startswith('color:'):
                        color_str = style.split(':')[1]
                        # 将颜色字符串转换为 RGB 分量
                        r, g, b = int(color_str[1:3], 16), int(color_str[3:5], 16), int(color_str[5:7], 16)
                        # 创建一个 RGBColor 对象
                        color = RGBColor(r, g, b)
                        run.font.color.rgb = color  # 上色
    # 保存Word文档
    doc.save(out_path + '.docx')


def get_text(bs_datas, headers, url, i):  # 获取p=i页内容(bs4)存在bs_datas[i-1]
    params = {
        "p": str(i)
    }
    with requests.get(url=url, headers=headers, params=params) as resp:
        resp.encoding = "utf-8"  # 当页面乱码改这里
        bs = BeautifulSoup(resp.text, "html.parser")
        data = bs.find("div", class_="CH396071PsfiiY01QjM3f")
        print(f"页面{i}结束")
        return str(data),i


if __name__ == "__main__":
    url = "https://www.doyo.cn/article/396071"
    headers = {
        # 用户代理,某些网站验证用户代理,微微改一下,如果提示要验证码之类的,使用它
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 "
                      "Safari/537.36 Edg/126.0.0.0",
    }
    bs_datas = [None] * 9
    data_chunks = [(bs_datas,headers, url, i) for i in range(1,10)]
    now_time = time.time()  # 记录访问时间
    with Pool(processes=4) as pool:  # 使用4个进程
        datas = pool.starmap(get_text, data_chunks)
    print("用时:", time.time() - now_time)
    for data in datas:
        bs_datas[data[1]-1]=BeautifulSoup(data[0], "html.parser")
    print(bs_datas)
    out_word(bs_datas, 'output')

二、线程 

        线程是cpu调度的基本单位,一个进程能有很多个线程(至少一个),进程是线程的容器。他的状态、特性、使用都和进程相似,有时候也成为轻量级进程。

        与进程相比,线程的资源分配、调度、切换的花销都更少。而线程因为没有自己独立的内存空间,在通信上更灵活。

特征:

  • 轻量级:相对于进程而言,线程是轻量级的执行单元,它只拥有一点必不可少的资源,如程序计数器、一组寄存器和栈。
  • 共享资源:线程属于同一进程,它们共享进程的内存空间和资源,这使得线程之间的通信更加方便。
  • 独立执行流:每个线程都有自己的执行路径,线程在执行过程中独立运行,互不干扰。
  • 上下文切换快:线程间的上下文切换相对较快,因为线程共享了大部分上下文信息。

使用: 

在python中,进程和线程的创建、使用的代码十分相似,这里只展示concurrent库线程池的使用:

import threading
from concurrent.futures import ThreadPoolExecutor
import time


def task(m, n):
    for i in range(m, n):
        print(f"线程: {threading.get_ident()} 输出:{i}")
        # time.sleep(0)   # 睡一下,让出cpu(为了更好展示并发性)


if __name__ == "__main__":
    with ThreadPoolExecutor(3) as t:  # 使用3个线程
        for i in range(10):
            t.submit(task,m=10,n=100)
    print("end")

使用线程修改代码: 线程因为切换消耗少,自然速度能更快一些。

import time
from io import BytesIO
from concurrent.futures import ThreadPoolExecutor
import requests
from bs4 import BeautifulSoup
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Inches, RGBColor


def out_word(bs_datas, out_path):  # 将bs_datas内容保存,out_path为保存文件名
    # 创建Word文档
    doc = Document()
    # 遍历HTML内容
    for bs_data in bs_datas:
        if bs_data is None:
            continue
        for section in bs_data.find_all('p'):
            section_all = section.find_all()  # 获取部分中所有元素
            section_all.insert(0, section)  # 列表第一个插入
            section_text = section_all[-1].string  # 最后一个应该是无嵌套的纯文本
            if section_text is None or section_text.strip() == "":  # 空的看看是不是图片
                if section_all[-1].name == "img":
                    paragraph = doc.add_paragraph()  # 添加一个新的段落
                    run = paragraph.add_run()
                    # 下载图片
                    img_url = section_all[-1]['src']
                    img_response = requests.get(img_url)
                    if not img_response ==200:
                        continue# 下载图片
                    img_stream = BytesIO(img_response.content)
                    # 将图片添加到Word文档中
                    run.add_picture(img_stream, Inches(5))  # 调整图片宽度
                else:
                    continue
            else:  # 有文本,写下来
                paragraph = doc.add_paragraph()  # 添加一个新的段落
                run = paragraph.add_run('\t' + section_text.strip())  # 获取标签文本,前面空格
            for part in section_all:  # 遍历每个部分,给段落添加属性
                if part.name == 'strong':  # 粗体
                    run.bold = True  # 设置为粗体
                elif 'align' in part.attrs:  # 有对齐方式,这估计只有图片有个居中对齐,不过都写上吧
                    align = part['align'].upper()
                    if align == 'LEFT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                    elif align == 'RIGHT':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
                    elif align == 'CENTER':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
                    elif align == 'JUSTIFY':
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY
                    else:
                        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
                elif part.name == 'span' and 'style' in part.attrs:  # 有颜色
                    style = part['style']
                    if style.startswith('color:'):
                        color_str = style.split(':')[1]
                        # 将颜色字符串转换为 RGB 分量
                        r, g, b = int(color_str[1:3], 16), int(color_str[3:5], 16), int(color_str[5:7], 16)
                        # 创建一个 RGBColor 对象
                        color = RGBColor(r, g, b)
                        run.font.color.rgb = color  # 上色
    # 保存Word文档
    doc.save(out_path + '.docx')


def get_text(bs_datas, headers, url, i):  # 获取p=i页内容(bs4)存在bs_datas[i-1]
    params = {
        "p": str(i)
    }
    with requests.get(url=url, headers=headers, params=params) as resp:
        resp.encoding = "utf-8"  # 当页面乱码改这里
        bs = BeautifulSoup(resp.text, "html.parser")
        data = bs.find("div", class_="CH396071PsfiiY01QjM3f")
        bs_datas[i - 1] = data
        print(f"页面{i}结束")


if __name__ == "__main__":
    url = "https://www.doyo.cn/article/396071"
    headers = {
        # 用户代理,某些网站验证用户代理,微微改一下,如果提示要验证码之类的,使用它
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 "
                      "Safari/537.36 Edg/126.0.0.0",
    }
    bs_datas = [None] * 9
    data_chunks = [(bs_datas,headers, url, i) for i in range(1,10)]
    now_time = time.time()  # 记录访问时间
    with ThreadPoolExecutor(4) as t:  # 使用4个线程
        for i in range(1,10):
            t.submit(get_text,bs_datas=bs_datas,headers=headers,url=url,i=i)
    print("用时:", time.time() - now_time)
    print(bs_datas)
    out_word(bs_datas, 'output')

 

三、协程 

        协程比线程更小,它完全是在程序中切换代码的执行,而不需要操作系统的参与,具体来说,它可以在程序阻塞时去执行其他的代码段,而不需要白白让出cpu,不必切换线程也意味着没有切换消耗。下面来一段程序来表现协程:

import asyncio
import time


def f1s():
    print("f1s-in")
    time.sleep(1)
    print("f1s-out")


def f3s():
    print("f3s-in")
    time.sleep(3)
    print("f3s-out")


def f5s():
    print("f5s-in")
    time.sleep(5)
    print("f5s-out")


async def af1s():
    print("f1s-in")
    # time.sleep(1) # time.sleep是同步操作,会终止异步
    await asyncio.sleep(1)  # 挂起代码,异步操作
    print("f1s-out")


async def af3s():
    print("f3s-in")
    # time.sleep(3)
    await asyncio.sleep(3)
    print("f3s-out")


async def af5s():
    print("f5s-in")
    # time.sleep(5)
    await asyncio.sleep(5)
    print("f5s-out")


async def main():
    now_time = time.time()
    tasks = [asyncio.create_task(af1s()),
             asyncio.create_task(af3s()),
             asyncio.create_task(af5s())]
    await asyncio.wait(tasks)  # 一次启动多个任务
    print("启动协程:", time.time() - now_time)


if __name__ == '__main__':
    now_time = time.time()
    f1s()
    f3s()
    f5s()
    print("正常:", time.time() - now_time)
    asyncio.run(main())

        可以看出协程能够在阻塞时执行其他函数,节约寿命。在爬虫中,请求服务器的过程中有大量等待操作,协程能尽可能利用这段等待时间。

        如果要在爬虫中使用协程,我们需要将会产生阻塞的函数换成协程异步函数,比如文件读写用aiofiles库,网络请求用aiohttp库。

        下面是用协程的代码,只需0.25s更快了。(没加后面保存部分,之前也一直没计算保存部分时间。)

import asyncio
import time

import aiohttp
from bs4 import BeautifulSoup


async def get_text(bs_datas, headers, url, i):  # 获取p=i页内容(bs4)存在bs_datas[i-1]
    params = {
        "p": str(i)
    }
    async with aiohttp.ClientSession() as session:  # aiohttp.ClientSession()相当于requests
        async with session.get(url=url, headers=headers, params=params)as resp:
            bs = BeautifulSoup(await resp.text(), "html.parser")  # 图片换.content.red()
            data = bs.find("div", class_="CH396071PsfiiY01QjM3f")
            bs_datas[i - 1] = data
            print(f"页面{i}结束")


async def main(bs_datas, headers, url):
    now_time = time.time()  # 记录访问时间
    tasks = []
    for i in range(1, 10):
        tasks.append(asyncio.create_task(get_text(bs_datas=bs_datas, headers=headers, url=url, i=i)))
    await asyncio.wait(tasks)  # 一次启动多个任务
    print("启动协程:", time.time() - now_time)


if __name__ == "__main__":
    url = "https://www.doyo.cn/article/396071"
    headers = {
        # 用户代理,某些网站验证用户代理,微微改一下,如果提示要验证码之类的,使用它
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 "
                      "Safari/537.36 Edg/126.0.0.0",
    }
    bs_datas = [None] * 9
    # asyncio.run(main(bs_datas, headers, url))
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(bs_datas, headers, url))
    print(bs_datas)

 在大量请求下,协程能够节省大量时间,请求数目越多越明显

后续:五、抓取图片、视频

        会有大量请求,正是协程展示的好时机

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

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

相关文章

GUI编程

GUI编程 【Java从0到架构师课程】笔记 GUI简介 GUI:图形用户界面,在计算机中采用图形的方式显示用户界面 java的GUI开发 AWT:java最早推出的GUI编程开发包,界面风格跟随操作系统SWT:eclipse就是java使用SWT开发的Sw…

【ArcGIS微课1000例】0125:ArcGIS矢量化无法自动完成面解决方案

文章目录 一、坐标系统问题二、正确使用自动完成面工具一、坐标系统问题 1. 数据库坐标系 arcgis矢量化的过程中,无法自动完成面,可能是因为图层要素没有坐标系造成的。双击数据库打开数据库属性,可以查看当前数据框的坐标系。 2. 图层坐标系 双击图层,打开图层属性,切…

从零开始学PHP之变量作用域数据类型

一、数据类型 上篇文章提到了数据类型,在PHP中支持以下几种类型 String (字符串)Integer(整型)Float (浮点型)Boolean(布尔型)Array(数组)Objec…

滤波算法与SLAM:从概率角度理解SLAM问题

滤波算法与SLAM 第三章:MAP/MLE问题和贝叶斯网络 文章目录 滤波算法与SLAM前言一、最大后验问题(MAP)与最大似然问题(MLE)二、贝叶斯网络与SLAM问题三、因子图与SLAM问题四、从概率角度理解Kalman Filter与SLAM 前言 …

我谈傅里叶变换幅值谱的显示

在图像处理和分析中通常需要可视化图像傅里叶变换的幅值谱。通过幅值谱,可以直观地观察频率成分的分布,帮助理解图像的结构和特征。 很多刊物中直接显示傅里叶变换的幅值谱。 FFT fftshift(fft2(double(Img))); FFT_mag mat2gray(log(1abs(FFT)));由…

【Linux】线程基本概念,线程控制

目录 基本概念 重新理解进程 线程真实存在吗? 问题解答 线程资源 线程控制 线程创建 如何全面看待线程函数传参 如何看到线程函数返回 线程查询 线程等待 线程终止 线程分离 基本概念 线程(thread)是指在单个进程内,多…

探索前端与 AI 的结合:如何用 GPT-4 助力开发效率

前言:开发者的“神队友” GPT-4 还记得那些深夜奋战,紧盯着屏幕敲代码的日子吗?表单不验证、布局乱飞、BUG 根本找不到,这些时刻简直能让人抓狂。你可能会想:“要是有个智能助手能帮我搞定这些多好!” 那么…

#HarmonyOS:页面和自定义组件生命周期

页面生命周期 即被Entry装饰的组件生命周期 onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。onPageHide: 页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。onBackPress: 当用户点击返回按钮是触发 组件…

全面了解 NGINX 的负载均衡算法

NGINX 提供多种负载均衡方法,以应对不同的流量分发需求。常用的算法包括:最少连接、最短时间、通用哈希、随机算法和 IP 哈希。这些负载均衡算法都通过独立指令来定义,每种算法都有其独特的应用场景。 以下负载均衡方法(IP 哈希除…

如何让自己的网站,被更多的人搜索到(免费方案)

文章目录 一、要做时间的朋友二、需要独立IP的服务器三、SEO信息如何设置设置网站TDK生成网站地图设置搜索引擎自动提交部署SSL证书加分项:定期更新文章 引言: 许多人都有这样一个问题:做好自己的网站,如何让这个网站被更多的人浏…

WPF实现类似网易云音乐的菜单切换

这里是借助三方UI框架实现了,感兴趣的小伙伴可以看一下。 深色模式:​ 浅色模式: ​这里主要使用了以下三个包: MahApps.Metro:UI库,提供菜单导航和其它控件​​​​​​​ 实现步骤:1、使用B…

SSRF-利用dict协议-攻击redis

1.靶场准备: CTFHub-技能树-Web-SSRF-Redis协议 蚁剑AntSword 2.简述: 2.1 SSRF 服务器端请求伪造,存在一个url参数,一般用于图片上传、网页重定向等,我们可以控制url参数,去访问内网服务器的敏感内容…

前端vue框架配置基础信息详解分析

前端vue2、vue3框架是我们最近常用的框架,今天我们分析一下配置基础信息、详解其中的功能含义。 1、vue.config.js 文件分析 这个 vue.config.js 文件是 Vue CLI 项目中用于配置项目构建行为和开发环境设置的文件。它能够让开发者定制打包、代理、路径、样式等方面…

干货:落地企业级RAG的实践指南

1. 什么是RAG? 检索增强生成(Retrieval-Augmented Generation,简称 RAG)通过结合大型语言模型(LLM)和信息检索系统来提高生成文本的准确性和相关性.这种方法允许模型在生成回答之前,先从权威知…

spdlog学习记录

spdlog Loggers:是 Spdlog 最基本的组件,负责记录日志消息。在 Spdlog 中,一个 Logger 对象代表着一个日志记录器,应用程序可以使用 Logger 对象记录不同级别的日志消息Sinks:决定了日志消息的输出位置。在 Spdlog 中&…

深入拆解TomcatJetty(三)

深入拆解Tomcat&Jetty(三) 专栏地址:https://time.geekbang.org/column/intro/100027701 1 Tomcat组件生命周期 Tomcat如何如何实现一键式启停 Tomcat 架构图和请求处理流程如图所示: 对组件之间的关系进行分析,…

MySQL(python开发)——(3)表数据的基本操作,增删改查

MySQL(python开发)——(1)数据库概述及其MySQL介绍 MySQL(python开发)——(2)数据库基本操作及数据类型 MySQL—— 表数据基本操作 一、表中插入(insert)数据——增 insert into 表名 values (值1&#…

人工智能正在扼杀云计算的可持续性

可持续性曾是公共云计算中备受推崇的优势。企业和云提供商大肆宣扬他们的绿色计划,推广采用可再生能源的数据中心,以减少碳足迹。 近几个月来,这个话题已悄然淡出人们的视线。罪魁祸首是什么?对人工智能功能的无限需求正在推动云…

大数据-180 Elasticsearch - 原理剖析 索引写入与近实时搜索

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Django配置路由后,为什么输入http://127.0.0.1:8000/ 网址后报错了?

问题探讨:为什么输入http://127.0.0.1:8000/ 网址后报错了? 翻译一下: 屏蔽一下新加的路由 发现界面正常了 现在翻译一下: 是不是比较理解了,admin 属于默认配置的URL,所以urlpatterns为空列表或仅配置admin路由时&…