【Python从入门到进阶】45、Scrapy框架核心组件介绍

接上篇《44、Scrapy的基本介绍和安装》
上一篇我们学习了Scrapy框架的基础介绍以及环境的搭建,本篇我们来学习一下Scrapy框架的核心组件的使用。

下面的核心组件的介绍,仍是基于这幅图的机制,大家可以再回顾一下:

注:图片来自[寻_觅]博主

一、Item定义与处理

1.1 Item的概述

在Scrapy框架中,Item是数据的主要载体,用于存储Spider从网页爬取的数据。Item定义了数据的结构,并通过Item Loader对爬取到的数据进行加载和清洗。

1.2 Item的定义

Item使用Python类来定义,通常继承自scrapy.item.Item基础类。通过定义Item类,我们可以明确数据的结构,如字段、类型等。例如:

import scrapy  
  
class MyprojectItem(scrapy.Item):  
    link = scrapy.Field()  # 字段名,数据类型默认为str  
    description = scrapy.Field()  # 字段名,数据类型默认为str

1.3 Item的处理

Item的处理主要涉及两个部分:Item Loader和Pipeline。Item Loader用于加载和清洗数据,Pipeline则负责数据的持久化存储。
Item Loader:Item Loader是用于加载和清洗数据的组件。通过使用Item Loader,我们可以对爬取到的数据进行预处理,如删除不需要的空白字符、转换数据类型等。使用Item Loader需要定义Loader类,并指定需要加载的字段。例如新建一个MySpider定义一个ItemLoader对象:

import scrapy
from scrapy.loader import ItemLoader
from ..items import MyprojectItem

class MySpider(scrapy.Spider):  
    name = 'myspider'  
    start_urls = ['http://example.com']  
  
    def parse(self, response):  
        loader = ItemLoader(item=MyprojectItem(), response=response)  
        # 使用XPath选择器选择<h1>标签中的内容作为标题。  
        loader.add_xpath('title', '//h1/text()')  
        # 使用CSS选择器选择class为content的元素中的内容作为内容。 
        loader.add_css('content', '.content')  
        return loader.load_item()

而Pipeline负责数据的持久化存储,如将爬取到的数据存储到数据库、文件等,我们在下面的小结详细讲解。

二、Spider爬虫定义与使用

2.1 Spider的概述

Spider是Scrapy框架中用于爬取网页数据的组件。Spider通过模拟浏览器行为,自动解析网页结构,提取所需的数据,并将其封装为Item对象。

2.2 Spider的编写

编写Spider需要继承scrapy.Spider基础类,并实现以下方法:

●name:Spider的唯一标识符,用于在Scrapy项目中区分不同的Spider。
●start_urls:爬取的起始URL列表。Scrapy会从这些URL开始爬取数据。
●parse():用于解析单个网页的回调函数。该函数将接收一个Response对象作为参数,并返回一个Item对象或一个Item生成器。

例如,以下是一个简单的Spider,用于爬取网站上的所有链接:

import scrapy
from ..items import MyprojectItem


class BaiduUrlSpider(scrapy.Spider):
    name = "baidu_url"
    allowed_domains = ["www.baidu.com"]
    start_urls = ["https://www.baidu.com"]

    def parse(self, response):
        # 抓取所有的链接
        for link in response.css('a::attr(href)').getall():
            if "http" in link or "https" in link:
                print("link: ", link)  # 打印出来抓取的链接地址
                item = MyprojectItem(link=link, description='test')
                yield item  # 把数据交给管道  piplines.py  进行数据的下载

2.3 Spider的使用

在Scrapy项目中,可以通过运行Scrapy命令来启动Spider:

●运行scrapy crawl <spider_name>命令,其中<spider_name>是Spider的名称。该命令将启动指定的Spider,并开始爬取数据。
●可以使用-o选项指定输出的文件名,例如scrapy crawl myspider -o output.csv将爬取的数据输出到output.csv文件中。
●可以使用-t选项指定输出数据的格式,例如scrapy crawl myspider -t csv将输出CSV格式的数据。

三、Pipeline数据处理管道

3.1 Pipeline的概述

Pipeline是Scrapy框架中负责处理已爬取数据的组件。它负责将爬取到的数据从Spider传递到最终的存储位置,并在传递过程中对数据进行清洗、验证和持久化。

3.2 Pipeline的工作流程

Pipeline的工作流程如下:

(1)Spider爬取数据完成后,将Item对象传递给Pipeline。
(2)Pipeline接收到Item对象后,会按照设定的顺序逐一进行处理。每个Pipeline都有一个唯一的优先级,优先级高的Pipeline会先于优先级低的Pipeline进行处理。
(3)在Pipeline中,可以对Item对象进行各种处理,如清洗数据、验证数据、持久化存储等。
(4)处理完成后,Pipeline将Item对象返回给Engine。
(5)Engine将Item对象传递给下一个Pipeline进行处理,或者将其传递给最终的存储位置。

3.3 自定义Pipeline

在Scrapy框架中,我们可以自定义Pipeline来满足特定的数据处理需求。要自定义Pipeline,需要创建一个Python类,并实现process_item()方法。process_item()方法接受一个Item对象作为参数,并返回一个Item对象。例如,我们可以创建一个将Item对象存储到CSV文件的Pipeline:
在settings.py中启用Pipeline:

ITEM_PIPELINES = {  
   'myproject.pipelines.MyPipeline': 300,  
}

分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)
创建Pipeline类,item pipiline组件是一个独立的Python类,其中process_item()方法必须实现:

from scrapy.exporters import CsvItemExporter
import json  # 需要导入的
from collections import OrderedDict  # 需要导入的


class MyPipeline(object):
    def __init__(self):
        # 可选实现,做参数初始化等
        self.file = open('news_data1.csv', 'wb')
        self.exporter = CsvItemExporter(self.file, encoding='gbk')
        self.exporter.start_exporting()

    def process_item(self, item, spider):
        # item (Item 对象) – 被爬取的item
        # spider (Spider 对象) – 爬取该item的spider
        # 这个方法必须实现,每个item pipeline组件都需要调用该方法,
        # 这个方法必须返回一个 Item 对象,被丢弃的item将不会被之后的pipeline组件所处理。
        print('默认的字段数据:{}\n'.format(item))
        item = OrderedDict(item)
        item = json.dumps(item, ensure_ascii=False)
        print('调整后的字段数据:{}\n'.format(item))
        self.exporter.export_item(eval(item))
        return item  # 返回一个Item对象,该对象将被持久化存储到CSV文件

    def open_spider(self, spider):
        # spider (Spider 对象) – 被开启的spider
        # 可选实现,当spider被开启时,这个方法被调用。
        pass

    def close_spider(self, spider):
        # spider (Spider 对象) – 被关闭的spider
        # 可选实现,当spider被关闭时,这个方法被调用
        self.exporter.finish_exporting()
        self.file.close()

四、Scheduler调度器

4.1 Scheduler的概述

Scheduler是Scrapy框架中的调度器组件,负责管理爬取任务的队列。它根据一定的优先级和规则,将爬取请求放入队列中,并按照顺序执行。

4.2 Scheduler的工作原理

Scheduler的工作原理如下:

(1)Spider爬取完一个网页后,将生成的请求(Request)对象传递给Scheduler。
(2)Scheduler根据请求的优先级、规则等因素,将其放入内部的队列中。
(3)Engine启动后,会定期从Scheduler中获取请求,并将其传递给下载器进行下载。
(4)下载完成后,Engine将下载的响应(Response)对象传递给Scheduler。
(5)Scheduler将响应对象传递给相应的Spider进行处理。

4.3 Scheduler的配置

在Scrapy项目的settings.py文件中,可以通过设置以下参数来配置Scheduler的行为:

●SCHEDULER:用于指定使用的Scheduler类。Scrapy框架提供了多种Scheduler的实现,如DumbScheduler、SqlalchemyScheduler等。可以根据需求选择合适的Scheduler。
●SCHEDULER_QUEUE_CLASS:用于指定请求队列的实现方式。Scrapy框架提供了多种队列的实现,如PriorityQueue、FifoQueue等。可以根据需求选择合适的队列。
●SCHEDULER_QUEUE_URL:用于指定请求队列的持久化存储方式。可以使用Redis、RabbitMQ等消息队列服务作为存储后端。
●SCHEDULER_PERSIST:用于指定是否启用请求队列的持久化存储。设置为True时,请求队列将在爬虫重启后继续存在,避免重复爬取。

4.4 自定义Scheduler

如果默认的Scheduler不能满足需求,我们可以自定义Scheduler来实现特定的调度逻辑。要自定义Scheduler,需要创建一个Python类,并实现以下方法:

●enqueue_request(request):将请求加入队列中。该方法需要返回一个布尔值,表示请求是否成功加入队列。
●dequeued_request():从队列中获取请求。该方法需要返回一个请求对象。
●has_pending_requests():检查队列中是否有待处理的请求。该方法需要返回一个布尔值。
●stats:返回调度器的统计信息。该方法需要返回一个字典,包含调度器的各种统计数据。

五、Downloader下载器

5.1 Downloader的概述

Downloader是Scrapy框架中负责下载网页数据的组件。它接收Engine传递的下载请求(Request),并发送HTTP请求到目标网站,获取网页的响应(Response)数据,并将其返回给Engine。

5.2 Downloader的工作流程

Downloader的工作流程如下:

(1)Engine将下载请求(Request)对象传递给Downloader。
(2)Downloader根据请求的URL、方法、头信息等,构建HTTP请求。
(3)Downloader发送HTTP请求到目标网站,并等待响应。
(4)一旦收到响应,Downloader将响应数据封装为Response对象,并将其返回给Engine。
(5)Engine将Response对象传递给相应的Spider进行处理。

5.3 Downloader的配置

在Scrapy项目的settings.py文件中,可以通过设置以下参数来配置Downloader的行为:

●DOWNLOADER:用于指定使用的Downloader类。Scrapy框架默认使用scrapy.core.downloader.handlers.http.HTTPDownloader作为Downloader的实现。
●DOWNLOAD_DELAY:用于设置下载器在连续下载请求之间的延迟时间(秒)。这可以避免对目标网站造成过大的访问压力。
●DOWNLOAD_TIMEOUT:用于设置下载请求的超时时间(秒)。如果请求在超时时间内没有响应,Downloader将引发超时异常。
●DOWNLOADER_MIDDLEWARES:用于指定使用的Downloader中间件列表。Downloader中间件可以对下载请求和响应进行预处理和后处理,例如添加代理、处理重定向等。
●DOWNLOADER_MIDDLEWARES_BASE:Scrapy框架提供的默认Downloader中间件列表。可以在自定义的Downloader中间件中继承或覆盖默认的中间件。

5.4 自定义Downloader

如果默认的Downloader不能满足需求,我们可以自定义Downloader来实现特定的下载逻辑。要自定义Downloader,需要创建一个Python类,并实现以下方法:

●fetch(request, spider):用于处理下载请求。该方法需要接收一个Request对象和一个Spider对象作为参数,并返回一个包含响应数据的Response对象。在该方法中,可以使用Python标准库中的HTTP客户端库(如urllib、requests等)来发送HTTP请求,并获取响应数据。
●close():用于在Downloader关闭时进行清理操作。该方法可选,可以根据需要进行实现。

通过自定义Downloader,我们可以实现更复杂的下载逻辑,例如使用代理、处理验证码、处理动态加载等。

六、Engine引擎

6.1 Engine的概述

Engine是Scrapy框架的核心组件,负责协调和控制整个爬取过程。它管理着Spider、Scheduler、Downloader和Pipeline等组件,确保它们按照正确的顺序和逻辑进行工作。

6.2 Engine的工作流程

Engine的工作流程如下:

(1)初始化Engine,并加载Scrapy项目的配置。
(2)加载并启动Spider,将Spider的起始URL传递给Scheduler。
(3)从Scheduler中获取下一个要爬取的请求(Request)。
(3)将请求传递给Downloader进行下载。
(4)等待Downloader返回响应(Response)。
(5)将响应传递给相应的Spider进行处理。
(6)Spider解析响应数据,提取所需的信息,并生成新的请求或Item对象。
(7)将新生成的请求传递给Scheduler进行调度。
(8)将生成的Item对象传递给Pipeline进行处理。
(9)重复步骤3-9,直到Scheduler中没有更多的请求或满足停止条件。
(10)关闭Engine,释放资源。

6.3 Engine的配置

在Scrapy项目的settings.py文件中,可以通过设置以下参数来配置Engine的行为:

●CONCURRENT_REQUESTS:用于设置同时进行的下载请求数量。该参数可以控制并发度,即Downloader同时处理的请求数量。
●CONCURRENT_REQUESTS_PER_DOMAIN:用于设置每个域名同时进行的下载请求数量。该参数可以限制对同一网站的并发访问量,避免对目标网站造成过大的访问压力。
●CONCURRENT_REQUESTS_PER_IP:用于设置每个IP地址同时进行的下载请求数量。该参数可以进一步细化对并发访问量的控制,限制对同一IP地址的请求频率。
●DOWNLOAD_TIMEOUT:用于设置下载请求的超时时间(秒)。如果请求在超时时间内没有响应,Engine将引发超时异常。
●ENGINE_STOPPER:用于指定Engine的停止条件。可以自定义一个类,并实现should_stop()方法来判断是否满足停止条件。

6.4 自定义Engine

在Scrapy框架中,一般情况下不需要自定义Engine,因为Engine的核心功能已经由框架提供,并且可以通过配置参数进行调整。但是,如果需要实现特殊的爬取逻辑或集成其他功能,可以通过继承Scrapy的Engine类来自定义Engine。自定义Engine时,可以重写start()和stop()方法来实现自定义的启动和停止逻辑,也可以重写其他方法来扩展Engine的功能。需要注意的是,自定义Engine需要熟悉Scrapy框架的内部工作原理和各个组件之间的交互方式。

七、Logging日志系统

7.1 日志系统的概述

日志系统是Scrapy框架中用于记录和跟踪爬虫运行信息的组件。通过日志系统,我们可以方便地查看爬虫的运行状态、调试问题、监控异常等。

7.2 日志级别的概念

Scrapy的日志系统使用Python的标准库logging模块实现,支持多种日志级别,包括:

●DEBUG:详细信息,用于开发和调试阶段。
●INFO:一般信息,用于了解爬虫的运行情况。
●WARNING:警告信息,用于指出可能的问题或异常。
●ERROR:错误信息,用于记录发生的错误。
●CRITICAL:严重错误,用于记录严重的问题或异常。

7.3 日志配置

在Scrapy项目的settings.py文件中,可以通过设置以下参数来配置日志系统的行为:

●LOG_LEVEL:用于设置日志级别。可选值包括DEBUG、INFO、WARNING、ERROR、CRITICAL。默认级别为WARNING。
●LOG_FILE:用于指定日志文件的路径。如果设置了这个参数,日志将输出到指定的文件中。
●LOG_ENABLED:用于启用或禁用日志功能。设置为True时,启用日志功能;设置为False时,禁用日志功能。默认值为True。
●LOG_STDOUT:用于将日志输出到标准输出(stdout)。设置为True时,将日志输出到控制台;设置为False时,不输出到控制台。默认值为False。
●LOG_FORMAT:用于设置日志的格式。格式化字符串可以根据需要自行定制,支持%levelname、%message等占位符。

7.4 自定义日志处理程序

如果默认的日志处理程序不能满足需求,我们可以自定义一个处理程序来自定义日志的行为。要自定义日志处理程序,需要创建一个Python类,并实现以下方法:

●__init__(self, logger, log_level, log_format):初始化方法,接收一个logger对象、一个log_level参数和一个log_format参数。
●handle(self, record):处理日志记录的方法。该方法接收一个Record对象作为参数,并返回一个处理后的日志记录对象。可以对该方法进行重写,实现自定义的日志处理逻辑。

通过自定义日志处理程序,我们可以对日志进行更详细的处理和定制化输出,例如将日志发送到远程服务器、将日志写入数据库等。

八、测试

刚刚上面定义的item、itemloder、spiders、pipelines跑一下试试:

在控制台输入:scrapy crawl baidu_url,效果(日志LOG_LEVEL = "ERROR"):

下载的csv文件内容:

成功的获取了百度首页的所有链接信息。

至此,我们对Scrapy框架的核心组件介绍就完毕了。下一篇我们以58同城网站抓取为样例,写一个实际案例来训练Scrapy框架的使用。

转载请注明出处:https://guangzai.blog.csdn.net/article/details/135187400

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

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

相关文章

2023年浙大城市学院新生程序设计竞赛(同步赛)G

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先想法非常单一&#xff0c;一定是去枚举操作点&#xff0c;然后看它染白和不染的价值差值 也就是说&#xff0c;把一个黑色结点染白之后&#xff0c;对哪些结点的价值会影响 不难想象其实就是操作结点的子树和该点连通的…

【C++】开源:FLTK图形界面库配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍FLTK图形界面库配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0…

Kali Linux—借助 SET+MSF 进行网络钓鱼、生成木马、获主机shell、权限提升、远程监控、钓鱼邮件等完整渗透测试(二)

远控木马 SET 同时集成了木马生成工具&#xff0c;可以生成木马并调用MSF框架对远程主机进行控制。直接使用MSF生成木马并控制主机的可参考之前另一篇博文&#xff1a;渗透测试-Kali入侵Win7主机。 控制主机 1、运行 SET&#xff0c;选择创建攻击载荷和监听器&#xff1a; 2…

漏洞复现-红帆OA iorepsavexml.aspx文件上传漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

D3839|完全背包

完全背包&#xff1a; 首先01背包的滚动数组中的解法是内嵌的循环是从大到小遍历&#xff0c;为了保证每个物品仅被添加一次。 for(int i 0; i < weight.size(); i) { // 遍历物品for(int j bagWeight; j > weight[i]; j--) { // 遍历背包容量dp[j] max(dp[j], dp[j…

连接服务器出现内部错误的原因与解决方案

服务器作为重要的数据存储和处理中心&#xff0c;其稳定性和可靠性对于企业和个人的业务运营至关重要。然而&#xff0c;在实际应用中&#xff0c;我们经常会遇到连接服务器时出现内部错误的情况。根据用户反馈显示&#xff0c;远程桌面出现内部错误的问题由来已久&#xff0c;…

Kali Linux—借助 SET+MSF 进行网络钓鱼、生成木马、获主机shell、权限提升、远程监控、钓鱼邮件等完整渗透测试(一)

社会工程学—世界头号黑客凯文米特尼克在《欺骗的艺术》中曾提到&#xff0c;这是一种通过对受害者心理弱点、本能反应、好奇心、信任、贪婪等心理陷阱进行诸如欺骗、伤害等危害手段。 SET最常用的攻击方法有&#xff1a;用恶意附件对目标进行 E-mail 钓鱼攻击、Java Applet攻…

xp的viostor驱动无法获取磁盘序列号的分析

深信服的viostor驱动在获取序列号的时候&#xff0c;多了一个IDE处理的代码&#xff0c;位置在1128处。它会在刚开机加载viostor.sys时机被调用&#xff0c;然后去读取注册表HKLM\\SYSTEM\CurrentControlSet\Services\viostor\Parameters的IDESNCompat&#xff0c;若为1则有此功…

第十四节TypeScript 联合类型

1、简介 联合类型可以通过管道&#xff08;|&#xff09;将变量设置多种类型&#xff0c;赋值时可以根据设置的类型来赋值。 注意&#xff1a;只能赋值指定的类型&#xff0c;如果赋值其它类型就会报错的。 2、创建联合类型的语法格式&#xff1a; Type1|Type2|Type3 实例&a…

【PostGIS】PostgreSQL15+对应PostGIS安装教程及空间数据可视化

一、PostgreSQL15与对应PostGIS安装 PostgreSQL15安装&#xff1a;下载地址PostGIS安装&#xff1a;下载地址&#xff08;选择倒数第二个&#xff09; 1、PostgreSQL安装 下载安装包&#xff1b;开始安装&#xff0c;这里使用默认安装&#xff0c;一直next直到安装完成&…

小狐狸ChatGPT系统 不同老版本升级至新版数据库结构同步教程

最新版2.6.7下载&#xff1a;https://download.csdn.net/download/mo3408/88656497 小狐狸GPT付费体验系统如何升级&#xff0c;该系统更新比较频繁&#xff0c;也造成了特别有用户数据情况下升级时麻烦&#xff0c;特别针对会员关心的问题出一篇操作教程&#xff0c;本次教程…

WT2605C高品质音频蓝牙语音芯片:外接功放实现双声道DAC输出的优势

在音频处理领域&#xff0c;双声道DAC输出能够提供更为清晰、逼真的音效&#xff0c;增强用户的听觉体验。针对这一需求&#xff0c;唯创知音的WT2605C高品质音频蓝牙语音芯片&#xff0c;通过外接功放实现双声道DAC输出&#xff0c;展现出独特的应用优势。 一、高品质音频处理…

Java 并发编程(八)-异步编程-CompletableFuture

目录 一、异步编程 1、CompletableFuture应用 1.1、CompletableFuture介绍 1.2、CompletableFuture应用 1.2.1、supplyAsync 1.2.2、runAsync 1.2.3、thenApply&#xff0c;thenApplyAsync 1.2.4、thenAccept&#xff0c;thenAcceptAsync 1.2.5、thenRun&#xff0c;t…

原来电脑并不需要重装系统才能恢复出厂设置,这个操作学起来!

前言 小伙伴们应该都知道手机上有恢复出厂设置的功能&#xff0c;如果想要把手机送给朋友或者卖给别人&#xff0c;就会先恢复出厂设置。 但换到Windows电脑上之后&#xff0c;如果出现同样的情况&#xff0c;就会第一时间想到重装系统。就好像Windows电脑上不存在恢复出厂设…

【教学类-42-01】20231224 X-Y 之间加法题判断题1.0(加法是否正确,写出正确答案)

作品展示&#xff1a; 背景需求&#xff1a; 很多大班孩子很熟练做“0-5&#xff0c;0-10的加法、或减法题目&#xff0c;需要新的题型来换花样。除了”比大小“&#xff0c;我能想起的就是”判断加法题答案是否正确。 WORD模板 代码展示&#xff1a; X-Y 之间的所有加法题的…

Pytorch项目(模型训练与优化),肺癌检测项目之六

数据优化方案 数据优化方案1&#xff1a;重复抽样 &#xff08;1&#xff09;对多数类的样本实施欠采样&#xff0c;减少多数类数量 &#xff08;2&#xff09;对少数类的样本实施过采样&#xff0c;增加少数类数量 数据优化方案2&#xff1a;数据增强 数据增强&#xff08…

IntelliJ IDEA 2023.3 最新版如何如何配置?IntelliJ IDEA 2023.3 最新版试用方法

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Vue 在同一个项目中,判断pc端和移动端,显示不同风格的页面(附pc端移动端显示效果图)

实现思路 1、修改index.html页面的meta 2、增加pc端移动端的判断 3、设置路由&#xff0c;根据不同的端&#xff0c;调用各自的路由&#xff0c;显示不同的页面 index.html 修改如下 <meta name"viewport" content"widthdevice-width,initial-scale1.0,minim…

智能算法(GA、DBO等)求解阻塞流水车间调度问题(BFSP)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

[VScode]Jupyter自动生成目录

用到插件Jupyter TOC 插件主页有一张动图介绍这个功能怎么用&#xff1a; 点击标签页面&#xff0c;右上角3个点那个位置&#xff0c;不是正文里单元格的右上角&#xff1b; 选Generate table of contents就可以自动生成目录 VScode 还有好多好多功能等待你发现呢&#xff0…