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

news2025/2/26 16:54:10

【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 LinkExtractor

class 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 XMLFeedSpider

class 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 LinkExtractor

class 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 scrapy


class 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:
            # 拼接完整的下一页URL
            next_page_url = response.urljoin(next_page)
            # 发送下一页的请求,并指定回调函数为parse
            yield 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 scrapy


class 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 scrapy


class 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 scrapy


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

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

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

相关文章

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

在 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创建用户组与用户,…

计算机毕业设计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.模拟/数字转换器的分辨率可以通过输出二进制…

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

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

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、 如…

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…

解锁养生密码,拥抱健康生活

在快节奏的现代生活中&#xff0c;养生不再是一种选择&#xff0c;而是我们保持活力、提升生活质量的关键。它不是什么高深莫测的学问&#xff0c;而是一系列融入日常的简单习惯&#xff0c;每一个习惯都在为我们的健康加分。 早晨&#xff0c;当第一缕阳光洒进窗户&#xff0c…

OpenCV(6):图像边缘检测

图像边缘检测是计算机视觉和图像处理中的一项基本任务&#xff0c;它用于识别图像中亮度变化明显的区域&#xff0c;这些区域通常对应于物体的边界。是 OpenCV 中常用的边缘检测函数及其说明: 函数算法说明适用场景cv2.Canny()Canny 边缘检测多阶段算法&#xff0c;检测效果较…

spark的一些指令

一&#xff0c;复制和移动 1、复制文件 格式&#xff1a;cp 源文件 目标文件 示例&#xff1a;把file1.txt 复制一份得到file2.txt 。那么对应的命令就是&#xff1a;cp file1.txt file2.txt 2、复制目录 格式&#xff1a;cp -r 源文件 目标文件夹 示例&#xff1a;把目…

OpenHarmony全球化子系统

OpenHarmony全球化子系统 简介系统架构目录相关仓 简介 当OpenHarmony系统/应用在全球不同区域使用时&#xff0c;系统/应用需要满足不同市场用户关于语言、文化习俗的需求。全球化子系统提供支持多语言、多文化的能力&#xff0c;包括&#xff1a; 资源管理能力 根据设备类…

创建私人阿里云docker镜像仓库

步骤1、登录阿里云 阿里云创建私人镜像仓库地址&#xff1a;容器镜像服务 步骤2、创建个人实例 步骤&#xff1a;【实例列表】 》【创建个人实例】 》【设置Registry登录密码】 步骤3、创建命名空间 步骤&#xff1a;【个人实例】》【命名空间】》【创建命名空间】 注意&am…

【LLM】本地部署LLM大语言模型+可视化交互聊天,附常见本地部署硬件要求(以Ollama+OpenWebUI部署DeepSeekR1为例)

【LLM】本地部署LLM大语言模型可视化交互聊天&#xff0c;附常见本地部署硬件要求&#xff08;以OllamaOpenWebUI部署DeepSeekR1为例&#xff09; 文章目录 1、本地部署LLM&#xff08;以Ollama为例&#xff09;2、本地LLM交互界面&#xff08;以OpenWebUI为例&#xff09;3、本…

LLM之论文阅读——Context Size对RAG的影响

前言 RAG 系统已经在多个行业中得到广泛应用&#xff0c;尤其是在企业内部文档查询等场景中。尽管 RAG 系统的应用日益广泛&#xff0c;关于其最佳配置的研究却相对缺乏&#xff0c;特别是在上下文大小、基础 LLM 选择以及检索方法等方面。 论文原文: On the Influence of Co…