当前位置: 首页 > article >正文

【Python爬虫(53)】从入门到精通:Scrapy Spider开发全攻略

【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取,还涉及数据处理与分析。无论是新手小白还是进阶开发者,都能从中汲取知识,助力掌握爬虫核心技能,开拓技术视野。

目录

  • 一、引言
  • 二、编写不同类型的 Spider
    • 2.1 CrawlSpider
    • 2.2 XMLFeedSpider
  • 三、Spider 的规则定义与链接提取
    • 3.1 LinkExtractor 概述
    • 3.2 规则定义示例
    • 3.3 实际应用中的链接提取技巧
  • 四、在 Spider 中处理复杂的网页逻辑
    • 4.1 分页处理
    • 4.2 表单提交
  • 五、总结与展望


一、引言

在 “Python 爬虫” 专栏的学习旅程中,我们已经深入了解了 Python 基础语法以及爬虫的入门知识,并且对 Scrapy 框架也有了一定程度的认识。而在 Scrapy 框架里,Spider 扮演着核心角色,它就像是一个智能探险家,根据我们设定的规则,在网页的海洋中精准地获取所需数据。本章节我们将深入探讨 Scrapy 的 Spider 开发,从编写不同类型的 Spider,到规则定义与链接提取,再到复杂网页逻辑的处理,全面掌握 Spider 开发的精髓,为我们的爬虫开发技能添砖加瓦。

二、编写不同类型的 Spider

2.1 CrawlSpider

CrawlSpider 是 Scrapy 中用于编写通用爬虫的类,它能够自动根据我们定义的规则跟踪链接,从而实现对网站的深度爬取。在实际应用中,当我们面对一个具有复杂链接结构和大量页面的网站时,CrawlSpider 就显得尤为重要。例如,对于一个新闻资讯网站,它的文章分布在不同的栏目和分页中,使用 CrawlSpider 可以方便地定义规则,自动遍历所有页面并获取新闻内容。

CrawlSpider 的规则定义主要通过rules属性来实现,rules是一个包含多个Rule对象的元组。每个Rule对象定义了如何从页面中提取链接以及如何处理这些链接。Rule对象的主要参数包括:

  • link_extractor:一个LinkExtractor对象,用于定义从页面中提取链接的规则。
  • callback:一个回调函数,用于处理提取到的链接对应的页面。
  • follow:一个布尔值,指定是否跟进从当前页面提取到的链接。

下面通过一个代码示例来展示如何创建一个 CrawlSpider:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractorclass ExampleCrawlSpider(CrawlSpider):name = 'example_crawl'allowed_domains = ['example.com']start_urls = ['http://www.example.com']rules = (Rule(LinkExtractor(allow=r'category/'), callback='parse_category', follow=True),Rule(LinkExtractor(allow=r'article/'), callback='parse_article', follow=False),)def parse_category(self, response):# 处理分类页面,提取分类信息category_name = response.css('h1.category-title::text').get()self.logger.info('Category: %s', category_name)def parse_article(self, response):# 处理文章页面,提取文章信息article_title = response.css('h1.article-title::text').get()article_content = response.css('div.article-content::text').get()yield {'title': article_title,'content': article_content}

在上述代码中:

  • allowed_domains指定了允许爬取的域名,防止爬虫爬取到其他不相关的网站。
  • start_urls设置了爬虫的起始 URL,爬虫将从这些 URL 开始发起请求。
  • rules定义了两个规则:
    • 第一个规则使用LinkExtractor提取所有匹配category/的链接,将这些链接对应的页面交给parse_category方法处理,并跟进这些链接继续爬取。
    • 第二个规则提取所有匹配article/的链接,交给parse_article方法处理,但不跟进这些链接。

2.2 XMLFeedSpider

XMLFeedSpider 主要用于解析 XML 格式的数据,它适用于处理一些以 XML 格式提供数据的网站,比如 RSS 订阅源。在当今信息爆炸的时代,许多网站提供 RSS 订阅服务,方便用户获取最新的内容更新。使用 XMLFeedSpider 可以轻松地从这些 RSS 订阅源中提取出文章标题、链接、发布时间等信息。

XMLFeedSpider 的工作原理是通过迭代 XML 文档中的节点来提取数据。它提供了一些重要的属性和方法:

  • iterator:指定使用的迭代器,默认为iternodes,这是一个基于正则表达式的高性能迭代器。还可以设置为html或xml迭代器。
  • itertag:设置开始迭代的节点,即从哪个节点开始提取数据。
  • parse_node:在节点与所提供的标签名相符合时被调用,在这个方法中定义信息提取和处理的操作。

下面是一个使用 XMLFeedSpider 的代码示例:

import scrapy
from scrapy.spiders import XMLFeedSpiderclass ExampleXMLFeedSpider(XMLFeedSpider):name = 'example_xml'allowed_domains = ['example.com']start_urls = ['http://www.example.com/rss.xml']iterator = 'iternodes'itertag = 'item'def parse_node(self, response, selector):item = {}item['title'] = selector.xpath('title/text()').get()item['link'] = selector.xpath('link/text()').get()item['pub_date'] = selector.xpath('pubDate/text()').get()yield item

在这个示例中:

  • start_urls指定了要爬取的 XML 文件的 URL,这里是一个 RSS 订阅源。
  • iterator设置为iternodes,使用默认的迭代器。
  • itertag设置为item,表示从节点开始迭代提取数据。
  • 在parse_node方法中,使用 XPath 表达式从 XML 节点中提取文章的标题、链接和发布时间,并将这些数据封装成一个字典返回。

三、Spider 的规则定义与链接提取

3.1 LinkExtractor 概述

在 Scrapy 的 Spider 开发中,链接提取是一个关键环节。LinkExtractor 作为 Scrapy 中专门用于提取链接的工具,为我们提供了强大且灵活的链接提取功能。它能够从网页的 HTML 或 XML 内容中按照我们设定的规则精准地提取出链接,为爬虫的后续爬取工作提供目标。

LinkExtractor 有许多常用参数,这些参数赋予了它强大的链接筛选能力:

  • allow:接收一个正则表达式或一个正则表达式列表,用于提取绝对 url 与正则表达式匹配的链接。例如,当我们爬取一个电商网站时,如果只想提取商品详情页的链接,就可以设置allow=r’product/\d+.html’,这样就只会提取符合该正则表达式的链接,如product/123.html。如果该参数为空(默认),则会提取全部链接。
  • deny:与allow相反,接收一个正则表达式或一个正则表达式列表,用于排除绝对 url 与正则表达式匹配的链接。比如在爬取一个包含多种页面类型的网站时,我们不想爬取关于网站介绍、联系我们等页面的链接,就可以设置deny=r’(about|contact).html’,这样就会排除掉这些匹配的链接。
  • restrict_xpaths:接收一个 XPath 表达式或一个 XPath 表达式列表,用于提取 XPath 表达式选中区域下的链接。假设我们要从一个新闻网站的首页提取新闻列表区域的链接,而新闻列表在一个特定的div标签下,我们就可以使用restrict_xpaths=‘//div[@class=“news-list”]’,这样就只会从这个新闻列表区域提取链接,避免提取到其他无关区域的链接。

此外,还有allow_domains(提取到指定域的链接)、deny_domains(排除到指定域的链接)、restrict_css(提取 CSS 选择器选中区域下的链接)、tags(提取指定标签内的链接,默认为[‘a’, ‘area’])、attrs(提取指定属性内的链接,默认为[‘href’])、process_value(对提取的每一个链接进行处理的回调函数)等参数,这些参数可以根据具体需求灵活组合使用,实现各种复杂的链接提取需求。

3.2 规则定义示例

在 CrawlSpider 中,我们通常会结合 LinkExtractor 来定义规则。下面通过一个具体的示例来展示如何在 Rule 中使用 LinkExtractor:

假设我们要爬取一个小说网站,网站的小说列表页面链接格式为http://www.example.com/novel/list/?page=1,http://www.example.com/novel/list/?page=2等,小说详情页链接格式为http://www.example.com/novel/detail/123,其中123是小说的 ID。我们可以定义如下规则:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractorclass NovelSpider(CrawlSpider):name = 'novel'allowed_domains = ['example.com']start_urls = ['http://www.example.com/novel/list/?page=1']rules = (Rule(LinkExtractor(allow=r'list/\?page=\d+'), follow=True),Rule(LinkExtractor(allow=r'detail/\d+'), callback='parse_novel', follow=False),)def parse_novel(self, response):novel_title = response.css('h1.novel-title::text').get()novel_content = response.css('div.novel-content::text').get()yield {'title': novel_title,'content': novel_content}

在这个示例中:

  • 第一个规则使用LinkExtractor提取所有匹配list/?page=\d+的链接,即小说列表页的链接。由于设置了follow=True,爬虫会跟进这些链接,继续爬取后续的列表页。
  • 第二个规则提取所有匹配detail/\d+的链接,即小说详情页的链接,并将这些链接对应的页面交给parse_novel方法处理。由于设置了follow=False,爬虫不会再从小说详情页中提取链接并跟进。

3.3 实际应用中的链接提取技巧

在实际的网页爬取中,经常会遇到复杂的网页结构,这就需要一些特殊的技巧来精准提取链接:

  • 处理多层嵌套标签:有些网页的链接可能嵌套在多层标签中,例如:
<div class="outer"><div class="middle"><a href="http://example.com/link1">Link 1</a></div>
</div>

如果我们使用restrict_xpaths参数,可以这样设置:restrict_xpaths=‘//div[@class=“outer”]/div[@class=“middle”]’,这样就能准确地从这个多层嵌套的结构中提取出链接。如果使用 CSS 选择器,可以设置为restrict_css=‘.outer.middle’。

  • 动态生成链接:对于一些通过 JavaScript 动态生成的链接,常规的 LinkExtractor 可能无法直接提取。这时可以考虑使用 Selenium 等工具来模拟浏览器行为,等待页面加载完成并生成链接后再进行提取。例如,使用 Selenium 打开网页,等待一段时间让 JavaScript 执行完毕,然后获取页面的源代码,再将其传递给 Scrapy 的 LinkExtractor 进行链接提取。具体实现可以参考以下代码:
from selenium import webdriver
from scrapy.http import HtmlResponse# 使用Selenium获取网页内容
driver = webdriver.Chrome()
driver.get('http://example.com')
# 等待页面加载,假设等待5秒
import time
time.sleep(5)
html = driver.page_source
driver.quit()# 将获取的内容转换为Scrapy的Response对象
response = HtmlResponse(url='http://example.com', body=html, encoding='utf-8')
# 使用LinkExtractor提取链接
from scrapy.linkextractors import LinkExtractor
link_extractor = LinkExtractor()
links = link_extractor.extract_links(response)
for link in links:print(link.url)

通过这些技巧,我们能够在复杂的网页环境中更准确地提取所需链接,提高爬虫的效率和准确性。

四、在 Spider 中处理复杂的网页逻辑

4.1 分页处理

在爬虫开发中,分页是一个非常常见的需求。许多网站为了提高用户体验和数据加载效率,会将数据分成多个页面展示。以电商网站为例,商品列表通常会分页显示,每页展示一定数量的商品;新闻网站的文章列表也会采用分页的形式,方便用户浏览不同时期的新闻。因此,实现分页处理对于爬虫获取完整的数据至关重要。

在 Scrapy 中,实现分页的方式有多种,其中一种常见的方法是通过分析 URL 规律来构造下一页的请求。例如,对于一个分页的新闻列表页面,其 URL 可能具有如下规律:http://www.example.com/news/list?page=1,http://www.example.com/news/list?page=2,http://www.example.com/news/list?page=3等。我们可以通过观察发现,URL 中page参数的值随着页码的增加而递增。在 Scrapy 中,我们可以利用这一规律来实现分页:

import scrapyclass NewsSpider(scrapy.Spider):name = 'news'start_urls = ['http://www.example.com/news/list?page=1']def parse(self, response):# 提取当前页面的新闻数据for news in response.css('div.news-item'):item = {'title': news.css('h2.title::text').get(),'content': news.css('p.content::text').get()}yield item# 提取下一页的链接next_page = response.css('a.next::attr(href)').get()if next_page:# 拼接完整的下一页URLnext_page_url = response.urljoin(next_page)# 发送下一页的请求,并指定回调函数为parseyield scrapy.Request(next_page_url, callback=self.parse)

在上述代码中:

  • 在parse方法中,首先提取当前页面的新闻数据,并将其封装成item字典返回。
  • 然后通过response.css(‘a.next::attr(href)’).get()提取下一页的链接。
  • 使用response.urljoin(next_page)拼接完整的下一页 URL,确保链接的正确性。
  • 最后使用yield scrapy.Request(next_page_url, callback=self.parse)发送下一页的请求,并指定回调函数为parse,这样当获取到下一页的响应时,会继续调用parse方法进行数据提取和下一页链接的提取,从而实现分页爬取。

另一种常用的方法是使用response.follow方法来跟进链接实现分页。response.follow方法是 Scrapy 提供的一个便捷方法,它可以自动处理相对链接和绝对链接的拼接,并且会自动设置请求的相关参数。例如:

import scrapyclass NewsSpider(scrapy.Spider):name = 'news'start_urls = ['http://www.example.com/news/list?page=1']def parse(self, response):# 提取当前页面的新闻数据for news in response.css('div.news-item'):item = {'title': news.css('h2.title::text').get(),'content': news.css('p.content::text').get()}yield item# 提取下一页的链接并跟进next_page = response.css('a.next::attr(href)').get()if next_page:yield response.follow(next_page, self.parse)

在这个示例中,yield response.follow(next_page, self.parse)实现了跟进下一页链接的操作,它与yield scrapy.Request(next_page_url, callback=self.parse)的效果类似,但response.follow方法更加简洁和方便 。

4.2 表单提交

表单提交在爬虫中有着广泛的应用场景,比如模拟用户登录、执行搜索操作等。在登录场景中,我们需要向服务器提交用户名和密码等信息,以获取登录后的权限,从而访问一些需要登录才能查看的页面;在搜索场景中,我们通过提交关键词等参数,获取相关的搜索结果页面。

在 Scrapy 中,使用FormRequest类来发送表单请求。FormRequest是Request的子类,专门用于处理表单提交。下面通过一个模拟登录的示例来展示如何使用FormRequest:

import scrapyclass LoginSpider(scrapy.Spider):name = 'login'start_urls = ['http://www.example.com/login']def parse(self, response):# 构造表单数据form_data = {'username': 'your_username','password': 'your_password'}# 发送表单请求yield scrapy.FormRequest.from_response(response,formdata=form_data,callback=self.after_login)def after_login(self, response):# 登录成功后处理响应if 'Login successful' in response.text:self.logger.info('Login successful')# 继续进行后续的爬取操作yield scrapy.Request('http://www.example.com/protected_page', callback=self.parse_protected)else:self.logger.error('Login failed')def parse_protected(self, response):# 处理需要登录后才能访问的页面data = response.css('div.protected-content::text').get()yield {'protected_data': data}

在上述代码中:

  • 在parse方法中,首先构造了包含用户名和密码的表单数据form_data。
  • 使用scrapy.FormRequest.from_response方法从当前响应中生成一个表单请求。from_response方法会自动从响应中提取表单信息,并根据我们提供的formdata参数填充表单数据。
  • 指定callback为after_login,表示在表单提交成功后,会调用after_login方法来处理响应。
  • 在after_login方法中,根据响应内容判断登录是否成功。如果登录成功,继续发送请求访问需要登录后才能访问的页面,并指定回调函数为parse_protected;如果登录失败,则记录错误信息。
  • 在parse_protected方法中,处理需要登录后才能访问的页面,提取其中的关键数据。

当处理一些需要动态生成表单参数的情况时,我们可能需要先解析页面,获取一些隐藏的参数,然后再构造表单数据。例如,有些网站在登录表单中会包含一个 CSRF(跨站请求伪造)令牌,这个令牌是动态生成的,每次页面加载时都可能不同。在这种情况下,我们需要先从页面中提取这个令牌,然后将其包含在表单数据中进行提交:

import scrapyclass LoginSpider(scrapy.Spider):name = 'login'start_urls = ['http://www.example.com/login']def parse(self, response):# 提取CSRF令牌csrf_token = response.css('input[name="csrf_token"]::attr(value)').get()# 构造表单数据form_data = {'username': 'your_username','password': 'your_password','csrf_token': csrf_token}# 发送表单请求yield scrapy.FormRequest.from_response(response,formdata=form_data,callback=self.after_login)def after_login(self, response):# 登录成功后处理响应if 'Login successful' in response.text:self.logger.info('Login successful')# 继续进行后续的爬取操作yield scrapy.Request('http://www.example.com/protected_page', callback=self.parse_protected)else:self.logger.error('Login failed')def parse_protected(self, response):# 处理需要登录后才能访问的页面data = response.css('div.protected-content::text').get()yield {'protected_data': data}

在这个示例中,通过response.css(‘input[name=“csrf_token”]::attr(value)’).get()从页面中提取了 CSRF 令牌,并将其添加到表单数据中,确保表单提交的正确性和安全性。通过这些方法,我们能够灵活地处理各种表单提交的场景,满足爬虫在不同网页环境下的需求。

五、总结与展望

在本章节中,我们深入探索了 Scrapy 的 Spider 开发。从编写不同类型的 Spider,如 CrawlSpider 和 XMLFeedSpider,了解它们各自的适用场景和实现方式;到学习 Spider 的规则定义与链接提取,掌握 LinkExtractor 的强大功能和使用技巧,能够在复杂的网页结构中精准地提取所需链接;再到处理复杂的网页逻辑,如分页处理和表单提交,让爬虫能够适应各种实际的网页爬取需求。这些知识和技能是我们在 Scrapy 爬虫开发道路上的重要基石。

理论知识固然重要,但实践才是检验真理的唯一标准。希望读者能够积极动手实践,将本章节所学应用到实际的项目中。通过不断地练习,加深对 Scrapy Spider 开发的理解和掌握,提高自己的爬虫开发能力。

下一章节,我们将继续深入 Scrapy 的世界,探讨反爬虫技术与应对策略。在如今的网络环境下,反爬虫技术日益成熟,爬虫开发者需要不断学习和探索新的方法来突破反爬虫机制,获取所需的数据。让我们一起期待下一章节的精彩内容,继续提升我们的爬虫技能。

相关文章:

【Python爬虫(53)】从入门到精通:Scrapy Spider开发全攻略

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

《Keras 3 : 使用迁移学习进行关键点检测》:此文为AI自动翻译

《Keras 3 :使用迁移学习进行关键点检测》 作者:Sayak Paul,由 Muhammad Anas Raza 转换为 Keras 3 创建日期:2021/05/02 最后修改时间:2023/07/19 描述:使用数据增强和迁移学习训练关键点检测器。 (i) 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 关键点检测包…...

CentOS停服后的替代选择:openEuler、Rocky Linux及其他系统的未来展望

CentOS停服后的替代选择&#xff1a;openEuler、Rocky Linux及其他系统的未来展望 引言CentOS停服的背景华为openEuler&#xff1a;面向未来的开源操作系统1. 简介2. 特点3. 发展趋势 Rocky Linux&#xff1a;CentOS的精神继承者1. 简介2. 特点3. 发展趋势 其他可选的替代系统1…...

【Qt】桌面应用开发 ------ 绘图事件和绘图设备 文件操作

文章目录 9、绘图事件和绘图设备9.1 QPainter9.2 手动触发绘图事件9.3 绘图设备9.3.1 QPixmap9.3.2 QImage9.3.3 QImage与QPixmap的区别9.3.4 QPicture 10、文件操作10.1 文件读写10.2 二进制文件读写10.3 文本文件读写10.4 综合案例 9、绘图事件和绘图设备 什么时候画&#x…...

python与C系列语言的差异总结(3)

与其他大部分编程语言不一样&#xff0c;Python使用空白符&#xff08;whitespace&#xff09;和缩进来标识代码块。也就是说&#xff0c;循环体、else条件从句之类的构成&#xff0c;都是由空白符加上冒号(:)来确定的。大部分编程语言都是使用某种大括号来标识代码块的。下面的…...

OpenCV(9):视频处理

1 介绍 视频是由一系列连续的图像帧组成的&#xff0c;每一帧都是一幅静态图像。视频处理的核心就是对这些图像帧进行处理。常见的视频处理任务包括视频读取、视频播放、视频保存、视频帧处理等。 视频分析: 通过视频处理技术&#xff0c;可以分析视频中的运动、目标、事件等。…...

【C++设计模式】观察者模式(1/2):从基础到优化实现

1. 引言 在 C++ 软件与设计系列课程中,观察者模式是一个重要的设计模式。本系列课程旨在深入探讨该模式的实现与优化。在之前的课程里,我们已对观察者模式有了初步认识,本次将在前两次课程的基础上,进一步深入研究,着重解决观察者生命周期问题,提升代码的安全性、灵活性…...

2025年华为手机解锁BL的方法

注&#xff1a;本文是我用老机型测试的&#xff0c;新机型可能不适用 背景 华为官方已经在2018年关闭了申请BL解锁码的通道&#xff0c;所以华为手机已经无法通过官方获取解锁码。最近翻出了一部家里的老手机华为畅玩5X&#xff0c;想着能不能刷个系统玩玩&#xff0c;但是卡…...

在 CentOS 7.9上部署 Oracle 11.2.0.4.0 数据库

目录 在 CentOS 7.9上部署 Oracle 11.2.0.4.0 数据库引言安装常见问题vim粘贴问题 环境情况环境信息安装包下载 初始环境准备关闭 SELinux关闭 firewalld 安装前初始化工作配置主机名安装依赖优化内核参数限制 Oracle 用户的 Shell 权限配置 PAM 模块配置swap创建用户组与用户,…...

idea里的插件spring boot helper 如何使用,有哪些强大的功能,该如何去习惯性的运用这些功能

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons&#xff1a;JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram&#xff0c;自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 &#xff1f; 5 IDEA必装的插件&…...

Docker 搭建 Redis 数据库

Docker 搭建 Redis 数据库 前言一、准备工作二、创建 Redis 容器的目录结构三、启动 Redis 容器1. 通过 redis.conf 配置文件设置密码2. 通过 Docker 命令中的 requirepass 参数设置密码 四、Host 网络模式与 Port 映射模式五、检查 Redis 容器状态六、访问 Redis 服务总结 前言…...

JAVAweb之过滤器,监听器

文章目录 过滤器认识生命周期FilterConfigFilterChain过滤器执行顺序应用场景代码 监听器认识ServletContextListenerHttpSessionListenerServletRequestListener代码 过滤器 认识 Java web三大组件之一&#xff0c;与Servlet相似。过滤器是用来拦截请求的&#xff0c;而非处…...

计算机毕业设计SpringBoot+Vue.js足球青训俱乐部管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

基于 DeepSeek LLM 本地知识库搭建开源方案(AnythingLLM、Cherry、Ragflow、Dify)认知

写在前面 博文内容涉及 基于 Deepseek LLM 的本地知识库搭建使用 ollama 部署 Deepseek-R1 LLM知识库能力通过 Ragflow、Dify 、AnythingLLM、Cherry 提供理解不足小伙伴帮忙指正 &#x1f603;,生活加油 我站在人潮中央&#xff0c;思考这日日重复的生活。我突然想&#xff0c…...

QSplashScreen --软件启动前的交互

目录 QSplashScreen 类介绍 使用方式 项目中使用 THPrinterSplashScreen头文件 THPrinterSplashScreen实现代码 使用代码 使用效果 QSplashScreen 类介绍 QSplashScreen 是 Qt 中的一个类&#xff0c;用于显示启动画面。它通常在应用程序启动时显示&#xff0c;以向用户显…...

「软件设计模式」责任链模式(Chain of Responsibility)

深入解析责任链模式&#xff1a;用C打造灵活的请求处理链 引言&#xff1a;当审批流程遇上设计模式 在软件系统中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个请求需要经过多个处理节点的判断&#xff0c;每个节点都有权决定是否处理或传递请求。就像企业的请假审批…...

蓝桥杯嵌入式客观题以及解释

第十一届省赛&#xff08;大学组&#xff09; 1.稳压二极管时利用PN节的反向击穿特性制作而成 2.STM32嵌套向量终端控制器NVIC具有可编程的优先等级 16 个 3.一个功能简单但是需要频繁调用的函数&#xff0c;比较适用内联函数 4.模拟/数字转换器的分辨率可以通过输出二进制…...

你对WebAssembly的看法是什么?

WebAssembly&#xff08;Wasm&#xff09;是一种新兴的技术&#xff0c;旨在通过提供一种新的低级字节码格式来提高 Web 应用程序的性能和效率。它与 JavaScript 互补&#xff0c;使得开发者可以将其他编程语言&#xff08;如 C、C、Rust 等&#xff09;编译为高效的字节码&…...

Qt在Linux嵌入式开发过程中复杂界面滑动时卡顿掉帧问题分析及解决方案

Qt在Linux嵌入式设备开发过程中&#xff0c;由于配置较低&#xff0c;加上没有GPU&#xff0c;我们有时候会遇到有些组件比较多的复杂界面&#xff0c;在滑动时会出现掉帧或卡顿的问题。要讲明白这个问题还得从CPU和GPU的分工说起。 一、硬件层面核心问题根源剖析 CPU&#x…...

vscode 版本

vscode官网 Visual Studio Code - Code Editing. Redefined 但是官网只提供最新 在之前的版本就要去github找了 https://github.com/microsoft/vscode/releases 获取旧版本vscode安装包的方法_vscode 老版本-CSDN博客...

low rank decomposition如何用于矩阵的分解

1. 什么是矩阵分解和低秩分解 矩阵分解是将一个矩阵表示为若干结构更简单或具有特定性质的矩阵的组合或乘积的过程。低秩分解&#xff08;Low Rank Decomposition&#xff09;是其中一种方法&#xff0c;旨在将原矩阵近似为两个或多个秩较低的矩阵的乘积&#xff0c;从而降低复…...

C# string转unicode字符

在 C# 中&#xff0c;将字符串转换为 Unicode 字符&#xff08;即每个字符的 Unicode 码点&#xff09;可以通过遍历字符串中的每个字符并获取其 Unicode 值来实现。Unicode 值是一个整数&#xff0c;表示字符在 Unicode 标准中的唯一编号。 以下是实现方法&#xff1a; 1. 获…...

51单片机-串口通信编程

串行口工作之前&#xff0c;应对其进行初始化&#xff0c;主要是设置产生波特率的定时器1、串行口控制盒中断控制。具体步骤如下&#xff1a; 确定T1的工作方式&#xff08;编程TMOD寄存器&#xff09;计算T1的初值&#xff0c;装载TH1\TL1启动T1&#xff08;编程TCON中的TR1位…...

Fisher信息矩阵与Hessian矩阵:区别与联系全解析

Fisher信息矩阵与Hessian矩阵&#xff1a;区别与联系全解析 在统计学和机器学习中&#xff0c;Fisher信息矩阵&#xff08;FIM&#xff09;和Hessian矩阵是两个经常出现的概念&#xff0c;它们都与“二阶信息”有关&#xff0c;常用来描述函数的曲率或参数的敏感性。你可能听说…...

有哪些开源大数据处理项目使用了大模型

以下是一些使用了大模型的开源大数据处理项目&#xff1a; 1. **RedPajama**&#xff1a;这是一个开源项目&#xff0c;使用了LLM大语言模型数据处理组件&#xff0c;对GitHub代码数据进行清洗和处理。具体流程包括数据清洗、过滤低质量样本、识别和删除重复样本等步骤。 2. …...

ubuntu离线安装Ollama并部署Llama3.1 70B INT4

文章目录 1.下载Ollama2. 下载安装Ollama的安装命令文件install.sh3.安装并验证Ollama4.下载所需要的大模型文件4.1 加载.GGUF文件&#xff08;推荐、更容易&#xff09;4.2 加载.Safetensors文件&#xff08;不建议使用&#xff09; 5.配置大模型文件 参考&#xff1a; 1、 如…...

机器学习数学通关指南——泰勒公式

前言 本文隶属于专栏《机器学习数学通关指南》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见《机器学习数学通关指南》 正文 一句话总结 泰勒公式是用多…...

目标检测tricks

A. Stochastic Weight Averaging (SWA) 1. 基本思想 SWA 的核心思想是通过对训练过程中不同时间点的模型参数进行加权平均&#xff0c;从而获得一个更好的模型。具体来说&#xff0c;SWA 在训练过程的后期阶段对多个不同的模型快照&#xff08;snapshots&#xff09;进行平均…...

JNA基础使用,调用C++返回结构体

C端 test.h文件 #pragma oncestruct RespInfo {char* path;char* content;int statusCode; };extern "C" { DLL_EXPORT void readInfo(char* path, RespInfo* respInfo); }test.cpp文件 #include "test.h"void readInfo(char* path, RespInfo* respInfo…...

【算法】793. 高精度乘法

题目 793. 高精度乘法 思路 把b当作一个整体进行乘法&#xff0c;用A的每一位和b相乘&#xff0c;还要加上判断001的情况&#xff0c;把前面的0删掉。 代码 #include<iostream> #include<vector> using namespace std; vector<int>mul(vector<int>…...