最大的公告来自对 WordPress.org 主题和插件生态系统的外部威胁。这个威胁就是 FAIR 软件包管理器——一个由 WordPress 长期贡献者发起、Linux 基金会支持的项目。
那么,让我们来聊聊 FAIR 究竟是什么,它目前的样子,以及更重要的是,你应该使用它吗?最后,我们再来看看 WordPress 联合创始人 Matt Mullenweg 对此的看法。
FAIR 这个缩写并非巧合,它的完整名称——“可信插件和主题的联合独立存储库”——也并非巧合。它是对去年 #wpdrama事件后果的直接回应,尤其是 10 月份Automattic 在生态系统中控制了 WP Engine 的 ACF 插件 slug事件。
正如企业机构 Crowd Favorite 首席执行官兼该项目发起人之一 Karim Marucchi 所解释的那样:
我清楚地记得那些电话。来自不同大企业的多位首席法律顾问在电话里直截了当地问我:‘Karim,如果一个人可以单方面做出危及我们供应链的改变,而且没有任何明显的制衡措施,我们为什么要信任 WordPress?’ ”
卡里姆并非唯一一个听到有人担忧开源 WordPress 项目“治理问题”的人。还有很多人呼吁建立一个公平、不集权的替代方案。
因此,FAIR 诞生了——联合且独立——或者换句话说,非集中式。
该项目历经六个月的合作,由来自十多个组织的一百多位贡献者共同完成。为了确保治理的中立性,该团队与Linux基金会进行了接洽。该组织也负责监管Linux和Kubernetes等重要的开源项目。此外,三位德高望重的WordPress资深人士被任命领导技术指导委员会:Carrie Dils、Mika Epstein和Ryan McCue(WordPress REST API的创建者)。
如果 FAIR 最终被广泛采用,它可能会挑战 Automattic 首席执行官 Matt Mullenweg 自 WordPress 创立以来对它的控制。因此,WordPress 社区的许多人将此视为 WordPress 历史时间线上的一个潜在分叉。
尽管如此——这一点需要强调——从技术角度来看,FAIR 并非 WordPress 的分支。它仍然是 100% 的 WordPress。它只是消除了对 WordPress.org 插件和主题的依赖。FAIR 的意义远不止于此,但这才是重点。
WordPress 切换到 FAIR 的两个选项
截至撰写本文时,WordPress 可通过两种方式使用 FAIR:
作为一个完整的 WordPress 安装,捆绑了 FAIR 插件(预安装)
WordPress 完整安装主要面向为新客户提供 WordPress 安装选项的托管公司。大多数现有 WordPress 网站的用户可以像其他插件一样直接下载并安装该插件。
要尝试 FAIR 插件,您需要做的第一件事就是前往其GitHub 发布页面并下载它:
然后,在 WordPress 仪表盘中,前往插件→添加插件→选择文件。在硬盘上找到fair-plugin-0.2.0.zip (请直接使用最新版本)。然后点击立即安装,然后点击激活插件:
成功激活插件后,您会注意到左侧边栏中有一个新的 FAIR 设置菜单选项:
目前实际上只有一个功能——可以覆盖强制使用 Gravatar设置用户头像的默认设置。该功能默认启用(标题为“FAIR Avatars”)。但是,如果您出于某种原因更喜欢使用 Gravatar,可以随时恢复使用。
除此之外,您还会注意到屏幕右下角有一条微妙但重要的信息:Updates served from the FAIR Package Manager and AspirePress.
相同的消息将显示在 WordPress 管理仪表板的其他区域 – 例如插件和主题页面。
这只是让您知道 FAIR 正在运行,并且您主题和插件的任何未来更新都不会来自 WordPress.org。而是来自 FAIR 和 AspirePress。
如果你好奇的话,AspirePress 是另一个与 FAIR 有着相似目标和价值观的开源项目。根据一位直接参与 FAIR 构建的人在 Reddit 上的帖子,Aspire 团队也参与了这个过程。在 FAIR 发布他们的插件的第二天,Aspire 也发布了他们自己的类似插件。所以看起来这两个项目正在协同工作。
如果你不是开发人员或 WordPress 高级用户,你可能会想——我为什么要安装这个?这是一个合理的问题。
对于普通用户来说,选择采用 FAIR 更多的是出于意识形态而非实用性考虑。该插件不会显著改变您日常使用 WordPress 的方式。但是,如果您关心 WordPress,并且相信转向更去中心化的系统是有益的,那么安装该插件来表达您的支持并不会损害您的网站。
对于开发者来说,激励机制会更加强大,因为它们会以积极的方式影响插件的分发。这是因为 FAIR 允许开发者将免费版和付费版插件捆绑到一个加密签名的软件包中。这可以简化用户体验,并创造新的商业模式。
对于企业和托管公司而言,FAIR 解决了供应链安全、法规遵从性和风险管理等关键业务问题:
组织可以在防火墙后运行 FAIR,从而完全控制可访问的插件和主题。
FAIR 与 GDPR 以及《网络弹性法案》等即将出台的法规更加一致。
它减少了关键业务基础设施中的单点故障。
该系统还引入了代码签名和改进的加密安全措施。这些都是企业客户一直要求的附加功能。
这一切听起来很美好,但也有一些反面观点需要考虑。WordPress 联合创始人马特·穆伦维格 (Matt Mullenweg) 在 WordCamp Europe 的演讲中迅速指出了这些反面观点。
FAIR 发布仅几小时后,Matt Mullenweg 与 WordPress 执行董事 Mary Hubbard 进行了“炉边谈话”,并直接被问及与该项目的潜在合作。他的回答既展现了外交上的开放态度,也体现了重大的技术担忧。
“当然,我们会考虑所有因素,”穆伦维格说,“但即使如你所说,我认为也存在很多挑战。”
安全性:虽然 FAIR 旨在提高安全性,但穆伦维格认为这可能会带来新的漏洞。“目前,供应链攻击需要攻破 WordPress.org,而该网站从未被黑客入侵过,”他指出。“但现在突然之间,就有 N 个地方可能被攻破。”
运营复杂性:他强调的挑战包括多个镜像可能存在正常运行时间问题、难以实施分阶段推出(例如首先与 5% 的用户测试更新)以及失去为 PHP 版本和数据库支持决策提供信息的集中式分析。
信任和质量控制:Mullenweg 认为,用户不一定要求提供更多的下载位置,而是要求提供信任指标:“我怎么知道这是值得信赖的?我怎么知道这些评论是真实的?谁在审核?谁在检查这些不同评论的 IP?插件评级是多少?兼容性如何?”
执行问题:他质疑如何在分布式系统中执行现有政策,例如对管理员横幅的限制。
尽管如此,穆伦维格也承认了积极的一面:“我认为大家能够互相传递代码,而不是仅仅争论、聊天或写博客文章,这真是太棒了。”他进一步强调,在做出任何合作承诺之前,他希望先审查代码,并仔细考虑了该项目可能采取的方向。
在我看来,考虑到他处理公告的时间很短,我觉得这是一个很好的回应。他提出的观点也很合理——虽然是双关语。
FAIR 项目是自该平台创建以来对 WordPress 基础设施进行去中心化最重要的尝试,其影响可能是深远的。
它能否获得广泛采用还有待观察。然而,它的存在本身——由Linux基金会支持,并由受人尊敬的社区人物开发——标志着生态系统对治理、控制以及支撑43.5%网络的平台未来发展的看法发生了转变。
Mullenweg 提出的技术挑战也是切实存在的,并非仅仅是一些转折点。他们需要解决方案。另一方面,促使 FAIR 成立的治理和供应链安全问题也同样重要。这些相互竞争的优先事项如何相互影响,很可能决定 WordPress 未来十年的未来。
你觉得 FAIR 怎么样?你会在你的 WordPress 网站上安装这个插件吗?
]]>大型语言模型 (LLM)越来越依赖网站信息,但面临一个关键的限制:上下文窗口太小,无法完整处理大多数网站。将包含导航、广告和 JavaScript 的复杂 HTML 页面转换为 LLM 友好的纯文本既困难又不精确。
虽然网站既服务于人类读者,也服务于大型语言模型 (LLM),但后者受益于更简洁、更专业的信息,这些信息集中在一个易于访问的单一位置。这对于开发环境等用例尤为重要,因为LLM 需要快速访问编程文档和 API。
为了解决以上问题,LLMs.txt 应运而生!
LLMs.txt 是一种专为大型语言模型(LLMs)设计的网站标准化文件,旨在帮助 AI 更高效、准确地理解和索引网站内容。其核心特点与作用如下:
一、本质与定位
AI 专用索引文件
类似 sitemap.xml 的站点地图功能,但专注于服务 AI 模型,而非搜索引擎爬虫。它提供网站内容的精简结构化索引,通常以 Markdown 格式存储于网站根目录(如 https://example.com/llms.txt)。
与传统文件的区别
VS robots.txt:后者控制爬虫访问权限,而 LLMs.txt 提供内容导航与语义说明,不限制访问。
VS sitemap.xml:LLMs.txt 包含内容摘要、分类标签及更新状态等上下文信息,而非仅页面链接。
二、核心功能
提升 AI 理解效率
通过剥离网页中的 HTML/CSS/JavaScript 等视觉渲染元素,直接提供纯文本核心内容,减少信息噪音与 Token 消耗,加速 AI 处理响应。
结构化内容导航
为 LLM 标注关键页面属性(如用途、分类、重要度),引导模型优先抓取高价值内容(如 API 文档、最新公告)。
支持 Markdown 版本访问
网站可为每个页面提供 Markdown 版本(例如在原始 URL 后追加 .md),供 AI 直接解析纯净文本。
三、典型应用场景
版权与合规声明:部分实现方案允许声明内容使用权限,规范 AI 模型的数据抓取行为
AI 问答优化:当用户向 ChatGPT、Claude 等询问网站信息时,LLMs.txt 帮助模型快速定位准确答案,避免因网页噪音导致错误。
开发者文档适配:如 Apifox、VitePress 等技术平台通过集成 LLMs.txt,显著提升 AI 对 API 文档的解析精度。
LLMs.txt 对 传统搜索引擎优化(SEO)没有直接影响,但可能通过间接方式影响网站在 AI 搜索环境中的表现,具体分析如下:
谷歌搜索倡导者 John Mueller 将 LLMs.txt 类比为已废弃的“关键词元标签”(keywords meta tag),强调其不被搜索引擎用作排名信号,且存在滥用风险。
与搜索引擎爬虫无关
LLMs.txt 专为大型语言模型(如 ChatGPT、Gemini)设计,不控制搜索引擎爬虫的访问权限或索引行为,传统 SEO 规则(如关键词密度、反向链接)仍独立生效。
通过为 LLM 提供结构化内容摘要,可优化网站在 AI 问答中的引用准确性(例如 ChatGPT 回答用户问题时更易调取正确信息),间接扩大内容触达范围。
剥离广告、导航等噪音的 Markdown 格式能避免 AI 因抓取冗余内容导致错误解读,尤其对技术文档(如 API 说明)、实时资讯类站点效果显著。
标注页面优先级与分类标签(如 #安全 #必备),可引导 LLM 优先抓取高价值内容,突破上下文长度限制,尤其利于大型网站。
无需替代传统 SEO 工作:LLMs.txt 应视为补充而非替代,需同步维护 robots.txt 和 sitemap.xml。
技术文档站点建议部署:API 服务商(如 Apifox)、开源项目(如 Vue/Vite)可通过 LLMs.txt 显著提升 AI 助手解析效率。
避免滥用风险:堆砌无关关键词或操纵 AI 行为可能降低内容可信度,需遵循简洁、真实原则。
总结:LLMs.txt 当前对 Google 等传统搜索引擎的 SEO 排名无影响,但能增强内容在 AI 生态中的可见性与准确性,是面向未来搜索场景的策略性补充。
WordPress 网站要生成 LLMs.txt 非常简单,只需要安装相关的插件即可,比如 Website LLMs.txt 或 LLMs.txt and LLMs-Full.txt Generator 都是不错的插件,二选一安装使用即可,如果你有使用 Yoast SEO 插件,貌似它已经集成了这个功能,就不需要借助其他插件了。
]]>访问 外观 – 自定义 界面的时候,看到错误提示 Non-existent changeset UUID,如下图所示:
说真的,倡萌也是第一次看到这个错误,搜索了一下,原来问题出在 设置 – 常规 中设置的两个网址不一致导致的:
解决办法就是将这两个网址修改为一样的就好了!
目前 RFC 标准里规定的状态码是三位数,所以取值范围就是从 000 到 999。但如果把代码简单地从 000 开始顺序编下去就显得有点太“low”,不灵活、不利于扩展,所以状态码也被设计成有一定的格式。
RFC 标准把状态码分成了五类,用数字的第一位表示分类,而 0~99 不用,这样状态码的实际可用范围就大大缩小了,由 000~999 变成了 100~599。
这五类的具体含义是:
1××:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;
2××:成功,报文已经收到并被正确处理;
3××:重定向,资源位置发生变动,需要客户端重新发送请求;
4××:客户端错误,请求报文有误,服务器无法处理;
5××:服务器错误,服务器在处理请求时内部发生了错误。
在 HTTP 协议中,正确理解和应用状态码并非客户端或服务器一方的单方面责任,而是双方共同的责任。
客户端作为请求的发起者,接收服务器返回的响应报文后,需要通过状态码来判断请求是否被正确处理。如果请求成功,客户端可以继续后续操作;如果请求失败,则需要根据状态码的具体含义,判断是否需要再次发送请求,或进行相应的错误处理。例如,如果状态码为 404,则表示请求的资源不存在,客户端需要重新检查请求地址或采取其他措施。
服务器端作为请求的接收者,也应该合理运用状态码,向客户端清晰地传达处理结果,并指示客户端下一步应该采取的行动。在处理请求时,服务器应该选择最恰当的状态码来回复客户端,避免使用过于笼统的状态码,例如 400 或 500,这些状态码的含义过于模糊,无法为客户端提供足够的信息。
1xx 类状态码属于提示信息,协议处理的中间状态
101(切换协议):请求者已要求服务器切换协议,服务器已确认并准备切换。它的意思是客户端使用 Upgrade 头字段,要求在 HTTP 协议的基础上改成其他的协议继续通信,比如 WebSocket。而如果服务器也同意变更协议,就会发生状态码 101,但这之后的数据传输就不会再使用 HTTP 了。
2xx类表示服务器成功处理了客户端的请求
200(成功) : 最常见的成功状态码,表示一切正常,服务器如客户端所期待的返回了处理结果,如果不是 HEAD 请求,通常在响应头后都会有 body 数据
201(已创建):请求成功并且服务器创建了新的资源
202(已接受):服务器已接受请求,但尚未处理
203(非授权信息):服务器已经成功处理了请求,但返回的信息可能来自于另一个来源
204(无内容):另一个常见的成功状态码,服务器成功处理了请求,但没有返回任何内容,也就是响应头后没有 body 数据
206(部分内容):服务器成功处理了部分 GET 请求,服务器返回的 body 数据是资源的一部分
3xx类 状态码表示客户端请求的资源的路径发生了转变,需要客户端用新的 URL 来获取资源,也就是重定向
301(永久重定向):请求的资源已经永久移动到了新的位置。值得注意的是严格来讲这种重定向并不是服务器跳转,而是客户端跳转,“跳”的动作实际上客户端根据服务器返回的状态码 301 后完成跳转的
302(临时重定向):说明请求路径的资源还在,但暂时需要另一个 URL 来访问
304(未修改):说明自从上次请求后,请求的网页未修改过,服务器返回此响应时,不会返回网页内容,而是重定向到客户端本地浏览器的缓存资源中
重定向301 和 302 的区别?
重定向301是永久重定向,客户端收到301状态码后,会记忆重定向后的新URL,这样下一次访问的时候,就不会再访问旧的URL,而是直接访问新的URL
重定向302是临时重定向,客户端收到302状态码后,不会记录重定向后的新URL,这样下一次访问的时候,还需要访问旧的URL,再重定向到新URL
4xx类 转态码表示客户端发送的请求报文错误
400(错误请求):表示请求报文错误,但具体是数据格式错误、请求头缺少还是 URI 长度过大没有明确说,只是一个笼统的错误,客户端看到 400 只会是“一头雾水”
401(未授权):请求要求身份验证,对于需要登录的网页,服务器可能返回此响应
403(禁止):服务器拒绝请求,没有权限去访问服务器的资源或者请求的 IP 地址被封掉了
404(未找到)代表服务器上没有该资源,或者说服务器找不到客户端请求的资源,是最常见的请求错误码
5xx类 状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码
500(服务器内部错误):代表服务器程序错误,也就是说请求的网页程序本身报错了。在服务器端的网页程序出错。由于现在的浏览器都会对 500 做一定的处理,所以在一般情况下会返回一个定制的错误页面
501(尚未实施):服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码
502(错误网关):通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误
503(服务不可用):表示服务器当前无法使用(超载或者停机维护),我们上网时遇到的“网络服务正忙,请稍后重试”的提示信息就是状态码 503
504(网关超时):服务器作为网关或者代理,但是没有及时从上游服务器收到请求。
]]>2025年7月24日,现代化、开源的Linux服务器运维管理面板1Panel正式发布v2.0.5版本。在这一版本中,1Panel新增数据库集群部署、邮件告警和主从节点灵活切换三项功能,聚焦为企业级运维场景提供更优使用体验。
1Panel v2.0.5版本是1Panel开源面板项目在交付企业级集群化和高可用能力方面迈出的关键一步,也是对社区用户长期支持与反馈的回应。从单机到多节点,从单实例数据库到数据库集群,从单一告警到邮件短信双通道,1Panel正在努力成为“可用、好用、值得信赖”的下一代Linux服务器运维面板。
数据库是数字化业务的核心。针对用户的集群化部署需求,1Panel v2.0.5版本在原有的数据库一键部署的基础之上,新增了MySQL、PostgreSQL和Redis的集群部署功能。
MySQL、PostgreSQL和Redis集群部署的功能优势主要体现在以下三方面:
更加重要的是,无需借助繁琐的命令行,用户仍然可以通过可视化的“傻瓜式”操作来进行MySQL、PostgreSQL和Redis的集群安装部署,从而大幅降低搭建高可用数据库集群的技术门槛。
在系统运行中,可靠的告警机制对及时发现系统风险尤为关键。1Panel v2.0.5版本在原有短信告警的基础上,新增了邮件告警功能。
现在,1Panel能够同时通过邮件和短信双通道,将告警信息第一时间推送给系统运维人员。相比单一通道,双通道告警能够覆盖更多场景,保障告警信息触达用户的即时性,为用户构建更为完善的监控闭环。
在分布式和多节点管理场景下,如何在主节点发生故障时快速切换节点,保障业务的正常可用,一直是高可用系统运维的核心。本次更新后,1Panel正式支持主从节点切换模式。运维人员可以根据需要,将某个从节点升级为主节点,或将主节点降级为从节点重新加入集群。
主从节点切换为用户带来的价值包括:
MinerU是一款开源的高质量数据提取工具,能够将PDF文档转换为Markdown和JSON格式。2025年6月13日,MinerU发布了v2.0版本,相较于v1.0版本实现了架构和功能的全面重构与升级。在优化代码结构和交互方式的同时,v2.0版本还集成了小参数量、高性能多模态文档解析模型,能够实现端到端的高速、高精度文档理解。实际测试表明,新版本对复杂图表的解析效果较上一版本有明显提升,目前已经能够满足90%以上的复杂文档解析需求。
值得一提的是,MinerU出色的PDF文档解析能力特别适合与MaxKB开源项目配合使用。通过"MinerU+MaxKB"的组合方案,用户不仅能够获得高质量的文档解析效果,还能显著提升知识库问答系统的性能。为方便用户集成,MinerU项目现已提供API对接服务(https://mineru.net/apiManage)。接下来,本文将详细介绍如何通过MinerU在线API实现与MaxKB的对接。
当用户提供文件地址后,系统会将该地址赋值给file_url变量,并作为参数传递给MinerU文件解析服务。MinerU在完成文件解析后,会返回一个任务ID(task_id)。系统会将其传入MinerU的查询接口,当检测到任务处理完成时,自动获取结果文件的下载链接(full_url)。随后,系统执行文件下载操作,将结果文件保存到MaxKB容器的/opt/maxkb/download目录下。最后,系统会自动完成文件上传和智能分段处理,将内容存储到知识库中。
我们需要在MaxKB的函数库中创建四个核心功能函数,其用途分别为:
■ MinerU单个文件解析函数:负责调用MinerU的单文件解析服务,通过传入PDF文档的在线地址来创建解析任务,并返回对应的task_id;
import requests
def create_task(file_url):
url = 'https://mineru.net/api/v4/extract/task'
token = '自己申请的 Token'
header = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
data = {
'url': file_url,
'is_ocr': True, #是否启动 ocr 功能,默认 false
'enable_formula': True, #是否开启公式识别,默认 true
'enable_table': True, #是否开启表格识别,默认 true
'language': "ch", #指定文档语言,默认 ch,可以设置为auto
'model_version': "v2", #mineru模型版本,两个选项:v1、v2,默认v1。
}
res = requests.post(url,headers=header,json=data,timeout=5)
res_data = res.json()
task_id_data = res_data["data"]["task_id"]
return task_id_data
■ MinerU获取任务结果函数:用于查询任务状态,通过传入task_id获取解析结果,成功后将返回ZIP格式解析文件的下载地址;
import time
import requests
def querybyid(task_id,max_retries=100,retry_interval=5):
url = f'https://mineru.net/api/v4/extract/task/{task_id}'
token = '申请的Token'
header = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
}
retries = 0
while retries < max_retries:
try:
res = requests.get(url, headers=header, timeout=5)
res.raise_for_status() # 检查请求是否成功
data = res.json()
if "data" in data and "full_zip_url" in data["data"] and data["data"]["full_zip_url"]:
return data["data"]["full_zip_url"]
else:
print(f"full_zip_url 为空,正在等待任务完成。已重试 {retries + 1} 次,共 {max_retries} 次。")
time.sleep(retry_interval)
retries += 1
except requests.exceptions.RequestException as e:
print(f"请求失败,错误信息:{e}。正在重试...")
time.sleep(retry_interval)
retries += 1
raise Exception(f"在 {max_retries} 次重试后,仍未获取到有效的 full_zip_url。")
■ 文件下载函数:根据提供的ZIP文件下载链接,将文件保存至容器内的/opt/maxkb/download目录。需要注意的是,MaxKB默认使用sandbox用户运行,需确保该用户对/opt/maxkb/download目录有读写权限;
import os
import requests
from urllib.parse import urlparse
def download_file(download_url, save_dir='/opt/maxkb/download'):
os.makedirs(save_dir, exist_ok=True)
# 获取文件名
parsed_url = urlparse(download_url)
filename = os.path.basename(parsed_url.path)
save_path = os.path.join(save_dir, filename) # 文件下载后保存的目录,需要默认用户对此目录有读写权限
# 下载文件
try:
response = requests.get(download_url, stream=True)
response.raise_for_status() # 检查请求是否成功
total_size = int(response.headers.get('content-length', 0))
block_size = 1024 # 1KB
progress = 0
print(f"开始下载 {filename} 到 {save_dir}")
with open(save_path, 'wb') as f:
for data in response.iter_content(block_size):
f.write(data)
progress += len(data)
# 打印下载进度
print(f"下载进度: {progress / total_size * 100:.2f}%", end='\r')
print(f"\n下载完成: {save_path}")
return save_path
except requests.exceptions.RequestException as e:
print(f"下载失败: {e}")
return None
■ ZIP文件上传至知识库:通过MaxKB API将服务器上的ZIP解析文件上传至知识库存储。
import json
import logging
import requests
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def initialize(file_path):
config = {
# MaxKB API密钥
'authorization_apikey': 'user-ac86ec515de17969f2f8a9c8ab21e52f',
# 文件分段处理的API地址
'split_url': 'http://10.1.11.58:8080/api/dataset/document/split',
# 目标知识库的API地址
'upload_url': 'http://10.1.11.58:8080/api/dataset/3d1d5d4e-5576-11f0-bc5c-0242ac120003/document/_bach',
'file_path': rf'{file_path}',
'file_name': '函数库上传文档分段'
}
return config
def upload_file(config):
headers = {
'accept': 'application/json',
'AUTHORIZATION': f'{config["authorization_apikey"]}'
}
try:
files = {'file': open(config["file_path"], 'rb')}
response = requests.post(config["split_url"], headers=headers, files=files)
response.raise_for_status()
response_data = response.json()
map_content = {}
for item in response_data.get("data", []):
for content_item in item.get("content", []):
map_content[content_item.get("title", "")] = content_item.get("content", "")
return map_content
except requests.exceptions.RequestException as e:
logging.error(f"文件分段上传失败: {e}")
return {}
except Exception as e:
logging.error(f"处理文件内容时出错: {e}")
return {}
def send_post_request(config, map_content):
headers = {
"Content-Type": "application/json",
"Authorization": f'{config["authorization_apikey"]}'
}
paragraphs = [{"title": key, "content": value} for key, value in map_content.items()]
document_wrapper = {
"name": config["file_name"],
"paragraphs": paragraphs
}
json_body = json.dumps([document_wrapper])
try:
response = requests.post(config["upload_url"], headers=headers, data=json_body)
response.raise_for_status()
logging.info(f"上传文件响应: {response.text}")
return True
except requests.exceptions.RequestException as e:
logging.error(f"上传文件失败: {e}")
return False
def main(file_path):
config = initialize(file_path)
map_content = upload_file(config)
if not map_content:
logging.error("文件分段上传失败或内容为空,程序终止")
return False
if not send_post_request(config, map_content):
logging.error("文件上传失败,程序终止")
return False
return "文件已上传成功,并保持在知识库中"
在上述四个函数创建完成后,我们可以在MaxKB中尝试创建高级应用。输入或提取上传文件的链接后,按照前文顺序依次添加MinerU单个文件解析函数节点→从MinerU获取任务结果函数节点→下载文件函数节点→文件上传函数节点。
小助手提示“文件上传成功”,即可回到知识库页面,在目标知识库中看到新上传的文档。
总结来说,MinerU v2.0是一款开源、高性能的PDF文档解析工具,具备强大的多模态处理能力。通过MaxKB与MinerU的深度联动,可以基于函数调用构建清晰高效的 “文件地址→解析→下载→上传” 自动化流程,无缝衔接原始文档与结构化知识库的构建。
“MinerU+MaxKB”的组合方案,不仅可以显著提升文档解析的精度与效率,更能大幅增强知识库问答系统的能力与效果。
]]>今天我要从腾讯网上弄个视频,放在 PPT 中讲课使用,我最先想到的方式是把链接放 PPT 文档中,讲课时点击链接打开即可,可我在试讲的时候,发现每次点击链接打开视频都要播放一段 30 秒的广告,不是会员不能跳过,然后页面还充斥着很多广告;其次,如果到时候讲课的环境没有网络的话,不就无法演示了吗?
想到这里,我觉得还是要把视频下载下来比较好,放在本地,可以直接插入到 PPT 中,然后我就想怎么才能下载下来,首先就是在页面鼠标右键,去看页面代码查找,发现没找到;然后就是去找猴油脚本,又遇到墙的问题;最后不得已下载了腾讯的客户端,一顿操作终于下载了,然后又卸载了腾讯视频客户端。为了一个视频折腾一顿,真心没必要,有没有简单好用的方法呢?
经过多次测试比较,我发现了这个,还是很实用的,后面我打算做个视频教程。
在电脑本地建立一个 HTML 格式文件,复制下面代码到文件里,双击打开文件,按页面提示操作即可。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta author="kevy tian">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<title> 腾讯视频下载 </title>
<style>
#res {
display: inline-block;
width: 500px;
height: 30px;
font-size: 14px;
line-height: 30px;
padding: 0;
}
.container {padding-top: 50px;}
#isVid {
display: inline-block;
width: 120px;
height: 30px;
font-size: 14px;
line-height: 30px;
}
#download {
display: inline-block;
width: 100px;
height: 30px;
font-size: 14px;
line-height: 25px;
text-align: center;
padding: 0;
margin-bottom: 4px;
}
</style>
</head>
<body>
<div class="container">
<p> 首先在视频上 <b> 点击播放视频 --> 鼠标右键 --> 视频信息 --> 复制 --> 粘贴到文本编辑器 --> 复制 vid 前半部分 </b>,然后将复制的 vid 粘贴到下方输入框:</p>
<div>
<select id="isVid" disabled>
<option style="display:none" value="1"> 视频页面地址 </option>
<option value="2" selected> 视频 vid</option>
</select>
<input id="res" type="text" placeholder="请输入视频 vid"/>
<button id="download" class="btn btn-large btn-primary" type="button"> 获取下载地址 </button>
</div>
<p style="width:100%;padding:20px;word-wrap:break-word;" id="result"></p>
</div>
<script type="text/javascript">
var downloadUrl = "";
var link = "";
var isVid = "";
var vids = "";
$("#download").click(function () {link = $("#res").val();
isVid = $("#isVid").val();
if (isVid == "1") {if (checkUrl(link)) {vids = getVids(link);
process()}
else {alert("视频链接不正确");
}
}
else {
vids = link;
if (vids != "") {process();
}
}
});
function checkUrl(url) {var reg = /(http|ftp|https)://[w-_]+(.[w-_]+)+([w-.,@?^=%&:/~+#]*[w-@?^=%&/~+#])?/;
if (url != ""&& reg.test(url) && url.indexOf("page/") != -1 && url.indexOf(".html") != -1) {return true;}
return false;
}
function getVids(url) {url = url.split(".html")[0].split("/");
return url[url.length - 1];
}
function process() {var bqApi = "http://vv.video.qq.com/getinfo?vids={vids}&platform=101001&charge=0&otype=json&defn=shd";
bqApi = bqApi.replaceAll("{vids}", vids);
var api1Json = {};
$.ajax({
type: "get",
url: bqApi,
dataType: "jsonp",
jsonpCallback: "cb",
success: function (data) {
api1Json = data;
downloadUrl = api1Json.vl.vi[0].ul.ui[0].url + api1Json.vl.vi[0].fn + "?vkey=" + api1Json.vl.vi[0].fvkey;
$("#result").html("<span style='font-weight:bold;font-size:20px;'> 下载方式:</span><br/> 方式一:" + "<a target='_blank'href='" + downloadUrl + "'> 点击此处 </a> 打开视频,在视频上右键另存为保存到本地。<br /> 方式二:如果您的浏览器比较新,直接 <a href='javascript:void(0)'onclick='dw(""+ downloadUrl +"")'> 点击此处 </a> 下载视频。");
}
});
}
function dw(url) {
try{fetch(url).then(res => res.blob().then(blob => {var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "kevy-download";
a.click();
window.URL.revokeObjectURL(url);
}));
}
catch(err){alert("您的浏览器不支持该方式,请使用方式一");
}
}
</script>
</body>
</html>
本人亲测目前仅支持腾讯视频。
]]>彩虹 Kangle 一键脚本,是一款可以一键安装 Kangle+Easypanel+MySQL+PHP 集合的 Linux 脚本。脚本本身集成:PHP5.3~8.2、MYSQL5.6~8.0,支持极速安装和编译安装 2 种模式,支持 CDN 专属安装模式。同时也对 Easypanel 面板进行了大量优化。
有国内和国外 2 个文件下载节点,提升安装速度
自带 Kangle 商业版最新版本免费使用
支持 EP 前台自由切换 PHP5.3-8.2
安装前可选 MySQL5.6、5.7、8.0 版本
预先设置各 PHP 版本 PHP.ini 安全问题
安装前可自定义数据库密码,避免安装完成后再设置的麻烦
支持自定义 403.404.503.504 等错误页面
脚本中可切换其它几套 EP 用户后台模板
脚本中集成 Linux 工具箱,可一键更换 Yum 源、更换 DNS、设置 Swap、同步时间、清理垃圾等
修改 kangle 二进制文件以提升错误页加载速度
0.EP 源码全解密并升级 smarty 框架
1.SSL 证书可同步到 cdn 节点
2.SSL 配置页面新增 ”HTTP 跳转到 HTTPS” 选项
3.SSL 配置页面新增 ” 开启 HTTP2″ 选项
4.CDN 可以给单个域名设置 SSL 证书
CentOS 7(推荐)
CentOS 8
CentOS Stream 8
Rocky Linux 8
AlmaLinux 8
OpenCloudOS 8
CentOS 6(不支持安装 PHP7.4 及以上版本)
请复制以下指令到 ssh 连接软件粘贴执行
yum -y install wget;wget http://kangle.cccyun.cn/start;sh start
]]>
Cloudflare Worker 是 Cloudflare 公司提供的一项服务,它允许开发者在 Cloudflare 的边缘服务器上运行自定义的 JavaScript 代码。通俗地说,它就像是一个小型的服务器,可以在互联网上的不同地点快速执行你编写的代码。
Cloudflare Worker 的主要用途包括网站加速和优化、路由请求、访问控制、CDN 功能增强、网站镜像与转发等。
本文将使用其网站镜像和访问控制的能力,实现 GitHub 站点的镜像,并通过自有域名实现在墙内的访问。
首先,登录 Cloudflare,切换至 Workers & Pages 菜单,点击 创建 按钮:
等待页面刷新,再点击点击 创建 Worker按钮新建一个 Worker:
接着,设置一个三级域名 https://demo.93653142.workers.dev,点击 部署 按钮:
再接着点击 编辑代码 按钮进行代码编辑
最后,粘贴以下代码片段后,右边就可以显示访问后的效果展示,点击 部署 完成部署,然后通过域名 https://demo.93653142.workers.dev/ 访问镜像站:
// 你要镜像的网站.
const upstream = 'github.com'
// 镜像网站的目录,比如你想镜像某个网站的二级目录则填写二级目录的目录名,镜像 google 用不到,默认即可.
const upstream_path = '/'
// 镜像站是否有手机访问专用网址,没有则填一样的.
const upstream_mobile = 'github.com'
// 屏蔽国家和地区.
const blocked_region = ['KP', 'SY', 'PK', 'CU']
// 屏蔽 IP 地址.
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
// 镜像站是否开启 HTTPS.
const https = true
// 文本替换.
const replace_dict = {'$upstream': '$custom_domain', '//github.com': ''}
// 以下保持默认,不要动
addEventListener('fetch', event => {
event.respondWith(fetchAndApply(event.request))
})
async function fetchAndApply(request) {
const region = request.headers.get('cf-ipcountry').toUpperCase()
const ip_address = request.headers.get('cf-connecting-ip')
const user_agent = request.headers.get('user-agent')
let response = null
let url = new URL(request.url)
let url_hostname = url.hostname
if (https == true) {
url.protocol = 'https:'
} else {
url.protocol = 'http:'
}
if (await device_status(user_agent)) {
var upstream_domain = upstream
} else {
var upstream_domain = upstream_mobile
}
url.host = upstream_domain
if (url.pathname == '/') {
url.pathname = upstream_path
} else {
url.pathname = upstream_path + url.pathname
}
if (blocked_region.includes(region)) {
response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
status: 403
})
} else if (blocked_ip_address.includes(ip_address)) {
response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
status: 403
})
} else {
let method = request.method
let request_headers = request.headers
let new_request_headers = new Headers(request_headers)
new_request_headers.set('Host', url.hostname)
new_request_headers.set('Referer', url.hostname)
let original_response = await fetch(url.href, {
method: method,
headers: new_request_headers
})
let original_response_clone = original_response.clone()
let original_text = null
let response_headers = original_response.headers
let new_response_headers = new Headers(response_headers)
let status = original_response.status
new_response_headers.set('access-control-allow-origin', '*')
new_response_headers.set('access-control-allow-credentials', true)
new_response_headers.delete('content-security-policy')
new_response_headers.delete('content-security-policy-report-only')
new_response_headers.delete('clear-site-data')
const content_type = new_response_headers.get('content-type')
if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
original_text = await replace_response_text(original_response_clone, upstream_domain, url_hostname)
} else {
original_text = original_response_clone.body
}
response = new Response(original_text, {
status,
headers: new_response_headers
})
}
return response
}
async function replace_response_text(response, upstream_domain, host_name) {
let text = await response.text()
var i, j
for (i in replace_dict) {
j = replace_dict[i]
if (i == '$upstream') {
i = upstream_domain
} else if (i == '$custom_domain') {
i = host_name
}
if (j == '$upstream') {
j = upstream_domain
} else if (j == '$custom_domain') {
j = host_name
}
let re = new RegExp(i, 'g')
text = text.replace(re, j)
}
return text
}
async function device_status(user_agent_info) {
var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]
var flag = true
for (var v = 0; v < agents.length; v++) {
if (user_agent_info.indexOf(agents[v]) > 0) {
flag = false
break
}
}
return flag
}
至此,镜像 GitHub 站点已完成,我们任意搜索一个 layui 的开源库,搜索结果如下图图所示。但是由于国内 workers.dev 域名的 DNS 已污染导致无法访问,所以需要绑定一个自定义域名来绕过该问题。
先返回上一次,找到对应的 名称 点击 设置,添加自定义域 添加一个自定义域名:
最后,等待 DNS 解析生效,然后使用 添加的自定义域名进行访问
]]>Telegraph 简介
Telegraph 是一个免费开源的平台,通过它可以创建和共享图像、视频与文本。
Cloudflare 简介
Cloudflare 是一家全球 CDN 和安全提供商,可以提高网站的性能和安全性。
网站、博客和电商平台等,图片是必不可少的元素。当然图片需要存储空间和带宽来支持。对于流量小的站点来说,这还好。但如果是大流量的站点,将产生一些额外的存储和带宽费用,不太划算。针对这种情况,我们往往可以采取外链图片的方式。
但是,外链图片会占用大量的带宽和服务器资源。因此,大部分站点只供站内观看,不允许外链。而一般可外链图片的站点会给免费用户提供比较少的月流量,使用比较受限,只有成为付费用户之后才能提升外链流量。当然,也有网站专门提供免费外链图片服务。此类网站通常称之为图床,不限流量。
自建图床的常用方式有阿里云 OSS、GitHub、Google Drive 等。本文并不使用这些常用的自建图床方式,而是使用 Telegraph 和 Cloudflare 来自建图床。
本文将使用其网站镜像和访问控制的能力,实现 GitHub 站点的镜像,并通过自有域名实现在墙内的访问。
访问 Telegraph-Image 仓库地址,fork 到个人仓库:
在 Cloudflare 创建一个应用:
点击 保存并部署 随后开始安装
等待安装完成后,可通过 Cloudflare 自动分配的域名访问,。
或点击 添加自定义域 绑定自定义域名
完成绑定后,可通过绑定的自定义域名进行或自动分配的域名访问,页面如下图:
因为使用 Cloudflare 的网络,图片的加载速度在某些地区可能得不到保证