【0基础学爬虫】爬虫基础之scrapy的使用

【0基础学爬虫】爬虫基础之scrapy的使用

7gJDd5.png

大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学爬虫】专栏,帮助小白快速入门爬虫,本期为自动化工具 Selenium 的使用。

scrapy简介

Scrapy 是一个用于爬取网站并提取结构化数据的强大且灵活的开源框架。它提供了简单易用的工具和组件,使开发者能够定义爬虫、调度请求、处理响应并存储提取的数据。Scrapy 具有高效的异步处理能力,支持分布式爬取,通过其中间件和扩展机制可以方便地定制和扩展功能,广泛应用于数据挖掘、信息聚合和自动化测试等领域。

scrapy 工作流程

7gJSwm.png

1、启动爬虫:Scrapy 启动并激活爬虫,从初始URL开始爬取。
2、调度请求:爬虫生成初始请求,并将其发送给调度器。
3、下载页面:调度器将请求发送给下载器,下载器从互联网获取页面。
4、处理响应:下载器将响应返回给引擎,传递给爬虫。
5、提取数据:爬虫从响应中提取数据(items)和更多的URL(新的请求)。
6、处理数据:提取的数据通过项目管道进行处理,清洗并存储。
7、继续爬取:新的请求被调度器处理,继续下载和提取数据,直到所有请求处理完毕。

scrapy 每个模块的具体作用

7gJUO4.png

安装scrapy

pip install scrapy

安装成功后,直接在命令终端输入 scrapy ,输出内容如下:

7gJ1ih.png

新建scrapy项目

使用 scrapy startproject + 项目名 创建新项目。

这里我们使用 scrapy startproject scrapy_demo 创建项目示例:

7gJYVY.png

然后通过下面命令创建我们的爬虫模板,这里就按照scrapy 给出的实例创建:

cd scrapy_demo
scrapy genspider example example.com

使用pycharm 打开我们的项目,项目格式如下:

7gJR79.png

各个文件夹的含义:

spiders:存放爬虫文件
items:定义爬取的数据结构
middlewares:定义下载中间件和爬虫中间件。中间件是处理请求和响应的钩子,可以修改请求、响应、异常等
pipelines:定义管道,用于处理爬虫提取的数据,例如数据清洗、验证和存储等操作。
settings:定义了项目的基本配置

使用scrapy

这里以我们熟悉的某瓣为例来说明 scrapy 的用法。

修改 example.py 文件:

import scrapyclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允许爬取的网站范围,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)

在终端输入 scrapy crawl example 运行结果如下:

7gJrXH.png

输出了很多信息,包含版本号、插件、启用的中间件等信息。

Versions:版本信息,包括scrapy和其它库的版本信息
Overridden settings: 重写的相关配置
Enabled downloader middlewares:开启的下载器中间件
Enabled spider middlewares:开启的爬虫中间件
Enabled item pipelines:开启的管道
Telnet Password:Telnet 平台密码(Scrapy附带一个内置的telnet控制台,用于检查和控制Scrapy运行过程)
Enabled extensions :开启的拓展功能
Dumping Scrapy stats:所以的信息汇总

我们重点看这里:

7gJ4hU.png

可以发现,我们返回了403状态码,原因是因为我们少了请求头和有robots协议。

在 setting.py 增加请求头、修改 robots 协议:

# Obey robots.txt rules
ROBOTSTXT_OBEY = False   # 这里改成False,表示不遵守robots协议# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language": "en","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
}  # 然后把这个放开,这个表示该项目的默认请求头

运行之后,可以发现能正常返回 html 页面数据。

scrapy 运行项目的两种方式

上面我们是通过终端运行的,下面我们使用 python 运行。

修改 example.py 文件代码:

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允许爬取的网站范围,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)if __name__ == '__main__':cmdline.execute("scrapy crawl example".split())# cmdline.execute("scrapy crawl example --nolog".split()) 不输出提示信息

如果不想输出与爬虫无关的信息,可以在后面加上 --nolog 命令,这样就不会打印提示信息了。

数据翻页抓取

scrapy实现翻页请求

我们可以直接利用scrapy 内置的数据解析方法对数据进行抓取:

代码如下:

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"# allowed_domains = ["example.com"]   # 允许爬取的网站范围,可以不要start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.text)ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# 利用scrapy封装好的xpath选择器定位元素,并通过extract()或extract_first()来获取结果item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())# cmdline.execute("scrapy crawl example".split())

上面只抓取到了第一页,那么我们怎么抓取后面的每一页呢?

这里介绍两种方式:

1、利用callback 参数,进入项目源码,找到Request请求对象:

7gJCrq.png

Request 对象含义如下:

参数描述
url (str)请求的 URL。
callback (callable)用于处理该请求的回调函数。默认是 parse 方法。
method (str)HTTP 请求方法,如 'GET', 'POST' 等。默认为 'GET'
headers (dict)请求头信息。
body (bytes or str)请求体,通常在 POST 请求中使用。
cookies (dict or list)请求携带的 Cookies,可以是一个字典或字典的列表。
meta (dict)该请求的元数据字典,用于在不同请求之间传递数据。
encoding (str)请求的编码格式。默认为 'utf-8'
priority (int)请求的优先级,默认值为 0。优先级值越高,优先级越高。

callback 就是回调函数,接收一个函数名为参数。

实现如下:

def parse(self, response):print(response.text)ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一个元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if response.xpath("//a[text()='后页>']/@href").extract_first() is not None:next_url = response.urljoin(response.xpath("//a[text()='后页>']/@href").extract_first())print(next_url)yield scrapy.Request(url=next_url, callback=self.parse)

2、重写 start_requests 方法:

7gJJds.png

代码如下:

    def start_requests(self):for i in range(0, 5):url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)yield scrapy.Request(url)def parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一个元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)

Responses 对象含义如下:

参数描述
url (str)响应的 URL。
status (int)HTTP 响应状态码。
headers (dict)响应头信息。
body (bytes)响应体内容,二进制格式。
flags (list)响应的标志列表。
request (Request)生成此响应的请求对象。
meta (dict)该请求的元数据字典,用于在不同请求之间传递数据。
encoding (str)响应的编码格式。通常由 Scrapy 自动检测,但可以手动设置。
text (str)响应体内容,解码为字符串格式。
css (callable)选择器,用于通过 CSS 表达式提取数据。
xpath (callable)选择器,用于通过 XPath 表达式提取数据。
json (callable)解析 JSON 响应体并返回字典或列表。

数据定义

数据爬取下来之后,我们通过scrapy 的 items 进行操作。item就是即提前规划好哪些字段需要抓取,比如上面的标题、评分这些字段就需要使用 item 提前定义好。

Scrapy Item 的作用

  1. 结构化数据:通过定义 Item,可以明确抓取数据的结构。例如,一个商品的信息可能包含名称、价格、库存等字段。
  2. 数据验证:可以在 Item 中定义字段的类型和验证规则,确保抓取的数据符合预期。
  3. 代码可读性:通过定义 Item,可以使代码更具可读性和可维护性,清晰地了解抓取的数据结构。

定义item

item.py 编写如下:

import scrapyclass ScrapyDemoItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()title = scrapy.Field()rating = scrapy.Field()quote = scrapy.Field()

使用item

使用 item 需要先实例化,使用方法和 python 字典方式一样

在example.py 导入我们需要使用的 item 类,这里我们就用默认的 ScrapyDemoItem 类

import scrapy  
from scrapy import cmdline
from scrapy_demo.items import ScrapyDemoItemclass ExampleSpider(scrapy.Spider):name = "example"def start_requests(self):for i in range(0, 5):url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)yield scrapy.Request(url)def parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = ScrapyDemoItem()# extract_first() 提取第一个元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())

数据存储

Scrapy Pipeline 的作用

  1. 数据清洗和验证:你可以在 pipeline 中编写代码来清洗和验证数据。例如,去除空白字符、处理缺失值、验证数据格式等。
  2. 去重:可以检查和去除重复的数据项,确保最终的数据集是唯一的。
  3. 存储:将处理过的数据存储到不同的存储后端,如数据库(MySQL、MongoDB)
  4. 进一步处理:执行复杂的转换、聚合等操作,以便在存储之前对数据进行进一步处理。

编写Pipeline

这里我们使用mysql 进行数据保存。

pipeline.py

import pymysql
from itemadapter import ItemAdapter
class MysqlPipeline:def __init__(self):self.connection = pymysql.connect(user='root',  # 换上你自己的账密和数据库 password='root', db='scrapy_demo',)self.cursor = self.connection.cursor()self.create_table()def create_table(self):table = """CREATE TABLE IF NOT EXISTS douban (id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255) NOT NULL,rating FLOAT NOT NULL,quote TEXT)CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"""self.cursor.execute(table)self.connection.commit()def process_item(self, item, spider):try:self.cursor.execute("INSERT INTO douban(id,title, rating, quote) VALUES (%s,%s, %s, %s)",(0, item['title'], item['rating'], item['quote']))self.connection.commit()except pymysql.MySQLError as e:spider.logger.error(f"Error saving item: {e}")print(e)return itemdef close_spider(self, spider):self.cursor.close()self.connection.close()

settings.py

ITEM_PIPELINES = {"scrapy_demo.pipelines.MysqlPipeline": 300,
}  # 放开Item 

配置好后,运行example 就能看到我们的数据被正确入库了。

数据不止能存储mysql,还存储到mongo、csv等等,感兴趣的小伙伴可以查看官方文档,有很详细的教程。

scrapy 中间件

scrapy中间件的分类和作用

根据scrapy运行流程中所在位置不同分为:

  1. 下载中间件
  2. 爬虫中间件

Scrapy 中间件 (middlewares) 的作用是处理 Scrapy 请求和响应的钩子(hook),允许你在它们被scrapy引擎处理前或处理后对它们进行处理和修改。中间件为用户提供了一种方式,可以在请求和响应的不同阶段插入自定义逻辑。

一般我们常用的是下载中间件,所以下面我们用下载中间件来说明用法。

middlewares.py

Downloader Middlewares默认的方法:- process_request(self, request, spider)- 当每个request通过下载中间件时,该方法被调用。- 返回None值:继续请求- 返回Response对象:不再请求,把response返回给引擎- 返回Request对象:把request对象交给调度器进行后续的请求
- process_response(self, request, response, spider)- 当下载器完成http请求,传递响应给引擎的时候调用- 返回Resposne:交给process_response来处理- 返回Request对象:交给调取器继续请求
- from_crawler(cls, crawler):- 类似于init初始化方法,只不过这里使用的classmethod类方法- 可以直接crawler.settings获得参数,也可以搭配信号使用

自定义随机ua

我们借助 feapder 给我们封装好的 ua 来进行测试:

middlewares.py

from feapder.network import user_agent
class ScrapyDemoDownloaderMiddleware:def process_request(self, request, spider):request.headers['User-Agent'] = user_agent.get()return None

settings.py

DOWNLOADER_MIDDLEWARES = {"scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware": 543,
} #放开下载中间件

example.py

import scrapy
from scrapy import cmdlineclass ExampleSpider(scrapy.Spider):name = "example"start_urls = ["https://movie.douban.com/top250"]def parse(self, response):print(response.request.headers)if __name__ == '__main__':cmdline.execute("scrapy crawl example --nolog".split())

可以发现每次输出的 ua 不一样。

自定义代理

通过Request 对象的 mata 参数来设置代理,这里以本地的 7890 端口为例:

middlewares.py

    def process_request(self, request, spider):request.headers['User-Agent'] = user_agent.get()request.meta['proxy'] = "http://127.0.0.1:7890"return None

中间件权重

当涉及到多个中间件的时候,请求时数字越小权重越高,越先执行 ,响应时数字越大越先执行。这里我们可以借助scrapy 流程图来理解,谁离scrapy engine 引擎越近,表明权重越高。

这里我们创建两个类来测试一下:

middlewares.py

class OneMiddleware(object):def process_request(self, request, spider):print('one 请求')def process_response(self, request, response, spider):print('one 响应')# return Noneclass TwoMiddleware(object):def process_request(self, request, spider):print('two 请求')def process_response(self, request, response, spider):print('two 响应')return response

settings.py

DOWNLOADER_MIDDLEWARES = {"scrapy_demo.middlewares.OneMiddleware": 543,"scrapy_demo.middlewares.TwoMiddleware": 544
}

运行 example.py 输出如下结果:

7gJnS7.png

scrapy-redis 组件

Scrapy-Redis 是 Scrapy 的一个扩展,允许你使用 Redis 作为爬虫队列,并共享爬虫状态:

7gJIiI.png

安装

pip install scrapy-redis
注意:这里scrapy 版本需要替换成 2.9.0版本或者2.0.0以下,不然会报错:
TypeError: crawl() got an unexpected keyword argument 'spider'
因为新版本已经不支持了。

然后新建 一个 redis_demo 爬虫

scrapy genspider redis_demo  redis_demo.com

配置 scrapy-redis

settings.py

加入下面代码
# 设置 Redis 主机和端口
REDIS_URL = 'redis://127.0.0.1:6379/0'
# 使用 Scrapy-Redis 的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 使用 Scrapy-Redis 的去重器
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"开启redis管道
ITEM_PIPELINES = {"scrapy_redis.pipelines.RedisPipeline": 301
}

redis_demo.py

from scrapy_redis.spiders import RedisSpider
from scrapy import cmdline# 继承scrapy——redis 类,实现分布式
class RedisDemoSpider(RedisSpider):name = "redis_demo"redis_key = "redis_demo:start_urls"  # redis keydef parse(self, response):ol_list = response.xpath('//ol[@class="grid_view"]/li')for ol in ol_list:item = {}# extract_first() 提取第一个元素item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()print(item)yield itemif __name__ == '__main__':cmdline.execute("scrapy crawl redis_demo".split())

运行后会发现已经在监听端口了:

7gJf7V.png

这时我们新建一个demo 文件:

import redisr = redis.Redis(db=0)
r.lpush('redis_demo:start_urls',"https://movie.douban.com/top250")
#r.lpush('redis_demo:start_urls',"https://movie.douban.com/top250?start=25&filter=")

然后运行这个demo.py文件,会发现数据已经成功入库了:

7gJiWL.png

我们打开redis 可视化工具进行查看:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是现在当我们每次跑一个地址的时候,原来的数据就没有了,要想解决这个问题,我们就得运用到scrapy-redis的持久化存储了。

redis 持久化存储

Scrapy-Redis 默认会在爬取全部完成后清空爬取队列和去重指纹集合。初始第一个网址一定会进行请求,后面的重复方式不会进行请求。

如果不想自动清空爬取队列和去重指纹集合,我们在 settings.py 增加如下配置:

SCHEDULER_PERSIST = True   #如果需要持久化爬取状态,可以开启

再次运行 redis_demo.py ,然后运行两次demo.py文件可以测试一下:

7gJsXJ.png

至此,完成了持久化存储。

redis 分布式

要想在多台电脑跑同一个程序,只需要把其它电脑的 redis 连接到一台就行。

settings.py
# 设置 Redis 主机和端口
REDIS_URL = '这里写你的远程电脑ip地址'
# 使用 Scrapy-Redis 的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"# 使用 Scrapy-Redis 的去重器
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"开启redis管道
ITEM_PIPELINES = {"scrapy_redis.pipelines.RedisPipeline": 301
}

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

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

相关文章

武汉星起航:亚马逊精选,中国卖家打造的时尚防雨装备推荐

炎炎夏日,突如其来的雨水成为了许多城市居民的“常客”。在这样的季节里,一套时尚又实用的防雨装备成为了人们出行的必备之选。中国卖家在亚马逊上的防雨装备选品,凭借其精湛的工艺和独特的设计理念,成为了消费者们的首选。 首先…

选哪个短剧系统源码好:全面评估与决策指南

在短剧内容创作和分享日益流行的今天,选择合适的短剧系统源码对于构建一个成功的短剧平台至关重要。短剧系统源码不仅关系到平台的稳定性和用户体验,还直接影响到内容创作者和观众的互动质量。本文将提供一份全面的评估指南,帮助您在众多短剧…

CesiumJS【Basic】- #037 绘制轮廓线(Entity方式)

文章目录 绘制轮廓线(Entity方式)1 目标2 代码2.1 main.ts绘制轮廓线(Entity方式) 1 目标 使用Entity方式绘制轮廓线 2 代码 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium.Viewer(<

互联网产品经理的薪资是多少?你拖后腿了吗?

互联网产品经理作为现代互联网行业中的核心角色&#xff0c;其薪资水平一直备受关注。然而&#xff0c;由于地区、公司规模、个人经验等多个因素的影响&#xff0c;互联网产品经理的年薪差异较大。本文将从多个角度对互联网产品经理的年薪进行分析&#xff0c;并给出具体数据。…

奔驰G350升级原厂自适应悬挂系统有哪些作用

奔驰 G350 升级自适应悬挂系统后&#xff0c;可根据行车路况自动调整悬架高度和弹性&#xff0c;从而提升驾乘的舒适性和稳定性。 这套系统的具体功能包括&#xff1a; • 多种模式选择&#xff1a;一般有舒适、弯道、运动及越野等模式。例如&#xff0c;弯道模式在过弯时能为…

SSM泰华超市商品管理系统-计算机毕业设计源码11946

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据新增流程 3.2.2 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

怎么采集天猫的商品或店铺数据

怎么使用简数采集器批量采集天猫的商品或店铺相关信息呢&#xff1f; 简数采集器暂时不支持采集天猫的商品或店铺相关数据&#xff0c;只能采集页面公开显示的信息&#xff0c;谢谢。 简数采集器抓取网页数据特别简单&#xff0c;不需要懂技术写代码&#xff0c;只需填写网址…

基于单片机的 LED 花样照明时钟设计

摘要 &#xff1a; 本设计是基于单片机的 LED 花样照明 &#xff0c; 并附加时钟设计 . 单片机也叫微控制器 &#xff08; Micro Control Unit, 简称 MCU &#xff09;&#xff0c; 因其价格低廉 &#xff0c; 功能强大 &#xff0c; 在实际应用中得到广泛认可 . 本设计…

高效、便捷的游戏代理结算方案,Xinstall让您的业务更上一层楼!

随着游戏行业的蓬勃发展&#xff0c;越来越多的企业和个人开始涉足游戏代理领域。然而&#xff0c;在这个充满机遇与挑战的市场中&#xff0c;游戏代理结算问题成为了许多代理商和开发者头疼的难题。繁琐的结算流程、复杂的费用计算以及资金安全问题&#xff0c;都让游戏代理结…

PHP语言学习02

好久不见&#xff0c;学如逆水行舟&#xff0c;不进则退&#xff0c;真是这样。。。突然感觉自己有点废。。。 <?php phpinfo(); ?> 新生第一个代码。 要想看到运行结果&#xff0c;打开浏览器&#xff08;127.0.0.1/start/demo01.php&#xff09; 其中&#xff0c…

django @login_required 为什么会自动重定向到/accounts/login/?next=/myblog/post/new/

在Django中&#xff0c;login_required 装饰器用于确保用户在访问某个视图时已经登录。如果用户未登录&#xff0c;那么Django会自动重定向用户到登录页面。默认情况下&#xff0c;Django使用/accounts/login/作为登录URL。如果用户试图访问一个需要登录的视图&#xff0c;比如…

K-Planes代码记录

随记 原文 K-Planes: Explicit Radiance Fields in Space, Time, and Appearance&#xff0c;又要换baseline&#xff0c;可是效果不好能怎么办呢&#xff0c;我可不可以发疯。k-planes的代码又是非常工程琐碎的&#xff0c;大佬的代码果然不顾小白死活。随便记录下整个过程。…

制造型企业生产管理的技巧,你都用过哪些?

作为管理者&#xff0c;一谈到生产管理&#xff0c;你可能会想到很多生产过程中的问题&#xff1a;订单准交率不高、计划达成率不高、生产效率低、再制品太多、生产周期长等等一系列问题&#xff1b;如果你不仅仅是一名管理者&#xff0c;你还是一名企业主&#xff0c;你甚至经…

实践Go的命令模式

简介 现在的软件系统往往是分层设计。在业务层执行一次请求时&#xff0c;我们很清楚请求的上下文&#xff0c;包括&#xff0c;请求是做什么的、参数有哪些、请求的接收者是谁、返回值是怎样的。相反&#xff0c;基础设施层并不需要完全清楚业务上下文&#xff0c;它只需知道…

Bootstrap更改默认的“请在电子邮件地址中包含@”

摘要&#xff1a; 今天开发一个外贸系统&#xff0c;必须全部英文的&#xff0c;但是使用到bootatrp 4的input标签的type"email"输入没有含“”符号时会提示&#xff1a;“请在电子邮件地址中包含”中文提示&#xff01;一开始以为是中国下载的谷歌是浏览器自带的提示…

AIGC重塑创意设计:不仅能带来新技术,更能引发新思考

随着科技的飞速发展&#xff0c;AIGC&#xff08;生成式人工智能&#xff09;已经逐渐成为创意设计领域的一股新势力。从影视制作到游戏设计&#xff0c;从平面广告到数字媒体&#xff0c;AIGC的影响力无处不在&#xff0c;它不仅带来了全新的技术手段&#xff0c;更在深层次上…

Linux-笔记 嵌入式gdb远程调试

目录 前言 实现 1、内核配置 2、GDB移植 3、准备调试程序 4、开始调试 前言 gdb调试器是基于命令行的GNU项目调试器&#xff0c;通过gdb工具我们可以实现许多调试手段&#xff0c;同时gdb支持多种语言&#xff0c;兼容性很强。 在桌面 Linux 系统&#xff08;如 Ubuntu、Cent…

Redis基础教程(三):redis命令

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

08 - Python面向对象编程进阶

面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识&#xff0c;知道了如何定义类&#xff0c;如何创建对象以及如何给对象发消息。为了能够更好的使用面向对象编程思想进行程序开发&#xff0c;我们还需要对Python中的面向对象编程进行更为深入的了解。 property装…

六西格玛绿带培训的证书有什么用处?

近年来&#xff0c;六西格玛作为一套严谨而系统的质量管理方法&#xff0c;被广泛运用于各行各业。而六西格玛绿带培训证书&#xff0c;作为这一方法论中基础且重要的认证&#xff0c;对于个人和企业而言&#xff0c;都具有不可忽视的价值。本文将从多个角度深入探讨六西格玛绿…