<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss-style.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:version="2.0"><channel><title>RyuChan</title><description>🌸 轻盈、优雅、纯净 —— 用文字与图片记录生活与创意 feedId:172229198194932736+userId:166528077360436224</description><link>https://hub.xiaozhangya.xin/</link><language>zh</language><item><title>To The Infinite Castle</title><link>https://hub.xiaozhangya.xin/blog/infinite_castle/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/infinite_castle/</guid><description>柱集结，决战无限城！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/infinite_castle/&quot;&gt;https://hub.xiaozhangya.xin/blog/infinite_castle/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;坠入无限城&lt;/h1&gt;
&lt;div style=&quot;width:100%;max-width:1200px;margin:auto&quot;&gt;
  &lt;div style=&quot;position:relative;padding-bottom:70%&quot;&gt;
    &lt;iframe
      src=&quot;https://picbed.xiaozhangya.xin/ToTheInfiniteCastle.mp4&quot;
      style=&quot;position:absolute;top:0;left:0;width:100%;height:100%;border:none&quot;
      allowfullscreen
      loading=&quot;lazy&quot;
    &gt;&lt;/iframe&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/br&gt;

&lt;h1&gt;我妻善逸&lt;/h1&gt;
&lt;div style=&quot;width:100%;max-width:1200px;margin:auto&quot;&gt;
  &lt;div style=&quot;position:relative;padding-bottom:70%&quot;&gt;
    &lt;iframe
      src=&quot;https://picbed.xiaozhangya.xin/woqishanyi.mp4&quot;
      style=&quot;position:absolute;top:0;left:0;width:100%;height:100%;border:none&quot;
      allowfullscreen
      loading=&quot;lazy&quot;
    &gt;&lt;/iframe&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/br&gt;

&lt;h1&gt;无限城第一章落幕&lt;/h1&gt;
&lt;div style=&quot;width:100%;max-width:1200px;margin:auto&quot;&gt;
  &lt;div style=&quot;position:relative;padding-bottom:70%&quot;&gt;
    &lt;iframe
      src=&quot;https://picbed.xiaozhangya.xin/EndOfInfiniteCastlePart1.mp4&quot;
      style=&quot;position:absolute;top:0;left:0;width:100%;height:100%;border:none&quot;
      allowfullscreen
      loading=&quot;lazy&quot;
    &gt;&lt;/iframe&gt;
  &lt;/div&gt;
&lt;/div&gt;</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Mon, 05 Jan 2026 18:53:00 GMT</pubDate></item><item><title>Apple 非国区ID注册教程</title><link>https://hub.xiaozhangya.xin/blog/appleid/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/appleid/</guid><description>手把手教你注册 Apple 非国区（如美区、日区）ID</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/appleid/&quot;&gt;https://hub.xiaozhangya.xin/blog/appleid/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;
import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;
import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;
import TimeLine from &amp;quot;../../components/mdx/TimeLine.astro&amp;quot;;&lt;/p&gt;
&lt;Info&gt;
本教程适用于需要注册 Apple 非国区（如美区、日区等）ID的用户，建议自用，勿用于灰产。
&lt;/Info&gt;

&lt;h2&gt;前期准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一个邮箱（QQ、谷歌、微软等常见邮箱均可）&lt;/li&gt;
&lt;li&gt;官方网址：&lt;a href=&quot;https://account.apple.com/account&quot;&gt;注册地址&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;一个自用的手机号&lt;/li&gt;
&lt;/ul&gt;
&lt;Warning&gt;
请勿使用虚假信息注册，避免账号被封。
&lt;/Warning&gt;

&lt;h2&gt;操作流程&lt;/h2&gt;
&lt;p&gt;&amp;lt;TimeLine
  items={[
    { year: &amp;quot;Step 1&amp;quot;, event: &amp;quot;访问 &lt;a href=&quot;https://account.apple.com/account&quot;&gt;Apple ID 注册官网&lt;/a&gt;&amp;quot; },
    { year: &amp;quot;Step 2&amp;quot;, event: &amp;quot;填写注册信息（邮箱、密码、姓名等）&amp;quot; },
    { year: &amp;quot;Step 3&amp;quot;, event: &amp;quot;选择国家或地区（如美国、日本等）&amp;quot; },
    { year: &amp;quot;Step 4&amp;quot;, event: &amp;quot;邮箱/手机验证&amp;quot; },
    { year: &amp;quot;Step 5&amp;quot;, event: &amp;quot;注册完成，可登录 Apple 相关服务&amp;quot; },
  ]}
/&amp;gt;&lt;/p&gt;
&lt;h2&gt;图文教程&lt;/h2&gt;
&lt;Collapse title=&quot;点击展开查看详细截图&quot;&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/blog/appleID/appleID01.png&quot; alt=&quot;注册页面1&quot; /&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/blog/appleID/appleID02.png&quot; alt=&quot;注册页面2&quot; /&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/blog/appleID/appleID03.png&quot; alt=&quot;注册页面3&quot; /&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/blog/appleID/appleID04.png&quot; alt=&quot;注册页面4&quot; /&gt;
&lt;/Collapse&gt;

&lt;Info&gt;
注册完成后，你可以在 App Store 下载国区无法获取的应用（如部分代理软件等）。
&lt;/Info&gt;</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 18 Sep 2025 00:00:00 GMT</pubDate></item><item><title>🚀 Umami 官方CSV数据导入自建Umami后端MySQL/PostgreSQL数据库</title><link>https://hub.xiaozhangya.xin/blog/umami/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/umami/</guid><description>将Umami云服务的CSV数据导入到自建MySQL或PostgreSQL数据库的完整解决方案，支持批量处理和自动去重。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/umami/&quot;&gt;https://hub.xiaozhangya.xin/blog/umami/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;&lt;br&gt;import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;&lt;br&gt;import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;;&lt;br&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;; 
import FriendCard from &amp;quot;@/components/mdx/FriendCard.astro&amp;quot;;
import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;&lt;/p&gt;
&lt;h1&gt;🚀 Umami 官方CSV数据导入自建Umami后端MySQL/PostgreSQL数据库&lt;/h1&gt;
&lt;Info&gt;  
需要将Umami云服务的CSV数据导入到自建MySQL或PostgreSQL数据库的完整解决方案。  
&lt;/Info&gt;  
## 介绍  
  
&lt;p&gt;说起&lt;strong&gt;Umami&lt;/strong&gt;，相信很多朋友都在用它来做网站分析。界面简洁，功能也挺全面的，确实是个不错的选择。不过呢，如果你用的是&lt;strong&gt;Umami Cloud的免费版本&lt;/strong&gt;，时间长了可能就会发现一些限制了——比如&lt;strong&gt;数据保留时间不够长&lt;/strong&gt;，或者想分析更多域名但&lt;strong&gt;额度不够用&lt;/strong&gt;。  &lt;/p&gt;
&lt;p&gt;这时候，很多人就会考虑：要不&lt;strong&gt;自己搭一个Umami&lt;/strong&gt;？但问题来了，之前在云端积累的那些&lt;strong&gt;数据怎么办&lt;/strong&gt;？总不能就这么丢了吧？  &lt;/p&gt;
&lt;p&gt;别担心，这篇教程就是来解决这个问题的。我会&lt;strong&gt;手把手教你&lt;/strong&gt;怎么把&lt;strong&gt;Umami Cloud上的数据完整地迁移&lt;/strong&gt;到自己搭建的Umami上，让你的数据分析不中断，还能享受&lt;strong&gt;自托管的各种好处&lt;/strong&gt;。&lt;br&gt;&lt;Info&gt;&lt;br&gt;如果您还没有自己的服务器或Umami实例，可以先查看我的博客文章&lt;a href=&quot;https://hub.xiaozhangya.xin/blog/umamicourse&quot;&gt;&lt;strong&gt;&lt;em&gt;《Umami + Neon + Vercel：免费搭建隐私友好的自己的Umami后端网站分析系统》&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;，了解如何免费搭建自己的Umami服务。&lt;br&gt;&lt;/Info&gt;  &lt;/p&gt;
&lt;h2&gt;核心思路&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;官方数据导出
&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/FCkmzRDT.png&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;li&gt;读取CSV → 清洗数据 → 分表插入  &lt;/li&gt;
&lt;li&gt;MySQL使用&lt;code&gt;INSERT IGNORE&lt;/code&gt;，PostgreSQL使用&lt;code&gt;ON CONFLICT DO NOTHING&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;批量处理提升性能&lt;/li&gt;
&lt;/ol&gt;
&lt;Warning&gt;  
⚠️ **安全提醒**：请替换配置中的数据库连接信息为您自己的，不要在代码中硬编码敏感信息。  
&lt;/Warning&gt;

&lt;h3&gt;关键配置&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;MySQL版本&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import pymysql
MYSQL_CONFIG = {
    &amp;#39;host&amp;#39;: &amp;#39;your-mysql-host.com&amp;#39;,
    &amp;#39;port&amp;#39;: 3306,
    &amp;#39;database&amp;#39;: &amp;#39;umami&amp;#39;,
    &amp;#39;user&amp;#39;: &amp;#39;your_username&amp;#39;,
    &amp;#39;password&amp;#39;: &amp;#39;your_password&amp;#39;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL版本（Neon数据库）&lt;/strong&gt;
&lt;Collapse title=&quot;PostgreSQL连接信息获取（Neon）&quot;&gt;
&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/EI8EPOlC.png&quot; alt=&quot;&quot;&gt;
&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/AE8tP3Vz.png&quot; alt=&quot;&quot;&gt;
&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/1wohUTiF.png&quot; alt=&quot;&quot;&gt;
&lt;/Collapse&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import psycopg2
POSTGRES_CONFIG = {
    &amp;#39;host&amp;#39;: &amp;#39;your-project-pooler.region.aws.neon.tech&amp;#39;,
    &amp;#39;port&amp;#39;: 5432,
    &amp;#39;database&amp;#39;: &amp;#39;your_database&amp;#39;,
    &amp;#39;user&amp;#39;: &amp;#39;your_username&amp;#39;,
    &amp;#39;password&amp;#39;: &amp;#39;your_password&amp;#39;,
    &amp;#39;sslmode&amp;#39;: &amp;#39;require&amp;#39;
}
# 或者直接使用连接字符串
POSTGRES_URL = &amp;#39;postgresql://username:password@host:port/database?sslmode=require&amp;amp;channel_binding=require&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;连接字符串解析&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组件&lt;/th&gt;
&lt;th&gt;示例值&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;协议类型&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;postgresql://&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL数据库协议标识&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;用户名&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;username&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库用户名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;密码&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库密码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;分隔符&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;认证信息与服务器地址的分隔符&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;主机地址&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;host.pooler.region.aws.neon.tech&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库服务器地址（Neon格式）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;端口&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5432&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库连接端口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;数据库名&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;database&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;目标数据库名称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSL模式&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sslmode=require&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SSL连接必须加密&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;通道绑定&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;channel_binding=require&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;通道绑定安全验证&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;数据库差异对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;MySQL&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;去重语法&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;INSERT IGNORE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ON CONFLICT DO NOTHING&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;字段引用&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;`field`&lt;/td&gt;
&lt;td&gt;&amp;quot;field&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;连接库&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;pymysql&lt;/td&gt;
&lt;td&gt;psycopg2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UUID类型&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR(36)&lt;/td&gt;
&lt;td&gt;UUID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;时间戳&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DATETIME&lt;/td&gt;
&lt;td&gt;TIMESTAMP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;📥 完整代码生成&lt;/h2&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;Umami CSV导入脚本&quot;  
  desc=&quot;完整的Python脚本，支持MySQL和PostgreSQL双数据库导入&quot;  
  url=&quot;https://umjs.131714.xyz&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/Avatar/1753524991293_avatar8.jpg&quot;  
/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;由于代码较长，完整版本已通过上方网页自行生成 ，包含以下功能：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 支持MySQL和PostgreSQL双数据库&lt;/li&gt;
&lt;li&gt;✅ 自动数据清洗和验证&lt;/li&gt;
&lt;li&gt;✅ 批量插入和去重处理&lt;/li&gt;
&lt;li&gt;✅ 完善的错误处理机制&lt;/li&gt;
&lt;li&gt;✅ 实时进度显示和统计&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;主要模块：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据库连接管理&lt;/li&gt;
&lt;li&gt;CSV数据读取和清洗&lt;/li&gt;
&lt;li&gt;批量数据插入&lt;/li&gt;
&lt;li&gt;结果验证和统计
🚀 使用说明&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;安装依赖包&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install pandas numpy pymysql psycopg2-binary
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;修改配置&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;根据您的实际数据库信息修改配置参数：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据库连接信息&lt;/li&gt;
&lt;li&gt;CSV文件路径&lt;/li&gt;
&lt;li&gt;目标website_id&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;选择数据库类型&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;脚本会提示您选择MySQL或PostgreSQL，然后自动处理数据导入。&lt;/p&gt;
&lt;p&gt;⚠️ &lt;strong&gt;使用前须知&lt;/strong&gt; 
&lt;strong&gt;安全提醒：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;请替换配置中的数据库连接信息为您自己的&lt;/li&gt;
&lt;li&gt;不要在代码中硬编码敏感信息&lt;/li&gt;
&lt;li&gt;建议使用环境变量存储数据库密码&lt;/li&gt;
&lt;li&gt;运行前请备份您的数据库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;注意事项：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确保目标数据库有足够的存储空间&lt;/li&gt;
&lt;li&gt;建议在测试环境先验证导入流程&lt;/li&gt;
&lt;li&gt;大数据量导入可能需要较长时间&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🤝 特别感谢&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;在数据导入后端的实现过程中，得到了以下朋友的大力帮助：&lt;/strong&gt;&lt;br&gt;&lt;FriendCard
  name=&quot;April&quot;
  avatar=&quot;https://picbed.xiaozhangya.xin/picbed/20250726061546364.png&quot;
  description=&quot;人间四月芳菲尽！&quot;
  url=&quot;https://www.zhaocloud.work&quot;
  type=&quot;friend&quot;
/&gt;&lt;/p&gt;
&lt;h2&gt;📚 参考资料&lt;/h2&gt;
&lt;p&gt;本文参考了以下资源：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.closex.org/posts/29bdb155/&quot;&gt;Umami数据导出与迁移实践&lt;/a&gt; - 提供了数据迁移的思路和方法  &lt;/li&gt;
&lt;li&gt;完整的Python导入脚本由AI辅助生成，经过实际测试验证&lt;/li&gt;
&lt;/ul&gt;
&lt;Success&gt;  
感谢开源社区的分享精神，让技术知识得以传播和改进。如果这篇文章对您有帮助，也欢迎分享给更多需要的朋友。  
&lt;/Success&gt;  
  
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 14 Aug 2025 00:00:00 GMT</pubDate></item><item><title>🚀 Umami + Neon + Vercel：免费搭建隐私友好的自己的Umami后端网站分析系统</title><link>https://hub.xiaozhangya.xin/blog/umamicourse/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/umamicourse/</guid><description>详细教程：使用 Neon PostgreSQL 数据库和 Vercel 部署 Umami 网站分析工具，实现隐私优先的访问统计</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/umamicourse/&quot;&gt;https://hub.xiaozhangya.xin/blog/umamicourse/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;; 
import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;; 
import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;; 
import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;; 
import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;; 
import Kbd from &amp;quot;../../components/mdx/Kbd.astro&amp;quot;; &lt;/p&gt;
&lt;h2&gt;📝 一、前提条件&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;前提准备：&lt;/strong&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 一个 &lt;a href=&quot;https://github.com/&quot;&gt;&lt;strong&gt;&lt;em&gt;GitHub&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; 账号（用于 fork &amp;amp; 部署） &lt;/li&gt;
&lt;li&gt;✅ 一个 &lt;a href=&quot;https://vercel.com/&quot;&gt;&lt;strong&gt;&lt;em&gt;Vercel&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; 账号（免费可用） &lt;/li&gt;
&lt;li&gt;✅ 一个 &lt;a href=&quot;https://neon.tech/&quot;&gt;&lt;strong&gt;&lt;em&gt;Neon&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; 账号（免费 PostgreSQL 数据库） &lt;/li&gt;
&lt;li&gt;✅ 基础 &lt;strong&gt;Node.js / Git&lt;/strong&gt; 操作知识（非强制）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🗄️ 二、什么是 Neon？&lt;/h2&gt;
&lt;p&gt;&lt;LinkCard 
 title=&quot;Neon&quot; 
 desc=&quot;现代化的无服务器 PostgreSQL 数据库平台&quot; 
 url=&quot;https://neon.tech/&quot; 
 img=&quot;https://neon.tech/favicon.ico&quot; 
/&gt; &lt;/p&gt;
&lt;Info&gt; 
Neon 是一个现代化的 PostgreSQL 数据库服务，提供无服务器架构、自动扩缩容和分支功能，非常适合现代 Web 应用。 
&lt;/Info&gt; 

&lt;h2&gt;🧩 三、什么是 Umami？&lt;/h2&gt;
&lt;p&gt;&lt;LinkCard 
 title=&quot;Umami&quot; 
 desc=&quot;轻量级、隐私优先的网站分析工具&quot; 
 url=&quot;https://github.com/umami-software/umami&quot; 
 img=&quot;https://img.xiaozhangya.xin/file/Logo/1753850918996_umami.png&quot; 
/&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Umami是一个轻量级、隐私优先的网站分析工具：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔍 实时访问分析 &lt;/li&gt;
&lt;li&gt;🌐 支持多个网站 &lt;/li&gt;
&lt;li&gt;📊 自定义事件追踪 &lt;/li&gt;
&lt;li&gt;💰 免费部署 &lt;/li&gt;
&lt;li&gt;🍪 不依赖 cookie&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🛠️ 四、在 Neon 上部署 PostgreSQL 数据库&lt;/h2&gt;
&lt;Collapse title=&quot;详细步骤展开&quot;&gt; 


&lt;ol&gt;
&lt;li&gt;&lt;p&gt;打开 &lt;a href=&quot;https://neon.tech/&quot;&gt;https://neon.tech/&lt;/a&gt; 并注册登录 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;创建新项目，选择合适的区域 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;获取数据库连接信息&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/O916LFpF.png&quot; alt=&quot;umami1.png&quot;&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/tn4ZR3KH.png&quot; alt=&quot;umami2.png&quot;&gt; &lt;/p&gt;
&lt;/Collapse&gt; 

&lt;Success&gt; 
Neon 提供免费的 PostgreSQL 数据库，非常适合小型项目使用！ 
&lt;/Success&gt; 

&lt;hr&gt;
&lt;h2&gt;🚀 五、在 Vercel 上部署 Umami&lt;/h2&gt;
&lt;h3&gt;1. Fork 仓库&lt;/h3&gt;
&lt;p&gt;前往 &lt;a href=&quot;https://github.com/umami-software/umami&quot;&gt;&lt;strong&gt;&lt;em&gt;umami 仓库&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;，点击 &lt;strong&gt;Fork&lt;/strong&gt;。 &lt;/p&gt;
&lt;h3&gt;2. 在 Vercel 导入仓库&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;登录 Vercel，点击 &lt;strong&gt;New Project&lt;/strong&gt; → &lt;strong&gt;Import Git Repository&lt;/strong&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;选择你 Fork 的 &lt;code&gt;umami&lt;/code&gt; 仓库 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;设置环境变量（Environment Variables）：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;HASH_SALT=任意字符串（用于密码加盐，建议随机生成） 
DATABASE_TYPE=postgresql 
DATABASE_URL=postgresql://&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;@&amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;/umami
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠ 将 &lt;code&gt;&amp;lt;user&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;password&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;host&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;port&amp;gt;&lt;/code&gt; 替换为 Neon 提供的连接信息&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;点击 &lt;strong&gt;Deploy&lt;/strong&gt; 部署。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;✅ 六、访问 Umami 后台&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;打开部署成功后的地址，例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://umami-yourproject.vercel.app
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;默认管理员账号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;用户名：admin
密码：umami
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;登录后务必修改默认密码。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/3rNFz35P.png&quot; alt=&quot;umami3.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/Q5HQ620E.png&quot; alt=&quot;umami4.png&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;📦 七、在网站中嵌入统计代码&lt;/h2&gt;
&lt;p&gt;在你的网站 &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; 或 &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; 前插入以下代码：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;script defer
  src=&amp;quot;https://umami-yourproject.vercel.app/script.js&amp;quot;
  data-website-id=&amp;quot;你的网站ID&amp;quot;
&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data-website-id&lt;/code&gt;：在 Umami 后台“添加网站”时会生成一个 UUID&lt;/li&gt;
&lt;li&gt;支持多个站点，每个站点生成独立的 ID&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;📊 八、功能预览&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/umami/d0scu1Tz.png&quot; alt=&quot;umami5.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Umami 提供丰富的分析功能：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📈 实时访问统计&lt;/li&gt;
&lt;li&gt;📄 页面访问量、跳出率、平均停留时间&lt;/li&gt;
&lt;li&gt;🌍 访客来源、设备、浏览器、操作系统&lt;/li&gt;
&lt;li&gt;🎯 自定义事件追踪（如点击按钮、提交表单）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;📚 九、参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Umami 文档：&lt;a href=&quot;https://umami.is/docs&quot;&gt;https://umami.is/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub 仓库：&lt;a href=&quot;https://github.com/umami-software/umami&quot;&gt;https://github.com/umami-software/umami&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Neon 官网：&lt;a href=&quot;https://neon.tech/&quot;&gt;https://neon.tech/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vercel 官网：&lt;a href=&quot;https://vercel.com/&quot;&gt;https://vercel.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Fri, 08 Aug 2025 00:00:00 GMT</pubDate></item><item><title>WordPress动态网站托管在InfinityFree平台</title><link>https://hub.xiaozhangya.xin/blog/infinityfree/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/infinityfree/</guid><description>详细介绍如何在InfinityFree免费主机平台部署WordPress网站，并使用EdgeOne CDN进行加速优化的完整教程</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/infinityfree/&quot;&gt;https://hub.xiaozhangya.xin/blog/infinityfree/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;&lt;br&gt;import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;&lt;br&gt;import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;;&lt;br&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;&lt;br&gt;import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;  &lt;/p&gt;
&lt;h2&gt;1、前期准备&lt;/h2&gt;
&lt;p&gt;在开始部署之前，您需要准备以下资源：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EdgeOne CDN账号&lt;/strong&gt;（可选，用于网站加速。如使用InfinityFree提供的免费域名，国内访问速度较慢）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InfinityFree账号&lt;/strong&gt;（免费主机服务商）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;域名&lt;/strong&gt;（可选，也可使用InfinityFree平台提供的免费域名）&lt;/li&gt;
&lt;/ul&gt;
&lt;Warning&gt;  
使用免费域名虽然成本为零，但在国内访问速度和稳定性方面可能存在限制。建议有条件的用户购买独立域名以获得更好的用户体验。  
&lt;/Warning&gt;  
  
&lt;h2&gt;2、平台介绍&lt;/h2&gt;
&lt;h3&gt;InfinityFree平台介绍&lt;/h3&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;InfinityFree&quot;  
  desc=&quot;提供免费PHP主机服务，支持MySQL数据库，适合WordPress等动态网站部署&quot;  
  url=&quot;https://www.infinityfree.com/&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/Logo/1754280946361_InfinityFree.png&quot;  
/&gt;  &lt;/p&gt;
&lt;p&gt;InfinityFree 是一个知名的免费虚拟主机服务商，提供以下特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;约 5 GB 磁盘空间 和 大额度流量（受每日访问次数和资源使用限制）&lt;/li&gt;
&lt;li&gt;支持 PHP 8.x 和 MySQL 数据库&lt;/li&gt;
&lt;li&gt;免费 SSL 证书（支持 Let&amp;#39;s Encrypt）&lt;/li&gt;
&lt;li&gt;自带 VistaPanel 控制面板（类似 cPanel）&lt;/li&gt;
&lt;li&gt;支持绑定 自定义域名 和创建子域名&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;EdgeOne介绍&lt;/h3&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;EdgeOne&quot;  
  desc=&quot;腾讯云提供的边缘计算和CDN加速服务&quot;  
  url=&quot;https://edgeone.ai&quot;  
  img=&quot;https://hub.xiaozhangya.xin/image/icons/edgeone.png&quot;  
/&gt;  &lt;/p&gt;
&lt;p&gt;EdgeOne是腾讯云的边缘计算平台，主要优势：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;针对中国大陆网络环境优化  &lt;/li&gt;
&lt;li&gt;智能路由和加速  &lt;/li&gt;
&lt;li&gt;DDoS防护和安全防护  &lt;/li&gt;
&lt;li&gt;支持动态和静态内容加速&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3、EdgeOne账号注册&lt;/h2&gt;
&lt;Collapse title=&quot;EdgeOne注册详细步骤&quot;&gt;  
  
&lt;ol&gt;
&lt;li&gt;访问 &lt;a href=&quot;https://edgeone.ai/&quot;&gt;EdgeOne官网&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;点击&amp;quot;立即注册&amp;quot;按钮  &lt;/li&gt;
&lt;li&gt;填写手机号码并获取验证码  &lt;/li&gt;
&lt;li&gt;设置登录密码  &lt;/li&gt;
&lt;li&gt;完成实名认证（企业或个人）  &lt;/li&gt;
&lt;li&gt;激活账号并登录控制台&lt;/li&gt;
&lt;/ol&gt;
&lt;/Collapse&gt;  
  
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/b2q9Z77p.png&quot; alt=&quot;EdgeOne注册界面&quot;&gt;  &lt;/p&gt;
&lt;Info&gt;  
EdgeOne目前不提供免费额度，但最近有活动可以获取免费套餐。访问 [**_活动网址_**](https://edgeone.ai/get-free-plan?from=marketing_banner) 进行测速分享可以获得两个免费套餐。  
&lt;/Info&gt;  
  
&lt;h2&gt;4、InfinityFree账号注册&lt;/h2&gt;
&lt;Collapse title=&quot;InfinityFree注册详细步骤&quot;&gt;  
  
&lt;ol&gt;
&lt;li&gt;访问 &lt;a href=&quot;https://infinityfree.net&quot;&gt;InfinityFree官网&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;点击&amp;quot;Create Account&amp;quot;  &lt;/li&gt;
&lt;li&gt;填写邮箱地址和密码  &lt;/li&gt;
&lt;li&gt;验证邮箱（检查垃圾邮件文件夹）  &lt;/li&gt;
&lt;li&gt;登录客户端面板  &lt;/li&gt;
&lt;li&gt;创建新的主机账户&lt;/li&gt;
&lt;/ol&gt;
&lt;/Collapse&gt;  
  
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/QnvMuom3.png&quot; alt=&quot;InfinityFree注册界面&quot;&gt;  &lt;/p&gt;
&lt;Success&gt;  
注册成功后，您将获得一个免费的子域名，格式通常为：yourusername.infinityfreeapp.com  
&lt;/Success&gt;  
  
&lt;h2&gt;5、InfinityFree详细安装WordPress教程&lt;/h2&gt;
&lt;Collapse title=&quot;WordPress安装步骤图解&quot;&gt;  
  
&lt;h3&gt;步骤1：创建主机账户&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/vT5Snazk.png&quot; alt=&quot;创建主机账户&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤2：选择计划&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/XsUPX34t.png&quot; alt=&quot;选择计划&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤3：选择域名&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/gWkIC4td.png&quot; alt=&quot;选择域名&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤4：打开管理界面&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/TrSQeUGj.png&quot; alt=&quot;打开管理界面&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤5：访问控制面板&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/qFI4aaLK.png&quot; alt=&quot;访问控制面板&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤6：安装WordPress&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/5UttNXlO.png&quot; alt=&quot;安装WordPress&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;步骤7：配置WordPress&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/uVRMXHNZ.png&quot; alt=&quot;配置WordPress&quot;&gt;&lt;br&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/dYhYYAgn.png&quot; alt=&quot;完成安装&quot;&gt;  &lt;/p&gt;
&lt;/Collapse&gt;  
  
&lt;h3&gt;验证安装结果&lt;/h3&gt;
&lt;p&gt;安装完成后，使用平台提供的域名访问您的网站：  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/5ErnBN4N.png&quot; alt=&quot;WordPress前台界面&quot;&gt;  &lt;/p&gt;
&lt;p&gt;要访问后台管理界面，在域名后添加 &lt;code&gt;/wp-admin&lt;/code&gt;，使用管理员账户登录：  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/qT1cF4jZ.png&quot; alt=&quot;WordPress后台界面&quot;&gt;  &lt;/p&gt;
&lt;Warning&gt;  
如果您已经在其他地方部署过WordPress，可以将主题文件和数据库文件迁移过来。  
&lt;/Warning&gt;  
  
&lt;h2&gt;6、配置EdgeOne CDN加速&lt;/h2&gt;
&lt;Warning&gt;  
EdgeOne不提供免费使用，但最近有活动可以获取免费套餐。访问 [**_活动网址_**](https://edgeone.ai/get-free-plan?from=marketing_banner) 进行测速分享可以获得两个免费套餐。  
&lt;/Warning&gt;  
  
&lt;h3&gt;6.1 添加站点&lt;/h3&gt;
&lt;Info&gt;  
需要使用自己购买的一级域名，否则无法添加站点。目前免费域名无法添加，EdgeOne需要验证域名归属权。  
&lt;/Info&gt;  
  
&lt;ol&gt;
&lt;li&gt;登录EdgeOne控制台  &lt;/li&gt;
&lt;li&gt;点击&amp;quot;添加站点&amp;quot;  &lt;/li&gt;
&lt;li&gt;输入您的域名  &lt;/li&gt;
&lt;li&gt;选择获得的免费套餐  &lt;/li&gt;
&lt;li&gt;完成站点添加&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;6.2 域名配置流程&lt;/h3&gt;
&lt;Collapse title=&quot;EdgeOne域名配置详细步骤&quot;&gt;  
  
&lt;h4&gt;步骤1：添加域名&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/sUUArBRX.png&quot; alt=&quot;添加域名&quot;&gt;  &lt;/p&gt;
&lt;h4&gt;步骤2：DNS配置&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/2xvvbStO.png&quot; alt=&quot;DNS配置&quot;&gt;  &lt;/p&gt;
&lt;h4&gt;步骤3：HTTPS配置&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/WKv1wMt6.png&quot; alt=&quot;HTTPS配置&quot;&gt;  &lt;/p&gt;
&lt;/Collapse&gt;  
  
&lt;h3&gt;6.3 WordPress站点地址配置&lt;/h3&gt;
&lt;p&gt;在WordPress后台管理界面，将站点地址和WordPress地址改为您的自定义域名：  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/dnYWuL12.png&quot; alt=&quot;WordPress地址配置&quot;&gt;  &lt;/p&gt;
&lt;h3&gt;6.4 加速效果对比&lt;/h3&gt;
&lt;p&gt;配置EdgeOne CDN前后的访问速度对比：  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置前（直接访问）：&lt;/strong&gt;&lt;br&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/dP4BnVHe.png&quot; alt=&quot;配置前速度&quot;&gt;  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置后（CDN加速）：&lt;/strong&gt;&lt;br&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/InfinityCourse/7FG1LSUl.png&quot; alt=&quot;配置后速度&quot;&gt;  &lt;/p&gt;
&lt;Success&gt;  
配置完成后，您的WordPress网站将通过EdgeOne CDN进行全球加速，显著提升访问速度和用户体验！  
&lt;/Success&gt;  
  
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;通过本教程，您已经成功完成：  &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;✅ 注册EdgeOne和InfinityFree账号  &lt;/li&gt;
&lt;li&gt;✅ 在免费主机上部署WordPress  &lt;/li&gt;
&lt;li&gt;✅ 配置CDN加速服务  &lt;/li&gt;
&lt;li&gt;✅ 优化网站性能和安全性&lt;/li&gt;
&lt;/ol&gt;
&lt;Info&gt;  
建议定期备份网站数据，监控网站性能，并根据实际需求调整CDN配置以获得最佳效果。  
&lt;/Info&gt;</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate></item><item><title>VPN代理软件配置完整教程</title><link>https://hub.xiaozhangya.xin/blog/subdy/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/subdy/</guid><description>SubsCheck、Mihomo代理软件的详细配置教程，包含订阅链接使用指南</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/subdy/&quot;&gt;https://hub.xiaozhangya.xin/blog/subdy/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;&lt;br&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;&lt;br&gt;import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;  &lt;/p&gt;
&lt;h1&gt;VPN代理软件配置完整教程&lt;/h1&gt;
&lt;h2&gt;⚠️ 免责声明&lt;/h2&gt;
&lt;Info&gt;  
本教程仅供学习和技术交流使用，请遵守当地法律法规。使用本教程所涉及的工具和服务时，用户需自行承担相关风险和责任。作者不对因使用本教程而产生的任何直接或间接损失承担责任。  
&lt;/Info&gt;  

&lt;h2&gt;📝 内容来源&lt;/h2&gt;
&lt;p&gt;本教程内容整理自开源社区和技术大佬的分享，特别感谢：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CM大佬&lt;/strong&gt; 的 SubsCheck Win GUI 项目 &lt;a href=&quot;#1-0&quot;&gt;1&lt;/a&gt;   &lt;/li&gt;
&lt;li&gt;各位开源贡献者的无私分享  &lt;/li&gt;
&lt;li&gt;社区技术交流和实践经验总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🛠️ 前期准备&lt;/h2&gt;
&lt;h3&gt;SubsCheck 订阅检测工具&lt;/h3&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;SubsCheck-Win-GUI&quot;  
  desc=&quot;Windows平台的订阅链接检测工具 - 来自CM大佬开源项目&quot;  
  url=&quot;https://github.com/cmliu/SubsCheck-Win-GUI&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/Avatar/1753524993769_avatar10.jpg&quot;  
/&gt;  &lt;/p&gt;
&lt;h3&gt;Mihomo 代理软件&lt;/h3&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;Mihomo Party&quot;  
  desc=&quot;跨平台的代理软件客户端 - 开源免费&quot;  
  url=&quot;https://github.com/mihomo-party-org/mihomo-party&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/demo/1753772902810_logo1.png&quot;
/&gt;&lt;/p&gt;
&lt;h3&gt;夸克网盘下载&lt;/h3&gt;
&lt;Info&gt;
上方无法访问的话则使用夸克网盘下载相关软件和配置文件。
&lt;/Info&gt;
---

&lt;p&gt;&lt;LinkCard  
  title=&quot;夸克网盘资源&quot;  
  desc=&quot;相关软件和配置文件下载（第三方整理）&quot;  
  url=&quot;https://pan.quark.cn/s/f6e8a750a2ae&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/demo/1753773251454_logo2.png&quot;  
/&gt;  &lt;/p&gt;
&lt;h2&gt;📺 教程资源&lt;/h2&gt;
&lt;h3&gt;视频教程&lt;/h3&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;订阅链接配置教程&quot;  
  desc=&quot;完整的视频教程，教您如何正确配置和使用订阅链接（转自技术大佬分享）&quot;  
  url=&quot;https://youtu.be/sS9Tuf1PCyc?si=xi6vZA_Z_gtViGov&quot;  
  img=&quot;https://img.xiaozhangya.xin/file/1753769786428_YouTube.png&quot;  
/&gt;  &lt;/p&gt;
&lt;h3&gt;图文教程&lt;/h3&gt;
&lt;Collapse title=&quot;查看详细配置步骤&quot;&gt;  

&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/demo/1753771659446_c1.png&quot; alt=&quot;配置步骤1&quot;&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/demo/1753771652467_c2.png&quot; alt=&quot;配置步骤2&quot;&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/demo/1753771770634_c3.png&quot; alt=&quot;配置步骤3&quot;&gt;  &lt;/p&gt;
&lt;/Collapse&gt;  

&lt;h2&gt;🎯 效果展示&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/demo/1753768851132_demo1.png&quot; alt=&quot;效果展示1&quot;&gt;  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/demo/1753768855621_demo2.png&quot; alt=&quot;效果展示2&quot;&gt;  &lt;/p&gt;
&lt;h2&gt;🔗 订阅链接&lt;/h2&gt;
&lt;Info&gt;  
⚠️ 重要提醒：以下订阅链接来源于作者的分享，可跟随上方教程视频进行自己部署。使用前请确保遵守相关法律法规。  
&lt;/Info&gt;  

&lt;h3&gt;自己部署的订阅链接：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;YAML 格式的订阅&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://dy.xiaozhangya.xin/storage?filename=all.yaml&amp;token=dy&quot;&gt;https://dy.xiaozhangya.xin/storage?filename=all.yaml&amp;amp;token=dy&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base64 编码的订阅&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://dy.xiaozhangya.xin/storage?filename=base64.txt&amp;token=dy&quot;&gt;https://dy.xiaozhangya.xin/storage?filename=base64.txt&amp;amp;token=dy&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;带规则的 Mihomo 配置文件&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://dy.xiaozhangya.xin/storage?filename=mihomo.yaml&amp;token=dy&quot;&gt;https://dy.xiaozhangya.xin/storage?filename=mihomo.yaml&amp;amp;token=dy&lt;/a&gt;&lt;/p&gt;
&lt;Collapse title=&quot;订阅链接使用说明&quot;&gt;  

&lt;ol&gt;
&lt;li&gt;复制对应格式的订阅链接  &lt;/li&gt;
&lt;li&gt;在客户端中添加订阅  &lt;/li&gt;
&lt;li&gt;更新订阅获取最新节点  &lt;/li&gt;
&lt;li&gt;选择合适的节点进行连接&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;注意事项：&lt;/strong&gt;  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;订阅链接仅供技术学习使用  &lt;/li&gt;
&lt;li&gt;请定期更新订阅以获取最新节点  &lt;/li&gt;
&lt;li&gt;如遇连接问题，请检查本地网络环境&lt;/li&gt;
&lt;/ul&gt;
&lt;/Collapse&gt;  

&lt;h2&gt;🙏 致谢&lt;/h2&gt;
&lt;p&gt;感谢以下技术大佬和开源项目：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CM大佬&lt;/strong&gt; - SubsCheck Win GUI 项目作者 &lt;a href=&quot;#1-1&quot;&gt;2&lt;/a&gt;   &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mihomo Party&lt;/strong&gt; 开发团队  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SubsCheck&lt;/strong&gt; 项目贡献者  &lt;/li&gt;
&lt;li&gt;所有为开源社区贡献代码的开发者们&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;📋 版权说明&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;本教程基于开源项目和社区分享整理  &lt;/li&gt;
&lt;li&gt;相关代码和工具版权归原作者所有  &lt;/li&gt;
&lt;li&gt;教程内容遵循 CC BY-SA 4.0 协议  &lt;/li&gt;
&lt;li&gt;转载请注明来源和原作者信息&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;温馨提示&lt;/strong&gt;：技术无罪，使用有责。请合理合法使用相关技术，共同维护良好的网络环境。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 29 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🛠️ 少年游未尽，我在折腾中成长</title><link>https://hub.xiaozhangya.xin/blog/growth-log/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/growth-log/</guid><description>从零开始捣鼓博客与建站：搭博客、部署评论、配置 Cloudflare 和图床、用 Git 管理项目……这是我从小白到站长的完整技术成长记录。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/growth-log/&quot;&gt;https://hub.xiaozhangya.xin/blog/growth-log/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;&lt;br&gt;import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;&lt;br&gt;import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;;&lt;br&gt;import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;&lt;br&gt;import TimeLine from &amp;quot;../../components/mdx/TimeLine.astro&amp;quot;;&lt;br&gt;import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;  &lt;/p&gt;
&lt;h1&gt;🚀 从 0 到 1：我的折腾记录&lt;/h1&gt;
&lt;Info&gt;  
这一段时间，**从完全不会建站，到现在能搭博客、部署评论、玩 Cloudflare 和图床、用 Git 管理项目、自己写页面**…  
  
&lt;p&gt;虽然大多数东西都是现学现用、边查边做，但也正是这种折腾，带来了最大的成就感。  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;也许我的站点看起来不够&amp;quot;高级&amp;quot;，但它的每一个页面、每一个功能，都是我亲手一点点折腾出来的。&lt;/strong&gt;&lt;br&gt;&lt;/Info&gt;  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;⏳ 技术成长时间线&lt;/h2&gt;
&lt;p&gt;&amp;lt;TimeLine&lt;br&gt;  items={[&lt;br&gt;    { year: &amp;quot;阶段1&amp;quot;, event: &amp;quot;🧊 SMB + Infuse 实现局域网影视播放&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段2&amp;quot;, event: &amp;quot;🧰 Alist + Cloudflare Tunnel 远程访问本地文件&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段3&amp;quot;, event: &amp;quot;🌐 GitHub Page + Vue 静态博客初体验&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段4&amp;quot;, event: &amp;quot;🧱 本地部署 WordPress（XAMPP）&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段5&amp;quot;, event: &amp;quot;🖼️ PicGo → Telegram 图床 + Web UI + Cloudflare R2&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段6&amp;quot;, event: &amp;quot;💠 更换二次元风格主题（Boxmoe / Lolimeow）&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段7&amp;quot;, event: &amp;quot;🧍 个人主页打包展示所有项目&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段8&amp;quot;, event: &amp;quot;📁 静态博客 fork + 自定义配置&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段9&amp;quot;, event: &amp;quot;💬 评论系统的思考：Giscus vs Waline&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段10&amp;quot;, event: &amp;quot;📊 加入 Umami 网站统计 + 自定义文章浏览量模块&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段11&amp;quot;, event: &amp;quot;🔍 接入微软 Clarity 用户行为分析&amp;quot; },&lt;br&gt;    { year: &amp;quot;阶段12&amp;quot;, event: &amp;quot;🧭 添加导航页收集常用站点&amp;quot; }&lt;br&gt;  ]}&lt;br&gt;/&amp;gt;  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🧊 1. 从 SMB 共享开启的观影时代&lt;/h2&gt;
&lt;p&gt;最早的一次技术折腾，就是想在 iPad 上看电脑里的影视剧。&lt;br&gt;以前都是先下载、再传输、再播放，贼麻烦。&lt;br&gt;后来发现了 &lt;strong&gt;Infuse&lt;/strong&gt; 这个 App，居然支持 SMB 共享挂载，直接串流播放电脑里的视频，太牛了！  &lt;/p&gt;
&lt;Success&gt;  
配置 SMB 的过程也让我第一次接触到了局域网共享，设置路径、权限、文件夹访问…手把手学会，体验一下子上了好几个台阶。  
&lt;/Success&gt;  
  
&lt;hr&gt;
&lt;h2&gt;🧰 2. Alist + Cloudflare Tunnel：让本地文件飞起来&lt;/h2&gt;
&lt;p&gt;Infuse 后，我开始思考——&lt;strong&gt;能不能在外面也访问我本地的文件？&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;&lt;LinkCard  
  title=&quot;Alist&quot;  
  desc=&quot;一个支持多种存储的文件列表程序，使用 Gin 和 Solidjs。&quot;  
  url=&quot;https://github.com/alist-org/alist&quot;  
  img=&quot;https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg&quot;  
/&gt;  &lt;/p&gt;
&lt;p&gt;查资料的时候遇到一个神器项目：&lt;strong&gt;Alist&lt;/strong&gt;，能把本地文件挂载成一个网页浏览器，简直绝了！&lt;br&gt;&lt;Collapse title=&quot;解决方案详解&quot;&gt;&lt;br&gt;但问题来了：我没有服务器、也没有公网 IP，怎么让别人访问我本地的服务？  &lt;/p&gt;
&lt;p&gt;查着查着，发现了 &lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;，直接内网穿透！完美解决。  &lt;/p&gt;
&lt;h2&gt;我还顺便买了人生中第一个阿里云域名，算是真正迈出了&amp;quot;站长第一步&amp;quot;。&lt;br&gt;&lt;/Collapse&gt;  &lt;/h2&gt;
&lt;Warning&gt;  
⚠️ **重要更新**：原来的 Alist 项目已经转手，出于安全考虑，我后面改用了 Alist 的 Fork 项目 **OpenList**。  
&lt;/Warning&gt;  
---  
&lt;Info&gt;  
感兴趣的可以查看我的博客部署教程：[OpenList 本地部署指南](https://hub.xiaozhangya.xin/blog/openlist/)  
  
&lt;p&gt;也可以查看 &lt;a href=&quot;https://docs.oplist.org/zh/&quot;&gt;OpenList 官方文档&lt;/a&gt;。我目前使用的就是 OpenList。&lt;br&gt;&lt;/Info&gt; &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🌐 3. 初识 GitHub 博客：惊为天人&lt;/h2&gt;
&lt;p&gt;偶然在 B 站刷到 Vue 搭建的博客项目，被界面惊艳到。  &lt;/p&gt;
&lt;p&gt;于是跟着部署教程，第一次认真使用 GitHub：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clone 仓库  &lt;/li&gt;
&lt;li&gt;配置 token  &lt;/li&gt;
&lt;li&gt;提交 push  &lt;/li&gt;
&lt;li&gt;配置 Actions 自动部署&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;Success&gt;边学边感叹：&lt;strong&gt;GitHub 这东西也太香了吧！&lt;/strong&gt;&lt;/Success&gt;  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🧱 4. WordPress 本地部署：玩转 XAMPP&lt;/h2&gt;
&lt;p&gt;又被一个叫 Argon 的 WordPress 主题种草，UI 那叫一个顺眼。  &lt;/p&gt;
&lt;p&gt;但没有服务器怎么办？查了一圈，找到了 XAMPP！  &lt;/p&gt;
&lt;Info&gt;  
Windows 本地环境 + WordPress + 本地数据库，一通操作下来终于跑起来了。  
  
&lt;p&gt;还写了几篇文章当博客玩：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Git 使用教程  &lt;/li&gt;
&lt;li&gt;Hive 离线数仓  &lt;/li&gt;
&lt;li&gt;数据挖掘学习笔记  &lt;/Info&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🖼️ 5. 折腾图床系统：PicGo 到 Telegram + R2&lt;/h2&gt;
&lt;p&gt;发博客时最头疼的是图片——不能总传本地图吧？  &lt;/p&gt;
&lt;Collapse title=&quot;图床系统演进历程&quot;&gt;  
  
&lt;h3&gt;✅ 第一阶段：PicGo + GitHub 仓库图床&lt;/h3&gt;
&lt;p&gt;体验很好，但问题是 GitHub 仓库一堆图片又丑又乱，还经常加载慢。  &lt;/p&gt;
&lt;h3&gt;📷 第二阶段：Telegram 图床 + 网页 UI 管理界面&lt;/h3&gt;
&lt;p&gt;TG 频道 + Bot + WebUI，拖拽上传即生成直链链接，还能预览、分类，堪比小型图床相册系统，视觉体验拉满！  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;上传逻辑是 Bot 转发图片 → Web UI 生成链接 → 自动绑定图床地址，真的像做了个小产品！  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;☁️ 第三阶段：Cloudflare R2 加入图床系统&lt;/h3&gt;
&lt;p&gt;为了更快访问速度，还接入了 Cloudflare R2 存储，图像资源全部走 CDN 加速。  &lt;/p&gt;
&lt;/Collapse&gt;  
  
&lt;hr&gt;
&lt;h2&gt;💠 6. 二次元风格主题：Boxmoe 模板真香！&lt;/h2&gt;
&lt;p&gt;刷到一个 up 主博客样式爆炸好看，一查发现是 Boxmoe 的 &lt;a href=&quot;https://www.boxmoe.com/468.html&quot;&gt;&lt;code&gt;lolimeow&lt;/code&gt;&lt;/a&gt; 主题。  &lt;/p&gt;
&lt;p&gt;&lt;Success&gt;二次元 UI 完美戳中我审美，立马动手换主题 + 调样式，直接美化！&lt;/Success&gt;  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🧍 7. 个人主页整合&lt;/h2&gt;
&lt;p&gt;既然有博客了，也顺便做了个导航页，整合我做过的项目、图床、博客、API 端口等等。&lt;br&gt;像一张属于自己的 ID 卡。  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;📁 8. 静态博客 + 自定义改造&lt;/h2&gt;
&lt;p&gt;被某个静态博客模板种草后 fork 下来，开始一步步魔改： 
&lt;LinkCard
  title=&quot;Frosti&quot;
  desc=&quot;A clean, elegant, and fast static blog template! 🚀 Developed with Astro&quot;
  url=&quot;https://frosti.saroprock.com&quot;
  img=&quot;https://frosti.saroprock.com/profile.png&quot;
/&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;接下来就是&lt;strong&gt;嘎嘎一顿造&lt;/strong&gt;哈，改成我现在这个博客的样子  &lt;/p&gt;
&lt;Collapse title=&quot;魔改过程详解&quot;&gt;  &lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;理解项目结构  &lt;/li&gt;
&lt;li&gt;修改首页 / 页面布局  &lt;/li&gt;
&lt;li&gt;添加新菜单  &lt;/li&gt;
&lt;li&gt;迁移 WordPress 上的文章  &lt;/li&gt;
&lt;li&gt;自定义样式、主题配色&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;学到的远比想象的多！&lt;br&gt;&lt;/Collapse&gt;  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;💬 9. 评论系统的思考：Giscus vs Waline&lt;/h2&gt;
&lt;p&gt;想要博客有互动，那就得有评论。  &lt;/p&gt;
&lt;p&gt;经过对比，我倾向于选择 Giscus 方案：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基于 GitHub Discussions，无需额外服务器  &lt;/li&gt;
&lt;li&gt;读者可以直接用 GitHub 账号参与讨论  &lt;/li&gt;
&lt;li&gt;对技术博客来说更加合适&lt;/li&gt;
&lt;/ul&gt;
&lt;Info&gt;  
虽然还没有实际部署，但这个想法很符合我&quot;折腾&quot;的精神 —— 总是在寻找更好的解决方案！  
&lt;/Info&gt;  
  
&lt;hr&gt;
&lt;h2&gt;📊 10. Umami 网站统计 + 自定义模块&lt;/h2&gt;
&lt;p&gt;用 Umami 加入访问数据统计后，博客体验更完整了：  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每日访问量  &lt;/li&gt;
&lt;li&gt;热门文章  &lt;/li&gt;
&lt;li&gt;访问来源等&lt;br&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250727165253723.png&quot; alt=&quot;Umami展示&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;Warning&gt;  
还尝试接入 token 获取实时浏览量，用异步方式加载失败，服务端渲染也不理想，暂时搁置（以后再研究）。  
&lt;/Warning&gt;  
  
&lt;hr&gt;
&lt;h2&gt;🔍 11. 微软 Clarity：深入了解用户行为&lt;/h2&gt;
&lt;p&gt;在有了 Umami 的基础统计后，我开始想要更深入地了解用户在网站上的具体行为。  &lt;/p&gt;
&lt;Success&gt;  
发现了微软的 Clarity 工具，提供热力图、用户录屏、点击分析等功能，完全免费！配合 Umami 使用，数据分析更全面。  
&lt;/Success&gt;  
---  
&lt;Collapse title=&quot;Clarity vs Umami 对比&quot;&gt;  
- **Umami**：注重隐私保护，提供基础的访问统计  
- **Clarity**：提供详细的用户行为分析，包括热力图和会话录制  
- **组合使用**：两者互补，既保护隐私又获得深度洞察  
&lt;/Collapse&gt;  
![Clarity展示](https://picbed.xiaozhangya.xin/picbed/20250727165721627.png)
---  
  
&lt;h2&gt;🧭 12. 搭建导航页&lt;/h2&gt;
&lt;p&gt;把常用网站整理成卡片组件样式，每次开博客就能快速进入常用页面，整洁又实用！ 
&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250727164646504.png&quot; alt=&quot;导航页示例&quot;&gt; &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎉 最后的话&lt;/h2&gt;
&lt;p&gt;也许在别人眼里，这些折腾显得 &lt;strong&gt;“麻烦”“没必要”&lt;/strong&gt;，&lt;br&gt;但我始终相信：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;成长、眼界的拓宽，正是从一次次主动探索中，一点点积累起来的。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;💡 &lt;strong&gt;生活嘛，总得做些自己真正感兴趣的事吧？&lt;/strong&gt;&lt;br&gt;只要你热爱，它就值得你投入。&lt;br&gt;&lt;strong&gt;拥有一个属于自己的小世界，也挺酷的。&lt;/strong&gt;    &lt;/p&gt;
&lt;p&gt;从一开始的&lt;strong&gt;一窍不通&lt;/strong&gt;,到如今能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;搭博客  &lt;/li&gt;
&lt;li&gt;配评论系统  &lt;/li&gt;
&lt;li&gt;折腾 Cloudflare 和图床  &lt;/li&gt;
&lt;li&gt;用 Git 管理项目  &lt;/li&gt;
&lt;li&gt;甚至亲手改写前端页面&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;哪怕是 &lt;strong&gt;现学现用、边查边做、解决不了就问 AI&lt;/strong&gt;，&lt;br&gt;这个 &lt;strong&gt;“从零到一”&lt;/strong&gt; 的过程，&lt;br&gt;就是最让人上头、也最有成就感的地方。&lt;/p&gt;
&lt;p&gt;很多个夜晚，我都一搞就到天亮，&lt;br&gt;&lt;strong&gt;完全沉浸在专注与创造的喜悦中。&lt;/strong&gt;&lt;br&gt;那种满足感，是其他事情难以带来的。&lt;/p&gt;
&lt;h3&gt;🌼🍶 欲买桂花同载酒，终不似，少年游。&lt;/h3&gt;
&lt;p&gt;年少的轻狂与热爱，终究会被时间温柔收起，&lt;br&gt;但只要我们还在为热爱的事投入时间，&lt;br&gt;那份“少年气”，就从未真正离开过。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;❤️ 最后，&lt;/h3&gt;
&lt;p&gt;感谢那个愿意折腾、肯深夜啃文档的自己，&lt;br&gt;也希望看到这篇文章的你，&lt;br&gt;也能勇敢开启，属于你的探索之旅。✨&lt;/p&gt;
&lt;p&gt;&lt;Success&gt;想折腾？那就现在开始吧。你会发现，这条路其实很有趣。&lt;/Success&gt;&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sun, 27 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🚀 Data Struct Sort</title><link>https://hub.xiaozhangya.xin/blog/sort/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/sort/</guid><description>数据结构中的排序算法介绍，包括快速排序、堆排序和归并排序的实现方法。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/sort/&quot;&gt;https://hub.xiaozhangya.xin/blog/sort/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🚀 Data Struct Sort&lt;/h1&gt;
&lt;h2&gt;快速排序&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;list = [1, 6, 9, 2, 5, 0, 7, 3]
def quickSort(list, low, high):
    if (low &amp;lt; high):
        pivot = huafen(list, low, high) # 取基准
        quickSort(list, low, pivot - 1) #左子区
        quickSort(list, pivot + 1, high) #右子区
def huafen(list, low, high):
    pivot = list[low] #定基准
    # 判断是否有小于pivot的值，没有则往左以此检查
    while(low &amp;lt; high and list[high] &amp;gt; pivot):
        high -= 1
    list[low] = list[high]
    # 判断是否有大于pivot的值，没有则往右以此检查
    while(low &amp;lt; high and list[low] &amp;lt;= pivot):
        low += 1
    list[high] = list[low]
    # 放回pivot (因为最后low=high，所以这里写low或者是high都相同)
    list[low] = pivot
    # 返回基准索引
    return low
if __name__ == &amp;quot;__main__&amp;quot;:
    print(&amp;#39;排序前：&amp;#39;, list)
    quickSort(list, 0, len(list) - 1)
    print(&amp;#39;排序后：&amp;#39;, list)

排序前： [1, 6, 9, 2, 5, 0, 7, 3]
排序后： [0, 1, 2, 3, 5, 6, 7, 9]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;
// 划分函数（类似于 Python 的 huafen）
int partition(int arr[], int low, int high) {
    int pivot = arr[low];   // 选择第一个元素作为基准
    while (low &amp;lt; high) {
        // 从右往左找比 pivot 小的元素
        while (low &amp;lt; high &amp;amp;&amp;amp; arr[high] &amp;gt; pivot) {
            high--;
        }
        arr[low] = arr[high];  // 把小的值移到左侧
        // 从左往右找比 pivot 大的元素
        while (low &amp;lt; high &amp;amp;&amp;amp; arr[low] &amp;lt;= pivot) {
            low++;
        }
        arr[high] = arr[low];  // 把大的值移到右侧
    }

    // 放回 pivot
    arr[low] = pivot;
    return low;  // 返回基准索引
}

// 快速排序递归实现
void quickSort(int arr[], int low, int high) {
    if (low &amp;lt; high) {
        int pivot = partition(arr, low, high);  // 划分
        quickSort(arr, low, pivot - 1);  // 递归排序左侧
        quickSort(arr, pivot + 1, high); // 递归排序右侧
    }
}
// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i &amp;lt; size; i++) {
        printf(&amp;quot;%d &amp;quot;, arr[i]);
    }
    printf(&amp;quot;\n&amp;quot;);
}
// 主函数
int main() {
    int arr[] = {1, 6, 9, 2, 5, 0, 7, 3};
    int size = sizeof(arr) / sizeof(arr[0]);
    printf(&amp;quot;排序前：&amp;quot;);
    printArray(arr, size);

    quickSort(arr, 0, size - 1);

    printf(&amp;quot;排序后：&amp;quot;);
    printArray(arr, size);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;堆排序&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// 建立大根堆
void BuildMaxHeap(int A[], int len){
    for(int i = len / 2;i &amp;gt; 0;i--)  // 从后往前调整所有非终端结点
        HeadAdjust(A, i, len);
}

// 将以K为根的字树调整为大根堆
void HeadAdjust(int A[],int k,int len){
    A[0] = A[k];                        // A[0]暂存子树的根节点
    for(int i = 2 * k;i &amp;lt;= len;i*=2){   // 沿key较大的子结点向下筛选
        if(i &amp;lt; len &amp;amp;&amp;amp; A[i] &amp;lt; A[i+1])
            i++;                        // 取key较大的子结点下标
        if(A[0] &amp;gt;= A[i])    break;      // 筛选结果
        else{
            A[k] = A[i];                // 将A[i]调整到双亲结点上
            k = i;                      // 修改k值，以便继续向下筛选
        }
    }
    A[k] = A[0];                        // 被筛选结点的值放入最终位置
}
    
// 堆排序的完整逻辑
void HeapSort(int A[], int len){
    BuildMaxHeap(int A[], int len);
    for (int i=len;i&amp;gt;1;i--){
        swap(A[i], A[1]);
        HeadAdjust(A,1,i-1);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;归并排序&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int *B = (int *)malloc(n*sizeof(int));  //辅助数组B
// A[low~mid]和A[mid+1~high]各自有序，将两部分进行合并
void Merge(int A[], int low, int mid, int high){
    int i, j, k;
    // 将A中所有元素复制到B中
    for(k=low;k&amp;lt;=high;k++){
        B[k] = A[k]；
    }
    for(i=low,j=mid+1,k=i;i&amp;lt;=mid&amp;amp;&amp;amp;j&amp;lt;=high;k++){
        if(B[i]&amp;lt;=B[j])
            A[k] = B[i++];
        else
            A[k] = B[j++];
    }
    while(i&amp;lt;=mid)   A[k] = B[i++];
    while(j&amp;lt;=high)  A[k] = B[j++];
}

void MergeSort(int A[], int low, int high){
    if(low&amp;lt;high){
        int mid = (low+high) / 2;   // 从中间划分
        MergeSort(A, low, mid);     // 对左半部分归并排序
        MergeSort(A, mid+1,high);   // 对右半部分归并排序
        Merge(A,low,mid,high);      // 归并
    }
}

// 思路：调用 MergeSort 函数将数组划分为两部分，依此递归调用 MergeSort 函数，将左半部分排序好后，对右半部分进行排序，最后将排序好的两部分进行归并排序
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Fri, 25 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🎉 鬼灭之刃全季动画及剧场版资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/gui_mie_zhi_ren/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/gui_mie_zhi_ren/</guid><description>鬼灭之刃4K BD版，非常适合收藏！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/gui_mie_zhi_ren/&quot;&gt;https://hub.xiaozhangya.xin/blog/gui_mie_zhi_ren/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🎴 鬼灭之刃（Demon Slayer: Kimetsu no Yaiba）&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/post/s2UY49Dr.png&quot; alt=&quot;主封面图&quot;&gt;
&lt;img src=&quot;https://img.xiaozhangya.xin/file/post/g0v0YdKW.png&quot; alt=&quot;screen&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：冒险 · 黑暗奇幻 · 武术动画  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作&lt;/strong&gt;：Ufotable（根据 TMDB）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;导演&lt;/strong&gt;：外崎春雄（Haruo Sotozaki）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播&lt;/strong&gt;：2019‑04‑06 至 2024‑06‑30，TV 动画共 4 季、63 集  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;声优&lt;/strong&gt;：花江夏树（炭治郎，63 集）、鬼头明里（祢豆子，63 集）、下野纮（善逸，54 集）、松冈祯丞（伊之助，53 集）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🗡 故事情节&lt;/h2&gt;
&lt;p&gt;大正时代，少年竈門炭治郎回家后发现家人被鬼屠杀，妹妹祢豆子变成恶鬼。为救妹回人形并复仇，他加入鬼杀队，学习呼吸法踏上斩鬼之路。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎬 动画各季信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;篇章名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第1季&lt;/td&gt;
&lt;td&gt;立志篇（Tanjiro&amp;#39;s Origin）&lt;/td&gt;
&lt;td&gt;2019‑04‑06 ~ 2019‑09‑28&lt;/td&gt;
&lt;td&gt;26 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第2季&lt;/td&gt;
&lt;td&gt;无限列车篇（Mugen Train Arc）&lt;/td&gt;
&lt;td&gt;2021‑10‑10 ~ 2021‑11‑28&lt;/td&gt;
&lt;td&gt;7 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第3季&lt;/td&gt;
&lt;td&gt;游郭篇（Entertainment District）&lt;/td&gt;
&lt;td&gt;2021‑12‑05 ~ 2022‑02‑13&lt;/td&gt;
&lt;td&gt;11 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第4季&lt;/td&gt;
&lt;td&gt;刀匠村篇（Swordsmith Village）&lt;/td&gt;
&lt;td&gt;2023‑04‑09 ~ 2023‑06‑18&lt;/td&gt;
&lt;td&gt;11 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第5季&lt;/td&gt;
&lt;td&gt;柱训练篇（Hashira Training）&lt;/td&gt;
&lt;td&gt;2024‑05‑12 ~ 2024‑06‑30&lt;/td&gt;
&lt;td&gt;8 集&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;🎥 剧场版 &amp;amp; 特别篇&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;无限列车篇&lt;/strong&gt;（2020）：票房超 5.07 亿美元，是历史最卖座动画电影之一。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;刀匠村篇纪念版&lt;/strong&gt;（2023）和&lt;strong&gt;柱训练特别篇&lt;/strong&gt;（2024）：TV 内容的剧场版浓缩。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无限城篇三部曲&lt;/strong&gt;：首部《猗窝座再袭》将于 2025‑07‑18 在日本上映，北美预计于 2025年秋季上映。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;📺 动画各季详情&lt;/h3&gt;
&lt;div style=&quot;display:flex; gap:10px; flex-wrap:wrap;&quot;&gt;
  &lt;a href=&quot;https://www.themoviedb.org/tv/85937/season/1?language=zh-CN&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E7%AB%8B%E5%BF%97%E7%AF%87-TMDB-blue?style=for-the-badge&amp;logo=themoviedb&quot; alt=&quot;立志篇&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://www.themoviedb.org/tv/85937/season/2?language=zh-CN&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E6%97%A0%E9%99%90%E5%88%97%E8%BD%A6%E7%AF%87-TMDB-brightgreen?style=for-the-badge&amp;logo=themoviedb&quot; alt=&quot;无限列车篇&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://www.themoviedb.org/tv/85937/season/3?language=zh-CN&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E6%B8%B8%E9%83%AD%E7%AF%87-TMDB-orange?style=for-the-badge&amp;logo=themoviedb&quot; alt=&quot;游郭篇&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://www.themoviedb.org/tv/85937/season/4?language=zh-CN&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E5%88%80%E5%8C%A0%E6%9D%91%E7%AF%87-TMDB-red?style=for-the-badge&amp;logo=themoviedb&quot; alt=&quot;刀匠村篇&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://www.themoviedb.org/tv/85937/season/5?language=zh-CN&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E6%9F%B1%E8%AE%AD%E7%BB%83%E7%AF%87-TMDB-yellow?style=for-the-badge&amp;logo=themoviedb&quot; alt=&quot;柱训练篇&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;
---
### 🎥 剧场版 &amp; 最新资讯

&lt;div style=&quot;display:flex; gap:12px; flex-wrap: wrap; align-items: center;&quot;&gt;
  &lt;a href=&quot;https://zh.wikipedia.org/wiki/%E9%AC%BC%E6%BB%85%E4%B9%8B%E5%88%83%E5%8A%87%E5%A0%B4%E7%89%88_%E7%84%A1%E9%99%90%E5%88%97%E8%BB%8A%E7%AF%87#%E7%A5%A8%E6%88%BF&quot; target=&quot;_blank&quot; rel=&quot;https://hub.xiaozhangya.xin/noopener%20noreferrer&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E7%A5%A8%E6%88%BF%E6%95%B0%E6%8D%AE-BoxOfficeMojo-blue?style=for-the-badge&amp;logo=boxofficemojo&quot; alt=&quot;无限列车票房&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://youtu.be/ZfIXXgqxVn8?si=v8lN_LiVlMJv0NCC&quot; target=&quot;_blank&quot; rel=&quot;https://hub.xiaozhangya.xin/noopener%20noreferrer&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E4%B8%8A%E6%98%A0%E9%A2%84%E5%91%8A-YouTube-red?style=for-the-badge&amp;logo=youtube&quot; alt=&quot;上映预告&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://www.ufotable.com/works/demonslayer&quot; target=&quot;_blank&quot; rel=&quot;https://hub.xiaozhangya.xin/noopener%20noreferrer&quot;&gt;
    &lt;img src=&quot;https://img.shields.io/badge/%E5%B9%95%E5%90%8E%E5%88%B6%E4%BD%9C-Ufotable-9cf?style=for-the-badge&amp;logo=artstation&quot; alt=&quot;幕后制作&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;
---
## 📥 资源下载

&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/cf0cf7409bd9&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;点击上方绿色按钮即可获取鬼灭之刃相关资源，夸克！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;p&gt;《鬼灭之刃》凭借其打动人心的剧情、Ufotable 顶级制作以及震撼战斗，成为近年来最受瞩目的动画之一。从「立志篇」到「无限城篇」三部剧场章，其故事正在迎来终极高潮。无论你是长期粉丝还是新入坑观众，希望这篇 Markdown 能帮助你快速搭建专业博客——配合视觉素材、互动设计及后续系列规划，你的文章将更具吸引力与粘性。&lt;/p&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 24 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🌟通过 Cloudflare 的 worker 、Pages 搭建永久免费的VPN，真正无限流量!🚀</title><link>https://hub.xiaozhangya.xin/blog/edgetunnel-vpn/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/edgetunnel-vpn/</guid><description>通过Cloudflare worker、page来收集可用的免费节点，速度甚至超过一些付费节点！！！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/edgetunnel-vpn/&quot;&gt;https://hub.xiaozhangya.xin/blog/edgetunnel-vpn/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;通过 Cloudflare 的 worker 、Pages 搭建永久免费的VPN，真正无限流量!&lt;/h1&gt;
&lt;p&gt;今天我们主要来说下如果通过 Cloudflare 的 worker 、Pages 搭建永久免费的VPN，真正做到无限流量！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.freedidi.com/wp-content/uploads/2024/12/8597cb298a20241211155448-2371x1440.webp&quot; alt=&quot;8597cb298a20241211155448&quot;&gt;&lt;/p&gt;
&lt;h2&gt;1、首选你需要注册一个免费的 Cloudflare 账号 【&lt;strong&gt;&lt;a href=&quot;https://dash.cloudflare.com/sign-up&quot;&gt;点击前往&lt;/a&gt;&lt;/strong&gt;】&lt;/h2&gt;
&lt;h2&gt;2、接着你需要准备好开源软件：V2rayN，因为一会要用到 【&lt;strong&gt;&lt;a href=&quot;https://github.com/2dust/v2rayN&quot;&gt;点击下载&lt;/a&gt;&lt;/strong&gt;】&lt;/h2&gt;
&lt;h2&gt;3、在Cloudflare 上创建worker，并填写下面的代码，这个代码来自CM在【 &lt;strong&gt;&lt;a href=&quot;https://github.com/cmliu/edgetunnel?tab=readme-ov-file&quot;&gt;GitHub&lt;/a&gt;&lt;/strong&gt; 】社区的开源项目，代码已经内置IP优选和代理功能，自带动态的UUID，可以大大减少手动配置过程，非常适合新手和特殊用户。&lt;/h2&gt;
&lt;p&gt;**注意：**创建的worker项目名称最好使用系统默认的，别自定义，以免被系统识别到特殊字符而被屏蔽。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;获取Cloudflare 的 worker 开源代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cmliu/edgetunnel/blob/main/_worker.js&quot;&gt;加密版&lt;/a&gt;：【&lt;strong&gt;&lt;a href=&quot;https://github.com/cmliu/edgetunnel/blob/main/_worker.js&quot;&gt;点击获取&lt;/a&gt;&lt;/strong&gt;】&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cmliu/edgetunnel/blob/main/%E6%98%8E%E6%96%87%E6%BA%90%E7%A0%81.js&quot;&gt;明文版&lt;/a&gt;：【&lt;strong&gt;&lt;a href=&quot;https://github.com/cmliu/edgetunnel/blob/main/%E6%98%8E%E6%96%87%E6%BA%90%E7%A0%81.js&quot;&gt;点击获取&lt;/a&gt;&lt;/strong&gt;】&lt;/p&gt;
&lt;p&gt;或者直接复制下方的代码即可！&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;import { connect } from &amp;#39;cloudflare:sockets&amp;#39;;

let userID = &amp;#39;&amp;#39;;
let proxyIP = &amp;#39;&amp;#39;;
//let sub = &amp;#39;&amp;#39;;
let subConverter = &amp;#39;SUBAPI.fxxk.dedyn.io&amp;#39;;
let subConfig = &amp;quot;https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiMode.ini&amp;quot;;
let subProtocol = &amp;#39;https&amp;#39;;
let subEmoji = &amp;#39;true&amp;#39;;
let socks5Address = &amp;#39;&amp;#39;;
let parsedSocks5Address = {};
let enableSocks = false;

let fakeUserID;
let fakeHostName;
let noTLS = &amp;#39;false&amp;#39;;
const expire = 4102329600;//2099-12-31
let proxyIPs;
let socks5s;
let go2Socks5s = [
  &amp;#39;*ttvnw.net&amp;#39;,
  &amp;#39;*tapecontent.net&amp;#39;,
  &amp;#39;*cloudatacdn.com&amp;#39;,
  &amp;#39;*.loadshare.org&amp;#39;,
];
let addresses = [];
let addressesapi = [];
let addressesnotls = [];
let addressesnotlsapi = [];
let addressescsv = [];
let DLS = 8;
let remarkIndex = 1;//CSV备注所在列偏移量
let FileName = atob(&amp;#39;ZWRnZXR1bm5lbA==&amp;#39;);
let BotToken;
let ChatID;
let proxyhosts = [];
let proxyhostsURL = &amp;#39;&amp;#39;;
let RproxyIP = &amp;#39;false&amp;#39;;
let httpsPorts = [&amp;quot;2053&amp;quot;, &amp;quot;2083&amp;quot;, &amp;quot;2087&amp;quot;, &amp;quot;2096&amp;quot;, &amp;quot;8443&amp;quot;];
let 有效时间 = 7;
let 更新时间 = 3;
let userIDLow;
let userIDTime = &amp;quot;&amp;quot;;
let proxyIPPool = [];
let path = &amp;#39;/?ed=2560&amp;#39;;
let 动态UUID;
let link = [];
let banHosts = [atob(&amp;#39;c3BlZWQuY2xvdWRmbGFyZS5jb20=&amp;#39;)];
export default {
  async fetch(request, env, ctx) {
    try {
      const UA = request.headers.get(&amp;#39;User-Agent&amp;#39;) || &amp;#39;null&amp;#39;;
      const userAgent = UA.toLowerCase();
      userID = env.UUID || env.uuid || env.PASSWORD || env.pswd || userID;
      if (env.KEY || env.TOKEN || (userID &amp;amp;&amp;amp; !isValidUUID(userID))) {
        动态UUID = env.KEY || env.TOKEN || userID;
        有效时间 = Number(env.TIME) || 有效时间;
        更新时间 = Number(env.UPTIME) || 更新时间;
        const userIDs = await 生成动态UUID(动态UUID);
        userID = userIDs[0];
        userIDLow = userIDs[1];
      }

      if (!userID) {
        return new Response(&amp;#39;请设置你的UUID变量，或尝试重试部署，检查变量是否生效？&amp;#39;, {
          status: 404,
          headers: {
            &amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain;charset=utf-8&amp;quot;,
          }
        });
      }
      const currentDate = new Date();
      currentDate.setHours(0, 0, 0, 0);
      const timestamp = Math.ceil(currentDate.getTime() / 1000);
      const fakeUserIDMD5 = await 双重哈希(`${userID}${timestamp}`);
      fakeUserID = [
        fakeUserIDMD5.slice(0, 8),
        fakeUserIDMD5.slice(8, 12),
        fakeUserIDMD5.slice(12, 16),
        fakeUserIDMD5.slice(16, 20),
        fakeUserIDMD5.slice(20)
      ].join(&amp;#39;-&amp;#39;);

      fakeHostName = `${fakeUserIDMD5.slice(6, 9)}.${fakeUserIDMD5.slice(13, 19)}`;

      proxyIP = env.PROXYIP || env.proxyip || proxyIP;
      proxyIPs = await 整理(proxyIP);
      proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];

      socks5Address = env.SOCKS5 || socks5Address;
      socks5s = await 整理(socks5Address);
      socks5Address = socks5s[Math.floor(Math.random() * socks5s.length)];
      socks5Address = socks5Address.split(&amp;#39;//&amp;#39;)[1] || socks5Address;
      if (env.GO2SOCKS5) go2Socks5s = await 整理(env.GO2SOCKS5);
      if (env.CFPORTS) httpsPorts = await 整理(env.CFPORTS);
      if (env.BAN) banHosts = await 整理(env.BAN);
      if (socks5Address) {
        try {
          parsedSocks5Address = socks5AddressParser(socks5Address);
          RproxyIP = env.RPROXYIP || &amp;#39;false&amp;#39;;
          enableSocks = true;
        } catch (err) {
          let e = err;
          console.log(e.toString());
          RproxyIP = env.RPROXYIP || !proxyIP ? &amp;#39;true&amp;#39; : &amp;#39;false&amp;#39;;
          enableSocks = false;
        }
      } else {
        RproxyIP = env.RPROXYIP || !proxyIP ? &amp;#39;true&amp;#39; : &amp;#39;false&amp;#39;;
      }

      const upgradeHeader = request.headers.get(&amp;#39;Upgrade&amp;#39;);
      const url = new URL(request.url);
      if (!upgradeHeader || upgradeHeader !== &amp;#39;websocket&amp;#39;) {
        if (env.ADD) addresses = await 整理(env.ADD);
        if (env.ADDAPI) addressesapi = await 整理(env.ADDAPI);
        if (env.ADDNOTLS) addressesnotls = await 整理(env.ADDNOTLS);
        if (env.ADDNOTLSAPI) addressesnotlsapi = await 整理(env.ADDNOTLSAPI);
        if (env.ADDCSV) addressescsv = await 整理(env.ADDCSV);
        DLS = Number(env.DLS) || DLS;
        remarkIndex = Number(env.CSVREMARK) || remarkIndex;
        BotToken = env.TGTOKEN || BotToken;
        ChatID = env.TGID || ChatID;
        FileName = env.SUBNAME || FileName;
        subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji;
        if (subEmoji == &amp;#39;0&amp;#39;) subEmoji = &amp;#39;false&amp;#39;;
        if (env.LINK) link = await 整理(env.LINK);
        let sub = env.SUB || &amp;#39;&amp;#39;;
        subConverter = env.SUBAPI || subConverter;
        if (subConverter.includes(&amp;quot;http://&amp;quot;)) {
          subConverter = subConverter.split(&amp;quot;//&amp;quot;)[1];
          subProtocol = &amp;#39;http&amp;#39;;
        } else {
          subConverter = subConverter.split(&amp;quot;//&amp;quot;)[1] || subConverter;
        }
        subConfig = env.SUBCONFIG || subConfig;
        if (url.searchParams.has(&amp;#39;sub&amp;#39;) &amp;amp;&amp;amp; url.searchParams.get(&amp;#39;sub&amp;#39;) !== &amp;#39;&amp;#39;) sub = url.searchParams.get(&amp;#39;sub&amp;#39;);
        if (url.searchParams.has(&amp;#39;notls&amp;#39;)) noTLS = &amp;#39;true&amp;#39;;

        if (url.searchParams.has(&amp;#39;proxyip&amp;#39;)) {
          path = `/?ed=2560&amp;amp;proxyip=${url.searchParams.get(&amp;#39;proxyip&amp;#39;)}`;
          RproxyIP = &amp;#39;false&amp;#39;;
        } else if (url.searchParams.has(&amp;#39;socks5&amp;#39;)) {
          path = `/?ed=2560&amp;amp;socks5=${url.searchParams.get(&amp;#39;socks5&amp;#39;)}`;
          RproxyIP = &amp;#39;false&amp;#39;;
        } else if (url.searchParams.has(&amp;#39;socks&amp;#39;)) {
          path = `/?ed=2560&amp;amp;socks5=${url.searchParams.get(&amp;#39;socks&amp;#39;)}`;
          RproxyIP = &amp;#39;false&amp;#39;;
        }

        const 路径 = url.pathname.toLowerCase();
        if (路径 == &amp;#39;/&amp;#39;) {
          if (env.URL302) return Response.redirect(env.URL302, 302);
          else if (env.URL) return await 代理URL(env.URL, url);
          else return new Response(JSON.stringify(request.cf, null, 4), {
            status: 200,
            headers: {
              &amp;#39;content-type&amp;#39;: &amp;#39;application/json&amp;#39;,
            },
          });
        } else if (路径 == `/${fakeUserID}`) {
          const fakeConfig = await 生成配置信息(userID, request.headers.get(&amp;#39;Host&amp;#39;), sub, &amp;#39;CF-Workers-SUB&amp;#39;, RproxyIP, url, env);
          return new Response(`${fakeConfig}`, { status: 200 });
        } else if (url.pathname == `/${动态UUID}/edit` || 路径 == `/${userID}/edit`) {
          const html = await KV(request, env);
          return html;
        } else if (url.pathname == `/${动态UUID}` || 路径 == `/${userID}`) {
          await sendMessage(`#获取订阅 ${FileName}`, request.headers.get(&amp;#39;CF-Connecting-IP&amp;#39;), `UA: ${UA}&amp;lt;/tg-spoiler&amp;gt;\n域名: ${url.hostname}\n&amp;lt;tg-spoiler&amp;gt;入口: ${url.pathname + url.search}&amp;lt;/tg-spoiler&amp;gt;`);
          const 维列斯Config = await 生成配置信息(userID, request.headers.get(&amp;#39;Host&amp;#39;), sub, UA, RproxyIP, url, env);
          const now = Date.now();
          //const timestamp = Math.floor(now / 1000);
          const today = new Date(now);
          today.setHours(0, 0, 0, 0);
          const UD = Math.floor(((now - today.getTime()) / 86400000) * 24 * 1099511627776 / 2);
          let pagesSum = UD;
          let workersSum = UD;
          let total = 24 * 1099511627776;

          if (userAgent &amp;amp;&amp;amp; userAgent.includes(&amp;#39;mozilla&amp;#39;)) {
            return new Response(`&amp;lt;div style=&amp;quot;font-size:13px;&amp;quot;&amp;gt;${维列斯Config}&amp;lt;/div&amp;gt;`, {
              status: 200,
              headers: {
                &amp;quot;Content-Type&amp;quot;: &amp;quot;text/html;charset=utf-8&amp;quot;,
                &amp;quot;Profile-Update-Interval&amp;quot;: &amp;quot;6&amp;quot;,
                &amp;quot;Subscription-Userinfo&amp;quot;: `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
                &amp;quot;Cache-Control&amp;quot;: &amp;quot;no-store&amp;quot;,
              }
            });
          } else {
            return new Response(`${维列斯Config}`, {
              status: 200,
              headers: {
                &amp;quot;Content-Disposition&amp;quot;: `attachment; filename=${FileName}; filename*=utf-8&amp;#39;&amp;#39;${encodeURIComponent(FileName)}`,
                &amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain;charset=utf-8&amp;quot;,
                &amp;quot;Profile-Update-Interval&amp;quot;: &amp;quot;6&amp;quot;,
                &amp;quot;Subscription-Userinfo&amp;quot;: `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`,
              }
            });
          }
        } else {
          if (env.URL302) return Response.redirect(env.URL302, 302);
          else if (env.URL) return await 代理URL(env.URL, url);
          else return new Response(&amp;#39;不用怀疑！你UUID就是错的！！！&amp;#39;, { status: 404 });
        }
      } else {
        socks5Address = url.searchParams.get(&amp;#39;socks5&amp;#39;) || socks5Address;
        if (new RegExp(&amp;#39;/socks5=&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname)) socks5Address = url.pathname.split(&amp;#39;5=&amp;#39;)[1];
        else if (new RegExp(&amp;#39;/socks://&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname) || new RegExp(&amp;#39;/socks5://&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname)) {
          socks5Address = url.pathname.split(&amp;#39;://&amp;#39;)[1].split(&amp;#39;#&amp;#39;)[0];
          if (socks5Address.includes(&amp;#39;@&amp;#39;)) {
            let userPassword = socks5Address.split(&amp;#39;@&amp;#39;)[0];
            const base64Regex = /^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i;
            if (base64Regex.test(userPassword) &amp;amp;&amp;amp; !userPassword.includes(&amp;#39;:&amp;#39;)) userPassword = atob(userPassword);
            socks5Address = `${userPassword}@${socks5Address.split(&amp;#39;@&amp;#39;)[1]}`;
          }
        }

        if (socks5Address) {
          try {
            parsedSocks5Address = socks5AddressParser(socks5Address);
            enableSocks = true;
          } catch (err) {
            let e = err;
            console.log(e.toString());
            enableSocks = false;
          }
        } else {
          enableSocks = false;
        }

        if (url.searchParams.has(&amp;#39;proxyip&amp;#39;)) {
          proxyIP = url.searchParams.get(&amp;#39;proxyip&amp;#39;);
          enableSocks = false;
        } else if (new RegExp(&amp;#39;/proxyip=&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname)) {
          proxyIP = url.pathname.toLowerCase().split(&amp;#39;/proxyip=&amp;#39;)[1];
          enableSocks = false;
        } else if (new RegExp(&amp;#39;/proxyip.&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname)) {
          proxyIP = `proxyip.${url.pathname.toLowerCase().split(&amp;quot;/proxyip.&amp;quot;)[1]}`;
          enableSocks = false;
        } else if (new RegExp(&amp;#39;/pyip=&amp;#39;, &amp;#39;i&amp;#39;).test(url.pathname)) {
          proxyIP = url.pathname.toLowerCase().split(&amp;#39;/pyip=&amp;#39;)[1];
          enableSocks = false;
        }

        return await 维列斯OverWSHandler(request);
      }
    } catch (err) {
      let e = err;
      return new Response(e.toString());
    }
  },
};

async function 维列斯OverWSHandler(request) {

  // @ts-ignore
  const webSocketPair = new WebSocketPair();
  const [client, webSocket] = Object.values(webSocketPair);

  // 接受 WebSocket 连接
  webSocket.accept();

  let address = &amp;#39;&amp;#39;;
  let portWithRandomLog = &amp;#39;&amp;#39;;
  // 日志函数，用于记录连接信息
  const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) =&amp;gt; {
    console.log(`[${address}:${portWithRandomLog}] ${info}`, event || &amp;#39;&amp;#39;);
  };
  // 获取早期数据头部，可能包含了一些初始化数据
  const earlyDataHeader = request.headers.get(&amp;#39;sec-websocket-protocol&amp;#39;) || &amp;#39;&amp;#39;;

  // 创建一个可读的 WebSocket 流，用于接收客户端数据
  const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log);

  // 用于存储远程 Socket 的包装器
  let remoteSocketWapper = {
    value: null,
  };
  // 标记是否为 DNS 查询
  let isDns = false;

  // WebSocket 数据流向远程服务器的管道
  readableWebSocketStream.pipeTo(new WritableStream({
    async write(chunk, controller) {
      if (isDns) {
        // 如果是 DNS 查询，调用 DNS 处理函数
        return await handleDNSQuery(chunk, webSocket, null, log);
      }
      if (remoteSocketWapper.value) {
        // 如果已有远程 Socket，直接写入数据
        const writer = remoteSocketWapper.value.writable.getWriter()
        await writer.write(chunk);
        writer.releaseLock();
        return;
      }

      // 处理 维列斯 协议头部
      const {
        hasError,
        message,
        addressType,
        portRemote = 443,
        addressRemote = &amp;#39;&amp;#39;,
        rawDataIndex,
        维列斯Version = new Uint8Array([0, 0]),
        isUDP,
      } = process维列斯Header(chunk, userID);
      // 设置地址和端口信息，用于日志
      address = addressRemote;
      portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? &amp;#39;udp &amp;#39; : &amp;#39;tcp &amp;#39;} `;
      if (hasError) {
        // 如果有错误，抛出异常
        throw new Error(message);
        return;
      }
      // 如果是 UDP 且端口不是 DNS 端口（53），则关闭连接
      if (isUDP) {
        if (portRemote === 53) {
          isDns = true;
        } else {
          throw new Error(&amp;#39;UDP 代理仅对 DNS（53 端口）启用&amp;#39;);
          return;
        }
      }
      // 构建 维列斯 响应头部
      const 维列斯ResponseHeader = new Uint8Array([维列斯Version[0], 0]);
      // 获取实际的客户端数据
      const rawClientData = chunk.slice(rawDataIndex);

      if (isDns) {
        // 如果是 DNS 查询，调用 DNS 处理函数
        return handleDNSQuery(rawClientData, webSocket, 维列斯ResponseHeader, log);
      }
      // 处理 TCP 出站连接
      if (!banHosts.includes(addressRemote)) {
        log(`处理 TCP 出站连接 ${addressRemote}:${portRemote}`);
        handleTCPOutBound(remoteSocketWapper, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log);
      } else {
        throw new Error(`黑名单关闭 TCP 出站连接 ${addressRemote}:${portRemote}`);
      }
    },
    close() {
      log(`readableWebSocketStream 已关闭`);
    },
    abort(reason) {
      log(`readableWebSocketStream 已中止`, JSON.stringify(reason));
    },
  })).catch((err) =&amp;gt; {
    log(&amp;#39;readableWebSocketStream 管道错误&amp;#39;, err);
  });

  // 返回一个 WebSocket 升级的响应
  return new Response(null, {
    status: 101,
    // @ts-ignore
    webSocket: client,
  });
}

async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log,) {
  async function useSocks5Pattern(address) {
    if (go2Socks5s.includes(atob(&amp;#39;YWxsIGlu&amp;#39;)) || go2Socks5s.includes(atob(&amp;#39;Kg==&amp;#39;))) return true;
    return go2Socks5s.some(pattern =&amp;gt; {
      let regexPattern = pattern.replace(/\*/g, &amp;#39;.*&amp;#39;);
      let regex = new RegExp(`^${regexPattern}$`, &amp;#39;i&amp;#39;);
      return regex.test(address);
    });
  }

  async function connectAndWrite(address, port, socks = false) {
    log(`connected to ${address}:${port}`);
    //if (/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(address)) address = `${atob(&amp;#39;d3d3Lg==&amp;#39;)}${address}${atob(&amp;#39;LmlwLjA5MDIyNy54eXo=&amp;#39;)}`;
    // 如果指定使用 SOCKS5 代理，则通过 SOCKS5 协议连接；否则直接连接
    const tcpSocket = socks ? await socks5Connect(addressType, address, port, log)
      : connect({
        hostname: address,
        port: port,
      });
    remoteSocket.value = tcpSocket;
    //log(`connected to ${address}:${port}`);
    const writer = tcpSocket.writable.getWriter();
    // 首次写入，通常是 TLS 客户端 Hello 消息
    await writer.write(rawClientData);
    writer.releaseLock();
    return tcpSocket;
  }

  /**
   * 重试函数：当 Cloudflare 的 TCP Socket 没有传入数据时，我们尝试重定向 IP
   * 这可能是因为某些网络问题导致的连接失败
   */
  async function retry() {
    if (enableSocks) {
      // 如果启用了 SOCKS5，通过 SOCKS5 代理重试连接
      tcpSocket = await connectAndWrite(addressRemote, portRemote, true);
    } else {
      // 否则，尝试使用预设的代理 IP（如果有）或原始地址重试连接
      if (!proxyIP || proxyIP == &amp;#39;&amp;#39;) {
        proxyIP = atob(`UFJPWFlJUC50cDEuZnh4ay5kZWR5bi5pbw==`);
      } else if (proxyIP.includes(&amp;#39;]:&amp;#39;)) {
        portRemote = proxyIP.split(&amp;#39;]:&amp;#39;)[1] || portRemote;
        proxyIP = proxyIP.split(&amp;#39;]:&amp;#39;)[0] || proxyIP;
      } else if (proxyIP.split(&amp;#39;:&amp;#39;).length === 2) {
        portRemote = proxyIP.split(&amp;#39;:&amp;#39;)[1] || portRemote;
        proxyIP = proxyIP.split(&amp;#39;:&amp;#39;)[0] || proxyIP;
      }
      if (proxyIP.includes(&amp;#39;.tp&amp;#39;)) portRemote = proxyIP.split(&amp;#39;.tp&amp;#39;)[1].split(&amp;#39;.&amp;#39;)[0] || portRemote;
      tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote);
    }
    // 无论重试是否成功，都要关闭 WebSocket（可能是为了重新建立连接）
    tcpSocket.closed.catch(error =&amp;gt; {
      console.log(&amp;#39;retry tcpSocket closed error&amp;#39;, error);
    }).finally(() =&amp;gt; {
      safeCloseWebSocket(webSocket);
    })
    // 建立从远程 Socket 到 WebSocket 的数据流
    remoteSocketToWS(tcpSocket, webSocket, 维列斯ResponseHeader, null, log);
  }

  let useSocks = false;
  if (go2Socks5s.length &amp;gt; 0 &amp;amp;&amp;amp; enableSocks) useSocks = await useSocks5Pattern(addressRemote);
  // 首次尝试连接远程服务器
  let tcpSocket = await connectAndWrite(addressRemote, portRemote, useSocks);

  // 当远程 Socket 就绪时，将其传递给 WebSocket
  // 建立从远程服务器到 WebSocket 的数据流，用于将远程服务器的响应发送回客户端
  // 如果连接失败或无数据，retry 函数将被调用进行重试
  remoteSocketToWS(tcpSocket, webSocket, 维列斯ResponseHeader, retry, log);
}

function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) {
  // 标记可读流是否已被取消
  let readableStreamCancel = false;

  // 创建一个新的可读流
  const stream = new ReadableStream({
    // 当流开始时的初始化函数
    start(controller) {
      // 监听 WebSocket 的消息事件
      webSocketServer.addEventListener(&amp;#39;message&amp;#39;, (event) =&amp;gt; {
        // 如果流已被取消，不再处理新消息
        if (readableStreamCancel) {
          return;
        }
        const message = event.data;
        // 将消息加入流的队列中
        controller.enqueue(message);
      });

      // 监听 WebSocket 的关闭事件
      // 注意：这个事件意味着客户端关闭了客户端 -&amp;gt; 服务器的流
      // 但是，服务器 -&amp;gt; 客户端的流仍然打开，直到在服务器端调用 close()
      // WebSocket 协议要求在每个方向上都要发送单独的关闭消息，以完全关闭 Socket
      webSocketServer.addEventListener(&amp;#39;close&amp;#39;, () =&amp;gt; {
        // 客户端发送了关闭信号，需要关闭服务器端
        safeCloseWebSocket(webSocketServer);
        // 如果流未被取消，则关闭控制器
        if (readableStreamCancel) {
          return;
        }
        controller.close();
      });

      // 监听 WebSocket 的错误事件
      webSocketServer.addEventListener(&amp;#39;error&amp;#39;, (err) =&amp;gt; {
        log(&amp;#39;WebSocket 服务器发生错误&amp;#39;);
        // 将错误传递给控制器
        controller.error(err);
      });

      // 处理 WebSocket 0-RTT（零往返时间）的早期数据
      // 0-RTT 允许在完全建立连接之前发送数据，提高了效率
      const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
      if (error) {
        // 如果解码早期数据时出错，将错误传递给控制器
        controller.error(error);
      } else if (earlyData) {
        // 如果有早期数据，将其加入流的队列中
        controller.enqueue(earlyData);
      }
    },

    // 当使用者从流中拉取数据时调用
    pull(controller) {
      // 这里可以实现反压机制
      // 如果 WebSocket 可以在流满时停止读取，我们就可以实现反压
      // 参考：https://streams.spec.whatwg.org/#example-rs-push-backpressure
    },

    // 当流被取消时调用
    cancel(reason) {
      // 流被取消的几种情况：
      // 1. 当管道的 WritableStream 有错误时，这个取消函数会被调用，所以在这里处理 WebSocket 服务器的关闭
      // 2. 如果 ReadableStream 被取消，所有 controller.close/enqueue 都需要跳过
      // 3. 但是经过测试，即使 ReadableStream 被取消，controller.error 仍然有效
      if (readableStreamCancel) {
        return;
      }
      log(`可读流被取消，原因是 ${reason}`);
      readableStreamCancel = true;
      // 安全地关闭 WebSocket
      safeCloseWebSocket(webSocketServer);
    }
  });

  return stream;
}

// https://xtls.github.io/development/protocols/维列斯.html
// https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw

/**
 * 解析 维列斯 协议的头部数据
 * @param { ArrayBuffer} 维列斯Buffer 维列斯 协议的原始头部数据
 * @param {string} userID 用于验证的用户 ID
 * @returns {Object} 解析结果，包括是否有错误、错误信息、远程地址信息等
 */
function process维列斯Header(维列斯Buffer, userID) {
  // 检查数据长度是否足够（至少需要 24 字节）
  if (维列斯Buffer.byteLength &amp;lt; 24) {
    return {
      hasError: true,
      message: &amp;#39;invalid data&amp;#39;,
    };
  }

  // 解析 维列斯 协议版本（第一个字节）
  const version = new Uint8Array(维列斯Buffer.slice(0, 1));

  let isValidUser = false;
  let isUDP = false;

  // 验证用户 ID（接下来的 16 个字节）
  function isUserIDValid(userID, userIDLow, buffer) {
    const userIDArray = new Uint8Array(buffer.slice(1, 17));
    const userIDString = stringify(userIDArray);
    return userIDString === userID || userIDString === userIDLow;
  }

  // 使用函数验证
  isValidUser = isUserIDValid(userID, userIDLow, 维列斯Buffer);

  // 如果用户 ID 无效，返回错误
  if (!isValidUser) {
    return {
      hasError: true,
      message: `invalid user ${(new Uint8Array(维列斯Buffer.slice(1, 17)))}`,
    };
  }

  // 获取附加选项的长度（第 17 个字节）
  const optLength = new Uint8Array(维列斯Buffer.slice(17, 18))[0];
  // 暂时跳过附加选项

  // 解析命令（紧跟在选项之后的 1 个字节）
  // 0x01: TCP, 0x02: UDP, 0x03: MUX（多路复用）
  const command = new Uint8Array(
    维列斯Buffer.slice(18 + optLength, 18 + optLength + 1)
  )[0];

  // 0x01 TCP
  // 0x02 UDP
  // 0x03 MUX
  if (command === 1) {
    // TCP 命令，不需特殊处理
  } else if (command === 2) {
    // UDP 命令
    isUDP = true;
  } else {
    // 不支持的命令
    return {
      hasError: true,
      message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`,
    };
  }

  // 解析远程端口（大端序，2 字节）
  const portIndex = 18 + optLength + 1;
  const portBuffer = 维列斯Buffer.slice(portIndex, portIndex + 2);
  // port is big-Endian in raw data etc 80 == 0x005d
  const portRemote = new DataView(portBuffer).getUint16(0);

  // 解析地址类型和地址
  let addressIndex = portIndex + 2;
  const addressBuffer = new Uint8Array(
    维列斯Buffer.slice(addressIndex, addressIndex + 1)
  );

  // 地址类型：1-IPv4(4字节), 2-域名(可变长), 3-IPv6(16字节)
  const addressType = addressBuffer[0];
  let addressLength = 0;
  let addressValueIndex = addressIndex + 1;
  let addressValue = &amp;#39;&amp;#39;;

  switch (addressType) {
    case 1:
      // IPv4 地址
      addressLength = 4;
      // 将 4 个字节转为点分十进制格式
      addressValue = new Uint8Array(
        维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength)
      ).join(&amp;#39;.&amp;#39;);
      break;
    case 2:
      // 域名
      // 第一个字节是域名长度
      addressLength = new Uint8Array(
        维列斯Buffer.slice(addressValueIndex, addressValueIndex + 1)
      )[0];
      addressValueIndex += 1;
      // 解码域名
      addressValue = new TextDecoder().decode(
        维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength)
      );
      break;
    case 3:
      // IPv6 地址
      addressLength = 16;
      const dataView = new DataView(
        维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength)
      );
      // 每 2 字节构成 IPv6 地址的一部分
      const ipv6 = [];
      for (let i = 0; i &amp;lt; 8; i++) {
        ipv6.push(dataView.getUint16(i * 2).toString(16));
      }
      addressValue = ipv6.join(&amp;#39;:&amp;#39;);
      // seems no need add [] for ipv6
      break;
    default:
      // 无效的地址类型
      return {
        hasError: true,
        message: `invild addressType is ${addressType}`,
      };
  }

  // 确保地址不为空
  if (!addressValue) {
    return {
      hasError: true,
      message: `addressValue is empty, addressType is ${addressType}`,
    };
  }

  // 返回解析结果
  return {
    hasError: false,
    addressRemote: addressValue,  // 解析后的远程地址
    addressType,         // 地址类型
    portRemote,         // 远程端口
    rawDataIndex: addressValueIndex + addressLength,  // 原始数据的实际起始位置
    维列斯Version: version,    // 维列斯 协议版本
    isUDP,           // 是否是 UDP 请求
  };
}

async function remoteSocketToWS(remoteSocket, webSocket, 维列斯ResponseHeader, retry, log) {
  // 将数据从远程服务器转发到 WebSocket
  let remoteChunkCount = 0;
  let chunks = [];
  /** @type {ArrayBuffer | null} */
  let 维列斯Header = 维列斯ResponseHeader;
  let hasIncomingData = false; // 检查远程 Socket 是否有传入数据

  // 使用管道将远程 Socket 的可读流连接到一个可写流
  await remoteSocket.readable
    .pipeTo(
      new WritableStream({
        start() {
          // 初始化时不需要任何操作
        },
        /**
         * 处理每个数据块
         * @param {Uint8Array} chunk 数据块
         * @param {*} controller 控制器
         */
        async write(chunk, controller) {
          hasIncomingData = true; // 标记已收到数据
          // remoteChunkCount++; // 用于流量控制，现在似乎不需要了

          // 检查 WebSocket 是否处于开放状态
          if (webSocket.readyState !== WS_READY_STATE_OPEN) {
            controller.error(
              &amp;#39;webSocket.readyState is not open, maybe close&amp;#39;
            );
          }

          if (维列斯Header) {
            // 如果有 维列斯 响应头部，将其与第一个数据块一起发送
            webSocket.send(await new Blob([维列斯Header, chunk]).arrayBuffer());
            维列斯Header = null; // 清空头部，之后不再发送
          } else {
            // 直接发送数据块
            // 以前这里有流量控制代码，限制大量数据的发送速率
            // 但现在 Cloudflare 似乎已经修复了这个问题
            // if (remoteChunkCount &amp;gt; 20000) {
            //   // cf one package is 4096 byte(4kb),  4096 * 20000 = 80M
            //   await delay(1);
            // }
            webSocket.send(chunk);
          }
        },
        close() {
          // 当远程连接的可读流关闭时
          log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`);
          // 不需要主动关闭 WebSocket，因为这可能导致 HTTP ERR_CONTENT_LENGTH_MISMATCH 问题
          // 客户端无论如何都会发送关闭事件
          // safeCloseWebSocket(webSocket);
        },
        abort(reason) {
          // 当远程连接的可读流中断时
          console.error(`remoteConnection!.readable abort`, reason);
        },
      })
    )
    .catch((error) =&amp;gt; {
      // 捕获并记录任何异常
      console.error(
        `remoteSocketToWS has exception `,
        error.stack || error
      );
      // 发生错误时安全地关闭 WebSocket
      safeCloseWebSocket(webSocket);
    });

  // 处理 Cloudflare 连接 Socket 的特殊错误情况
  // 1. Socket.closed 将有错误
  // 2. Socket.readable 将关闭，但没有任何数据
  if (hasIncomingData === false &amp;amp;&amp;amp; retry) {
    log(`retry`);
    retry(); // 调用重试函数，尝试重新建立连接
  }
}

/**
 * 将 Base64 编码的字符串转换为 ArrayBuffer
 * 
 * @param {string} base64Str Base64 编码的输入字符串
 * @returns {{ earlyData: ArrayBuffer | undefined, error: Error | null }} 返回解码后的 ArrayBuffer 或错误
 */
function base64ToArrayBuffer(base64Str) {
  // 如果输入为空，直接返回空结果
  if (!base64Str) {
    return { earlyData: undefined, error: null };
  }
  try {
    // Go 语言使用了 URL 安全的 Base64 变体（RFC 4648）
    // 这种变体使用 &amp;#39;-&amp;#39; 和 &amp;#39;_&amp;#39; 来代替标准 Base64 中的 &amp;#39;+&amp;#39; 和 &amp;#39;/&amp;#39;
    // JavaScript 的 atob 函数不直接支持这种变体，所以我们需要先转换
    base64Str = base64Str.replace(/-/g, &amp;#39;+&amp;#39;).replace(/_/g, &amp;#39;/&amp;#39;);

    // 使用 atob 函数解码 Base64 字符串
    // atob 将 Base64 编码的 ASCII 字符串转换为原始的二进制字符串
    const decode = atob(base64Str);

    // 将二进制字符串转换为 Uint8Array
    // 这是通过遍历字符串中的每个字符并获取其 Unicode 编码值（0-255）来完成的
    const arryBuffer = Uint8Array.from(decode, (c) =&amp;gt; c.charCodeAt(0));

    // 返回 Uint8Array 的底层 ArrayBuffer
    // 这是实际的二进制数据，可以用于网络传输或其他二进制操作
    return { earlyData: arryBuffer.buffer, error: null };
  } catch (error) {
    // 如果在任何步骤中出现错误（如非法 Base64 字符），则返回错误
    return { earlyData: undefined, error };
  }
}

/**
 * 这不是真正的 UUID 验证，而是一个简化的版本
 * @param {string} uuid 要验证的 UUID 字符串
 * @returns {boolean} 如果字符串匹配 UUID 格式则返回 true，否则返回 false
 */
function isValidUUID(uuid) {
  // 定义一个正则表达式来匹配 UUID 格式
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

  // 使用正则表达式测试 UUID 字符串
  return uuidRegex.test(uuid);
}

// WebSocket 的两个重要状态常量
const WS_READY_STATE_OPEN = 1;   // WebSocket 处于开放状态，可以发送和接收消息
const WS_READY_STATE_CLOSING = 2;  // WebSocket 正在关闭过程中

function safeCloseWebSocket(socket) {
  try {
    // 只有在 WebSocket 处于开放或正在关闭状态时才调用 close()
    // 这避免了在已关闭或连接中的 WebSocket 上调用 close()
    if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) {
      socket.close();
    }
  } catch (error) {
    // 记录任何可能发生的错误，虽然按照规范不应该有错误
    console.error(&amp;#39;safeCloseWebSocket error&amp;#39;, error);
  }
}

// 预计算 0-255 每个字节的十六进制表示
const byteToHex = [];
for (let i = 0; i &amp;lt; 256; ++i) {
  // (i + 256).toString(16) 确保总是得到两位数的十六进制
  // .slice(1) 删除前导的 &amp;quot;1&amp;quot;，只保留两位十六进制数
  byteToHex.push((i + 256).toString(16).slice(1));
}

/**
 * 快速地将字节数组转换为 UUID 字符串，不进行有效性检查
 * 这是一个底层函数，直接操作字节，不做任何验证
 * @param {Uint8Array} arr 包含 UUID 字节的数组
 * @param {number} offset 数组中 UUID 开始的位置，默认为 0
 * @returns {string} UUID 字符串
 */
function unsafeStringify(arr, offset = 0) {
  // 直接从查找表中获取每个字节的十六进制表示，并拼接成 UUID 格式
  // 8-4-4-4-12 的分组是通过精心放置的连字符 &amp;quot;-&amp;quot; 实现的
  // toLowerCase() 确保整个 UUID 是小写的
  return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + &amp;quot;-&amp;quot; +
    byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + &amp;quot;-&amp;quot; +
    byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + &amp;quot;-&amp;quot; +
    byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + &amp;quot;-&amp;quot; +
    byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] +
    byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
}

/**
 * 将字节数组转换为 UUID 字符串，并验证其有效性
 * 这是一个安全的函数，它确保返回的 UUID 格式正确
 * @param {Uint8Array} arr 包含 UUID 字节的数组
 * @param {number} offset 数组中 UUID 开始的位置，默认为 0
 * @returns {string} 有效的 UUID 字符串
 * @throws {TypeError} 如果生成的 UUID 字符串无效
 */
function stringify(arr, offset = 0) {
  // 使用不安全的函数快速生成 UUID 字符串
  const uuid = unsafeStringify(arr, offset);
  // 验证生成的 UUID 是否有效
  if (!isValidUUID(uuid)) {
    // 原：throw TypeError(&amp;quot;Stringified UUID is invalid&amp;quot;);
    throw TypeError(`生成的 UUID 不符合规范 ${uuid}`);
    //uuid = userID;
  }
  return uuid;
}

/**
 * 处理 DNS 查询的函数
 * @param {ArrayBuffer} udpChunk - 客户端发送的 DNS 查询数据
 * @param {ArrayBuffer} 维列斯ResponseHeader - 维列斯 协议的响应头部数据
 * @param {(string)=&amp;gt; void} log - 日志记录函数
 */
async function handleDNSQuery(udpChunk, webSocket, 维列斯ResponseHeader, log) {
  // 无论客户端发送到哪个 DNS 服务器，我们总是使用硬编码的服务器
  // 因为有些 DNS 服务器不支持 DNS over TCP
  try {
    // 选用 Google 的 DNS 服务器（注：后续可能会改为 Cloudflare 的 1.1.1.1）
    const dnsServer = &amp;#39;8.8.4.4&amp;#39;; // 在 Cloudflare 修复连接自身 IP 的 bug 后，将改为 1.1.1.1
    const dnsPort = 53; // DNS 服务的标准端口

    let 维列斯Header = 维列斯ResponseHeader; // 保存 维列斯 响应头部，用于后续发送

    // 与指定的 DNS 服务器建立 TCP 连接
    const tcpSocket = connect({
      hostname: dnsServer,
      port: dnsPort,
    });

    log(`连接到 ${dnsServer}:${dnsPort}`); // 记录连接信息
    const writer = tcpSocket.writable.getWriter();
    await writer.write(udpChunk); // 将客户端的 DNS 查询数据发送给 DNS 服务器
    writer.releaseLock(); // 释放写入器，允许其他部分使用

    // 将从 DNS 服务器接收到的响应数据通过 WebSocket 发送回客户端
    await tcpSocket.readable.pipeTo(new WritableStream({
      async write(chunk) {
        if (webSocket.readyState === WS_READY_STATE_OPEN) {
          if (维列斯Header) {
            // 如果有 维列斯 头部，则将其与 DNS 响应数据合并后发送
            webSocket.send(await new Blob([维列斯Header, chunk]).arrayBuffer());
            维列斯Header = null; // 头部只发送一次，之后置为 null
          } else {
            // 否则直接发送 DNS 响应数据
            webSocket.send(chunk);
          }
        }
      },
      close() {
        log(`DNS 服务器(${dnsServer}) TCP 连接已关闭`); // 记录连接关闭信息
      },
      abort(reason) {
        console.error(`DNS 服务器(${dnsServer}) TCP 连接异常中断`, reason); // 记录异常中断原因
      },
    }));
  } catch (error) {
    // 捕获并记录任何可能发生的错误
    console.error(
      `handleDNSQuery 函数发生异常，错误信息: ${error.message}`
    );
  }
}

/**
 * 建立 SOCKS5 代理连接
 * @param {number} addressType 目标地址类型（1: IPv4, 2: 域名, 3: IPv6）
 * @param {string} addressRemote 目标地址（可以是 IP 或域名）
 * @param {number} portRemote 目标端口
 * @param {function} log 日志记录函数
 */
async function socks5Connect(addressType, addressRemote, portRemote, log) {
  const { username, password, hostname, port } = parsedSocks5Address;
  // 连接到 SOCKS5 代理服务器
  const socket = connect({
    hostname, // SOCKS5 服务器的主机名
    port,  // SOCKS5 服务器的端口
  });

  // 请求头格式（Worker -&amp;gt; SOCKS5 服务器）:
  // +----+----------+----------+
  // |VER | NMETHODS | METHODS  |
  // +----+----------+----------+
  // | 1  |  1   | 1 to 255 |
  // +----+----------+----------+

  // https://en.wikipedia.org/wiki/SOCKS#SOCKS5
  // METHODS 字段的含义:
  // 0x00 不需要认证
  // 0x02 用户名/密码认证 https://datatracker.ietf.org/doc/html/rfc1929
  const socksGreeting = new Uint8Array([5, 2, 0, 2]);
  // 5: SOCKS5 版本号, 2: 支持的认证方法数, 0和2: 两种认证方法（无认证和用户名/密码）

  const writer = socket.writable.getWriter();

  await writer.write(socksGreeting);
  log(&amp;#39;已发送 SOCKS5 问候消息&amp;#39;);

  const reader = socket.readable.getReader();
  const encoder = new TextEncoder();
  let res = (await reader.read()).value;
  // 响应格式（SOCKS5 服务器 -&amp;gt; Worker）:
  // +----+--------+
  // |VER | METHOD |
  // +----+--------+
  // | 1  |   1  |
  // +----+--------+
  if (res[0] !== 0x05) {
    log(`SOCKS5 服务器版本错误: 收到 ${res[0]}，期望是 5`);
    return;
  }
  if (res[1] === 0xff) {
    log(&amp;quot;服务器不接受任何认证方法&amp;quot;);
    return;
  }

  // 如果返回 0x0502，表示需要用户名/密码认证
  if (res[1] === 0x02) {
    log(&amp;quot;SOCKS5 服务器需要认证&amp;quot;);
    if (!username || !password) {
      log(&amp;quot;请提供用户名和密码&amp;quot;);
      return;
    }
    // 认证请求格式:
    // +----+------+----------+------+----------+
    // |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
    // +----+------+----------+------+----------+
    // | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
    // +----+------+----------+------+----------+
    const authRequest = new Uint8Array([
      1,           // 认证子协议版本
      username.length,  // 用户名长度
      ...encoder.encode(username), // 用户名
      password.length,  // 密码长度
      ...encoder.encode(password)  // 密码
    ]);
    await writer.write(authRequest);
    res = (await reader.read()).value;
    // 期望返回 0x0100 表示认证成功
    if (res[0] !== 0x01 || res[1] !== 0x00) {
      log(&amp;quot;SOCKS5 服务器认证失败&amp;quot;);
      return;
    }
  }

  // 请求数据格式（Worker -&amp;gt; SOCKS5 服务器）:
  // +----+-----+-------+------+----------+----------+
  // |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
  // +----+-----+-------+------+----------+----------+
  // | 1  |  1  | X&amp;#39;00&amp;#39; |  1   | Variable |  2   |
  // +----+-----+-------+------+----------+----------+
  // ATYP: 地址类型
  // 0x01: IPv4 地址
  // 0x03: 域名
  // 0x04: IPv6 地址
  // DST.ADDR: 目标地址
  // DST.PORT: 目标端口（网络字节序）

  // addressType
  // 1 --&amp;gt; IPv4  地址长度 = 4
  // 2 --&amp;gt; 域名
  // 3 --&amp;gt; IPv6  地址长度 = 16
  let DSTADDR;  // DSTADDR = ATYP + DST.ADDR
  switch (addressType) {
    case 1: // IPv4
      DSTADDR = new Uint8Array(
        [1, ...addressRemote.split(&amp;#39;.&amp;#39;).map(Number)]
      );
      break;
    case 2: // 域名
      DSTADDR = new Uint8Array(
        [3, addressRemote.length, ...encoder.encode(addressRemote)]
      );
      break;
    case 3: // IPv6
      DSTADDR = new Uint8Array(
        [4, ...addressRemote.split(&amp;#39;:&amp;#39;).flatMap(x =&amp;gt; [parseInt(x.slice(0, 2), 16), parseInt(x.slice(2), 16)])]
      );
      break;
    default:
      log(`无效的地址类型: ${addressType}`);
      return;
  }
  const socksRequest = new Uint8Array([5, 1, 0, ...DSTADDR, portRemote &amp;gt;&amp;gt; 8, portRemote &amp;amp; 0xff]);
  // 5: SOCKS5版本, 1: 表示CONNECT请求, 0: 保留字段
  // ...DSTADDR: 目标地址, portRemote &amp;gt;&amp;gt; 8 和 &amp;amp; 0xff: 将端口转为网络字节序
  await writer.write(socksRequest);
  log(&amp;#39;已发送 SOCKS5 请求&amp;#39;);

  res = (await reader.read()).value;
  // 响应格式（SOCKS5 服务器 -&amp;gt; Worker）:
  //  +----+-----+-------+------+----------+----------+
  // |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
  // +----+-----+-------+------+----------+----------+
  // | 1  |  1  | X&amp;#39;00&amp;#39; |  1   | Variable |  2   |
  // +----+-----+-------+------+----------+----------+
  if (res[1] === 0x00) {
    log(&amp;quot;SOCKS5 连接已建立&amp;quot;);
  } else {
    log(&amp;quot;SOCKS5 连接建立失败&amp;quot;);
    return;
  }
  writer.releaseLock();
  reader.releaseLock();
  return socket;
}

/**
 * SOCKS5 代理地址解析器
 * 此函数用于解析 SOCKS5 代理地址字符串，提取出用户名、密码、主机名和端口号
 * 
 * @param {string} address SOCKS5 代理地址，格式可以是：
 *   - &amp;quot;username:password@hostname:port&amp;quot; （带认证）
 *   - &amp;quot;hostname:port&amp;quot; （不需认证）
 *   - &amp;quot;username:password@[ipv6]:port&amp;quot; （IPv6 地址需要用方括号括起来）
 */
function socks5AddressParser(address) {
  // 使用 &amp;quot;@&amp;quot; 分割地址，分为认证部分和服务器地址部分
  // reverse() 是为了处理没有认证信息的情况，确保 latter 总是包含服务器地址
  let [latter, former] = address.split(&amp;quot;@&amp;quot;).reverse();
  let username, password, hostname, port;

  // 如果存在 former 部分，说明提供了认证信息
  if (former) {
    const formers = former.split(&amp;quot;:&amp;quot;);
    if (formers.length !== 2) {
      throw new Error(&amp;#39;无效的 SOCKS 地址格式：认证部分必须是 &amp;quot;username:password&amp;quot; 的形式&amp;#39;);
    }
    [username, password] = formers;
  }

  // 解析服务器地址部分
  const latters = latter.split(&amp;quot;:&amp;quot;);
  // 从末尾提取端口号（因为 IPv6 地址中也包含冒号）
  port = Number(latters.pop());
  if (isNaN(port)) {
    throw new Error(&amp;#39;无效的 SOCKS 地址格式：端口号必须是数字&amp;#39;);
  }

  // 剩余部分就是主机名（可能是域名、IPv4 或 IPv6 地址）
  hostname = latters.join(&amp;quot;:&amp;quot;);

  // 处理 IPv6 地址的特殊情况
  // IPv6 地址包含多个冒号，所以必须用方括号括起来，如 [2001:db8::1]
  const regex = /^\[.*\]$/;
  if (hostname.includes(&amp;quot;:&amp;quot;) &amp;amp;&amp;amp; !regex.test(hostname)) {
    throw new Error(&amp;#39;无效的 SOCKS 地址格式：IPv6 地址必须用方括号括起来，如 [2001:db8::1]&amp;#39;);
  }

  //if (/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(hostname)) hostname = `${atob(&amp;#39;d3d3Lg==&amp;#39;)}${hostname}${atob(&amp;#39;LmlwLjA5MDIyNy54eXo=&amp;#39;)}`;
  // 返回解析后的结果
  return {
    username,  // 用户名，如果没有则为 undefined
    password,  // 密码，如果没有则为 undefined
    hostname,  // 主机名，可以是域名、IPv4 或 IPv6 地址
    port,   // 端口号，已转换为数字类型
  }
}

/**
 * 恢复被伪装的信息
 * 这个函数用于将内容中的假用户ID和假主机名替换回真实的值
 * 
 * @param {string} content 需要处理的内容
 * @param {string} userID 真实的用户ID
 * @param {string} hostName 真实的主机名
 * @param {boolean} isBase64 内容是否是Base64编码的
 * @returns {string} 恢复真实信息后的内容
 */
function 恢复伪装信息(content, userID, hostName, isBase64) {
  if (isBase64) content = atob(content);  // 如果内容是Base64编码的，先解码

  // 使用正则表达式全局替换（&amp;#39;g&amp;#39;标志）
  // 将所有出现的假用户ID和假主机名替换为真实的值
  content = content.replace(new RegExp(fakeUserID, &amp;#39;g&amp;#39;), userID)
    .replace(new RegExp(fakeHostName, &amp;#39;g&amp;#39;), hostName);

  if (isBase64) content = btoa(content);  // 如果原内容是Base64编码的，处理完后再次编码

  return content;
}

/**
 * 双重MD5哈希函数
 * 这个函数对输入文本进行两次MD5哈希，增强安全性
 * 第二次哈希使用第一次哈希结果的一部分作为输入
 * 
 * @param {string} 文本 要哈希的文本
 * @returns {Promise&amp;lt;string&amp;gt;} 双重哈希后的小写十六进制字符串
 */
async function 双重哈希(文本) {
  const 编码器 = new TextEncoder();

  const 第一次哈希 = await crypto.subtle.digest(&amp;#39;MD5&amp;#39;, 编码器.encode(文本));
  const 第一次哈希数组 = Array.from(new Uint8Array(第一次哈希));
  const 第一次十六进制 = 第一次哈希数组.map(字节 =&amp;gt; 字节.toString(16).padStart(2, &amp;#39;0&amp;#39;)).join(&amp;#39;&amp;#39;);

  const 第二次哈希 = await crypto.subtle.digest(&amp;#39;MD5&amp;#39;, 编码器.encode(第一次十六进制.slice(7, 27)));
  const 第二次哈希数组 = Array.from(new Uint8Array(第二次哈希));
  const 第二次十六进制 = 第二次哈希数组.map(字节 =&amp;gt; 字节.toString(16).padStart(2, &amp;#39;0&amp;#39;)).join(&amp;#39;&amp;#39;);

  return 第二次十六进制.toLowerCase();
}

async function 代理URL(代理网址, 目标网址) {
  const 网址列表 = await 整理(代理网址);
  const 完整网址 = 网址列表[Math.floor(Math.random() * 网址列表.length)];

  // 解析目标 URL
  let 解析后的网址 = new URL(完整网址);
  console.log(解析后的网址);
  // 提取并可能修改 URL 组件
  let 协议 = 解析后的网址.protocol.slice(0, -1) || &amp;#39;https&amp;#39;;
  let 主机名 = 解析后的网址.hostname;
  let 路径名 = 解析后的网址.pathname;
  let 查询参数 = 解析后的网址.search;

  // 处理路径名
  if (路径名.charAt(路径名.length - 1) == &amp;#39;/&amp;#39;) {
    路径名 = 路径名.slice(0, -1);
  }
  路径名 += 目标网址.pathname;

  // 构建新的 URL
  let 新网址 = `${协议}://${主机名}${路径名}${查询参数}`;

  // 反向代理请求
  let 响应 = await fetch(新网址);

  // 创建新的响应
  let 新响应 = new Response(响应.body, {
    status: 响应.status,
    statusText: 响应.statusText,
    headers: 响应.headers
  });

  // 添加自定义头部，包含 URL 信息
  //新响应.headers.set(&amp;#39;X-Proxied-By&amp;#39;, &amp;#39;Cloudflare Worker&amp;#39;);
  //新响应.headers.set(&amp;#39;X-Original-URL&amp;#39;, 完整网址);
  新响应.headers.set(&amp;#39;X-New-URL&amp;#39;, 新网址);

  return 新响应;
}

const 啥啥啥_写的这是啥啊 = atob(&amp;#39;ZG14bGMzTT0=&amp;#39;);
function 配置信息(UUID, 域名地址) {
  const 协议类型 = atob(啥啥啥_写的这是啥啊);

  const 别名 = FileName;
  let 地址 = 域名地址;
  let 端口 = 443;

  const 用户ID = UUID;
  const 加密方式 = &amp;#39;none&amp;#39;;

  const 传输层协议 = &amp;#39;ws&amp;#39;;
  const 伪装域名 = 域名地址;
  const 路径 = path;

  let 传输层安全 = [&amp;#39;tls&amp;#39;, true];
  const SNI = 域名地址;
  const 指纹 = &amp;#39;randomized&amp;#39;;

  if (域名地址.includes(&amp;#39;.workers.dev&amp;#39;)) {
    地址 = atob(&amp;#39;dmlzYS5jbg==&amp;#39;);
    端口 = 80;
    传输层安全 = [&amp;#39;&amp;#39;, false];
  }

  const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\u003f\u0065\u006e\u0063\u0072\u0079` + &amp;#39;p&amp;#39; + `${atob(&amp;#39;dGlvbj0=&amp;#39;) + 加密方式}\u0026\u0073\u0065\u0063\u0075\u0072\u0069\u0074\u0079\u003d${传输层安全[0]}&amp;amp;sni=${SNI}&amp;amp;fp=${指纹}&amp;amp;type=${传输层协议}&amp;amp;host=${伪装域名}&amp;amp;path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`;
  const 猫猫猫 = `- {name: ${FileName}, server: ${地址}, port: ${端口}, type: ${协议类型}, uuid: ${用户ID}, tls: ${传输层安全[1]}, alpn: [h3], udp: false, sni: ${SNI}, tfo: false, skip-cert-verify: true, servername: ${伪装域名}, client-fingerprint: ${指纹}, network: ${传输层协议}, ws-opts: {path: &amp;quot;${路径}&amp;quot;, headers: {${伪装域名}}}}`;
  return [威图瑞, 猫猫猫];
}

let subParams = [&amp;#39;sub&amp;#39;, &amp;#39;base64&amp;#39;, &amp;#39;b64&amp;#39;, &amp;#39;clash&amp;#39;, &amp;#39;singbox&amp;#39;, &amp;#39;sb&amp;#39;];
const cmad = decodeURIComponent(atob(&amp;#39;dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUyNyUzRWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUzQyUyRmElM0UlM0NiciUzRQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0lM0NiciUzRQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM=&amp;#39;));
/**
 * @param {string} userID
 * @param {string | null} hostName
 * @param {string} sub
 * @param {string} UA
 * @returns {Promise&amp;lt;string&amp;gt;}
 */
async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env) {
  if (sub) {
    const match = sub.match(/^(?:https?:\/\/)?([^\/]+)/);
    if (match) {
      sub = match[1];
    }
    const subs = await 整理(sub);
    if (subs.length &amp;gt; 1) sub = subs[0];
  } else {
    if (env.KV) {
      await 迁移地址列表(env);
      const 优选地址列表 = await env.KV.get(&amp;#39;ADD.txt&amp;#39;);
      if (优选地址列表) {
        const 优选地址数组 = await 整理(优选地址列表);
        const 分类地址 = {
          接口地址: new Set(),
          链接地址: new Set(),
          优选地址: new Set()
        };

        for (const 元素 of 优选地址数组) {
          if (元素.startsWith(&amp;#39;https://&amp;#39;)) {
            分类地址.接口地址.add(元素);
          } else if (元素.includes(&amp;#39;://&amp;#39;)) {
            分类地址.链接地址.add(元素);
          } else {
            分类地址.优选地址.add(元素);
          }
        }

        addressesapi = [...分类地址.接口地址];
        link = [...分类地址.链接地址];
        addresses = [...分类地址.优选地址];
      }
    }

    if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0) {
      // 定义 Cloudflare IP 范围的 CIDR 列表
      let cfips = [
        &amp;#39;103.21.244.0/23&amp;#39;,
        &amp;#39;104.16.0.0/13&amp;#39;,
        &amp;#39;104.24.0.0/14&amp;#39;,
        &amp;#39;172.64.0.0/14&amp;#39;,
        &amp;#39;103.21.244.0/23&amp;#39;,
        &amp;#39;104.16.0.0/14&amp;#39;,
        &amp;#39;104.24.0.0/15&amp;#39;,
        &amp;#39;141.101.64.0/19&amp;#39;,
        &amp;#39;172.64.0.0/14&amp;#39;,
        &amp;#39;188.114.96.0/21&amp;#39;,
        &amp;#39;190.93.240.0/21&amp;#39;,
      ];

      // 生成符合给定 CIDR 范围的随机 IP 地址
      function generateRandomIPFromCIDR(cidr) {
        const [base, mask] = cidr.split(&amp;#39;/&amp;#39;);
        const baseIP = base.split(&amp;#39;.&amp;#39;).map(Number);
        const subnetMask = 32 - parseInt(mask, 10);
        const maxHosts = Math.pow(2, subnetMask) - 1;
        const randomHost = Math.floor(Math.random() * maxHosts);

        const randomIP = baseIP.map((octet, index) =&amp;gt; {
          if (index &amp;lt; 2) return octet;
          if (index === 2) return (octet &amp;amp; (255 &amp;lt;&amp;lt; (subnetMask - 8))) + ((randomHost &amp;gt;&amp;gt; 8) &amp;amp; 255);
          return (octet &amp;amp; (255 &amp;lt;&amp;lt; subnetMask)) + (randomHost &amp;amp; 255);
        });

        return randomIP.join(&amp;#39;.&amp;#39;);
      }
      addresses = addresses.concat(&amp;#39;127.0.0.1:1234#CFnat&amp;#39;);
      if (hostName.includes(&amp;quot;.workers.dev&amp;quot;)) {
        addressesnotls = addressesnotls.concat(cfips.map(cidr =&amp;gt; generateRandomIPFromCIDR(cidr) + &amp;#39;#CF随机节点&amp;#39;));
      } else {
        addresses = addresses.concat(cfips.map(cidr =&amp;gt; generateRandomIPFromCIDR(cidr) + &amp;#39;#CF随机节点&amp;#39;));
      }
    }
  }

  const uuid = (_url.pathname == `/${动态UUID}`) ? 动态UUID : userID;
  const userAgent = UA.toLowerCase();
  const Config = 配置信息(userID, hostName);
  const v2ray = Config[0];
  const clash = Config[1];
  let proxyhost = &amp;quot;&amp;quot;;
  if (hostName.includes(&amp;quot;.workers.dev&amp;quot;)) {
    if (proxyhostsURL &amp;amp;&amp;amp; (!proxyhosts || proxyhosts.length == 0)) {
      try {
        const response = await fetch(proxyhostsURL);

        if (!response.ok) {
          console.error(&amp;#39;获取地址时出错:&amp;#39;, response.status, response.statusText);
          return; // 如果有错误，直接返回
        }

        const text = await response.text();
        const lines = text.split(&amp;#39;\n&amp;#39;);
        // 过滤掉空行或只包含空白字符的行
        const nonEmptyLines = lines.filter(line =&amp;gt; line.trim() !== &amp;#39;&amp;#39;);

        proxyhosts = proxyhosts.concat(nonEmptyLines);
      } catch (error) {
        //console.error(&amp;#39;获取地址时出错:&amp;#39;, error);
      }
    }
    if (proxyhosts.length != 0) proxyhost = proxyhosts[Math.floor(Math.random() * proxyhosts.length)] + &amp;quot;/&amp;quot;;
  }

  if (userAgent.includes(&amp;#39;mozilla&amp;#39;) &amp;amp;&amp;amp; !subParams.some(_searchParams =&amp;gt; _url.searchParams.has(_searchParams))) {
    const newSocks5s = socks5s.map(socks5Address =&amp;gt; {
      if (socks5Address.includes(&amp;#39;@&amp;#39;)) return socks5Address.split(&amp;#39;@&amp;#39;)[1];
      else if (socks5Address.includes(&amp;#39;//&amp;#39;)) return socks5Address.split(&amp;#39;//&amp;#39;)[1];
      else return socks5Address;
    });

    let socks5List = &amp;#39;&amp;#39;;
    if (go2Socks5s.length &amp;gt; 0 &amp;amp;&amp;amp; enableSocks) {
      socks5List = `${decodeURIComponent(&amp;#39;SOCKS5%EF%BC%88%E7%99%BD%E5%90%8D%E5%8D%95%EF%BC%89%3A%20&amp;#39;)}`;
      if (go2Socks5s.includes(atob(&amp;#39;YWxsIGlu&amp;#39;)) || go2Socks5s.includes(atob(&amp;#39;Kg==&amp;#39;))) socks5List += `${decodeURIComponent(&amp;#39;%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F&amp;#39;)}&amp;lt;br&amp;gt;`;
      else socks5List += `&amp;lt;br&amp;gt;  ${go2Socks5s.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
    }

    let 订阅器 = &amp;#39;&amp;lt;br&amp;gt;&amp;#39;;
    if (sub) {
      if (enableSocks) 订阅器 += `CFCDN（访问方式）: Socks5&amp;lt;br&amp;gt;  ${newSocks5s.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;${socks5List}`;
      else if (proxyIP &amp;amp;&amp;amp; proxyIP != &amp;#39;&amp;#39;) 订阅器 += `CFCDN（访问方式）: ProxyIP&amp;lt;br&amp;gt;  ${proxyIPs.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      else if (RproxyIP == &amp;#39;true&amp;#39;) 订阅器 += `CFCDN（访问方式）: 自动获取ProxyIP&amp;lt;br&amp;gt;`;
      else 订阅器 += `CFCDN（访问方式）: 无法访问, 需要您设置 proxyIP/PROXYIP ！！！&amp;lt;br&amp;gt;`
      订阅器 += `&amp;lt;br&amp;gt;SUB（优选订阅生成器）: ${sub}`;
    } else {
      if (enableSocks) 订阅器 += `CFCDN（访问方式）: Socks5&amp;lt;br&amp;gt;  ${newSocks5s.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;${socks5List}`;
      else if (proxyIP &amp;amp;&amp;amp; proxyIP != &amp;#39;&amp;#39;) 订阅器 += `CFCDN（访问方式）: ProxyIP&amp;lt;br&amp;gt;  ${proxyIPs.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      else 订阅器 += `CFCDN（访问方式）: 无法访问, 需要您设置 proxyIP/PROXYIP ！！！&amp;lt;br&amp;gt;`;
      let 判断是否绑定KV空间 = &amp;#39;&amp;#39;;
      if (env.KV) 判断是否绑定KV空间 = ` &amp;lt;a href=&amp;#39;${_url.pathname}/edit&amp;#39;&amp;gt;编辑优选列表&amp;lt;/a&amp;gt;`;
      订阅器 += `&amp;lt;br&amp;gt;您的订阅内容由 内置 addresses/ADD* 参数变量提供${判断是否绑定KV空间}&amp;lt;br&amp;gt;`;
      if (addresses.length &amp;gt; 0) 订阅器 += `ADD（TLS优选域名&amp;amp;IP）: &amp;lt;br&amp;gt;  ${addresses.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      if (addressesnotls.length &amp;gt; 0) 订阅器 += `ADDNOTLS（noTLS优选域名&amp;amp;IP）: &amp;lt;br&amp;gt;  ${addressesnotls.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      if (addressesapi.length &amp;gt; 0) 订阅器 += `ADDAPI（TLS优选域名&amp;amp;IP 的 API）: &amp;lt;br&amp;gt;  ${addressesapi.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      if (addressesnotlsapi.length &amp;gt; 0) 订阅器 += `ADDNOTLSAPI（noTLS优选域名&amp;amp;IP 的 API）: &amp;lt;br&amp;gt;  ${addressesnotlsapi.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
      if (addressescsv.length &amp;gt; 0) 订阅器 += `ADDCSV（IPTest测速csv文件 限速 ${DLS} ）: &amp;lt;br&amp;gt;  ${addressescsv.join(&amp;#39;&amp;lt;br&amp;gt;  &amp;#39;)}&amp;lt;br&amp;gt;`;
    }

    if (动态UUID &amp;amp;&amp;amp; _url.pathname !== `/${动态UUID}`) 订阅器 = &amp;#39;&amp;#39;;
    else 订阅器 += `&amp;lt;br&amp;gt;SUBAPI（订阅转换后端）: ${subProtocol}://${subConverter}&amp;lt;br&amp;gt;SUBCONFIG（订阅转换配置文件）: ${subConfig}`;
    const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}&amp;lt;br&amp;gt;UUIDNow: ${userID}&amp;lt;br&amp;gt;UUIDLow: ${userIDLow}&amp;lt;br&amp;gt;${userIDTime}TIME（动态UUID有效时间）: ${有效时间} 天&amp;lt;br&amp;gt;UPTIME（动态UUID更新时间）: ${更新时间} 时（北京时间）&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;` : `${userIDTime}`;
    const 节点配置页 = `
      ################################################################&amp;lt;br&amp;gt;
      Subscribe / sub 订阅地址, 点击链接自动 &amp;lt;strong&amp;gt;复制订阅链接&amp;lt;/strong&amp;gt; 并 &amp;lt;strong&amp;gt;生成订阅二维码&amp;lt;/strong&amp;gt; &amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      自适应订阅地址:&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; onclick=&amp;quot;copyToClipboard(&amp;#39;https://${proxyhost}${hostName}/${uuid}?sub&amp;#39;,&amp;#39;qrcode_0&amp;#39;)&amp;quot; style=&amp;quot;color:blue;text-decoration:underline;cursor:pointer;&amp;quot;&amp;gt;https://${proxyhost}${hostName}/${uuid}&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;div id=&amp;quot;qrcode_0&amp;quot; style=&amp;quot;margin: 10px 10px 10px 10px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      Base64订阅地址:&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; onclick=&amp;quot;copyToClipboard(&amp;#39;https://${proxyhost}${hostName}/${uuid}?b64&amp;#39;,&amp;#39;qrcode_1&amp;#39;)&amp;quot; style=&amp;quot;color:blue;text-decoration:underline;cursor:pointer;&amp;quot;&amp;gt;https://${proxyhost}${hostName}/${uuid}?b64&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;div id=&amp;quot;qrcode_1&amp;quot; style=&amp;quot;margin: 10px 10px 10px 10px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      clash订阅地址:&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; onclick=&amp;quot;copyToClipboard(&amp;#39;https://${proxyhost}${hostName}/${uuid}?clash&amp;#39;,&amp;#39;qrcode_2&amp;#39;)&amp;quot; style=&amp;quot;color:blue;text-decoration:underline;cursor:pointer;&amp;quot;&amp;gt;https://${proxyhost}${hostName}/${uuid}?clash&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;div id=&amp;quot;qrcode_2&amp;quot; style=&amp;quot;margin: 10px 10px 10px 10px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      singbox订阅地址:&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; onclick=&amp;quot;copyToClipboard(&amp;#39;https://${proxyhost}${hostName}/${uuid}?sb&amp;#39;,&amp;#39;qrcode_3&amp;#39;)&amp;quot; style=&amp;quot;color:blue;text-decoration:underline;cursor:pointer;&amp;quot;&amp;gt;https://${proxyhost}${hostName}/${uuid}?sb&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;div id=&amp;quot;qrcode_3&amp;quot; style=&amp;quot;margin: 10px 10px 10px 10px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;strong&amp;gt;&amp;lt;a href=&amp;quot;javascript:void(0);&amp;quot; id=&amp;quot;noticeToggle&amp;quot; onclick=&amp;quot;toggleNotice()&amp;quot;&amp;gt;实用订阅技巧∨&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
        &amp;lt;div id=&amp;quot;noticeContent&amp;quot; class=&amp;quot;notice-content&amp;quot; style=&amp;quot;display: none;&amp;quot;&amp;gt;
          &amp;lt;strong&amp;gt;1.&amp;lt;/strong&amp;gt; 如您使用的是 PassWall、SSR+ 等路由插件，推荐使用 &amp;lt;strong&amp;gt;Base64订阅地址&amp;lt;/strong&amp;gt; 进行订阅；&amp;lt;br&amp;gt;
          &amp;lt;br&amp;gt;
          &amp;lt;strong&amp;gt;2.&amp;lt;/strong&amp;gt; 快速切换 &amp;lt;a href=&amp;#39;${atob(&amp;#39;aHR0cHM6Ly9naXRodWIuY29tL2NtbGl1L1dvcmtlclZsZXNzMnN1Yg==&amp;#39;)}&amp;#39;&amp;gt;优选订阅生成器&amp;lt;/a&amp;gt; 至：sub.google.com，您可将&amp;quot;?sub=sub.google.com&amp;quot;参数添加到链接末尾，例如：&amp;lt;br&amp;gt;
            https://${proxyhost}${hostName}/${uuid}&amp;lt;strong&amp;gt;?sub=sub.google.com&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
          &amp;lt;br&amp;gt;
          &amp;lt;strong&amp;gt;3.&amp;lt;/strong&amp;gt; 快速更换 PROXYIP 至：proxyip.fxxk.dedyn.io:443，您可将&amp;quot;?proxyip=proxyip.fxxk.dedyn.io:443&amp;quot;参数添加到链接末尾，例如：&amp;lt;br&amp;gt;
             https://${proxyhost}${hostName}/${uuid}&amp;lt;strong&amp;gt;?proxyip=proxyip.fxxk.dedyn.io:443&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
          &amp;lt;br&amp;gt;
          &amp;lt;strong&amp;gt;4.&amp;lt;/strong&amp;gt; 快速更换 SOCKS5 至：user:password@127.0.0.1:1080，您可将&amp;quot;?socks5=user:password@127.0.0.1:1080&amp;quot;参数添加到链接末尾，例如：&amp;lt;br&amp;gt;
            https://${proxyhost}${hostName}/${uuid}&amp;lt;strong&amp;gt;?socks5=user:password@127.0.0.1:1080&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
          &amp;lt;br&amp;gt;
          &amp;lt;strong&amp;gt;5.&amp;lt;/strong&amp;gt; 如需指定多个参数则需要使用&amp;#39;&amp;amp;&amp;#39;做间隔，例如：&amp;lt;br&amp;gt;
            https://${proxyhost}${hostName}/${uuid}?sub=sub.google.com&amp;lt;strong&amp;gt;&amp;amp;&amp;lt;/strong&amp;gt;proxyip=proxyip.fxxk.dedyn.io&amp;lt;br&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;script src=&amp;quot;https://cdn.jsdelivr.net/npm/@keeex/qrcodejs-kx@1.0.2/qrcode.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
      &amp;lt;script&amp;gt;
      function copyToClipboard(text, qrcode) {
        navigator.clipboard.writeText(text).then(() =&amp;gt; {
          alert(&amp;#39;已复制到剪贴板&amp;#39;);
        }).catch(err =&amp;gt; {
          console.error(&amp;#39;复制失败:&amp;#39;, err);
        });
        const qrcodeDiv = document.getElementById(qrcode);
        qrcodeDiv.innerHTML = &amp;#39;&amp;#39;;
        new QRCode(qrcodeDiv, {
          text: text,
          width: 220, // 调整宽度
          height: 220, // 调整高度
          colorDark: &amp;quot;#000000&amp;quot;, // 二维码颜色
          colorLight: &amp;quot;#ffffff&amp;quot;, // 背景颜色
          correctLevel: QRCode.CorrectLevel.Q, // 设置纠错级别
          scale: 1 // 调整像素颗粒度
        });
      }

      function toggleNotice() {
        const noticeContent = document.getElementById(&amp;#39;noticeContent&amp;#39;);
        const noticeToggle = document.getElementById(&amp;#39;noticeToggle&amp;#39;);
        if (noticeContent.style.display === &amp;#39;none&amp;#39;) {
          noticeContent.style.display = &amp;#39;block&amp;#39;;
          noticeToggle.textContent = &amp;#39;实用订阅技巧∧&amp;#39;;
        } else {
          noticeContent.style.display = &amp;#39;none&amp;#39;; 
          noticeToggle.textContent = &amp;#39;实用订阅技巧∨&amp;#39;;
        }
      }
      &amp;lt;/script&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ################################################################&amp;lt;br&amp;gt;
      ${FileName} 配置信息&amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ${动态UUID信息}HOST: ${hostName}&amp;lt;br&amp;gt;
      UUID: ${userID}&amp;lt;br&amp;gt;
      FKID: ${fakeUserID}&amp;lt;br&amp;gt;
      UA: ${UA}&amp;lt;br&amp;gt;
      ${订阅器}&amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ################################################################&amp;lt;br&amp;gt;
      v2ray&amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      &amp;lt;a href=&amp;quot;javascript:void(0)&amp;quot; onclick=&amp;quot;copyToClipboard(&amp;#39;${v2ray}&amp;#39;,&amp;#39;qrcode_v2ray&amp;#39;)&amp;quot; style=&amp;quot;color:blue;text-decoration:underline;cursor:pointer;&amp;quot;&amp;gt;${v2ray}&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
      &amp;lt;div id=&amp;quot;qrcode_v2ray&amp;quot; style=&amp;quot;margin: 10px 10px 10px 10px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ################################################################&amp;lt;br&amp;gt;
      clash-meta&amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ${clash}&amp;lt;br&amp;gt;
      ---------------------------------------------------------------&amp;lt;br&amp;gt;
      ################################################################&amp;lt;br&amp;gt;
      ${cmad}
      `;
    return 节点配置页;
  } else {
    if (typeof fetch != &amp;#39;function&amp;#39;) {
      return &amp;#39;Error: fetch is not available in this environment.&amp;#39;;
    }

    let newAddressesapi = [];
    let newAddressescsv = [];
    let newAddressesnotlsapi = [];
    let newAddressesnotlscsv = [];

    // 如果是使用默认域名，则改成一个workers的域名，订阅器会加上代理
    if (hostName.includes(&amp;quot;.workers.dev&amp;quot;)) {
      noTLS = &amp;#39;true&amp;#39;;
      fakeHostName = `${fakeHostName}.workers.dev`;
      newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi);
      newAddressesnotlscsv = await 整理测速结果(&amp;#39;FALSE&amp;#39;);
    } else if (hostName.includes(&amp;quot;.pages.dev&amp;quot;)) {
      fakeHostName = `${fakeHostName}.pages.dev`;
    } else if (hostName.includes(&amp;quot;worker&amp;quot;) || hostName.includes(&amp;quot;notls&amp;quot;) || noTLS == &amp;#39;true&amp;#39;) {
      noTLS = &amp;#39;true&amp;#39;;
      fakeHostName = `notls${fakeHostName}.net`;
      newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi);
      newAddressesnotlscsv = await 整理测速结果(&amp;#39;FALSE&amp;#39;);
    } else {
      fakeHostName = `${fakeHostName}.xyz`
    }
    console.log(`虚假HOST: ${fakeHostName}`);
    let url = `${subProtocol}://${sub}/sub?host=${fakeHostName}&amp;amp;uuid=${fakeUserID + atob(&amp;#39;JmVkZ2V0dW5uZWw9Y21saXUmcHJveHlpcD0=&amp;#39;) + RproxyIP}&amp;amp;path=${encodeURIComponent(path)}`;
    let isBase64 = true;

    if (!sub || sub == &amp;quot;&amp;quot;) {
      if (hostName.includes(&amp;#39;workers.dev&amp;#39;)) {
        if (proxyhostsURL &amp;amp;&amp;amp; (!proxyhosts || proxyhosts.length == 0)) {
          try {
            const response = await fetch(proxyhostsURL);

            if (!response.ok) {
              console.error(&amp;#39;获取地址时出错:&amp;#39;, response.status, response.statusText);
              return; // 如果有错误，直接返回
            }

            const text = await response.text();
            const lines = text.split(&amp;#39;\n&amp;#39;);
            // 过滤掉空行或只包含空白字符的行
            const nonEmptyLines = lines.filter(line =&amp;gt; line.trim() !== &amp;#39;&amp;#39;);

            proxyhosts = proxyhosts.concat(nonEmptyLines);
          } catch (error) {
            console.error(&amp;#39;获取地址时出错:&amp;#39;, error);
          }
        }
        // 使用Set对象去重
        proxyhosts = [...new Set(proxyhosts)];
      }

      newAddressesapi = await 整理优选列表(addressesapi);
      newAddressescsv = await 整理测速结果(&amp;#39;TRUE&amp;#39;);
      url = `https://${hostName}/${fakeUserID + _url.search}`;
      if (hostName.includes(&amp;quot;worker&amp;quot;) || hostName.includes(&amp;quot;notls&amp;quot;) || noTLS == &amp;#39;true&amp;#39;) {
        if (_url.search) url += &amp;#39;&amp;amp;notls&amp;#39;;
        else url += &amp;#39;?notls&amp;#39;;
      }
      console.log(`虚假订阅: ${url}`);
    }

    if (!userAgent.includes((&amp;#39;CF-Workers-SUB&amp;#39;).toLowerCase())) {
      if ((userAgent.includes(&amp;#39;clash&amp;#39;) &amp;amp;&amp;amp; !userAgent.includes(&amp;#39;nekobox&amp;#39;)) || (_url.searchParams.has(&amp;#39;clash&amp;#39;) &amp;amp;&amp;amp; !userAgent.includes(&amp;#39;subconverter&amp;#39;))) {
        url = `${subProtocol}://${subConverter}/sub?target=clash&amp;amp;url=${encodeURIComponent(url)}&amp;amp;insert=false&amp;amp;config=${encodeURIComponent(subConfig)}&amp;amp;emoji=${subEmoji}&amp;amp;list=false&amp;amp;tfo=false&amp;amp;scv=true&amp;amp;fdn=false&amp;amp;sort=false&amp;amp;new_name=true`;
        isBase64 = false;
      } else if (userAgent.includes(&amp;#39;sing-box&amp;#39;) || userAgent.includes(&amp;#39;singbox&amp;#39;) || ((_url.searchParams.has(&amp;#39;singbox&amp;#39;) || _url.searchParams.has(&amp;#39;sb&amp;#39;)) &amp;amp;&amp;amp; !userAgent.includes(&amp;#39;subconverter&amp;#39;))) {
        url = `${subProtocol}://${subConverter}/sub?target=singbox&amp;amp;url=${encodeURIComponent(url)}&amp;amp;insert=false&amp;amp;config=${encodeURIComponent(subConfig)}&amp;amp;emoji=${subEmoji}&amp;amp;list=false&amp;amp;tfo=false&amp;amp;scv=true&amp;amp;fdn=false&amp;amp;sort=false&amp;amp;new_name=true`;
        isBase64 = false;
      }
    }

    try {
      let content;
      if ((!sub || sub == &amp;quot;&amp;quot;) &amp;amp;&amp;amp; isBase64 == true) {
        content = await 生成本地订阅(fakeHostName, fakeUserID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv);
      } else {
        const response = await fetch(url, {
          headers: {
            &amp;#39;User-Agent&amp;#39;: UA + atob(&amp;#39;IENGLVdvcmtlcnMtZWRnZXR1bm5lbC9jbWxpdQ==&amp;#39;)
          }
        });
        content = await response.text();
      }

      if (_url.pathname == `/${fakeUserID}`) return content;

      return 恢复伪装信息(content, userID, hostName, isBase64);

    } catch (error) {
      console.error(&amp;#39;Error fetching content:&amp;#39;, error);
      return `Error fetching content: ${error.message}`;
    }
  }
}

async function 整理优选列表(api) {
  if (!api || api.length === 0) return [];

  let newapi = &amp;quot;&amp;quot;;

  // 创建一个AbortController对象，用于控制fetch请求的取消
  const controller = new AbortController();

  const timeout = setTimeout(() =&amp;gt; {
    controller.abort(); // 取消所有请求
  }, 2000); // 2秒后触发

  try {
    // 使用Promise.allSettled等待所有API请求完成，无论成功或失败
    // 对api数组进行遍历，对每个API地址发起fetch请求
    const responses = await Promise.allSettled(api.map(apiUrl =&amp;gt; fetch(apiUrl, {
      method: &amp;#39;get&amp;#39;,
      headers: {
        &amp;#39;Accept&amp;#39;: &amp;#39;text/html,application/xhtml+xml,application/xml;&amp;#39;,
        &amp;#39;User-Agent&amp;#39;: atob(&amp;#39;Q0YtV29ya2Vycy1lZGdldHVubmVsL2NtbGl1&amp;#39;)
      },
      signal: controller.signal // 将AbortController的信号量添加到fetch请求中，以便于需要时可以取消请求
    }).then(response =&amp;gt; response.ok ? response.text() : Promise.reject())));

    // 遍历所有响应
    for (const [index, response] of responses.entries()) {
      // 检查响应状态是否为&amp;#39;fulfilled&amp;#39;，即请求成功完成
      if (response.status === &amp;#39;fulfilled&amp;#39;) {
        // 获取响应的内容
        const content = await response.value;

        const lines = content.split(/\r?\n/);
        let 节点备注 = &amp;#39;&amp;#39;;
        let 测速端口 = &amp;#39;443&amp;#39;;

        if (lines[0].split(&amp;#39;,&amp;#39;).length &amp;gt; 3) {
          const idMatch = api[index].match(/id=([^&amp;amp;]*)/);
          if (idMatch) 节点备注 = idMatch[1];

          const portMatch = api[index].match(/port=([^&amp;amp;]*)/);
          if (portMatch) 测速端口 = portMatch[1];

          for (let i = 1; i &amp;lt; lines.length; i++) {
            const columns = lines[i].split(&amp;#39;,&amp;#39;)[0];
            if (columns) {
              newapi += `${columns}:${测速端口}${节点备注 ? `#${节点备注}` : &amp;#39;&amp;#39;}\n`;
              if (api[index].includes(&amp;#39;proxyip=true&amp;#39;)) proxyIPPool.push(`${columns}:${测速端口}`);
            }
          }
        } else {
          // 验证当前apiUrl是否带有&amp;#39;proxyip=true&amp;#39;
          if (api[index].includes(&amp;#39;proxyip=true&amp;#39;)) {
            // 如果URL带有&amp;#39;proxyip=true&amp;#39;，则将内容添加到proxyIPPool
            proxyIPPool = proxyIPPool.concat((await 整理(content)).map(item =&amp;gt; {
              const baseItem = item.split(&amp;#39;#&amp;#39;)[0] || item;
              if (baseItem.includes(&amp;#39;:&amp;#39;)) {
                const port = baseItem.split(&amp;#39;:&amp;#39;)[1];
                if (!httpsPorts.includes(port)) {
                  return baseItem;
                }
              } else {
                return `${baseItem}:443`;
              }
              return null; // 不符合条件时返回 null
            }).filter(Boolean)); // 过滤掉 null 值
          }
          // 将内容添加到newapi中
          newapi += content + &amp;#39;\n&amp;#39;;
        }
      }
    }
  } catch (error) {
    console.error(error);
  } finally {
    // 无论成功或失败，最后都清除设置的超时定时器
    clearTimeout(timeout);
  }

  const newAddressesapi = await 整理(newapi);

  // 返回处理后的结果
  return newAddressesapi;
}

async function 整理测速结果(tls) {
  if (!addressescsv || addressescsv.length === 0) {
    return [];
  }

  let newAddressescsv = [];

  for (const csvUrl of addressescsv) {
    try {
      const response = await fetch(csvUrl);

      if (!response.ok) {
        console.error(&amp;#39;获取CSV地址时出错:&amp;#39;, response.status, response.statusText);
        continue;
      }

      const text = await response.text();// 使用正确的字符编码解析文本内容
      let lines;
      if (text.includes(&amp;#39;\r\n&amp;#39;)) {
        lines = text.split(&amp;#39;\r\n&amp;#39;);
      } else {
        lines = text.split(&amp;#39;\n&amp;#39;);
      }

      // 检查CSV头部是否包含必需字段
      const header = lines[0].split(&amp;#39;,&amp;#39;);
      const tlsIndex = header.indexOf(&amp;#39;TLS&amp;#39;);

      const ipAddressIndex = 0;// IP地址在 CSV 头部的位置
      const portIndex = 1;// 端口在 CSV 头部的位置
      const dataCenterIndex = tlsIndex + remarkIndex; // 数据中心是 TLS 的后一个字段

      if (tlsIndex === -1) {
        console.error(&amp;#39;CSV文件缺少必需的字段&amp;#39;);
        continue;
      }

      // 从第二行开始遍历CSV行
      for (let i = 1; i &amp;lt; lines.length; i++) {
        const columns = lines[i].split(&amp;#39;,&amp;#39;);
        const speedIndex = columns.length - 1; // 最后一个字段
        // 检查TLS是否为&amp;quot;TRUE&amp;quot;且速度大于DLS
        if (columns[tlsIndex].toUpperCase() === tls &amp;amp;&amp;amp; parseFloat(columns[speedIndex]) &amp;gt; DLS) {
          const ipAddress = columns[ipAddressIndex];
          const port = columns[portIndex];
          const dataCenter = columns[dataCenterIndex];

          const formattedAddress = `${ipAddress}:${port}#${dataCenter}`;
          newAddressescsv.push(formattedAddress);
          if (csvUrl.includes(&amp;#39;proxyip=true&amp;#39;) &amp;amp;&amp;amp; columns[tlsIndex].toUpperCase() == &amp;#39;true&amp;#39; &amp;amp;&amp;amp; !httpsPorts.includes(port)) {
            // 如果URL带有&amp;#39;proxyip=true&amp;#39;，则将内容添加到proxyIPPool
            proxyIPPool.push(`${ipAddress}:${port}`);
          }
        }
      }
    } catch (error) {
      console.error(&amp;#39;获取CSV地址时出错:&amp;#39;, error);
      continue;
    }
  }

  return newAddressescsv;
}

function 生成本地订阅(host, UUID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv) {
  const regex = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[.*\]):?(\d+)?#?(.*)?$/;
  addresses = addresses.concat(newAddressesapi);
  addresses = addresses.concat(newAddressescsv);
  let notlsresponseBody;
  if (noTLS == &amp;#39;true&amp;#39;) {
    addressesnotls = addressesnotls.concat(newAddressesnotlsapi);
    addressesnotls = addressesnotls.concat(newAddressesnotlscsv);
    const uniqueAddressesnotls = [...new Set(addressesnotls)];

    notlsresponseBody = uniqueAddressesnotls.map(address =&amp;gt; {
      let port = &amp;quot;-1&amp;quot;;
      let addressid = address;

      const match = addressid.match(regex);
      if (!match) {
        if (address.includes(&amp;#39;:&amp;#39;) &amp;amp;&amp;amp; address.includes(&amp;#39;#&amp;#39;)) {
          const parts = address.split(&amp;#39;:&amp;#39;);
          address = parts[0];
          const subParts = parts[1].split(&amp;#39;#&amp;#39;);
          port = subParts[0];
          addressid = subParts[1];
        } else if (address.includes(&amp;#39;:&amp;#39;)) {
          const parts = address.split(&amp;#39;:&amp;#39;);
          address = parts[0];
          port = parts[1];
        } else if (address.includes(&amp;#39;#&amp;#39;)) {
          const parts = address.split(&amp;#39;#&amp;#39;);
          address = parts[0];
          addressid = parts[1];
        }

        if (addressid.includes(&amp;#39;:&amp;#39;)) {
          addressid = addressid.split(&amp;#39;:&amp;#39;)[0];
        }
      } else {
        address = match[1];
        port = match[2] || port;
        addressid = match[3] || address;
      }

      const httpPorts = [&amp;quot;8080&amp;quot;, &amp;quot;8880&amp;quot;, &amp;quot;2052&amp;quot;, &amp;quot;2082&amp;quot;, &amp;quot;2086&amp;quot;, &amp;quot;2095&amp;quot;];
      if (!isValidIPv4(address) &amp;amp;&amp;amp; port == &amp;quot;-1&amp;quot;) {
        for (let httpPort of httpPorts) {
          if (address.includes(httpPort)) {
            port = httpPort;
            break;
          }
        }
      }
      if (port == &amp;quot;-1&amp;quot;) port = &amp;quot;80&amp;quot;;

      let 伪装域名 = host;
      let 最终路径 = path;
      let 节点备注 = &amp;#39;&amp;#39;;
      const 协议类型 = atob(啥啥啥_写的这是啥啊);

      const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob(&amp;#39;P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT0mdHlwZT13cyZob3N0PQ==&amp;#39;) + 伪装域名}&amp;amp;path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`;

      return 维列斯Link;

    }).join(&amp;#39;\n&amp;#39;);

  }

  // 使用Set对象去重
  const uniqueAddresses = [...new Set(addresses)];

  const responseBody = uniqueAddresses.map(address =&amp;gt; {
    let port = &amp;quot;-1&amp;quot;;
    let addressid = address;

    const match = addressid.match(regex);
    if (!match) {
      if (address.includes(&amp;#39;:&amp;#39;) &amp;amp;&amp;amp; address.includes(&amp;#39;#&amp;#39;)) {
        const parts = address.split(&amp;#39;:&amp;#39;);
        address = parts[0];
        const subParts = parts[1].split(&amp;#39;#&amp;#39;);
        port = subParts[0];
        addressid = subParts[1];
      } else if (address.includes(&amp;#39;:&amp;#39;)) {
        const parts = address.split(&amp;#39;:&amp;#39;);
        address = parts[0];
        port = parts[1];
      } else if (address.includes(&amp;#39;#&amp;#39;)) {
        const parts = address.split(&amp;#39;#&amp;#39;);
        address = parts[0];
        addressid = parts[1];
      }

      if (addressid.includes(&amp;#39;:&amp;#39;)) {
        addressid = addressid.split(&amp;#39;:&amp;#39;)[0];
      }
    } else {
      address = match[1];
      port = match[2] || port;
      addressid = match[3] || address;
    }

    if (!isValidIPv4(address) &amp;amp;&amp;amp; port == &amp;quot;-1&amp;quot;) {
      for (let httpsPort of httpsPorts) {
        if (address.includes(httpsPort)) {
          port = httpsPort;
          break;
        }
      }
    }
    if (port == &amp;quot;-1&amp;quot;) port = &amp;quot;443&amp;quot;;

    let 伪装域名 = host;
    let 最终路径 = path;
    let 节点备注 = &amp;#39;&amp;#39;;
    const matchingProxyIP = proxyIPPool.find(proxyIP =&amp;gt; proxyIP.includes(address));
    if (matchingProxyIP) 最终路径 += `&amp;amp;proxyip=${matchingProxyIP}`;

    if (proxyhosts.length &amp;gt; 0 &amp;amp;&amp;amp; (伪装域名.includes(&amp;#39;.workers.dev&amp;#39;))) {
      最终路径 = `/${伪装域名}${最终路径}`;
      伪装域名 = proxyhosts[Math.floor(Math.random() * proxyhosts.length)];
      节点备注 = ` 已启用临时域名中转服务，请尽快绑定自定义域！`;
    }

    const 协议类型 = atob(啥啥啥_写的这是啥啊);
    const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob(&amp;#39;P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT10bHMmc25pPQ==&amp;#39;) + 伪装域名}&amp;amp;fp=random&amp;amp;type=ws&amp;amp;host=${伪装域名}&amp;amp;path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`;

    return 维列斯Link;
  }).join(&amp;#39;\n&amp;#39;);

  let base64Response = responseBody; // 重新进行 Base64 编码
  if (noTLS == &amp;#39;true&amp;#39;) base64Response += `\n${notlsresponseBody}`;
  if (link.length &amp;gt; 0) base64Response += &amp;#39;\n&amp;#39; + link.join(&amp;#39;\n&amp;#39;);
  return btoa(base64Response);
}

async function 整理(内容) {
  // 将制表符、双引号、单引号和换行符都替换为逗号
  // 然后将连续的多个逗号替换为单个逗号
  var 替换后的内容 = 内容.replace(/[  |&amp;quot;&amp;#39;\r\n]+/g, &amp;#39;,&amp;#39;).replace(/,+/g, &amp;#39;,&amp;#39;);

  // 删除开头和结尾的逗号（如果有的话）
  if (替换后的内容.charAt(0) == &amp;#39;,&amp;#39;) 替换后的内容 = 替换后的内容.slice(1);
  if (替换后的内容.charAt(替换后的内容.length - 1) == &amp;#39;,&amp;#39;) 替换后的内容 = 替换后的内容.slice(0, 替换后的内容.length - 1);

  // 使用逗号分割字符串，得到地址数组
  const 地址数组 = 替换后的内容.split(&amp;#39;,&amp;#39;);

  return 地址数组;
}

async function sendMessage(type, ip, add_data = &amp;quot;&amp;quot;) {
  if (!BotToken || !ChatID) return;

  try {
    let msg = &amp;quot;&amp;quot;;
    const response = await fetch(`http://ip-api.com/json/${ip}?lang=zh-CN`);
    if (response.ok) {
      const ipInfo = await response.json();
      msg = `${type}\nIP: ${ip}\n国家: ${ipInfo.country}\n&amp;lt;tg-spoiler&amp;gt;城市: ${ipInfo.city}\n组织: ${ipInfo.org}\nASN: ${ipInfo.as}\n${add_data}`;
    } else {
      msg = `${type}\nIP: ${ip}\n&amp;lt;tg-spoiler&amp;gt;${add_data}`;
    }

    const url = `https://api.telegram.org/bot${BotToken}/sendMessage?chat_id=${ChatID}&amp;amp;parse_mode=HTML&amp;amp;text=${encodeURIComponent(msg)}`;
    return fetch(url, {
      method: &amp;#39;GET&amp;#39;,
      headers: {
        &amp;#39;Accept&amp;#39;: &amp;#39;text/html,application/xhtml+xml,application/xml;&amp;#39;,
        &amp;#39;Accept-Encoding&amp;#39;: &amp;#39;gzip, deflate, br&amp;#39;,
        &amp;#39;User-Agent&amp;#39;: &amp;#39;Mozilla/5.0 Chrome/90.0.4430.72&amp;#39;
      }
    });
  } catch (error) {
    console.error(&amp;#39;Error sending message:&amp;#39;, error);
  }
}

function isValidIPv4(address) {
  const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
  return ipv4Regex.test(address);
}

function 生成动态UUID(密钥) {
  const 时区偏移 = 8; // 北京时间相对于UTC的时区偏移+8小时
  const 起始日期 = new Date(2007, 6, 7, 更新时间, 0, 0); // 固定起始日期为2007年7月7日的凌晨3点
  const 一周的毫秒数 = 1000 * 60 * 60 * 24 * 有效时间;

  function 获取当前周数() {
    const 现在 = new Date();
    const 调整后的现在 = new Date(现在.getTime() + 时区偏移 * 60 * 60 * 1000);
    const 时间差 = Number(调整后的现在) - Number(起始日期);
    return Math.ceil(时间差 / 一周的毫秒数);
  }

  function 生成UUID(基础字符串) {
    const 哈希缓冲区 = new TextEncoder().encode(基础字符串);
    return crypto.subtle.digest(&amp;#39;SHA-256&amp;#39;, 哈希缓冲区).then((哈希) =&amp;gt; {
      const 哈希数组 = Array.from(new Uint8Array(哈希));
      const 十六进制哈希 = 哈希数组.map(b =&amp;gt; b.toString(16).padStart(2, &amp;#39;0&amp;#39;)).join(&amp;#39;&amp;#39;);
      return `${十六进制哈希.substr(0, 8)}-${十六进制哈希.substr(8, 4)}-4${十六进制哈希.substr(13, 3)}-${(parseInt(十六进制哈希.substr(16, 2), 16) &amp;amp; 0x3f | 0x80).toString(16)}${十六进制哈希.substr(18, 2)}-${十六进制哈希.substr(20, 12)}`;
    });
  }

  const 当前周数 = 获取当前周数(); // 获取当前周数
  const 结束时间 = new Date(起始日期.getTime() + 当前周数 * 一周的毫秒数);

  // 生成两个 UUID
  const 当前UUIDPromise = 生成UUID(密钥 + 当前周数);
  const 上一个UUIDPromise = 生成UUID(密钥 + (当前周数 - 1));

  // 格式化到期时间
  const 到期时间UTC = new Date(结束时间.getTime() - 时区偏移 * 60 * 60 * 1000); // UTC时间
  const 到期时间字符串 = `到期时间(UTC): ${到期时间UTC.toISOString().slice(0, 19).replace(&amp;#39;T&amp;#39;, &amp;#39; &amp;#39;)} (UTC+8): ${结束时间.toISOString().slice(0, 19).replace(&amp;#39;T&amp;#39;, &amp;#39; &amp;#39;)}\n`;

  return Promise.all([当前UUIDPromise, 上一个UUIDPromise, 到期时间字符串]);
}

async function 迁移地址列表(env, txt = &amp;#39;ADD.txt&amp;#39;) {
  const 旧数据 = await env.KV.get(`/${txt}`);
  const 新数据 = await env.KV.get(txt);

  if (旧数据 &amp;amp;&amp;amp; !新数据) {
    // 写入新位置
    await env.KV.put(txt, 旧数据);
    // 删除旧数据
    await env.KV.delete(`/${txt}`);
    return true;
  }
  return false;
}

async function KV(request, env, txt = &amp;#39;ADD.txt&amp;#39;) {
  try {
    // POST请求处理
    if (request.method === &amp;quot;POST&amp;quot;) {
      if (!env.KV) return new Response(&amp;quot;未绑定KV空间&amp;quot;, { status: 400 });
      try {
        const content = await request.text();
        await env.KV.put(txt, content);
        return new Response(&amp;quot;保存成功&amp;quot;);
      } catch (error) {
        console.error(&amp;#39;保存KV时发生错误:&amp;#39;, error);
        return new Response(&amp;quot;保存失败: &amp;quot; + error.message, { status: 500 });
      }
    }

    // GET请求部分
    let content = &amp;#39;&amp;#39;;
    let hasKV = !!env.KV;

    if (hasKV) {
      try {
        content = await env.KV.get(txt) || &amp;#39;&amp;#39;;
      } catch (error) {
        console.error(&amp;#39;读取KV时发生错误:&amp;#39;, error);
        content = &amp;#39;读取数据时发生错误: &amp;#39; + error.message;
      }
    }

    const html = `
      &amp;lt;!DOCTYPE html&amp;gt;
      &amp;lt;html&amp;gt;
      &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;优选订阅列表&amp;lt;/title&amp;gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
        &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1&amp;quot;&amp;gt;
        &amp;lt;style&amp;gt;
          body {
            margin: 0;
            padding: 15px; /* 调整padding */
            box-sizing: border-box;
            font-size: 13px; /* 设置全局字体大小 */
          }
          .editor-container {
            width: 100%;
            max-width: 100%;
            margin: 0 auto;
          }
          .editor {
            width: 100%;
            height: 520px; /* 调整高度 */
            margin: 15px 0; /* 调整margin */
            padding: 10px; /* 调整padding */
            box-sizing: border-box;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 13px;
            line-height: 1.5;
            overflow-y: auto;
            resize: none;
          }
          .save-container {
            margin-top: 8px; /* 调整margin */
            display: flex;
            align-items: center;
            gap: 10px; /* 调整gap */
          }
          .save-btn, .back-btn {
            padding: 6px 15px; /* 调整padding */
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
          }
          .save-btn {
            background: #4CAF50;
          }
          .save-btn:hover {
            background: #45a049;
          }
          .back-btn {
            background: #666;
          }
          .back-btn:hover {
            background: #555;
          }
          .save-status {
            color: #666;
          }
          .notice-content {
            display: none;
            margin-top: 10px;
            font-size: 13px;
            color: #333;
          }
        &amp;lt;/style&amp;gt;
      &amp;lt;/head&amp;gt;
      &amp;lt;body&amp;gt;
        ################################################################&amp;lt;br&amp;gt;
        ${FileName} 优选订阅列表:&amp;lt;br&amp;gt;
        ---------------------------------------------------------------&amp;lt;br&amp;gt;
          &amp;lt;strong&amp;gt;&amp;lt;a href=&amp;quot;javascript:void(0);&amp;quot; id=&amp;quot;noticeToggle&amp;quot; onclick=&amp;quot;toggleNotice()&amp;quot;&amp;gt;注意事项∨&amp;lt;/a&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
        &amp;lt;div id=&amp;quot;noticeContent&amp;quot; class=&amp;quot;notice-content&amp;quot;&amp;gt;
          ${decodeURIComponent(atob(&amp;#39;JTA5JTA5JTA5JTA5JTA5JTNDc3Ryb25nJTNFMS4lM0MlMkZzdHJvbmclM0UlMjBBRERBUEklMjAlRTUlQTYlODIlRTYlOUUlOUMlRTYlOTglQUYlRTUlOEYlOEQlRTQlQkIlQTNJUCVFRiVCQyU4QyVFNSU4RiVBRiVFNCVCRCU5QyVFNCVCOCVCQVBST1hZSVAlRTclOUElODQlRTglQUYlOUQlRUYlQkMlOEMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwcm94eWlwJTNEdHJ1ZSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGYWRkcmVzc2VzYXBpLnR4dCUzQ3N0cm9uZyUzRSUzRnByb3h5aXAlM0R0cnVlJTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklM0NzdHJvbmclM0UyLiUzQyUyRnN0cm9uZyUzRSUyMEFEREFQSSUyMCVFNSVBNiU4MiVFNiU5RSU5QyVFNiU5OCVBRiUyMCUzQ2ElMjBocmVmJTNEJTI3aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGWElVMiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QlMjclM0VDbG91ZGZsYXJlU3BlZWRUZXN0JTNDJTJGYSUzRSUyMCVFNyU5QSU4NCUyMGNzdiUyMCVFNyVCQiU5MyVFNiU5RSU5QyVFNiU5NiU4NyVFNCVCQiVCNiVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NiciUzRSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCLSUyMCVFNSVBNiU4MiVFOSU5QyU4MCVFNiU4QyU4NyVFNSVBRSU5QTIwNTMlRTclQUIlQUYlRTUlOEYlQTMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwb3J0JTNEMjA1MyUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0Zwb3J0JTNEMjA1MyUzQyUyRnN0cm9uZyUzRSUzQ2JyJTNFJTNDYnIlM0UKJTA5JTA5JTA5JTA5JTA5JTI2bmJzcCUzQiUyNm5ic3AlM0ItJTIwJUU1JUE2JTgyJUU5JTlDJTgwJUU2JThDJTg3JUU1JUFFJTlBJUU4JThBJTgyJUU3JTgyJUI5JUU1JUE0JTg3JUU2JUIzJUE4JUU1JThGJUFGJUU1JUIwJTg2JTIyJTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0ZpZCUzRENGJUU0JUJDJTk4JUU5JTgwJTg5JTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQi0lMjAlRTUlQTYlODIlRTklOUMlODAlRTYlOEMlODclRTUlQUUlOUElRTUlQTQlOUElRTQlQjglQUElRTUlOEYlODIlRTYlOTUlQjAlRTUlODglOTklRTklOUMlODAlRTglQTYlODElRTQlQkQlQkYlRTclOTQlQTglMjclMjYlMjclRTUlODElOUElRTklOTclQjQlRTklOUElOTQlRUYlQkMlOEMlRTQlQkUlOEIlRTUlQTYlODIlRUYlQkMlOUElM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGbWFpbiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QuY3N2JTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUzQ3N0cm9uZyUzRSUyNiUzQyUyRnN0cm9uZyUzRXBvcnQlM0QyMDUzJTNDYnIlM0U=&amp;#39;))}
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;editor-container&amp;quot;&amp;gt;
          ${hasKV ? `
          &amp;lt;textarea class=&amp;quot;editor&amp;quot; 
            placeholder=&amp;quot;${decodeURIComponent(atob(&amp;#39;QUREJUU3JUE0JUJBJUU0JUJFJThCJUVGJUJDJTlBCnZpc2EuY24lMjMlRTQlQkMlOTglRTklODAlODklRTUlOUYlOUYlRTUlOTAlOEQKMTI3LjAuMC4xJTNBMTIzNCUyM0NGbmF0CiU1QjI2MDYlM0E0NzAwJTNBJTNBJTVEJTNBMjA1MyUyM0lQdjYKCiVFNiVCMyVBOCVFNiU4NCU4RiVFRiVCQyU5QQolRTYlQUYlOEYlRTglQTElOEMlRTQlQjglODAlRTQlQjglQUElRTUlOUMlQjAlRTUlOUQlODAlRUYlQkMlOEMlRTYlQTAlQkMlRTUlQkMlOEYlRTQlQjglQkElMjAlRTUlOUMlQjAlRTUlOUQlODAlM0ElRTclQUIlQUYlRTUlOEYlQTMlMjMlRTUlQTQlODclRTYlQjMlQTgKSVB2NiVFNSU5QyVCMCVFNSU5RCU4MCVFOSU5QyU4MCVFOCVBNiU4MSVFNyU5NCVBOCVFNCVCOCVBRCVFNiU4QiVBQyVFNSU4RiVCNyVFNiU4QiVBQyVFOCVCNSVCNyVFNiU5RCVBNSVFRiVCQyU4QyVFNSVBNiU4MiVFRiVCQyU5QSU1QjI2MDYlM0E0NzAwJTNBJTNBJTVEJTNBMjA1MwolRTclQUIlQUYlRTUlOEYlQTMlRTQlQjglOEQlRTUlODYlOTklRUYlQkMlOEMlRTklQkIlOTglRTglQUUlQTQlRTQlQjglQkElMjA0NDMlMjAlRTclQUIlQUYlRTUlOEYlQTMlRUYlQkMlOEMlRTUlQTYlODIlRUYlQkMlOUF2aXNhLmNuJTIzJUU0JUJDJTk4JUU5JTgwJTg5JUU1JTlGJTlGJUU1JTkwJThECgoKQUREQVBJJUU3JUE0JUJBJUU0JUJFJThCJUVGJUJDJTlBCmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGcmVmcyUyRmhlYWRzJTJGbWFpbiUyRmFkZHJlc3Nlc2FwaS50eHQKCiVFNiVCMyVBOCVFNiU4NCU4RiVFRiVCQyU5QUFEREFQSSVFNyU5QiVCNCVFNiU4RSVBNSVFNiVCNyVCQiVFNSU4QSVBMCVFNyU5QiVCNCVFOSU5MyVCRSVFNSU4RCVCMyVFNSU4RiVBRg==&amp;#39;))}&amp;quot;
            id=&amp;quot;content&amp;quot;&amp;gt;${content}&amp;lt;/textarea&amp;gt;
          &amp;lt;div class=&amp;quot;save-container&amp;quot;&amp;gt;
            &amp;lt;button class=&amp;quot;back-btn&amp;quot; onclick=&amp;quot;goBack()&amp;quot;&amp;gt;返回配置页&amp;lt;/button&amp;gt;
            &amp;lt;button class=&amp;quot;save-btn&amp;quot; onclick=&amp;quot;saveContent(this)&amp;quot;&amp;gt;保存&amp;lt;/button&amp;gt;
            &amp;lt;span class=&amp;quot;save-status&amp;quot; id=&amp;quot;saveStatus&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;br&amp;gt;
          ################################################################&amp;lt;br&amp;gt;
          ${cmad}
          ` : &amp;#39;&amp;lt;p&amp;gt;未绑定KV空间&amp;lt;/p&amp;gt;&amp;#39;}
        &amp;lt;/div&amp;gt;
    
        &amp;lt;script&amp;gt;
        if (document.querySelector(&amp;#39;.editor&amp;#39;)) {
          let timer;
          const textarea = document.getElementById(&amp;#39;content&amp;#39;);
          const originalContent = textarea.value;
    
          function goBack() {
            const currentUrl = window.location.href;
            const parentUrl = currentUrl.substring(0, currentUrl.lastIndexOf(&amp;#39;/&amp;#39;));
            window.location.href = parentUrl;
          }
    
          function replaceFullwidthColon() {
            const text = textarea.value;
            textarea.value = text.replace(/：/g, &amp;#39;:&amp;#39;);
          }
          
          function saveContent(button) {
            try {
              const updateButtonText = (step) =&amp;gt; {
                button.textContent = \`保存中: \${step}\`;
              };
              // 检测是否为iOS设备
              const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
              
              // 仅在非iOS设备上执行replaceFullwidthColon
              if (!isIOS) {
                replaceFullwidthColon();
              }
              updateButtonText(&amp;#39;开始保存&amp;#39;);
              button.disabled = true;
              // 获取textarea内容和原始内容
              const textarea = document.getElementById(&amp;#39;content&amp;#39;);
              if (!textarea) {
                throw new Error(&amp;#39;找不到文本编辑区域&amp;#39;);
              }
              updateButtonText(&amp;#39;获取内容&amp;#39;);
              let newContent;
              let originalContent;
              try {
                newContent = textarea.value || &amp;#39;&amp;#39;;
                originalContent = textarea.defaultValue || &amp;#39;&amp;#39;;
              } catch (e) {
                console.error(&amp;#39;获取内容错误:&amp;#39;, e);
                throw new Error(&amp;#39;无法获取编辑内容&amp;#39;);
              }
              updateButtonText(&amp;#39;准备状态更新函数&amp;#39;);
              const updateStatus = (message, isError = false) =&amp;gt; {
                const statusElem = document.getElementById(&amp;#39;saveStatus&amp;#39;);
                if (statusElem) {
                  statusElem.textContent = message;
                  statusElem.style.color = isError ? &amp;#39;red&amp;#39; : &amp;#39;#666&amp;#39;;
                }
              };
              updateButtonText(&amp;#39;准备按钮重置函数&amp;#39;);
              const resetButton = () =&amp;gt; {
                button.textContent = &amp;#39;保存&amp;#39;;
                button.disabled = false;
              };
              if (newContent !== originalContent) {
                updateButtonText(&amp;#39;发送保存请求&amp;#39;);
                fetch(window.location.href, {
                  method: &amp;#39;POST&amp;#39;,
                  body: newContent,
                  headers: {
                    &amp;#39;Content-Type&amp;#39;: &amp;#39;text/plain;charset=UTF-8&amp;#39;
                  },
                  cache: &amp;#39;no-cache&amp;#39;
                })
                .then(response =&amp;gt; {
                  updateButtonText(&amp;#39;检查响应状态&amp;#39;);
                  if (!response.ok) {
                    throw new Error(\`HTTP error! status: \${response.status}\`);
                  }
                  updateButtonText(&amp;#39;更新保存状态&amp;#39;);
                  const now = new Date().toLocaleString();
                  document.title = \`编辑已保存 \${now}\`;
                  updateStatus(\`已保存 \${now}\`);
                })
                .catch(error =&amp;gt; {
                  updateButtonText(&amp;#39;处理错误&amp;#39;);
                  console.error(&amp;#39;Save error:&amp;#39;, error);
                  updateStatus(\`保存失败: \${error.message}\`, true);
                })
                .finally(() =&amp;gt; {
                  resetButton();
                });
              } else {
                updateButtonText(&amp;#39;检查内容变化&amp;#39;);
                updateStatus(&amp;#39;内容未变化&amp;#39;);
                resetButton();
              }
            } catch (error) {
              console.error(&amp;#39;保存过程出错:&amp;#39;, error);
              button.textContent = &amp;#39;保存&amp;#39;;
              button.disabled = false;
              const statusElem = document.getElementById(&amp;#39;saveStatus&amp;#39;);
              if (statusElem) {
                statusElem.textContent = \`错误: \${error.message}\`;
                statusElem.style.color = &amp;#39;red&amp;#39;;
              }
            }
          }
    
          textarea.addEventListener(&amp;#39;blur&amp;#39;, saveContent);
          textarea.addEventListener(&amp;#39;input&amp;#39;, () =&amp;gt; {
            clearTimeout(timer);
            timer = setTimeout(saveContent, 5000);
          });
        }
    
        function toggleNotice() {
          const noticeContent = document.getElementById(&amp;#39;noticeContent&amp;#39;);
          const noticeToggle = document.getElementById(&amp;#39;noticeToggle&amp;#39;);
          if (noticeContent.style.display === &amp;#39;none&amp;#39; || noticeContent.style.display === &amp;#39;&amp;#39;) {
            noticeContent.style.display = &amp;#39;block&amp;#39;;
            noticeToggle.textContent = &amp;#39;注意事项∧&amp;#39;;
          } else {
            noticeContent.style.display = &amp;#39;none&amp;#39;;
            noticeToggle.textContent = &amp;#39;注意事项∨&amp;#39;;
          }
        }
    
        // 初始化 noticeContent 的 display 属性
        document.addEventListener(&amp;#39;DOMContentLoaded&amp;#39;, () =&amp;gt; {
          document.getElementById(&amp;#39;noticeContent&amp;#39;).style.display = &amp;#39;none&amp;#39;;
        });
        &amp;lt;/script&amp;gt;
      &amp;lt;/body&amp;gt;
      &amp;lt;/html&amp;gt;
    `;

    return new Response(html, {
      headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;text/html;charset=utf-8&amp;quot; }
    });
  } catch (error) {
    console.error(&amp;#39;处理请求时发生错误:&amp;#39;, error);
    return new Response(&amp;quot;服务器错误: &amp;quot; + error.message, {
      status: 500,
      headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain;charset=utf-8&amp;quot; }
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 22 Jul 2025 00:00:00 GMT</pubDate></item><item><title>📦 PicGo + GitHub 图床搭建指南</title><link>https://hub.xiaozhangya.xin/blog/picgogithub-imgbed/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/picgogithub-imgbed/</guid><description>PicGO 配合Github仓库：实现免费图床！！！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/picgogithub-imgbed/&quot;&gt;https://hub.xiaozhangya.xin/blog/picgogithub-imgbed/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;搭配使用 &lt;strong&gt;PicGo&lt;/strong&gt; 和 &lt;strong&gt;GitHub&lt;/strong&gt;，可构建一个稳定、免费的图床，非常适合博客、文档插图等静态资源管理。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;⚠️ &lt;span style=&quot;color:#e2d849; font-weight: bold;&quot;&gt;注：GitHub 可能需科学上网才能访问&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color:#ef475d; font-weight: bold;&quot;&gt;科学上网方面可单独联系我（完全无偿）&lt;/span&gt;&lt;br&gt;💬 &lt;strong&gt;WeChat：&lt;/strong&gt; &lt;span style=&quot;color:#1DA1F2; font-weight:bold;&quot;&gt;tzyy131714&lt;/span&gt;  &lt;/p&gt;
&lt;h2&gt;🚧 流程概述&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;创建 GitHub 仓库&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安装 PicGo 客户端&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;获取 GitHub Token&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PicGo 配置 GitHub 图床&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上传测试，自动生成图片链接&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;🔧 准备工作&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;✅ 一个 GitHub 账号：👉 &lt;a href=&quot;https://github.com/&quot;&gt;https://github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;✅ 一个公开仓库（建议命名为 &lt;code&gt;picbed&lt;/code&gt; 或类似）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🛠️ 安装 PicGo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;主下载地址：👉 &lt;a href=&quot;https://github.com/Molunerfinn/PicGo/releases&quot;&gt;&lt;strong&gt;PicGo Releases&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;备用下载： 👉 &lt;a href=&quot;https://op.xiaozhangya.xin/software/PicGo-Setup-2.3.1-x64.exe&quot;&gt;&lt;strong&gt;点击下载 PicGo 2.3.1 x64&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;支持系统：&lt;strong&gt;Windows / macOS / Linux&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;⚙️ 配置 GitHub 图床&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;打开 &lt;strong&gt;PicGo&lt;/strong&gt; → 左侧选择【图床设置】 → 添加图床类型：&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;填写以下信息：&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;设置项&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;示例&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;仓库名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;yourusername/picbed&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分支名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;main&lt;/code&gt;（或 &lt;code&gt;master&lt;/code&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;生成 GitHub Token&lt;/a&gt;，勾选 &lt;code&gt;repo&lt;/code&gt; 权限&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;存储路径&lt;/td&gt;
&lt;td&gt;&lt;code&gt;img/&lt;/code&gt;（可选）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;自定义域名&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://raw.githubusercontent.com&lt;/code&gt;（或 CDN 加速域名）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ol&gt;
&lt;li&gt;设置完毕后，点击「&lt;strong&gt;设为默认图床&lt;/strong&gt;」，并保存配置 ✅&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;🚀 上传使用&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;打开 &lt;strong&gt;PicGo 主界面&lt;/strong&gt; → 拖拽图片或点击选择图片上传&lt;/li&gt;
&lt;li&gt;上传成功后，自动复制 Markdown 格式链接到剪贴板：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;![image](https://raw.githubusercontent.com/yourusername/picbed/main/img/yourimage.png)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;📌 推荐使用 &lt;strong&gt;jsDelivr CDN 加速&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;https://cdn.jsdelivr.net/gh/yourusername/picbed@main/img/yourimage.png
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;📁 实操截图&lt;/h2&gt;
&lt;h3&gt;1. GitHub 注册与创建仓库&lt;/h3&gt;
&lt;p&gt;👉 &lt;a href=&quot;https://github.com/signup&quot;&gt;&lt;strong&gt;点击注册 GitHub 账号&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250708233052803.png&quot; alt=&quot;注册账号&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250708234253092.png&quot; alt=&quot;创建仓库&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2. 创建 GitHub Token&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250709000417470.png&quot; alt=&quot;生成 Token&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3. PicGo GitHub 图床配置&lt;/h3&gt;
&lt;p&gt;📁 添加图床配置：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250709001039193.png&quot; alt=&quot;添加图床&quot;&gt;&lt;/p&gt;
&lt;p&gt;📝 填写配置信息：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250709002102369.png&quot; alt=&quot;配置内容&quot;&gt;&lt;/p&gt;
&lt;p&gt;💾 保存后查看图床列表：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250709004155718.png&quot; alt=&quot;保存配置&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🌐 GitHub Pages 简介（可选加速）&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pages.github.com/&quot;&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/a&gt; 是 GitHub 提供的免费静态网站托管服务，可用于自定义域名/CDN 加速等。&lt;/p&gt;
&lt;h3&gt;✅ 特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;🆓 免费的子域名（如：&lt;code&gt;username.github.io&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;🔧 支持绑定自定义域名（如 &lt;code&gt;www.example.com&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;⚙️ 支持 Jekyll 等静态站点生成器&lt;/li&gt;
&lt;li&gt;🚀 推送即部署，无需服务器配置&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🚀 启用方法&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;创建公开仓库 &lt;code&gt;yourname.github.io&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;上传 HTML/CSS/JS 等网页文件&lt;/li&gt;
&lt;li&gt;打开仓库 → &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;Pages&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;选择发布源（如 &lt;code&gt;main&lt;/code&gt; 分支 &lt;code&gt;/root&lt;/code&gt; 路径）&lt;/li&gt;
&lt;li&gt;稍等几秒，即可访问公开站点！&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;📸 页面配置示意：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/picgo-github/20250709003908369.png&quot; alt=&quot;GitHub Pages 设置&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;🎉 至此，&lt;strong&gt;PicGo + GitHub 图床搭建完成！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如需进一步优化（CDN、备份、自动命名等），可探索 PicGo 插件或绑定自定义域名。&lt;/p&gt;
&lt;p&gt;🚀 欢迎将此方案用于博客、笔记、技术文档等静态资源托管！&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 22 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🏐 排球少年！！动画资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/pai_qiu_shao_nian/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/pai_qiu_shao_nian/</guid><description>立志成为如“巨人之手”的高中排球选手，身材矮小的日向翔阳在中学时代成立排球队，却在首战中惨败给“球场之王”影山飞雄。高中时代二人意外成为队友，凭借“身高劣势+迅捷攻防”的奇想组合，带领烏野高中排球队逐步成长，挑战全国顶尖劲旅。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/pai_qiu_shao_nian/&quot;&gt;https://hub.xiaozhangya.xin/blog/pai_qiu_shao_nian/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🏐 &lt;strong&gt;排球少年！！ &lt;em&gt;Haikyu!!&lt;/em&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/post/s9S70YU7.png&quot; alt=&quot;poster&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：运动 · 少年 · 校园  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作&lt;/strong&gt;：古馆春一（Haruichi Furudate）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：Production I.G  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2014‑04‑06 至 2020‑12‑18  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配音阵容（部分）&lt;/strong&gt;：&lt;br&gt;村濑步（日向翔阳）、石川界人（影山飞雄）、梶裕贵（孤爪研磨）、中村悠一（黑尾铁朗）、浪川大辅（及川彻）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;立志成为如“巨人之手”的高中排球选手，身材矮小的日向翔阳在中学时代成立排球队，却在首战中惨败给“球场之王”影山飞雄。高中时代二人意外成为队友，凭借“身高劣势+迅捷攻防”的奇想组合，带领烏野高中排球队逐步成长，挑战全国顶尖劲旅。:contentReference[oaicite:1]{index=1}&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎬 动画各季信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第1季&lt;/td&gt;
&lt;td&gt;排球少年！！ 第一季&lt;/td&gt;
&lt;td&gt;2014‑04‑06 ~ 2014‑09‑21&lt;/td&gt;
&lt;td&gt;25（+OAD）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第2季&lt;/td&gt;
&lt;td&gt;排球少年！！ Second Season&lt;/td&gt;
&lt;td&gt;2015‑10‑03 ~ 2016‑03‑26&lt;/td&gt;
&lt;td&gt;25（+OAD）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第3季&lt;/td&gt;
&lt;td&gt;排球少年！！ 乌野高中 VS 白鸟泽学园高校&lt;/td&gt;
&lt;td&gt;2016‑10‑07 ~ 2016‑12‑09&lt;/td&gt;
&lt;td&gt;10（+特辑）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第4季&lt;/td&gt;
&lt;td&gt;排球少年！！ TO THE TOP&lt;/td&gt;
&lt;td&gt;2020‑01‑10 ~ 2020‑12‑18&lt;/td&gt;
&lt;td&gt;25（+OVA）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;剧场版&lt;/td&gt;
&lt;td&gt;垃圾场的决战（The Dumpster Battle）&lt;/td&gt;
&lt;td&gt;2024‑02‑16（日本）&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;续篇剧场版&lt;/td&gt;
&lt;td&gt;VS 小巨人（Vs. The Little Giant，制作中）&lt;/td&gt;
&lt;td&gt;预计上映于 2025‑03‑02 :contentReference[oaicite:2]{index=2}&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;📺 动画各季详情&lt;/h2&gt;
&lt;hr&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/60863/season/1&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第1季-TMDB-blue?style=for-the-badge&quot; alt=&quot;第1季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/60863/season/2&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第2季-TMDB-green?style=for-the-badge&quot; alt=&quot;第2季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/60863/season/3&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第3季-TMDB-orange?style=for-the-badge&quot; alt=&quot;第3季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/60863/season/4&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第4季-TMDB-red?style=for-the-badge&quot; alt=&quot;第4季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;


&lt;hr&gt;
&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;hr&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/f7fa24d6e2bf&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ 支持在线观看与打包下载，推荐使用夸克客户端或 PC 浏览器！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;《排球少年！！》以“矮个少年”的励志形象为切入口，通过日向与影山的成长与团队协作，展现运动中最纯粹的热血与友情。无论你是热爱体育、励志故事或青春校园题材，都难以抵抗那份拼尽全力、跳跃欢呼的心动瞬间。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“即使飞不高，我也要成为在场上闪耀的存在。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 22 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🌟 OpenList本地部署（Windows）！</title><link>https://hub.xiaozhangya.xin/blog/openlist/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/openlist/</guid><description>在本地电脑部署一个超级网盘集结器，当然也包含本机存储！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/openlist/&quot;&gt;https://hub.xiaozhangya.xin/blog/openlist/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🎉 OpenList 本地部署指南（Windows）&lt;/h1&gt;
&lt;h2&gt;📁 1. 文件准备&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ 注意：原 Alist 项目已被出售，存在数据安全隐患，推荐使用 &lt;strong&gt;OpenList&lt;/strong&gt; 替代。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;🔗 &lt;strong&gt;官方下载地址：&lt;/strong&gt;
&lt;a href=&quot;https://github.com/OpenListTeam/OpenList/releases&quot;&gt;👉 OpenList Releases（GitHub）&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📌 请根据你的 Windows 系统架构选择对应版本下载，&lt;strong&gt;推荐默认下载后缀为 &lt;code&gt;amd64&lt;/code&gt; 的 ZIP 文件&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123097.png&quot; alt=&quot;下载包选择示意图&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🚀 2. 启动本地服务&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;解压下载的 ZIP 文件，&lt;strong&gt;默认仅包含 &lt;code&gt;openlist.exe&lt;/code&gt; 文件&lt;/strong&gt;。
启动后会自动生成 &lt;code&gt;data&lt;/code&gt; 目录，其他脚本为后续设置自启动使用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123096.png&quot; alt=&quot;解压目录结构&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;进入该目录，在地址栏输入 &lt;code&gt;cmd&lt;/code&gt; 回车，打开命令行窗口，执行以下命令启动服务：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openlist.exe server
# 或者
openlist server
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;启动成功后，命令行窗口将输出如下内容：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123095.png&quot; alt=&quot;服务启动效果&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;🌐 3. 访问 OpenList UI 页面&lt;/h2&gt;
&lt;p&gt;🔗 浏览器输入以下任一地址访问 Web UI：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://localhost:5244
http://127.0.0.1:5244
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;📌 &lt;strong&gt;默认账号密码如下：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用户名：&lt;/strong&gt; &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;密码：&lt;/strong&gt; 启动服务时生成（可后续修改）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123094.png&quot; alt=&quot;登录页面&quot;&gt;&lt;/p&gt;
&lt;p&gt;📂 登录后即可看到已挂载的网盘、本机存储等资源：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123102.png&quot; alt=&quot;UI展示图&quot;&gt;&lt;/p&gt;
&lt;p&gt;⚙️ 更多配置可在页面底部的管理栏中完成，如：存储添加、用户管理等。&lt;/p&gt;
&lt;p&gt;📖 &lt;strong&gt;官方文档（强烈推荐查阅）：&lt;/strong&gt;
&lt;a href=&quot;https://docs.oplist.org/zh/&quot;&gt;📘 OpenList 使用文档&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123100.png&quot; alt=&quot;文档图示&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🔄 4. 设置开机自启动&lt;/h2&gt;
&lt;p&gt;📦 &lt;strong&gt;自启动脚本下载地址：&lt;/strong&gt;
&lt;a href=&quot;https://openlist.xiaozhangya.xin/software/OpenList%E8%87%AA%E5%90%AF%E5%8A%A8&quot;&gt;📥 点击下载（run.vbs 脚本）&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;📌 步骤如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;将下载的脚本放入 &lt;strong&gt;OpenList 安装目录&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;为 &lt;code&gt;run.vbs&lt;/code&gt; 创建快捷方式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;按下 &lt;code&gt;Win + R&lt;/code&gt;，输入 &lt;code&gt;shell:startup&lt;/code&gt; 并回车。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;将快捷方式拖入打开的启动目录中：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123099.png&quot; alt=&quot;自启动设置步骤图&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;✅ 部署完成！&lt;/h2&gt;
&lt;p&gt;🎉 至此，OpenList 本地部署已经全部完成，快去享受属于自己的私有网盘服务吧！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141123098.png&quot; alt=&quot;结尾图&quot;&gt;&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Mon, 21 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🌸 葬送的芙莉莲动画资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/zang_song_de_fu_li_lian/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/zang_song_de_fu_li_lian/</guid><description>魔王被击败后，英雄一行人解散，精灵魔法使「芙莉莲」开始漫长的旅程。寿命悠长的她，在送别昔日伙伴的过程中逐渐理解人类情感与“别离”的重量。她与新的同伴一同踏上旅途，不再是打倒敌人的冒险，而是一次感悟人生、治愈人心的旅程</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/zang_song_de_fu_li_lian/&quot;&gt;https://hub.xiaozhangya.xin/blog/zang_song_de_fu_li_lian/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🌸 &lt;strong&gt;葬送的芙莉莲（Sousou no Frieren）&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/post/pJmK9rJO.webp&quot; alt=&quot;poster&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：奇幻 · 冒险 · 治愈 · 人生  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作&lt;/strong&gt;：山田钟人（原作）、阿部司（作画）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：MADHOUSE  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2023‑09‑29 起  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配音阵容&lt;/strong&gt;：&lt;br&gt;种崎敦美（芙莉莲）、市之濑加那（费伦）、小林千晃（施塔克）、冈本信彦（辛美尔）、东地宏树（海塔）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;魔王被击败后，英雄一行人解散，精灵魔法使「芙莉莲」开始漫长的旅程。寿命悠长的她，在送别昔日伙伴的过程中逐渐理解人类情感与“别离”的重量。她与新的同伴一同踏上旅途，不再是打倒敌人的冒险，而是一次感悟人生、治愈人心的旅程。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎬 动画各季信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第1季&lt;/td&gt;
&lt;td&gt;葬送的芙莉莲 第一季&lt;/td&gt;
&lt;td&gt;2023‑09‑29 ~ 2024‑03‑22&lt;/td&gt;
&lt;td&gt;28 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第2季&lt;/td&gt;
&lt;td&gt;葬送的芙莉莲 第二季（制作中）&lt;/td&gt;
&lt;td&gt;待定&lt;/td&gt;
&lt;td&gt;待定&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;📺 动画各季详情&lt;/h2&gt;
&lt;hr&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/209867/season/1&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第1季-TMDB-blueviolet?style=for-the-badge&quot;
    alt=&quot;第1季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/209867/season/2&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第2季-制作中-yellow?style=for-the-badge&quot;
    alt=&quot;第2季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/0c75eae575fd&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;✅ 画质丰富（2160P/1080P），支持在线观看，推荐使用夸克客户端或 PC 浏览器访问！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;与热血冒险截然不同，《葬送的芙莉莲》以“后冒险时代”为背景，讲述一个关于回忆、告别与成长的故事。它是静谧如水的旅程，也是感动人心的哲思绘卷。若你曾为英雄的胜利欢呼，不妨来聆听战后静谧时光中，那位长寿精灵的心声。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“与你们一起的十年，只是我长久人生的一瞬，但却是最不可替代的回忆。”&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Mon, 21 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🌟 CloudFlare ImgBed：美化界面✨与无限存储🚀的完美结合！</title><link>https://hub.xiaozhangya.xin/blog/cloudflare-imgbed/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/cloudflare-imgbed/</guid><description>Telegram 配合Cloudflare ImgBed：实现无限存储空间的图床！！！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/cloudflare-imgbed/&quot;&gt;https://hub.xiaozhangya.xin/blog/cloudflare-imgbed/&lt;/a&gt;&lt;/blockquote&gt; &lt;div align=&quot;center&quot;&gt;
        &lt;img width=&quot;80%&quot; alt=&quot;CloudFlare ImgBed logo&quot; src=&quot;https://img.xiaozhangya.xin/file/Customer/1753263471324_image.png&quot;/&gt;
    &lt;p&gt;&lt;em&gt;🗂️ 一个开源的文件托管解决方案，支持 Docker 和无服务器部署，支持 Telegram Bot、Cloudflare R2、S3 等多种存储渠道&lt;/em&gt;&lt;/p&gt;
    &lt;p&gt;
        &lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed/blob/main/README.md&quot;&gt;简体中文&lt;/a&gt; | 
        &lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed/blob/main/README_en.md&quot;&gt;English&lt;/a&gt; | 
        &lt;a href=&quot;https://cfbed.sanyue.de&quot;&gt;官方网站&lt;/a&gt;
    &lt;/p&gt;
&lt;/div&gt;


&lt;h3&gt;🌐 什么是 CloudFlare ImgBed？&lt;/h3&gt;
&lt;p&gt;CloudFlare ImgBed 是一个轻量级、开源的图床解决方案，支持通过多种存储渠道进行图像存储。该项目提供了简单的部署方式，支持 Docker 和无服务器（Serverless）部署，使得用户可以在不同的环境下轻松搭建自己的图床系统。&lt;/p&gt;
&lt;p&gt;通过集成 Telegram Bot，用户可以实现自动上传功能，将图片上传至 Cloudflare R2 或 S3 存储，实现“无限存储”需求，既方便又高效。&lt;/p&gt;
&lt;h3&gt;🔧 功能特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多存储支持&lt;/strong&gt;：支持 Telegram Bot、Cloudflare R2、S3 等多种存储渠道。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker 支持&lt;/strong&gt;：支持 Docker 部署，快速搭建。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无服务器支持&lt;/strong&gt;：可以在云端环境下无缝部署，避免本地存储的限制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动化图床&lt;/strong&gt;：通过 Telegram Bot 自动上传图片，免去手动上传的麻烦。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开源项目&lt;/strong&gt;：项目代码完全开源，任何人都可以贡献或修改。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🚀 部署步骤&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Docker 部署&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;确保已经安装 Docker 和 Docker Compose。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;克隆项目：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/MarSeventh/CloudFlare-ImgBed.git
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;进入项目目录，运行 Docker Compose：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd CloudFlare-ImgBed
docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;通过访问 &lt;code&gt;http://your-domain&lt;/code&gt; 访问图床管理后台。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;无服务器部署&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考官方文档配置无服务器部署，支持 AWS Lambda 等云端服务。&lt;/li&gt;
&lt;li&gt;根据文档中的配置指南，设置环境变量和存储渠道。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;📸 通过 Telegram 实现图像上传&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;通过 Telegram Bot，用户可以直接将图片发送到 Bot，Bot 会自动将图片上传到配置的存储系统中。您可以参考&lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed/blob/main/docs/telegram.md&quot;&gt;官方指南&lt;/a&gt;进行配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🎨 示例展示&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://img.xiaozhangya.xin/file/post/87vzvRFk.png&quot; alt=&quot;CloudFlare ImgBed Example&quot;&gt;&lt;/p&gt;
&lt;p&gt;通过这种方式，您可以轻松管理和分享您的图像资源，无需担心存储限制。&lt;/p&gt;
&lt;h3&gt;💡 常见问题&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;如何修改存储渠道？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;您可以通过修改 &lt;code&gt;config.json&lt;/code&gt; 文件来更改存储渠道设置，例如切换至 Cloudflare R2 或 S3。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;如何更新 Docker 镜像？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;通过以下命令拉取最新镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker pull marseventh/cloudflare-imgbed
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;GitHub 仓库&lt;/strong&gt;：&lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed&quot;&gt;CloudFlare ImgBed GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🎉 进击的巨人全季动画及剧场版资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/jin_ji_de_ju_ren/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/jin_ji_de_ju_ren/</guid><description>海的对面是自由，还是敌人呢？三重高墙围起的人类最后净土，看似和平的世界却隐藏着惊天真相。少年艾伦亲眼目睹母亲被巨人吞噬，发誓杀尽所有巨人。加入调查兵团后，他逐步揭露了「墙内外」世界的真相：不是怪物的侵略，而是人类自身的战争与背叛——人性之战由此展开。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/jin_ji_de_ju_ren/&quot;&gt;https://hub.xiaozhangya.xin/blog/jin_ji_de_ju_ren/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🗡️ &lt;strong&gt;进击的巨人（Attack on Titan）&lt;/strong&gt;&lt;/h1&gt;
&lt;div style=&quot;display:flex; gap:10px; flex-wrap:wrap; justify-content:center;&quot;&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250716180309140.jpg&quot; alt=&quot;Fragments Poster 1&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250716180313745.jpg&quot; alt=&quot;Fragments Poster 2&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
&lt;/div&gt;

&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：黑暗奇幻 · 动作 · 末世  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作&lt;/strong&gt;：谏山创（Hajime Isayama）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：WIT STUDIO（S1–S3） → MAPPA（S4）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2013‑04‑07 至 2023‑11‑05  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配音阵容&lt;/strong&gt;：
梶裕贵（艾伦）、石川由依（三笠）、井上麻里奈（阿尔敏）、神谷浩史（利威尔）、细谷佳正（莱纳）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;三重高墙围起的人类最后净土，看似和平的世界却隐藏着惊天真相。少年艾伦亲眼目睹母亲被巨人吞噬，发誓杀尽所有巨人。加入调查兵团后，他逐步揭露了「墙内外」世界的真相：不是怪物的侵略，而是人类自身的战争与背叛——人性之战由此展开。&lt;/p&gt;
&lt;h2&gt;🎬 动画各季信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第1季&lt;/td&gt;
&lt;td&gt;进击的巨人 第一季&lt;/td&gt;
&lt;td&gt;2013‑04‑07 ~ 2013‑09‑28&lt;/td&gt;
&lt;td&gt;25 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第2季&lt;/td&gt;
&lt;td&gt;进击的巨人 第二季&lt;/td&gt;
&lt;td&gt;2017‑04‑01 ~ 2017‑06‑17&lt;/td&gt;
&lt;td&gt;12 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第3季&lt;/td&gt;
&lt;td&gt;进击的巨人 第三季（前/后篇）&lt;/td&gt;
&lt;td&gt;2018‑07‑23 ~ 2019‑06‑30&lt;/td&gt;
&lt;td&gt;22 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第4季&lt;/td&gt;
&lt;td&gt;进击的巨人 最终季（Final Season）&lt;/td&gt;
&lt;td&gt;2020‑12‑07 ~ 2023‑03‑04&lt;/td&gt;
&lt;td&gt;28 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;特别篇&lt;/td&gt;
&lt;td&gt;完结篇《Final Chapters》&lt;/td&gt;
&lt;td&gt;2023‑03‑04 &amp;amp; 2023‑11‑05&lt;/td&gt;
&lt;td&gt;前后篇&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;📺 动画各季详情&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/1429/season/1?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第1季-TMDB-blue?style=for-the-badge&quot;
    alt=&quot;第1季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/1429/season/2?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第2季-TMDB-green?style=for-the-badge&quot;
    alt=&quot;第2季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/1429/season/3?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第3季-TMDB-orange?style=for-the-badge&quot;
    alt=&quot;第3季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/1429/season/4?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/最终季-TMDB-red?style=for-the-badge&quot;
    alt=&quot;第4季 最终季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/1429/season/0?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/完结篇-特别篇-yellow?style=for-the-badge&quot;
    alt=&quot;特别篇 完结篇&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/3445f199258b&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ 无需提取码，支持在线播放、打包解压，推荐使用夸克客户端或 Chrome 浏览器！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;p&gt;《进击的巨人》以其宏大的世界观、震撼的反转、人性的挣扎，掀起了近十年的动画狂潮。从少年艾伦的愤怒呐喊，到世界对立、宿命交错的终章，它不仅仅是热血，更是思想。愿你在重温这部史诗时，仍记得那句最初的誓言——&lt;strong&gt;自由，为之战斗！&lt;/strong&gt;&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate></item><item><title> 安卓 &amp; 🍎 iOS 科学上网客户端使用指南</title><link>https://hub.xiaozhangya.xin/blog/vpn-use/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/vpn-use/</guid><description>Hiddfy、Shadowrocket🚀、Flclash三端的使用教程</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/vpn-use/&quot;&gt;https://hub.xiaozhangya.xin/blog/vpn-use/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;📱 安卓 &amp;amp; 🍎 iOS 科学上网客户端使用指南（FLClash / Hiddify / Shadowrocket）&lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt;📲 安卓端配置教程（FLClash）&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;FLClash Download&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;&lt;strong&gt;Download based on your OS:&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-android-arm64-v8a.apk&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/40225ceb1a905d3c12a01903192bf5c21ea4eb6a9ed3c42ac527ebfd62aa7982/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41504b2d41524d76382d3136383033392e7376673f6c6f676f3d616e64726f6964&quot; alt=&quot;Android arm64&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-android-armeabi-v7a.apk&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/77075a881e298fa51bd3d969914fa291f6c22ddfdf0e3425990d3b16d4376b5d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41504b2d41524d76372d3435626635352e7376673f6c6f676f3d616e64726f6964&quot; alt=&quot;Android armeabi-v7a&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-android-x86_64.apk&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/191779d40cbd2d763cfa11c6f86eb84867aeefbf9a581ff966e428047b66c2f0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41504b2d7836342d3936656438392e7376673f6c6f676f3d616e64726f6964&quot; alt=&quot;Android x86_64&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-windows-amd64-setup.exe&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/cf8134d6b42928ccba11797e170c3c186a67627d3b1c2a4b33fa8551bb92e70a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53657475702d7836342d3264376439612e7376673f6c6f676f3d77696e646f7773&quot; alt=&quot;Windows Setup&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-windows-amd64.zip&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/7b9637338a7485e3534c68205bd47b8c5483467170de34a98f1180b39c84963d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f727461626c652d7836342d3637623764312e7376673f6c6f676f3d77696e646f7773&quot; alt=&quot;Windows Zip&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-macos-arm64.dmg&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/39f18a40cd7e51f05fc25c0d4938fc41b8a596ca21b62f3b0672834c49a370f8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f444d472d4170706c6525323053696c69636f6e2d2532333030303030302e7376673f6c6f676f3d6170706c65&quot; alt=&quot;macOS arm64&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-macos-amd64.dmg&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/f98569ccf2719290a247f3d44c6c530848972fb08ef3398589f7918230bd8422/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f444d472d496e74656c2532305836342d2532333030413945302e7376673f6c6f676f3d6170706c65&quot; alt=&quot;macOS amd64&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;hr&gt;
&lt;h3&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/h3&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-linux-amd64.AppImage&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/5e0042f47cf06176e0ac4ed8f6d5f0c21e31adcdfc737b617a975c610d95eabc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f417070496d6167652d7836342d6638346532392e7376673f6c6f676f3d6c696e7578&quot; alt=&quot;Linux AppImage&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-linux-amd64.deb&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/34e70144d435beffe476fba6953acdf1ffa8b560791561b17a8e7917681522a6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4465625061636b6167652d7836342d4646393936362e7376673f6c6f676f3d64656269616e&quot; alt=&quot;Linux deb&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;https://github.com/chen08209/FlClash/releases/download/v0.8.86/FlClash-0.8.86-linux-amd64.deb&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
    &lt;img src=&quot;https://camo.githubusercontent.com/c0d319e25b53f016bdaee002cbc3d6121e0cb810c6cbac23759e90bddd2f18b1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52706d5061636b6167652d7836342d4631423432462e7376673f6c6f676f3d726564686174&quot; alt=&quot;Linux deb&quot; style=&quot;border-radius:12px;&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h3&gt;✅ 1. 复制订阅链接并打开 FLClash&lt;/h3&gt;
&lt;p&gt;复制你获取的 &lt;strong&gt;订阅链接&lt;/strong&gt;，打开 &lt;strong&gt;FLClash&lt;/strong&gt; 应用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/07/13/4CfePUjrc2vodBJ.jpg&quot; alt=&quot;FLClash 主界面&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;🔗 2. 将订阅链接粘贴至 FLClash&lt;/h3&gt;
&lt;p&gt;点击右上角「+」，粘贴订阅链接并保存。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/07/13/l7RAKLGtUFar3hs.jpg&quot; alt=&quot;填写订阅链接&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;🚀 3. 返回首页并开启代理&lt;/h3&gt;
&lt;p&gt;添加成功后，返回主页，点击中间开关启动代理服务。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/07/13/R5cpN8t9EZyMOHa.jpg&quot; alt=&quot;开启代理&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;📊 4. 测试节点速度&lt;/h3&gt;
&lt;p&gt;点击测速按钮即可测试当前节点的延迟。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/07/13/J7BYAR6Ny4mv1cQ.jpg&quot; alt=&quot;测速界面&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🍏 iOS 端配置教程&lt;/h2&gt;
&lt;hr&gt;
&lt;h3&gt;✅ 1. Hiddify 客户端（推荐 · 免费）&lt;/h3&gt;
&lt;h4&gt;🔽 下载方式&lt;/h4&gt;
&lt;div style=&quot;display: flex; gap: 12px; flex-wrap: wrap; align-items: center;&quot;&gt;
  &lt;a href=&quot;https://github.com/hiddify/hiddify-app/releases/download/v2.0.5/Hiddify-iOS.ipa&quot; target=&quot;_blank&quot;&gt;
    &lt;img
      src=&quot;https://img.shields.io/badge/IPA下载-GitHub-4c8eda?style=for-the-badge&amp;logo=github&amp;logoColor=white&quot;
      alt=&quot;GitHub 下载&quot;
      style=&quot;border-radius: 12px;&quot; /&gt;
  &lt;/a&gt;
  &lt;a href=&quot;http://8.210.255.76:5212/s/YeCp&quot; target=&quot;_blank&quot;&gt;
    &lt;img
      src=&quot;https://img.shields.io/badge/备用下载-云盘-00c1de?style=for-the-badge&amp;logo=icloud&amp;logoColor=white&quot;
      alt=&quot;云盘下载&quot;
      style=&quot;border-radius: 12px;&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Hiddify 支持 iPhone / iPad，免费开源、无广告。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/11/06/mEKTdSXM74fpx68.png&quot; alt=&quot;Hiddify 主界面&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;🔧 1.1 禁用“启用分析”功能&lt;/h4&gt;
&lt;p&gt;保护隐私，建议关闭「启用分析」。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/11/06/pA24c86EDeCHGPk.png&quot; alt=&quot;关闭分析&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;🔗 1.2 复制并粘贴订阅链接&lt;/h4&gt;
&lt;p&gt;获取订阅链接后，复制并粘贴到 Hiddify 中。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/11/06/SOADX6gQ8VYPMZ2.png&quot; alt=&quot;复制订阅链接&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;🔍 1.3 测试并连接节点&lt;/h4&gt;
&lt;p&gt;点击链接进行测速，选择速度较快的节点使用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/11/06/ZrJvn6RmuoTsDfg.png&quot; alt=&quot;节点测试&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;💰 2. Shadowrocket（收费软件 · $3）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Shadowrocket（小火箭）是一款专业的 iOS 科学上网工具，价格为 &lt;strong&gt;$2.99 美元&lt;/strong&gt;，需使用 &lt;strong&gt;美区 Apple ID&lt;/strong&gt; 购买。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h4&gt;🛠️ 2.1 安装步骤&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;打开 &lt;strong&gt;App Store&lt;/strong&gt; → 点击右上角头像 → 退出当前账号  &lt;/li&gt;
&lt;li&gt;使用注册好的 &lt;strong&gt;美区 Apple ID&lt;/strong&gt; 登录  &lt;/li&gt;
&lt;li&gt;搜索 “Shadowrocket”，价格约为 &lt;code&gt;$2.99&lt;/code&gt;（一次性购买）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4&gt;📥 2.2 添加订阅链接&lt;/h4&gt;
&lt;p&gt;安装后打开 App，点击右上角「+」添加订阅链接。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/10/13/fOtrIXSYZkUH1vQ.png&quot; alt=&quot;添加订阅链接&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;🚀 2.3 启动代理连接&lt;/h4&gt;
&lt;p&gt;选择节点，点击右上角开关。出现 VPN 配置提示，点击「允许」，输入设备密码即可连接成功。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/10/13/iYFEWR57AQZCVpO.png&quot; alt=&quot;连接界面&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;📡 2.4 节点测试与设置优化&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;可手动更新订阅：在订阅页面向左滑动&lt;/li&gt;
&lt;li&gt;打开设置：&lt;ul&gt;
&lt;li&gt;开启 &lt;code&gt;打开时更新&lt;/code&gt; 与 &lt;code&gt;后台自动更新&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;将 &lt;code&gt;延迟测试方法&lt;/code&gt; 设置为 &lt;code&gt;CONNECT&lt;/code&gt; 或 &lt;code&gt;ICMP&lt;/code&gt;，提升测速准确性&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://s2.loli.net/2024/10/13/LtVvSdF12l9QEUz.png&quot; alt=&quot;测速设置&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🧾 总结对比表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;平台&lt;/th&gt;
&lt;th&gt;客户端&lt;/th&gt;
&lt;th&gt;免费&lt;/th&gt;
&lt;th&gt;下载方式&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;安卓&lt;/td&gt;
&lt;td&gt;FLClash&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;应用商店或安装包&lt;/td&gt;
&lt;td&gt;简洁好用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;Hiddify&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;GitHub / 云盘&lt;/td&gt;
&lt;td&gt;免费推荐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;Shadowrocket&lt;/td&gt;
&lt;td&gt;❌ $2.99&lt;/td&gt;
&lt;td&gt;App Store（美区）&lt;/td&gt;
&lt;td&gt;功能强大、需付费&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;小贴士&lt;/strong&gt;：建议定期更新订阅链接，测速时选择 &lt;code&gt;CONNECT&lt;/code&gt; 或 &lt;code&gt;ICMP&lt;/code&gt; 可有效检测节点连通性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如需订阅源、Apple ID 注册、节点推荐等帮助，可留言或联系站长咨询 🤝&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🚀 百度网盘极速下载指南：Motrix + 闪链解析</title><link>https://hub.xiaozhangya.xin/blog/bai_du_wang_pan_shan_lian_jie_xi/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/bai_du_wang_pan_shan_lian_jie_xi/</guid><description>百度网盘通过下载器：Motrix + 解析网站：闪链解析，实现下载速度的飞快提升！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/bai_du_wang_pan_shan_lian_jie_xi/&quot;&gt;https://hub.xiaozhangya.xin/blog/bai_du_wang_pan_shan_lian_jie_xi/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🚀 百度网盘极速下载指南：Motrix + 闪链解析&lt;/h1&gt;
&lt;h2&gt;🔧 工具准备&lt;/h2&gt;
&lt;h3&gt;1.1 Motrix 下载神器&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://motrix.app/zh-CN/download&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/%E4%B8%8B%E8%BD%BD-Motrix-%2300a1d6?style=for-the-badge&amp;logo=appveyor&quot; alt=&quot;Motrix Download&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;✨ &lt;strong&gt;核心优势&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;💯 完全开源免费&lt;/li&gt;
&lt;li&gt;⚡ 多线程加速下载&lt;/li&gt;
&lt;li&gt;🌐 支持多种协议&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250715134445086.png&quot; alt=&quot;Motrix精美界面&quot;&gt;&lt;/p&gt;
&lt;h3&gt;1.2 闪链解析服务&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://mf.dp.wpurl.cc/user/parse&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/%E8%AE%BF%E9%97%AE-%E9%97%AA%E9%93%BE%E8%A7%A3%E6%9E%90-%23ff4d4f?style=for-the-badge&quot; alt=&quot;闪链解析&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🔍 &lt;strong&gt;服务特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🆓 纯公益性质&lt;/li&gt;
&lt;li&gt;🔒 无需登录&lt;/li&gt;
&lt;li&gt;🚫 无广告干扰&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;📝 详细操作指南&lt;/h2&gt;
&lt;h3&gt;2.1 获取百度分享链接&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;在百度网盘中 &lt;strong&gt;右键点击&lt;/strong&gt; 目标文件&lt;/li&gt;
&lt;li&gt;选择「&lt;strong&gt;分享&lt;/strong&gt;」→「&lt;strong&gt;创建链接&lt;/strong&gt;」&lt;/li&gt;
&lt;li&gt;复制生成的 &lt;strong&gt;链接和提取码&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250715133250319.png&quot; alt=&quot;分享链接获取演示&quot;&gt;&lt;/p&gt;
&lt;h3&gt;2.2 闪链解析步骤&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;访问 &lt;a href=&quot;https://mf.dp.wpurl.cc/user/parse&quot;&gt;&lt;strong&gt;闪链官网&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;在输入框粘贴分享链接&lt;/li&gt;
&lt;li&gt;填写提取码（若需要）&lt;/li&gt;
&lt;li&gt;点击「&lt;strong&gt;解析&lt;/strong&gt;」按钮&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250715134129671.png&quot; alt=&quot;闪链解析界面展示&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;⚡ 速度对比实测&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;下载方式&lt;/th&gt;
&lt;th&gt;速度表现&lt;/th&gt;
&lt;th&gt;状态展示&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;官方客户端&lt;/td&gt;
&lt;td&gt;🐢 97.55KB/s&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250715134311368.png&quot; alt=&quot;官方速度&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Motrix+闪链&lt;/td&gt;
&lt;td&gt;🚀 9.3MB/s&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250715134230296.png&quot; alt=&quot;极速下载&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;⚠️ 重要注意事项&lt;/h2&gt;
&lt;p&gt;🔹 公益服务资源有限，建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;避开高峰时段（20:00-24:00）&lt;/li&gt;
&lt;li&gt;单个文件建议不超过5GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🔹 网络优化建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;推荐使用有线网络连接&lt;/li&gt;
&lt;li&gt;关闭其他占用带宽的应用&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 温馨提示：本方案适合临时应急使用，长期大容量需求建议开通百度网盘会员&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;🌟 进阶技巧&lt;/h2&gt;
&lt;p&gt;✅ 批量下载技巧：在Motrix中导入「批量任务.txt」&lt;br&gt;✅ 断点续传：Motrix自动支持&lt;br&gt;✅ 速度限制：可在设置中调整线程数（推荐8-16线程）&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/agalwood/Motrix&quot;&gt;&lt;img src=&quot;https://img.shields.io/github/stars/agalwood/Motrix.svg?style=social&quot; alt=&quot;Star on GitHub&quot;&gt;&lt;/a&gt; 如果觉得有用，请给Motrix点个Star吧！&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sat, 19 Jul 2025 00:00:00 GMT</pubDate></item><item><title>💖 更衣人偶坠入爱河动画资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/geng_yi_ren_ou_zhui_ru_ai_he/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/geng_yi_ren_ou_zhui_ru_ai_he/</guid><description>立志成为雏人形工匠的高中生五条新菜，因不擅长与人交际，始终独来独往。直到某天，班上的闪耀辣妹——喜多川海梦发现了他的缝纫才能，并大胆请求他为她制作 Cosplay 服装。从此，一段“宅男 × 女神”的甜蜜物语就此展开！</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/geng_yi_ren_ou_zhui_ru_ai_he/&quot;&gt;https://hub.xiaozhangya.xin/blog/geng_yi_ren_ou_zhui_ru_ai_he/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;💖 &lt;strong&gt;更衣人偶坠入爱河&lt;/strong&gt;&lt;/h1&gt;
&lt;div style=&quot;display:flex; gap:10px; flex-wrap:wrap; justify-content:center;&quot;&gt;
&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250716225833069.jpg&quot; alt=&quot;Haikyu Poster 2&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
  &lt;img src=&quot;https://image.tmdb.org/t/p/original/qcVvlnovweMyWGMGMPSBYSpscB8.jpg&quot; alt=&quot;Haikyu Poster 1&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
&lt;/div&gt;

&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：恋爱 · 日常 · Cosplay · 校园  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作&lt;/strong&gt;：福田晋一  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：CloverWorks  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2022‑01‑08 至 2022‑03‑26  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配音阵容&lt;/strong&gt;：&lt;br&gt;直田姬奈（喜多川海梦）、石毛翔弥（五条新菜）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;立志成为雏人形工匠的高中生五条新菜，因不擅长与人交际，始终独来独往。直到某天，班上的闪耀辣妹——喜多川海梦发现了他的缝纫才能，并大胆请求他为她制作 Cosplay 服装。从此，一段“宅男 × 女神”的甜蜜物语就此展开！&lt;/p&gt;
&lt;h2&gt;🎬 动画各季信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第1季&lt;/td&gt;
&lt;td&gt;更衣人偶坠入爱河 第一季&lt;/td&gt;
&lt;td&gt;2022‑01‑08 ~ 2022‑03‑26&lt;/td&gt;
&lt;td&gt;12 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第2季&lt;/td&gt;
&lt;td&gt;更衣人偶坠入爱河 第二季&lt;/td&gt;
&lt;td&gt;2022‑07‑06 ~ 2025‑09‑21&lt;/td&gt;
&lt;td&gt;12 集&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;📺 动画各季详情&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/114410/season/1?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第1季-TMDB-pink?style=for-the-badge&quot;
    alt=&quot;第1季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/114410/season/1?language=zh-CN&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/第2季-连载中-yellow?style=for-the-badge&quot;
    alt=&quot;第2季&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/07ac05f9ab25&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;
&gt; ✅ 2160P ***SENIX***压制组重制 

&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;p&gt;《更衣人偶坠入爱河》凭借甜到炸裂的恋爱剧情、细致的 Cosplay 文化描写和神还原作画，被誉为“恋爱番天花板”。不管你是阿宅、绅士，还是恋爱初心者，这部作品都能让你笑中带羞，甜到打滚！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“我喜欢的东西，我当然不觉得羞耻！”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Fri, 18 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🌸 葬送的芙莉莲动画资源分享 🎬✨</title><link>https://hub.xiaozhangya.xin/blog/steinsgate/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/steinsgate/</guid><description>在秋叶原，大学生兼“中二病”科学狂人冈部伦太郎，意外将家中微波炉改造成可发送短信到过去的“电话微波炉”。在一次次穿越中，他和伙伴们无意中引发蝴蝶效应，遭遇神秘组织 CERN 的追杀。为了拯救世界与最重要的人，冈部必须找出真正的世界线，抵达那扇改变命运的门——Steins;Gate。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/steinsgate/&quot;&gt;https://hub.xiaozhangya.xin/blog/steinsgate/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;🧪 &lt;strong&gt;命运石之门 &lt;em&gt;Steins;Gate&lt;/em&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250717231835628.png&quot; alt=&quot;poster&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：科幻 · 悬疑 · 心理惊悚 · 喜剧  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作&lt;/strong&gt;：5pb. × Nitroplus（视觉小说）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：WHITE FOX  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2011‑04‑06 至 2011‑09‑14（24 集 + OVA）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;导演&lt;/strong&gt;：濱崎博嗣、佐藤卓哉  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配音阵容&lt;/strong&gt;：&lt;br&gt;宫野真守（冈部伦太郎）、今井麻美（牧濑红莉栖）、花泽香菜（椎名真由理）、关智一（桥田至）、田村由香里（阿万音铃羽）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;在秋叶原，大学生兼“中二病”科学狂人冈部伦太郎，意外将家中微波炉改造成可发送短信到过去的“电话微波炉”。&lt;br&gt;在一次次穿越中，他和伙伴们无意中引发蝴蝶效应，遭遇神秘组织 CERN 的追杀。为了拯救世界与最重要的人，冈部必须找出真正的世界线，抵达那扇改变命运的门——Steins;Gate。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎬 动画各季 &amp;amp; 剧场版信息&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;类型&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;名称&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;播出/上映时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数/时长&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;TV动画&lt;/td&gt;
&lt;td&gt;命运石之门 &lt;em&gt;Steins;Gate&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;2011‑04‑06 ~ 2011‑09‑14&lt;/td&gt;
&lt;td&gt;24 集 + OVA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;剧场版&lt;/td&gt;
&lt;td&gt;负荷领域的既视感（The Movie）&lt;/td&gt;
&lt;td&gt;2013‑04‑20&lt;/td&gt;
&lt;td&gt;约 89 分钟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TV续作&lt;/td&gt;
&lt;td&gt;命运石之门 0 &lt;em&gt;Steins;Gate 0&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;2018‑04‑12 ~ 2018‑09‑27&lt;/td&gt;
&lt;td&gt;23 集 + OVA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;📺 动画各季详情&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/42509-steins-gate&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/Steins;Gate-TMDB-blue?style=for-the-badge&quot; alt=&quot;Steins;Gate&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/movie/225745-steins-gate&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/剧场版-负荷领域的既视感-purple?style=for-the-badge&quot; alt=&quot;剧场版&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/78102-steins-gate-0&quot; target=&quot;_blank&quot; style=&quot;display:inline-block;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/Steins;Gate%200-TMDB-black?style=for-the-badge&quot; alt=&quot;Steins;Gate 0&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;



&lt;hr&gt;
&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/aace835a000c&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;✅ 提供完整 Steins;Gate &amp;amp; Steins;Gate 0 + 剧场版资源，推荐使用夸克客户端或 PC 浏览器高速下载。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;✍️ 结语&lt;/h2&gt;
&lt;p&gt;《命运石之门》是一部将科学理论与人性挣扎完美结合的神作，从“中二”搞笑过渡到严肃沉重的剧情，每一次世界线跳跃都扣人心弦。如果你喜欢关于时间、命运、牺牲与救赎的故事，这部作品绝对值得一看再看！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“最伟大的奇迹，莫过于你们仍记得我。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 17 Jul 2025 00:00:00 GMT</pubDate></item><item><title>👻 怪奇物语剧集资源分享🎬✨</title><link>https://hub.xiaozhangya.xin/blog/strangerthings/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/strangerthings/</guid><description>位于 1980 年代的 Hawkins 小镇，一名少年 Will 突然失踪，引发了一连串超自然事件。神秘的实验、特殊能力的少女 Eleven 以及“颠倒世界”暗流涌动。孩子们与大人并肩作战，试图揭开阴谋、阻止灾难，同时面对青春成长的阵痛。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/strangerthings/&quot;&gt;https://hub.xiaozhangya.xin/blog/strangerthings/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;👻 &lt;strong&gt;怪奇物语 &lt;em&gt;Stranger Things&lt;/em&gt;&lt;/strong&gt;&lt;/h1&gt;
&lt;hr&gt;
&lt;div style=&quot;display:flex; gap:10px; flex-wrap:wrap; justify-content:center;&quot;&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250717231936846.png&quot; alt=&quot;Steins;Gate Poster 1&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
  &lt;img src=&quot;https://picbed.xiaozhangya.xin/picbed/20250717232030810.png&quot; alt=&quot;Steins;Gate Poster 2&quot; style=&quot;width:49%; border-radius:8px;&quot; /&gt;
&lt;/div&gt;


&lt;h2&gt;✨ 概览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型&lt;/strong&gt;：科幻 · 悬疑 · 恐怖 · 青春成长  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原作/创作者&lt;/strong&gt;：达菲兄弟（The Duffer Brothers）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制作公司&lt;/strong&gt;：21 Laps Entertainment、Monkey Massacre Productions、Upside Down Pictures  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;首播时间&lt;/strong&gt;：2016‑07‑15 起（至今）  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;季数与集数&lt;/strong&gt;：目前共 4 季（34 集），第五季预计 2025 年底完结  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配乐&lt;/strong&gt;：Michael Stein、Kyle Dixon  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主要阵容&lt;/strong&gt;：&lt;br&gt;Millie Bobby Brown（Eleven）&lt;br&gt;Finn Wolfhard（Mike）&lt;br&gt;Gaten Matarazzo（Dustin）&lt;br&gt;Caleb McLaughlin（Lucas）&lt;br&gt;David Harbour（Hopper）&lt;br&gt;Winona Ryder（Joyce）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🧱 故事情节&lt;/h2&gt;
&lt;p&gt;位于 1980 年代的 Hawkins 小镇，一名少年 Will 突然失踪，引发了一连串超自然事件。神秘的实验、特殊能力的少女 Eleven 以及“颠倒世界”暗流涌动。孩子们与大人并肩作战，试图揭开阴谋、阻止灾难，同时面对青春成长的阵痛。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;🎬 剧集&amp;amp;剧场版信息一览&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;季度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;标题&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;上映时间&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;集数&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;第一季&lt;/td&gt;
&lt;td&gt;Stranger Things S1&lt;/td&gt;
&lt;td&gt;2016-07-15&lt;/td&gt;
&lt;td&gt;8 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第二季&lt;/td&gt;
&lt;td&gt;Stranger Things S2&lt;/td&gt;
&lt;td&gt;2017-10-27&lt;/td&gt;
&lt;td&gt;9 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第三季&lt;/td&gt;
&lt;td&gt;Stranger Things S3&lt;/td&gt;
&lt;td&gt;2019-07-04&lt;/td&gt;
&lt;td&gt;8 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第四季&lt;/td&gt;
&lt;td&gt;Stranger Things S4（分卷）&lt;/td&gt;
&lt;td&gt;2022-05-27 / 2022-07-01&lt;/td&gt;
&lt;td&gt;9 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第五季&lt;/td&gt;
&lt;td&gt;Stranger Things S5 Vol.1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2025-11-26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 集&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;第五季&lt;/td&gt;
&lt;td&gt;Stranger Things S5 Vol.2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2025 圣诞档期&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4 集&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;📺 各季 TMDB 信息&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/66732-stranger-things/season/1&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第1季-TMDB-blue?style=for-the-badge&quot; alt=&quot;第1季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/66732-stranger-things/season/2&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第2季-TMDB-green?style=for-the-badge&quot; alt=&quot;第2季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/66732-stranger-things/season/3&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第3季-TMDB-orange?style=for-the-badge&quot; alt=&quot;第3季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/66732-stranger-things/season/4&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第4季-TMDB-red?style=for-the-badge&quot; alt=&quot;第4季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt;
&lt;a href=&quot;https://www.themoviedb.org/tv/66732-stranger-things/season/5&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img src=&quot;https://img.shields.io/badge/第5季-TMDB-purple?style=for-the-badge&quot; alt=&quot;第5季&quot; style=&quot;border-radius:12px;&quot; /&gt;
&lt;/div&gt;



&lt;h2&gt;📥 资源下载&lt;/h2&gt;
&lt;div&gt;
&lt;a href=&quot;https://pan.quark.cn/s/28e91f88176b&quot; target=&quot;_blank&quot; style=&quot;display:inline-block; margin-right:5px;&quot;&gt;
  &lt;img
    src=&quot;https://img.shields.io/badge/资源下载-夸克网盘-4CAF50?style=for-the-badge&quot;
    alt=&quot;资源下载&quot;
    style=&quot;border-radius:12px;&quot; /&gt;
&lt;/a&gt; 
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;✅ 包含全 1–4 季 + 第 5 季预告资源，适合在线观看与打包收藏，建议使用夸克客户端或桌面浏览。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;✍️ 一句话总结&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“我就像一盏灯，想赶走黑暗，却发现自己也渴望光亮。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 17 Jul 2025 00:00:00 GMT</pubDate></item><item><title>🚀 数据挖掘（DataMing）</title><link>https://hub.xiaozhangya.xin/blog/datamining/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/datamining/</guid><description>数据挖掘是从大量数据中提取有价值信息的过程，广泛应用于商业、科学和社会研究等领域。本文将介绍数据挖掘的基本概念、常用技术和应用场景。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/datamining/&quot;&gt;https://hub.xiaozhangya.xin/blog/datamining/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;帕累托图&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;帕累托图（Pareto Chart）是一种结合了柱状图和折线图的统计图表，常用于显示各因素的频数及其累计百分比，帮助识别主要问题或关键因素。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141330966.png&quot; alt=&quot;帕累托图&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams[&amp;#39;font.sans-serif&amp;#39;] = &amp;#39;SimHei&amp;#39;
# 示例数据：类别及对应频数
data = {
    &amp;#39;类别&amp;#39;: [&amp;#39;A&amp;#39;, &amp;#39;B&amp;#39;, &amp;#39;C&amp;#39;, &amp;#39;D&amp;#39;, &amp;#39;E&amp;#39;, &amp;#39;F&amp;#39;],
    &amp;#39;频数&amp;#39;: [120, 90, 60, 30, 20, 10]
}

df = pd.DataFrame(data)

# 按频数降序排序
df = df.sort_values(by=&amp;#39;频数&amp;#39;, ascending=False).reset_index(drop=True)

# 计算累计频数及累计百分比
df[&amp;#39;累计频数&amp;#39;] = df[&amp;#39;频数&amp;#39;].cumsum()
df[&amp;#39;累计百分比&amp;#39;] = 100 * df[&amp;#39;累计频数&amp;#39;] / df[&amp;#39;频数&amp;#39;].sum()

# 创建双轴图
fig, ax1 = plt.subplots()

# 绘制柱状图 - 频数
ax1.bar(df[&amp;#39;类别&amp;#39;], df[&amp;#39;频数&amp;#39;], color=&amp;#39;C0&amp;#39;)
ax1.set_ylabel(&amp;#39;频数&amp;#39;, color=&amp;#39;C0&amp;#39;)
ax1.tick_params(axis=&amp;#39;y&amp;#39;, labelcolor=&amp;#39;C0&amp;#39;)

# 创建第二个纵轴 - 累计百分比
ax2 = ax1.twinx()
ax2.plot(df[&amp;#39;类别&amp;#39;], df[&amp;#39;累计百分比&amp;#39;], color=&amp;#39;C1&amp;#39;, marker=&amp;#39;D&amp;#39;, ms=7)
ax2.yaxis.set_major_formatter(plt.PercentFormatter())
ax2.set_ylabel(&amp;#39;累计百分比&amp;#39;, color=&amp;#39;C1&amp;#39;)
ax2.tick_params(axis=&amp;#39;y&amp;#39;, labelcolor=&amp;#39;C1&amp;#39;)
ax2.set_ylim(0, 110)

# 标题和布局
plt.title(&amp;#39;帕累托图示例&amp;#39;)
plt.tight_layout()
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;ROC曲线&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ROC（Receiver Operating Characteristic）曲线&lt;/strong&gt; 是用于二分类模型性能评估的重要工具，特别适合不均衡数据集。它反映了分类器在不同阈值下的**假阳性率（False Positive Rate, FPR）&lt;strong&gt;与&lt;/strong&gt;真阳性率（True Positive Rate, TPR）**的关系。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;真阳性率（TPR）&lt;/strong&gt;：也叫召回率，表示被正确识别为正类的比例。计算公式：TPR = TP / (TP + FN)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;假阳性率（FPR）&lt;/strong&gt;：错误地被识别为正类的负类比例。计算公式：FPR = FP / (FP + TN)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ROC曲线&lt;/strong&gt;是以FPR为横轴，TPR为纵轴绘制的曲线，越接近左上角（FPR低，TPR高）说明模型越好。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AUC（Area Under Curve）&lt;/strong&gt; 是ROC曲线下的面积，表示模型整体的分类能力。AUC越接近1越好，0.5相当于随机猜测。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506141407860.png&quot; alt=&quot;ROC曲线&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
import matplotlib as mpl

# 设置中文字体
mpl.rcParams[&amp;#39;font.sans-serif&amp;#39;] = [&amp;#39;SimHei&amp;#39;]  # 指定字体为 SimHei（黑体）
mpl.rcParams[&amp;#39;axes.unicode_minus&amp;#39;] = False  # 解决负号显示问题

# 生成模拟二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练逻辑回归模型
model = LogisticRegression()
model.fit(X_train, y_train)

# 预测测试集正类概率
y_score = model.predict_proba(X_test)[:, 1]

# 计算假阳性率（FPR）、真阳性率（TPR）和阈值
fpr, tpr, thresholds = roc_curve(y_test, y_score)

# 计算 AUC 值
roc_auc = auc(fpr, tpr)

# 绘制 ROC 曲线
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color=&amp;#39;blue&amp;#39;, lw=2, label=f&amp;#39;ROC 曲线 (AUC = {roc_auc:.2f})&amp;#39;)
plt.plot([0, 1], [0, 1], color=&amp;#39;gray&amp;#39;, linestyle=&amp;#39;--&amp;#39;, lw=2)  # 随机猜测参考线
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel(&amp;#39;假阳性率（False Positive Rate）&amp;#39;)
plt.ylabel(&amp;#39;真阳性率（True Positive Rate）&amp;#39;)
plt.title(&amp;#39;ROC 曲线示例&amp;#39;)
plt.legend(loc=&amp;quot;lower right&amp;quot;)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;数据挖掘算法&lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt;回归&lt;/h2&gt;
&lt;h3&gt;特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目标&lt;/strong&gt;：预测连续值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模型&lt;/strong&gt;：连续函数  $f(X) \rightarrow Y$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;常用指标&lt;/strong&gt;：MAE、MSE、MedAE、R2R^2、EVS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;线性回归 (Linear Regression)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, \
                            median_absolute_error, explained_variance_score, r2_score
import pandas as pd

# 1⃣ 读取数据
# 读取数据文件 &amp;#39;financial.csv&amp;#39;，数据集包含自变量 X 和因变量 y
data = pd.read_csv(&amp;quot;financial.csv&amp;quot;)
X = data.drop(columns=&amp;quot;target&amp;quot;)   # 自变量 X，去掉目标列 &amp;#39;target&amp;#39;
y = data[&amp;quot;target&amp;quot;]               # 因变量 y，目标列

# 2⃣ 划分数据集
# 将数据集按 80/20 的比例划分为训练集和测试集，随机种子为 125
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.20, random_state=125)

# 3⃣ 建模与训练
# 使用线性回归模型并对训练数据进行训练
model = LinearRegression().fit(X_train, y_train)

# 4⃣ 预测
# 使用训练好的模型对测试数据进行预测
y_pred = model.predict(X_test)

# 5⃣ 评估
# 输出各种回归评估指标
print(&amp;quot;MAE :&amp;quot;, mean_absolute_error(y_test, y_pred))         # 平均绝对误差
print(&amp;quot;MSE :&amp;quot;, mean_squared_error(y_test, y_pred))         # 均方误差
print(&amp;quot;MedAE :&amp;quot;, median_absolute_error(y_test, y_pred))    # 中位绝对误差
print(&amp;quot;EVS :&amp;quot;, explained_variance_score(y_test, y_pred))   # 解释方差得分
print(&amp;quot;R² :&amp;quot;, r2_score(y_test, y_pred))                    # R² 决定系数
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;逻辑回归（含ROC曲线绘制）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;虽名为“回归”，也可以进行&lt;strong&gt;二元或多元分类&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, \
                            confusion_matrix, roc_curve, auc
import pandas as pd
import matplotlib.pyplot as plt

# 读取数据
data = pd.read_csv(&amp;quot;financial.csv&amp;quot;)
X = data.drop(columns=&amp;quot;label&amp;quot;)  # 自变量 X
y = data[&amp;quot;label&amp;quot;]              # 因变量 y

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.20, random_state=125)

# 初始化逻辑回归模型并训练
clf = LogisticRegression(max_iter=1000).fit(X_train, y_train)
y_pred = clf.predict(X_test)  # 对测试集进行预测

# 输出分类指标
print(&amp;quot;Accuracy :&amp;quot;, accuracy_score(y_test, y_pred))        # 准确率
print(&amp;quot;Precision:&amp;quot;, precision_score(y_test, y_pred))       # 精确度
print(&amp;quot;Recall   :&amp;quot;, recall_score(y_test, y_pred))          # 召回率
print(&amp;quot;ConfMat  :\n&amp;quot;, confusion_matrix(y_test, y_pred))    # 混淆矩阵

# === ROC 曲线 ===
# 计算预测结果的概率并绘制 ROC 曲线
y_score = clf.predict_proba(X_test)[:, 1]  # 获取正类的概率
fpr, tpr, _ = roc_curve(y_test, y_score)   # 计算假阳性率与真阳性率
roc_auc = auc(fpr, tpr)                    # 计算 AUC 值

# 绘制 ROC 曲线
plt.figure()
plt.plot(fpr, tpr, lw=2, label=f&amp;quot;ROC (AUC={roc_auc:.2f})&amp;quot;)
plt.plot([0, 1], [0, 1], &amp;quot;--&amp;quot;)             # 参考线：完全随机
plt.xlabel(&amp;quot;False Positive Rate&amp;quot;)
plt.ylabel(&amp;quot;True Positive Rate&amp;quot;)
plt.title(&amp;quot;ROC Curve — Logistic Regression&amp;quot;)
plt.legend()
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;分类&lt;/h2&gt;
&lt;h3&gt;特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;输出&lt;/strong&gt;：离散类别&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入&lt;/strong&gt;：样本属性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;训练方式&lt;/strong&gt;：监督学习&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;常用指标&lt;/strong&gt;：Accuracy、Precision、Recall、F1、ROC/AUC&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;决策树 (Decision Tree)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix
import pandas as pd

# 读取数据
data = pd.read_excel(&amp;quot;sales_data.xls&amp;quot;)
X = data.drop(columns=&amp;quot;label&amp;quot;)  # 特征自变量
y = data[&amp;quot;label&amp;quot;]              # 目标标签

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.20, random_state=125)

# 创建决策树分类器并训练
dtc = DecisionTreeClassifier(criterion=&amp;quot;entropy&amp;quot;).fit(X_train, y_train)
y_pred = dtc.predict(X_test)  # 对测试集进行预测

# 输出分类指标
print(&amp;quot;Accuracy :&amp;quot;, accuracy_score(y_test, y_pred))        # 准确率
print(&amp;quot;Precision:&amp;quot;, precision_score(y_test, y_pred))       # 精确度
print(&amp;quot;Recall   :&amp;quot;, recall_score(y_test, y_pred))          # 召回率
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;K 近邻 (K‑NN)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris

# 加载 Iris 数据集
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.20, random_state=125)

# 创建 K-近邻分类器并训练
knn = KNeighborsClassifier(n_neighbors=5).fit(X_train, y_train)
y_pred = knn.predict(X_test)  # 对测试集进行预测

# 输出准确率
print(&amp;quot;Accuracy :&amp;quot;, accuracy_score(y_test, y_pred))  # 准确率
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;支持向量机 (SVM)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits

# 加载手写数字数据集
digits = load_digits()
X_train, X_test, y_train, y_test = train_test_split(
    digits.data, digits.target, test_size=0.20, random_state=125)

# 创建支持向量机分类器并训练
svc = SVC().fit(X_train, y_train)
# 输出准确率
print(&amp;quot;Accuracy :&amp;quot;, accuracy_score(y_test, svc.predict(X_test)))  # 准确率
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;聚类&lt;/h2&gt;
&lt;h3&gt;特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;无监督学习&lt;/strong&gt;：无需事先标签&lt;/li&gt;
&lt;li&gt;根据相似度自动划分簇&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;K‑Means 示例（含参数寻优）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import pandas as pd
import matplotlib.pyplot as plt

# 读取数据并进行标准化
data = pd.read_excel(&amp;quot;air_features.xlsx&amp;quot;, index_col=&amp;quot;ID&amp;quot;)
data_z = (data - data.mean()) / data.std()  # Z-score 标准化

# ========== 固定聚类数为5，进行聚类并输出中心和簇大小 ==========
kmeans_5 = KMeans(n_clusters=5, random_state=3).fit(data_z)

# 聚类中心 + 每簇数量
centers = pd.DataFrame(kmeans_5.cluster_centers_, columns=data.columns)
counts  = pd.Series(kmeans_5.labels_).value_counts().sort_index().rename(&amp;quot;数量&amp;quot;)
result  = pd.concat([centers, counts], axis=1)
print(&amp;quot;K=5 聚类中心及每簇数量：&amp;quot;)
print(result)

# ========== 对不同聚类数做指标评估，绘制Inertia和轮廓系数 ==========
sse = []
silhouette_scores = []
K_range = range(2, 11)

for k in K_range:
    kmeans = KMeans(n_clusters=k, random_state=42).fit(data_z)
    sse.append(kmeans.inertia_)
    silhouette_scores.append(silhouette_score(data_z, kmeans.labels_))

plt.figure(figsize=(10, 4))

plt.subplot(1, 2, 1)
plt.plot(K_range, sse, &amp;#39;o-&amp;#39;, color=&amp;#39;blue&amp;#39;)
plt.xlabel(&amp;#39;聚类数 K&amp;#39;)
plt.ylabel(&amp;#39;簇内误差平方和 (Inertia)&amp;#39;)
plt.title(&amp;#39;Inertia - 聚类数与簇内误差平方和关系&amp;#39;)

plt.subplot(1, 2, 2)
plt.plot(K_range, silhouette_scores, &amp;#39;s-&amp;#39;, color=&amp;#39;red&amp;#39;)
plt.xlabel(&amp;#39;聚类数 K&amp;#39;)
plt.ylabel(&amp;#39;轮廓系数&amp;#39;)
plt.title(&amp;#39;轮廓系数法 - 聚类数与轮廓系数关系&amp;#39;)
plt.tight_layout()
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;关联规则&lt;/h2&gt;
&lt;h3&gt;Apriori 算法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori, association_rules
# 读取用户访问记录数据
info = pd.read_csv(&amp;quot;acc_records.csv&amp;quot;)
# 1 去重用户IP
user_ips = info[&amp;quot;用户IP&amp;quot;].unique()
# 2 构建用户访问列表
url_baskets = [
 info.loc[info[&amp;quot;用户IP&amp;quot;] == ip, &amp;quot;URL&amp;quot;].tolist()
 for ip in user_ips
]
# 3 One‑Hot 编码
te = TransactionEncoder()
df = pd.DataFrame(te.fit_transform(url_baskets), columns=te.columns_)
# 4 频繁项集 &amp;amp; 关联规则
freq_itemsets = apriori(df, min_support=0.005, use_colnames=True)
rules = association_rules(freq_itemsets, metric=&amp;quot;confidence&amp;quot;, min_threshold=0.05)
print(rules.sort_values(&amp;quot;lift&amp;quot;, ascending=False).head())
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Thu, 19 Jun 2025 00:00:00 GMT</pubDate></item><item><title>Git使用教程</title><link>https://hub.xiaozhangya.xin/blog/git-use/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/git-use/</guid><description>git是一个分布式版本控制系统，广泛用于软件开发和其他版本控制任务。本文将介绍git的基本使用方法，包括安装、配置、常用命令等。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/git-use/&quot;&gt;https://hub.xiaozhangya.xin/blog/git-use/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;Git使用教程&lt;/h1&gt;
&lt;h2&gt;部分命令&lt;/h2&gt;
&lt;h3&gt;一、新建代码库&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 在当前目录新建一个Git代码库
$ git init
# 新建一个目录，将其初始化为Git代码库
$ git init [project-name]
# 下载一个项目和它的整个代码历史
$ git clone [url]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;二、配置&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 显示当前的Git配置
$ git config --list
# 编辑Git配置文件
$ git config -e [--global]
# 设置提交代码时的用户信息
$ git config [--global] user.name &amp;quot;[name]&amp;quot;
$ git config [--global] user.email &amp;quot;[email address]&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;三、增加/删除文件&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 添加指定文件到暂存区
$ git add [file1] [file2] ...
# 添加指定目录到暂存区，包括子目录
$ git add [dir]
# 添加当前目录的所有文件到暂存区
$ git add .
# 添加每个变化前，都会要求确认
# 对于同一个文件的多处变化，可以实现分次提交
$ git add -p
# 删除工作区文件，并且将这次删除放入暂存区
$ git rm [file1] [file2] ...
# 停止追踪指定文件，但该文件会保留在工作区
$ git rm --cached [file]
# 改名文件，并且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;四、代码提交&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 提交暂存区到仓库区
$ git commit -m [message]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化，直接到仓库区
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit，替代上一次提交
# 如果代码没有任何新变化，则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
五、分支
# 重做上一次commit，并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;五、分支&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 列出所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支，但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支，并切换到该分支
$ git checkout -b [branch]
# 新建一个分支，指向指定commit
$ git branch [branch] [commit]
# 新建一个分支，与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 切换到指定分支，并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系，在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 选择一个commit，合并进当前分支
$ git cherry-pick [commit]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;六、标签&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 列出所有tag
$ git tag
# 新建一个tag在当前commit
$ git tag [tag]
# 新建一个tag在指定commit
$ git tag [tag] [commit]
# 删除本地tag
$ git tag -d [tag]
# 删除远程tag
$ git push origin :refs/tags/[tagName]
# 查看tag信息
$ git show [tag]
# 提交指定tag
$ git push [remote] [tag]
# 提交所有tag
$ git push [remote] --tags
# 新建一个分支，指向某个tag
$ git checkout -b [branch] [tag]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;七、查看信息&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 显示有变更的文件
$ git status
# 显示当前分支的版本历史
$ git log
# 显示commit历史，以及每次commit发生变更的文件
$ git log --stat
# 搜索提交历史，根据关键词
$ git log -S [keyword]
# 显示某个commit之后的所有变动，每个commit占据一行
$ git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动，其&amp;quot;提交说明&amp;quot;必须符合搜索条件
$ git log [tag] HEAD --grep feature
# 显示某个文件的版本历史，包括文件改名
$ git log --follow [file]
$ git whatchanged [file]
# 显示指定文件相关的每一次diff
八、远程同步
$ git log -p [file]
# 显示过去5次提交
$ git log -5 --pretty --oneline
# 显示所有提交过的用户，按提交次数排序
$ git shortlog -sn
# 显示指定文件是什么人在什么时间修改过
$ git blame [file]
# 显示暂存区和工作区的差异
$ git diff
# 显示暂存区和上一个commit的差异
$ git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码
$ git diff --shortstat &amp;quot;@{0 day ago}&amp;quot;
# 显示某次提交的元数据和内容变化
$ git show [commit]
# 显示某次提交发生变化的文件
$ git show --name-only [commit]
# 显示某次提交时，某个文件的内容
$ git show [commit]:[filename]
# 显示当前分支的最近几次提交
$ git reflog
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;八、远程同步&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加一个新的远程仓库，并命名
$ git remote add [shortname] [url]
# 取回远程仓库的变化，并与本地分支合并
$ git pull [remote] [branch]
九、撤销
# 上传本地指定分支到远程仓库
$ git push [remote] [branch]
# 强行推送当前分支到远程仓库，即使有冲突
$ git push [remote] --force
# 推送所有分支到远程仓库
$ git push [remote] --all
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;九、撤销&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 恢复暂存区的指定文件到工作区
$ git checkout [file]
# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
$ git checkout .
# 重置暂存区的指定文件，与上一次commit保持一致，但工作区不变
$ git reset [file]
# 重置暂存区与工作区，与上一次commit保持一致
$ git reset --hard
# 重置当前分支的指针为指定commit，同时重置暂存区，但工作区不变
$ git reset [commit]
# 重置当前分支的HEAD为指定commit，同时重置暂存区和工作区，与指定commit一致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit，但保持暂存区和工作区不变
$ git reset --keep [commit]
# 新建一个commit，用来撤销指定commit
# 后者的所有变化都将被前者抵消，并且应用到当前分支
$ git revert [commit]
# 暂时将未提交的变化移除，稍后再移入
$ git stash
$ git stash pop
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;一：Git是什么？&lt;/h2&gt;
&lt;p&gt;Git是目前世界上最先进的分布式版本控制系统。
工作原理 / 流程：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171616277.png&quot; alt=&quot;image-20250617161620237&quot;&gt;
Workspace：工作区&lt;br&gt;Index / Stage：暂存区&lt;br&gt;Repository：仓库区（或本地仓库）&lt;br&gt;Remote：远程仓库    &lt;/p&gt;
&lt;h2&gt;二：在windows上如何安装Git？&lt;/h2&gt;
&lt;p&gt;msysgit是 windows版的Git,如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171532432.png&quot; alt=&quot;image-20250617153207411&quot;&gt;&lt;/p&gt;
&lt;p&gt;需要从网上下载一个，然后进行默认安装即可。安装完成后，在开始菜单里面找到 &amp;quot;Git --&amp;gt; Git Bash&amp;quot;,如
下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171532354.png&quot; alt=&quot;image-20250617153249332&quot;&gt;&lt;/p&gt;
&lt;p&gt;会弹出一个类似的命令窗口的东西，就说明Git安装成功。如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171533801.png&quot; alt=&quot;image-20250617153309764&quot;&gt;&lt;/p&gt;
&lt;p&gt;安装完成后，还需要最后一步设置，在命令行输入如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171533807.png&quot; alt=&quot;image-20250617153326771&quot;&gt;&lt;/p&gt;
&lt;p&gt;因为Git是分布式版本控制系统，所以需要填写用户名和邮箱作为一个标识。
注意：git config --global 参数，有了这个参数，表示你这台机器上所有的Git仓库都会使用这个配置，当
然你也可以对某个仓库指定的不同的用户名和邮箱。&lt;/p&gt;
&lt;h2&gt;三：如何操作？&lt;/h2&gt;
&lt;h3&gt;一、创建版本库。&lt;/h3&gt;
&lt;p&gt;什么是版本库？版本库又名仓库，英文名repository,你可以简单的理解一个目录，这个目录里面的所有
文件都可以被Git管理起来，每个文件的修改，删除，Git都能跟踪，以便任何时刻都可以追踪历史，或者
在将来某个时刻还可以将文件”还原”。
所以创建一个版本库也非常简单，如下我是D盘 –&amp;gt; www下 目录下新建一个testgit版本库。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171534501.png&quot; alt=&quot;image-20250617153407477&quot;&gt;&lt;/p&gt;
&lt;p&gt;pwd 命令是用于显示当前的目录。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;通过命令 git init 把这个目录变成git可以管理的仓库，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171534107.png&quot; alt=&quot;image-20250617153428083&quot;&gt;&lt;/p&gt;
&lt;p&gt;这时候你当前testgit目录下会多了一个.git的目录，这个目录是Git来跟踪管理版本的，没事千万不
要手动乱改这个目录里面的文件，否则，会把git仓库给破坏了。
如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171534916.png&quot; alt=&quot;image-20250617153458890&quot;&gt;&lt;/p&gt;
&lt;p&gt;把文件添加到版本库中。
首先要明确下，所有的版本控制系统，只能跟踪文本文件的改动，比如txt文件，网页，所有程序的
代码等，Git也不列外，版本控制系统可以告诉你每次的改动，但是图片，视频这些二进制文件，虽
能也能由版本控制系统管理，但没法跟踪文件的变化，只能把二进制文件每次改动串起来，也就是
知道图片从1kb变成2kb，但是到底改了啥，版本控制也不知道。&lt;/p&gt;
&lt;h4&gt;下面先看演示&lt;/h4&gt;
&lt;p&gt;我在版本库testgit目录下新建一个记事本文件 readme.txt 内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tex&quot;&gt;1111111
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;第一步：git add&lt;/h4&gt;
&lt;p&gt;使用命令 git add readme.txt添加到暂存区里面去。如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171537853.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果和上面一样，没有任何提示，说明已经添加成功了。&lt;/p&gt;
&lt;h4&gt;第二步：git commit&lt;/h4&gt;
&lt;p&gt;用命令 git commit告诉Git，把文件提交到仓库。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171537699.png&quot; alt=&quot;image-20250617153729677&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;现在我们已经提交了一个readme.txt文件了，我们下面可以通过命令git status来查看是否还有文件未提交，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171538538.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;说明没有任何文件未提交，但是我现在继续来改下readme.txt内容，比如我在下面添加一行2222222222
内容，继续使用git status 来查看下结果，如下：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171621614.png&quot; alt=&quot;image-20250617162158565&quot;&gt;&lt;/p&gt;
&lt;p&gt;上面的命令告诉我们 readme.txt文件已被修改，但是未被提交的修改。
接下来我想看下readme.txt文件到底改了什么内容，如何查看呢？可以使用如下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git diff readme.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如下：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171539762.png&quot; alt=&quot;image-20250617153935736&quot;&gt;&lt;/p&gt;
&lt;p&gt;如上可以看到，readme.txt文件内容从一行11111111改成 二行 添加了一行22222222内容。
知道了对readme.txt文件做了什么修改后，我们可以放心的提交到仓库了。
提交修改和提交文件是一样的2步： &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;git add&lt;/strong&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;git commit&lt;/strong&gt;       &lt;/p&gt;
&lt;p&gt;如下：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171541794.png&quot; alt=&quot;image-20250617154101763&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;二、版本回退&lt;/h3&gt;
&lt;p&gt;如上，我们已经学会了修改文件，现在我继续对readme.txt文件进行修改，再增加一行内容为
33333333333333.继续执行命令如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171541205.png&quot; alt=&quot;image-20250617154128180&quot;&gt;&lt;/p&gt;
&lt;h4&gt;1、git log&lt;/h4&gt;
&lt;p&gt;现在我已经对readme.txt文件做了三次修改了，那么我现在想查看下历史记录，如何查呢？我们现在可
以使用命令 git log 演示如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171541401.png&quot; alt=&quot;image-20250617154159370&quot;&gt;&lt;/p&gt;
&lt;p&gt;git log命令显示从最近到最远的显示日志，我们可以看到最近三次提交，最近的一次是,增加内容为
333333.上一次是添加内容222222，第一次默认是 111111.如果嫌上面显示的信息太多的话，我们可以
使用命令 git log --pretty=oneline 演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171542347.png&quot; alt=&quot;image-20250617154224322&quot;&gt;&lt;/p&gt;
&lt;h4&gt;2、版本回退&lt;/h4&gt;
&lt;p&gt;现在我想使用版本回退操作，我想把当前的版本回退到上一个版本，要使用什么命令呢？
可以使用如下2种命令：&lt;/p&gt;
&lt;h5&gt;git reset --hard HEAD^&lt;/h5&gt;
&lt;p&gt;第一种是：git reset --hard HEAD^ 那么如果要回退到上上个版本只需把HEAD^ 改成 HEAD^^ 以此
类推。那如果要回退到前100个版本的话，使用上面的方法肯定不方便，我们可以使用下面的简便命令操
作：git reset --hard HEAD~100 即可。未回退之前的readme.txt内容如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171542212.png&quot; alt=&quot;image-20250617154248184&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果想回退到上一个版本的命令如下操作：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171543589.png&quot; alt=&quot;image-20250617154301565&quot;&gt;&lt;/p&gt;
&lt;p&gt;再来查看下 readme.txt内容如下：通过命令cat readme.txt查看&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171543326.png&quot; alt=&quot;image-20250617154316303&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看到，内容已经回退到上一个版本了。我们可以继续使用git log 来查看下历史记录信息，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171543797.png&quot; alt=&quot;image-20250617154332771&quot;&gt;&lt;/p&gt;
&lt;h5&gt;git reset --hard 版本号&lt;/h5&gt;
&lt;p&gt;我们看到 增加333333 内容我们没有看到了，但是现在我想回退到最新的版本，如：有333333的内容要
如何恢复呢？我们可以通过版本号回退，使用命令方法如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git reset --hard 版本号 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是现在的问题假如我已经关掉过一次命令行或者333内容的版本号我并不知
道呢？要如何知道增加3333内容的版本号呢？可以通过如下命令即可获取到版本号：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git reflog 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171545856.png&quot; alt=&quot;image-20250617154528828&quot;&gt;&lt;/p&gt;
&lt;p&gt;通过上面的显示我们可以知道，增加内容3333的版本号是 6fcfc89.我们现在可以命令git reset --hard
6fcfc89来恢复了。演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171547793.png&quot; alt=&quot;image-20250617154707767&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看到 目前已经是最新的版本了。&lt;/p&gt;
&lt;h2&gt;三、理解工作区与暂存区的区别？&lt;/h2&gt;
&lt;p&gt;工作区：就是你在电脑上看到的目录，比如目录下testgit里的文件(.git隐藏目录版本库除外)。或者以后
需要再新建的目录文件等等都属于工作区范畴。
版本库(Repository)：工作区有一个隐藏目录.git,这个不属于工作区，这是版本库。其中版本库里面存了
很多东西，其中最重要的就是stage(暂存区)，还有Git为我们自动创建了第一个分支master,以及指向
master的一个指针HEAD。
我们前面说过使用Git提交文件到版本库有两步：
第一步：是使用 git add 把文件添加进去，实际上就是把文件添加到暂存区。
第二步：使用git commit提交更改，实际上就是把暂存区的所有内容提交到当前分支上。
我们继续使用demo来演示下：
我们在readme.txt再添加一行内容为4444444，接着在目录下新建一个文件为test.txt 内容为test，我们先用命令 &lt;strong&gt;git status&lt;/strong&gt;来查看下状态，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171548177.png&quot; alt=&quot;image-20250617154836149&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在我们先使用git add 命令把2个文件都添加到暂存区中，再使用git status来查看下状态，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171548013.png&quot; alt=&quot;image-20250617154851985&quot;&gt;&lt;/p&gt;
&lt;p&gt;接着我们可以使用git commit一次性提交到分支上，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171549770.png&quot; alt=&quot;image-20250617154905744&quot;&gt;&lt;/p&gt;
&lt;p&gt;四：Git撤销修改和删除文件操作。
一：撤销修改：
比如我现在在readme.txt文件里面增加一行 内容为555555555555，我们先通过命令查看如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171549780.png&quot; alt=&quot;image-20250617154925756&quot;&gt;&lt;/p&gt;
&lt;p&gt;在我未提交之前，我发现添加5555555555555内容有误，所以我得马上恢复以前的版本，现在我可以有
如下几种方法可以做修改：
第一：如果我知道要删掉那些内容的话，直接手动更改去掉那些需要的文件，然后add添加到暂存区，最
后commit掉。
第二：我可以按以前的方法直接恢复到上一个版本。使用 git reset --hard HEAD^
但是现在我不想使用上面的2种方法，我想直接想使用撤销命令该如何操作呢？首先在做撤销之前，我们
可以先用 git status 查看下当前的状态。如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171549014.png&quot; alt=&quot;image-20250617154945989&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以发现，Git会告诉你，git checkout -- file 可以丢弃工作区的修改，如下命令：
git checkout -- readme.txt,如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171550147.png&quot; alt=&quot;image-20250617155006119&quot;&gt;&lt;/p&gt;
&lt;p&gt;命令 git checkout --readme.txt 意思就是，把readme.txt文件在工作区做的修改全部撤销，这里有2种
情况，如下：
1.readme.txt自动修改后，还没有放到暂存区，使用 撤销修改就回到和版本库一模一样的状态。
2.另外一种是readme.txt已经放入暂存区了，接着又作了修改，撤销修改就回到添加暂存区后的状态。
对于第二种情况，假如现在我对readme.txt添加一行 内容为6666666666666，我git add 增加到暂存区
后，接着添加内容7777777，我想通过撤销命令让其回到暂存区后的状态。如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171550300.png&quot; alt=&quot;image-20250617155022269&quot;&gt;&lt;/p&gt;
&lt;p&gt;注意：命令git checkout -- readme.txt 中的 -- 很重要，如果没有 -- 的话，那么命令变成创建分支了。
二：删除文件。
假如我现在版本库testgit目录添加一个文件b.txt,然后提交。如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171550264.png&quot; alt=&quot;image-20250617155037221&quot;&gt;&lt;/p&gt;
&lt;p&gt;如上：一般情况下，可以直接在文件目录中把文件删了，或者使用如上rm命令：rm b.txt ，如果我想彻
底从版本库中删掉了此文件的话，可以再执行commit命令 提交掉，现在目录是这样的，&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171550139.png&quot; alt=&quot;image-20250617155053112&quot;&gt;&lt;/p&gt;
&lt;p&gt;只要没有commit之前，如果我想在版本库中恢复此文件如何操作呢？
可以使用如下命令 git checkout -- b.txt，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171551287.png&quot; alt=&quot;image-20250617155105262&quot;&gt;&lt;/p&gt;
&lt;p&gt;再来看看我们testgit目录，添加了3个文件了。如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171551964.png&quot; alt=&quot;image-20250617155120933&quot;&gt;&lt;/p&gt;
&lt;h2&gt;四：远程仓库&lt;/h2&gt;
&lt;p&gt;在了解之前，先注册github账号，由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的，所
以需要一点设置：&lt;/p&gt;
&lt;h3&gt;第一步：创建SSH Key。&lt;/h3&gt;
&lt;p&gt;在用户主目录下，看看有没有.ssh目录，如果有，再看看这个目录下有没有id_rsa和id_rsa.pub这两个文
件，如果有的话，直接跳过此如下命令，如果没有的话，打开命令行，输入如下命令：
ssh-keygen -t rsa –C “&lt;a href=&quot;mailto:youremail@example.com&quot;&gt;youremail@example.com&lt;/a&gt;”, 由于我本地此前运行过一次，所以本地有，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171551621.png&quot; alt=&quot;image-20250617155149588&quot;&gt;&lt;/p&gt;
&lt;p&gt;id_rsa是私钥，不能泄露出去，id_rsa.pub是公钥，可以放心地告诉任何人。&lt;/p&gt;
&lt;h3&gt;第二步：Add SSH Key&lt;/h3&gt;
&lt;p&gt;登录github,打开” settings”中的SSH Keys页面，然后点击“Add SSH Key”,填上任意title，在Key文本框里
黏贴id_rsa.pub文件的内容。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171552776.png&quot; alt=&quot;image-20250617155213724&quot;&gt;&lt;/p&gt;
&lt;p&gt;点击 Add Key，你就应该可以看到已经添加的key。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171552881.png&quot; alt=&quot;image-20250617155231847&quot;&gt;&lt;/p&gt;
&lt;p&gt;如何添加远程库？
现在的情景是：我们已经在本地创建了一个Git仓库后，又想在github创建一个Git仓库，并且希望这两个
仓库进行远程同步，这样github的仓库可以作为备份，又可以其他人通过该仓库来协作。
首先，登录github上，然后在右上角找到“create a new repo”创建一个新的仓库。如下&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171552245.png&quot; alt=&quot;image-20250617155243200&quot;&gt;&lt;/p&gt;
&lt;p&gt;在Repository name填入testgit，其他保持默认设置，点击“Create repository”按钮，就成功地创建了一
个新的Git仓库：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171553918.png&quot; alt=&quot;image-20250617155300863&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以把一个已有的本地仓库与之关联，然后，把本地仓库的内容推送到GitHub仓库。
现在，我们根据GitHub的提示，在本地的testgit仓库下运行命令：
git remote add origin &lt;a href=&quot;https://github.com/tugenhua0707/testgit.git&quot;&gt;https://github.com/tugenhua0707/testgit.git&lt;/a&gt;
所有的如下：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171553233.png&quot; alt=&quot;image-20250617155315203&quot;&gt;&lt;/p&gt;
&lt;p&gt;把本地库的内容推送到远程，使用 git push命令，实际上是把当前分支master推送到远程。
由于远程库是空的，我们第一次推送master分支时，加上了 –u参数，Git不但会把本地的master分支内
容推送的远程新的master分支，还会把本地的master分支和远程的master分支关联起来，在以后的推
送或者拉取时就可以简化命令。推送成功后，可以立刻在github页面中看到远程库的内容已经和本地一
模一样了，上面的要输入github的用户名和密码如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171553304.png&quot; alt=&quot;image-20250617155335260&quot;&gt;&lt;/p&gt;
&lt;p&gt;从现在起，只要本地作了提交，就可以通过如下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git push origin master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;把本地master分支的最新修改推送到github上了，现在你就拥有了真正的分布式版本库了。&lt;/p&gt;
&lt;h3&gt;如何从远程库克隆？&lt;/h3&gt;
&lt;p&gt;上面我们了解了先有本地库，后有远程库时候，如何关联远程库。
现在我们想，假如远程库有新的内容了，我想克隆到本地来 如何克隆呢？
首先，登录github，创建一个新的仓库，名字叫testgit2.如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171554277.png&quot; alt=&quot;image-20250617155430236&quot;&gt;&lt;/p&gt;
&lt;p&gt;如下，我们看到：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171554108.png&quot; alt=&quot;image-20250617155446060&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在，远程库已经准备好了，下一步是使用命令git clone克隆一个本地库了。如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171554153.png&quot; alt=&quot;image-20250617155459126&quot;&gt;&lt;/p&gt;
&lt;p&gt;接着在我本地目录下 生成testgit2目录了，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171555028.png&quot; alt=&quot;image-20250617155511995&quot;&gt;&lt;/p&gt;
&lt;h2&gt;五：创建与合并分支&lt;/h2&gt;
&lt;p&gt;在版本回退里，你已经知道，每次提交，Git都把它们串成一条时间线，这条时间线就是一个分支。截止
到目前，只有一条时间线，在Git里，这个分支叫主分支，即master分支。HEAD严格来说不是指向提
交，而是指向master，master才是指向提交的，所以，HEAD指向的就是当前分支。&lt;/p&gt;
&lt;h3&gt;创建dev分支&lt;/h3&gt;
&lt;p&gt;首先，我们来创建dev分支，然后切换到dev分支上。如下操作：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171555544.png&quot; alt=&quot;image-20250617155536516&quot;&gt;&lt;/p&gt;
&lt;p&gt;git checkout 命令加上 –b参数表示创建并切换，相当于如下2条命令&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git branch dev
git checkout dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;git branch查看分支，会列出所有的分支，当前分支前面会添加一个星号。然后我们在dev分支上继续做
demo，比如我们现在在readme.txt再增加一行 7777777777777
首先我们先来查看下readme.txt内容，接着添加内容77777777，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171556535.png&quot; alt=&quot;image-20250617155618506&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在dev分支工作已完成，现在我们切换到主分支master上，继续查看readme.txt内容如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171556423.png&quot; alt=&quot;image-20250617155629395&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在我们可以把dev分支上的内容合并到分支master上了，可以在master分支上，使用如下命令 git
merge dev 如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171556193.png&quot; alt=&quot;image-20250617155644160&quot;&gt;&lt;/p&gt;
&lt;h3&gt;git merge合并&lt;/h3&gt;
&lt;p&gt;git merge命令用于合并指定分支到当前分支上，合并后，再查看readme.txt内容，可以看到，和dev分
支最新提交的是完全一样的。注意到上面的Fast-forward信息，Git告诉我们，这次合并是“快进模式”，
也就是直接把master指向dev的当前提交，所以合并速度非常快。合并完成后，我们可以接着删除dev分
支了，操作如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171557184.png&quot; alt=&quot;image-20250617155705157&quot;&gt;&lt;/p&gt;
&lt;p&gt;总结创建与合并分支命令如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;查看分支：git branch
创建分支：git branch name
切换分支：git checkout name
创建+切换分支：git checkout –b name
合并某分支到当前分支：git merge name
删除分支：git branch –d name
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;如何解决冲突？&lt;/h3&gt;
&lt;p&gt;下面我们还是一步一步来，先新建一个新分支，比如名字叫fenzhi1，在readme.txt添加一行内容
8888888，然后提交，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171558101.png&quot; alt=&quot;image-20250617155813071&quot;&gt;&lt;/p&gt;
&lt;p&gt;同样，我们现在切换到master分支上来，也在最后一行添加内容，内容为99999999，如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171558166.png&quot; alt=&quot;image-20250617155826135&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在我们需要在master分支上来合并fenzhi1，如下操作：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171558673.png&quot; alt=&quot;image-20250617155854635&quot;&gt;&lt;/p&gt;
&lt;p&gt;Git用&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;，=======，&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;标记出不同分支的内容，其中&amp;lt;&amp;lt;&amp;lt;HEAD是指主分支修改的内容，&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;fenzhi1 是指fenzhi1上修改的内容，我们可以修改下如下后保存：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171559899.png&quot; alt=&quot;image-20250617155915859&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果我想查看分支合并的情况的话，需要使用命令 git log.命令行演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171559316.png&quot; alt=&quot;image-20250617155931261&quot;&gt;&lt;/p&gt;
&lt;h3&gt;分支管理策略。&lt;/h3&gt;
&lt;p&gt;通常合并分支时，git一般使用”Fast forward”模式，在这种模式下，删除分支后，会丢掉分支信息，现在
我们来使用带参数 –no-ff来禁用”Fast forward”模式。首先我们来做demo演示下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;1、创建一个dev分支。
2、修改readme.txt内容。
3、添加到暂存区。
4、切换回主分支(master)。
5、合并dev分支，使用命令 git merge –no-ff -m “注释” dev
6、查看历史记录
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;截图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171600458.png&quot; alt=&quot;image-20250617160018417&quot;&gt;&lt;/p&gt;
&lt;p&gt;分支策略：首先master主分支应该是非常稳定的，也就是用来发布新版本，一般情况下不允许在上面干
活，干活一般情况下在新建的dev分支上干活，干完后，比如要发布，或者说dev分支代码稳定后可以合
并到主分支master上来。
1、创建一个dev分支。
2、修改readme.txt内容。
3、添加到暂存区。
4、切换回主分支(master)。
5、合并dev分支，使用命令 git merge –no-ff -m “注释” dev
6、查看历史记录&lt;/p&gt;
&lt;h2&gt;六：bug分支&lt;/h2&gt;
&lt;p&gt;在开发中，会经常碰到bug问题，那么有了bug就需要修复，在Git中，分支是很强大的，每个bug都可以
通过一个临时分支来修复，修复完成后，合并分支，然后将临时的分支删除掉。
比如我在开发中接到一个404 bug时候，我们可以创建一个404分支来修复它，但是，当前的dev分支上
的工作还没有提交。比如如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171600011.png&quot; alt=&quot;image-20250617160039981&quot;&gt;&lt;/p&gt;
&lt;p&gt;并不是我不想提交，而是工作进行到一半时候，我们还无法提交，比如我这个分支bug要2天完成，但是
我issue-404 bug需要5个小时内完成。怎么办呢？还好，Git还提供了一个stash功能，可以把当前工作现
场 ”隐藏起来”，等以后恢复现场后继续工作。如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171600597.png&quot; alt=&quot;image-20250617160059568&quot;&gt;&lt;/p&gt;
&lt;p&gt;所以现在我可以通过创建issue-404分支来修复bug了。
首先我们要确定在那个分支上修复bug，比如我现在是在主分支master上来修复的，现在我要在master
分支上创建一个临时分支，演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171601497.png&quot; alt=&quot;image-20250617160112464&quot;&gt;&lt;/p&gt;
&lt;p&gt;修复完成后，切换到master分支上，并完成合并，最后删除issue-404分支。演示如下：
&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171601451.png&quot; alt=&quot;image-20250617160126415&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在，我们回到dev分支上干活了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171601021.png&quot; alt=&quot;image-20250617160140992&quot;&gt;&lt;/p&gt;
&lt;p&gt;工作区是干净的，那么我们工作现场去哪里呢？我们可以使用命令 git stash list来查看下。如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171601373.png&quot; alt=&quot;image-20250617160153342&quot;&gt;&lt;/p&gt;
&lt;p&gt;工作现场还在，Git把stash内容存在某个地方了，但是需要恢复一下，可以使用如下2个方法：
1.git stash apply恢复，恢复后，stash内容并不删除，你需要使用命令git stash drop来删除。
2.另一种方式是使用git stash pop,恢复的同时把stash内容也删除了。
演示如下&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171602109.png&quot; alt=&quot;image-20250617160236071&quot;&gt;&lt;/p&gt;
&lt;h2&gt;七：多人协作&lt;/h2&gt;
&lt;p&gt;当你从远程库克隆时候，实际上Git自动把本地的master分支和远程的master分支对应起来了，并且远
程库的默认名称是origin。
要查看远程库的信息 使用 git remote
要查看远程库的详细信息 使用 git remote –v
如下演示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171602049.png&quot; alt=&quot;image-20250617160247020&quot;&gt;&lt;/p&gt;
&lt;h3&gt;一、推送分支：&lt;/h3&gt;
&lt;p&gt;推送分支就是把该分支上所有本地提交到远程库中，推送时，要指定本地分支，这样，Git就会把该分支
推送到远程库对应的远程分支上：
使用命令 git push origin master
比如我现在的github上的readme.txt代码如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171603742.png&quot; alt=&quot;image-20250617160309703&quot;&gt;&lt;/p&gt;
&lt;p&gt;本地的readme.txt代码如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171603112.png&quot; alt=&quot;image-20250617160321084&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在我想把本地更新的readme.txt代码推送到远程库中，使用命令如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171603373.png&quot; alt=&quot;image-20250617160331344&quot;&gt;&lt;/p&gt;
&lt;p&gt;我们可以看到如上，推送成功，我们可以继续来截图github上的readme.txt内容 如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171603703.png&quot; alt=&quot;image-20250617160341656&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看到 推送成功了，如果我们现在要推送到其他分支，比如dev分支上，我们还是那个命令 git push
origin dev 那么一般情况下，那些分支要推送呢？
master分支是主分支，因此要时刻与远程同步。
一些修复bug分支不需要推送到远程去，可以先合并到主分支上，然后把主分支master推送到远程去。&lt;/p&gt;
&lt;h3&gt;二：抓取分支：&lt;/h3&gt;
&lt;p&gt;多人协作时，大家都会往master分支上推送各自的修改。现在我们可以模拟另外一个同事，可以在另一
台电脑上（注意要把SSH key添加到github上）或者同一台电脑上另外一个目录克隆，新建一个目录名字
叫testgit2
但是我首先要把dev分支也要推送到远程去，如下&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171603598.png&quot; alt=&quot;image-20250617160357563&quot;&gt;&lt;/p&gt;
&lt;p&gt;接着进入testgit2目录，进行克隆远程的库到本地来，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171604904.png&quot; alt=&quot;image-20250617160406867&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在目录下生成有如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171604602.png&quot; alt=&quot;image-20250617160431567&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在我们的小伙伴要在dev分支上做开发，就必须把远程的origin的dev分支到本地来，于是可以使用命
令创建本地dev分支：git checkout –b dev origin/dev
现在小伙伴们就可以在dev分支上做开发了，开发完成后把dev分支推送到远程库时。
如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171604271.png&quot; alt=&quot;image-20250617160448234&quot;&gt;&lt;/p&gt;
&lt;p&gt;小伙伴们已经向origin/dev分支上推送了提交，而我在我的目录文件下也对同样的文件同个地方作了修
改，也试图推送到远程库时，如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171605627.png&quot; alt=&quot;image-20250617160513583&quot;&gt;&lt;/p&gt;
&lt;p&gt;由上面可知：推送失败，因为我的小伙伴最新提交的和我试图推送的有冲突，解决的办法也很简单，上
面已经提示我们，先用git pull把最新的提交从origin/dev抓下来，然后在本地合并，解决冲突，再推
送。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171605155.png&quot; alt=&quot;image-20250617160537118&quot;&gt;&lt;/p&gt;
&lt;p&gt;git pull也失败了，原因是没有指定本地dev分支与远程origin/dev分支的链接，根据提示，设置dev和
origin/dev的链接：如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171605999.png&quot; alt=&quot;image-20250617160555967&quot;&gt;&lt;/p&gt;
&lt;p&gt;这回git pull成功，但是合并有冲突，需要手动解决，解决的方法和分支管理中的 解决冲突完全一样。解
决后，提交，再push：
我们可以先来看看readme.txt内容了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171606357.png&quot; alt=&quot;image-20250617160608327&quot;&gt;&lt;/p&gt;
&lt;p&gt;现在手动已经解决完了，我接在需要再提交，再push到远程库里面去。如下所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/xz131714/PicBed@main/202506171606564.png&quot; alt=&quot;image-20250617160620529&quot;&gt;&lt;/p&gt;
&lt;p&gt;因此：多人协作工作模式一般是这样的：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;首先，可以试图用git push origin branch-name推送自己的修改.
如果推送失败，则因为远程分支比你的本地更新早，需要先用git pull试图合并。
如果合并有冲突，则需要解决冲突，并在本地提交。再用git push origin branch-name推送。
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 17 Jun 2025 00:00:00 GMT</pubDate></item><item><title>🚀 Sqoop的导入导出</title><link>https://hub.xiaozhangya.xin/blog/sqoop/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/sqoop/</guid><description>Sqoop的导入导出命令的基本使用方法</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/sqoop/&quot;&gt;https://hub.xiaozhangya.xin/blog/sqoop/&lt;/a&gt;&lt;/blockquote&gt; &lt;h2&gt;🔁 一、全量导入（Import）&lt;/h2&gt;
&lt;h3&gt;1. 导入 MySQL 表到 HDFS&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqoop import \
--connect jdbc:mysql://localhost:3306/testdb \     # MySQL JDBC连接
--username root \                                  # 用户名
--password root \                                  # 密码
--table emp \                                      # 要导入的MySQL表名
--target-dir /user/hadoop/emp \                    # 数据导入到的HDFS目录
--delete-target-dir \                              # 删除原有目录（防止重复）
--fields-terminated-by &amp;#39;\t&amp;#39; \                      # 指定字段分隔符为tab
--num-mappers 1                                    # 使用一个Map任务（方便查看）
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;2. 导入 MySQL 表到 Hive 表中&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqoop import \
--connect jdbc:mysql://localhost:3306/testdb \     # 连接MySQL数据库
--username root \                                  # 用户名
--password root \                                  # 密码
--table emp \                                      # 表名
--hive-import \                                    # 导入到Hive中
--hive-table emp_hive \                            # 指定Hive表名
--fields-terminated-by &amp;#39;\t&amp;#39; \                      # 字段分隔符
--num-mappers 1                                    # 一个Map任务
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;🔄 二、增量导入（Incremental Import）&lt;/h2&gt;
&lt;h3&gt;1. 模式一：追加模式（append）按ID导入新数据&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqoop import \
--connect jdbc:mysql://localhost:3306/testdb \     # MySQL连接
--username root \                                  # 用户名
--password root \                                  # 密码
--table emp \                                      # 表名
--incremental append \                             # 使用追加模式
--check-column id \                                # 检查id字段的值
--last-value 1000 \                                # 上次最大id，导入id &amp;gt; 1000的数据
--target-dir /user/hadoop/emp_increment \          # HDFS目标路径
--fields-terminated-by &amp;#39;\t&amp;#39; \                      # 字段分隔符
--num-mappers 1                                    # Map任务数量
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;2. 模式二：按更新时间（lastmodified）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqoop import \
--connect jdbc:mysql://localhost:3306/testdb \     # MySQL连接
--username root \                                  # 用户名
--password root \                                  # 密码
--table emp \                                      # 表名
--incremental lastmodified \                       # 使用lastmodified模式
--check-column last_updated \                      # 检查更新时间字段
--last-value &amp;quot;2024-01-01 00:00:00&amp;quot; \               # 上次导入时间
--target-dir /user/hadoop/emp_updated \            # HDFS路径
--fields-terminated-by &amp;#39;\t&amp;#39; \                      # 字段分隔符
--num-mappers 1                                    # Map任务数量
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;🔃 三、导出（Export）从 HDFS 到 MySQL&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqoop export \
--connect jdbc:mysql://localhost:3306/testdb \     # 目标MySQL数据库
--username root \                                  # 用户名
--password root \                                  # 密码
--table emp_backup \                               # 要导出的MySQL表
--export-dir /user/hadoop/emp \                    # HDFS中源数据路径
--fields-terminated-by &amp;#39;\t&amp;#39; \                      # 字段分隔符要和导入时一致
--num-mappers 1                                    # 使用一个Map任务导出
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;📌 附加说明&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数&lt;/th&gt;
&lt;th&gt;中文说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--connect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定数据库 JDBC 连接字符串（例如 MySQL）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--username&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库用户名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;数据库密码（建议改为 --password-file 以提升安全）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--password-file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;从本地文件读取密码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--table&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;要导入或导出的数据库表名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--target-dir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定导入数据的 HDFS 目标目录&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--delete-target-dir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;如果目标目录已存在，则先删除它&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--fields-terminated-by&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;设置字段之间的分隔符，常用 &lt;code&gt;&amp;#39;\t&amp;#39;&lt;/code&gt;（制表符）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--num-mappers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;设置并行执行 Map 任务数（默认4）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--split-by&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;用于 Map 任务并发切分的字段名，通常为主键&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--hive-import&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;导入数据后自动将其加载到 Hive 表中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--hive-table&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定 Hive 中的目标表名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--incremental&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;增量导入模式：&lt;code&gt;append&lt;/code&gt;（追加）或 &lt;code&gt;lastmodified&lt;/code&gt;（按更新时间）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--check-column&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;增量导入时用于判断新增数据的列名（如 &lt;code&gt;id&lt;/code&gt; 或 &lt;code&gt;last_updated&lt;/code&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--last-value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定上次导入的最大ID或最近更新时间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--columns&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定导入/导出的字段子集，使用逗号分隔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--where&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;自定义SQL查询条件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--export-dir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HDFS中要导出数据的目录路径&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--as-textfile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定数据以文本格式保存（默认）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--compress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;启用压缩&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--compression-codec&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;压缩类型（如 &lt;code&gt;org.apache.hadoop.io.compress.GzipCodec&lt;/code&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--map-column-java&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定字段与 Java 类型的映射&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--driver&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定数据库的 JDBC 驱动类（如非 MySQL）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sun, 15 Jun 2025 00:00:00 GMT</pubDate></item><item><title>🚀 Hadoop &amp; Hive 数据仓库</title><link>https://hub.xiaozhangya.xin/blog/hadoop_hive_warehouse/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/hadoop_hive_warehouse/</guid><description>Hadoop与Hive的基本概念、安装配置及使用方法。</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/hadoop_hive_warehouse/&quot;&gt;https://hub.xiaozhangya.xin/blog/hadoop_hive_warehouse/&lt;/a&gt;&lt;/blockquote&gt; &lt;h1&gt;Hadoop &amp;amp; Hive 数据仓库&lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt;一、数据仓库定义&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;数据仓库（Data Warehouse）&lt;/strong&gt; 是面向主题的、集成的、相对稳定的、反映历史变化的数据集合，用于支持管理决策。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;主要特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;面向主题（主题导向）&lt;/li&gt;
&lt;li&gt;集成多个数据源数据&lt;/li&gt;
&lt;li&gt;数据相对稳定，历史数据保存&lt;/li&gt;
&lt;li&gt;支持复杂查询和分析，不适合频繁更新&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;二、数据仓库与数据库的对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;比较维度&lt;/th&gt;
&lt;th&gt;数据库&lt;/th&gt;
&lt;th&gt;数据仓库&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;设计目的&lt;/td&gt;
&lt;td&gt;支持日常业务操作（OLTP）&lt;/td&gt;
&lt;td&gt;支持决策分析（OLAP）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据结构&lt;/td&gt;
&lt;td&gt;规范化，减少冗余&lt;/td&gt;
&lt;td&gt;非规范化，方便查询和分析&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据更新频率&lt;/td&gt;
&lt;td&gt;高频更新&lt;/td&gt;
&lt;td&gt;低频更新，主要为批量加载&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;查询类型&lt;/td&gt;
&lt;td&gt;简单、频繁&lt;/td&gt;
&lt;td&gt;复杂、跨时间和主题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据历史&lt;/td&gt;
&lt;td&gt;一般只保存当前数据&lt;/td&gt;
&lt;td&gt;保存大量历史数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;性能优化&lt;/td&gt;
&lt;td&gt;针对事务处理优化&lt;/td&gt;
&lt;td&gt;针对查询和分析优化&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;三、简答题模板答案&lt;/h2&gt;
&lt;h3&gt;1. Hadoop 环境搭建步骤&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;安装 JDK，配置环境变量 &lt;code&gt;JAVA_HOME&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;配置主机名映射（&lt;code&gt;/etc/hosts&lt;/code&gt;），确保各节点能互相解析。&lt;/li&gt;
&lt;li&gt;配置 SSH 免密登录，使用 &lt;code&gt;ssh-keygen&lt;/code&gt; 和 &lt;code&gt;ssh-copy-id&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;安装 Hadoop，配置核心文件，启动集群。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;2. Hive 数据仓库层次结构&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ODS（原始层）&lt;/strong&gt;：存储原始日志和业务数据，未清洗。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DWD（明细层）&lt;/strong&gt;：数据清洗、结构化，规范字段。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DWS（汇总层）&lt;/strong&gt;：按主题聚合，支持分析查询。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ADS（应用层）&lt;/strong&gt;：面向应用和报表的最终数据层。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;3. 日志数据采集方式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;strong&gt;Flume&lt;/strong&gt; 采集日志，组成：Source（数据输入）、Channel（缓冲）、Sink（输出存储）。&lt;/li&gt;
&lt;li&gt;结合 &lt;strong&gt;Kafka&lt;/strong&gt; 实现高吞吐、实时处理，日志写入 Kafka，再由 Spark/Flink 等实时消费。&lt;/li&gt;
&lt;li&gt;Flume 可直接将日志写入 HDFS 或 Kafka。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;4. Hive 中常用概念&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分区表&lt;/strong&gt;：按字段分区存储，提高查询效率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内部表&lt;/strong&gt;：Hive 管理数据，删除表时数据也删除。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;外部表&lt;/strong&gt;：只管理表结构，删除表不删除数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据倾斜&lt;/strong&gt;：某些 key 数据量过大，导致资源分配不均衡，影响性能。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;四、口诀记忆版&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;th&gt;口诀&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;JDK+主机映射+免密登录&lt;/td&gt;
&lt;td&gt;JDK装好主机通，免密SSH连通&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive仓库四层结构&lt;/td&gt;
&lt;td&gt;原始ODS明细DWD，汇总DWS应用ADS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flume采集三大件&lt;/td&gt;
&lt;td&gt;来源输入缓冲流，输出到存储去&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kafka作用&lt;/td&gt;
&lt;td&gt;高吞吐，消息队，实时流数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hive表两种类型&lt;/td&gt;
&lt;td&gt;内表管数据，外表管结构&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据倾斜问题&lt;/td&gt;
&lt;td&gt;某键数据大，计算资源卡&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;五、Hive 基础操作&lt;/h2&gt;
&lt;h3&gt;1. 创建数据库&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE DATABASE mydb;     -- 创建一个名为 mydb 的数据库
USE mydb;                 -- 切换当前使用的数据库为 mydb
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 创建表&lt;/h3&gt;
&lt;h4&gt;管理表（内部表）&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE emp (
    id INT,              -- 员工编号，整型
    name STRING,         -- 员工姓名，字符串
    age INT,             -- 员工年龄，整型
    dept STRING          -- 员工所在部门，字符串
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY &amp;#39;\t&amp;#39;;  -- 字段分隔符为制表符
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;外部表&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTERNAL TABLE emp_ext (
    id INT,
    name STRING,
    age INT,
    dept STRING
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY &amp;#39;\t&amp;#39;
LOCATION &amp;#39;/user/hive/warehouse/emp_ext&amp;#39;;  -- 指定外部表数据存储路径
-- 外部表删除只删除元数据，不会删除数据文件
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;六、数据导入操作&lt;/h2&gt;
&lt;h3&gt;1. 本地文件导入表&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;LOAD DATA LOCAL INPATH &amp;#39;/home/user/emp.txt&amp;#39; INTO TABLE emp;  -- 将本地文件数据导入表
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. HDFS 文件导入表&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;LOAD DATA INPATH &amp;#39;/user/hadoop/emp.txt&amp;#39; INTO TABLE emp;      -- 将HDFS文件追加导入表
LOAD DATA INPATH &amp;#39;/user/hadoop/emp.txt&amp;#39; OVERWRITE INTO TABLE emp;  -- 将HDFS文件覆盖导入表
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;七、Hive 数据分析操作&lt;/h2&gt;
&lt;h3&gt;1. 查询所有数据&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM emp;   -- 查询表中所有记录
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 分组聚合查询（GROUP BY）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT dept, COUNT(*) AS emp_count    -- 按部门统计员工数量
FROM emp
GROUP BY dept;

SELECT dept, AVG(age) AS avg_age      -- 按部门计算平均年龄
FROM emp
GROUP BY dept;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 过滤条件（WHERE）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM emp
WHERE age &amp;gt; 30;   -- 查询年龄大于30岁的员工
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 排序（ORDER BY / SORT BY / DISTRIBUTE BY）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM emp ORDER BY age;                      -- 全局排序，按年龄升序
SELECT * FROM emp SORT BY age;                       -- 局部排序，适合MapReduce局部排序
SELECT * FROM emp DISTRIBUTE BY dept SORT BY age;   -- 按部门分区后，部门内按年龄排序
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;八、多表关联查询（JOIN）&lt;/h2&gt;
&lt;h3&gt;1. 内连接（INNER JOIN）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT e.id, e.name, d.dept_name
FROM emp e
JOIN dept d
ON e.dept = d.dept_id;    -- 返回两个表匹配部门的记录
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 左外连接（LEFT OUTER JOIN）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT e.id, e.name, d.dept_name
FROM emp e
LEFT OUTER JOIN dept d
ON e.dept = d.dept_id;    -- 返回所有员工及对应部门，部门不存在显示NULL
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 右外连接（RIGHT OUTER JOIN）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT e.id, e.name, d.dept_name
FROM emp e
RIGHT OUTER JOIN dept d
ON e.dept = d.dept_id;    -- 返回所有部门及对应员工，员工不存在显示NULL
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 全外连接（FULL OUTER JOIN）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT e.id, e.name, d.dept_name
FROM emp e
FULL OUTER JOIN dept d
ON e.dept = d.dept_id;    -- 返回所有员工和部门的匹配及不匹配记录
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;九、常用函数&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CONCAT(col1, col2);                      -- 字符串连接函数
REPLACE(&amp;#39;hello world&amp;#39;, &amp;#39;world&amp;#39;, &amp;#39;Hive&amp;#39;); -- 字符串替换，将world替换为Hive
FROM_UNIXTIME(UNIX_TIMESTAMP());         -- 获取当前时间，格式化显示
IF(col IS NULL, &amp;#39;空&amp;#39;, col);               -- 条件判断，空值替换为&amp;#39;空&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;十、表结构修改（ALTER TABLE）&lt;/h2&gt;
&lt;h3&gt;1. 重命名表&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE emp RENAME TO emp_new;   -- 将表emp重命名为emp_new
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 添加列&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE emp ADD COLUMNS (
    gender STRING COMMENT &amp;#39;性别&amp;#39;,    -- 新增性别字段，字符串类型，带注释
    salary FLOAT COMMENT &amp;#39;薪资&amp;#39;      -- 新增薪资字段，浮点型，带注释
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 替换列结构（慎用）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE emp REPLACE COLUMNS (
    id INT,
    name STRING,
    age INT,
    dept STRING,
    gender STRING
);  -- 替换表结构，会丢失未列出的字段数据
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 修改列名、类型、位置&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE emp CHANGE name emp_name STRING;        -- 修改列名name为emp_name，类型为STRING
ALTER TABLE emp CHANGE age age INT AFTER emp_name;  -- 修改列age位置，移动到emp_name后
ALTER TABLE emp CHANGE dept dept STRING FIRST;      -- 修改列dept位置，放置为第一列
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. 添加/删除分区（分区表）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE sales ADD PARTITION (year=&amp;#39;2025&amp;#39;, month=&amp;#39;06&amp;#39;);   -- 添加指定分区
ALTER TABLE sales DROP PARTITION (year=&amp;#39;2024&amp;#39;, month=&amp;#39;12&amp;#39;);  -- 删除指定分区
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. 修改表属性或位置&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER TABLE emp SET TBLPROPERTIES (&amp;#39;comment&amp;#39; = &amp;#39;员工信息表&amp;#39;);  -- 设置表注释属性
ALTER TABLE emp SET LOCATION &amp;#39;/new/location&amp;#39;;                 -- 修改表存储路径
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;十一、数据操作（DML）&lt;/h2&gt;
&lt;p&gt;-- Hive默认不支持细粒度UPDATE/DELETE，需要开启ACID支持事务&lt;/p&gt;
&lt;h3&gt;1. 插入数据&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO TABLE emp
SELECT * FROM emp_temp;      -- 将emp_temp数据追加到emp表

INSERT INTO TABLE emp (id, name)
VALUES (1001, &amp;#39;Alice&amp;#39;);     -- 指定列插入单条数据
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 覆盖插入&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT OVERWRITE TABLE emp
SELECT * FROM emp_temp;      -- 用emp_temp数据覆盖emp表
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 更新数据（需启用 ACID）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE emp SET salary = 8000 WHERE id = 1001;   -- 更新指定员工薪资

-- ACID 配置示例
SET hive.support.concurrency = true;
SET hive.enforce.bucketing = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 删除数据（需启用 ACID）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;DELETE FROM emp WHERE age &amp;gt; 60;   -- 删除年龄大于60的员工数据
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. 查询数据&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM emp;                      -- 查询所有员工数据
SELECT name, salary FROM emp WHERE dept = &amp;#39;D001&amp;#39;;  -- 查询指定部门员工姓名和薪资
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. 清空表&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;TRUNCATE TABLE emp;   -- 清空表数据但保留表结构
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sat, 14 Jun 2025 00:00:00 GMT</pubDate></item><item><title>Mathematical Formulas in Markdown</title><link>https://hub.xiaozhangya.xin/blog/mathematics-examples/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/mathematics-examples/</guid><description>A demonstration of various mathematical formulas rendered using LaTeX within Markdown.</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/mathematics-examples/&quot;&gt;https://hub.xiaozhangya.xin/blog/mathematics-examples/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;This document serves as a test for rendering mathematical formulas in Markdown using &lt;code&gt;$$&lt;/code&gt; delimiters.&lt;/p&gt;
&lt;h2&gt;Basic Algebra&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s start with some fundamental algebraic expressions.&lt;/p&gt;
&lt;p&gt;The quadratic formula is given by:
$$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$$&lt;/p&gt;
&lt;p&gt;A simple linear equation:
$$y = mx + c$$&lt;/p&gt;
&lt;p&gt;Expansion of a binomial square:
$$(a+b)^2 = a^2 + 2ab + b^2$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Calculus&lt;/h2&gt;
&lt;p&gt;Here are some common expressions from calculus.&lt;/p&gt;
&lt;p&gt;The limit definition of a derivative:
$$f&amp;#39;(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}$$&lt;/p&gt;
&lt;p&gt;A definite integral:
$$\int_{a}^{b} f(x) dx$$&lt;/p&gt;
&lt;p&gt;The Taylor series expansion of $e^x$ around $x=0$:
$$e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!} = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Trigonometry&lt;/h2&gt;
&lt;p&gt;Some basic trigonometric identities.&lt;/p&gt;
&lt;p&gt;Pythagorean identity:
$$\sin^2\theta + \cos^2\theta = 1$$&lt;/p&gt;
&lt;p&gt;Angle addition formula for sine:
$$\sin(\alpha + \beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta$$&lt;/p&gt;
&lt;p&gt;Euler&amp;#39;s formula:
$$e^{i\theta} = \cos\theta + i\sin\theta$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Statistics and Probability&lt;/h2&gt;
&lt;p&gt;Formulas commonly used in statistics and probability.&lt;/p&gt;
&lt;p&gt;The formula for the mean ($\mu$) of a set of $n$ numbers $x_1, x_2, \ldots, x_n$:
$$\mu = \frac{1}{n} \sum_{i=1}^{n} x_i$$&lt;/p&gt;
&lt;p&gt;The probability density function of a normal distribution:
$$f(x | \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}$$&lt;/p&gt;
&lt;p&gt;Bayes&amp;#39; theorem:
$$P(A|B) = \frac{P(B|A)P(A)}{P(B)}$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Linear Algebra&lt;/h2&gt;
&lt;p&gt;Examples from linear algebra.&lt;/p&gt;
&lt;p&gt;A 2x2 matrix:
$$A = \begin{pmatrix} a &amp;amp; b \ c &amp;amp; d \end{pmatrix}$$&lt;/p&gt;
&lt;p&gt;The determinant of a 2x2 matrix:
$$\det(A) = ad - bc$$&lt;/p&gt;
&lt;p&gt;Matrix multiplication of two matrices A and B:
$$C = AB$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Physics&lt;/h2&gt;
&lt;p&gt;A couple of well-known physics equations.&lt;/p&gt;
&lt;p&gt;Einstein&amp;#39;s mass-energy equivalence:
$$E = mc^2$$&lt;/p&gt;
&lt;p&gt;Newton&amp;#39;s second law of motion:
$$F = ma$$&lt;/p&gt;
&lt;p&gt;This should provide a good test of how various mathematical formulas are rendered.&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sat, 31 May 2025 00:00:00 GMT</pubDate></item><item><title>Adding Comment Systems to RyuChan</title><link>https://hub.xiaozhangya.xin/blog/adding-comment-systems/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/adding-comment-systems/</guid><description>A comprehensive guide on how to integrate the Waline comment system into your RyuChan blog</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/adding-comment-systems/&quot;&gt;https://hub.xiaozhangya.xin/blog/adding-comment-systems/&lt;/a&gt;&lt;/blockquote&gt; &lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;RyuChan 博客现已支持通过配置文件集中管理评论系统，无需在页面手动引入组件或硬编码参数，只需在 &lt;code&gt;ryuchan.config.yaml&lt;/code&gt; 中配置即可。&lt;/p&gt;
&lt;h2&gt;集中式评论系统配置&lt;/h2&gt;
&lt;h3&gt;步骤 1：配置评论系统&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;ryuchan.config.yaml&lt;/code&gt; 中找到 &lt;code&gt;comments&lt;/code&gt; 配置块：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;comments:
  enable: true         # 是否启用评论
  type: giscus        # 可选 giscus/waline/none
  giscus:
    repo: &amp;quot;xxx/xxx&amp;quot;
    repoId: &amp;quot;xxx&amp;quot;
    category: &amp;quot;General&amp;quot;
    categoryId: &amp;quot;xxx&amp;quot;
    mapping: &amp;quot;pathname&amp;quot;
    lang: &amp;quot;zh-CN&amp;quot;
    inputPosition: &amp;quot;top&amp;quot;
    reactionsEnabled: &amp;quot;1&amp;quot;
    emitMetadata: &amp;quot;0&amp;quot;
    loading: &amp;quot;lazy&amp;quot;
  waline:
    serverURL: &amp;quot;https://your-waline-server&amp;quot;
    lang: &amp;quot;zh-CN&amp;quot;
    emoji:
      - &amp;quot;https://unpkg.com/@waline/emojis@1.1.0/weibo&amp;quot;
      - &amp;quot;https://unpkg.com/@waline/emojis@1.1.0/bilibili&amp;quot;
    meta: [&amp;quot;nick&amp;quot;, &amp;quot;mail&amp;quot;, &amp;quot;link&amp;quot;]
    requiredMeta: []
    reaction: false
    pageview: false
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enable: true/false&lt;/code&gt; 控制是否全站显示评论。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type: giscus/waline/none&lt;/code&gt; 控制评论系统类型，&lt;strong&gt;同一时间只会启用一个&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;详细参数请参考各自官方文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;步骤 2：自动渲染，无需手动引入&lt;/h3&gt;
&lt;p&gt;你无需在页面或模板中手动引入 &lt;code&gt;&amp;lt;Giscus /&amp;gt;&lt;/code&gt; 或 &lt;code&gt;&amp;lt;Waline /&amp;gt;&lt;/code&gt; 组件，Ryuchan 已自动根据配置渲染对应评论系统。只需专注于内容创作和配置维护。&lt;/p&gt;
&lt;h3&gt;步骤 3：切换或禁用评论系统&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;切换评论系统：只需修改 &lt;code&gt;type&lt;/code&gt; 字段为 &lt;code&gt;giscus&lt;/code&gt; 或 &lt;code&gt;waline&lt;/code&gt;，保存后自动生效。&lt;/li&gt;
&lt;li&gt;禁用评论系统：将 &lt;code&gt;enable&lt;/code&gt; 设为 &lt;code&gt;false&lt;/code&gt; 即可。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;进阶：自定义 Waline 组件&lt;/h2&gt;
&lt;p&gt;如需自定义 Waline 组件样式或参数，可参考如下代码（已内置于 RyuChan）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;---
// src/components/comments/Waline.astro
interface Props {
  serverURL: string;
  lang?: string;
  dark?: string;
  emoji?: string[];
  meta?: string[];
  requiredMeta?: string[];
  reaction?: boolean;
  pageview?: boolean;
}
const {
  serverURL,
  lang = &amp;quot;zh-CN&amp;quot;,
  dark = &amp;quot;html[data-theme-type=&amp;#39;dark&amp;#39;]&amp;quot;,
  emoji = [&amp;quot;https://unpkg.com/@waline/emojis@1.1.0/weibo&amp;quot;, &amp;quot;https://unpkg.com/@waline/emojis@1.1.0/bilibili&amp;quot;],
  meta = [&amp;quot;nick&amp;quot;, &amp;quot;mail&amp;quot;, &amp;quot;link&amp;quot;],
  requiredMeta = [],
  reaction = false,
  pageview = false,
} = Astro.props;
---
&amp;lt;div id=&amp;quot;waline-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://unpkg.com/@waline/client@v3/dist/waline.css&amp;quot; /&amp;gt;
&amp;lt;script type=&amp;quot;module&amp;quot; define:vars={{
  serverURL, lang, dark, emoji, meta, requiredMeta, reaction, pageview,
}}&amp;gt;
  import { init } from &amp;quot;https://unpkg.com/@waline/client@v3/dist/waline.js&amp;quot;;
  let walineInstance;
  async function mountWaline() {
    if (walineInstance) await walineInstance.destroy();
    walineInstance = init({
      el: &amp;quot;#waline-container&amp;quot;,
      serverURL, path: location.pathname, lang, dark, emoji, meta, requiredMeta, reaction, pageview,
    });
  }
  document.addEventListener(&amp;quot;astro:after-swap&amp;quot;, mountWaline);
  document.addEventListener(&amp;quot;DOMContentLoaded&amp;quot;, mountWaline);
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
  #waline-container { margin-top: 2rem; margin-bottom: 2rem; }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;常见问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;评论不显示&lt;/strong&gt;：请检查配置文件参数是否正确，Waline/Giscus 服务端是否可访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;切换无效&lt;/strong&gt;：确认已保存配置文件并重启开发服务。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Tue, 15 Apr 2025 00:00:00 GMT</pubDate></item><item><title>Using mdx in RyuChan</title><link>https://hub.xiaozhangya.xin/blog/ryuchan-mdx/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/ryuchan-mdx/</guid><description>Using MDX in RyuChan to enrich article content with more components</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/ryuchan-mdx/&quot;&gt;https://hub.xiaozhangya.xin/blog/ryuchan-mdx/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;
import Diff from &amp;quot;../../components/mdx/Diff.astro&amp;quot;;
import Error from &amp;quot;../../components/mdx/Error.astro&amp;quot;;
import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;
import Kbd from &amp;quot;../../components/mdx/Kbd.astro&amp;quot;;
import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;;
import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;
import TimeLine from &amp;quot;../../components/mdx/TimeLine.astro&amp;quot;;
import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;&lt;/p&gt;
&lt;h2&gt;Preface&lt;/h2&gt;
&lt;p&gt;This article describes how to use the components provided by RyuChan in &lt;code&gt;mdx&lt;/code&gt; to realize the functions that can&amp;#39;t be realized by normal &lt;code&gt;md&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Main text&lt;/h2&gt;
&lt;h3&gt;Getting started&lt;/h3&gt;
&lt;p&gt;First you need to create an &lt;code&gt;mdx&lt;/code&gt; file, which is as simple as changing the extension to &lt;code&gt;.mdx&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Introducing&lt;/h3&gt;
&lt;p&gt;The components provided by Ryuchan are placed in the &lt;code&gt;/mdx&lt;/code&gt; folders. Write something under the document properties (frontmatter):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;import Collapse from &amp;quot;../../components/mdx/Collapse.astro&amp;quot;;
import Diff from &amp;quot;../../components/mdx/Diff.astro&amp;quot;;
import Error from &amp;quot;../../components/mdx/Error.astro&amp;quot;;
import Info from &amp;quot;../../components/mdx/Info.astro&amp;quot;;
import Kbd from &amp;quot;../../components/mdx/Kbd.astro&amp;quot;;
import Success from &amp;quot;../../components/mdx/Success.astro&amp;quot;;
import Warning from &amp;quot;../../components/mdx/Warning.astro&amp;quot;;
import TimeLine from &amp;quot;../../components/mdx/TimeLine.astro&amp;quot;;
import LinkCard from &amp;quot;../../components/mdx/LinkCard.astro&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;h4&gt;Collapse&lt;/h4&gt;
&lt;Collapse title=&quot;This is an example text.&quot;&gt;
  This is the hidden content!
&lt;/Collapse&gt;

&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Collapse title=&amp;quot;This is an example text.&amp;quot;&amp;gt;
  This is the hidden content!
&amp;lt;/Collapse&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Diff&lt;/h4&gt;
&lt;Diff l=&quot;https://hub.xiaozhangya.xin/image/l.png&quot; r=&quot;https://hub.xiaozhangya.xin/image/r.png&quot; /&gt;

&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Diff l=&amp;quot;/image/l.png&amp;quot; r=&amp;quot;/image/r.png&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Error&lt;/h4&gt;
&lt;p&gt;&lt;Error&gt;Maybe something went wrong?&lt;/Error&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Error&amp;gt;Maybe something went wrong? &amp;lt;/Error&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Warning&lt;/h4&gt;
&lt;p&gt;&lt;Warning&gt;Hey! Watch out for potholes! &lt;/Warning&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Warning&amp;gt;Hey! Watch out for potholes! &amp;lt;/Warning&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Message&lt;/h4&gt;
&lt;p&gt;&lt;Info&gt;It&amp;#39;s just a message. &lt;/Info&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Info&amp;gt;It&amp;#39;s just a message. &amp;lt;/Info&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Success&lt;/h4&gt;
&lt;p&gt;&lt;Success&gt;Congratulations on your successful deployment! &lt;/Success&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Success&amp;gt;Congratulations on your successful deployment! &amp;lt;/Success&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Kbd&lt;/h4&gt;
&lt;p&gt;&lt;Kbd&gt;Ctrl&lt;/Kbd&gt; + &lt;Kbd&gt;C&lt;/Kbd&gt; to copy the text.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;Kbd&amp;gt;Ctrl&amp;lt;/Kbd&amp;gt; + &amp;lt;Kbd&amp;gt;C&amp;lt;/Kbd&amp;gt; to copy the text.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;TimeLine&lt;/h4&gt;
&lt;p&gt;&amp;lt;TimeLine
  items={[
    { year: &amp;quot;1984&amp;quot;, event: &amp;quot;First Macintosh computer&amp;quot; },
    { year: &amp;quot;1998&amp;quot;, event: &amp;quot;iMac&amp;quot; },
    { year: &amp;quot;2001&amp;quot;, event: &amp;quot;iPod&amp;quot; },
    { year: &amp;quot;2007&amp;quot;, event: &amp;quot;iPhone&amp;quot; },
    { year: &amp;quot;2015&amp;quot;, event: &amp;quot;Apple Watch&amp;quot; },
  ]}
/&amp;gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;TimeLine
  items={[
    { year: &amp;quot;1984&amp;quot;, event: &amp;quot;First Macintosh computer&amp;quot; },
    { year: &amp;quot;1998&amp;quot;, event: &amp;quot;iMac&amp;quot; },
    { year: &amp;quot;2001&amp;quot;, event: &amp;quot;iPod&amp;quot; },
    { year: &amp;quot;2007&amp;quot;, event: &amp;quot;iPhone&amp;quot; },
    { year: &amp;quot;2015&amp;quot;, event: &amp;quot;Apple Watch&amp;quot; },
  ]}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;LinkCard&lt;/h4&gt;
&lt;p&gt;&lt;LinkCard
  title=&quot;RyuChan&quot;
  desc=&quot;My blog project!&quot;
  url=&quot;https://github.com/xz131714/RyuChan&quot;
  img=&quot;https://img.xiaozhangya.xin/file/Avatar/NOr1G3Zs.jpeg&quot;
/&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;&amp;lt;LinkCard
  title=&amp;quot;RyuChan&amp;quot;
  desc=&amp;quot;My blog project!&amp;quot;
  url=&amp;quot;https://github.com/xz131714/RyuChan&amp;quot;
  img=&amp;quot;https://img.xiaozhangya.xin/file/Avatar/NOr1G3Zs.jpeg&amp;quot;
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Fri, 12 Jul 2024 00:00:00 GMT</pubDate></item><item><title>Markdown Style Guide</title><link>https://hub.xiaozhangya.xin/blog/markdown-style-guide/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/markdown-style-guide/</guid><description>Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/markdown-style-guide/&quot;&gt;https://hub.xiaozhangya.xin/blog/markdown-style-guide/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.&lt;/p&gt;
&lt;h2&gt;Headings&lt;/h2&gt;
&lt;p&gt;The following HTML &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;—&lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; elements represent six levels of section headings. &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; is the highest section level while &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; is the lowest.&lt;/p&gt;
&lt;h1&gt;H1&lt;/h1&gt;
&lt;h2&gt;H2&lt;/h2&gt;
&lt;h3&gt;H3&lt;/h3&gt;
&lt;h4&gt;H4&lt;/h4&gt;
&lt;h5&gt;H5&lt;/h5&gt;
&lt;h6&gt;H6&lt;/h6&gt;
&lt;h2&gt;Paragraph&lt;/h2&gt;
&lt;p&gt;Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.&lt;/p&gt;
&lt;p&gt;Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.&lt;/p&gt;
&lt;h2&gt;Images&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;![Alt text](./full/or/relative/path/of/image)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://hub.xiaozhangya.xin/logo.png&quot; alt=&quot;blog placeholder&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Blockquotes&lt;/h2&gt;
&lt;p&gt;The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a &lt;code&gt;footer&lt;/code&gt; or &lt;code&gt;cite&lt;/code&gt; element, and optionally with in-line changes such as annotations and abbreviations.&lt;/p&gt;
&lt;h3&gt;Blockquote without attribution&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;gt; Tiam, ad mint andaepu dandae nostion secatur sequo quae.
&amp;gt; **Note** that you can use _Markdown syntax_ within a blockquote.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Tiam, ad mint andaepu dandae nostion secatur sequo quae.
&lt;strong&gt;Note&lt;/strong&gt; that you can use &lt;em&gt;Markdown syntax&lt;/em&gt; within a blockquote.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Blockquote with attribution&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;gt; Don&amp;#39;t communicate by sharing memory, share memory by communicating.&amp;lt;br&amp;gt;
&amp;gt; — &amp;lt;cite&amp;gt;Rob Pike[^1]&amp;lt;/cite&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&amp;#39;t communicate by sharing memory, share memory by communicating.&lt;br&gt;
— &lt;cite&gt;Rob Pike[^1]&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;[^1]: The above quote is excerpted from Rob Pike&amp;#39;s &lt;a href=&quot;https://www.youtube.com/watch?v=PAAkCSZUG1c&quot;&gt;talk&lt;/a&gt; during Gopherfest, November 18, 2015.&lt;/p&gt;
&lt;h2&gt;Tables&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;| Italics   | Bold     | Code   |
| --------- | -------- | ------ |
| _italics_ | **bold** | `code` |
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Italics&lt;/th&gt;
&lt;th&gt;Bold&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;em&gt;italics&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;bold&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Code Blocks&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;p&gt;we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntac, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;```cpp
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int N = 1e5 + 5;
int n, k, a[N];
long long ans;
vector&amp;lt;int&amp;gt; v[N];
int main()
{
    scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k);
    for (int i = 1; i &amp;lt;= n; i++)
    {
        scanf(&amp;quot;%d&amp;quot;, &amp;amp;a[i]);
        v[i % k].push_back(a[i]);
    }
    for (int i = 0; i &amp;lt; k; i++)
        sort(v[i].rbegin(), v[i].rend());
    for (int i = 0; i &amp;lt; k; i++)
    {
        for (int j = 0; j + 1 &amp;lt; v[i].size(); j += 2)
        {
            ans += v[i][j] + v[i][j + 1];
        }
    }
    printf(&amp;quot;%lld\n&amp;quot;, ans);
    return 0;
}
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int N = 1e5 + 5;
int n, k, a[N];
long long ans;
vector&amp;lt;int&amp;gt; v[N];
int main()
{
    scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k);
    for (int i = 1; i &amp;lt;= n; i++)
    {
        scanf(&amp;quot;%d&amp;quot;, &amp;amp;a[i]);
        v[i % k].push_back(a[i]);
    }
    for (int i = 0; i &amp;lt; k; i++)
        sort(v[i].rbegin(), v[i].rend());
    for (int i = 0; i &amp;lt; k; i++)
    {
        for (int j = 0; j + 1 &amp;lt; v[i].size(); j += 2)
        {
            ans += v[i][j] + v[i][j + 1];
        }
    }
    printf(&amp;quot;%lld\n&amp;quot;, ans);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;List Types&lt;/h2&gt;
&lt;h3&gt;Ordered List&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;1. First item
2. Second item
3. Third item
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;First item&lt;/li&gt;
&lt;li&gt;Second item&lt;/li&gt;
&lt;li&gt;Third item&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Unordered List&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- List item
- Another item
- And another item
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;List item&lt;/li&gt;
&lt;li&gt;Another item&lt;/li&gt;
&lt;li&gt;And another item&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Nested list&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- Fruit
  - Apple
  - Orange
  - Banana
- Dairy
  - Milk
  - Cheese
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Fruit&lt;ul&gt;
&lt;li&gt;Apple&lt;/li&gt;
&lt;li&gt;Orange&lt;/li&gt;
&lt;li&gt;Banana&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dairy&lt;ul&gt;
&lt;li&gt;Milk&lt;/li&gt;
&lt;li&gt;Cheese&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other Elements&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;lt;abbr title=&amp;quot;Graphics Interchange Format&amp;quot;&amp;gt;GIF&amp;lt;/abbr&amp;gt; is a bitmap image format.

H&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;O

X&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; + Y&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; = Z&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;

Press &amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;ALT&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;Delete&amp;lt;/kbd&amp;gt; to end the session.

Most &amp;lt;mark&amp;gt;salamanders&amp;lt;/mark&amp;gt; are nocturnal, and hunt for insects, worms, and other small creatures.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;p&gt;&lt;abbr title=&quot;Graphics Interchange Format&quot;&gt;GIF&lt;/abbr&gt; is a bitmap image format.&lt;/p&gt;
&lt;p&gt;H&lt;sub&gt;2&lt;/sub&gt;O&lt;/p&gt;
&lt;p&gt;X&lt;sup&gt;n&lt;/sup&gt; + Y&lt;sup&gt;n&lt;/sup&gt; = Z&lt;sup&gt;n&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Press &lt;kbd&gt;CTRL&lt;/kbd&gt;+&lt;kbd&gt;ALT&lt;/kbd&gt;+&lt;kbd&gt;Delete&lt;/kbd&gt; to end the session.&lt;/p&gt;
&lt;p&gt;Most &lt;mark&gt;salamanders&lt;/mark&gt; are nocturnal, and hunt for insects, worms, and other small creatures.&lt;/p&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Mon, 01 Jul 2024 00:00:00 GMT</pubDate></item><item><title>Using MDX</title><link>https://hub.xiaozhangya.xin/blog/using-mdx/</link><guid isPermaLink="true">https://hub.xiaozhangya.xin/blog/using-mdx/</guid><description>Lorem ipsum dolor sit amet</description><content:encoded>&lt;blockquote&gt;This rendering was automatically generated by Ryuchan Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://hub.xiaozhangya.xin/blog/using-mdx/&quot;&gt;https://hub.xiaozhangya.xin/blog/using-mdx/&lt;/a&gt;&lt;/blockquote&gt; &lt;p&gt;This theme comes with the &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/mdx/&quot;&gt;@astrojs/mdx&lt;/a&gt; integration installed and configured in your &lt;code&gt;astro.config.mjs&lt;/code&gt; config file. If you prefer not to use MDX, you can disable support by removing the integration from your config file.&lt;/p&gt;
&lt;h2&gt;Why MDX?&lt;/h2&gt;
&lt;p&gt;MDX is a special flavor of Markdown that supports embedded JavaScript &amp;amp; JSX syntax. This unlocks the ability to &lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#mdx-features&quot;&gt;mix JavaScript and UI Components into your Markdown content&lt;/a&gt; for things like interactive charts or alerts.&lt;/p&gt;
&lt;p&gt;If you have existing content authored in MDX, this integration will hopefully make migrating to Astro a breeze.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Here is how you import and use a UI component inside of MDX.&lt;br&gt;When you open this page in the browser, you should see the clickable button below.&lt;/p&gt;
&lt;h2&gt;More Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mdxjs.com/docs/what-is-mdx&quot;&gt;MDX Syntax Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages&quot;&gt;Astro Usage Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;a href=&quot;https://docs.astro.build/en/reference/directives-reference/#client-directives&quot;&gt;Client Directives&lt;/a&gt; are still required to create interactive components. Otherwise, all components in your MDX will render as static HTML (no JavaScript) by default.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>RyuChan</dc:creator><pubDate>Sat, 02 Jul 2022 00:00:00 GMT</pubDate></item></channel></rss>