Python 如何高效实现 PDF 内容差异对比
Python 如何高效实现 PDF 内容差异对比
- 1. 安装 PyMuPDF 库
- 2. 获取 PDF 内容
- 通过文件路径获取
- 通过 URL 获取
- 3. 提取 PDF 每页信息
- 4. 内容对比
- metadata 差异
- 文本对比
- 可视化对比
- 5. 提升对比效率
- 通过哈希值快速判断页面是否相同
- 早停机制
- 多进程机制
- 6. 其他
最近有接触到 PDF 内容对比,所以分享一下如何用 Python 实现 PDF 内容对比。
1. 安装 PyMuPDF 库
PyMuPDF 提供了丰富的文档操作功能,包括文本/图像提取、页面渲染、文档合并拆分、注释添加等。支持格式包括 PDF、EPUB、XPS 等。它是基于 C 语言库 MuPDF 的 Python 绑定,MuPDF 由 Artifex 公司开发,以高性能和小巧著称。通过 pip install PyMuPDF 安装,但在代码中需通过 import fitz 调用其功能。fitz 是该库的核心模块,fitz 名称源自 MuPDF 的原始渲染引擎 “Fitz”。为保持一致性,PyMuPDF 的 Python 接口沿用了此名称。
pip install pymupdf
import fitz
2. 获取 PDF 内容
fitz.open 是 PyMuPDF(fitz 模块)中用于打开 PDF 或其他支持的文档格式的函数。它返回一个 fitz.Document 对象。
通过 fitz.Document 对象,可以:
- 访问页面:
使用索引访问文档中的页面,例如 doc[0] 表示第一页。
每个页面是一个 fitz.Page 对象。 - 获取文档信息:
获取文档的元数据(如标题、作者、创建时间等)。
获取文档的页数。
获取 PDF 内容有两种方式:
通过文件路径获取
def get_pdf_content_from_path(pdf_path):"""Get PDF content from a local file path"""pdf = fitz.open(pdf_path)return pdf
通过 URL 获取
注意通过接口调用获取 repsonce.content 字节类型 content,而不是 response.text 字符串类型 content
属性 | response.content | response.text |
---|---|---|
返回类型 | bytes(字节) | str(字符串) |
解码 | 不进行解码,返回原始二进制数据 | 自动根据 response.encoding 解码 |
适用场景 | 处理二进制文件(如图片、PDF 等) | 处理文本数据(如 HTML、JSON 等) |
手动解码 | 需要手动解码(如 content.decode(‘utf-8’)) | 自动解码,无需额外操作 |
def get_pdf_content_from_datalake(content_url):"""Get PDF content using content_url"""content = get_content_by_content_url(content_url)try:pdf = fitz.open(filetype="pdf", stream=content)except Exception as e:raise ValueError(f"Failed to open PDF from DataLake for URL: {content_url}. Error: {str(e)}")return pdf
3. 提取 PDF 每页信息
PDF 通常有很多页 content,需要比较每页的 content,前面获取到 fitz.Document,使用索引访问文档中的页面 doc[index] 返回 fitz.Page 对象。
下面是 fitz.Page 的常用属性,我们对比内容只需要用到 get_text() 和 get_pixmap(),通过比较每页的 text 和像素就能找出 PDF 任何细微的差异,包括内容格式,e.g 字体,加粗,高亮,table 布局,图片大小等。
属性/方法 | 描述 |
---|---|
number | 当前页面的页码(从 0 开始)。 |
rect | 页面尺寸(矩形区域)。 |
rotation | 页面旋转角度(0、90、180 或 270)。 |
mediabox | 页面媒体框的尺寸。 |
cropbox | 页面裁剪框的尺寸。 |
get_text() | 提取页面文本(支持多种格式,如 “text”、“html”、“json”)。 |
get_pixmap() | 将页面渲染为图像。 |
search_for() | 搜索页面中的文本。 |
get_images() | 获取页面中的嵌入图像信息。 |
add_annot() | 在页面上添加注释。 |
write() | 将页面内容导出为字节流。 |
其中 get_pixmap() 用于将 PDF 页面渲染为像素图(图像)。它是将 PDF 页面转换为图像格式的核心方法,常用于生成页面的可视化表示或进行图像比较。返回的 fitz.Pixmap 对象包含图像的像素数据和相关信息,常用属性如下:
属性名 | 描述 |
---|---|
samples | 图像的原始像素数据(字节流)。 |
width | 图像的宽度(像素)。 |
height | 图像的高度(像素)。 |
stride | 每行像素的字节数。 |
colorspace | 图像的颜色空间(如 RGB、灰度等)。 |
# Determine the maximum number of pagesmax_pages = max(len(pdf_base), len(pdf_target))
def extract_page_data(pdf, page_num):"""Extract text and pixel data from a PDF page."""page = pdf[page_num]text = page.get_text()pix = page.get_pixmap()return {"text": text,"pix_samples": pix.samples,"pix_width": pix.width,"pix_height": pix.height,}
def generate_page_data(pdf_base, pdf_target, max_pages, doc_folder):"""Generator to yield page data for multiprocessing."""for page_num in range(max_pages):page_data_base = extract_page_data(pdf_base, page_num)page_data_target = extract_page_data(pdf_target, page_num)yield (page_data_base, page_data_target, page_num, doc_folder)
4. 内容对比
metadata 差异
fitz.Document 对象元数据 metadata 属性,通常包括文档的基本信息,例如标题、作者、创建时间等。如果忽略 metadata 差异,可以忽略此项对比。
以下是 metadata 字典中常见的键及其含义:
键名 | 描述 |
---|---|
title | 文档的标题(Title)。 |
author | 文档的作者(Author)。 |
subject | 文档的主题(Subject)。 |
keywords | 文档的关键字(Keywords)。 |
creator | 创建文档的应用程序(Creator)。 |
producer | 生成文档的工具或软件(Producer)。 |
creationDate | 文档的创建日期(Creation Date)。 |
modDate | 文档的最后修改日期(Modification Date)。 |
trapped | 文档是否被标记为“Trapped”(通常为 True 或 False,可能为空)。 |
compare_metadata(pdf_base.metadata, pdf_target.metadata, result)
def compare_metadata(metadata_base, metadata_target, result):"""Compare PDF metadata"""for key in set(metadata_base.keys()) | set(metadata_target.keys()):if metadata_base.get(key) != metadata_target.get(key):result["metadata_differences"].append(f"Metadata '{key}' differs: pdf_base='{metadata_base.get(key)}', pdf_target='{metadata_target.get(key)}'")
文本对比
ndiff 是 Python 标准库 difflib 中的一个方法,用于逐行比较两个字符串序列,并生成一个可读的差异列表。它特别适合用于文本比较,能够清晰地标记出新增、删除和修改的部分。
difflib.ndiff 的功能
- 输入: 两个字符串序列(通常是通过 splitlines() 分割的多行文本)。
- 输出: 一个迭代器,生成每一行的差异标记。
- 差异标记:
-:表示在第一个序列中存在,但在第二个序列中不存在的行。
+:表示在第二个序列中存在,但在第一个序列中不存在的行。
(空格):表示两个序列中都存在的行(没有变化)。
?:表示上一行的具体差异(通常用于标记字符级别的变化)。
def compare_text_content(page_data_base, page_data_target, page_num, result):"""Compare text content of two pages."""text_base = page_data_base["text"]text_target = page_data_target["text"]if text_base != text_target:result["text_differences"].append(f"Text differs on page {page_num + 1}")diff = list(difflib.ndiff(text_base.splitlines(), text_target.splitlines()))differences = [d for d in diff if d.startswith('+ ') or d.startswith('- ')]if differences:result["text_differences"].append(f"Page {page_num + 1} specific differences: {differences[:5]}...")
可视化对比
比较两个 PDF 页面视觉内容,通过比较页面的像素数据来检测页面之间的视觉差异。
- 页面尺寸比较:
首先比较两个页面的宽度和高度,如果页面尺寸不同,记录差异并退出函数。 - 像素数据比较:
将页面的像素数据转换为图像对象。使用 PIL.Image.frombytes 将页面的像素数据转换为 RGB 图像对象。
使用 ImageChops.difference 计算两个图像的差异,返回一个差异图像,其中每个像素的值表示两个图像对应像素的差异程度。 - 保存差异图像:
如果发现差异,保存基准页面、目标页面和差异图像到指定的文件夹。
记录差异信息到 result 字典中。
def compare_visual_content(page_data_base, page_data_target, page_num, doc_folder, result):"""Compare visual content of two pages."""if (page_data_base["pix_width"] != page_data_target["pix_width"] orpage_data_base["pix_height"] != page_data_target["pix_height"]):result["format_differences"].append(f"Page {page_num + 1} size differs: PDF_base={page_data_base['pix_width']}x{page_data_base['pix_height']}, "f"PDF_target={page_data_target['pix_width']}x{page_data_target['pix_height']}")returnimg_base = Image.frombytes("RGB", [page_data_base["pix_width"], page_data_base["pix_height"]], page_data_base["pix_samples"])img_target = Image.frombytes("RGB", [page_data_target["pix_width"], page_data_target["pix_height"]], page_data_target["pix_samples"])diff_img = ImageChops.difference(img_base, img_target)if np.any(np.array(diff_img)):img_base_path = os.path.join(doc_folder, f"page_{page_num + 1}_pdf_base.png")img_target_path = os.path.join(doc_folder, f"page_{page_num + 1}_pdf_target.png")diff_path = os.path.join(doc_folder, f"page_{page_num + 1}_diff.png")img_base.save(img_base_path)img_target.save(img_target_path)diff_img.save(diff_path)result["format_differences"].append(f"differs on page {page_num + 1}: difference image saved at {diff_path}")
5. 提升对比效率
通过哈希值快速判断页面是否相同
通过比较页面内容的哈希值(包括文本和像素数据),如果哈希值相同,则跳过进一步比较。
如果哈希值不同,调用 compare_text_content 和 compare_visual_content 方法分别比较文本和视觉内容。
def hash_page_content(page_data):"""Generate a hash for the page content."""text_hash = hashlib.md5(page_data["text"].encode()).hexdigest()pix_hash = hashlib.md5(page_data["pix_samples"]).hexdigest()return text_hash, pix_hashdef compare_page(page_data_base, page_data_target, page_num, doc_folder):"""Compare a single page for text and visual differences."""result = {"text_differences": [],"format_differences": []}try:# Compare hashes firstbase_hash = hash_page_content(page_data_base)target_hash = hash_page_content(page_data_target)if base_hash == target_hash:return result # Skip comparison if hashes are identical# Compare text and visual contentcompare_text_content(page_data_base, page_data_target, page_num, result)compare_visual_content(page_data_base, page_data_target, page_num, doc_folder, result)except Exception as e:result["format_differences"].append(f"Failed to compare page {page_num + 1}: {str(e)}")return result
早停机制
如果 PDF 差异页面非常很多,后续的页面差异其实是无意义的,我们可以设定一个差异页面数量的最大值,比如 3 或 5,当发现的差异页面数量达到指定的最大值时,函数会停止进一步的比较。
def compare_page_with_limit(args, diff_page_count, max_diff_pages, lock):"""Compare a single page with early termination."""page_data_base, page_data_target, page_num, doc_folder = argswith lock:if diff_page_count.value >= max_diff_pages:return None # Skip further processing if limit is reachedpage_result = compare_page(page_data_base, page_data_target, page_num, doc_folder)if page_result["text_differences"] or page_result["format_differences"]:with lock:diff_page_count.value += 1return page_result
多进程机制
如果需要比较的 PDF 文件比较多,我们也可以采用多进程并发比较,提升脚本执行时间。这里可以根据实际情况,是基于 PDF 之间并行,还是基于单个 PDF 页面之间并行。我这边是基于 PDF 页面之间并发执行的,考虑到大多数 PDF 页面达上百页,页面之间并发效率更高。
pool.starmap 是 Python 中 multiprocessing.Pool 提供的一种方法,用于在多进程环境下并行执行函数。它类似于 map 方法,但支持将多个参数传递给目标函数。
这里定义了一个 diff_page_count 共享变量(通过 manager.Value 创建),因为是 int 型,所以在多进程环境下需要使用 lock 来保护它。这是因为 manager.Value 本身并不能保证对其值的操作是原子的(atomic)。
共享变量的非原子操作,对共享变量的操作(如 diff_page_count.value += 1)实际上是由多个步骤组成的:
- 读取当前值。
- 增加值。
- 写回新值。
在多进程环境下,如果多个进程同时执行这些步骤,就可能导致数据竞争(race condition),从而导致共享变量的值不正确。假设两个进程同时读取 diff_page_count.value 的值为 5,然后分别将其加 1 并写回。最终的结果可能是 6 而不是预期的 7,因为两个进程的操作互相覆盖了。使用 lock 可以确保在一个进程修改共享变量时,其他进程必须等待,直到当前进程完成操作并释放锁。这就避免了数据竞争,确保共享变量的值始终正确。
当然如果换成 diff_page_count = manager.list(),它的操作(如添加或删除元素)是线程安全的,底层已经实现了同步机制。因此,多个进程可以安全地向列表中添加元素,而无需显式使用 lock。但是 manager.list() 的操作比直接操作 manager.Value 稍慢,因为它需要处理线程安全。如果性能是关键问题,仍然可以考虑使用 manager.Value 和 lock。
def prepare_output_folder(output_folder, pdf_object_id):"""Prepare the output folder for storing comparison results."""output_folder = os.path.join(constants.OUTPUT_DIR, output_folder)os.makedirs(output_folder, exist_ok=True)doc_folder = os.path.join(output_folder, pdf_object_id.replace(":", "_"))clear_and_create_content_dir(doc_folder)return doc_folderdef compare_pdf(pdf_base_path, pdf_target_path, pdf_object_id, pdf_base_object_url, pdf_target_object_url,is_from_datalake=True, output_folder="pdf_diff_results", max_diff_pages=3):"""Compare two PDF files for content and format differences"""# Prepare output folderdoc_folder = prepare_output_folder(output_folder, pdf_object_id)# Initialize resultresult = {"text_differences": [],"format_differences": [],"metadata_differences": [],"page_count": {"pdf_base": 0, "pdf_target": 0}}# Open PDF filespdf_base = get_pdf_content_from_datalake(pdf_base_object_url) if is_from_datalake else get_pdf_content_from_path(pdf_base_path)pdf_target = get_pdf_content_from_datalake(pdf_target_object_url) if is_from_datalake else get_pdf_content_from_path(pdf_target_path)# Compare page countresult["page_count"]["pdf_base"] = len(pdf_base)result["page_count"]["pdf_target"] = len(pdf_target)# Compare metadata, ignore differences in creation/modification dates# compare_metadata(pdf_base.metadata, pdf_target.metadata, result)# Determine the maximum number of pagesmax_pages = max(len(pdf_base), len(pdf_target))# Compare pages in parallel using a generatorwith Manager() as manager:# Shared counter for tracking pages with differencesdiff_page_count = manager.Value('i', 0)lock = manager.Lock()# Create a pool of worker processeswith Pool() as pool:page_results = pool.starmap(compare_page_with_limit,[(args, diff_page_count, max_diff_pages, lock) for args in generate_page_data(pdf_base, pdf_target, max_pages, doc_folder)])if diff_page_count.value >= max_diff_pages:print(f"Early termination: {diff_page_count.value} pages with differences found, stopping further processing.")pool.terminate()pool.join()# Aggregate resultsfor page_result in page_results:if page_result is None:continue # Skip if terminated earlyresult["text_differences"].extend(page_result["text_differences"])result["format_differences"].extend(page_result["format_differences"])return result
6. 其他
还有一些其他细节问题,这里就不细说了,一个完整的脚本执行是需要考虑很多因素的,目的就是为了全自动化,减少人工干预成本,提高整体效率。
这里罗列一些:
- 测试数据收集和配置,方便后期定制化执行不同的测试数据集
- 脚本执行过程中的 log,方便 troubleshooting
- 生成测试报告,包括细节信息,汇总信息(total,fail,pass),及其他统计信息,方便 triage
- 部署到 Jenkins 上日常执行,并发送测试报告,方便 CICD
相关文章:
Python 如何高效实现 PDF 内容差异对比
Python 如何高效实现 PDF 内容差异对比 1. 安装 PyMuPDF 库2. 获取 PDF 内容通过文件路径获取通过 URL 获取 3. 提取 PDF 每页信息4. 内容对比metadata 差异文本对比可视化对比 5. 提升对比效率通过哈希值快速判断页面是否相同早停机制多进程机制 6. 其他 最近有接触到 PDF 内容…...
JJJ:generic netlink例程分析
接嵌入式毕设、课设辅导、技术咨询,欢迎私信 完整代码:github代码仓链接 若想要和指定的generic netlink family通信,如: 994 static struct genl_family genl_ctrl __ro_after_init { // generic netlink子协议995 .module THIS_MODU…...
3D图像重建中Bundle Adjustment的推导与实现
介绍 捆集调整(Bundle Adjustment),也称为光束平差法,是一种利用来自多台相机的图像数据同时优化相机位置和姿态以及 3D 点位置的技术。该技术历史相当悠久,于 1958 年由 DC Brown1 首次提出。 最初这是美国空军正在进行的从航拍照片中恢复环境的研究,随着视觉SLAM和Sf…...
【代码模板】C语言如何修改文件权限?读写执行权限对应值是多少?(chmod(“./a.out“, 0741);bit 2 1 0表示 读 写 执行)
#include "stdio.h" #include "unistd.h"int main(int argc, char *argv[]) {if (chmod("./a.out", 0741) ! 0) {perror("Failed to set exec permission");return -1;}return 1; }0741中0是8进制,7是 0111, 4是…...
新版pycharm如何实现debug调试需要参数的python文件
在最顶上有这个选项 把鼠标移上去 点击号 选择python 具体长这样 名字随便取 script选择你要调试的python文件 脚本形参填入参数,如:--arg1 value1 --arg2 value2 点击应用确定 最后给文件打上断点,再点击调试按键,就可以调试了…...
赚钱模拟器-百宝库v0.1.1
#include<bits/stdc.h> #include<windows.h> using namespace std; int n,i,j; void welcome(); void zhuye(); void GAME(); int main(){welcome();zhuye();return 0; }void welcome(){cout<<"欢迎您使用更多资源-百宝库v0.1.1"<<endl;sys…...
实战打靶集锦-38-inclusiveness
文章目录 1. 主机发现2. 端口扫描&服务枚举3. 服务探查4.系统提权 靶机地址:https://download.vulnhub.com/inclusiveness/Inclusiveness.ova 1. 主机发现 目前只知道目标靶机在192.168.56.xx网段,通过如下的命令,看看这个网段上在线的主…...
01人工智能基础入门
一、AI应用场景和发展历程 1.1行业应用 1、deepdream图像生成、yolo目标检测 2、知识图谱、画风迁移 3、语音识别、计算机视觉 4、用户画像 5、百度人工智能布局 1.2发展历程 人工智能的发展经历了 3 个阶段: 1980年代是正式成形期,尚不具备影响力。 …...
SortedSet结构之用户积分实时榜单实战
Redis 中的SortedSet结构非常适合用于实现实时榜单的场景,它根据成员的分数自动进行排序,支持高效的添加、更新和查询操作。 SortedSet实时榜单的一些典型应用场景: 游戏中的玩家排行榜:在多人在线游戏中,使用 Sorte…...
C++_类和对象(上)
【本节目标】 面向过程和面向对象初步认识类的引入类的定义类的访问限定符及封装类的作用域.类的实例化类的对象大小的计算类成员函数的this指针 1. 面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过…...
vllm作为服务启动,无需额外编写sh文件,一步到位【Ubuntu】
看到网上有的vllm写法,需要额外建立一个.sh文件,还是不够简捷。这里提供一种直接编写service文件一步到位的写法: vi /etc/systemd/system/vllm.service [Unit] DescriptionvLLM Service Afternetwork.target[Service] Typesimple Userroot…...
Mathematics | Branch
注:本文为“遇见数学”翻译的 “数学分支概览” 两篇文章合辑。 数学世界的版图:主要分支概览(上) 原创 遇见数学 2025 年 04 月 03 日 12:02 河南 数学的分支(Areas of Mathematics) 在文艺复兴之前&am…...
8.5/Q1,Charls最新文章解读
文章题目:Associations of estimated glucose disposal rate with frailty progression: results from two prospective cohorts DOI:10.1186/s12933-025-02650-7 中文标题:估计葡萄糖处理率与虚弱进展的关系:两个前瞻性队列的结果…...
PCL学习(5)随机采样一致性算法RANSAC
一、RANSAC概念及作用 1.1 基本概念 RANSAC是一种鲁棒的参数估计方法,用于从包含大量异常值的数据中拟合数学模型。其核心思想是通过随机采样和迭代验证,找到最优的模型参数,避免异常值的干扰。 1.2 核心思想 随机采样:每次从数…...
app逆向专题一:如何下载app
app逆向专题一:如何下载app 一、打开豌豆荚官网 一、打开豌豆荚官网 打开豌豆荚官网豌豆荚,在右上角搜索框中输入要下载的app名称 依次点击搜索–查看–普通下载,即可将apk文件下载到本地电脑上。...
将 DataFrame 中某一列的列表拆分成多个独立的列的方式
要将 DataFrame 中某一列的列表拆分成多个独立的列,可以使用以下方法,具体取决于数据结构和需求: 场景示例 假设 DataFrame 中 genres 列存储的是列表(如 [drama, action]),目标是将每个列表元素拆分成多列…...
VUE+SPRINGBOOT+语音技术实现智能语音歌曲管理系统
语音控制歌曲的播放、暂停、增删改查 <template><div class"Music-container"><div style"margin: 10px 0"><!--检索部分--><el-input style"width: 200px;" placeholder"请输入歌曲名称"v-model"sen…...
安卓开发工程师-自定义 View
1. 如何创建一个简单的自定义 View? 创建自定义 View 的基本步骤如下: 继承 View 或其子类:自定义 View 可以继承自 View 或其他更具体的视图类(如 ImageView、Button 等)。重写构造方法:通常需要重写三个…...
Vue中权限控制的方案
文章目录 源码:一、页面级1.1、路由守卫1.2、动态路由 二、按钮级别2.1、通过v-if来判断2.2、通过组件包裹的方式来判断2.3、通过自定义指令的方式 三、接口级别 源码: https://gitee.com/liu-qiang-yyds/sysPermission 一、页面级 1.1、路由守卫 前端…...
磁盘分析工具合集:告别C盘焦虑!
今天李师傅带大家盘点五款硬盘空间分析利器,帮你精准定位那些"吃空间"的元凶,让C盘告别臃肿烦恼! 一、WizTree 这款NTFS磁盘的"透视眼"堪称效率典范。它通过直接读取硬盘主文件表(MFT)实现秒级扫描,1TB机械…...
硬件学习之器件篇-蜂鸣器
根据工作原理的不同,可以分为电磁式蜂鸣器和压电式蜂鸣器。 1、电磁式蜂鸣器 电磁式蜂鸣器根据内部是否有震荡源,又可以分为有源电磁式蜂鸣器和无源电磁式蜂鸣器。 1.1 外观区别 有源电磁式蜂鸣器从底部看是,是黑胶密封的。 无源电磁式蜂…...
紫檀博物馆一游与软件开发
今天去逛了中国紫檀博物馆,里边很多层展品,也有一些清代的古物,檀木,黄花梨木家具和各种摆件,馆主陈丽华女士也是发心复原、保留和弘扬中国的传统文化,和西游记唐僧扮演者迟成瑞先生一家。 每一件展品都精…...
Cribl 新建Datatype
Cribl 数据dataset 有个很重要的就是datatype, 下面来新建一下: 先看一下原来的datatype : 再点击Add Datatype: Rule...
开源 LLM 应用开发平台 Dify 全栈部署指南(Docker Compose 方案)
开源 LLM 应用开发平台 Dify 全栈部署指南(Docker Compose 方案) 一、部署环境要求与前置检查 1.1 硬件最低配置 组件要求CPU双核及以上内存4GB 及以上磁盘空间20GB 可用空间 1.2 系统兼容性验证 ✅ 官方支持系统: Ubuntu 20.04/22.04 L…...
医药档案区块链系统
1. 医生用户模块 目标用户:医护人员 核心功能: 检索档案:通过关键词或筛选条件快速定位患者健康档案。请求授权:向个人用户发起档案访问权限申请,需经对方确认。查看档案…...
Redis常见命令
(一)常见命令① 一、数据结构 二、通用命令 ①KEYS查询语句 pattern代表模板,有点像匹配表达式(不是正则),是redis的一种内置表达式,可以在里面使用通配符 底层存在一种模糊查询机制,效率并不高。当redis的数据量达到一定规模时(数百万上千万甚至更多),使用这种模糊查询机制会…...
Qt的window注册表读写以及删除
Qt的window注册表读写以及删除 1. 使用 QSettings(Qt推荐方式)基本操作关键点限制 2. 调用Windows原生API示例:创建/读取键值常用API注意事项 3. 高级场景(1) 递归删除键(2) 注册表权限修改 4. 安全性建议总结其他QT文章推荐 在Qt中操作Windo…...
纯css实现环形进度条
需要在中实现一个定制化的环形进度条,最终效果如图: 使用代码 <divclass"circular-progress":style"{--progress: nextProgress,--color: endSliderColor,--size: isFull ? 60rpx : 90rpx,}"><div class"inner-conte…...
20250405周赛-S
链接 A. 日历 我的: #include<bits/stdc.h> using namespace std; int n,d[105],ans; bool check(int x,int y){if(x<10){if(y<10){return xy;}else{return xy%10&&xy/10;}}else{if(y<10){return yx%10&&yx/10;}else{return y/10…...
某碰瓷国赛美赛,号称第三赛事的数模竞赛
首先我非常不能理解的就是怎么好意思自称第三赛事的呢?下面我们进行一个简单讨论,当然这里不对国赛和美赛进行讨论。首先我们来明确一点,比赛的含金量由什么来定?这个可能大家的评价指标可能不唯一,我通过DeepSeek选取…...
希象传屏下载
2025年4月5日,11~22℃ 免费软件,功能:手机、个人笔记本和智慧黑板可以双向控制。要求在同一网络下或者同一WiFi下。 目的:自己下载的时候比较方便。 1、希沃易官网 2、如何下载? 被投屏:接收端࿱…...
解决 PDF 难题:批量处理、文档清理与自由拆分合并
软件介绍 在日常办公与学习中,处理 PDF 文件常常让人头疼不已,不过别担心,今天有一款堪称神器的国产老牌 PDF 工具要分享给大家。它就是 PDF 补丁丁,凭借其强大功能,为大家排忧解难。 界面体验 初次打开 PDF 补丁丁&…...
SQL Server 2022 数据同步到 Elasticsearch 思考
公司的老项目了,采用的是sqlserver 2022作为数据卡做的,但是产品对接客户,发现对搜索的要求很高,尤其是全文检索,考虑到ES采用倒排所以效率上的优势和整体开发的成本,大佬们商量之后,果断的采用…...
基于Spark的哔哩哔哩舆情数据分析系统
【Spark】基于Spark的哔哩哔哩舆情数据分析系统 (完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 本项目基于Python和Django框架进行开发,为了便于广大用户针对舆情进行个性化分析处…...
分布式事务解决方案全解析:从经典模式到现代实践
前言 在分布式系统中,数据一致性是一个核心问题。随着微服务架构的普及,跨服务、跨数据库的操作变得越来越普遍,如何保证这些操作的原子性、一致性、隔离性和持久性(ACID)成为了一个极具挑战性的任务。本文将全面介绍…...
迈向未来:数字化工厂管理如何重塑生产力
迈向未来:数字化工厂管理如何重塑生产力 随着工业4.0的浪潮席卷全球,“数字化工厂管理”成为制造业转型的关键一步。从传统生产模式到数据驱动的智能制造,企业在追求生产效率、质量与灵活性方面实现了飞跃式发展。然而,实施数字化管理不仅仅是技术问题,更关乎流程优化、数…...
LeetCode 1863.找出所有子集的异或总和再求和
题解 根据上述图可以根据二进制运算获取所有的子集,但是可以使用二进制获取所有子集需要有题目的这一句话才能够使用注意:在本题中,元素相同的不同子集应多次计数。 也就是对于{2,2,3,4,5}的子集不会简化成{2,3,4,5} public static int sub…...
蓝桥云客---蓝桥速算
3.蓝桥速算【算法赛】 - 蓝桥云课 问题描述 蓝桥杯大赛最近新增了一项娱乐比赛——口算大赛,目的是测试选手的口算能力。 比赛规则如下: 初始给定一个长度为 N 的数组 A,其中第 i 个数字为 Ai。随后数组会被隐藏,并进行 Q 次…...
Kafka 概念
🌀 Kafka 是什么? Kafka 是一个分布式流处理平台,可以用来: 🚚 高效地收集、传输、存储、处理 实时数据流。 它最初由 LinkedIn 开发,用于解决海量日志处理的问题,后来开源给 Apache࿰…...
双向链表增删改查的模拟实现
本章目标 0.双向链表的基本结构 1.双向链表的初始化 2.头插尾插 3.头删尾删 4.查找与打印 5.在指定位置之前插入数据/在指定位置之后插入数据 6.在指定位置之前删除数据/在指定位置之后删除数据 7.销毁链表 0.双向链表的基本结构 本章所实现的双向链表是双向循环带头链表,是…...
配置ASP.NET Core+NLog配置日志示例
以下是一个精简且实用的 NLog 配置文件示例,适用于 ASP.NET Core 项目,包含文件日志、控制台日志和自动归档功能: NLog.config 示例 (保存到项目根目录) xml Copy Code <?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http:…...
Roo Code使用MCP服务(大模型上下文协议)
MCP概念火爆,但是理解起来有点难度,使用起来也有点难度。 启用MCP RooCode直接支持使用MCP服务,甚至可以帮助写MCP,为我们提供了很大的方便。单击 Roo Code 窗格顶部导航栏中的类似三个插座的图标,显示如下MCP的配置…...
【项目管理】第一部分 信息技术 1/2
相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 概要 知识点: 现代化基础设施、数字经济、工业互联网、车联网、智能制造、智慧城市、数字政府、5G、常用数据库类型、数据仓库、信息安全、网络安全态势感知、物联网、大数…...
《UNIX网络编程卷1:套接字联网API》第6章 IO复用:select和poll函数
《UNIX网络编程卷1:套接字联网API》第6章 I/O复用:select和poll函数 6.1 I/O复用的核心价值与适用场景 I/O复用是高并发网络编程的基石,允许单个进程/线程同时监控多个文件描述符(套接字)的状态变化,从而高…...
Three.js 系列专题 1:入门与基础
什么是 Three.js? Three.js 是一个基于 WebGL 的 JavaScript 库,它简化了 3D 图形编程,让开发者无需深入了解底层 WebGL API 就能创建复杂的 3D 场景。它广泛应用于网页游戏、可视化、虚拟现实等领域。 学习目标 理解 Three.js 的核心组件:场景(Scene)、相机(Camera)…...
Qt框架深度解析:核心技术、应用场景与实战指南
Qt(发音同“cute”)是一个跨平台的C应用程序开发框架,广泛用于开发图形用户界面(GUI)程序,但也支持非GUI的后台服务、命令行工具等。它由挪威的Trolltech公司于1995年推出,后由诺基亚、Digia等公…...
低代码开发平台:飞帆中的控件中转区
低代码开发平台:飞帆中的控件中转区的作用 当控件因为尺寸太大难以拖到 div 框中时,可以先拖到控件中转区中,此时控件会变成一个标签,然后将这个标签拖到 div 框中即可。 飞帆 fvi.cn...
基于STM32的智能门禁系统设计与实现
一、项目背景与功能概述 在物联网技术快速发展的今天,传统门锁正在向智能化方向演进。本系统基于STM32F103C8T6微控制器,整合多种外设模块,实现了一个具备以下核心功能的智能门禁系统: 密码输入与验证(4x3矩阵键盘&a…...
maven项目打包jar给其他项目pom外部引用
maven项目打包jar给其他项目pom外部引用 在现实开发过程中,很多代码需要被重复利用的,但是代码量又是很多,这样的代码可以提出出来作为公共代码或者叫做工具使用,通常这样的工具会以jar包的形式被其他项目pom引入使用。第一步 创…...
Linux线程
一、线程的使用 线程创建 函数原型及头文件 #include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); 参数: tidp:当pthread_create成功…...