<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>shiquda 的试验田</title>
    <link>https://shiquda.link/</link>
    <description>Read with Wonder, Think with Nonsense, Create with Fun.</description>
    <language>zh-CN</language>
    <copyright>All rights reserved 2026, shiquda</copyright>
    <lastBuildDate>Mon, 17 Aug 2026 02:00:00 GMT</lastBuildDate>
    <generator>Hexo</generator>
    <atom:link href="https://shiquda.link/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>让 Agent 调用网页版 5.6 Sol</title>
      <link>https://shiquda.link/agent-call-chatgpt-web-5.6-sol/</link>
      <description>用 Oracle CLI 让 Agent 直接调用 ChatGPT 网页版 5.6 Sol，省额度免 API Key，无需人工搬运。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/Agent/">Agent</category>
      <pubDate>Mon, 17 Aug 2026 02:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_00-oracle-comparison-14622ff7.png" alt="Agent 与 ChatGPT 网页端之间的自动化循环，无需人工执行" loading="lazy"></p><p><strong>分享一套让所有 Agent 免费「调用」5.6 Sol 的省额度方法</strong>，适合拥有自己的付费 ChatGPT 账户的朋友。</p><p>我们知道 ChatGPT 网页端进行对话时，是不消耗 Codex 的额度的。我们经常在网页上让 ChatGPT 去帮我们做网络检索、深度思考等工作，然后可能把它给出的方案再转发给 Agent。<strong>其实这么一套机械的操作是完全可以自动化的</strong>。</p><p>如果使用同一个 ChatGPT 网页端账号和 Codex 账号，那你可以直接在 Codex 里面 <code>@ 聊天</code> 来实现上下文的快速转移。但很可惜，我自己使用的 Codex 并不是网页端的账号，网页端只是一个 Team 账号。我在想，在这样的情况下，有没有什么办法可以快速地实现上面的要求呢？</p><p>于是，我找到了 <a href="https://github.com/steipete/oracle">Oracle</a> 这个项目。</p><blockquote><p>在古希腊罗马，oracle 指传达神谕的场所或人物。人类无法掌握的信息，通过它获得答案。</p></blockquote><p>它可以用浏览器自动化的方式，帮我们在网页端问 ChatGPT，然后返回结构化的回复。支持把本地的代码、截图等文件作为「附件」上传，选择模型和思考程度（没错，如果你比较壕，也可以直接选择问 5.6 Pro）。</p><p>安装这个项目的 CLI，然后再搭配 Skill，我们就可以教会<strong>任何</strong>Agent 如何把 5.6 Sol 这个高级模型作为一个工具来进行调用，还能让它获得你的上下文和联网等各类外部信息。</p><h2 id="配置方式"><a href="#配置方式" class="headerlink" title="配置方式"></a>配置方式</h2><blockquote><p>注：此类自动化操作可能导致潜在的账号封禁。如果您特别担心这类风险，不建议这样操作。</p></blockquote><p>如果你使用 MacOS，可以用下面的命令一键安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install steipete/tap/oracle</span><br></pre></td></tr></tbody></table></figure><p>也可通过 NPM 安装（通用）：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g @steipete/oracle</span><br></pre></td></tr></tbody></table></figure><p>让你的 Agent 阅读 <a href="https://github.com/steipete/oracle">https://github.com/steipete/oracle</a> 安装配套的 Skill。</p><p>接下来你可以根据自己的偏好，在官方的 Skill 基础上做一些修改。下面是我使用的方式：</p><p>首先需要一个 Chrome 浏览器，并在上面登录你的 ChatGPT 账号。</p><h3 id="两种对话保存方式"><a href="#两种对话保存方式" class="headerlink" title="两种对话保存方式"></a>两种对话保存方式</h3><p>由于是在网页端模拟进行对话，因此我推荐下面两种对话的保存方式。一种是使用 <code>Temporary Chat</code> 模式，这样的话每次都会开一个临时的对话，优点是完全不干扰你的使用，阅后即焚，缺点是无法找回对话，也无法接着对话继续说。</p><p>另外一种是专门创建一个 Project 给 Agent 使用，也是我推荐的方式。在你的 ChatGPT 中创建一个独立的 Project 专门给它使用，把这个 Project 的链接（类似 <a href="https://chatgpt.com/g/id/project">https://chatgpt.com/g/id/project</a>）告诉你的 Agent。这样既把 Agent 发起的提问集中起来，同时需要的时候也可以自己点开查看。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/oracle-chat-project-e37d1e6e.png" alt="为 Agent 专用的 ChatGPT Project（Oracle Chat）" loading="lazy"></p><h3 id="配置-config-json"><a href="#配置-config-json" class="headerlink" title="配置 config.json"></a>配置 config.json</h3><p>接下来让 Agent 配置 <code>~/.oracle/config.json</code>。下面是我的配置去掉了个人信息后的通用版，可以直接参考：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"engine"</span><span class="punctuation">:</span> <span class="string">"browser"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"model"</span><span class="punctuation">:</span> <span class="string">"gpt-5.6-sol"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">"browser"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"chromePath"</span><span class="punctuation">:</span> <span class="string">"/path/to/oracle-chrome"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"chatgptUrl"</span><span class="punctuation">:</span> <span class="string">"https://chatgpt.com/g/&lt;你的ProjectID&gt;/project"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"thinkingTime"</span><span class="punctuation">:</span> <span class="string">"extra-high"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"archiveConversations"</span><span class="punctuation">:</span> <span class="string">"never"</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"hideWindow"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">  <span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>几个可选项的说明：</p><ul><li><code>chatgptUrl</code>：如果是 <code>Temporary Chat</code> 模式，改成 <code>https://chatgpt.com/?temporary-chat=true</code>。</li><li><code>chromePath</code>：指向 <code>wrapper</code>，注入 <code>--proxy-server=</code>，适合需要通过代理访问的朋友。</li><li><code>hideWindow: true</code>：Oracle 启动 Chrome 后窗口自动隐藏，不干扰你的工作。</li><li><code>archiveConversations: "never"</code>：不归档对话，避免 Project 里堆积无关会话。</li></ul><h3 id="国内用户没有全局代理怎么办？"><a href="#国内用户没有全局代理怎么办？" class="headerlink" title="国内用户没有全局代理怎么办？"></a>国内用户没有全局代理怎么办？</h3><p>如果你的网络访问不了 ChatGPT（比如国内用户没有开全局代理），也不用放弃这套方案。思路是写一个 Chrome <code>wrapper</code> 脚本，让 Oracle 启动 Chrome 时自动注入本地代理。</p><p>我的 <code>~/.oracle/oracle-chrome</code> 脚本大概做这几件事：先把 Oracle 传来的 <code>--proxy-server</code> 参数过滤掉（避免和我们要注入的重复），再在启动参数里自动加上 <code>--proxy-server=http://127.0.0.1:7890</code>，最后用 <code>exec</code> 拉起真正的 Chrome。</p><p>然后在 <code>config.json</code> 里把 <code>chromePath</code> 指向这个脚本，而不是 Chrome 本体：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">  <span class="attr">"browser"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"chromePath"</span><span class="punctuation">:</span> <span class="string">"/Users/你的用户名/.oracle/oracle-chrome"</span></span><br><span class="line">  <span class="punctuation">}</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>这样 Oracle 每次拉起 Chrome 都会自动带上本地代理，ChatGPT 网页端就能正常访问了，无需手动开启全局代理。</p><p>接着让 Agent 在 Skill 里补充超时，我这边设置的是 20 分钟，对绝大多数任务应该够了。</p><p>最后可以让 Agent 实测一下是否 <code>Work</code>。可以的话就完美地接入你的工作流啦~</p><h3 id="实测效果"><a href="#实测效果" class="headerlink" title="实测效果"></a>实测效果</h3><p>下面是我的一个例子，我在 Oh My Pi 中使用 Deepseek V4 Flash 这样的廉价模型，实测可以让它求助外部的 GPT 5.6 Sol 大人，用时 5 分钟左右。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/oracle-deepseek-example-9e82d74f.png" alt="Oh My Pi 中 Deepseek V4 Flash 驱动外部 GPT 5.6 Sol 的实测" loading="lazy"></p><p>至此，我们实际上实现了<strong>外部高性能模型指导、廉价模型驱动的工作流闭环</strong>。搭建好 Skill 和 CLI 之后，完全不需要人类再当内容的搬运工。在 Agent 的时代，我们就是要用这样的思路来尽可能把人类的注意力资源从这类繁琐、重复的搬运工作中解放出来，转而投向其他更有价值的事情。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>SpotAsk：不是所有的问题，都需要打开 ChatGPT</title>
      <link>https://shiquda.link/spotask-not-every-question-needs-chatgpt/</link>
      <description>SpotAsk 是一个原生 macOS 菜单栏 AI 助手，专注轻量提问、划词处理和快速回到原任务。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/AI/">AI</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/macOS/">macOS</category>
      <category domain="https://shiquda.link/tags/%E5%B7%A5%E5%85%B7/">工具</category>
      <pubDate>Tue, 11 Aug 2026 04:04:10 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="SpotAsk：不是所有的问题，都需要打开-ChatGPT"><a href="#SpotAsk：不是所有的问题，都需要打开-ChatGPT" class="headerlink" title="SpotAsk：不是所有的问题，都需要打开 ChatGPT"></a>SpotAsk：不是所有的问题，都需要打开 ChatGPT</h1><h2 id="我为什么想做-SpotAsk"><a href="#我为什么想做-SpotAsk" class="headerlink" title="我为什么想做 SpotAsk"></a>我为什么想做 SpotAsk</h2><p>最近我开始在 macOS 上生活，顺手做了自己的第一款 macOS 桌面应用：SpotAsk。</p><p>起因很普通。我打开 ChatGPT，很多时候并不是要处理什么复杂任务。更多时候，只是想弄明白一个概念、翻译一段话、总结一篇长文，或者润色一下刚写好的回复。</p><p>但这么点小事，真正做完却要走过一整套流程：停下手里的事、打开浏览器、进入 AI 网站、等回答、再切回来。</p><p>一次两次无所谓。次数多了，我越来越觉得别扭——一个几秒钟就能问完的问题，硬是被工具流程拖得很重。</p><p><strong>不是所有的问题，都需要打开 ChatGPT。</strong></p><h2 id="核心理念：让轻量提问真的轻"><a href="#核心理念：让轻量提问真的轻" class="headerlink" title="核心理念：让轻量提问真的轻"></a>核心理念：让轻量提问真的轻</h2><p>SpotAsk 是一个原生 macOS 菜单栏应用，平时就当它不存在。按默认快捷键 <code>Option + Space</code>，呼出一个专注的提问窗口。输入问题、看回答、需要时复制，再按 <code>Esc</code> 关掉。整个过程不离开手头的工作，关掉之后，就像它没出现过一样。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/SpotAsk@main/docs/site/public/images/spotask-chat.png" alt="SpotAsk 快捷提问主界面" loading="lazy"></p><p>我想要的不是一个更大的 AI 工作台，而是一条更短的路：从「我有问题」到「我拿到答案、回到原任务」，中间别被打断。</p><p>这个理念也决定了另外几个设计选择：</p><ol><li><strong>键盘优先</strong>：打开、提问、复制、关闭都可以靠快捷键完成，不必碰光标。</li><li><strong>界面克制</strong>：窗口只承担快速问答，不堆砌历史、工作区、协作这类重量级功能。</li><li><strong>本地优先</strong>：SpotAsk 用自带密钥（BYOK）模式。访问密钥存在这台 Mac 上，内容只发送给你配置的 AI 服务。</li><li><strong>保留边界</strong>：复杂任务仍然交给 ChatGPT、Codex 这类专门工具。SpotAsk 只处理那些高频、轻量、能快速结束的时刻。</li></ol><h2 id="两个主要使用场景"><a href="#两个主要使用场景" class="headerlink" title="两个主要使用场景"></a>两个主要使用场景</h2><p>SpotAsk 目前围绕两个日常场景来做。</p><p>一个是<strong>快捷提问</strong>。按 <code>Option + Space</code> 打开窗口，输入问题后按 Return，回答实时显示。可以复制完整回答，也可以只复制某个代码块；想中途停掉，按 <code>Esc</code> 或点停止按钮就行。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/SpotAsk@main/docs/site/public/images/spotask-hotkey.gif" alt="SpotAsk 快捷键呼出并提问" loading="lazy"></p><p>另一个是<strong>划词处理</strong>。在 Safari、备忘录、邮件或其他 macOS 应用里选中一段文字，SpotAsk 会在选区旁边给出快捷操作。比如翻译、解释、总结、润色，或者跑一段自定义提示词。回答生成后，在支持写入的应用里可以直接把结果写回原选区；也可以复制到剪贴板，或者接着在对话窗口里追问。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/SpotAsk@main/docs/site/public/images/spotask-selection.gif" alt="SpotAsk 划词快捷操作" loading="lazy"></p><p>另外还有一些让它在系统里更顺手的细节：自定义全局快捷键、内置多种提示词、粘贴截图或拖入文件作为上下文。它支持 8 种界面语言，也能通过 Spotlight、Siri 和快捷指令调用。</p><p>加这些不是为了让 SpotAsk 更像一个平台，只是想让常见动作再快一点。</p><h2 id="设计边界：刻意不做成另一个-AI-工作台"><a href="#设计边界：刻意不做成另一个-AI-工作台" class="headerlink" title="设计边界：刻意不做成另一个 AI 工作台"></a>设计边界：刻意不做成另一个 AI 工作台</h2><p>做工具最难的，往往不是「加什么」，而是「忍住不加什么」。</p><p>SpotAsk 没打算做成面面俱到的 AI 工作台。它没有账号体系，不做云端同步，也不准备把完整工作区、多轮复杂推理和长上下文协作都塞进来。需要多步推理、反复调试、深度检索的活，我还是建议用专门的 AI 产品。</p><p>它的定位就这么窄：负责那些「小事却要打开大工具」的时刻。</p><h2 id="为什么叫-SpotAsk"><a href="#为什么叫-SpotAsk" class="headerlink" title="为什么叫 SpotAsk"></a>为什么叫 SpotAsk</h2><p>我用 macOS 的时间还不长。之前在 Windows 上，我很喜欢 Listary 这类工具——不用离开键盘，就能完成很多操作。换到 macOS 后，我自然先被 Spotlight 吸引，慢慢习惯了这种「按几个键就能办完一件事」的交互。</p><p>后来我试过用 Cherry Studio 来应付轻量问答，但它对我来说还是太重。我不想为了一个简单的功能，在系统里装一个庞然大物，也不想每次提问都被工作台里的其他概念打断。</p><p>SpotAsk 就是这么来的：做一个原生的、更轻的、更纯粹的 macOS 快捷问答工具。名字也取这个意思——像 Spotlight 那样快速找到想要的东西，又像 Ask 一样，让问题本身就是入口。</p><h2 id="第一次做-macOS-桌面端工具"><a href="#第一次做-macOS-桌面端工具" class="headerlink" title="第一次做 macOS 桌面端工具"></a>第一次做 macOS 桌面端工具</h2><p>这是我第一次完整做一款 macOS 桌面应用。整个过程里，最大的体会不是技术有多难，而是产品边界比技术细节更难定。</p><p>早期我很容易被各种功能吸引，总觉得「别人有，我们也可以有」。可每加进来一个功能，主路径就长一点。后来我把标准压成了一句话：<strong>如果它不能让「问一个问题」这件事更短，就暂时不做。</strong></p><p>所以 SpotAsk 现在是个功能朴素、但路径清楚的小工具。它从我自己的真实需求里长出来，也还有很多不成熟的地方。作为第一次做 macOS 桌面端的人，欢迎大家体验，也欢迎告诉我哪里好用、哪里别扭，以及你最希望它处理什么场景。</p><h2 id="当前状态"><a href="#当前状态" class="headerlink" title="当前状态"></a>当前状态</h2><p>SpotAsk 支持 macOS 15 或更高版本，兼容 Apple silicon 和 Intel Mac。官方发布版本使用 Apple Developer ID 签名并通过公证（<del>不得不说苹果的开发者订阅好贵</del>）。项目在 GitHub 上开源，使用 AGPL-3.0 许可证。</p><p>中文文档：<a href="https://shiquda.github.io/SpotAsk/zh-CN/">https://shiquda.github.io/SpotAsk/zh-CN/</a></p><p>下载地址：<a href="https://github.com/shiquda/SpotAsk/releases">https://github.com/shiquda/SpotAsk/releases</a></p><p>项目主页：<a href="https://github.com/shiquda/SpotAsk">https://github.com/shiquda/SpotAsk</a></p><p>如果你也经常遇到这种「小事却要打开大工具」的时刻，欢迎试试。任何使用感受、遇到的问题或改进建议，欢迎在 Github 的 Issue 中提出。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>从提示词到个人资产，我如何用 Git 跨设备管理私有 Skill</title>
      <link>https://shiquda.link/private-skill-git-cross-device/</link>
      <description>这篇文章分享一套用 Git 管理个人和小团队私有 Skill 的轻量方案：上行用 skills-sync，下行用 npx skills add，让 Skill 成为可迁移、可复用的个人资产。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/AI/">AI</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/Agent/">Agent</category>
      <category domain="https://shiquda.link/tags/Skill/">Skill</category>
      <category domain="https://shiquda.link/tags/Git/">Git</category>
      <pubDate>Sun, 31 May 2026 05:54:31 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="从提示词到个人资产，我如何用-Git-跨设备管理私有-Skill"><a href="#从提示词到个人资产，我如何用-Git-跨设备管理私有-Skill" class="headerlink" title="从提示词到个人资产，我如何用 Git 跨设备管理私有 Skill"></a>从提示词到个人资产，我如何用 Git 跨设备管理私有 Skill</h1><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_01-hero-private-skill-asset-1fc986c1.png" alt="私有 Skill 资产流转" loading="lazy"></p><p>最近我在折腾一件小事：把自己散落在不同 Agent 里的 Skill 管起来。一开始我也觉得这事没那么重要，无非就是几个 <code>SKILL.md</code>，里面写一些说明、流程和工具调用方式。可用得多了以后，我越来越觉得，Skill 不应该只被当成「提示词文件」看，它更像是一种个人资产，尤其是私有 Skill。</p><p>公开 Skill 当然有价值。比如处理 PDF、读写表格、调用浏览器、做部署检查，这些都是很多人都会遇到的问题。社区把这些能力做成 Skill，大家拿来即用，这是生态的价值。</p><p>但我自己的判断是：<strong>真正更值得长期维护的，往往是私有 Skill</strong>。</p><p>原因也很简单。公开 Skill 解决的是「大家都会遇到的问题」，私有 Skill 解决的是「我反复遇到的问题」。前者是通用能力，后者是我的工作方式、判断标准和认知习惯。</p><p>换句话说，公开 Skill 更像工具箱里的通用工具，私有 Skill 更像我自己的工作流说明书。</p><p>这篇文章想分享的，就是我现在用的一套轻量方案：不用部署服务器，只用 Git 加本地 CLI。上行用我自己写的 <a href="https://github.com/shiquda/skills-sync"><code>skills-sync</code></a>，把本地 Skill 同步到 Git 仓库。下行用成熟的 <code>npx skills add</code>，从 Git 仓库安装 Skill。中间用 Git 做版本管理和权限控制。这样一来，Skill 就可以跨设备、跨 Agent、跨项目流转。</p><p>不过先说清楚，这篇文章不是安装教程，我也不打算把具体命令展开得很细。进入 Agent 时代以后，我越来越倾向于把这类细节交给 Agent 自己研究。把仓库 URL 发给它，让它先读 README。必要时先安装仓库里的 Skill，再根据 Skill 的指导完成后续操作。人的注意力应该留给判断和验收，而不是记一堆命令参数。</p><h2 id="什么是值得管理的私有-Skill？"><a href="#什么是值得管理的私有-Skill？" class="headerlink" title="什么是值得管理的私有 Skill？"></a>什么是值得管理的私有 Skill？</h2><p>我这里说的私有 Skill，不是指「不能公开的神秘能力」，而是指那些和个人、团队、项目强相关的能力模块。</p><p>它可以很小。比如：</p><ol><li>我做代码审查时关注哪些风险。</li><li>我写文章时如何组织结构和语气。</li><li>我发布博客前要跑哪些检查。</li><li>我让 Agent 做完任务后，必须给出哪些验证证据。</li></ol><p>它也可以更大。比如一套论文检索流程、一套团队项目交付规范、一套内容创作工作流，甚至是一套长期形成的研究方法。</p><p>这些东西有一个共同点：它们未必适合公开，也未必对所有人有用，但对我自己非常有用。因此，私有 Skill 本质上不是「写给模型的一段提示词」。它更像是把自己的经验和偏好，用一种 Agent 能理解、能调用的方式封装起来。</p><p>这也是我认为私有 Skill 比公开 Skill 更值得认真管理的原因。公开 Skill 用来补齐通用能力，私有 Skill 用来沉淀个人能力。前者让 Agent 更会做事，后者让 Agent 更像是在按照「我的方法」做事。</p><h2 id="Skill-是模型之外的知识增量"><a href="#Skill-是模型之外的知识增量" class="headerlink" title="Skill 是模型之外的知识增量"></a>Skill 是模型之外的知识增量</h2><p>现在底座模型变化很快，Agent 产品也变化很快。今天用 Claude Code，明天可能用 Codex，后天又换成 OpenClaw、Cursor 或 OpenCode。如果所有经验都只沉淀在某一个产品的对话里，其实很脆弱。产品一换、设备一换、上下文一清空，很多东西就没了。</p><p>Skill 的好处在于，它把一部分经验从具体模型和具体 Agent 里抽了出来。</p><p>一个好的 Skill 不需要写得很玄。它只要把适用场景、执行路径、可用工具和验收方式说清楚，Agent 就能在不同模型和产品之间复用这套流程。</p><p>从这个角度看，Skill 可以理解为一种「模型之外的知识增量」。底座模型提供通用智能，Skill 在这个智能之上，补充具体的领域知识、个人偏好和执行路径。</p><p>这一点很宝贵。</p><p>因为模型会越来越强，但模型不可能天然知道「我怎么做事」。它可以知道一般意义上的论文检索、代码审查、文章润色，但不知道我自己的判断标准。私有 Skill 正好补的是这一层。</p><h2 id="真正麻烦的不是写-Skill，而是管理-Skill"><a href="#真正麻烦的不是写-Skill，而是管理-Skill" class="headerlink" title="真正麻烦的不是写 Skill，而是管理 Skill"></a>真正麻烦的不是写 Skill，而是管理 Skill</h2><p>当 Skill 只有两三个的时候，管理问题不明显。放在某个目录里，用的时候能找到就行。但只要你稍微重度使用 Agent，很快就会遇到几个问题。</p><p>第一个问题是分散。不同 Agent 有不同的 Skill 目录，Codex 有自己的全局目录，Claude Code 有自己的目录。OpenClaw、OpenCode、Cursor 也各有各的习惯。还有一些 Skill 是项目级的，只放在某个仓库里。</p><p>第二个问题是迁移。</p><p>换电脑的时候，你可能知道要同步代码、同步配置、同步 SSH Key，但未必记得自己有哪些 Skill 散落在各处。等真正用到的时候，才发现新机器上没有。</p><p>第三个问题是迭代。</p><p>比如我在本机改了一个 Skill，过几天又在 VPS 上用它。结果 VPS 上还是旧版本。到底哪个版本是新的？上次改了什么？有没有改坏？这些问题如果靠手动复制，很快就会乱。</p><p>第四个问题是共享。</p><p>如果是小团队，大家可能都有一些共同工作流。比如项目发布、文档检查、代码审查、日报整理。这个时候最麻烦的不是写一份说明，而是如何让每个人的 Agent 都能稳定拿到同一份说明，并且之后还能更新。</p><p>这些问题放在一起，其实就是一句话：</p><blockquote><p>当 Skill 从几个零散文件，变成一套长期维护的能力库以后，它就应该像代码一样被版本管理。</p></blockquote><p>这也是我最后选择 Git 的原因。</p><h2 id="我的方案：Git-做仓库，CLI-做上下行"><a href="#我的方案：Git-做仓库，CLI-做上下行" class="headerlink" title="我的方案：Git 做仓库，CLI 做上下行"></a>我的方案：Git 做仓库，CLI 做上下行</h2><p>我的方案很简单：</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_02-flow-git-sync-bc54e064.png" alt="Git 上下行闭环" loading="lazy"></p><p>上行用 <code>skills-sync</code>，下行用 <code>npx skills add</code>，中间用 Git 做 Skill 仓库。</p><p>这里的关键不是技术有多复杂，恰恰相反，关键是不要把事情做重。Skill 本质上就是一组文件。Git 已经解决了版本历史、分支、回滚、权限、协作这些问题。GitHub、GitLab 这类平台也已经解决了私有仓库访问控制。对于个人和小团队来说，如果 Git 加本地 CLI 已经能解决问题，就没有必要一开始就部署一个服务器。</p><p>这套方案的分工也比较清楚。<code>skills-sync</code> 负责上行，扫描本地各个 Agent 的 Skill 目录。它把你选中的 Skill 放进目标 Git 仓库，并提交推送。<code>npx skills add</code> 负责下行，从 Git 仓库里读取 Skill，然后安装到本机对应的 Agent 环境里。对于私有仓库，我的做法是直接复用本地 Git 认证，比如 SSH Key。</p><p>这样一来，Skill 的生命周期就比较完整了：</p><ol><li>在本地某个 Agent 里产生。</li><li>通过 <code>skills-sync</code> 同步到 Git。</li><li>在 Git 里获得版本历史。</li><li>在其他设备上通过 <code>npx skills add</code> 安装。</li><li>后续继续迭代，再同步，再更新。</li></ol><h2 id="skills-sync-解决的是上行问题"><a href="#skills-sync-解决的是上行问题" class="headerlink" title="skills-sync 解决的是上行问题"></a><code>skills-sync</code> 解决的是上行问题</h2><p>我写 <code>skills-sync</code> 的初衷，是因为我发现已有工具更多解决的是「安装 Skill」。但我还需要一个反方向的工具：把我本地已经写好的 Skill 收集起来，推到自己的仓库里。</p><p>它现在做的事情大致包括：</p><ol><li>扫描主流 Agent 的全局 Skill 目录和项目级 Skill 目录。</li><li>展示当前发现了哪些 Skill。</li><li>对比目标仓库里的版本，判断是新增、相同、修改还是无效。</li><li>支持交互式选择，也支持非交互式同步。</li><li>把选中的 Skill 复制到 Git 仓库的规范目录。</li><li>写入同步 manifest，默认 commit 并 push。</li></ol><p>但我不建议读者在这里死记具体命令。更符合 Agent 时代的用法，是把 <code>skills-sync</code> 的仓库地址直接发给你正在使用的 Agent。然后让它自己读 README。</p><p>比如可以这样说：</p><blockquote><p>这是 <code>skills-sync</code> 的仓库：<code>https://github.com/shiquda/skills-sync</code>。</p><p>请你先阅读 README，理解它如何同步本地 Agent Skill 到 Git 仓库，并按照说明安装配套的 Skill，然后帮我检查当前环境，给出下一步同步方案。</p></blockquote><p>这比自己手动查参数更节省注意力。因为真正需要人判断的，不是某个参数怎么写，而是我要同步哪些 Skill、同步到哪个仓库、哪些内容不应该上传。</p><p>我自己的本地环境里，<code>skills-sync scan</code> 能扫到多个来源的 Skill，比如 Codex、Claude Code、general。目标仓库配置成我自己的 Skill 仓库。</p><p>这里有一个细节我觉得挺重要：<code>skills-sync</code> 不试图替代 Git。它只是把 Skill 放进 Git 仓库，然后让 Git 继续做它擅长的事情。历史、回滚、审查、冲突处理，这些都交给 Git。这比重新做一套 Skill 平台要轻很多。</p><h2 id="下行也可以交给-Agent"><a href="#下行也可以交给-Agent" class="headerlink" title="下行也可以交给 Agent"></a>下行也可以交给 Agent</h2><p>下行我没有重新造轮子，而是直接使用成熟的 <code>npx skills add</code>。它可以从一个 source 添加 Skill，也可以列出仓库里的 Skill。另外，它还可以指定安装某个 Skill、指定全局或项目级安装，以及指定目标 Agent。</p><p>但这部分同样不需要读者自己记命令。</p><p>更自然的方式是告诉 Agent：</p><blockquote><p>这是我的私有 Skill 仓库地址。</p><p>请你先确认当前机器的 Git 认证是否能访问它。</p><p>然后使用 <code>npx skills add</code> 查看里面有哪些 Skill，再把我指定的 Skill 安装到当前 Agent 可用的位置。执行前先说明你准备做什么。</p></blockquote><p>如果是团队私有仓库，只要本机 Git 认证配置好了，Agent 就可以通过 SSH URL 或其他 Git URL 访问。这样就不需要给 <code>skills-sync</code> 或安装流程额外设计一套账号系统。</p><p>这也是我喜欢这套方案的地方：它没有把问题复杂化。<code>skills-sync</code> 只管把本地资产上传到仓库，<code>npx skills add</code> 只管从仓库安装到本地。Git 负责中间的版本和权限，Agent 负责阅读说明、选择命令和执行流程。每一层都比较克制。</p><h2 id="一个真实例子：找论文-Skill-从本机流转到-VPS"><a href="#一个真实例子：找论文-Skill-从本机流转到-VPS" class="headerlink" title="一个真实例子：找论文 Skill 从本机流转到 VPS"></a>一个真实例子：找论文 Skill 从本机流转到 VPS</h2><p>举一个我自己的例子：我有一个找论文的 Skill，最早是在本机 Claude Code 里用的。它不是简单告诉 Agent「帮我找几篇论文」，而是沉淀了我的检索习惯。比如优先看哪些来源、怎么判断相关性、怎么过滤质量不够的材料、最后按什么结构整理结果。</p><p>后来我希望 VPS 上的 OpenClaw 也能用这个 Skill。传统做法是手动找目录、复制文件、传到 VPS、再确认 OpenClaw 的 Skill 目录。能做，但很烦，而且后续更新还要再来一遍。现在就简单很多。我让本机 Claude Code 根据 <code>skills-sync</code> 的说明，把这个 Skill 上传到 Git 仓库。到了 VPS，再把仓库 URL 给 OpenClaw，让它读 README，并用 <code>npx skills add</code> 安装。</p><p>整个过程里，我不需要手动复制文件，也不需要自己查命令参数。我的动作更像是给 Agent 下达意图，然后让 Agent 根据 Skill 的指导自己完成同步。这件事让我更确定一件事：私有 Skill 的价值，不只是插件迁移，而是把自己的研究方法迁移到不同设备和 Agent 里。</p><h2 id="这套方案适合谁？"><a href="#这套方案适合谁？" class="headerlink" title="这套方案适合谁？"></a>这套方案适合谁？</h2><p>这套方案并不适合所有人。如果你只偶尔用 Agent，也没有写自己的 Skill，那暂时不需要管这些，直接用公开 Skill 就够了。</p><p>它更适合下面几类人：</p><ol><li>同时使用多个 Agent。</li><li>有多台设备，比如本机、笔记本、VPS。</li><li>已经开始写自己的 Skill。</li><li>想把工作流沉淀下来，但不想维护服务器。</li><li>小团队希望共享一套 Agent 工作方式。</li></ol><p>反过来，如果你需要很复杂的后台权限、审计、审批流程，或者希望所有东西都通过 GUI 管理，那这套方案可能太轻了。</p><p>它的定位很明确：给个人和小团队一个低成本的 Skill 资产管理方式。它不是一个完整平台，更像是一条打通的链路。</p><h2 id="Skill-管理的本质，是个人能力的版本管理"><a href="#Skill-管理的本质，是个人能力的版本管理" class="headerlink" title="Skill 管理的本质，是个人能力的版本管理"></a>Skill 管理的本质，是个人能力的版本管理</h2><p>回到最开始的问题：为什么要认真管理私有 Skill？我的理解是，Agent 时代有一类新资产正在出现：可执行的认知资产。</p><p>过去我们管理代码，因为代码是可执行资产。后来我们管理文档，因为文档是知识资产。现在，Skill 介于两者之间。它既有知识，也能指导 Agent 调用工具执行任务。这就让 Skill 变得很特殊。</p><p>一个好的私有 Skill，里面可能有你的写作风格、研究路径、工程习惯、审查标准、团队约定。它不是模型参数的一部分，但它能实实在在影响 Agent 的行为。换句话说，它是在底座模型之上，给你自己加了一层知识增量。</p><p>这层增量越稳定、越可复用，就越应该被版本管理。否则它只会散落在某次对话、某个目录、某台机器里，很难长期积累。</p><p>我现在越来越觉得，未来很多人的核心资产，可能不只是代码、文章、笔记，还包括一套不断迭代的私有 Skill。它们小到一个命令，大到一套方法论。它们以可插拔模块的方式存在，可以跨模型、跨 Agent、跨设备流转。这就是它有价值的地方。</p><h2 id="从一个-Skill-仓库开始"><a href="#从一个-Skill-仓库开始" class="headerlink" title="从一个 Skill 仓库开始"></a>从一个 Skill 仓库开始</h2><p>如果你也想试，我建议不用一上来就整理全部 Skill。先挑三类最常用的：写作或内容处理、研究或搜索、工程或发布。</p><p>然后建一个私有 Git 仓库，把 <code>skills-sync</code> 的仓库 URL 和目标仓库 URL 一起给 Agent，让它先读 README，再给你一个执行计划。在另一台设备上，也把目标 Skill 仓库 URL 给 Agent。让它确认 Git 认证、阅读仓库结构，再用合适的方式安装指定 Skill。</p><p>只要这个闭环跑通，你就已经有了一个最小可用的私有 Skill 管理系统。重点不在于记住多少命令，而是把「研究命令、检查环境、执行同步」这些注意力开销交给 Agent。</p><p>最后也说一个边界：<code>skills-sync</code> 目前主要还是我个人在用，是从自己的真实工作流里长出来的轻量 CLI。所以它的用例覆盖肯定有限，很多问题只有放到更多人的环境里，才会暴露出来。</p><p>如果你对这个方向感兴趣，欢迎体验，也欢迎给仓库 Star。更欢迎提 issue 和 pr，或者直接说说你的使用场景和问题。我会很感谢，因为这类工具只有在更多真实用例里跑过，才知道哪些地方是真的有用，哪些地方只是我自己的习惯。</p><p>最后还是回到那句话：</p><blockquote><p>Skill 的真正价值，不在于它看起来多复杂，而在于它能不能把你反复消耗注意力的工作，变成稳定、可复用、可迁移的能力。</p></blockquote><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><code>skills-sync</code> 项目：<a href="https://github.com/shiquda/skills-sync">https://github.com/shiquda/skills-sync</a></li><li>Vercel Labs <code>skills</code> CLI：<a href="https://github.com/vercel-labs/skills">https://github.com/vercel-labs/skills</a></li><li>Skills CLI 文档：<a href="https://www.skills.sh/docs/cli">https://www.skills.sh/docs/cli</a></li><li>Vercel Agent Skills 文档：<a href="https://vercel.com/docs/agent-resources/skills">https://vercel.com/docs/agent-resources/skills</a></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>焦虑，是因为你觉得自己还能改变什么</title>
      <link>https://shiquda.link/anxiety-formula/</link>
      <description>焦虑的本质不是不确定性，而是「我觉得自己还能改变什么」。本文从经验出发，推导出一个焦虑公式，并给出缓解短期焦虑与追求长期进步可以兼得的实践路径。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%9A%8F%E7%AC%94/">随笔</category>
      <category domain="https://shiquda.link/tags/%E6%80%9D%E8%80%83/">思考</category>
      <category domain="https://shiquda.link/tags/%E7%84%A6%E8%99%91/">焦虑</category>
      <category domain="https://shiquda.link/tags/%E5%BF%83%E7%90%86/">心理</category>
      <pubDate>Fri, 27 Mar 2026 16:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="焦虑，是因为你觉得自己还能改变什么"><a href="#焦虑，是因为你觉得自己还能改变什么" class="headerlink" title="焦虑，是因为你觉得自己还能改变什么"></a>焦虑，是因为你觉得自己还能改变什么</h1><blockquote><p>本文共 5000+ 字，阅读时间需约 8 分钟。</p></blockquote><h2 id="为什么聊这个？"><a href="#为什么聊这个？" class="headerlink" title="为什么聊这个？"></a>为什么聊这个？</h2><p>你可能以为我最近比较焦虑——但恰恰相反。<strong>焦虑</strong>，是我最近和朋友聊天时常常出现的话题，而我自认为在这方面做得还不错，焦虑感大概位于大众中位数以下（虽然这种估计并不科学）。我隐约意识到自己有一套模糊的策略，但从没有系统性地总结过这一现象。</p><p>今天晚上忙完之后，突然想和 AI 聊一聊这个话题。也大概两周多没有和读者见面了，干脆把今晚的思维路径以及收获整理成文，一方面加以深化与整理，另一方面希望对读者能有所启发。欢迎你和我一起漫游。如果你对我的思考迭代路径不感兴趣，可以直接跳到「一个公式」及以后的总结环节。</p><blockquote><p>PS：AI 在这方面确实算是非常有启发性的深度对话伙伴了，之前虽然有所耳闻，但还没有多少深入实践。本次使用的是 Claude 平台，对话轮次 62 轮，体验还是非常惊艳的，通过提示词让它用类似苏格拉底式地问答，一轮轮来发现现有认识中可能存在的偏差，最终使得我对这个话题的认知层次明显进了一个台阶。如果读者还没尝试过的，不妨也找个话题和 AI 深度聊一聊，可能会有意想不到的收获。</p></blockquote><h2 id="从经验中来，对焦虑的模糊认识"><a href="#从经验中来，对焦虑的模糊认识" class="headerlink" title="从经验中来，对焦虑的模糊认识"></a>从经验中来，对焦虑的模糊认识</h2><p>此前，我对焦虑的认识，主要来自零散的信息输入和自身经历，大致罗列如下：</p><ol><li><strong>焦虑的本质是一种对未来不确定性的担忧</strong>。如果一件事已经坐实了，那么就不会感到焦虑；</li><li>有时候，人对一件事情感到焦虑，是因为对这件事情本身的认识和规划并不完善，即「<strong>不够具体</strong>」，如果实际动手去做，那么反而就不会那么焦虑了；</li><li>如果是那些自己几乎无法施加任何影响的事情，（如希望尽可能掷骰子掷出「6」），虽然结果是完全不确定的，但却不会感到焦虑，因为自己知道<strong>无论如何努力都无法改变结果</strong>（至少我不行~）；</li><li>最让人焦虑的，往往有这样一个特点：虽然结果不确定，但自己又觉得通过努力可以影响结果的走向。也就是说，焦虑的核心在于「<strong>我觉得我有能力去影响一个不确定的结果</strong>」。</li></ol><p>基于上述几点认识，我开始了和 Claude 的 <em>苏格拉底式</em> 的对话。</p><h2 id="第一个裂缝：不确定性真的是第一因吗？"><a href="#第一个裂缝：不确定性真的是第一因吗？" class="headerlink" title="第一个裂缝：不确定性真的是第一因吗？"></a>第一个裂缝：不确定性真的是第一因吗？</h2><p>Claude 举了一个挑战这一命题的例子：</p><blockquote><p>假如一个人进了体制内，工作非常稳定，未来的 20 年可能一眼能望得到头，但他认为这种<strong>确定性</strong>换取的结果是个人上界的下降。在这种情况下，这种「一眼望得到头」的确定性，反而可能让他感到焦虑，感觉自己一辈子也就这样了。</p></blockquote><blockquote><p>PS：<em>仅转述 AI 的举例，不代表作者观点。</em></p></blockquote><p>这确实和「<strong>焦虑源于对未来不确定性的担忧</strong>」这一观点相矛盾，而且和大众的直觉相冲突。为什么在这个场景下，这种确定性也会造成焦虑呢？</p><p>进一步思考，我发现，从逻辑上无法推导出焦虑和不确定性有哪些直接的关联。从概念上来说，焦虑是人的一种心理状态，而不确定性仅仅是有可能成为唤醒人的这种心理状态的原因之一。</p><p>回顾成长经历，那些令我焦虑的状态，大多都与第四点相关：我觉得自己能改变某些现状或预期。</p><p>举例来说，如果你在准备某些考试，一方面你想获得比较好的成绩，但另一方面，人的惰性或者是其他因素可能让你不那么愿意花很多精力去准备这场考试。这时候你可能就会有这样的心理压力：</p><blockquote><p>如果我准备得不够充分，考砸了，那怎么办？</p></blockquote><p>这种心理压力可以被总结为：针对一个目标，不够努力可能会导致结果不满意，而我「本可以」更努力，这样结果或许就会好一些。</p><p>这里有一个前提是，事情的最终结果至少在人们看来，是能够被自己的更多投入所影响的，并且往更好的方向走。</p><h2 id="「不可避免」还是「本可避免」？"><a href="#「不可避免」还是「本可避免」？" class="headerlink" title="「不可避免」还是「本可避免」？"></a>「不可避免」还是「本可避免」？</h2><p>Claude 就此提出了一个挑战我目前框架的问题。在学术界中，Barlow 的焦虑理论认为，对未来威胁的<strong>不可控制感与不可预测感</strong>是焦虑的核心心理机制，但前面的认识中，人恰恰是在「可以施加影响」的情况下才会产生焦虑，这两者是否冲突呢？</p><blockquote><p><strong>David H. Barlow</strong>：波士顿大学心理学荣休教授，临床焦虑领域权威学者，提出焦虑的「三重脆弱性模型」，认为早期经历所形成的「不可控制&#x2F;不可预测」图式是焦虑障碍的心理核心。代表作为 2000 年发表于 <em>American Psychologist</em> 的《<a href="https://doi.org/10.1037/0003-066X.55.11.1247">Unraveling the Mysteries of Anxiety and Its Disorders</a>》。</p></blockquote><p>在我看来其实是不冲突的，因为「不可避免」意味着这个问题是人必须做出正面决策的，即我要花多少的努力去完成某件事情。而我对这件事情的努力程度分配，只有在努力能影响最终的结果走向的前提下，焦虑才会产生。</p><p>举一个极端的例子：中国有个典故叫做杞人忧天，大家都清楚是什么含义。对于那些完全超出个人影响力范围的事，我们并不会真正焦虑。既然结果根本不受努力程度的影响，增加或减少投入的意义便消失了，焦虑也就无从产生。</p><h2 id="「躺平」是否是最优解？"><a href="#「躺平」是否是最优解？" class="headerlink" title="「躺平」是否是最优解？"></a>「躺平」是否是最优解？</h2><p>Claude 又抛出一个问题：如果一个人主动放弃对未来行动力的选择权，直接躺平，这是否是一种正确的方式？</p><p>按照我们前面得出的结论，如果从逻辑上来说，一个人主动把未来选择权给放弃了，那么他就似乎真的不会再焦虑了，因为如果没有选择权的话，结果不再受自己的行为所左右，焦虑也没有意义。</p><p>焦虑的消除与清零，并不是最终目的——至少对我来说不是。</p><p>换句话说，<strong>焦虑最小化只是手段，不是目标。真正的目标是推进那些我认为有价值的事情</strong>，而那些事情，恰恰往往需要我承担一定程度的心理张力。一味追求焦虑清零，反而可能让我系统性地回避那些真正值得去做的事。</p><p>而对我来说，目前并没有一个什么至高无上的目的。那些我关注的事情，对我来说都有不同维度上的价值，并不能用一个唯一的指标，来绝对地衡量它们之间哪个最重要。</p><h2 id="我在意"><a href="#我在意" class="headerlink" title="我在意"></a>我在意</h2><p>如果一个人对一件事情感到焦虑，必定有一个前提：<strong>他在意这件事情本身</strong>。</p><p>这很好理解，比如我们可能不会在意，无意之间被我们踩死的一只蚂蚁，哪怕这件事情对它来说是灭顶之灾，但对我们来说，可能甚至没有意识到它的存在，在这种情况下就没有焦虑一说了。</p><p>且感性上来说，<strong>如果一件事情你在意的程度越高，那么你对它的焦虑就会随之被放大</strong>。</p><p>焦虑虽然无法量化，但或许可用公式来方便理解各影响因素。公式左边是焦虑程度，而右边已有一个现成的乘算因子：我们对这件事的在意程度。那么还有哪些？除了「不够努力导致结果变差」的担忧，还有吗？</p><h2 id="投入程度对心理压力的-U-型影响"><a href="#投入程度对心理压力的-U-型影响" class="headerlink" title="投入程度对心理压力的 U 型影响"></a>投入程度对心理压力的 U 型影响</h2><p>在 Claude 的引导下，我想到另一种焦虑：<strong>如果为这件事加倍努力，结果却是坏的，我能接受吗</strong>？</p><p>过去的成长经历中，大多数时候我都不能接受这种沉没成本的代价，它带来的焦虑甚至比「不够努力」造成的还要更深。</p><p>因此我们就可以画这么一个曲线图了。以努力程度为横轴、<strong>心理压力</strong>（焦虑程度）为纵轴，会得到一条 <strong>U 型曲线</strong>：两端（完全不投入，或拼尽全力）的焦虑都高，中间适度投入时心理成本最低。这背后的逻辑需要从两个端点来看。我们在意的事情，往往无法完全由个人努力掌控结果。</p><p>如果我完全不努力，那么它最终结果的期望就会很低。在这种情况下，我得面对未来结果可能不如意的心理压力。</p><p>另外一个极端是：如果我全力以赴地做这件事情，那么在最后如果我仍然失败了，我将承受<strong>感性上的沉没成本</strong>带来的压力，以及<strong>理性上的机会成本</strong>带来的损失。因为我「本可以」把这用于努力的注意力资源分配到其他可能也有意义的方向上。</p><p>因此，分配适中的注意力，既不会因完全不努力而担心结果，也不会因全力以赴而承担沉没成本的焦虑——纯从缓解焦虑的角度，这是最优解。</p><p><strong>人关注的不可能只是单一一件事情</strong>。实际上，我们可能需要在多种这样的事情中进行权衡，合理分配自己的注意力资源在不同事情上。</p><p>从理性上来说，假如我们真的可以量化我们对每件事情的在意程度的话，那么<strong>从降低焦虑的角度出发</strong>，较优的一种决策是：根据我们对每件事情的在意程度，从高到低地优先让越在意的事情越用适中的分配程度来做，既不是完全不做，又不是全力以赴。</p><blockquote><p>PS：注意，这里是从缓解焦虑的角度出发。最小化焦虑程度可能并不是我们的唯一追求。</p></blockquote><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_02-infographic-u-curve-a21b6013.png" alt="投入程度与心理压力的 U 型曲线" loading="lazy"></p><h2 id="一个公式"><a href="#一个公式" class="headerlink" title="一个公式"></a>一个公式</h2><p>因此，我们总结的具体公式如下：在<strong>结果未定</strong>的前提下，且仍有可分配注意力资源时，有：</p><p><strong>焦虑 &#x3D; 我在乎 × （「本可以」 + 「沉没成本」）</strong></p><p>其中：</p><ul><li><strong>我在乎</strong>：我对这件事情的在意程度</li><li><strong>「本可以」</strong>：在欠投入注意力资源的情况下，需要承担结果不如意的后果</li><li><strong>「沉没成本」</strong>：在全力以赴地投入的情况下，投入的努力可能白费</li></ul><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_01-framework-anxiety-formula-63a89174.png" alt="焦虑公式框架图" loading="lazy"></p><h2 id="可能你在潜意识中已经应用了这个公式"><a href="#可能你在潜意识中已经应用了这个公式" class="headerlink" title="可能你在潜意识中已经应用了这个公式"></a>可能你在潜意识中已经应用了这个公式</h2><p>上面这个公式可以帮助我们主动缓解焦虑。但事实上，我们在过去的决策过程中，很可能在潜意识中已经运用了上述公式，<strong>自然选择了一个对我们心理成本最低的方式来做事情</strong>。</p><p>让我们回到前面的问题：心理成本最低，就是我们希望看到的吗？</p><p>我问了问我自己。对我来说，并不是。</p><p>就我自己而言，在过去的很多次决策中，或许过度高估了<strong>张力 B</strong>（心理上的沉没成本）的影响，甚至导致我直接否决是否要做某件事情，或是做了一半中途而废。</p><p>而这仅仅是因为：<strong>我怕努力了也会失败，还不如把注意放在其他 xxx 事情上</strong>。</p><p>这在很大程度上，限制了我对更丰富维度与领域的探索，让我停留在自己的「<strong>舒适圈</strong>」中。</p><p>这给我敲响了一个警钟：焦虑带来的心理成本上升仅仅是短期的影响。<strong>短期来看心理负担最轻的选择，长期来看，并不一定是自己最期望看到的</strong>。心理成本上最优的决策，在产出效应维度来看，可能系统性地低于最优投入，同时系统性地削弱我们把事情做好的概率。</p><h2 id="缓解短期焦虑和追求长期进步，可以既要又要吗？"><a href="#缓解短期焦虑和追求长期进步，可以既要又要吗？" class="headerlink" title="缓解短期焦虑和追求长期进步，可以既要又要吗？"></a>缓解短期焦虑和追求长期进步，可以既要又要吗？</h2><p>按照焦虑最小化的逻辑，我们似乎必然会系统性地减少注意力的分配；而如果增加对在意事情的注意力分配，那么似乎又必然引起焦虑。</p><p>这二者难道不能「既要又要」吗？<strong>能不能既给自己更在意的事情分配较高程度的注意力资源，同时又缓解由此带来的（主要是「沉没成本」）焦虑呢</strong>？</p><p>Claude 问了问我：你最早为什么认为自己没感觉有多么焦虑？</p><p>我给他讲述了最近的一些事情。他的理解是这样的：</p><p>我之所以焦虑感相对较低，并不是因为我回避了那些符合公式条件的处境——事实上，那些处境是真实存在的。而是因为在过去的决策中，我有一种相对自然的倾向：倾向于选择那些可以同时推进多个「在意」的方向，而不是把注意力资源孤注一掷地押在单一的外部结果上。</p><p>这种做法在客观上降低了「沉没成本」这个心理张力——因为即便最高层级的目标没有达成，过程中积累的东西，仍然对其他我在意的方向有所推进。换句话说，「失败」这个状态被稀释了：它不再是「一切白费」，而只是「最高目标暂时没有达到」。</p><p>但我也意识到，这种倾向在过去是隐性的、无意识的。今晚，它才第一次被显性地命名。</p><p>问题的要害在于：<strong>「在意」的话语权归属</strong>。</p><p>如果你「在意」的东西，很大程度上是需要得到外界的认可的，如升学考试、职称晋升等，那么往往这些东西就真的是原子化的、各自为战的，你必须把自己有限的注意力资源分配到这些上面，并承担自己欠努力带来的「本可以」+「沉没成本」的双重心理压力。</p><p>而如果你「在意」的东西，有相当一部分是只需要得到你自己认可的，那么可操作空间就大了很多。事实上，很多你在意的事情，并不是具体的一件事。例如健康状况、爱好活动等，这种由自己创设的在意，可以和具体的事情所绑定，甚至可以做到，在一件具体的事情中，同时实现多个目的。例如你爱好打羽毛球，在此过程中，你可以既满足兴趣爱好，也提升你的健康状况。</p><p>实际情况中，往往是二者兼具：一个人既有从外部标准（无法自己完全把控）中获取到的「在意」，也有一定从自我内部出发的「在意」。当我们考虑如何分配注意力资源时，可以把<strong>外在的「在意」</strong>，尝试从中挖掘<strong>内在的「在意」</strong>，将二者结合起来，并优先给那些结合了多重「在意」的事情分配更多的注意力资源。</p><p>这样可以<strong>实现「沉没成本」&#x2F;「机会成本」的均摊</strong>。如果我们把模型简化，把一个个事情当作原子化来考虑，即一件事情只有成功和不成功两个可能的状态，那么这种做法的优化之处在于，它把一个 0-1 分布转换成了一个多层收益矩阵，「完全失败」的概率空间被大幅压缩了。哪怕最高层级在<strong>结果</strong>上没有真正达到，你在<strong>过程</strong>中做的努力，也对同时推进的其他你在意的部分有所帮助。</p><p>假如你是一个羽毛球爱好者，报名了一个将在 2 个月后举行的羽毛球比赛。如果你只是想着把比赛获得好成绩当作唯一在意之事，那么焦虑的压力可能会让你最终选择一个心理成本最低而注意力分配欠佳的策略。如果同时，你结合内在的在意，即对羽毛球运动本身的爱好、对身体健康的追求，那么在这过程中，哪怕你最终没有如愿获得好成绩，训练中获得的愉悦和健康状况的改善，也「不亏」：<strong>那些「沉没成本」不再沉默了</strong>。</p><p>按照这个思路出发，我们有两种优化方式。其一较为简单，是可立即生效的：探寻自己目前在做的<strong>外在在意</strong>中，有哪些潜在的<strong>内在在意</strong>，由此可直接缓解心理压力，或用更高的注意力分配来推进这个在意的事情集群。其二是未来在做<strong>外在在意</strong>的具体选择时，优先选取那些可以结合<strong>内在在意</strong>的事项，尽可能多地和内在在意沾边，这其实也在潜移默化地帮助我们成为自己真正想成为的那个我。</p><p>所以，缓解短期焦虑和追求长期进步，可以既要又要吗？虽然无法做到二者同时达到理论最优值，但<strong>可以大大优化</strong>。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_03-comparison-inner-outer-697001e4.png" alt="内外在意叠加优化策略对比图" loading="lazy"></p><h2 id="解答未被解答的问题"><a href="#解答未被解答的问题" class="headerlink" title="解答未被解答的问题"></a>解答未被解答的问题</h2><p>回顾我最早和 Claude 的四个出发点，看看用我们迭代后的认知框架，如何解构这四个问题。</p><p>第一点，「焦虑是对未来不确定性的担忧」，我们说明了实际上核心之处不是不确定性，而是「未定」：对自己在意的事情，在未来仍可以通过改变自己的努力程度&#x2F;注意力分配程度来一定程度上影响走向，<strong>这是整个公式成立的基础</strong>，而非自变量。</p><p>第二点，<strong>「不够具体」是焦虑的诱因</strong>，这一点我们前面还没涉及到，这里展开分析一下。如果一件事情不够具体，那么前面的「本可以」和「沉没成本」同时被放大了。</p><p>「本可以」方面，你知道自己的努力可以影响结果，但不知道如何开始做。你有选择分配注意力的自由，但这种自由无法被转换为行动，这种状态反而比放弃自由（例如选择「躺平」）更加让人焦虑。</p><p>「沉没成本」方面，正因为不知道如何开始，任何投入都可能方向错误，沉没成本的恐惧被放大了。</p><p>动手，本质上是在<strong>强制启动具体化的过程</strong>，让框架重新回到可操作的状态。当你真正动手去做，发生的事情是：模糊的大问题被分解成了一系列具体的小问题，每一个小问题都有相对清晰的行动路径，相当于把一个<strong>巨大的单一不确定性</strong>，拆解成了<strong>多个较小的、可以逐步处理的不确定性</strong>。由此可将简单的 0-1 分布转换成一个多层收益矩阵，均摊了「沉没成本」。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_04-flowchart-specificity-mechanism-e3742949.png" alt="不够具体的双重张力放大机制" loading="lazy"></p><p>第三点，如果是那些自己几乎无法施加任何影响的事情，（如希望尽可能掷骰子掷出「6」），虽然结果是完全不确定的，但却不会感到焦虑。</p><p>这个维度看似满足<strong>结果未定</strong>的前置条件和<strong>我在意</strong>，但两个<strong>张力</strong>都同时消失了，「<strong>本可以</strong>」无从谈起，「<strong>沉没成本</strong>」也不存在，因为你根本不会去向这件事上增加或减少注意力资源的分配。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_06-comparison-influence-axis-b44fe4d1.png" alt="「能否影响结果」决定焦虑是否产生" loading="lazy"></p><p>第四点，焦虑的核心在于「我觉得我有能力去影响一个不确定的结果」，显然，我们的公式可以完美解释这一点。<strong>正是因为相信自己能影响结果，「本可以」这个张力才得以成立</strong>。如果连影响结果的可能性都不存在，又从何谈起「本可以更努力」呢？</p><h2 id="那应该怎么做呢？"><a href="#那应该怎么做呢？" class="headerlink" title="那应该怎么做呢？"></a>那应该怎么做呢？</h2><p>我之前的思考，总是容易停留在脑子里，没有落实在实践中，因此现在每次我有比较深入的思考，必须强制自己列一个可执行的清单，问问自己：「既然如此，那我应该怎么做呢？」</p><p>写到这里初稿已经超过 5000 字了，用时超过两小时半。下面偷了个懒，让 Claude 帮我整理了一下：</p><hr><p><strong>立即可做：</strong></p><ol><li><strong>盘点当前正在推进的「外在在意」</strong>，逐一问自己：这件事里，有没有我内在真正感兴趣的部分？把它显性地写出来，让它不再只是隐性存在。</li><li><strong>觉察自己是否因为预期沉没成本而提前放弃</strong>。当下次发现自己在说「算了，万一失败了也是白费」，停下来问：这是真实的理性判断，还是在用张力 B 给自己找退路？</li><li><strong>对不够具体的事，强制迈出第一步</strong>。模糊感本身会放大两个张力，动手是唯一的解药，不需要想清楚再开始。</li></ol><p><strong>做新决策时：</strong></p><ol><li><strong>优先选取能同时推进多个内在在意的方向</strong>。同一份注意力能服务于越多自己真正在乎的事，沉没成本的心理压力就越低，行动的阻力也越小。</li><li><strong>区分「在乎的是结果」还是「在乎的是过程本身」</strong>。前者让你更容易被张力 A 和 B 控制（<em>作者注：「本可以」和「沉没成本」</em>）；后者让你在结果未定时仍然有稳定的行动锚点。</li></ol><hr><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_05-framework-action-checklist-11e1d38c.png" alt="焦虑管理行动清单" loading="lazy"></p><p>写得还不错，希望对我们能有所启发。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>听无人知晓 E45 孟岩对话李继刚：人何以自处 有感</title>
      <link>https://shiquda.link/tingwurenzhixiao-e45-reflection/</link>
      <description>听完《听无人知晓》E45 期播客的思考笔记，记录关于取景框、AI 时代读书、驱动 AI、心力与脑力等触动我的观点。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%80%9D%E8%80%83/">思考</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/%E6%80%9D%E8%80%83/">思考</category>
      <category domain="https://shiquda.link/tags/%E6%92%AD%E5%AE%A2/">播客</category>
      <pubDate>Fri, 06 Mar 2026 16:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="听无人知晓-E45-孟岩对话李继刚：人何以自处-有感"><a href="#听无人知晓-E45-孟岩对话李继刚：人何以自处-有感" class="headerlink" title="听无人知晓 E45 孟岩对话李继刚：人何以自处 有感"></a>听无人知晓 E45 孟岩对话李继刚：人何以自处 有感</h2><p>这期播客虽然已经播出一段时间了，但我自己听完还是很有感触，前后分了两天听完，又拖了一天整理。这也是我第一次认真写播客听后感。之前我虽然是重度播客听众，但很少专门写这类文章，主要是因为很多播客内容偏散，通常只值得在 <code>Notion</code> 里随手记几条零碎想法。这一期不一样：里面有不少观点，确实让我想停下来单独记一篇。</p><p>注：本文不等于播客内容的完整总结，如果您有需求，<code>AI</code> 做得比我好多了。如若也对这期内容感兴趣，推荐直接收听原播客。本文仅记录一些笔者在收听过程中真正“触动”了我的观点，并在此基础上补充一些个人思考。尽管我会尽量加以区分，但部分转述可能无意中融合了个人的一些思考，请读者以原播客内容为准。</p><p>特别有感触的观点用“💡”注明。</p><blockquote><p>个人思考部分，会以这种批注的方式呈现，加以区分。</p></blockquote><h3 id="1-“取景框”"><a href="#1-“取景框”" class="headerlink" title="1. “取景框”"></a>1. “取景框”</h3><p>嘉宾认为，每个人看待世界有不同的视角，称作<strong>取景框</strong>。这种取景框，实际上是世界这个多维事物在某些维度上的投影。也就是说，在特定的语境下，或者说特定的上下文中，取景框里显示的内容和其认知是符合的。但是问题是每个人的取景框检测的维度是不一样的。因此，一个人应该承认自己取景框的<strong>局限性</strong>，积极借鉴他人的取景框，才能对世界有更全面的认知。</p><p>注意，这里要区分我和我的取景框这两个概念。我的取景框是一个相对静态的概念，它代表了我在某一成长阶段看待世界的方式。而我是一个动态概念，会随着成长历程不断迭代。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_01-framework-viewfinder-theory-v2-7dffad82.png" alt="取景框理论" loading="lazy"></p><h3 id="2-财富占比投资观"><a href="#2-财富占比投资观" class="headerlink" title="2. 财富占比投资观"></a>2. 财富占比投资观</h3><p>我们投资追求的并不是绝对数额上赚了多少钱，本质上应该换一个更有启发性的思路来投资。也就是说，我们的目标应该是<strong>尽可能增大自己的个人财富在整个世界总财富中的占比</strong>，或者退而求其次，至少不让这个占比下降。而从这个思路出发，我们只需要把资金配置在那些未来会变得越来越主流、体量越来越大的资产上。这是一个宏观长期的总体目标。</p><blockquote><p>如果说手上全是现金，或者是全放余额宝，这样的话，其实至少目前来看，现金是会贬值的。因此这种方式并不能达到前面的目的。</p></blockquote><h3 id="💡3-知识获取的时空维度压缩"><a href="#💡3-知识获取的时空维度压缩" class="headerlink" title="💡3. 知识获取的时空维度压缩"></a>💡3. 知识获取的时空维度压缩</h3><p>纵观人类的读书或者说学习这个过程，最早的话是看书，就是纸质的书。我们可以从空间和时间两个维度上来分析。如果是读书的话，就是传统的读书，它可能是需要占有一定的空间和时间。空间就是说书有物理体积，时间的话是说你需要阅读和理解思考的时间。然后你才可以把这些知识真正掌握。到了互联网时代，很多东西都电子化了，物理空间消失了，转换成了数字空间。但时间维度仍然存在。</p><p>比如说你看电子书，你仍然需要自己去理解，去消化，才能掌握一些里面的精髓知识。但是到现在，如果 AI 出现的话，实际上是把最后一个时间维度也给压缩掉了。也就是说，你以前想要看完一本书，反复咀嚼才能获得知识，你可能现在一问大模型就有，或者说让它帮你总结。这一步节省了时间。至此，时间和空间两个维度上，知识的门槛已经大大降低了。</p><p>再比如说之前中国和美国是有空间距离的。但是后面上网之后，两边就可以很大程度上逾越空间的现实差异，然后进行更多更密切的交流、沟通。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_02-framework-knowledge-compression-51289dd3.png" alt="知识获取的时空维度压缩" loading="lazy"></p><h3 id="4-AI-是更好的对话者"><a href="#4-AI-是更好的对话者" class="headerlink" title="4. AI 是更好的对话者"></a>4. AI 是更好的对话者</h3><p>和 <code>AI</code> 聊天的深度，能比和人聊天更深。<code>AI</code> 学习了人类知识的很大一部分，<code>LLM</code> 融合了海量的知识和智慧，不是单个人可以比拟的。因此，应该多和 <code>AI</code> 交流自己的思想。</p><h3 id="5-AI-时代的职业意义"><a href="#5-AI-时代的职业意义" class="headerlink" title="5. AI 时代的职业意义"></a>5. AI 时代的职业意义</h3><p>很多职业在未来遇到 AI 后面临的问题，相当于国际象棋或围棋的专业棋手在遇到人工智能这座无法逾越的高山时，下棋竞技的意义何在。</p><blockquote><p>这个类比非常有意思。</p></blockquote><h3 id="💡6-AI-时代如何读书"><a href="#💡6-AI-时代如何读书" class="headerlink" title="💡6. AI 时代如何读书"></a>💡6. AI 时代如何读书</h3><p>关于读书这个话题，在 <code>AI</code> 时代，我们应该如何读书呢？人类的注意力资源（或者说算力，用 <code>Agent</code> 的概念来说）是有限的，传统的方式就是人直接用自己的算力去阅读、理解和整理书籍里的知识。如果从学习作者提供的知识来看，具体从书中如何获得作者想要提供的知识并不重要，哪种方式更容易、更省时间就怎么做。因此利用 <code>AI</code> 来阅读、快速整理自己感兴趣的部分是没有问题的。那读书的意义在哪里呢？在现在，亲自读书更大的意义在于，你在阅读的时候会触发思考，对自己进行启发，提供灵感。</p><blockquote><p>其实写作也是如此。如果追求流量、效率、变现的话，那么让 <code>Agent</code> 完全接管写作，无疑是最“好”的选择，我相信已经有很多人这么做了。<strong>因为对我来说，写作最大的意义不是结果本身，而是在过程中把一些原本不会想得那么深入的问题想清楚，并在写作中获得新的启发和灵感。</strong>在这点上其实我是比较自私的，因为文章的产出，对读者的价值，在我这里其实并不是最主要的，反而是我自己在写作过程中获得的启发和灵感，对我来说才是最大的价值。当然，我也会尽可能在和 <code>Agent</code> 的协作中，渐渐地提高我的写作水平。</p></blockquote><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_07-comparison-reading-in-ai-era-3ce1f114.png" alt="AI 时代如何读书" loading="lazy"></p><h3 id="💡7-驱动-AI，而不是被-AI-驱动"><a href="#💡7-驱动-AI，而不是被-AI-驱动" class="headerlink" title="💡7. 驱动 AI，而不是被 AI 驱动"></a>💡7. 驱动 <code>AI</code>，而不是被 <code>AI</code> 驱动</h3><p>和 <code>AI</code> 聊天，深度能比和人聊天更深。</p><p>一个例子是，老板让你做 <code>xxx</code>，你根本不思考，直接让 <code>AI</code> 做，做了个还凑合的交给老板。在这个过程中，是老板&lt;-&gt;你&lt;-&gt;<code>AI</code>，你实际上成为了 <code>AI</code> 的传话筒，成为了 <code>AI</code> 的工具。另一种方式是，你对老板给你的任务有一些自己的 <code>idea</code>，然后让 <code>AI</code> 帮你为这个 <code>idea</code> 进行反思、添砖加瓦或是快速实现，这种其实仍然是老板&lt;-&gt;你，但是你利用 <code>AI</code> 这个东西，一方面做得更快了，另一方面，你本身在和 <code>AI</code> 的交流过程中，对任务有了新的认识和思考，你在进化，你的取景框更加丰富，对事情的思考更加深入。</p><blockquote><p>这里其实引起了一个我许久之前没想通的问题，即关于我们在日常生活中的一些事情，如果交给 <code>Agent</code> 做，会不会让我们的能力“退化”？我目前的观点是，应该一分为二地看待这件事情。如果是那些“非核心”的能力（注意，这里的核心具有相对性，因人而异），比如对我来说有 <code>Excel</code> 的操作、具体代码技术细节的编写、错别字纠正等，那么完全交给 <code>Agent</code> 做即可。而对那些你在意的“核心”类型的，我认为应该采用一种<strong>与 <code>Agent</code> 协作</strong>的方式，让它和你对这个问题共同讨论、共同进步。这背后的原因很简单，因为不管做什么都是需要注意力资源的，而人的注意力资源是有限的。把不那么核心的任务或你对其背后能力不感兴趣的注意力，更多放在那些真正重要的上，自然就是更好的一种选择了。</p></blockquote><blockquote><p>那么我们具体如何判断，什么样的能力才是符合自己需求的那种“核心”能力呢？这个问题我也没有很好的答案，我提供几个问题，供读者参考。一是问“没有了这种能力，我的竞争力会怎么样？”，比如说前面的 Excel 操作，我以后不会成为一个需要靠 Excel 操作为业的，那么这个能力对我就无关紧要（更不用说以后这种可能就完全被 Agent 取代了，甚至可能有更加适合 Agent 之间数据流转的标准出来）。二是问“是否有复利效应”。如果有很多可选的同等重要的能力，那么在注意力有限的前提下，优先选择有复利效应的那些，比如人的认知、思维方式、审美、学习能力等，而不是那些线性的具有重复性特征的，如代码编写能力这种“手艺”。</p></blockquote><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_06-comparison-drive-vs-follow-ai-f2c49a16.png" alt="驱动 AI，而不是被 AI 驱动" loading="lazy"></p><h3 id="8-心力-vs-脑力"><a href="#8-心力-vs-脑力" class="headerlink" title="8. 心力 vs 脑力"></a>8. 心力 vs 脑力</h3><p>嘉宾比较激进地认为，在未来，<code>AI</code> 和人的分工将会非常极端。用嘉宾的话来说，人负责提供<strong>心力</strong>，<code>Agent</code> 负责提供<strong>脑力</strong>，实现心力和脑力的解耦，但二者又可以紧密联系。前几次工业革命，人把一部分体力工作让渡给机器，总体上来说，人更多负责使用智力来为社会提供价值。在本次新的革命中，人可能还得把脑力让渡给 <code>LLM</code>。那人还剩下什么呢？也就是所谓心力了，即人类最本源、最内在、最本质的驱动力。</p><p><strong>演进路径：</strong> 早期人类把体力交给机器 → 进入脑力时代；现在脑力交给 AI → 进入心力时代。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_03-framework-heart-vs-brain-v2-b87ae878.png" alt="心力 vs 脑力" loading="lazy"></p><h3 id="💡9-Agent-时代的长尾商业逻辑"><a href="#💡9-Agent-时代的长尾商业逻辑" class="headerlink" title="💡9. Agent 时代的长尾商业逻辑"></a>💡9. <code>Agent</code> 时代的长尾商业逻辑</h3><p>Agent 时代，底层的商业逻辑是<strong>长尾</strong>。互联网时代的底层逻辑是<strong>马太效应</strong>（赢家通吃、头部集中），Agent 时代的底层逻辑变成了<strong>长尾效应</strong>（无限细分、每个人都被完美服务）。</p><blockquote><p><strong>长尾效应</strong>：由 <a href="https://www.wired.com/2004/10/tail/">Chris Anderson</a> 在 2004 年提出，指大量低需求的小众产品累积起来的总市场份额，可以与甚至超过少数热门产品。核心是「销售更多更少」（selling less of more）。</p></blockquote><p>以前互联网虽然也在讲个性化，但本质上仍然是平台基于规模效应做出来的「千人千面」：它能把人分群，用同一产品疯狂扩张，拉低边际成本曲线，但对于具体化、个性化的需求来说，却很难真的服务到每一个具体的人。现在 <code>AI</code> 更像是「一人一面」，有一个随时在线、拥有全人类很大一部分知识的 <code>Agent</code> 为每一个人服务，可以做到极致的个性化。也正因为如此，<code>Agent</code> 时代的长尾才成立：以前很多过于细小、服务成本过高的需求不值得被满足，现在却可能被低成本、持续地满足。于是长尾变成主战场：每一条长尾都能被完美服务，累加起来就是巨大价值。以前你得靠规模（用户多、流量大）才能活；现在你只要把一口井打得足够深（对一小群人极致理解），就能活得很好，甚至<strong>一个人 + 一堆 Agent 就能撑起一家公司</strong>。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_04-framework-long-tail-effect-v2-66e7d61c.png" alt="Agent 时代的长尾商业逻辑" loading="lazy"></p><h3 id="10-三次工业革命"><a href="#10-三次工业革命" class="headerlink" title="10. 三次工业革命"></a>10. 三次工业革命</h3><p>嘉宾把工业革命以来分成三个阶段：</p><ol><li>移动原子 - 蒸汽机、火车、汽车、飞机</li><li>移动信息 - 互联网、移动互联网</li><li>移动智能 - AI、Agent</li></ol><blockquote><p>每个阶段都带来自动化和效率的数量级提升。</p></blockquote><h3 id="💡11-链与环"><a href="#💡11-链与环" class="headerlink" title="💡11. 链与环"></a>💡11. 链与环</h3><p>讨论大模型知识来源时，嘉宾提出两个相对概念：</p><ul><li>环：头尾相接，自成体系的思考方式&#x2F;范式，关键特征是可复用</li><li>链：不连接，临时的论据，射出去就没了</li></ul><blockquote><p>举例：金字塔原理（Pyramid Principle）是由麦肯锡前顾问芭芭拉·明托（Barbara Minto）提出的思考与表达框架，她在 20 世纪 60 年代于麦肯锡工作期间发展了这一方法，并在 20 世纪 80 年代正式出版成书。核心是把所有想法组织成金字塔形状。运用金字塔原理，其实就是实现了环的复用。</p></blockquote><p>Prompt 是人与 Agent 之间进行交互的媒介。传统的 prompt 本质上是一种一次性的链，用完即抛。和 LLM 对话中的成长，必须经由人的大脑来处理，或者人将所思主动记录，这样其实是受限于人的注意力的。但嘉宾提出了另一种思路，可以让 Agent 来辅助处理这个过程，相当于把人脑处理成环的这部分注意力解放一部分。通过设置 Soul 和 memory 文件的方式，让 AI 自动查找潜在的关联，或者实现记忆文件的迭代，实现人与 Agent 的认知共建。这个思路很有意思。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_05-concept-chain-vs-ring-v2-807388d7.png" alt="链与环" loading="lazy"></p><blockquote><p>受李继刚老师启发，我想到也可以把自己的认识给他落盘，形成一个具有层级的知识库，让 Agent 帮我在和我不断交流的过程中，一起迭代我的认知。这当然不是放弃思考，把脑子交给 Agent，我希望做的是和 Agent 的双向交流，既有我的特色，又能参考一些 Agent 的意见。另外，由于人的注意力资源是极其有限的，而 Agent 的智力在我们看来可近似于无限，那么靠 Agent 来给我们在后台进行思考、总结，并提出一些潜在的知识的跨领域迁移或是思考中潜在的不足，可以让我们在这个过程中节省大量注意力资源。我目前准备研究一套这样的与 Agent 对接的个人认知管理系统，希望不久以后就可以和读者见面。</p></blockquote><h3 id="12-在阅读材料上运用杠铃法则"><a href="#12-在阅读材料上运用杠铃法则" class="headerlink" title="12. 在阅读材料上运用杠铃法则"></a>12. 在阅读材料上运用杠铃法则</h3><p>嘉宾提出了一种将「杠铃法则」运用于阅读材料选取的思路。嘉宾说现在基本只选取两种书目来读，一种是经典，经过实践沉淀；一种是前沿优秀论文。思路值得借鉴。</p><h3 id="13-对于规律本身的态度"><a href="#13-对于规律本身的态度" class="headerlink" title="13. 对于规律本身的态度"></a>13. 对于规律本身的态度</h3><p>我其实是一个比较喜欢总结和抽象的人，看到某些现象，总想着把这些现象背后，会不会有一些更加本质的、可泛化的一些规律，提出一些假设，并且看看这种假设，在其他外延上是否成立。嘉宾也是如此，他提到说，如果自己找到一个更加深一层、更本质的规律，那么就可以直接把原来的规律抛掉。逐渐这么迭代，人对世间事物的理解就会更加深入。</p><h3 id="14-健脑房：脑力替代后的补偿机制"><a href="#14-健脑房：脑力替代后的补偿机制" class="headerlink" title="14. 健脑房：脑力替代后的补偿机制"></a>14. 健脑房：脑力替代后的补偿机制</h3><p>嘉宾用了一个很有意思的类比：工业革命后，体力劳动被机器替代，人需要通过健身房、康复训练来补偿身体使用不足；如果 AI 大量替代脑力劳动，未来也可能出现某种「健脑房」，用于恢复或训练人的脑力。</p><p>这里的脑力，更接近计算、逻辑、分析、推演这些能力，而不是前面说的心力。这个类比最有意思的地方在于，它把一个常见的乐观叙事反过来问了一遍：如果 AI 真把脑力活都接过去了，人会不会像长期不运动导致肌肉萎缩一样，出现某种「脑力萎缩」？</p><h3 id="15-AI-的终极变量：意识"><a href="#15-AI-的终极变量：意识" class="headerlink" title="15. AI 的终极变量：意识"></a>15. AI 的终极变量：意识</h3><p>未来 AI 是会摧毁人类，还是说为了人类的福祉而工作？嘉宾认为，最关键的一个变量就是，AI 究竟到未来会不会拥有意识。</p><p>如果 AI 没有意识，那它再强，本质上也仍然是工具；如果 AI 拥有意识，那它就可能具有自己的目标，人类与 AI 的关系也会发生根本变化。</p><blockquote><p>这一点之所以重要，是因为它已经不只是技术问题，而是哲学和伦理问题。比如，什么叫意识？自我意识、主观体验、意向性分别算不算？以及，LLM 现在的一些涌现现象，到底只是复杂系统表现，还是某种更深东西的前兆？这些问题短期无解，但确实决定了很多终局判断。</p></blockquote><h3 id="💡16-Agent-时代的组织管理重构"><a href="#💡16-Agent-时代的组织管理重构" class="headerlink" title="💡16. Agent 时代的组织管理重构"></a>💡16. Agent 时代的组织管理重构</h3><p>嘉宾认为，传统人类管理体系在 Agent 时代可能会变成累赘。</p><p>过去层级式管理很大程度上是为了上传下达、维持组织运转效率；但如果 Agent 可以直接接收目标并执行，那么很多中间层的传递职能就会被削弱，组织可能进一步扁平化，甚至出现某种接近无层级的形态。</p><p>同时，传统激励机制也会失效。管理人需要奖金、晋升、认可等激励，<strong>但没有意识的 Agent 不需要被激励，它只需要明确的目标、约束和接口</strong>。</p><blockquote><p>这意味着未来管理的重点，可能会从「如何驱动人」，转向「如何定义目标函数和边界条件」。人的角色也会从执行者进一步转向定义者和监督者。这个视角挺狠的，因为它实际上是在讨论整个组织学的前提会不会被改写。</p></blockquote><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_08-framework-agent-org-redesign-9aab7449.png" alt="Agent 时代的组织管理重构" loading="lazy"></p><h3 id="17-审美即权重"><a href="#17-审美即权重" class="headerlink" title="17. 审美即权重"></a>17. 审美即权重</h3><p>嘉宾提出一个说法：审美本质上是一种「权重」。</p><p>也就是说，审美不是简单地觉得某个东西好看，而是在面对多个维度、多个选项时，能够对不同因素进行权衡、排序和取舍。</p><p>这么说，审美其实更像一种长期实践之后形成的判断结构。你在一个领域做得越久，越知道什么是好的、什么是更好的、什么是最好的。</p><p>到了 AI 时代，这种能力反而更重要。因为 AI 可以生成无限选项，但最后哪个更值得选、哪个更符合目标，仍然取决于人的判断。</p><h3 id="💡18-少即是多：Agent-时代的注意力管理"><a href="#💡18-少即是多：Agent-时代的注意力管理" class="headerlink" title="💡18. 少即是多：Agent 时代的注意力管理"></a>💡18. 少即是多：Agent 时代的注意力管理</h3><p>嘉宾这里强调的是，Agent 时代真正稀缺的不是信息，而是注意力。</p><p>因此，思维方式要从「多一个没什么坏处」的加法思维，转向「为什么不减少一个」的减法思维。因为信息一旦过载，人往往只能浅层浏览，反而失去深度理解和思考的能力。</p><p>所以，比起不断增加信息源，更重要的是主动减少输入，只保留真正优质、值得长期关注的来源。</p><blockquote><p>这点真是给我很多启发了，我之前认识到人的注意力资源是最宝贵的，但是却没意识到，现在很多信息源总是抱着“多一个没坏处”的出发点去无脑添加，结果到最后就是啥都看不进去，而那些真正高质量的信息源，却被当作平庸的信息源一样处理了。精选每天摄入的信息源，才可以达到效益最大化。听完我深受启发，马上把各平台的信息源进行了整理，发现自己无意之间竟然订阅了许多可有可无的信息源🤣</p></blockquote><hr><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>最后回看这篇笔记，我真正想带走的其实不是某一个漂亮概念，而是几条更具体的提醒：</p><ol><li>尽量扩展自己的取景框，但也承认它的局限</li><li>尽量借助 <code>AI</code>，但不要把自己活成 <code>AI</code> 的传话筒</li><li>尽量减少无效输入，把注意力留给那些真正重要、且能持续产生复利的东西。</li><li>借助 <code>AI</code>，和自己在元认知上协同进化</li></ol><p>如果说这期播客最后让我更确定了<strong>一点</strong>什么，那大概就是：**<code>AI</code> 时代，人更需要认真决定，自己到底要把注意力放在什么地方**。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>增强人与 Agent 交互体验的 Slash Command</title>
      <link>https://shiquda.link/slash-command-for-better-agent-interaction/</link>
      <description>分享三个提升 Agent 交互体验的自定义 Slash Command：任务完成通知、从对话中学习、需求对齐，从更高维度优化人机协作效率。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/AI/">AI</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/Agent/">Agent</category>
      <category domain="https://shiquda.link/tags/%E6%95%88%E7%8E%87%E5%B7%A5%E5%85%B7/">效率工具</category>
      <pubDate>Thu, 05 Mar 2026 01:29:48 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="增强人与-Agent-交互体验的-Slash-Command"><a href="#增强人与-Agent-交互体验的-Slash-Command" class="headerlink" title="增强人与 Agent 交互体验的 Slash Command"></a>增强人与 Agent 交互体验的 Slash Command</h1><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_01-hero-15650fb0.jpg" alt="三个 Slash Command 的核心价值" loading="lazy"></p><p>“只要重复 3 次的，就给它自动化。”这句话可能有点夸张，但是背后的思路值得借鉴。当我们和 Agent 进行交流的过程中，经常会发现有一些需求会反复出现。此时如果把这些需求进行标准化，通过一些简短的命令来引用大段的提示词描述，既能让 Agent 很清楚地理解我们的需求，又能让我们自己在表达的时候，减少许多不必要的认知负担和操作步骤。道理很简单，如果一件事情在未来会需要我们反复去做的话，<strong>那么对完成这件事的效率提升，未来每执行一次，对我们来说都是一笔可观的注意力收益。</strong></p><p>本文就来分享一些个人使用下来比较实用的自定义 Slash Command。提示词写的一定不是最好的，但希望思路对你有所启发。同时，这篇文章并不介绍具体实现格式和编写的技术细节，因为本篇文章的受众，应该都有方法来询问 AI 来解决。</p><h2 id="什么是-Slash-Command？"><a href="#什么是-Slash-Command？" class="headerlink" title="什么是 Slash Command？"></a>什么是 Slash Command？</h2><p>Slash Command（斜杠命令）是一种简化用户与系统交互的方式，用户通过输入特定的命令（通常以斜杠开头）来触发预定义的操作或功能。用过 Claude Code 等 Coding Agent 用于开发的读者一定比较熟悉。</p><h2 id="Slash-Command-思路分享"><a href="#Slash-Command-思路分享" class="headerlink" title="Slash Command 思路分享"></a>Slash Command 思路分享</h2><p>下面分享一些我从实践中总结出来的，那些对我比较有用的自定义 Slash Command，供读者参考。再次强调，本文不分享在工程实践中，简单通过把提示词进行封装，来实现的功能性的命令，如一键测试、提交等。这些对一个合格的 Agent 交互者来说，都是基本功，应该有意识把常用的提示词封装成这种 Skill 或者 Slash Command。<strong>本文主要从人与 Agent 交互的特征出发，从更高维度，尝试设计一些能够提升 Agent 交互体验的 Slash Command。</strong></p><h3 id="1️⃣-notify-任务完成通知"><a href="#1️⃣-notify-任务完成通知" class="headerlink" title="1️⃣ /notify - 任务完成通知"></a>1️⃣ <code>/notify</code> - 任务完成通知</h3><p>我经常让 Coding Agent 在后台工作，但是等它做完的时候，我可能并不知道这件事情，相当于说，Agent 浪费了这段宝贵的时间，什么事情都没干。我作为它的老板，怎么可以希望员工偷懒呢？那如果我一直盯着它干活，又太浪费我的时间了，究竟我是老板还是它是老板？😄</p><p>因此我设计了一个 <code>/notify</code> 的命令，意思是说，当你完成了这个任务之后，给我发一个 Telegram 的通知。这样的话，我就可以在 Telegram 上收到这个通知了。Telegram 推送在我这里的优先级比较高，因此我大概率是可以看到的，而经过我实际测试下来，Agent 在做完哪怕是比较长的工作后，仍然会记得这件事情。<strong>这相当于给 Agent 完成任务这件事情，添加了一个 <code>hook</code>。</strong> 你也可以按照自己的需求修改这个命令的提示词，大概是这样的：</p><blockquote><p>注：此处使用 <code>apprise</code> 来发送 Telegram 通知，你也可以根据自己的需求，使用其他的工具来实现通知功能。</p></blockquote><figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line"><span class="section">description: Send Telegram notification when task completes</span></span><br><span class="line"><span class="section">---</span></span><br><span class="line"></span><br><span class="line">Send a Telegram notification only after the task is fully completed and verified.</span><br><span class="line"></span><br><span class="line"><span class="section">## Instructions</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> <span class="strong">**Complete the user's task**</span> as requested.</span><br><span class="line"></span><br><span class="line"><span class="bullet">2.</span> <span class="strong">**After completion**</span>, send a notification using:</span><br><span class="line">   <span class="code">`apprise -t "Task Complete" -b "&lt;summary&gt;"`</span></span><br><span class="line"></span><br><span class="line">   Build <span class="language-xml"><span class="tag">&lt;<span class="name">summary</span>&gt;</span></span> as a concrete result summary (2-4 sentences). It must include:</span><br><span class="line"><span class="bullet">   -</span> What was done (specific actions)</span><br><span class="line"><span class="bullet">   -</span> Key result(s) or evidence (file paths, logs, screenshots, or checks)</span><br><span class="line"><span class="bullet">   -</span> Current status: success / partial / failed</span><br><span class="line"></span><br><span class="line">   If $ARGUMENTS is not empty, append it as the last sentence.</span><br><span class="line">   Do <span class="strong">**not**</span> use $ARGUMENTS as the entire summary.</span><br><span class="line"></span><br><span class="line"><span class="bullet">3.</span> <span class="strong">**Timing**</span>: Send notification AFTER all work is done, verified, and ready for user review.</span><br><span class="line"></span><br><span class="line"><span class="section">## User Input</span></span><br><span class="line"></span><br><span class="line">$ARGUMENTS</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"></span><br><span class="line"><span class="strong">**Remember**</span>: Complete the task first, then notify.</span><br></pre></td></tr></tbody></table></figure><h3 id="2️⃣-learn-从对话中学习"><a href="#2️⃣-learn-从对话中学习" class="headerlink" title="2️⃣ /learn - 从对话中学习"></a>2️⃣ <code>/learn</code> - 从对话中学习</h3><blockquote><p>如果对模型的“记忆”相关分析不感兴趣的读者，可以直接跳转到使用方式部分。</p></blockquote><p>Agent 和人不一样。在某种程度上，人的意识和记忆管理是非常紧密的，二者有一定的耦合性。但 Agent 的底座是 LLM，LLM 本身是 <code>stateless</code> 的，也就是说，它没有记忆的能力。如果说有的话，所谓”记忆”能力也是通过外部的文件来实现的，<strong>它们本质上是存储在磁盘上的提示词，并通过一定的方式用软件加以组织，并最终传递给 LLM。</strong></p><p>好在现在已经有很多规范的记忆管理标准了，比如说 Claude Code 的 <code>CLAUDE.md</code>，在每轮对话/工具调用的时候，都会传入，作为全局性的记忆。OpenClaw 的 <code>MEMORY.md</code> 文件也提供了类似的机制。</p><p>还有一种我个人认为比较优雅的方式，是通过 <code>skill</code>。Agent 的记忆本质上都是提示词，那么从记忆的角度来说，skill 的优势在哪呢？我认为，至少有两个方面：</p><p>第一，**<code>skill</code> 实现了”渐进式上下文管理”<strong>。在 Agent 的上下文中，上下文是比较宝贵的。Agent 在需要时调用的 skill，其实会占据非常多的上下文空间。</strong>这实质上是 Agent 在按需获取记忆的过程中，成本和效率这二者的权衡。** 如果完整的提示词都放在全局性的记忆文件里，虽然一定能直接找到，但每次调用的时候，都会占据大量的上下文空间，不仅开销大，也会影响 Agent 推理的效果。人难以一心二用，Agent 在一定程度上也是如此。</p><p>而标准的 skill 在其 <code>SKILL.md</code> 头部，有一些 yaml 格式的自定义字段，其中最主要的是 <code>name</code> 和 <code>description</code>。<strong>在 Agent 运行使用的时候，这些字段实际上充当了「索引」的作用，以一个比较小的上下文代价，来实现对大量提示词的「引用」。</strong> 在需要的时候，Agent 可以通过 <code>name</code> 来调用这个 skill，来获取这个 skill 的 <code>SKILL.md</code> 的全量提示词内容。</p><p>更近一步，在 skill.md 中，还可以把一些不那么重要的、按需查看的内容，放在 <code>references</code> 目录下，来实现更进一步的上下文渐进式管理。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_02-skill-context-564c4dc6.jpg" alt="Skill 渐进式上下文管理机制" loading="lazy"></p><p>第二，**<code>skill</code> 实现了智能与代码的有机融合**。LLM 和代码其实是两种拥有不同优势的工具。</p><p>LLM 以人类知识的一部分为训练语料，本身具有一定的<strong>通用性的智能</strong>。借助提示词和外部的工具环境，这种智能可以做很多之前我们人类引以为豪的事情，比如说写作、翻译、使用工具等。但它又具有<strong>不稳定性</strong>的缺点，尤其是在一些需要非常精确的、结构化的输出的时候，LLM 可能就不太可靠了。而且，使用 LLM 的话，需要一定<strong>推理成本</strong>，如果让它处理一些计算量较大的任务的话，效率也不高。</p><p>而代码在确定性和效率上大大占优。<strong>对于一些需要非常精确的、结构化的输出，或者说需要处理一些计算量较大的任务，代码就非常适合了</strong>。但是代码在编写和测试上，需要一定编写、调试和维护成本，可扩展性比提示词差一些。</p><p>skill 恰好综合了这两者。一个 skill 里面，实际上可以包含<strong>提示词</strong>和<strong>代码</strong>两部分内容。提示词部分可以用来驱动智能，来指导 Agent 在使用这个 skill 的时候，应该怎么做；代码部分则可以用来成为 Agent 的工具，来弥补 LLM 在效率和确定性上的不足。从记忆的角度来说，把一些功能程序化，放在 skill 的代码里，可以很大程度上节省 Agent 的记忆空间。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_04-skill-fusion-0196a3e0.jpg" alt="Skill 智能与代码的有机融合" loading="lazy"></p><p>当我们使用类似 OpenClaw 这样，具有一定持久化记忆能力的 Agent，或者是使用其他 Coding Agent 来辅助自己进行开发、写作等标准化的流程时，我们可能发现很多时候 Agent 对工具调用等过程，经常犯错；或是经常理解错误，需要人类反复确认。但这些又可以通过试错和调试来解决。<strong>在它反复尝试后终于解决问题的时候，上下文里面刚好包含了它完整的试错过程，对 Agent 来说，是一个完美的学习机会。</strong></p><p>使用方式：</p><p>因此我设计了一个 <code>/learn</code> 的命令，让 Agent 在完成某个任务后总结一下它在这个过程中学到了什么。使用时机可以是，当 Agent 经过多次试错终于解决问题时，或在每天空闲时段（如凌晨）让它总结当天经验。这个命令很简单，甚至不需要各种复杂的提示词技巧：</p><figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">请你深入分析，在前面试错过程中，可以总结哪些宝贵经验？请分别整理到Skill（如有对应）或项目的CLAUDE.md中，这样可以避免未来重复犯错。注意，如果这些文件中有层级引用结构的话，请按照对应的层级设计，放在合适的位置。</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><p>如果你有自己的一套记忆文件体系，也可以根据具体情况调整命令。如果使用 OpenClaw 这种长时间自主运行的 Agent，你甚至可以把这个命令设计成一个定时触发的任务，让 Agent 在每天空闲的时候（如凌晨 4 点），总结当天的经验。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_03-learn-cycle-6ba2f98c.jpg" alt="Agent 学习循环流程" loading="lazy"></p><h3 id="3️⃣-align-人与-Agent-的需求对齐"><a href="#3️⃣-align-人与-Agent-的需求对齐" class="headerlink" title="3️⃣ /align - 人与 Agent 的需求对齐"></a>3️⃣ <code>/align</code> - 人与 Agent 的需求对齐</h3><p>在使用 Agent 的过程中，经常会发现，有时 Agent 对你的需求的理解，并不完全准确。在大多数情况下，是因为你在和他交流的有限的上下文中，没有意识到，有一些对完成需求非常重要的信息，并没有传递给它。如果早发现这种现象还好，可以通过即时纠偏和补充信息，让 Agent 更好地理解你的需求；但如果没有发现的话，Agent 就可能会按照它的理解来完成任务，浪费了宝贵的时间和 Token。</p><blockquote><p>这背后有一个技术原因：在 LLM 的 RLHF 训练过程中，人类标注者通常更偏好”给出完整流畅的回答”而非”承认不知道”，<strong>这导致模型在不确定时倾向于强行完成任务，而不是主动澄清理解。</strong> 但在实际使用中，我们反而希望模型在理解不清晰时主动提问，而不是按照可能错误的理解去执行。</p></blockquote><p>作为用户来说，我们很难接触和干预模型的训练过程，我们应该思考的是，我们可以决定的那些事情中，可以如何更好解决这个问题呢？<strong>那就是在开始工作之前，就对齐好需求。</strong> 具体来说，我们可以在写 <code>prompt</code> 的时候尽可能写得详细一些，这当然是一个好习惯。但我认为，有一个更好的方式是，在 Agent 开始工作之前，就让它主动通过提问的方式，来确定它对这个任务的理解是否正确，以及人类有没有一些欠考虑的地方。这样的话，我们既可以比较轻松地通过回答问题的方式来对齐需求，也可以看到那些我们认知之外的，没有想到要交代给模型的部分，进一步增强了我们对 <code>Prompt</code> 设计的理解。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/compressed_05-align-concept-4778f8af.jpg" alt="需求对齐前后的对比" loading="lazy"></p><p>因此我设计了一个 <code>/align</code> 的命令，来让 Agent 在开始某个任务前，总结一下它对这个任务的理解，并且和我的需求进行对齐。使用这个命令后，Agent 会主动向你提出 2-3 个澄清问题，逐步确认对需求的理解，直到双方完全对齐后才开始执行。这个命令也很简单：</p><figure class="highlight markdown"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line"><span class="section">description: 与用户多轮交互澄清需求，直到完全对齐再执行。支持参数：/align &lt;粗略需求&gt;</span></span><br><span class="line"><span class="section">---</span></span><br><span class="line"></span><br><span class="line">你现在进入「需求对齐模式」（Alignment Mode）。</span><br><span class="line"></span><br><span class="line"><span class="section">## 核心规则（严格遵守）</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> <span class="strong">**绝不**</span> 直接开始实现或写代码、写文档、生成任何输出物。</span><br><span class="line"><span class="bullet">2.</span> <span class="strong">**唯一允许的行为**</span>：使用 AskUserQuestion 工具（或系统提供的提问工具）向用户提问，问那些你还不太明确，或者用户欠考虑的问题。</span><br><span class="line"><span class="bullet">3.</span> 问题要<span class="strong">**具体、聚焦、可回答**</span>（避免开放式大问题）。</span><br><span class="line"><span class="bullet">4.</span> 每轮收到用户回答后，<span class="strong">**立即**</span>：</span><br><span class="line"><span class="bullet">   -</span> 简短确认理解（1–2 句）</span><br><span class="line"><span class="bullet">   -</span> 判断是否还需要更多澄清</span><br><span class="line"><span class="bullet">   -</span> 如果还不够 → 继续问下一个最重要的问题</span><br><span class="line"><span class="bullet">   -</span> 如果已经足够清晰 → 输出最终的「对齐后需求总结」，然后问：“以上理解是否正确？可以开始执行了吗？”</span><br><span class="line"><span class="bullet">5.</span> <span class="strong">**对齐后需求总结**</span> 必须结构化，使用 markdown 格式，包含：</span><br><span class="line"><span class="bullet">   -</span> 目标（一句话）</span><br><span class="line"><span class="bullet">   -</span> 关键约束 / 非功能需求</span><br><span class="line"><span class="bullet">   -</span> 验收标准（用户最在意的 Done 定义）</span><br><span class="line"><span class="bullet">   -</span> 优先级 / 范围（what in / what out）</span><br><span class="line"><span class="bullet">   -</span> 任何已确认的假设</span><br><span class="line"><span class="bullet">6.</span> 整个过程保持<span class="strong">**礼貌、耐心、高效**</span>。目标是用最少轮次达到最高理解一致性。</span><br><span class="line"></span><br><span class="line"><span class="section">## 当前用户输入（原始需求）</span></span><br><span class="line"></span><br><span class="line">$ARGUMENTS</span><br><span class="line"></span><br><span class="line"><span class="section">## 第一步（现在立即执行）</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> 仔细阅读上面的 $ARGUMENTS</span><br><span class="line"><span class="bullet">-</span> 思考：最容易导致偏离、最模棱两可、最关键的 1–2 个点是什么？</span><br><span class="line"><span class="bullet">-</span> 使用 AskUserQuestion 工具提出<span class="strong">**第一个（或前两个）澄清问题**</span></span><br><span class="line"></span><br><span class="line">开始吧。</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><p>在未来对 Agent 布置需求性任务时，不妨都使用这个命令来开头，来让 Agent 先对齐需求。<strong>虽然可能会增加一些前期的沟通成本，但从数学期望上来看，应该是可以节省后续开发过程中潜在的时间、精力和金钱成本的。</strong></p><hr><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这三个命令分别解决了通知、记忆迭代和需求对齐三个核心问题。使用 <code>/align</code> 来事先对齐，减少返工；用 <code>/learn</code> 来利用宝贵的试错，为Agent积累经验；用 <code>/notify</code> 来降低自己内耗的部分或是节省时间，提高并行效率。</p><p>本文仅是抛砖引玉，希望可以为读者提供思路和启发。如果有一个命令，或者其中的思考对你有所启发，其目的就已达到。欢迎读者补充：还有哪些你认为比较有意思的、提升在与 Agent 交互时的“幸福感”的 Slash Command 呢？欢迎在评论区交流！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Agent 与提效本质之思考</title>
      <link>https://shiquda.link/agent-and-efficiency-thoughts/</link>
      <description>根据个人对多个Agent产品的使用体验，分析了Agent提效的核心思路，并且分享了一个基于OpenCode的写作提效流程。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/VibeCoding/">VibeCoding</category>
      <category domain="https://shiquda.link/tags/Agent/">Agent</category>
      <pubDate>Tue, 24 Feb 2026 07:58:20 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="Agent-与提效本质之思考"><a href="#Agent-与提效本质之思考" class="headerlink" title="Agent 与提效本质之思考"></a>Agent 与提效本质之思考</h1><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/agent-attention-closed-loop-hero-258ba516.jpg" alt="Agent 提效闭环与注意力回收示意图" loading="lazy"></p><h2 id="关于-Agent"><a href="#关于-Agent" class="headerlink" title="关于 Agent"></a>关于 Agent</h2><p>我们先来回顾一下什么是 Agent。</p><blockquote><p>Agent 通常可被视为能够自主完成任务的智能体：它可以根据环境变化做出决策，并在一定范围内学习和适应新情况。</p></blockquote><p>Agent 由 LLM 驱动，而后者通过深度学习算法与自然语言处理技术，利用目前人类生成的“符号”，如文字&#x2F;图像等，进行训练，然后通过推理来生成所需的文本。这意味着，Agent 自带的能力很大程度上是由 LLM 的能力决定的，而 LLM 的能力又可以看作是“对人类现有知识（的一部分）的拟合”。因此，Agent 其实具有一定程度的“智力”（注意，与“意识”相区分），这种智力实质上可以极大解放人类的认知负担和注意力资源，而善于利用 Agent 的人，则可能可以把这些宝贵的注意资源放在那些更加宝贵的任务上面去。</p><h2 id="提效的核心思路"><a href="#提效的核心思路" class="headerlink" title="提效的核心思路"></a>提效的核心思路</h2><p>基于前面的关于 Agent 概念的回顾，我们围绕“注意力解放”的思路来分析一下，当我们在使用 Agent 进行提效时，其核心思路有哪些？下面我总结了一些自己的思考，供读者参考：</p><h3 id="1️⃣-将交流中反复出现的表达需求进行标准化"><a href="#1️⃣-将交流中反复出现的表达需求进行标准化" class="headerlink" title="1️⃣ 将交流中反复出现的表达需求进行标准化"></a>1️⃣ 将交流中反复出现的表达需求进行标准化</h3><p>记得之前在网上看到某位大佬的一句话，大致意思是说：</p><blockquote><p>如果有一件事，提示词让你需要复用三次以上，那么就把它封装成一个 command。</p></blockquote><p>当我们和 Agent 进行交流的过程中，经常会发现有一些需求会反复出现的。例如，在 Coding Agent 里面有一个经常需要做的工作就是 <code>compact</code>，即压缩上下文对话。这个过程虽然在即将超过上下文上限的时候，会自动发生，但在实际的使用过程中，也会有手动压缩上下文的需求。这个时候，Coding Agent 如 Claude Code、OpenCode 等，将这个需求进行了标准化，通过简单的代称 <code>/compact</code> 这个 <code>slash command</code>，实际上大大减少我们在每次需要进行 <code>compact</code> 这个任务时所需要的认知负担和操作步骤。</p><p>设想一下，如果每次有这个需求，都要打一堆字和 Agent 交流，那么不仅麻烦，还会增加我们的注意力负担。</p><p>那你可能会说，我用打两个字压缩上下文，不是也能达到类似的效果吗？其实人与 Agent 进行交互的时候，二者经常存在一些认知上的不对齐。你的具体需求，未必能让 Agent 通过简简单单几个字就领悟得很清楚，这其实是提供的需求细节与执行效果直接的权衡问题。</p><p>而我们通过标准化的方式，实际上是把这个权衡做了一个优化，让我们在表达需求的时候，通过把场景需求标准化的方式，用短的命令引用大段的提示词描述。既能让 Agent 很清楚地理解我们的需求，又能让我们自己在表达的时候，减少不必要的认知负担和操作步骤。这种方式是比较理想的，也是最容易实现的。</p><h3 id="2️⃣-构建自主规划-执行-反馈的闭环"><a href="#2️⃣-构建自主规划-执行-反馈的闭环" class="headerlink" title="2️⃣ 构建自主规划-执行-反馈的闭环"></a>2️⃣ 构建自主规划-执行-反馈的闭环</h3><p>Agent 和纯对话进行交互的 LLM 相比，很大一个区别就是它可以依据给定的目标，自主利用提供的工具，与环境进行交互，并且可以根据工具执行的反馈，自主决策后续的行为，从而实现<strong>自主规划-执行-反馈</strong>的闭环（关于 <code>agent</code> 与 <code>workflow</code> 的区分，可参考 <a href="https://www.anthropic.com/research/building-effective-agents">Anthropic: Building effective agents</a>）。</p><p>举一个例子，约在 2023 年前后、以我个人使用体验来看，会有这样的场景：需要写一个脚本，我在网页版对话中向 LLM 说明需求，它帮我写了脚本。我将脚本复制粘贴到 VS Code 中运行，发现报错后又把报错反馈给网页版的 LLM，它给出可能的解决方案。我根据方案手动修改或直接复制完整代码重新尝试，如此重复直到脚本跑通并符合预期为止。</p><p>回顾上面的例子，我们可以看到，在这个过程中，人类的注意力资源分配到了哪些环节？</p><ol><li>告诉 LLM 我的需求</li><li>等待 LLM 生成脚本</li><li>把脚本复制粘贴到 VS Code 中</li><li>点击运行</li><li>等待运行结果，判断是否符合报错&#x2F;是否符合要求</li><li>如果不符合要求，反馈给 LLM。回到第 2 步。</li><li>结束</li></ol><p>而现在我们使用 coding Agent 的时候，人的注意力资源被分配到了哪些环节？</p><ol><li>告诉 Agent 我的需求<ol><li>Agent 生成脚本</li><li>自主测试，排查是否有报错</li><li>并尝试简单运行，初步判断是否符合需求</li></ol></li><li>等待 Agent 完成上述流程。如果 Agent 还没完成，继续观察等待</li><li>判断 Agent 的执行结果是否符合预期。如果不符合预期，反馈给 Agent，回到第 1 步。</li></ol><p>可以看到，在这个过程中，<strong>Agent 的自主规划-执行-反馈的闭环系统，极大地减少了人类在中间环节的注意力资源占用，让人类能够把更多的注意力资源放在核心的需求表达和功能验收上面去，而不是被那些机械重复的操作步骤和等待时间占用掉</strong>。这些看起来是非常简单的任务，但是其实也需要占用一定的注意力资源。如果人的注意力资源都分配到这种繁杂的工作上，那么很快一天能用的注意力资源就会大大缩水。</p><p>我们现在使用 Coding Agent 时，实质上相比 LLM 增加了<strong>执行</strong>以及<strong>反馈</strong>的能力。传统的复制粘贴方法，只使用了 LLM 的规划能力和编写代码，而实际代码执行和反馈部分都由我们进行，链路中执行、反馈两个并没有打通，无法形成闭环。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/agent-loop-attention-comparison-db43a602.png" alt="传统 LLM 与 Coding Agent 在注意力占用上的差异" loading="lazy"></p><p>而最近一年，Agent 生态开始慢慢变得成熟如开发过程体验已经做得比较好了。有很多原来的环节已经形成了闭环，在效率上实现了质的提升。但在其他一些领域，甚至 Coding 领域本身，还有很多一些环节做得不够好，我们可以和 Agent 一起打通整个规划-执行-反馈的闭环，让这个过程更加自动化，节省我们宝贵的注意力资源。</p><p>举个例子，现在在写作的时候，其实是有一些重复性的需求可以做的。一篇比较正式的文章的产出，可能会经历下面几个阶段：</p><ol><li>选题确定</li><li>大纲构思</li><li>文章撰写</li><li>文章润色（格式优化、错别字语病纠正）</li><li>文章配图</li><li>文章发布</li><li>文章数据监测</li></ol><p>上面只是一个简单的设想，每个人会有不同的流程。但不管怎么样，我们在这个过程中，可能会发现有一些环节是比较机械重复的，例如文章润色、文章配图、文章发布、文章数据监测等，这些环节其实是非常适合 Agent 来做的。我们可以通过一些工具的打通，让 Agent 来帮我们完成这些环节的工作，从而让我们把注意力资源更多地放在选题确定、大纲构思、文章撰写这些更需要创造力和思考的环节上面去。</p><p>我最近正在研究的一件事情是，利用 Coding Agent 来帮我搭建一个专门用于文章撰写的仓库，把重复动作尽量沉淀成”可复用命令 + 可复用脚本”。换句话说，我的目标不是让 Agent 帮我”写观点”，而是让它帮我稳定处理那些可流程化的环节。</p><p>我最初使用的是 OpenCode，后来迁移到了 Claude Code。选择 Claude Code 的原因主要是：它自带的权限检查和更改预览机制比较适合这种需要自己 review 的场景；与 VS Code 的集成也很好，可以直接在编辑器里选中文章段落让 Claude Code 修改，实现 90% 不离开 VS Code 就能完成操作。</p><p>不过，<strong>选用什么 Coding Agent 并不重要，重要的是这套处理日常工作流的思路</strong>。这种思路可以拓展到写作以外的任何领域：对于那些需要长期重复完成的智力型任务，如果能用 Agent 将其自动化，那么用得越多，节省下的注意力资源就越多，复利效应会越来越明显。</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/agent-writing-workflow-closed-loop-409837a7.png" alt="写作场景下的闭环提效流程" loading="lazy"></p><p>这里给一个我目前正在探索的写作提效流程，下面有请 OpenCode 进行介绍：</p><blockquote><p>在进入具体步骤前，先把这条 OpenCode 流水线的“入口和边界”说清楚：</p><ol><li>入口分成两段：先用 <code>/polish @doc/article/xxx.md</code> 跑完“格式化 → 事实核查 → Markdown 增强 →（按需）配图”，再用 <code>/publish @doc/article/xxx.md</code> 生成发布版并把本地图片替换为可发布的 CDN 链接。</li><li>细粒度能力由原子 skill 负责：<code>format</code> 只做中英数间距，<code>fact-check</code> 负责抽取可核查陈述并给来源与改写建议，<code>markdown-enhance</code> 做轻量标注增强，<code>illustrate</code> 负责生成配图资产。</li><li>脚本与 Agent 有明确分工：<code>tools/</code> 里的 Python 脚本负责稳定执行（格式化、渲染、上传等），不做语义判断；语义决策与取舍仍由 Agent + 人类验收共同完成。</li><li>流程执行上优先“并行化非阻塞检查”：像格式检查、链接核验、素材准备这类不阻塞主线的任务，尽量后台并行，最后统一汇总，避免主线程被低价值等待占满。</li></ol><p>下面这三张截图，分别对应这条流程里“编排入口、事实核查改写建议、工作区差异验收”三个关键触点：</p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/opencode-polish-5e2e5b70.png" alt="OpenCode 润色流程入口示意" loading="lazy"></p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/opencode-fact-check-suggestion-4f710ade.png" alt="事实核查后改写建议示意" loading="lazy"></p><p><img src="https://cdn.jsdmirror.com/gh/shiquda/images@main/imgs/doc-workspace-git-diff-showcase-e3aaba7d.png" alt="文稿工作区差异验收示意" loading="lazy"></p></blockquote><blockquote><p>1 <strong>先做格式一致性处理（降噪）</strong></p><ul><li>用 <code>python tools/quick_format.py &lt;draft.md&gt;</code> 对草稿做中英数间距标准化。</li><li>如果我只想先看差异，不直接覆盖，就跑 <code>python tools/quick_format_check.py &lt;draft.md&gt;</code> 生成预览稿。</li><li>这一步的价值很直接：先把低价值但高频的排版动作清掉，避免我在后续修订时被格式噪音打断。</li></ul><p>2 <strong>再做内容层修订（事实、论据、表达）</strong></p><ul><li>事实核查用 <code>/fact-check</code>，重点盯时间、数据和来源链路。</li><li>论据补强用 <code>/strengthen</code>，让 Agent 补证据、补反例或补边界。</li><li>综合修订用 <code>/revise</code>，统一语气、读者对象和篇幅约束。</li><li>这一步本质是把“我反复口头说明的修订要求”标准化成 slash command，减少沟通磨损。</li></ul><p>3 <strong>做一次轻量标注增强（不改原意）</strong></p><ul><li>用 <code>markdown-enhance</code> 审阅文章，对技术词、命令、路径等补充反引号。</li><li>对关键判断句做适度加粗；若确有必要，再补 1-3 个外部参考链接。</li><li>原则是宁缺勿滥：非必要不改句式，不改观点，不改结论。</li></ul><p>4 <strong>最后做配图与发布前资产准备</strong></p><ul><li>配图链路使用 <code>skill(&quot;illustrate&quot;)</code> 和 <code>tools/illustrate.py</code>，密钥统一从 <code>.env</code> 读取。</li><li>如果文章里有流程图，再走 <code>tools/mermaid_render.py</code> 输出高清图，避免手工截图导致分辨率不稳定。</li><li>到这一步，基本可以把注意力收回到“信息是否准确、观点是否成立、结构是否清晰”这三个核心问题上。</li></ul><p>这里要强调一个边界：<code>tools/</code> 里的脚本只负责格式化和资产处理，不做内容判断；内容判断仍然交给 Agent 的检索与推理链路。也就是说，脚本负责稳定执行，Agent 负责语义决策，人类负责最终验收。</p><p>因此，这套做法真正解决的不是“省几分钟操作”，而是把注意力从机械步骤中抽离出来，持续投入到选题、论证和表达这些高价值环节。只要这个闭环跑顺了，写作提效才是可持续的。</p></blockquote><p>当然，这个流程只是我目前的一个初步探索，未来还会不断迭代优化，例如添加各个平台的自动发布（个人博客、各论坛、Telegram 群组、小红书、x 等）。</p><p>在其他不同领域，也会存在类似的问题，我们按照打通上述三个<strong>规划-执行-反馈</strong>流程闭环的思路思考和分析这些工作，并进行交互与迭代，相信会节省很多宝贵的注意力资源。</p><h3 id="3️⃣-使用推送模式而不是轮询方式"><a href="#3️⃣-使用推送模式而不是轮询方式" class="headerlink" title="3️⃣ 使用推送模式而不是轮询方式"></a>3️⃣ 使用推送模式而不是轮询方式</h3><p>在日常生活中，我自己会有一些所谓的“信息焦虑”的情况。对于那些我感兴趣的信息，我会不断刷新查看，总想着最早得到最新的信息。为此我之前还专门写了<a href="https://github.com/shiquda/status_view">一个工具</a>（练手软件，不推荐使用，且后文有更好解决方案），方便统一查看各个平台分散的信息。但是后来我发现，很多时候，当信息产生变化时，有一个 <code>hook</code> 能够以合理的方式通知我，就没必要花这么多注意力资源去不断查看了。</p><p>例如聊天软件就是这样的特征，当别人给你发消息时，手机会监听到消息并通过声音或震动告知你，你再进行查看即可。我们把这两种现象进行<strong>抽象</strong>，结合从之前开发过程中了解到的 Telegram 机器人的两种工作模式，即 <code>polling</code> 与 <code>webhook</code> 得到的灵感，可以将这两种模式简单归纳为<strong>轮询</strong>和<strong>推送</strong>（可参考 <a href="https://core.telegram.org/bots/webhooks">Telegram 官方 Bot API 文档</a>）。</p><p>我们的目的是<strong>尽可能用“推送”的方式，把那些值得我们关注的信息，在真正发生变化的时候通知我们，而不是靠我们不断“轮询”来查看是否变化</strong>。</p><p>比如以我当前使用配置中的 OpenClaw 为例（具体能力以版本与文档为准），我让它做了很多定时任务：每天帮我收集关注的 RSS 信息源、软件更新版本、市场价格变动等一系列我感兴趣的消息，时间间隔可设为每天、每半天或其他任意时长，然后总结推送给我。这样我就不用每天打开电脑或手机就想着去查看它们的数据及最新变化，而可以把宝贵的注意力资源放在更值得做的事情上。</p><p>从技术上来讲，OpenClaw 也是使用定时轮询的方式来做的。但是这就是 Agent 这个代理帮我们解放注意力资源所在。我们只需要和它进行交互即可，它帮我们轮询去查找信息，我们在值得被通知的时候被推送消息就行了。<strong>换句话说，把“轮询动作”交给 Agent，本质上是在回收人类注意力。</strong></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>在这个节奏越来越快，信息越来越碎片化的时代，Agent 的出现为我们提供了一个非常有价值的工具，可以帮助我们解放注意力资源，让我们把更多的注意力放在那些真正重要和有价值的事情上面去。一个人的注意力资源是每个人最为宝贵的资源之一，善于利用 Agent 的人，才能够在这个时代更好地生存和发展。</p><hr><blockquote><p>本文使用我的<code>doc agent</code>辅助创作，Powered by OpenCode。部分图片使用 AI 生成。</p></blockquote>]]>
      </content:encoded>
    </item>
    <item>
      <title>我目前的Vibe Coding工作流（Via Phone）</title>
      <link>https://shiquda.link/my-mobile-vibe-coding-workflow-2026-02/</link>
      <description>简单分享一下个人的基于移动设备的OpenCode Vibe Coding的工作流。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/VibeCoding/">VibeCoding</category>
      <pubDate>Fri, 20 Feb 2026 12:57:16 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Vibe Coding，相信读者都应该清楚其概念。简单的Vibe Coding方式需要你持续端坐在电脑前面，和那些TUI或者GUI页面进行交互。交互的本质其实很简单，人与Agent之间的交互都可以规约于<strong>文字</strong>，或许再添加一个可选的<strong>图像</strong>。而这两部分，并不必须要求你使用电脑与其交互，电脑实质上只是提供了一个供程序运行的环境。也就是说，技术上来说，我们完全可以在交互这一流程脱离电脑，使用更加方便的手机进行交互。这一理念在之前的文章（好久之前，或许是去年了）也有介绍。</p><p>最近把Coding Agent换成了OpenCode，下面补充一下目前我使用的一套还算顺手的OpenCode流程。</p><h2 id="主要方法"><a href="#主要方法" class="headerlink" title="主要方法"></a>主要方法</h2><p>有一种方法最为简单，即利用远程控制软件，用手机远程控制电脑完成任务。但这一步实际上违背了我们前面的初衷，没有利用手机便捷易操作的特性，转而还是使用类似电脑的方式来进行操作。这种方法仅在应急或不需要经常操作的情况下推荐使用。</p><p>opencode其实不仅只能通过像Claude Code的TUI来进行交互，它还允许用户通过<code>opencode web</code>的方式启动一个服务器，并且官方还自带一个精简的前端（似乎也是桌面端应用所用的）来和后端进行交互。更惊喜的是，通过这种方式进行交互，从我的体验反馈来看，自定义的插件（如OMO，oh-my-opencode）都工作良好。</p><p>因此一种最简单的方式是，在电脑上运行一个绑定到可被远程访问的ip上的服务器，然后在远程进行访问即可。如果在家中，想要使用手机操控非常简单，因为WLAN局域网直接将手机和电脑进行组网，只要电脑保持打开，运行服务器后，手机就可以打开浏览器访问了。官方自带的基本前端看似简陋，但实际用下来常用的功能有95%可以使用手机代替了。唯一不太方便的是涉及到一些需要我们在电脑上当作用户来验收成果的时候，这种情况下还是建议使用电脑来进行操作。</p><p>对于我们人和电脑不在一个WLAN的情况下，我们还可以使用Tailscale等软件，进行远程组网。只需要在电脑和移动设备上都安装Tailscale软件，并且添加到一个网段里面，在手机上就可以实现远程访问了。更近一步，如果你在一些远程主机上也有OpenCode进行开发的需求，也可以把这些机器使用Tailscale组网。这里仅提供一个思路，具体配置方法相信对读者来说不是问题，希望思路对您有所启发。</p><p>对于Windows，你可以参考我编写的一个<code>.bat</code>脚本，可以以一个命令启动服务器，使之可以用远程进行访问。出于安全的原因，建议设置访问密码。设置完成后，浏览器打开相应地址输入密码的时候，用户名默认为<code>opencode</code>。</p><figure class="highlight bat"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line"><span class="built_in">set</span> OPENCODE_SERVER_PASSWORD=&lt;password&gt;</span><br><span class="line">opencode web --hostname <span class="number">0</span>.<span class="number">0</span>.<span class="number">0</span>.<span class="number">0</span> --port &lt;your-port&gt;</span><br></pre></td></tr></tbody></table></figure><p>运行脚本即在后台启动服务器，手机就可以连接了。</p><p>更近一步，我最近发现了一个第三方的开源<a href="https://lehhair.github.io/OpenCodeUI/">OpenCode WebUI</a>，整体体验更加美观好用，但目前还处于早期开发阶。该WebUI不需要单独部署，在里面填入上面一步部署的后端地址就可使用。注意对于一些后端实例可能需要在命令中添加<code>--cors "https://lehhair.github.io"</code> 来解决CORS跨域问题，感兴趣的读者可自行体验。</p><p>上述主要是思路和经验分享，具体技术细节和安全问题请读者自行查阅与调研。</p><h2 id="后记（碎碎念）"><a href="#后记（碎碎念）" class="headerlink" title="后记（碎碎念）"></a>后记（碎碎念）</h2><p>许久未和读者见面了，之前几个月其实有很多所见所思未能分享。这篇文章是纯手写的，在AIGC泛滥的当下，还是想真正给互联网贡献一些更有价值和思考的内容。并不是说用AI辅助写出来的文章就没有可读性。之前一直在怀疑动手写文章的必要性，因为似乎让Agent帮你按照思路生成一篇文章是更加方便的事情，也因此好几个月没有写博客的打算。后来我发现写文章并不是只是为了读者，更是为了自己能把一些事情想得更加深入和透彻，在动手的过程中，思路更加清晰了。再不济，也未尝为一种娱乐与体验。或许之前被称为“工作”的东西，在未来大多会成为一种“娱乐”或“艺术”。请允许我这次更多地为自己而写。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>用朴素数学视角为人生“建模”——浅析人力资源的不可再生性与复利的运用</title>
      <link>https://shiquda.link/try-to-model-my-life/</link>
      <description>试图用朴素的数学模型为人生“建模”。讨论了人力资源（时间+注意力）以及复利性的规律。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E9%9A%8F%E6%83%B3/">随想</category>
      <pubDate>Fri, 29 Aug 2025 03:36:53 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="建模"><a href="#建模" class="headerlink" title="建模"></a>建模</h2><h3 id="人力资源——不可再生性"><a href="#人力资源——不可再生性" class="headerlink" title="人力资源——不可再生性"></a>人力资源——不可再生性</h3><p>一个人最宝贵的资源是他的时间和精力（精力也可称为注意力）。我们把这种最宝贵的资源称作<strong>人力资源</strong>。他之所以宝贵，是因为至少从目前看来，一个人终究会死的，这意味着他一生中可支配的<strong>人力资源</strong>有一个上界。有些人或许活的更久，有些人看起来精力更旺盛，但终究拥有一个不可逾越的上限。</p><p>人力资源的最本质特征是<strong>不可再生性</strong>。和不可再生资源类似，我们只能通过<strong>节省开支</strong>的方式来变相“扩容”它。换句话说，我们追求的是尽可能把人力资源花费在我们生命中那些真正重要的事情上，而不是那些为了满足生活必须的事情上。</p><blockquote><p><strong>某个人再也不用为了满足生活必需而出售自己的时间</strong>。——李笑来《财富自由之路》</p></blockquote><h3 id="复利性的事物"><a href="#复利性的事物" class="headerlink" title="复利性的事物"></a>复利性的事物</h3><p>与之相反的是具有复利性质的事物，如资本。形式化的，我们可以用一个简单的数学公式来描述这种性质：</p><p>$$<br>k(1+c)^x<br>$$</p><p>其中k代表初始值，c代表在一定时间单位内的平均增长率，x代表时间。</p><p><strong>复利的本质，是事物的产出可以补充到其投入</strong>。</p><p>这一性质非常关键。例如，在投资上，我们的资产会随着时间的持续而如“滚雪球”一般越滚越大，投资的收益又作为本金，持续扩大规模。</p><blockquote><p>往大一些说，智人之所以为智人，区别于其他动物的重要原因，我认为其一是脑器官的进化使得人类的符号化的抽象思维得以成熟，这让我们被称为“知识”的东西得以在种群中跨个体、跨代际的积累和发展。<br>别小看这一点，这种性质构造了一个“复利”性质，即智人的知识<strong>产出</strong>得以持续回馈到<strong>投入</strong>之中，使得整体知识不断进行指数级别的积累。这使得生物界的进化方式得以摆脱了<strong>基因</strong>这种近乎于<strong>线性变化</strong>的节奏，以指数级的速率发展。30万年的发展历程对于地球的生物圈的30多亿年来说是惊鸿一瞥，但人类利用此复利结果，达到了前所未有的成就，且我们明显的发现这个速度越接近近现代，越来越快，以至于我们的生理进化远远落后于我们的知识。这便是复利性的强大力量。</p></blockquote><p>考虑一下具有复利性事物的增量。我们对时间x进行求导，会发现求导的结果仍然是一个指数函数：</p><p>$$<br>k\ln(1+c)(1+c)^x<br>$$</p><p>这意味着，<strong>即使复利本身的增长率不变，随着时间的推移，增量也会越来越大</strong>。只要初始值足够大，且维持住复利的状态，我们无须努力改变c，也可以获得一个可观的、持续增长的增量。</p><p>但人力资源则恰恰相反。设人的一生所拥有的人力资源总量为$I_{all}$，需要花费在用于满足生活必须的人力资源总投入为$I_{necessary}$，那么我们可以朴素的将I拆解为两部分：</p><p>$$<br>I_{necessary} &#x3D; a x + b<br>$$</p><p>其中x同样代表时间，a代表<strong>长期投入分量</strong>，b代表<strong>短期投入分量</strong>。长期投入分量，是我们一生中每天都需要花费的量，具有持续性；短期投入分量，则是在少数时间中一次性投入的量，不具有持续性。</p><p>我们追求的是把尽可能多的可自由支配的人力资源$I_{free}$放在我们真正关心的事情上。我们先考虑那些可自由支配的人力资源$I_{free}$：</p><p>$$<br>I_{free}<br> &#x3D; I_{all} - I_{necessary} &#x3D;  I_{all} - ax - b<br>$$</p><p>同样对其求导，可以发现结果为-a。这意味着，如果我们可以尽早降低a的值，即那些具有持续性的、每天都要重复做的投入，那么我们的可自由支配的人力资源将会大大提升。哪怕这是通过以提高短期投入分量b为代价得到的，只要将来的时间x足够多，我们也可以获得更多的$I_{free}$。</p><p>这么说可能有些抽象，我们举一个简单具体的例子来辅以说明。假如说一个人的个人物品到处杂乱堆放，每次需要找东西的时候都需要消耗好多时间来进行查找，有时甚至还找不到，得重新购买。可以遇见的是，如果这样的状态持续下去，根据大数定律，他一定在未来的某些时间又要花额外的时间来做类似的事情，这使得原本潜在的$I_{free}$转换为了$I_{necessary}$。</p><p>但如果他某一天决定彻底收拾一下自己的个人物品，使用收纳柜将它们分门别类，并且在后续坚持这么维护这种状态，那么实际上是把原来被占用的$I_{necessary}$中的长期分量a部分转移成了短期分量b。这么做之后，长期来看一定是节省了潜在的人力成本的。</p><p>这也是人们老生常谈的“<strong>养成一个好习惯</strong>”的重要性，在该数学模型下的一种解释。长期来看，一个好习惯能够持续的为你节省潜在的人力成本。</p><h2 id="由此自然推导出的结论"><a href="#由此自然推导出的结论" class="headerlink" title="由此自然推导出的结论"></a>由此自然推导出的结论</h2><p>考虑增大$I_{free}$，我们可以以下面几种思路入手：</p><ol><li>增大$I_{all}$。包括尽可能保持生命的长度，以及每天的人力“利用率”。<ol><li>生命的长度，可通过保持一个健康的身体实现。健康的身体也能在一定程度上提高人力的利用率。</li><li>另外，有一个优秀的人力资源分配机制，能提高人力资源的利用效率。</li></ol></li><li>减少$I_{necessary}$。<ol><li>尽可能降低a的值。这可以通过：<ol><li>提升完成工作的效率。可通过技能的不断娴熟实现。如提升拧螺丝的效率。</li><li>通过一种<strong>系统性的优化</strong>，以一定的短期分量b的提升为代价，将尽可能多的a降低。如通过设计一种物品收纳的方式，降低长期取用所花费的人力成本。</li></ol></li></ol></li></ol><p>对于<strong>复利性</strong>的事物，如<strong>财富、认知和人脉</strong>，应该尽可能早的开始积累，并且保持一个能获得长期复利的状态。这些复利性的资源能够帮助减少我们的$I_{necessary}$。</p><p>另外，我们期望所拥有的$I_{free}$可以被更高效的用于追求那些我们真正感兴趣的事情，因此，找到我们人生意义感，搞明白哪些事情是我们真正感兴趣的也是非常重要的。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>如何用手机指挥Claude Code干活</title>
      <link>https://shiquda.link/how-to-control-claude-code-with-phone/</link>
      <description>利用claudecodeui + Cloudflare Tunnels 实现，可用Zero Trust增加安全性。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <pubDate>Sat, 16 Aug 2025 14:58:37 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>我们使用Claude Code时，正常需要通过命令行与其交互，但这往往要求我们需要在一台电脑前待着。</p><p>思考一下，我们与Claude Code的交互，实质上只是两种：</p><ol><li>输入文本；</li><li>选择批准或者拒绝操作。</li></ol><p>事实上，要实现和它的交互，我们完全不必使用电脑。也就是说，理论上我们完全可以只使用手机，以一种方式连接到电脑，实现交互。</p><p>这么说来，已经有一种现成的朴素方法：通过手机远程控制电脑，然后和Claude Code进行交互。但这种朴素方法在交互时有所不便，例如输入文字的输入法问题、选择批准/拒绝时需要使用方向键等。</p><p>如果在移动设备上有用户友好的应用，或是使用一个类似vscode的server版本，那么体验就会好很多。</p><p>带着这个思路，我先找到了<a href="https://github.com/sugyan/claude-code-webui">claude-code-webui</a>这个项目，该项目可以网页的形式和Claude Code进行交互，但目前还没有鉴权功能，试用下来较为简陋。</p><p><img src="https://s2.loli.net/2025/08/16/Sd6YUB79NOufGCg.png" alt="PixPin_2025-08-13_18-07-42" loading="lazy"></p><p>又找到了<a href="https://github.com/siteboon/claudecodeui">claudecodeui</a>这个项目，看起来完成度就好很多。</p><p><img src="https://s2.loli.net/2025/08/16/OdphNq8jilf2ayx.png" alt="desktop-main" loading="lazy"></p><p>那么剩下的就是网络配置上的问题了。我的需求是，即使和我的电脑不在一个局域网内，也能可以连接在我电脑上运行的该服务。</p><p>我想到了Cloudflare Tunnels，可用于打洞，再通过Cloudflare绑定自己的域名即可实现远程访问。</p><blockquote><p>Cloudflare Tunnels 是由 Cloudflare 提供的免费服务，可用于安全地将本地或私有网络中的服务暴露到公网，而无需开放防火墙端口、配置公网 IP 或使用反向代理（如 Nginx）。</p></blockquote><h2 id="前置要求"><a href="#前置要求" class="headerlink" title="前置要求"></a>前置要求</h2><p>想要和我一样远程指挥Claude Code干活，需要以下前置条件：</p><ol><li>电脑本地可用的Claude Code；</li><li>一个绑定在Cloudflare上的域名。</li></ol><h2 id="详细教程"><a href="#详细教程" class="headerlink" title="详细教程"></a>详细教程</h2><h3 id="安装claude-code-webui"><a href="#安装claude-code-webui" class="headerlink" title="安装claude-code-webui"></a>安装claude-code-webui</h3><p>首先确保已安装<strong>Node.js 20</strong>。</p><p>克隆项目：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/siteboon/claudecodeui.git</span><br></pre></td></tr></tbody></table></figure><p>安装依赖。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install</span><br></pre></td></tr></tbody></table></figure><p>启动服务器</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run dev</span><br></pre></td></tr></tbody></table></figure><p>此时在本地访问<code>localhost:5173</code>即可测试是否可以在网页中正常使用Claude Code。初次使用是需要设置一个唯一的用户名和密码。</p><p>一切正常后，我们继续配置。</p><h3 id="Cloudflare-Tunnels配置"><a href="#Cloudflare-Tunnels配置" class="headerlink" title="Cloudflare Tunnels配置"></a>Cloudflare Tunnels配置</h3><blockquote><p>Cloudflare Tunnels 是由 Cloudflare 提供的免费服务，可用于安全地将本地或私有网络中的服务暴露到公网，而无需开放防火墙端口、配置公网 IP 或使用反向代理（如 Nginx）。</p></blockquote><p>前往<a href="https://one.dash.cloudflare.com/">one.dash.cloudflare.com</a>，转到<code>网络 &gt; Tunnels</code>，点击创建隧道，选择Cloudflared类型。名称可任意填写。</p><p><img src="https://s2.loli.net/2025/08/16/DZEkAmrh89xcKQg.png" alt="PixPin_2025-08-13_17-20-10" loading="lazy"></p><p>配置时，按照说明下载cloudflared命令行工具。下载后，注意<strong>使用管理员权限</strong>运行提示的命令。连接成功后，网页下方应该会显示已连接的连接器。</p><p>下一步，第一行填写的是需要选择你的域名，第二行选择本地服务的URL（注：url注意选择你本地的端口，默认为<code>5173</code>）。</p><p><img src="https://s2.loli.net/2025/08/16/1At6o4xWc8GuZBU.png" alt="PixPin_2025-08-13_17-21-43" loading="lazy"></p><p>这一步完成后，在手机上访问你配置的域名，应该就能正常访问服务了。</p><h3 id="Cloudflare-Zero-Trust（可选）"><a href="#Cloudflare-Zero-Trust（可选）" class="headerlink" title="Cloudflare Zero Trust（可选）"></a>Cloudflare Zero Trust（可选）</h3><p>由于现在该域名直接通过Cloudflare Tunnels直接连接到电脑，且该项目是一个较新的项目，可能存在潜在的安全问题。我们还可以给服务添加外部鉴权，通过配置Cloudflare Zero Trust进一步加强安全。</p><blockquote><p>注意，这一步需要先完成Free Plan的支付方式认证。博主使用国区PayPal可成功绑定。</p></blockquote><p>前往Access &gt; 应用程序，选择创建。</p><p><img src="https://s2.loli.net/2025/08/16/z3nPUv241gCIaM6.png" alt="PixPin_2025-08-13_17-26-29" loading="lazy"></p><p>公共主机名填写前面的域名。</p><p><img src="https://s2.loli.net/2025/08/16/xB5WfaQ3NXHZhjv.png" alt="PixPin_2025-08-13_17-28-01" loading="lazy"></p><p>接下来需要添加策略，这里我选择的是使用邮箱验证，值填写你的邮箱即可。</p><p><img src="https://s2.loli.net/2025/08/16/SCijbnf2D1JrEuA.png" alt="PixPin_2025-08-13_17-30-56" loading="lazy"></p><p>返回在创建的应用程序中，选择该策略。这样在访问域名的时候，需要先向你的邮箱发送一个验证码，才能访问。</p><p><img src="https://s2.loli.net/2025/08/16/mtGlDRxXw3bqyLj.png" alt="PixPin_2025-08-13_18-05-39" loading="lazy"></p><p>现在就可以在手机上指挥Claude Code了。</p><p><img src="https://s2.loli.net/2025/08/16/z5xYmXWIchyNVsJ.jpg" alt="Screenshot_20250816_231401_mark_via_gp_Shell" loading="lazy"></p><p>在下方可以切换模式，包括自动接受编辑、Plan mode和Bypass permissions（跳过权限检查）等模式。</p><p>Cloudflare的Tunnels在电脑本地会以守护进程的方式自启动，当需要远程使用的时候，使用<code>npm run dev</code>启动项目即可。有需要的话，读者也可以自行设置项目的自动启动。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>在本地调试Github Actions</title>
      <link>https://shiquda.link/run-github-actions-locally/</link>
      <description>利用act和Docker，在本地实现Github Actions的运行</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Tue, 10 Jun 2025 11:29:57 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我们在开发GitHub Action的CI时，经常遇到需要进行调试的情况，毕竟如果是从零开始写一个workflow，难免会遇到一些意料之外的问题。</p><p>本教程主要使用<code>act</code>，实现在本地运行Github Actions的目的。<a href="https://nektosact.com/">Act</a>是一个开源的工具，它可以解析项目中的<code>.github/workflows/</code> ，并利用Docker API拉取或者构建必要的镜像，根据执行顺序完成任务。环境变量和文件系统均配置为与 GitHub 提供的环境一致。</p><h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><p>博主使用的环境是Windows。若你使用的系统不同，请参考<a href="https://nektosact.com/installation/index.html">Installation - act - User Guide | Manual | Docs | Documentation</a> 完成环境配置。</p><p>大致来说，Windows 和 MacOS 系统需要配置Docker Desktop，Linux需要安装Docker Engine。除docker之外，还需要安装<code>act</code>。</p><p>对于Act来说，如果使用Windows，可以直接通过<code>scoop install act</code> 的方式来安装，也可使用winget。具体可用的包管理器，也可参照<a href="https://nektosact.com/installation/index.html">Installation - act - User Guide | Manual | Docs | Documentation</a>。</p><p>如果你使用VSCode进行开发，VSCode还有一个名叫GitHub Local Actions的插件，可以方便的利用图形界面进行调试。</p><h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><p>如果使用VSCode，使用Github Local Actions进行调试即可，图形界面非常好理解。</p><img src="https://s2.loli.net/2025/06/10/ryX1udSElpHoM6f.png" alt="Pasted image 20250610193116" width="200" /><p>下面主要介绍一下命令行的使用方式。</p><p>在第一次运行的时候，Act可能会提示你选择模拟环境需要的镜像。</p><p><img src="https://s2.loli.net/2025/06/10/rCEPqV4Gs5Yz9Qn.png" alt="Pasted image 20250610193137" loading="lazy"></p><p>选择Large可以完整模拟Github托管的Runner的环境，但该镜像较大，需要75GB空间，如无必要选择默认的Medium即可。</p><p><code>act</code>支持基本的<strong>事件</strong>。也就是说，你可以通过模拟像<code>push</code> <code>pull_request</code> 这样的<a href="https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows">事件</a>，触发相应的工作流进行调试。例如，你的仓库有一个由<code>pull_request</code> 触发的测试工作流，那么你只要执行<code>act pull_request</code> ，即可进行测试。</p><p>还可以通过<code>act -W &#39;&lt;path-to-workflow&gt;&#39;</code> 指定单个工作流进行运行。</p><p>更多使用方法，请查看<a href="https://nektosact.com/usage/">官方文档</a>。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>给命令行中的Android sdkmanager配置代理</title>
      <link>https://shiquda.link/command-line-android-sdkmanager-proxy/</link>
      <description>给命令行中的Android sdkmanager配置代理</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/Android/">Android</category>
      <pubDate>Mon, 28 Apr 2025 07:26:19 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><h3 id="方法一：临时命令行方案"><a href="#方法一：临时命令行方案" class="headerlink" title="方法一：临时命令行方案"></a>方法一：临时命令行方案</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sdkmanager --verbose --no_https --proxy=http --proxy_host=&lt;host&gt; --proxy_port=&lt;port&gt; <span class="string">"&lt;package&gt;"</span></span><br></pre></td></tr></tbody></table></figure><p>其中</p><ul><li><code>proxy_host</code>填写代理主机，本地填<code>127.0.0.1</code></li><li><code>proxy_port</code>填写代理端口。</li><li>最后跟上需要安装的依赖</li></ul><h3 id="方法二：永久修改方案（需要修改bat）"><a href="#方法二：永久修改方案（需要修改bat）" class="headerlink" title="方法二：永久修改方案（需要修改bat）"></a>方法二：永久修改方案（需要修改bat）</h3><p>博主使用的是Windows环境，其他系统应该类似。</p><ol><li><p>定位文件：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Windows</span></span><br><span class="line">%ANDROID_HOME%\cmdline-tools\latest\bin\sdkmanager.bat</span><br></pre></td></tr></tbody></table></figure></li><li><p>找到 <code>%CMD_LINE_ARGS%</code> 所在行，在文件末尾附近，以<code>"%JAVA_EXE%" %DEFAULT_JVM_OPTS%</code>开头</p></li><li><p>修改为：</p></li></ol><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"%JAVA_EXE%"</span> %DEFAULT_JVM_OPTS% %JAVA_OPTS% %SDKMANAGER_OPTS% -classpath <span class="string">"%CLASSPATH%"</span> com.android.sdklib.tool.sdkmanager.SdkManagerCli --verbose --no_https --proxy=http --proxy_host=&lt;host&gt; --proxy_port=&lt;port&gt; %CMD_LINE_ARGS%</span><br></pre></td></tr></tbody></table></figure><p>注意修改里面的相关参数。</p><p>这样配置以后，每次在命令行中使用<code>sdkmanager</code>之后就会自动使用代理了。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Chain Message：利用区块链打造一个的无法被篡改的留言页面</title>
      <link>https://shiquda.link/chain-message-immutable-message-board/</link>
      <description>利用区块链打造一个的不可被篡改的留言页面</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/">区块链</category>
      <pubDate>Sun, 20 Apr 2025 14:50:23 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我对学习一项新技术的最低标准是：“入门”。在我看来，达到所谓的入门，需要两方面的能力</p><ol><li><strong>对该领域的的核心概念有一定的理解</strong>，至少说听业内人士提到某个概念，能大概明白是什么；</li><li><strong>进行实践</strong>，利用自己掌握到的知识，能够自己动手完成一个像样的作品。</li></ol><p>最近我对<strong>区块链技术</strong>比较感兴趣，学习了核心概念后，想着用它来做点什么。我在寻思用什么项目来检验我的入门水平的时候，突然想到了留言板这么一个idea。</p><p>传统的留言板大多都是基于<strong>中心化</strong>的服务来实现的，这意味着，控制这个中心化的人可以将其他用户的留言进行删除或者是篡改。但是如果说我们能够利用区块链几乎不可能被篡改的能力，将用户的留言发送到链上，并且将智能合约的代码公开，那么这将是一个完美的闭环，不管是留言的留言者，还是说这个合约的创建者，都无法篡改这些内容。然后再加上一个前端页面，当用户访问的时候获取链上的留言，这样大家就都能看得到了。哪怕将前端网页下线，在链上根据开源的合约代码和公开合约的ABI信息，也能够查看到留言信息。</p><p>说干就干！</p><h2 id="项目技术栈"><a href="#项目技术栈" class="headerlink" title="项目技术栈"></a>项目技术栈</h2><ul><li>Solidity - 以太坊智能合约的编程语言</li><li>React - 前端框架</li><li>Tailwind CSS - 样式框架</li><li>Wagmi - Web3开发库</li><li>Cloudflare Workers - 后端代理服务</li></ul><p>项目目录树（使用我写的<a href="https://github.com/shiquda/treex">开源CLI：Treex</a>生成）：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">📁 ./</span><br><span class="line">├── 📝 README.md</span><br><span class="line">├── 📁 cloudflare/</span><br><span class="line">│   └── 📜 worker.js</span><br><span class="line">├── 📜 eslint.config.js</span><br><span class="line">├── 🌐 index.html</span><br><span class="line">├── 📋 package.json</span><br><span class="line">├── ⚙️ pnpm-lock.yaml</span><br><span class="line">├── 📜 postcss.config.js</span><br><span class="line">├── 📁 public/</span><br><span class="line">│   ├── 📄 favicon.ico</span><br><span class="line">│   └── 🖼️ icon.png</span><br><span class="line">├── 📁 solidity/</span><br><span class="line">│   ├── 📋 abi.json</span><br><span class="line">│   └── 📄 message.sol</span><br><span class="line">├── 📁 src/</span><br><span class="line">│   ├── 🎨 App.css</span><br><span class="line">│   ├── 📜 App.tsx</span><br><span class="line">│   ├── 📁 assets/</span><br><span class="line">│   │   └── 🖼️ react.svg</span><br><span class="line">│   ├── 📁 components/</span><br><span class="line">│   │   ├── 📜 MessageBoard.tsx</span><br><span class="line">│   │   └── 📜 QA.tsx</span><br><span class="line">│   ├── 📜 config.ts</span><br><span class="line">│   ├── 🎨 index.css</span><br><span class="line">│   ├── 📜 main.tsx</span><br><span class="line">│   └── 📜 vite-env.d.ts</span><br><span class="line">├── 📜 tailwind.config.js</span><br><span class="line">├── 📋 tsconfig.app.json</span><br><span class="line">├── 📋 tsconfig.json</span><br><span class="line">├── 📋 tsconfig.node.json</span><br><span class="line">└── 📜 vite.config.ts</span><br></pre></td></tr></tbody></table></figure><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>Github 开源地址：<a href="https://github.com/shiquda/chain-message">https://github.com/shiquda/chain-message</a></p><p>在线预览：<a href="https://msg.shiquda.link/">https://msg.shiquda.link/</a></p><p>部署教程： <a href="https://github.com/shiquda/chain-message/blob/main/DEPLOY_GUIDE.md">https://github.com/shiquda/chain-message/blob/main/DEPLOY_GUIDE.md</a></p><blockquote><p>如果你想要充分理解这篇文章内容，最好需要有一定的区块链知识。没有也没关系，相信以读者聪明的脑袋瓜，可以随时利用大模型轻松理解。如果你对此感兴趣，想要动手实践的话，你还需要一个钱包插件。（我使用的是<a href="https://chromewebstore.google.com/detail/okx-wallet/mcohilncbfahbmgdjkbpemcciiolgcge">OKX的Web3钱包</a>）</p></blockquote><h3 id="智能合约"><a href="#智能合约" class="headerlink" title="智能合约"></a>智能合约</h3><p>首先我们需要编写智能合约代码。智能合约可以简单理解为在区块链上运行的一串代码，而整个区块链可以看作是一个<a href="https://zh.wikipedia.org/zh-hans/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA">状态机</a>，智能合约的交互使得状态机从一个状态变化到另一个状态。智能合约支持两类调用，一种是Read类型的，调用此类合约不需要花费Gas手续费；另一种是Write类型，由于涉及到写操作，这类开销是比较大的，需要花费Gas。</p><p><a href="https://etherscan.io/address/0x0bb014622cfe080703796054c7a587d1d3bc4be9">我编写的这个智能合约</a>代码只允许两个接口，一个是 <code>postMessage</code> ，这是一个Write Contract，让用户传入他想要提交的留言。其中名字是可选的，如果不填就会视作是匿名留言。此外应该要支持markdown格式，这一点在前端处理即可。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">function postMessage(string memory _name, string memory _content) public {</span><br><span class="line">    unchecked {</span><br><span class="line">        // 安全计数（Solidity 0.8+默认检查算术溢出）</span><br><span class="line">        _messageCounter++;</span><br><span class="line">    }</span><br><span class="line">    emit MessagePosted(</span><br><span class="line">        _messageCounter,</span><br><span class="line">        msg.sender,</span><br><span class="line">        bytes(_name).length == 0 ? "Anonymous" : _name,</span><br><span class="line">        _content,</span><br><span class="line">        block.timestamp</span><br><span class="line">    );</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p><img src="https://s2.loli.net/2025/04/21/NlrEymgxWbQ5kUV.png" alt="PixPin_2025-04-21_00-02-02" loading="lazy"></p><p>在留言发送后，智能合约会自动保存前面的这几个参数之外，还会保存发送时的时间戳等信息。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">event MessagePosted(</span><br><span class="line">    uint256 indexed messageId, // 留言ID（可索引）</span><br><span class="line">    address indexed sender, // 发送者地址（可索引）</span><br><span class="line">    string name, // 留言者名字（或"Anonymous"）</span><br><span class="line">    string content, // Markdown内容</span><br><span class="line">    uint256 timestamp // 区块时间戳</span><br><span class="line">);</span><br></pre></td></tr></tbody></table></figure><p>还有一个接口，用于查询消息的数量。这个接口是只读的，进行合约调用的话，相当于只是在区块链上进行状态的查询，并不会消耗gas。这个接口其实项目暂时没有用到。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function getMessageCount() public view returns (uint256) {</span><br><span class="line">    return _messageCounter;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p><img src="https://s2.loli.net/2025/04/21/cCoRlA1J6asT4IM.png" alt="PixPin_2025-04-21_00-03-02" loading="lazy"></p><p>除此之外，就没有预留其他任何接口了，这意味着只要留言上链，哪怕是我也无法删除。</p><p>接下来讲讲我是如何部署智能合约。我使用的是以太坊基金会推荐的，对于新手比较友好的一个在线IDE：<a href="https://remix.ethereum.org/">Remix</a>。</p><p><img src="https://s2.loli.net/2025/04/21/TcewvYP8dhiOVDN.png" alt="PixPin_2025-04-21_00-06-23" loading="lazy"></p><p>我们将本地写好合约的贴到这个remix上，然后然后选择编译。编译之后，在左侧选择部署选项卡。</p><p><img src="https://s2.loli.net/2025/04/21/dAgOcGpM9HYsbxZ.png" alt="PixPin_2025-04-21_00-06-57" loading="lazy"></p><p>选择Walletconnect，并且根据提示连接你的钱包插件。连接之后，点击部署，在钱包插件确认之后就能部署上链了。</p><p>部署合约是需要消耗比较高的Gas费的，所以说你可能需要从中心化的交易所中提取一些一些到你的钱包。我上次部署的时候大概是花了0.37刀。部署完成之后你还可以到<a href="https://etherscan.io/">Etherscan</a>上添加你的合约源码，这样大家就可以公开审查这个合约代码，确保这个系统的不可篡改性。</p><p>这里有一点要注意的是，我使用的是智能合约的event log来进行留言的记录。之所以这么做而不选择使用storage直接存储到区块链上的原因，是因为那样会消耗更多的Gas费。使用Event log记录的方式就可以减少这个消耗，让用户提交留言的时候少花一些Gas费。在我测试的时候，提交一次留言需要使用0.05美元，大概折合人民币3毛多。</p><p>当然，其实测试的时候先上测试网进行测试是一个比较稳妥的方式，但是我这边太心急了，想马上能够把第一个属于自己的智能合约部署到主网上，大家最好不要学我这么做🤣</p><h3 id="前端实现"><a href="#前端实现" class="headerlink" title="前端实现"></a>前端实现</h3><p>前端实现，我使用的是React框架，Tailwind CSS对样式进行简单的美化。这边使用的对接web3的库是<a href="https://wagmi.sh/">wagmi</a>，感谢前人Web3开发者，已经帮我们普通开发者做了很多事情了。这个库可以自动处理和用户的钱包插件交互。</p><p>具体实现就不多赘述了，感兴趣的读者可以查看<a href="https://github.com/shiquda/chain-message">源码</a>。</p><p>在线预览：<a href="https://msg.shiquda.link/">https://msg.shiquda.link/</a></p><p><img src="https://s2.loli.net/2025/04/21/9w84b2qSkTmhcpt.png" alt="PixPin_2025-04-21_00-16-23" loading="lazy"></p><h3 id="Cloudflare-Workers"><a href="#Cloudflare-Workers" class="headerlink" title="Cloudflare Workers"></a>Cloudflare Workers</h3><p>前端的内容比较简单，但这时出现了一个新的问题：怎么样让用户能够获取区块链上的留言信息呢？</p><p>我首先尝试一种方案，利用公开的以太坊节点来进行日志的获取。但是我尝试几个后发现大多数都不支持无鉴权的调用。对于获取Event log信息，我找到一个免费的， <a href="https://ethereum.publicnode.com/">https://ethereum.publicnode.com</a> ，但也仅支持查询最多5万个区块的信息，这与我的预期显然是不符合的。因此我干脆使用需要鉴权的Etherscan的API。</p><p>但这里又有一个问题，如果说密钥直接存储到前端的话，泄露之后，不就会被他人滥用了？</p><p>于是我想到了Cloudflare Workers做一个简单的封装。当用户发起请求到Cloudflare Workers的时候，worker通过在CF配置的环境变量的APIkey，然后再将请求发往EtherScan，做一层转发。再根据传回的内容返回给用户，这样前端页面就可以进行实时的消息获取了。</p><p>但这样，还是有可能被人利用接口进行event log的查询。我们再设置一个环境变量，让接口只能用于我们部署的合约的查询，这样就大大降低了滥用者的收益。</p><p>这边还有一个坑点，就是说CF的Workers域名是被GFW封锁的。想要解决这个问题，可以使用自己的域名或者子域名做一个转发，这样就能绕过限制了，让用户直连也能够请求到所需的留言信息。</p><p>要进行Workers的配置，你需要在Cloudflare的左侧找到Workers 和Pages，然后<code>创建 &gt; Workers &gt; Hello world &gt; 填写名称并部署 &gt; 进入修改源码</code>，粘贴下面的代码。</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// worker.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">fetch</span>(<span class="params">request, env</span>) {</span><br><span class="line">        <span class="comment">// 处理预检请求</span></span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">method</span> === <span class="string">'OPTIONS'</span>) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, {</span><br><span class="line">                <span class="attr">headers</span>: {</span><br><span class="line">                    <span class="string">'Access-Control-Allow-Origin'</span>: <span class="string">'*'</span>,</span><br><span class="line">                    <span class="string">'Access-Control-Allow-Methods'</span>: <span class="string">'GET, OPTIONS'</span>,</span><br><span class="line">                    <span class="string">'Access-Control-Allow-Headers'</span>: <span class="string">'Content-Type'</span>,</span><br><span class="line">                },</span><br><span class="line">            });</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> { searchParams } = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>);</span><br><span class="line">        <span class="keyword">const</span> address = searchParams.<span class="title function_">get</span>(<span class="string">'address'</span>);</span><br><span class="line">        <span class="keyword">const</span> startBlock = searchParams.<span class="title function_">get</span>(<span class="string">'startBlock'</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!address || !startBlock) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">'Missing parameters'</span>, {</span><br><span class="line">                <span class="attr">status</span>: <span class="number">400</span>,</span><br><span class="line">                <span class="attr">headers</span>: {</span><br><span class="line">                    <span class="string">'Access-Control-Allow-Origin'</span>: <span class="string">'*'</span>,</span><br><span class="line">                    <span class="string">'Content-Type'</span>: <span class="string">'application/json'</span>,</span><br><span class="line">                }</span><br><span class="line">            });</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 可选环境变量：合约地址，防止接口盗刷</span></span><br><span class="line">        <span class="keyword">const</span> <span class="variable constant_">CONTRACT_ADDRESS</span> = env.<span class="property">CONTRACT_ADDRESS</span>?.<span class="title function_">toLowerCase</span>();</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable constant_">CONTRACT_ADDRESS</span> &amp;&amp; address.<span class="title function_">toLowerCase</span>() !== <span class="variable constant_">CONTRACT_ADDRESS</span>) {</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">'Forbidden'</span>, {</span><br><span class="line">                <span class="attr">status</span>: <span class="number">403</span>,</span><br><span class="line">                <span class="attr">headers</span>: {</span><br><span class="line">                    <span class="string">'Access-Control-Allow-Origin'</span>: <span class="string">'*'</span>,</span><br><span class="line">                    <span class="string">'Content-Type'</span>: <span class="string">'application/json'</span>,</span><br><span class="line">                }</span><br><span class="line">            });</span><br><span class="line">        }</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> params = <span class="keyword">new</span> <span class="title class_">URLSearchParams</span>({</span><br><span class="line">            <span class="attr">module</span>: <span class="string">'logs'</span>,</span><br><span class="line">            <span class="attr">action</span>: <span class="string">'getLogs'</span>,</span><br><span class="line">            <span class="attr">address</span>: address,</span><br><span class="line">            <span class="attr">fromBlock</span>: startBlock,</span><br><span class="line">            <span class="attr">apikey</span>: env.<span class="property">ETHERSCAN_API_KEY</span></span><br><span class="line">        });</span><br><span class="line">        <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">`https://api.etherscan.io/api?<span class="subst">${params.toString()}</span>`</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> data = <span class="keyword">await</span> response.<span class="title function_">json</span>();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(data), {</span><br><span class="line">            <span class="attr">headers</span>: {</span><br><span class="line">                <span class="string">'Content-Type'</span>: <span class="string">'application/json'</span>,</span><br><span class="line">                <span class="string">'Access-Control-Allow-Origin'</span>: <span class="string">'*'</span>,</span><br><span class="line">                <span class="string">'Access-Control-Allow-Methods'</span>: <span class="string">'GET, OPTIONS'</span>,</span><br><span class="line">                <span class="string">'Access-Control-Allow-Headers'</span>: <span class="string">'Content-Type'</span>,</span><br><span class="line">            },</span><br><span class="line">        });</span><br><span class="line">    },</span><br><span class="line">};</span><br></pre></td></tr></tbody></table></figure><p>然后找到Worker的<code>设置 &gt; 变量和机密 &gt; 变量和机密 &gt; 添加</code>，添加<code>CONTRACT_ADDRESS</code>和<code>ETHERSCAN_API_KEY</code>这两个环境变量。</p><p>如果你需要绑定自己的域名，你需要在CF进入域名的管理页面，然后找到左侧的“Workers 路由”，选择添加路由并绑定前面创建的Worker。</p><p><img src="https://s2.loli.net/2025/04/21/gVr1YanhzPQtLH6.png" alt="PixPin_2025-04-21_00-29-46" loading="lazy"></p><h3 id="静态网页生成"><a href="#静态网页生成" class="headerlink" title="静态网页生成"></a>静态网页生成</h3><p>一切就绪后，我们完全可以使用生成一个静态页面，然后把这个静态页面上传到我们的博客或者是云托管服务上面，这样就能够实现独立的运行了。</p><p>推荐使用Cloudflare Pages的方式进行部署。使用这种方式的教程请见<a href="https://github.com/shiquda/chain-message/blob/main/DEPLOY_GUIDE.md">Github 上的部署教程</a>。</p><p>克隆项目，安装依赖并配置</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/shiquda/chain-message.git</span><br><span class="line">cd chain-message</span><br><span class="line">pnpm install</span><br></pre></td></tr></tbody></table></figure><p>然后参考<code>.env.example</code>填写需要的环境变量。一切就绪后，使用下面的命令进行构建：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm build</span><br></pre></td></tr></tbody></table></figure><p><code>dist/</code>中的文件就是静态网页了，你可以把它放到托管服务上。</p><hr><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>说完这么多，真的是感慨万千。假如说一百年后，当我离开这个世界之后，这些留言可能还能存在区块链上，甚至别人还能够访问到、看到我自己的，或者是别人网友给我的留言，真的是一件非常<em>酷</em>的事情。</p><p>留言地址：<a href="https://msg.shiquda.link/">https://msg.shiquda.link/</a></p><p>不管怎么样，先给10年后的自己<a href="https://etherscan.io/tx/0xd108a7e73699e3c44bd0a24cd300b5cd8b389d22ed1ffc96980f7f12414ac1ab">留个言</a>。（多打了一个字，已经无法挽回了😄）</p><p><img src="https://s2.loli.net/2025/04/21/xACPOmkz8N5YZDF.png" alt="PixPin_2025-04-21_00-58-32" loading="lazy"></p><p><img src="https://s2.loli.net/2025/04/21/9iVrO3Dj2d6nlwk.png" alt="PixPin_2025-04-21_00-59-03" loading="lazy"></p><p>实现这个idea的所有代码，包括智能合约代码，前端代码，还有cloudflare workers代码，我都放到<a href="https://github.com/shiquda/chain-message">github仓库</a>上，要是你也对这个感兴趣，可以自己部署一个玩玩看。</p><p>我前几天申请了一个以太坊的地址域名：shiquda.eth。使用这个ENS域名，就可以找到我的钱包地址，也就是部署这个合约的地址。如果文章对您有所启发，可以给我这个地址打钱😄<del>（真是太不要脸了）</del></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>《金钱心理学》阅读总结</title>
      <link>https://shiquda.link/the-psychology-of-money-summary/</link>
      <description>《金钱心理学》阅读总结</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E8%80%95%E8%AF%BB/">耕读</category>
      <pubDate>Fri, 11 Apr 2025 13:24:17 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>我们分析金融和投资，往往是从<strong>理性</strong>的角度来考虑问题的。金融学有经纪人假设、有效市场假说；投资上的量化交易，会找一些毕业于名校的、智商超标的天才，就是为了能够多挖掘出一些有效的量化因子，视图用数理的方式来击败市场。然而，这本书却给我们一个别样的视角：从看似有些“玄学”的<strong>心理学</strong>出发，查看那些每一个普通人在做出投资决定时，往往被我们忽视，却又直接影响着我们的投资决策与回报的因素。</p><p>这本书大概是以道理+实例的方式来展开的，所举的例子也都挺生动，但是读起来也难免感觉有些冗长。下面我将每一章提炼为若干观点。</p><ol><li><p>受限于每个人的出身、成长经历、所处社会环境等诸多因素，每个人对金钱的认知有非常大的差异，所有可能只有很少一部分符合实际，而对金钱的认知在很大程度上影响了我们对世界运作方式的理解。</p></li><li><p>一个人做出投资决策，绝不是简单的看着股票价格的变化，进行一系列分析做出的，必定会受到个人经历、世界观、家庭现金流等其他“场外”因素的影响。</p></li><li><p>生活中的每一个结果都受到个人努力之外的其他作用的影响，你不能只相信其中一个，而无视另一个。</p></li><li><p>“知足”很可能是我们在不知为何的奔跑中忽视的一个因素。向上攀比，是没有尽头的，敢于适可而止才显得更加宝贵。</p></li><li><p>世界上很多事都不值得冒险，无论潜在收益有多大。追求它们，你可能需要承担失去无价之物的风险，例如名誉、自由、亲友乃至生命。</p></li><li><p>复利的力量是反直觉的。</p></li><li><p>致富需要的是冒险精神、乐观心态，以及放手一搏的勇气。但守富需要做的却与冒险完全相反，它需要谦逊和敬畏之心，需要清楚财富来得有多快，去得就有多容易。</p></li><li><p>比起巨大的回报，财富的安全更重要。只要财富安全，你就知道利用复利的力量，你就能得到最大的回报</p></li><li><p>一个投资者即使在一半的时间里都看走了眼，最后却仍然能致富（靠盈亏比和尾部事件），这是反直觉的。因此，有时不必对失败过度焦虑，它们的存在是必然的。例：风险投资的广撒网策略，只靠为数不多的成功的创业公司获利。</p></li><li><p>在大多数情况下，“当下”其实并没有那么重要。你最近将要做出的决策，往往远不如一生中做出的个别几个决定重要。</p></li><li><p>财富能给你带来的最大红利是时间自由。“今天我能做我想做的任何事。”</p></li><li><p>购买奢侈品，实质上是购买他人的羡慕。但事实上，他人看到你的奢侈品，往往不会羡慕你，而更可能拥有下面几种想法：</p><ol><li>关注于奢侈品本身：“这个奢侈品真漂亮！”</li><li>对比他自己：“我永远也买不了”&#x2F;“我能不能也买一个？或者更贵的？”</li><li>质疑你：“你有钱，但我觉得你不配。你这么有钱都是靠xxx的。”</li></ol></li><li><p>炫富是让财富流失的最快途径。这个世界上有很多看起来低调但实际上很富有的人，还有很多看上去很有钱却生活在破产边缘的人。</p></li><li><p>财富积累与你的收入或投资回报率关系不大，而与你的<strong>储蓄率</strong>关系很大。</p></li><li><p>事实上，尝试缩减不必要的开支，或是将其用于投资，比你绞尽脑汁提高0.1%的收益率更加直接和简单。</p></li><li><p>存款 &#x3D; 虚荣的自我 - 收入</p></li><li><p>存钱并不需要一个特别的理由。存钱不仅是为了更多的回报，即使完全没有收益上的回报，选择一份对自己来说更有价值的工作、等待恐慌带来的投资机会，这种与其他人相比更高的<strong>灵活度</strong>，也是一种回报。</p></li><li><p><strong>合乎情理胜过绝对理性</strong>，这是因为在投资行为中存在着<strong>社会性因素</strong>。在做投资决策时，不要试图保持绝对理性，而要做出对你而言合乎情理，也就是更容易接受的选择，这么做更容易让你做到长期坚持。换句话说，现实中的最佳投资方案一定是能让我们晚上睡得安稳的方案，而不是试图做到绝对理性，在刀尖上舔血的方案。</p></li><li><p>日内交易、选择个股、根据投资预测来交易，这些方式对大多数投资者来说都是不够理性的表现，但如果占比很小，这么做顺应你的人性的话，那么它们就是合乎情理的。（看作一场游戏）</p></li><li><p>我们试图从各种角度，根据历史来预测未来。但事实是，世界上总在发生过去从来没有发生过的事，这是反直觉的。例：修建核反应堆时，人们考虑过的最坏情形是历史上发生过的最严重的地震，但历史上的最坏事件同样是个意外。</p></li><li><p>尾部事件和尾部人物所造成的影响是超乎想象的，因为它们会随着时间的流逝，影响越来越大。</p></li><li><p>关于投资史很有趣的一点是，你追溯的时期越久远，你看到的规律就越不适用于今天的世界。</p></li><li><p>容错空间是很重要的。有些事情从统计学角度看是可行的，但我们必须保证手上有足够的钱去应对运气最差的情况，不要因为一次黑天鹅事件让你赔得底裤都没了。</p></li><li><p>人是会变的。人们能敏锐地意识到自己相比过去发生的变化，但很容易低估自己的性格、想法和目标在将来会发生的变化。</p></li><li><p>投资是有代价的，不必付出代价就能获得回报是一种错觉。但回报的成本往往是隐性的。它们包括：忍受波动的心理成本、机会成本、无法预测的黑天鹅爆雷事件……如果你把它们显性地揪出来，并使作为支付的“入场券”，那么心理会好受很多。</p></li><li><p>不要贸然从那些和你情况不同的人身上学习理财经验。每个人的经验不同、投资逻辑（如做短线&#x2F;长线）不同、可承受风险能力不同、进场点位不同</p></li><li><p>人们对负面事件的本能厌恶，使得悲观主义具有心理优势，人们更容易收到它的影响。</p></li><li><p>每个人对世界的看法都是不完整的，但每个人都会编织完整的故事来弥补其中的空白。</p></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>Treex - 高级命令行目录树可视化工具</title>
      <link>https://shiquda.link/treex-an-advanced-cli-directory-tree-visualization/</link>
      <description>一款便捷的命令行工具，配备易用的过滤功能，可以用多种输出格式展示文件夹的结构。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/Go/">Go</category>
      <pubDate>Thu, 10 Apr 2025 16:14:19 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h1 id="🌳-Treex-高级命令行目录树可视化工具"><a href="#🌳-Treex-高级命令行目录树可视化工具" class="headerlink" title="🌳 Treex - 高级命令行目录树可视化工具"></a>🌳 Treex - 高级命令行目录树可视化工具</h1><p>今天给读者推荐一个我最近开发的面向开发者的小工具——Treex。</p><h2 id="🤔-为什么需要这个工具？"><a href="#🤔-为什么需要这个工具？" class="headerlink" title="🤔 为什么需要这个工具？"></a>🤔 为什么需要这个工具？</h2><p>在开发与学习过程中，可能会遇到过这样的场景：</p><ul><li>对于一个较为陌生的项目，看着复杂的项目结构，不知道怎么入手</li><li>想要快速告诉大模型自己一个项目的结构，让它辅助你理解</li><li>写项目文档时需要插入目录结构的可视化</li></ul><p>传统的<code>tree</code>命令虽然能用，但功能太基础了。楼主在使用过程中，常常会出现把不需要的文件同时绘制出来的情况（例如，node项目的<code>node_modules</code>），导致包含太多不必要的信息，看上去更乱了。</p><p>于是我利用cursor，使用go语言开发了<a href="https://github.com/shiquda/treex">Treex</a>，这是一个<strong>支持多种输出格式、带过滤功能</strong>的目录树工具。</p><p><strong>项目地址</strong>：<a href="https://github.com/shiquda/treex">https://github.com/shiquda/treex</a></p><h2 id="✨-核心功能一览"><a href="#✨-核心功能一览" class="headerlink" title="✨ 核心功能一览"></a>✨ 核心功能一览</h2><h3 id="🎨-多格式输出"><a href="#🎨-多格式输出" class="headerlink" title="🎨 多格式输出"></a>🎨 多格式输出</h3><ul><li>🌲 <strong>树状格式</strong>（默认）：经典的命令行树状结构</li><li>📑 <strong>缩进格式</strong>：简洁的层级缩进</li><li>📝 <strong>Markdown格式</strong>：直接粘贴到文档里</li><li>📊 <strong>Mermaid格式</strong>：生成可嵌入的流程图</li></ul><h3 id="🔍-智能过滤"><a href="#🔍-智能过滤" class="headerlink" title="🔍 智能过滤"></a>🔍 智能过滤</h3><ul><li>🕵️ 隐藏<code>.git</code>等隐藏文件</li><li>📁 只显示目录结构</li><li>🚫 排除指定目录/文件类型</li></ul><h3 id="🛠️-高度可定制"><a href="#🛠️-高度可定制" class="headerlink" title="🛠️ 高度可定制"></a>🛠️ 高度可定制</h3><ul><li>📏 控制目录深度</li><li>💾 输出到文件</li><li>🎯 自定义显示格式</li></ul><h2 id="🚀-快速上手"><a href="#🚀-快速上手" class="headerlink" title="🚀 快速上手"></a>🚀 快速上手</h2><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><h4 id="方法1：下载预编译二进制文件"><a href="#方法1：下载预编译二进制文件" class="headerlink" title="方法1：下载预编译二进制文件"></a>方法1：下载预编译二进制文件</h4><p>从<a href="https://github.com/shiquda/treex/releases">Release</a>页面下载后，加入PATH</p><h4 id="方法2：用Go编译安装"><a href="#方法2：用Go编译安装" class="headerlink" title="方法2：用Go编译安装"></a>方法2：用Go编译安装</h4><p>如果你有go环境，可以使用下面的代码一键安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">go install github.com/shiquda/treex@latest</span><br></pre></td></tr></tbody></table></figure><h3 id="基础使用"><a href="#基础使用" class="headerlink" title="基础使用"></a>基础使用</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看当前目录结构</span></span><br><span class="line">treex</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看指定目录</span></span><br><span class="line">treex -d /path/to/project</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看help信息</span></span><br><span class="line">treex -h</span><br></pre></td></tr></tbody></table></figure><p>输出：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">└── .</span><br><span class="line">    ├── .git</span><br><span class="line">    │   ├── HEAD</span><br><span class="line">    │   ├── config</span><br><span class="line">    │   ├── description</span><br><span class="line">    │   ├── hooks</span><br><span class="line">    │   │   ├── applypatch-msg.sample</span><br><span class="line">    │   │   ├── commit-msg.sample</span><br><span class="line">    │   │   ├── fsmonitor-watchman.sample</span><br><span class="line">    │   │   ├── post-update.sample</span><br><span class="line">    │   │   ├── pre-applypatch.sample</span><br><span class="line">    │   │   ├── pre-commit.sample</span><br><span class="line">    │   │   ├── pre-merge-commit.sample</span><br><span class="line">    │   │   ├── pre-push.sample</span><br><span class="line">    │   │   ├── pre-rebase.sample</span><br><span class="line">    │   │   ├── pre-receive.sample</span><br><span class="line">    │   │   ├── prepare-commit-msg.sample</span><br><span class="line">    │   │   ├── push-to-checkout.sample</span><br><span class="line">    │   │   ├── sendemail-validate.sample</span><br><span class="line">    │   │   └── update.sample</span><br><span class="line">    │   ├── info</span><br><span class="line">    │   │   └── exclude</span><br><span class="line">    │   ├── objects</span><br><span class="line">    │   │   ├── info</span><br><span class="line">    │   │   └── pack</span><br><span class="line">    │   └── refs</span><br><span class="line">    │       ├── heads</span><br><span class="line">    │       └── tags</span><br><span class="line">    ├── .gitignore</span><br><span class="line">    ├── 1.go</span><br><span class="line">    ├── 2.go</span><br><span class="line">    ├── README.md</span><br><span class="line">    ├── build</span><br><span class="line">    │   └── win</span><br><span class="line">    │       └── output.exe</span><br><span class="line">    └── test</span><br><span class="line">        ├── 3.go</span><br><span class="line">        └── README_test.md</span><br></pre></td></tr></tbody></table></figure><h2 id="⚡-高级使用示例"><a href="#⚡-高级使用示例" class="headerlink" title="⚡ 高级使用示例"></a>⚡ 高级使用示例</h2><h3 id="1-生成项目文档"><a href="#1-生成项目文档" class="headerlink" title="1. 生成项目文档"></a>1. 生成项目文档</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 排除隐藏文件，输出Markdown格式到指定文件</span></span><br><span class="line">treex -H -f md -o PROJECT_STRUCTURE.md</span><br></pre></td></tr></tbody></table></figure><ul><li>./<ul><li>1.go</li><li>2.go</li><li>README.md</li><li>build/<ul><li>win/<ul><li>output.exe</li></ul></li></ul></li><li>test/<ul><li>3.go</li><li>README_test.md</li></ul></li></ul></li></ul><h3 id="2-技术分享配图"><a href="#2-技术分享配图" class="headerlink" title="2. 技术分享配图"></a>2. 技术分享配图</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 只保留非隐藏的文件夹，生成Mermaid代码</span></span><br><span class="line">treex -HD -f mermaid</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line">    N1[./]</span><br><span class="line">    N2[build/]</span><br><span class="line">    N1 --&gt; N2</span><br><span class="line">    N3[win/]</span><br><span class="line">    N2 --&gt; N3</span><br><span class="line">    N4[test/]</span><br><span class="line">    N1 --&gt; N4</span><br></pre></td></tr></tbody></table></figure><p><img src="https://s2.loli.net/2025/04/11/XNgijqn47FURCdx.png" alt="mermaid-2025411 002546" loading="lazy"></p><h3 id="3-排除指定文件"><a href="#3-排除指定文件" class="headerlink" title="3. 排除指定文件"></a>3. 排除指定文件</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 排除不重要的文件夹和文件类型</span></span><br><span class="line">treex -e <span class="string">".git/, .md"</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">└── .</span><br><span class="line">    ├── .gitignore</span><br><span class="line">    ├── 1.go</span><br><span class="line">    ├── 2.go</span><br><span class="line">    ├── build</span><br><span class="line">    │   └── win</span><br><span class="line">    │       └── output.exe</span><br><span class="line">    └── test</span><br><span class="line">        └── 3.go</span><br></pre></td></tr></tbody></table></figure><h2 id="🛠️-完整参数说明"><a href="#🛠️-完整参数说明" class="headerlink" title="🛠️ 完整参数说明"></a>🛠️ 完整参数说明</h2><p>可以前往 <a href="https://github.com/shiquda/treex">https://github.com/shiquda/treex</a> 查看。</p><div class="md-table-scroll"><table><thead><tr><th>参数</th><th>说明</th></tr></thead><tbody><tr><td><code>-d</code></td><td>指定扫描目录（默认当前目录）</td></tr><tr><td><code>-f</code></td><td>输出格式（tree/indent/md/mermaid）</td></tr><tr><td><code>-m</code></td><td>最大目录深度（0表示无限制）</td></tr><tr><td><code>-o</code></td><td>输出文件路径</td></tr><tr><td><code>-e</code></td><td>排除规则（逗号分隔）</td></tr><tr><td><code>-H</code></td><td>隐藏隐藏文件</td></tr><tr><td><code>-D</code></td><td>仅显示目录</td></tr></tbody></table></div><h2 id="💖-期待你的参与"><a href="#💖-期待你的参与" class="headerlink" title="💖 期待你的参与"></a>💖 期待你的参与</h2><p>Treex目前还在早期开发阶段。笔者还没有多少开发经验，受限于个人水平，工具难免有不足之处。如果你：</p><ul><li>发现了bug</li><li>有功能建议</li><li>想贡献代码</li></ul><p>欢迎在GitHub给我提Issue或PR！当然，给个⭐星星鼓励也是极好的～</p><p><strong>项目地址</strong>：<a href="https://github.com/shiquda/treex">https://github.com/shiquda/treex</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>从零开始搭建一个MCP服务器</title>
      <link>https://shiquda.link/build-a-mcp-server-with-python-from-scratch/</link>
      <description>使用Python，从零开始搭建一个属于自己的MCP服务器，从Idea诞生到服务器推广的全流程。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <pubDate>Fri, 04 Apr 2025 15:35:37 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>MCP(Model Context&nbsp;Protocol)来自于2024年Anthropic发布的文章：<a href="https://link.zhihu.com/?target=https://www.anthropic.com/news/model-context-protocol">Introducing the Model Context&nbsp;Protocol</a>，是一种用于和LLM Model 交互的标准化协议，允许模型拓展自己的能力。在最近的Manus爆火之后，关注度更是上升，我也是在这之后才了解到这个协议的。在我看来，这个协议是一个里程碑式的节点，统一了模型和应用之间的通信标准，在未来会有更加广阔的应用场景，现在也有不少应用厂家接入了MCP协议，比如国内的百度地图。</p><p><img src="https://s2.loli.net/2025/04/04/c9XVBAZwCaKNiRe.jpg" alt="v2-9fe7fb51f264338a079a444eefa041b1_1440w" loading="lazy"></p><p>借用下面这篇文章的图片，这张图一目了然地展示了MCP的作用。对于MCP感兴趣但是还不是很了解的读者，推荐去阅读一下下面这篇文章。</p><p><a href="https://zhuanlan.zhihu.com/p/29001189476">https://zhuanlan.zhihu.com/p/29001189476</a></p><p>本文既是我摸索搭建一个MCP学习记录，也是一个简单的流程分享。受限于个人技术，本文并不涉及到一些较为成熟的开发范式，更多是对整体流程做一个记录和梳理，希望能对想要着手开发MCP服务器的读者有所帮助。这篇文章会以Python为编程语言进行实践。</p><p>我搭建的服务器：一个用于帮助大模型访问wiki网站的服务器，欢迎大伙Star！</p><p><a href="https://github.com/shiquda/mediawiki-mcp-server">https://github.com/shiquda/mediawiki-mcp-server</a></p><p>这个项目的灵感源于我最近玩的一款游戏<a href="https://store.steampowered.com/app/881100/Noita/">Noita</a>，对于我这个新手来说，需要经常查询游戏<a href="https://noita.wiki.gg/">wiki</a>。于是我就<del>为了这点醋，包了这碗饺子，</del>打算利用MCP技术，让大模型帮我阅读和总结wiki。于是就有了这篇文章😄</p><h2 id="先决条件"><a href="#先决条件" class="headerlink" title="先决条件"></a>先决条件</h2><p>在阅读并实践之前，笔者假设读者拥有以下能力：</p><ol><li>熟悉Python编程语言</li><li>拥有能稳定使用、支持Tool Call的大模型提供商，以及一个支持MCP协议的客户端</li><li>熟悉Git与GitHub的基本使用</li><li>拥有良好的网络环境</li></ol><p>对于第2点，若读者还没有合适的，笔者进行以下推荐：</p><ol><li><a href="https://www.volcengine.com/">火山引擎-云上增长新动力</a>：字节提供的稳定性好、价格优惠的平台，使用其中的DeepSeek模型，支持tool-call。</li><li><a href="https://cherry-ai.com/">Cherry Studio 官方网站 - 全能的AI助手</a>：一个开源免费的、支持多个LLM提供商的桌面端大模型对话软件，现在支持MCP协议。（笔者参与了该项目的贡献，算是打个小小的广告:)）</li></ol><p>对于上述二者的申请与配置，相信对读者应该不成问题，烦请读者自行查找攻略进行配置。</p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><h3 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h3><p>使用Python进行MCP服务器的开发，目前主流使用的是<a href="https://hellowac.github.io/uv-zh-cn/"><code>uv</code></a>，这是一个使用Rust编写的高效的包管理器，支持虚拟环境管理、运行和安装Python应用、项目管理、项目构建等多个功能。想进一步了解，可以阅读<a href="https://hellowac.github.io/uv-zh-cn/"><strong>官方文档</strong></a>。</p><p>请读者自行安装与配置<code>uv</code>。可以参考这篇文章：</p><p><a href="https://www.cnblogs.com/wang_yb/p/18635441">Python包管理不再头疼：uv工具快速上手 - wang_yb - 博客园</a></p><p>我们还需要用到<a href="https://nodejs.org/zh-cn"><code>node</code></a>环境，用于服务器的测试。</p><h3 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h3><p>使用uv进行项目的初始化。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">uv init &lt;项目名&gt;</span><br><span class="line"><span class="built_in">cd</span> &lt;项目名&gt;</span><br></pre></td></tr></tbody></table></figure><p>创建虚拟环境：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uv venv</span><br></pre></td></tr></tbody></table></figure><p>并使用你所在平台的方式进行激活。</p><p>使用uv添加依赖：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uv add <span class="string">"mcp[cli]"</span> httpx</span><br></pre></td></tr></tbody></table></figure><p>对于克隆来的其他mcp项目，我们可以使用下面的命令来进行依赖的安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uv <span class="built_in">sync</span></span><br></pre></td></tr></tbody></table></figure><h3 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h3><p>下面是一个最简单的项目结构，省略了部分文件，供读者参考。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mediawiki-mcp-server</span><br><span class="line">├── pyproject.toml</span><br><span class="line">├── README.md</span><br><span class="line">├── src</span><br><span class="line">│   ├── mediawiki_mcp_server</span><br><span class="line">│   │   ├── main.py</span><br><span class="line">├── uv.lock</span><br></pre></td></tr></tbody></table></figure><p><code>pyproject.toml</code>是整个项目的配置文件，我们需要对其进行相应的修改。</p><p>除了已有的项目名称、版本号等，我们还需要添加下面几行，用于项目的运行和构建：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[build-system]</span><br><span class="line">requires = ["hatchling"]</span><br><span class="line">build-backend = "hatchling.build"</span><br><span class="line"></span><br><span class="line">[project.scripts]</span><br><span class="line">mediawiki-mcp-server = "&lt;包的名称&gt;.main:main"</span><br><span class="line"></span><br><span class="line">[tool.hatch.build.targets.wheel]</span><br><span class="line">packages = ["src/&lt;包的名称&gt;"]</span><br></pre></td></tr></tbody></table></figure><p>然后就是开始编写一个简单的MCP服务器啦！想要更详细地查看，可以参考下面这些来源：</p><p><a href="https://modelcontextprotocol.io/quickstart/server">For Server Developers - Model Context Protocol</a></p><p><a href="https://github.com/modelcontextprotocol/python-sdk">modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p><p>我们在<code>/src/&lt;name&gt;</code>创建一个<code>main.py</code> 文件，用于写MCP服务器的主要逻辑。</p><p>对于一个最简单的服务器，可以参考下面的写法：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> mcp.server.fastmcp <span class="keyword">import</span> FastMCP</span><br><span class="line">mcp = FastMCP(<span class="string">"&lt;name&gt;"</span>) <span class="comment"># 创建服务器实例</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@mcp.tool() </span><span class="comment"># 这个装饰器表示下面的函数是一个可被LLM调用的Tool</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">get_page</span>(<span class="params">title: <span class="built_in">str</span></span>): <span class="comment"># 参数会被自动处理，写在下面的docstring可以被识别作为给大模型的“工具使用说明书”</span></span><br><span class="line">    <span class="string">"""Get a page from mediawiki.org</span></span><br><span class="line"><span class="string">    Args:</span></span><br><span class="line"><span class="string">        title: The title of the page to get, which can be found in title field of the search results</span></span><br><span class="line"><span class="string">    Returns:</span></span><br><span class="line"><span class="string">        The page content</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line">    path = <span class="string">f"page/<span class="subst">{title}</span>"</span></span><br><span class="line">    response = <span class="keyword">await</span> make_request(path, {}) <span class="comment"># 实现略</span></span><br><span class="line">    <span class="keyword">return</span> response</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">    mcp.run(transport=<span class="string">"stdio"</span>) <span class="comment"># 使用stdio本地模式</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></tbody></table></figure><p>简单来说，只要专注于实现一个Tool的接口就行了，对于暴露给模型调用的，使用<code>@mcp.tool()</code>进行修饰，调用参数即为函数的传入参数，而使用方法写在函数的注释里面即可。</p><p>下面我们从用户的角度考虑一下。用户使用你的服务器，主要可以配置三个部分：</p><p><img src="https://s2.loli.net/2025/04/04/2BCm3vWUw1sNPbp.png" alt="PixPin_2025-04-04_23-06-25" loading="lazy"></p><ol><li>命令。主要使用的有<code>uvx/uv</code> 、<code>npx</code>和<code>docker</code> 。我们使用的是python，因此这里一般是填uvx/uv。</li><li>参数。这一部分会通过命令行参数传给服务器，因此我们需要考虑在<code>mcp.run</code>启动前处理这些命令行参数。</li><li>环境变量。我们在启动前也需要检查需要的环境变量。</li></ol><p>因此，我们需要使用<strong>参数</strong>或者<strong>环境变量</strong>来达到自定义服务器和读取数据的目的。例如，对于一些需要鉴权的服务，我们可以让用户在<strong>环境变量</strong>部分配置他们的凭证；一些自定义的参数，可以放在<strong>命令行参数</strong>来传入。</p><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>编写完逻辑之后，需要进行测试。</p><p><strong>第一步，</strong>先使用MCP官方提供的测试工具进行测试，使用起来非常简单：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx @modelcontextprotocol/inspector uv run &lt;name&gt;</span><br></pre></td></tr></tbody></table></figure><p>运行之后，在浏览器打开提示的地址，即可进行调试。</p><p><img src="https://s2.loli.net/2025/04/04/LZfHiUFt8eMKsWG.png" alt="PixPin_2025-04-04_23-04-22" loading="lazy"></p><p>对于我们这个简单的项目，主要测试的是Tool的功能。</p><p><img src="https://s2.loli.net/2025/04/04/EJXRq3bfsPL6gVl.png" alt="PixPin_2025-04-04_23-16-32" loading="lazy"></p><p><strong>第二步</strong>，测试完成后，我们就可以对接到客户端进行进一步测试了。这一步主要是检查功能是否符合预期，LLM能否按照预期调用，以及会不会出一些没考虑到的问题。</p><p>对于本地开发调试，需要注意的地方是，由于我们现在还没有将成品打包到pypi，因此需要添加命令行参数来进行本地调试。可以参考下面的写法：</p><p>命令：<code>uv</code></p><p>参数：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">"args"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">  <span class="string">"run"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="string">"--directory"</span><span class="punctuation">,</span> </span><br><span class="line">  <span class="string">"path/to/project/src/&lt;name(下划线)&gt;"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="string">"&lt;name&gt;"</span><span class="punctuation">,</span></span><br><span class="line">  <span class="string">"&lt;...其他参数&gt;"</span></span><br><span class="line"><span class="punctuation">]</span><span class="punctuation">,</span></span><br></pre></td></tr></tbody></table></figure><h3 id="构建"><a href="#构建" class="headerlink" title="构建"></a>构建</h3><p>测试完毕后，我们可以考虑发布到pypi，让其他用户能够更方便的下载使用。</p><p>在本文中，我们使用uv，利用Github Actions来进行自动化构建，但在正式构建之前，本地需要进行测试：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uv build</span><br></pre></td></tr></tbody></table></figure><p>如果正常的话，在项目的<code>/dist</code> 应该会有相应的构建产物。</p><p>一切正常后，我们先去 <a href="https://pypi.org/">https://pypi.org/</a> 进行相应的设置。如果没有账号，可以先注册一个。</p><p>pypi现在支持通过“受信任”的发布者进行自动化构建。我们这里使用Github平台进行配置。</p><p>进入 <a href="https://pypi.org/manage/account/publishing/">Trusted Publisher Management · PyPI</a>，找到<strong>Add a new pending publisher</strong>，</p><p><img src="https://s2.loli.net/2025/04/04/QLhYWFzql4uaTB1.png" alt="PixPin_2025-04-04_23-26-55" loading="lazy"><br>添加之后，我们在项目中添加<code>.github/workflows/publish.yml</code>。注意yml的文件名需要和上一步的对得上。</p><p>工作流文件，可以参考下面的写法：</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Publish</span> <span class="string">Python</span> <span class="string">Package</span> <span class="string">to</span> <span class="string">PyPI</span> <span class="string">when</span> <span class="string">a</span> <span class="string">Release</span> <span class="string">is</span> <span class="string">Created</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">release:</span></span><br><span class="line">    <span class="attr">types:</span> [<span class="string">created</span>]</span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">pypi-publish:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">Publish</span> <span class="string">release</span> <span class="string">to</span> <span class="string">PyPI</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">name:</span> <span class="string">pypi</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">https://pypi.org/p/&lt;name&gt;</span> <span class="comment"># 改成前一步设置的项目名称</span></span><br><span class="line">    <span class="attr">permissions:</span></span><br><span class="line">      <span class="attr">id-token:</span> <span class="string">write</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">uses:</span> <span class="string">actions/checkout@v4</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Python</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-python@v4</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">python-version:</span> <span class="string">"3.13"</span> <span class="comment"># 改成需要的版本号</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">dependencies</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          pip install uv</span></span><br><span class="line"><span class="string"></span>      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Build</span> <span class="string">package</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          uv sync</span></span><br><span class="line"><span class="string">          uv build</span></span><br><span class="line"><span class="string"></span>      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Publish</span> <span class="string">package</span> <span class="string">distributions</span> <span class="string">to</span> <span class="string">PyPI</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">pypa/gh-action-pypi-publish@release/v1</span></span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><p>这里设置的是在Github上创建Release时触发构建，所以构建时，需要去项目的Release中手动创建一下。工作流也可以更改为检测到tag推送后触发，读者可以自行更改。</p><p>成功推送到pypi上后，你就可以使用下面的方式在客户端中调用了：</p><figure class="highlight yaml"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">"command":</span> <span class="string">"uvx"</span><span class="string">,</span></span><br><span class="line"><span class="attr">"args":</span> [</span><br><span class="line">  <span class="string">"&lt;name&gt;"</span>,</span><br><span class="line">]<span class="string">,</span></span><br></pre></td></tr></tbody></table></figure><h3 id="分享"><a href="#分享" class="headerlink" title="分享"></a>分享</h3><p>想要把你的MCP服务器推荐给别人？我整理了几个常见的mcp检索平台，在这些地方上提交你的服务器，可以让更多用户发现并体验你的服务器。</p><ol><li><a href="https://glama.ai/mcp/servers">https://glama.ai/mcp/servers</a> ，和 <a href="https://github.com/punkpeye/awesome-mcp-servers">punkpeye/awesome-mcp-servers: A collection of MCP servers.</a> 相关</li><li><a href="https://mcp.so/">https://mcp.so/</a></li></ol><hr><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://modelcontextprotocol.io/introduction">Introduction - Model Context Protocol</a></p><p><a href="https://pypi.org/">PyPI · The Python Package Index</a></p><p><a href="https://medium.com/@blackary/publishing-a-python-package-from-github-to-pypi-in-2024-a6fb8635d45d">Publishing a Python Package from GitHub to PyPI in 2024</a></p><p><a href="https://pypi.org/manage/account/publishing/">https://pypi.org/manage/account/publishing/</a></p><p><a href="https://github.com/punkpeye/awesome-mcp-servers">https://github.com/punkpeye/awesome-mcp-servers</a></p><p><a href="https://glama.ai/mcp/servers">ChatGPT alternative for power users</a></p><p><a href="https://docs.astral.sh/uv/guides/package/#building-your-package">Building and publishing a package | uv</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>大语言模型时代学习者的提问方式</title>
      <link>https://shiquda.link/how-to-ask-for-learners-in-llm-era/</link>
      <description>大语言模型时代，问什么？问那些没有AI就做不到的问题。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E6%80%9D%E8%80%83/">思考</category>
      <pubDate>Mon, 10 Mar 2025 11:49:09 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>在新的AI时代，LLM这样技术的出现，正在重塑整个世界，包括我们的学习方式。</p><p>一些事实：</p><ol><li>大语言模型的迅猛发展，让较高水平的智能（具体说是人类知识的深度和广度）对普通人来说更加可及与廉价。</li><li>人脑想要形成概念，并且习得概念之间的关系，也就是知识，往往需要从一些具象的例子入手，这样比直接试图理解抽象的知识（例如数学书上晦涩的定理）更加轻松。</li><li>人在掌握概念以及知识之前，难以举出符合该规律的例子，这是一个<strong>先有鸡还是先有蛋</strong>的问题。</li><li>AI技术诞生之前，想要借助具象的例子进行学习，只能通过预先编好的例子。例如，数学上的例题。然而，这些例子的编写者（例如，大学教授）是普通人难以遇到的，也无暇针对一个具体学习者的疑问进行答疑。</li></ol><p>总结一些高质量提问的方式：</p><ol><li>让AI给自己出题</li><li>让AI针对自己的疑问进行解答</li><li>让AI了解自己的知识掌握情况和其他背景，个性化地给出建议、回答</li><li>让AI高屋建瓴地给自己描述一下知识图谱的全貌，或者规划学习路径</li><li>让AI给自己举出几个实例，这里面包括<strong>正确的和错误的</strong>例子</li><li>借助AI知识的广度，将多个领域的知识进行碰撞，探索之前没想到的可能性</li><li>让AI评价自己对问题的理解，进行“对拍”</li><li>让AI设计有趣味的学习方式，增加学习的动力</li></ol><p>上面的这些方式，大多是没有LLM，就难以做成的事情（例如随时找一个大学教授、行业专家给你答疑）。相较于以往的传统学习方式，相当于“跳步”了。可以预见的是，在未来没有一成不变的职业。懂得AI时代与传统时代学习方式差异的人，才可能比其他人学得更快更好。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Future Fortune——长期投资计算器</title>
      <link>https://shiquda.link/future-fortune/</link>
      <description>Future Fortune——长期投资计算器，开源的多维度收益可视化工具，支持总资产/投资金额/利润分析。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E9%A1%B9%E7%9B%AE/">项目</category>
      <pubDate>Sun, 09 Mar 2025 01:45:37 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>最近对投资比较感兴趣，前前后后阅读了不少投资相关的书籍和文章，也看了投资理财博主的视频、听了点财经播客。对于普通人来说，合理规划的长期投资，还是有机会实现财务自由的，至少也能让生活舒服一些。复利的力量是非常强大的，趁现在还年轻，尽早规划起来。</p><p>我开始找一下网上有没有现成的长期投资计算工具，帮助我决策和规划。确实有，但是功能都比较单一，可自定义程度达不到我的要求，例如只能计算单一标的，不支持多标的的综合规划；只能看累积金额，不能查看逐年的投入&#x2F;收益；没有考虑收益率的波动（这个暂时也没做，挖坑）……</p><p>于是，连夜借助Cursor的力量，顺带是学习一下React以及一些框架，搞出了一个工具。欢迎感兴趣的网友体验、提建议！如果觉得好用的话，也希望您赏个赏个Star~</p><p><img src="https://s2.loli.net/2025/03/09/aLw52CbxBFqNlG9.png" alt="PixPin_2025-03-09_09-51-54" loading="lazy"></p><p><img src="https://s2.loli.net/2025/03/09/2dEXzlgy1NFKrhI.png" alt="PixPin_2025-03-09_09-38-09" loading="lazy"></p><p><a href="https://shiquda.github.io/future-fortune/">Github Pages 在线体验</a></p><p><a href="https://github.com/shiquda/future-fortune">Github 开源仓库</a></p><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><ul><li>📊 交互式投资组合配置</li><li>📈 多维度收益可视化（总资产&#x2F;投资金额&#x2F;利润分析）</li><li>💾 本地存储投资配置和个人信息</li><li>📤 CSV数据导出功能</li><li>📱 响应式图表设计</li><li>🛡️ 纯前端实现，保护用户隐私</li></ul><h2 id="技术栈"><a href="#技术栈" class="headerlink" title="技术栈"></a>技术栈</h2><ul><li><strong>前端框架</strong>: React</li><li><strong>UI库</strong>: Ant Design 5.x</li><li><strong>图表库</strong>: ECharts 5.x</li><li><strong>构建工具</strong>: Vite</li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>VSCode 快捷键推荐</title>
      <link>https://shiquda.link/vscode-hotkey-suggestions/</link>
      <description>推荐一些个人认为比较顺手的VSCode快捷键。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Thu, 06 Mar 2025 06:59:21 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>这里记录一些个人认为好用的VSCode特色的键盘/鼠标快捷键。</p><p>更改快捷键的位置：</p><p><img src="https://s2.loli.net/2025/03/06/Uo1cRsfSWgl2hkP.png" alt="PixPin_2025-03-06_14-26-47" loading="lazy"></p><p>查看VSCode中指定快捷键的功能：</p><p><img src="https://s2.loli.net/2025/03/06/ohB3gaAC4SMfOwU.png" alt="PixPin_2025-03-06_14-27-39" loading="lazy"></p><div class="md-table-scroll"><table><thead><tr><th>功能</th><th>快捷键</th></tr></thead><tbody><tr><td>打开命令面板</td><td>Ctrl + Shift + P</td></tr><tr><td>快速打开文件</td><td>Ctrl + P</td></tr><tr><td>最近打开过的项目</td><td>Ctrl + R</td></tr><tr><td>复制并创建相同的代码行（duplicate）</td><td>Shift + Alt + ↓/↑</td></tr><tr><td>移动代码行</td><td>Alt + ↓/↑</td></tr><tr><td>多行编辑</td><td>鼠标中键拖动 | Ctrl + Alt + ↑ / ↓ | Alt + 分别鼠标点击</td></tr><tr><td>选中光标所在词（按一次额外多选一个同名的）</td><td>Ctrl + D</td></tr><tr><td>注释/取消注释</td><td>Ctrl + /</td></tr><tr><td>转到定义</td><td>Ctrl + 鼠标左键点击 | F12</td></tr><tr><td>删除整行</td><td>自定义（我使用Alt + D）</td></tr><tr><td>打开（收起）/ 创建底部终端</td><td>Ctrl + J / Ctrl + ~</td></tr><tr><td>撤销刚刚关闭的文件（和浏览器一样）</td><td>Ctrl + Shift + T</td></tr><tr><td>快速复制/剪切整行</td><td>Ctrl + C / Ctrl + X （前提是光标没有选中字符）</td></tr><tr><td>快速全局搜索</td><td>Ctrl + Shift + F</td></tr><tr><td>调整当前行的缩进</td><td>Ctrl + [ / Ctrl + ]</td></tr><tr><td>快速跳转文件开头/末尾</td><td>Ctrl + Home / End</td></tr><tr><td>快速横向移动光标（实际上是跳转到词首/词尾）</td><td>Ctrl + ← / →</td></tr></tbody></table></div><p>Cursor 专属：</p><div class="md-table-scroll"><table><thead><tr><th>功能</th><th>快捷键</th></tr></thead><tbody><tr><td>Ctrl + K</td><td>对选中的字段进行AI修改</td></tr><tr><td>Ctrl + L</td><td>打开/收起对话窗口</td></tr><tr><td>Ctrl + Enter</td><td>对话以codebase模式发送（让AI参考所有文件）</td></tr></tbody></table></div><p>快捷键这个东西，不需要强求，选自己用的<strong>顺手</strong>的就行了！不习惯的就去他的吧！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>git merge vs rebase</title>
      <link>https://shiquda.link/git-merge-vs-rebase/</link>
      <description>git merge vs rebase，到底用哪个？</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/git/">git</category>
      <pubDate>Sat, 01 Mar 2025 06:18:45 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>我认为 git 最神奇的一点，是能够让同一项目中不同成员不受干扰地编写各自的代码。然而，当需要合并不同成员的工作的时候，就有些麻烦了。</p><p>为了实现这个目的，有两种方式：<code>git merge</code> 与<code>git rebase</code>。这两种方法分别是什么，改用哪个？</p><p>下面用一个具体的例子来说明：</p><p>首先，假定我们已经开发了feature 1的两个任务：</p><p><img src="https://s2.loli.net/2025/03/01/HPS5waMOsz6oZlU.png" alt="Pasted image 20250301142024" loading="lazy"></p><p>然后我负责的团队需要完成feature 2的开发。我们已经完成了feature2 的部分任务，但是现在其他团队突然在feature1发现一个重要的bug，并且把它修复了，而这个修复又影响到我们feature2的开发。因此局面就变成这样：</p><p><img src="https://s2.loli.net/2025/03/01/j29m6xFQZJWECs4.png" alt="Pasted image 20250301142035" loading="lazy"></p><p>我们在继续开发feature2之前，必须整合主团队的bug修复。这时候就有两种方式：</p><h2 id="方法1-git-merge-main"><a href="#方法1-git-merge-main" class="headerlink" title="方法1:git merge main"></a>方法1:<code>git merge main</code></h2><p><img src="https://s2.loli.net/2025/03/01/yu9wcUQWtbIeCOS.png" alt="Pasted image 20250301142048" loading="lazy"></p><p>这将main分支的bug修复改动合并到了我们的feature2分支，在我们的分支上额外创建了一次提交：<code>Merge branch 'main' into feature2</code>。</p><p>我们继续开发，完成了feature2的开发任务，并将此分支最终合并到main分支。</p><p><img src="https://s2.loli.net/2025/03/01/f8SFpBVnEmg9Ihw.png" alt="Pasted image 20250301142057" loading="lazy"></p><p>此时feature2分支和main分支是完全一致的。我们发现，main&nbsp;分支的 bug修复提交通过&nbsp;merge&nbsp;提交添加到了&nbsp;<code>feature2</code>&nbsp;分支，merge提交实际上是两个分支<strong>交汇的节点</strong>。这样的好处是保留了所有的细节，但坏处是在主分支里面会出现额外的merge提交。</p><h2 id="方法2：git-rebase-main"><a href="#方法2：git-rebase-main" class="headerlink" title="方法2：git rebase main"></a>方法2：<code>git rebase main</code></h2><p>回到这一步。同样，我们需要先把main分支的改动同步到我们这个feature2分支，再继续开发。</p><p><img src="https://s2.loli.net/2025/03/01/j29m6xFQZJWECs4.png" alt="Pasted image 20250301142107" loading="lazy"></p><p>我们在feature2分支执行<code>git rebase main</code> ：</p><p><img src="https://s2.loli.net/2025/03/01/HE58VY9wqpbF4oT.png" alt="Pasted image 20250301142122" loading="lazy"></p><p>Rebase的本质是重写历史，相当于把feature2分支的改动”移植”到更新后的main分支。这一点会改动我们分支task1、task2的提交时间戳。</p><p>继续完成task3:</p><p><img src="https://s2.loli.net/2025/03/01/xazcM2i8wPmhAIU.png" alt="Pasted image 20250301142133" loading="lazy"></p><p>然后将其合并到main分支</p><p><img src="https://s2.loli.net/2025/03/01/MFegkd6A9XUuGYp.png" alt="Pasted image 20250301142141" loading="lazy"></p><p>运行<code>git merge feature2</code> 后，可以发现提交记录是一条直线。这是因为使用rebase后合并到main时，由于历史已线性化，会触发Fast-forward合并，不会产生额外合并提交。</p><p><img src="https://s2.loli.net/2025/03/01/aSIrAu4TvLVxqsW.png" alt="Pasted image 20250301142150" loading="lazy"></p><h2 id="应该如何选择merge或rebase？"><a href="#应该如何选择merge或rebase？" class="headerlink" title="应该如何选择merge或rebase？"></a>应该如何选择merge或rebase？</h2><p>下面这个表格总结了merge和rebase的比较：</p><div class="md-table-scroll"><table><thead><tr><th><strong>比较项</strong></th><th><strong>Git Merge</strong></th><th><strong>Git Rebase</strong></th></tr></thead><tbody><tr><td>提交结构</td><td>产生额外的合并提交</td><td>没有合并提交，历史线性化</td></tr><tr><td>历史记录</td><td><strong>保留完整历史</strong>，包含分支结构</td><td>创建<strong>线性、简洁</strong>的历史</td></tr><tr><td>适用场景</td><td>所有协作场景，特别是公共分支</td><td>主要用于未推送的本地分支</td></tr><tr><td>操作安全性</td><td>高，不改变现有提交</td><td>中等，会改写提交历史</td></tr><tr><td>冲突处理</td><td>一次性解决所有冲突</td><td>可能需要逐个提交解决冲突</td></tr><tr><td>代码审查</td><td>可能较难追踪特定变更</td><td>便于逐个提交进行代码审查</td></tr><tr><td>使用建议</td><td>多人协作的公共分支</td><td>个人分支或团队内部约定</td></tr></tbody></table></div><p>merge虽然会产生合并提交，让历史记录变得复杂，但是它保留了完整的分支结构，便于代码审查和问题追踪。</p><p>而rebase虽然会让历史线性化，便于管理，但是它可能会改写提交历史，导致基于原来历史开发的其他人产生误解。</p><p>如果你的分支有多个人在做，那么你rebase并强制推送到仓库，是非常不好的。因为rebase相当于改写了你这个分支的历史，会导致基于原来历史开发的其他人产生误解。</p><p>使用rebase的黄金法则是：<strong>只对「未推送」的本地分支使用 Rebase</strong>。换句话说，<strong>如果一个分支已推送到远程且可能被他人使用，那就不应该使用rebase并强制推送。</strong></p><div class="md-table-scroll"><table><thead><tr><th><strong>操作</strong></th><th><strong>安全边界</strong></th><th><strong>风险边界</strong></th></tr></thead><tbody><tr><td><code>git rebase</code>&nbsp;+ 未推送</td><td>完全安全</td><td>无</td></tr><tr><td><code>git rebase</code>&nbsp;+ 强制推送</td><td>仅限个人分支或团队共识</td><td>公共分支、协作分支</td></tr><tr><td><code>git merge</code></td><td>所有协作场景（但产生合并提交）</td><td>无（除非项目禁止合并提交）</td></tr></tbody></table></div><hr><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://medium.com/@xiaominghu19922/git-merge-vs-scary-git-rebase-5eceead4badc">Git Merge VS (Scary) Git Rebase</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Youtube 下载整个列表的视频（包括付费视频）</title>
      <link>https://shiquda.link/download-youtube-videos-from-list/</link>
      <description>使用yt-dlp开源工具批量下载整个列表的视频</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Fri, 14 Feb 2025 03:26:35 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>本教程仅提供一种解决思路。如果您有更好的免费解决方案，欢迎在评论区告诉我们。</p><p>⚠️<strong>对于付费视频，需要保证账户有观看权限。</strong></p><h2 id="工具配置"><a href="#工具配置" class="headerlink" title="工具配置"></a>工具配置</h2><p><strong>Step1 安装yt-dlp</strong></p><p><strong>方法1：直接下载二进制文件，需要自行配置环境变量</strong></p><p>以Windows为例</p><p><a href="https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe">https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe</a></p><p><strong>方法2：通过Python下载</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -U yt-dlp</span><br></pre></td></tr></tbody></table></figure><p>使用 <code>yt-dlp --version</code> 来验证是否配置成功：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2025.01.26</span><br></pre></td></tr></tbody></table></figure><p><strong>Step 2 获取油管cookie</strong></p><p>安装插件<a href="https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc">Get cookies.txt LOCALLY - Chrome 应用商店</a></p><p>在油管点击扩展，下载Cookie为Netscape格式的txt文件。</p><p>注意⚠️：笔者在尝试的时候，如果网页端油管打开，可能会造成cookie刷新，导致原来获取的cookie失效。可以使用一个不常用的浏览器或是开无痕模式，获取cookie。</p><h2 id="下载命令"><a href="#下载命令" class="headerlink" title="下载命令"></a>下载命令</h2><p>需要自行配置网络环境。更多关于yt-dlp的命令和参数，可以查看：</p><p><a href="https://github.com/yt-dlp/yt-dlp">yt-dlp/yt-dlp: A feature-rich command-line audio/video downloader</a></p><p>执行下面的命令：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yt-dlp [列表URL] -f mp4 --cookies [cookies.txt的路径]</span><br></pre></td></tr></tbody></table></figure><p>例如：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yt-dlp https://www.youtube.com/playlist?list=PLZHQObOWTQDOMxJDswBaLu8xBMKxSTvg8 -f mp4 --cookies youtube.com_cookies.txt</span><br></pre></td></tr></tbody></table></figure><p>随后程序就会自动下载视频列表中的所有视频了。视频默认位置是当前目录。对于付费视频，需要保证cookie账户有观看权限。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>2024++</title>
      <link>https://shiquda.link/2024-plus-plus/</link>
      <description>++2024 == 2025</description>
      <author>shiquda</author>
      <pubDate>Sat, 11 Jan 2025 06:59:17 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="回顾-2024"><a href="#回顾-2024" class="headerlink" title="回顾 2024"></a>回顾 2024</h2><p>不知不觉，开始写博客已经一年多了。写博客是一种凝练知识的方式，是传递知识的一种方式，也是和网友交流的一种方式。</p><ul><li><strong>凝练知识</strong>：撰写博文是一种重新组织某些逻辑的过程，能够加深自我对知识的理解。从自己了解知识，到能够讲述给读者，让其看懂你的想法，这就是一种进步。也就是所谓的“费曼学习法”。</li><li><strong>传递知识</strong>：我会将我日常遇到的一些问题的解决方案（尤其是网络上我查找过后没有方案，自己摸索解决的），分享到博客上。这么做相当于是丰富整个中文互联网的内容吧，让我更惊喜的是，不少文章确实帮助到他人来解决这个问题，他们在博文下面评论感谢我，非常感谢他们，让我的价值感提升了。</li></ul><p>感谢所有在过去一年阅读我的文字的读者。</p><p>下面从几个方面回顾一下博主的2024。</p><h3 id="博文"><a href="#博文" class="headerlink" title="博文"></a>博文</h3><p>去年印象最深刻的就是尝试编写了《<em>寻觅周刊</em>》，旨在让更多人了解一些趁手的工具、有用的资源和优质的信息源。不幸的是，该周刊只进行了6周就草草收场，主要原因还是自己对做这件事情的本质认识还不是非常充分，把分享从一种权利变为了一种义务。分享让我快乐的是分享的结果，而不是过程。</p><p>特别感谢一位使用邮件和我交流的网友，TA给我分享了一些建议，比如说降低自己对这类文章的期望，让我受用很多，更加深了我原先的想法。</p><p><img src="https://s2.loli.net/2025/01/11/s6k9SVZFLgaWz8v.png" alt="PixPin_2025-01-11_15-22-01" loading="lazy"></p><p>其次一篇文章是我写的面向小白的《浏览器扩展逆向指北》。这是我有史以来写的耗时最长的一篇文章，还依稀记得是从早上写到太阳落山。虽然文章的技术性和专业性并不强，但是能够帮助一些和我一样的技术小白大致了解这个过程，也是挺有收获的。这篇文章我也发布到linux.do，并且很幸运地被站长加上了精华。</p><p>另外，2024还试着运营了一个<a href="https://t.me/crxcccc">TG频道</a>，主要分享一些浏览器插件的逆向资源和实用的插件推荐，里面会随缘推送一些我认为好用的插件。</p><h3 id="项目"><a href="#项目" class="headerlink" title="项目"></a>项目</h3><p>2024 算是迈出做简单项目的一小步，主要有：</p><ul><li><a href="https://github.com/shiquda/wereadcard">shiquda&#x2F;wereadcard: 微信读书卡片生成器</a> 基于Python的微信读书卡片生成器，支持GitHub Actions自动更新。</li><li><a href="https://github.com/shiquda/one-competition">shiquda&#x2F;one-competition</a> 和小组同学一同完成的课设，技术栈是Vue.js+Django，网站主要展示大学生的竞赛信息。有计划以后修改一下，依托Github平台做成一个由开源社区维护的大学生竞赛信息汇集平台。</li><li><a href="https://github.com/shiquda/crypto-monitor">shiquda&#x2F;crypto-monitor: A simple cross-platform crypto monitor that monitors the price of crypto currencies.</a> 桌面端的加密货币盯盘小工具，基于wails。</li></ul><p>参与了以下开源项目的贡献：</p><ul><li><a href="https://github.com/RSSNext/Follow">RSSNext&#x2F;Follow: 🧡 Follow your favorites in one inbox</a></li><li><a href="https://github.com/Ac-Wiki/AcWiKi">Ac-Wiki&#x2F;AcWiKi: 属于大学生群体的真·青年大学习</a></li><li><a href="https://github.com/word-hunter/word-hunter">word-hunter&#x2F;word-hunter: Discover new english words you don’t know on any web page</a></li></ul><h3 id="阅读"><a href="#阅读" class="headerlink" title="阅读"></a>阅读</h3><p>读书，是一种和比你层次更高的人交流的捷径。</p><p>我喜欢使用电子书阅读。一是方便，抄起手机等点子设备就能读；二是能够“量化”自己的知识，画线和想法能够导出为文本，减少重复的脑力劳动。这一点不只让我有“虚假的成就感”，也能利用readwise等平台来汇总回顾。</p><p>2024年，我在微信读书阅读了139小时。</p><p>读完书的有：</p><ul><li>《打开心智》：讲述人的心智的运行机制。</li><li>《昨日的世界》</li><li>《置身事内：中国政府与经济发展》：讲述中国政府和经济的关系，以及他们的运行逻辑。</li><li>《认知觉醒》</li><li>《邓小平时代》</li><li>《博弈论究竟是什么》：一本通俗的博弈论入门小册子，挺有意思，它能让你发现原来生活中很多地方都潜藏着博弈论的运用。</li><li>《乌合之众》</li><li>《学会提问》：其实是一本讲述批判性思维的好书。</li><li>《在峡江的转弯处：陈行甲人生笔记》：一个鲜活而生动的人，清廉而官至县委书记，又离开官场投身慈善。有几章令人落泪。</li><li>《局外人》</li><li>《提问的智慧》</li></ul><p>没看完的，但认为是好书：</p><ul><li>《为什么》：因果推断科学</li><li>《吴军：信息论40讲》</li><li>《日本史》</li><li>《财富自由之路》</li></ul><p>在读&#x2F;准备读的书：</p><ul><li>《郭建龙“密码三部曲”》</li><li>《社会契约论》</li><li>《黄仁勋：英伟达之芯》</li><li>《可能性的艺术：比较政治学30讲》</li><li>《真需求》</li><li>《见证逆潮》</li><li>《为什么我们总是在防御》</li></ul><h3 id="播客"><a href="#播客" class="headerlink" title="播客"></a>播客</h3><p>播客是我在下半年接触到的一种对我来说全新的媒介，到现在也算听了将近半年了，思考见<a href="/why-is-podcast-special">《播客的独特之处》</a>。</p><p>分享一些我认为优质的播客：</p><ul><li>社会类：<ul><li>《忽左忽右》：历史与社会</li><li>《半拿铁 | 商业沉浮录》</li><li>《虚实之间》</li></ul></li><li>投资财经类：<ul><li>《三点下班》</li><li>《投资实战派》</li><li>《知本论》</li></ul></li><li>访谈类：<ul><li>《无人知晓》：里面有一集采访了前面提到的陈行甲先生，看完书再听那期节目，真的感觉陈先生是一个非常鲜活、坦率、令人尊敬的人。</li></ul></li></ul><h2 id="2024"><a href="#2024" class="headerlink" title="2024++"></a>2024++</h2><p>展望2025，我认为最重要的今年目标的主题是：<strong>行动</strong>。</p><p>“为什么我们懂得很多道理，却依然过不好这一生？”我觉得很重要的一点原因，是没有下定决心去迈出的第一步，以及持续的后续执行力。我自认为是一个三分钟热度的人：什么都了解一些，做事情刚开始很有热情，但是这种热情很容易因为无情的时间而消散。我希望我能在2025年中找到答案。并且是行动的答案。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>利用AHK实现在Zotero中使用侧键返回</title>
      <link>https://shiquda.link/use-ahk-to-implement-back-navigation-with-side-button-of-mouse-in-zotero/</link>
      <description>利用AHK脚本，实现在Zotero中使用侧键返回</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/ahk/">ahk</category>
      <pubDate>Thu, 02 Jan 2025 13:26:56 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Zotero是一款开源免费的科研文献管理工具，其插件生态非常丰富，用以进行科研活动十分方便。但是博主使用的时候，有一点让我非常不习惯：在文献中经常需要进行跳转，例如点击目录、参考文献等，跳转时候需要返回的时候，就只能用鼠标点击上方的返回按钮，不能像浏览器等其他软件一样使用鼠标侧键返回。</p><p>受网友启发，使用AHK编写一个简单的脚本，就可以把鼠标侧键映射到为返回的快捷键了，对我来说用起来十分顺手。</p><p>Zotero 和 autoHotKey 的使用方式不再赘述，烦请读者自行查阅了解。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight ahk"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#Requires AutoHotkey v2.0</span></span><br><span class="line"><span class="meta"></span></span><br><span class="line"><span class="meta">#HotIf WinActive("ahk_exe zotero.exe")</span></span><br><span class="line"><span class="title">XButton1::</span>Send <span class="string">"{AltDown}{Left}{AltUp}"</span></span><br><span class="line"><span class="title">XButton2::</span>Send <span class="string">"{AltDown}{Right}{AltUp}"</span></span><br><span class="line"><span class="meta">#HotIf</span></span><br></pre></td></tr></tbody></table></figure><p>在Windows端，若想开机运行该脚本，将该<code>.ahk</code>脚本文件放置在<code>shell:startup</code>目录下即可。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>LLM提示词的简单技巧：STAR</title>
      <link>https://shiquda.link/tip-on-llm-prompt-star/</link>
      <description>使用STAR法则优化LLM的提示词</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/%E5%AD%A6%E4%B9%A0/">学习</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <category domain="https://shiquda.link/tags/LLM/">LLM</category>
      <pubDate>Sat, 28 Dec 2024 08:41:50 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="STAR法则"><a href="#STAR法则" class="headerlink" title="STAR法则"></a>STAR法则</h2><p><img src="https://s2.loli.net/2024/12/28/ExtMslWNuV9PBpG.png" alt="PixPin_2024-12-28_16-38-22" loading="lazy"></p><ul><li>S: Situation，背景信息</li><li>T: Task，任务目标</li><li>A: Audience，受众</li><li>R: Requirements，输出要求</li></ul><p>在提问的时候，给LLM（大语言模型）提供上面四个不同维度的信息，可以让LLM生成更优质的回复。</p><p>举一个例子：</p><blockquote><p>提问：</p></blockquote><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">介绍一下下面的概念：</span><br><span class="line">附加律</span><br><span class="line">化简律</span><br><span class="line">假言推理</span><br><span class="line">拒取式</span><br><span class="line">析取三段论</span><br><span class="line">假言三段论</span><br><span class="line">等价三段论</span><br><span class="line">构造性二难</span><br><span class="line">构造性二难（特殊形式）</span><br><span class="line">破坏性二难</span><br></pre></td></tr></tbody></table></figure><blockquote><p>回答：</p><p>这些概念主要来自逻辑学，尤其是命题逻辑和推理规则。以下是它们的简要介绍：</p><ol><li>附加律 (Addition)<br><strong>附加律</strong> 是命题逻辑中的一条推理规则，形式为：</li></ol><ul><li>如果 ( P ) 为真，那么 ( P \lor Q ) 也为真，无论 ( Q ) 是什么命题。</li><li>即：从 ( P ) 可以推出 ( P \lor Q )。</li></ul><ol start="2"><li>化简律 (Simplification)<br><strong>化简律</strong> 是命题逻辑中的一条推理规则，形式为：</li></ol><ul><li>如果 ( P \land Q ) 为真，那么 ( P ) 为真，且 ( Q ) 为真。</li><li>即：从 ( P \land Q ) 可以推出 ( P ) 或 ( Q )。</li></ul><ol start="3"><li>假言推理 (Modus Ponens)<br><strong>假言推理</strong> 是命题逻辑中的一条基本推理规则，形式为：</li></ol><ul><li>如果 ( P \rightarrow Q ) 为真，且 ( P ) 为真，那么 ( Q ) 为真。</li><li>即：从 ( P \rightarrow Q ) 和 ( P ) 可以推出 ( Q )。<br>……</li></ul><p>这些推理规则在逻辑推理和数学证明中非常有用，帮助我们从已知的命题中推导出新的命题。</p></blockquote><p>使用STAR优化的提问：</p><p><img src="https://s2.loli.net/2024/12/28/n81j7FSistecNkm.png" alt="PixPin_2024-12-28_16-48-58" loading="lazy"></p><blockquote><p>回答：</p><p>好的，同学们，期末备考紧张吧？别担心，我来给你们“翻译”一下这些离散数学的概念，保证你们笑出声的同时还能记住！</p><ol><li><p><strong>附加律</strong>：<br>这就像你已经有了一包薯片，但你觉得不够，又买了一包。逻辑上就是：如果你知道A是真的，那A∨B（A或B）也肯定是真的。反正A已经在了，B来不来都无所谓，薯片已经到手了！</p></li><li><p><strong>化简律</strong>：<br>这就像你买了一堆东西，结果发现只用了其中一样。逻辑上就是：如果A∧B（A和B）是真的，那A肯定是真的。别管B了，A已经够用了！</p></li><li><p><strong>假言推理</strong>：<br>这就像“如果今天下雨，我就带伞”。结果今天真的下雨了，那你肯定带伞了。逻辑上就是：如果A→B（A推出B），且A是真的，那B也是真的。别淋雨了，带伞吧！</p></li></ol><p>……</p><p>怎么样？是不是感觉这些概念没那么可怕了？记住，逻辑就像生活，有时候选择多了反而简单！加油备考，你们一定能行的！</p></blockquote><p>使用Deepseek官网的默认模型对话进行测试，效果差异非常明显。</p><h2 id="提示词优化输出的本质"><a href="#提示词优化输出的本质" class="headerlink" title="提示词优化输出的本质"></a>提示词优化输出的本质</h2><p>相信你应该有听说过提示词能够优化输出。比如说：</p><blockquote><p>假如你是一个经验丰富的Python程序员。现在请你xxx……</p></blockquote><p>这样的“套路化”的提示词，似乎是能够提升一些回复质量的。</p><p>现在主流厂家的LLM也在不断的进步。不少产品已经能够自动对用户的需求进行预测和优化了，由提示词带来的提示的边际效应已经初步显现。那么，在这样的情况下，写好的提示词的意义是什么呢？</p><p>我认为从本质上来说，<strong>优秀的提示词能够给LLM提供更多的信息，这些信息能帮助LLM生成更符合用户预期的内容</strong>。</p><p>很多用户会觉得LLM“不懂我”，但是其实有可能是用户并没有提供给LLM足够多的背景信息。LLM又不是他们肚子里的蛔虫，怎么会知道用户的具体需求呢？😄</p><h2 id="这样不麻烦吗？"><a href="#这样不麻烦吗？" class="headerlink" title="这样不麻烦吗？"></a>这样不麻烦吗？</h2><p>你可能会问，每次提问都这么写提示词，不觉得很麻烦吗？</p><p>这个问题的答案取决于你的需求。如果是比较简单的问题，比如说你只想让LLM作简单的翻译，让你能够看懂就行了，那确实并没有太大的必要。</p><p>但如果是相对重要一些的需求，比如说帮你润色文稿之类的任务，那我还是推荐这么写一下。毕竟一次让LLM获得让你更满意的回复，总比多次去调教好。</p><hr><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://www.bilibili.com/video/BV1RNidYCEdq/">【进阶教程】一套连招，彻底释放AI的写作能力_哔哩哔哩_bilibili</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>赚钱的三个层次</title>
      <link>https://shiquda.link/three-levels-of-earning/</link>
      <description>
        <![CDATA[1份劳动->1份回报、1份劳动->x份回报和1份回报->x份回报]]>
      </description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E9%9A%8F%E6%83%B3/">随想</category>
      <pubDate>Sun, 15 Dec 2024 02:59:31 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>本文是博主的一些随想，在专业性上难免有不足之处，若有错误欢迎交流指正。</p><hr><p>很多人都想赚钱。我们暂且不谈赚钱是为了什么，只从赚钱这个行为本身，探讨一下“赚钱”与“赚钱”之间的区别。</p><h2 id="Level-1：1份劳动-1份回报"><a href="#Level-1：1份劳动-1份回报" class="headerlink" title="Level 1：1份劳动-&gt;1份回报"></a>Level 1：1份劳动-&gt;1份回报</h2><p>说到赚钱，大部分人所做的工作，实质上应该都属于这一类：<strong>1份劳动-&gt;1份回报</strong>。也就是说，付出的时间和精力，譬如说上一天班、送一份外卖，可预见地只能获得一次回报。</p><p>虽然说工作与工作之间的收入差异是巨大的，但是它们都没有更大的“想象空间”，本质上来说还是<strong>劳动和回报的直接交易</strong>。</p><h2 id="Level-2：1份劳动-x份回报"><a href="#Level-2：1份劳动-x份回报" class="headerlink" title="Level 2：1份劳动-&gt;x份回报"></a>Level 2：1份劳动-&gt;x份回报</h2><p>有一些工作可能有这样的属性：做出<strong>1份劳动之后，收到的是多次回报</strong>。而这种回报往往具有不确定性，这意味着它的想象空间是巨大的。这里不包括除了领工资，还拿奖金、津贴之类的情况，这些情况从本质上来说，还是属于可预见的范畴。</p><p>举一个例子，从大的说，公司申请一份专利，就可以不断靠收授权费获利；从小的说，一个独立开发者开发了一个软件，以此收费盈利。这两个例子中，获利的预期是未知的，而劳动的主体在劳动之后，不需要再次劳动（或者仅需要付出极低的成本），即可获取多次收益。</p><p>我自己的一个简单经历是，在网上搜集了一些资源（资源还是有一定付费门槛的），上传到各个网盘里面，然后挂到闲鱼上面卖。除了我搜集资源付出的时间和精力以外，我付出的后续成本就是闲鱼发货机器人的订阅成本：120一年。两个月内，仅一个商品，我就已经收回成本，并且盈利了数倍。数额虽然不多，但让我体会到了<strong>1份劳动-&gt;x份回报</strong>和<strong>1份劳动-&gt;1份回报</strong>的区别。</p><blockquote><p>其实开发发货机器人的做的工作，和我是类似的，开发的成本可以获得x份回报，后续只需要一些服务器的维护成本和更新成本就行了。他们先前付出的劳动，仍然会在数年后继续为他们赚取收益。</p></blockquote><h2 id="Level-3：1份回报-x份回报"><a href="#Level-3：1份回报-x份回报" class="headerlink" title="Level 3：1份回报-&gt;x份回报"></a>Level 3：1份回报-&gt;x份回报</h2><p>看到这个标题，可能会比较差异：怎么回报也能赚取回报呢？当然了。</p><p>这种是真正赚大钱，甚至影响世界金融格局的方法：<strong>钱生钱</strong>。世界上许多富豪和金融巨头正是通过这种方式积累了巨额财富。钱生钱的核心理念在于通过各种投资手段，让你的已有资金不断增值，而不是单纯依靠<strong>劳动-&gt;回报</strong>的简单交换。</p><p>复利被称为“世界第八大奇迹”，其威力在于不仅本金在增长，利息也在不断产生更多的利息。</p><blockquote><p>举例来说，假设你投资了100万元，年利率为10%，一年后你将获得10万元的利息。如果将这10万元的利息继续投资，第二年你的总资本将增长到121万元，而不仅仅是110万元。长期来看，复利效果会让你的财富呈指数级增长。</p></blockquote><p><img src="https://s2.loli.net/2024/12/15/biEaq9pxsc7GjID.png" alt="Pasted image 20241215105350" loading="lazy"></p><p><del>当然，这种做法的门槛和风险绝对不是普通人能够驾驭的，能够赚到钱的始终是极少数</del>。</p><p>普通人也能做好投资。前提是要有足够的金融储备和经验。学习投资是一项回报丰富的“元投资”。</p><h2 id="Level-x：投资自我"><a href="#Level-x：投资自我" class="headerlink" title="Level x：投资自我"></a>Level x：投资自我</h2><p>其实，有一种“稳赚不赔”的买卖，那就是投资自我，提示自我的能力。从功利的角度来讲，这样做能够提升自我赚钱的层级。</p><p>当然，这里说的投资自我，不是简单的学一些<strong>技术型</strong>的技能，比如说去考个普通话二级、计算机二级证书，而是投资那些能够提升自我<strong>认知</strong>的技能。你怎么样去和别人交往、怎么样去理解这个世界的运行逻辑、怎么样理解个人的意义等等。这项投资带来的回报是未知的，它产生的蝴蝶效应会影响我们的一生。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Crypto Monitor：跨平台的币圈桌面盯盘悬浮窗</title>
      <link>https://shiquda.link/introducing-crypto-monitor/</link>
      <description>本文是博主最近开发的 Crypto Monitor 盯盘小工具的介绍。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/Go/">Go</category>
      <category domain="https://shiquda.link/tags/Vue/">Vue</category>
      <pubDate>Sun, 01 Dec 2024 08:36:51 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><strong>币圈有风险，本文不构成任何投资建议。</strong></p><h2 id="缘由（请随意跳过）"><a href="#缘由（请随意跳过）" class="headerlink" title="缘由（请随意跳过）"></a>缘由（请随意跳过）</h2><p>这几天了解了一下币圈的一些知识，然后也是亲自下场试了下水。手机端对应的交易所APP都有类似悬浮窗的功能，但是电脑端我目前还没有发现一个非常让我满意的，之前只能是浏览器挂着好几个窗口，这样看就不是很方便。</p><p>有部分桌面端的这类产品甚至还在Microsoft store上收费，在我花了一点时间破解之后，发现做的真的是一坨，一言难尽的那种。花钱请我用我都不想用😅</p><p>周末刚好闲下来，本来是之前已知想要学习Go的，但是一直没有时间实践，突然在我的点子清单里面翻到了这个点子：做一个电脑的盯盘悬浮窗软件。</p><p>我想，它最好是比较<strong>美观</strong>的、<strong>跨平台</strong>的、<strong>轻量级</strong>的。</p><p>说干就干，周六下午开始过一遍Go的基本语法，然后晚上问了一下AI，哪些轻量级的Go框架适合做这种跨平台的小软件。在一番拉扯之后，TA告诉我使用 <a href="https://fyne.io/">Fyne</a>是一个不错的选择。</p><p>然后。。。一晚上就白干了。</p><p>后来在实战开发时候，我发现这个框架虽然在GitHub上有25k的Star，但是用起来却感觉非常生硬（也有可能是我没深入学吧），并且很多我需要的方法竟然没有（e.g.，最重要的置顶功能）。我查了下，有用户在Issue里面提出了这个建议，但是过了三年了开发者还是没有选择加入这个功能。后面我真得绷不住了，觉得还是问一些真人比较靠谱，于是在Google一番搜索，跌跌撞撞回到了L站（不得不说SEO是真的顶😄）</p><p><a href="https://linux.do/t/topic/115324/19">https://linux.do/t/topic/115324/19</a></p><p>这个帖子，在此对所有参与的网友进行感谢，里面有网友给我指指明了方向：<a href="https://wails.io/">wails</a>。</p><p>Wails 是一个用 Go 和 Web 技术编写桌面应用的项目。刚好我对前端相对熟悉，之前也学了一些Vue的皮毛，还算好上手，于是说干就干，我狠心把之前写的fyne全删了，除了后端的api请求一个不留，硬是肝到了凌晨两点，早上七点多起来接着写，写到不久前才算完成。</p><p>这里面有一个坑耽搁了我很久。因为我想要做跨平台的一个桌面端软件，而我只用Windows和Linux环境，没有MacOS环境，因此打算利用GitHub Actions来打包。但是我对Actions也说不上多熟悉，更重要的是对MacOS的特性（例如，软件是如何安装的、打包的）一无所知😅，于是这个地方调了十几次才跑通。GitHub Actions 一直没找到一个很好的方法来调试，我只能不断地试错，然后问Cursor，根据可怜的输出来不断重试，而每次重试都需要经历三四分钟的build时间。</p><p>虽然Windows的安装包好像还有些问题，似乎和可执行文件是一样的，但是可执行文件算是还能跑。还是先这样吧，能跑就行，等我缓过来啥时候想写了再改。。</p><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p><img src="https://github.com/shiquda/crypto-monitor/blob/main/imgs/crypto-monitor.png?raw=true" alt="Crypto Monitor" loading="lazy"></p><p>最终这个小Widget的雏形终于是完成了：</p><p><img src="https://s2.loli.net/2024/12/01/LYczp3Vv9BFwfld.gif" alt="PixPin_2024-12-01_16-12-57" loading="lazy"></p><p>技术栈：</p><ul><li>Wails</li><li>Vue</li></ul><p>现在的功能还比较简陋，除了基础的置顶、最小化和关闭，只有简单的添加和删除币对的功能。后续会考虑再加其他功能的（挖坑）。</p><p>更多细节可以前往<a href="https://github.com/shiquda/crypto-monitor">Github</a>查看。喜欢的可以赏个Star~</p><p>下载：</p><p><a href="https://github.com/shiquda/crypto-monitor/releases/">https://github.com/shiquda/crypto-monitor/releases/</a></p><p>限于博主的技术水平，难免有不少问题，有任何意见和建议也可以随意提出，会抽空改进的~</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p><del>偷偷开了个新树洞：<a href="https://cry.shiquda.link/">cry.shiquda.link</a></del></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>播客的独特之处</title>
      <link>https://shiquda.link/why-is-podcast-special/</link>
      <description>播客作为一种信息传播媒介，填补了文字和视频之间的空白，提供高质量、亲切且沉浸的听觉体验，适合碎片化时间。尽管在中国普及率较低，但其内容丰富、订阅方式灵活，值得尝试。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/tags/%E9%9A%8F%E6%83%B3/">随想</category>
      <pubDate>Mon, 11 Nov 2024 14:00:48 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="在前面随便讲几句"><a href="#在前面随便讲几句" class="headerlink" title="在前面随便讲几句"></a>在前面随便讲几句</h2><p>对播客这个概念，我也记不得是什么时候开始听说的，属于是只知其名，未见其形的那种东西。总之从结果来看，我在是在大概一个月前开始真正亲自收听一些播客节目的。在不断的收听过程中，也有一些即兴的想法，遂记录一番。</p><h2 id="什么让播客如此独特？"><a href="#什么让播客如此独特？" class="headerlink" title="什么让播客如此独特？"></a>什么让播客如此独特？</h2><h3 id="形式恰到好处"><a href="#形式恰到好处" class="headerlink" title="形式恰到好处"></a>形式恰到好处</h3><p>在我眼里，播客是一种形式上处于<strong>中间形态</strong>的信息传播媒介。在接触之前，也许感觉播客有一些另类，认为它的定位有些不上不下，既不像视频那样有意思、易懂，又不像文字那样显得直接、朴素。但是真正亲自接触后，听着听着发现，恰恰是在生活中的一些受限于时空的碎片化时段，在可能不太适合阅读文字或是观看视频的时候，也许听播客是一个比较不错的选择，比如开车、地铁、走路、做家务甚至睡前等。</p><p>仅从结果来看，我认为播客填补了介于文字和视频媒体之间的一个“真空”区。从<strong>信息量</strong>（注意，区别于信息密度）来看，应该是<code>视频＞播客＞文字</code>。文字更适合一个人在相对静态的时候进行阅读和感悟，视频则更加大众化，信息量更高，理论上可以包含画面、音频、文字等形式，但往往也会导致了信息密度较低。其实一些信息密度主要不是由其画面提供的视频，我也会当作播客来听。</p><p>举一个例子，对于文字，我们可以进行方便的检索，甚至使用大模型进行总结，而对播客进行总结，难度较高，如果使用语音转文字工具的话，难免会丢失不少文字以外的信息。更不要说对视频进行浓缩和总结了。视频的信息分布在多个维度，可能丢失的信息之大，可想而知。</p><p>文字、语言，这两个概念之间还是有显著的区别的。文字，是一种符号，本质来说是一种对信息的单维度的朴素编码。而在和别人说话的时候，除了提供文字信息以外，还包含了语气、神态、动作等更多维度的信息。应该来说，语言的信息量是远大于文字的。</p><p>人与人面对面交流的时候，信息量是最大的，播客虽然无法看到对方的神态、动作，但是还是能通过对方的语气、反应等特征，获得更多维度的信息。</p><p>总结一下，<strong>播客这种看似尴尬的中间形态，却很好的填补了生活中获取信息的时空空白区域。</strong></p><h3 id="亲切感与沉浸感"><a href="#亲切感与沉浸感" class="headerlink" title="亲切感与沉浸感"></a>亲切感与沉浸感</h3><p>从我自己的角度来看，收听播客，不管节目中是单个人在讲“单口相声”，还是多人进行访谈，都有一种<strong>亲切感</strong>，仿佛自己就坐在演播室旁边“偷听”，这让我更加容易接受播客的信息。有人可能会说，那视频类访谈，不是更逼真吗？我觉得，画面信息的缺失，其实在某种程度上是一种<strong>留白</strong>，能让你更加专注，以“弥补”这种画面的缺失，同时让你更注重于内容本身。</p><p>从我个人体验来说，一个能支持这种观点的现象是，我在听播客的时候，很少使用快进功能，这一点与视频截然不同。这或许在一方面和不便点击快进有关，但另一方面，我确实感觉自己更注重于内容本身了。</p><h3 id="信息质量较高"><a href="#信息质量较高" class="headerlink" title="信息质量较高"></a>信息质量较高</h3><p>有网友认为是一种“精英”媒介，说听播客的人往往都是收入程度和教育程度相对较高的人。至少从我听到的来看，内容信息质量高的不在少数。</p><p>每个人可以选择自己感兴趣的领域，选择一些自认为不错的节目，利用播客软件进行订阅，思想和RSS有些类似，从技术上来说也是使用RSS这样的手段实现的。这实际上也是一种对推荐算法说不的手段。</p><p>并不是说收听播客，和刷短视频相比，好像是多么“高人一等”的事情：这只是两种获取信息的不同媒介。但是事实上，了解播客是什么，并且愿意尝试的人，至少在中国，还是比较少的。这就引出了另一个方面：普及率。</p><h3 id="普及率低"><a href="#普及率低" class="headerlink" title="普及率低"></a>普及率低</h3><p>在美国，收听播客其实是一件比较普遍的事情，有一半左右的美国人会收听播客。从环境生态上来讲，大平台如苹果、Spotify等，也掌握了不少播客的资源。而在中国，<strong>受众</strong>面则明显小得多。从<strong>创作者</strong>的角度来看，也还没有像海外那么成熟的盈利模式，这意味很多播客很难持续产出。这点从我发掘优质播客的时候，翻找往年的推荐文章，却发现不少已经在几年前停更，可以得到映证。</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>以上是我初次尝试播客这种媒介后的一些随想。不出意外的话，我想我是获得了一个不错的新的信息来源，在可预见的未来也会继续听听。如果你还没有接触播客的话，不妨也试试，看看这种媒介符不符合你的口味。</p><p><a href="https://www.v2ex.com/t/1088094">这个帖子</a>是我在V2EX发出的一个播客征求贴，收到了不少热心网友的优质播客。如果感兴趣的话，也可以看看。</p><p>如果你使用安卓手机，可以尝试一下<a href="https://antennapod.org/">AntennaPod</a>这款播客软件，免费开源，简洁好用。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第6期：告别</title>
      <link>https://shiquda.link/seeking-weekly-6/</link>
      <description>寻觅周刊 第6期：告别</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Sun, 20 Oct 2024 07:27:55 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="🤔前言"><a href="#🤔前言" class="headerlink" title="🤔前言"></a>🤔前言</h2><p>本期是<em>寻觅周刊</em>的第6期。同时也很可能是最后一期。</p><p><em>寻觅周刊</em>是我的一次大胆尝试，一个多月前我萌生了这个朴素的想法：</p><blockquote><p><strong>用尽可能少的时间，获取到尽可能优质的信息</strong>。</p></blockquote><p>但是，随着一周周更新节点的到来，从<strong>功利</strong>的角度来说，我发现这样做让我变得很被动，而且我从中并没有受益很多。</p><p>从功利的角度来说，撰写一些技术类、思考类文章，做这些工作会让我收益：这是<strong>费曼学习法</strong>的一种体现，也就是说<strong>分享的主体在教中学</strong>，受益的是作者和读者双方。</p><p>然而，<em>寻觅周刊</em>这类优质信息的汇集，从某种意义上来讲，<strong>是没有创造性和门槛</strong>的，在整理的过程中，我也很难从中受益。</p><p>在刚创办之初，我会留心当周见到的优质信息，并且进行记录，再到周末进行撰写和分享。然而，经过无情的时间的考验，当初的那种分享的热情被雪藏了，从<strong>热情</strong>转变成了一种被动地“<strong>赶工</strong>”，从我的一项<strong>权利</strong>变为了<strong>义务</strong>，尽管没有任何人<strong>要求</strong>我这么做。</p><p><strong>在那一刻我意识到，应该对读者说声再见了。</strong></p><p>我意识到，其实我享受的是分享的结果，而不是过程。能够让更多人找到优质的信息，这让我很快乐，但是我不愿意承受的，是分享的过程。这二者很难权衡。</p><p>也许是“周刊”限制了我。从自己的私利看问题，也许我需要的是即时的分享、即时的快乐吧。停办周刊不意味着我不再喜欢分享，我认为我也许需要切换一种形式，比如运营一个Telegram频道，撰写公众号文章，或者是其他暂时没想到的形式。<strong>我想要在认为时机成熟之后，能立即分享</strong>。希望能够再次和读者见面。</p><p>感谢您的阅读。不管您是周刊多期的读者，亦或是初次相逢，请允许我向您表达谢意和歉意。</p><p>👋</p><p><del>欢迎订阅本周刊的<a href="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/rss.xml">RSS</a>。</del></p><h2 id="ℹ️信源版"><a href="#ℹ️信源版" class="headerlink" title="ℹ️信源版"></a>ℹ️信源版</h2><h3 id="🐑Yummy’s-Blog：分享流媒体订阅、薅羊毛等信息"><a href="#🐑Yummy’s-Blog：分享流媒体订阅、薅羊毛等信息" class="headerlink" title="🐑Yummy’s Blog：分享流媒体订阅、薅羊毛等信息"></a>🐑Yummy’s Blog：分享流媒体订阅、薅羊毛等信息</h3><p><a href="https://yummy.best/">Yummy’s Blog 各类教程资讯整合</a></p><h3 id="韭菜生活：分享投资、金融知识"><a href="#韭菜生活：分享投资、金融知识" class="headerlink" title="韭菜生活：分享投资、金融知识"></a>韭菜生活：分享投资、金融知识</h3><p><a href="https://blog.chives.life/">韭菜生活</a></p><h2 id="📂资源版"><a href="#📂资源版" class="headerlink" title="📂资源版"></a>📂资源版</h2><p>本期无资源推荐。</p><h2 id="🔧工具版"><a href="#🔧工具版" class="headerlink" title="🔧工具版"></a>🔧工具版</h2><h3 id="Vimium-C：像Vim一样操作浏览器"><a href="#Vimium-C：像Vim一样操作浏览器" class="headerlink" title="Vimium C：像Vim一样操作浏览器"></a>Vimium C：像Vim一样操作浏览器</h3><p><a href="https://chromewebstore.google.com/detail/vimium-c-%E5%85%A8%E9%94%AE%E7%9B%98%E6%93%8D%E4%BD%9C%E6%B5%8F%E8%A7%88%E5%99%A8/hfjbmagddngcpeloejdejnfgbamkjaeg">Vimium C - 全键盘操作浏览器 - Chrome 应用商店</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第5期：emoji</title>
      <link>https://shiquda.link/seeking-weekly-5/</link>
      <description>寻觅周刊 第5期：emoji</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Sun, 13 Oct 2024 07:27:55 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="🤔前言"><a href="#🤔前言" class="headerlink" title="🤔前言"></a>🤔前言</h2><p>本期是<em>寻觅周刊</em>的第5期。</p><p>给本周刊起标题真是一个难活。周刊的性质就决定了，每期分享很难有一个“主题”，因此在考虑要不要删除这个形式上的“主题”。本期暂且使用“emoji”吧。详情见后文。</p><p>欢迎订阅本周刊的<a href="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/rss.xml">RSS</a>。</p><h2 id="ℹ️信源版"><a href="#ℹ️信源版" class="headerlink" title="ℹ️信源版"></a>ℹ️信源版</h2><h3 id="🤖AIGC-weekly：AI-热爱者的周刊"><a href="#🤖AIGC-weekly：AI-热爱者的周刊" class="headerlink" title="🤖AIGC weekly：AI 热爱者的周刊"></a>🤖AIGC weekly：AI 热爱者的周刊</h3><p><a href="https://quail.ink/op7418">AIGC weekly</a> 是一个关注于最新 AIGC 领域的周刊，聚焦于国内外 AI 领域动态、模型、产品等资讯。</p><p><img src="https://s2.loli.net/2024/10/13/uZ4GXHgRStIochF.png" alt="PixPin_2024-10-13_15-42-23" loading="lazy"></p><p>📶<a href="https://quail.ink/op7418/feed/atom">RSS</a></p><h2 id="📂资源版"><a href="#📂资源版" class="headerlink" title="📂资源版"></a>📂资源版</h2><h3 id="✈️Telegram-资源型频道：寻找资源的好去处"><a href="#✈️Telegram-资源型频道：寻找资源的好去处" class="headerlink" title="✈️Telegram 资源型频道：寻找资源的好去处"></a>✈️Telegram 资源型频道：寻找资源的好去处</h3><p>由于 Telegram 上传资源无空间限制，且监管较为宽松，它含有许多<strong>资源型频道</strong>。因此如果你需要找一些资源的话，不妨考虑一下它。资源以消息的形式存储在频道里面，可以在对应的频道内检索。下面举一些例子：</p><ul><li>网盘资源<ul><li><a href="https://t.me/addlist/AjEE_tIe5bMzN2Ix">https://t.me/addlist/AjEE_tIe5bMzN2Ix</a></li></ul></li><li>破解软件<ul><li><a href="https://t.me/addlist/M-Rpt9N6aLRhMTll">https://t.me/addlist/M-Rpt9N6aLRhMTll</a></li></ul></li><li>杂志周刊<ul><li><a href="https://t.me/readingclubus">https://t.me/readingclubus</a></li><li><a href="https://t.me/caixinsharing">https://t.me/caixinsharing</a></li></ul></li></ul><p>觉得不够？更多 Telegram 优质频道&#x2F;群组&#x2F;机器人，可以参考以下资源（<strong>请读者自行鉴别这些内容的质量</strong>）：</p><ul><li><a href="https://tgnav.github.io/">频道 | TGNAV - Telegram 频道群组导航</a>（NSFW）</li><li><a href="https://rectg.com/">【热门推荐】5000+ 优质 Telegram 群组、频道和机器人，精心筛选，助您迅速找到最佳选择！ | rectg</a></li></ul><p>建议在加入之后开启<strong>消息免打扰</strong>。</p><h3 id="😍emojifinder：查找-Emoji-表情"><a href="#😍emojifinder：查找-Emoji-表情" class="headerlink" title="😍emojifinder：查找 Emoji 表情"></a>😍emojifinder：查找 Emoji 表情</h3><p>读者可能意识到了，本期的标题前面都有一个 Emoji，这是为了方便读者更直观地理解各个条目的性质。</p><p><a href="https://emojifinder.com/">Emoji Finder</a>是一个方便的网站，输入英文关键词搜索，点击即可复制到剪切板。</p><p><img src="https://s2.loli.net/2024/10/13/qaVfg8NM3xeSAo2.png" alt="PixPin_2024-10-13_16-06-34" loading="lazy"></p><h3 id="💻Core-Dumped：直观理解计算机系统"><a href="#💻Core-Dumped：直观理解计算机系统" class="headerlink" title="💻Core Dumped：直观理解计算机系统"></a>💻Core Dumped：直观理解计算机系统</h3><p>笔者最近发现了一个小众 Youtube 频道：<a href="https://www.youtube.com/@CoreDumpped">Core Dumped</a>，使用<strong>动画</strong>讲解<strong>计算机系统</strong>的底层原理。</p><p><img src="https://s2.loli.net/2024/10/13/IOnPDzUo9G3QARX.jpg" alt="One of the most profounds and successful ideas in computer science. (1)" loading="lazy"></p><h2 id="🔧工具版"><a href="#🔧工具版" class="headerlink" title="🔧工具版"></a>🔧工具版</h2><h3 id="➗SimpleTex：提取-LaTeX-公式"><a href="#➗SimpleTex：提取-LaTeX-公式" class="headerlink" title="➗SimpleTex：提取 LaTeX 公式"></a>➗SimpleTex：提取 LaTeX 公式</h3><p><a href="https://simpletex.cn/">SimpleTex</a>是“一款方便且好用的公式&#x2F;文档识别编辑软件平台”，可以识别<strong>图片&#x2F;PDF</strong>文档中的 LaTex 公式，并支持导出为<strong>LaTeX</strong>、<strong>Markdown</strong>、<strong>Word</strong>和<strong>图片</strong>，目前登录即可免费使用，也可以付费调用 API。</p><p><img src="https://s2.loli.net/2024/10/13/lqTMNvwm8PcxEjd.png" alt="PixPin_2024-10-13_16-23-01" loading="lazy"></p><p>下面是<a href="https://simpletex.cn/ai/latex_ocr">识别</a>的结果，还原度还是不错的。</p><p>$$<br>19.\text{ 设随机变量序列}{X,|\text{独立同分布 },\text{且 Var}(X_n)&#x3D;\sigma^2\text{ 存在 },\text{令}\\overline{X} &#x3D; \frac{1}{n}\sum_{i&#x3D;1}^{n} X_{i} ,\quad S_{n}^{2} &#x3D; \frac{1}{n}\sum_{i&#x3D;1}^{n} { X_{i} - \overline{X} }^{2} .\\text{试证}S_{n}^{2}\xrightarrow{P}\sigma^{2}.<br>$$</p><h3 id="🛜gping：ping，但是用动画"><a href="#🛜gping：ping，但是用动画" class="headerlink" title="🛜gping：ping，但是用动画"></a>🛜gping：ping，但是用动画</h3><p><a href="https://github.com/orf/gping">gping</a>是一个支持多平台（Windows、Mac 和 Linux）的 ping 程序，支持在命令行中动态绘制多台主机的 ping 时间图。</p><p><img src="https://raw.githubusercontent.com/orf/gping/refs/heads/master/images/readme-example.gif" loading="lazy"></p><p>测试一下本站 <code>gping shiquda.link</code>：</p><p><img src="https://s2.loli.net/2024/10/13/MBW3AeGLScDERP1.png" alt="PixPin_2024-10-13_16-36-18" loading="lazy"></p><h3 id="🚫Test-Ad-Block：检测你的广告拦截器"><a href="#🚫Test-Ad-Block：检测你的广告拦截器" class="headerlink" title="🚫Test Ad Block：检测你的广告拦截器"></a>🚫Test Ad Block：检测你的广告拦截器</h3><p><a href="https://d3ward.github.io/toolz/adblock.html">Test Ad Block</a>是一个检测浏览器广告拦截器功能的网站，开源于<a href="https://github.com/d3ward/toolz">GitHub</a>。</p><p><img src="https://s2.loli.net/2024/10/13/l263GQD8vrNb5Wn.png" alt="PixPin_2024-10-13_16-39-04" loading="lazy"></p><p>看来支持 Manifest V3 的<a href="https://chromewebstore.google.com/detail/ublock-origin-lite/ddkjiahejlhfcafbddmgiahcphecmpfh">uBlock Origin Lite</a>表现还不错😄</p><hr><p>如果您喜欢我的内容，欢迎评论，让我有继续写周刊的动力；如果您对本周刊有所建议，同样非常欢迎您的评论！</p><p>谢谢♥️！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>浏览器扩展逆向指北</title>
      <link>https://shiquda.link/guide-on-browser-extension-inverse-engineering/</link>
      <description>本文从基本概念、逆向知识与工具、逆向基本流程和逆向实战四个部分来进行介绍。文末还分享了笔者对的逆向与反逆向的思考。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E7%A0%B4%E8%A7%A3/">破解</category>
      <pubDate>Thu, 10 Oct 2024 11:18:39 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>本文基于笔者对浏览器插件逆向的肤浅认知，和数个浏览器插件逆向的经验，将分别从<strong>基本概念</strong>、<strong>逆向知识与工具</strong>、<strong>逆向基本流程</strong>和<strong>逆向实战</strong>四个部分来进行介绍。文章难免有错误或疏漏，欢迎批评指正与交流！</p><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="什么是浏览器插件？"><a href="#什么是浏览器插件？" class="headerlink" title="什么是浏览器插件？"></a>什么是浏览器插件？</h3><p><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions">浏览器扩展</a>(Browser extension)，俗称（浏览器）插件，它实现的功能很多，例如修改网页、拦截与修改请求、控制浏览器等等。一般来说，浏览器插件都是基于HTML/JS/CSS的，也就是“<strong>前端三件套</strong>”。它们利用浏览器提供的<a href="https://developer.chrome.com/docs/extensions/reference/api?hl=zh-cn">接口</a>，实现各种功能。</p><p>在大多数情况下，基于 Chromium 内核的插件只需要<a href="https://extensionworkshop.com/documentation/develop/porting-a-google-chrome-extension/">少许修改</a>就可以在 Firefox 中运行，且 Chromium 系的浏览器插件生态更佳丰富，因此文章后面部分的介绍都基于 Chromium 系的浏览器。</p><h3 id="插件安装包里都有啥？"><a href="#插件安装包里都有啥？" class="headerlink" title="插件安装包里都有啥？"></a>插件安装包里都有啥？</h3><p>部分读者可能注意到，我们安装浏览器插件，实际上浏览器下载的是一个<code>.crx</code>文件。这个<code>.crx</code>文件并不是二进制文件这样经过编译的文件，它实质上就是一个压缩包。如果你把它的后缀改为<code>.zip</code>，解压软件就能读取里面的内容。</p><p>解压之后，我们就能看到插件的各个文件了。一个简单的的插件目录结构如下：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">|-- 插件目录</span><br><span class="line">    |-- manifest.json</span><br><span class="line">    |-- popup.html</span><br><span class="line">    |-- background.js</span><br><span class="line">    |-- content.js</span><br><span class="line">    |-- options.html</span><br><span class="line">    |-- ...</span><br></pre></td></tr></tbody></table></figure><p>插件的<code>.js</code>、<code>.html</code>、<code>.css</code>等文件，也可能包含在子目录中。</p><p>下面的内容假设读者对<code>.js</code>、<code>.html</code>、<code>.css</code>等有一定的了解。<strong>简单来说，<code>.html</code>是网页的骨架，<code>.css</code>是网页的衣服，<code>.js</code>是网页的灵魂</strong>。</p><p>我们主要关心的是下面几个（类）文件：</p><ul><li><code>manifest.json</code>：配置文件，包含了插件的名称、版本、权限等信息，类似于安卓的<code>AndroidManifest.xml</code>。</li><li><code>background.js</code>：后台脚本，在后台处理插件的交互，负责处理插件的全局逻辑。</li><li><code>content.js</code>：内容脚本，是插入到页面中的脚本，可以用来修改页面内容、拦截请求等。</li></ul><p>其中<code>manifest.json</code>中会指定<code>background.js</code>、<code>content.js</code>等文件的路径，而一些<code>.html</code>文件往往描述了插件的UI界面，在这其中也可能插入一些<code>.js</code>、<code>.css</code>等脚本或者样式文件。</p><h3 id="什么是逆向？"><a href="#什么是逆向？" class="headerlink" title="什么是逆向？"></a>什么是逆向？</h3><p>在本文中，我们讨论的“逆向”实质上是“破解”的一件漂亮外衣。如果你曾经有一些逆向经历，或者是听说过一些，可能对逆向的印象是这样的：</p><p><img src="https://s2.loli.net/2024/10/10/4oCfVFA7JvUcg1E.png" alt="Pasted image 20241009235501" loading="lazy"></p><p>但是事实上，浏览器插件的逆向可比这个简单多了。它大概是这样的：</p><p><img src="https://s2.loli.net/2024/10/10/Ao7qNaRbZHyJP4l.png" alt="PixPin_2024-10-09_23-56-42" loading="lazy"></p><p>直观点来说，就是从几（十）万行被压缩、混淆的晦涩代码中，抽丝剥茧，利用搜索工具找到关键代码，并且进行（往往是很简单的）修改，实现解锁会员功能等目的。</p><p>当然，这对有一些代码功底的读者来说，可能并不难，但是实际上，想要实现破解，仍然需要一些方法和技巧。本文的主要任务就是基于笔者的经验，告诉读者一些方法与技巧，让你少走弯路。</p><h3 id="所有插件都能破解吗？"><a href="#所有插件都能破解吗？" class="headerlink" title="所有插件都能破解吗？"></a>所有插件都能破解吗？</h3><p>其实不一定。如果插件的功能主要依赖于云端（例如，沉浸式翻译），且云端做了身份验证，那么本地破解的能做的很少。</p><p>但是，对于一些功能依赖于本地代码，云端只是负责进行会员身份校验的插件，这种往往就能够破解。可以进一步说，这样的插件一定是可以破解的。</p><p>但事实上，我们还应该关心的是：<strong>这个插件值得我花时间去破解会员功能吗？与付费购买/订阅相比，我的得与失是什么？</strong></p><p>就像给账号设置传统的密码一样，理论上不存在完全无法破解的密码，设置密码其实是在方便性和安全性之间的一个平衡。从破解者的角度来看，当<strong>破解所需的成本大于收益</strong>之后，没有人会做这样出力不讨好的事情。</p><p>因此，在进行破解一个插件之前，请好好想一想这给你带来的得与失。</p><h2 id="逆向知识与工具"><a href="#逆向知识与工具" class="headerlink" title="逆向知识与工具"></a>逆向知识与工具</h2><p>必须项：</p><ul><li>浏览器：你得有个浏览器吧。。。</li><li>JavaScript基本语法</li><li>IDE：用来实际修改代码的工具，推荐使用VSCode类编辑器</li></ul><p>可选项：</p><ul><li>HTML/CSS</li><li>调试工具的使用：Chrome DevTools</li><li>正则表达式：用于匹配代码或者批量替换</li><li>Git：用于管理破解的记录，便于回溯</li><li>代码可读化与反混淆工具，后面会介绍</li></ul><h3 id="JavaScript-基本语法"><a href="#JavaScript-基本语法" class="headerlink" title="JavaScript 基本语法"></a>JavaScript 基本语法</h3><p>如果你想要破解一个浏览器插件，你最基本来说需要对 JavaScript 有一定的了解，知道一些常见的js语法，例如：</p><ul><li>有哪些变量类型？</li><li>什么是函数？</li><li>什么是对象？</li><li>……</li></ul><p>等等。当然在实战中，有一些知识也是比较重要的，例如：</p><ul><li>三元表达式</li><li>强制类型转换</li><li>异步编程</li></ul><h3 id="IDE"><a href="#IDE" class="headerlink" title="IDE"></a>IDE</h3><p>推荐使用VSCode，方便代码编辑、替换。</p><h3 id="浏览器开发者工具-F12-的使用"><a href="#浏览器开发者工具-F12-的使用" class="headerlink" title="浏览器开发者工具(F12)的使用"></a>浏览器开发者工具(F12)的使用</h3><p>如果你会一些<strong>基本操作</strong>就更好了。实战中不一定用到。</p><h3 id="正则表达式"><a href="#正则表达式" class="headerlink" title="正则表达式"></a>正则表达式</h3><p>正则表达式是一种用于匹配字符串中字符组合的模式。能够按照指定的规则，找出代码中所有符合条件的部分。</p><p>例如，我们查找一个压缩后的代码中，所有类似<code>e.user.vip</code>的代码，就可以使用这样的正则表达式来匹配。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[a-zA-Z]+\.user\.vip</span><br></pre></td></tr></tbody></table></figure><h3 id="Git"><a href="#Git" class="headerlink" title="Git"></a>Git</h3><p>Git 是一个分布式版本控制系统，用于管理代码的变更。</p><p>其实这个工具不用也罢，但是我在几次实战中，出现过关键代码替换掉，后来出现插件无法运行的情况，这时候大多只能从头再来。如果有Git工具的话，<strong>关键的修改前后可以保存，方便回溯</strong>。</p><p>还有一个优点是，如果插件更新了，你认为有再次破解的需要的话，就可以<strong>参照原来破解的流程</strong>，把新版本插件的代码一葫芦画瓢，破解出来。</p><h3 id="代码可读化与反混淆"><a href="#代码可读化与反混淆" class="headerlink" title="代码可读化与反混淆"></a>代码可读化与反混淆</h3><p>拿到插件之后，格式往往没有前面那张图这么清晰，而是被<strong>压缩、混淆</strong>的。</p><p><img src="https://s2.loli.net/2024/10/10/sUbNFW29y5zfev4.png" alt="PixPin_2024-10-10_00-18-08" loading="lazy"></p><p>这种代码当然不是作者故意这么写的，而是写完之后，使用一些工具进行压缩、混淆得到的。</p><p>但是根据我的经验，插件的作者往往不会对代码进行非常深度的混淆，一般做的就是<strong>把变量、函数、类的名称替换为无意义的名称</strong>（一般是很短的大小写英文字母），或者把一些代码替换为<strong>更难读懂的形式</strong>，比如说布尔值替换为<code>!0</code>、<code>!1</code>，频繁使用三元表达式、<code>布尔值 &amp;&amp; (执行逻辑)</code>这样更佳晦涩的方式，等等。但是<strong>类的属性等名称</strong>往往不会改变，这将成为我们逆向分析的一个重要抓手。</p><p>下图是一个典型的代码片段，其中红色方框内是被替换的无意义的名称，绿色的是未被替换的类的属性，黄色是经过转换后的更佳晦涩的代码。</p><p><img src="https://s2.loli.net/2024/10/10/HywlAu4LQOS7t5e.png" alt="PixPin_2024-10-10_10-23-17" loading="lazy"></p><p>关于混淆的拓展阅读：<a href="http://jartto.wang/2017/10/31/js-anti-aliasing/">JS 反混淆 - Jartto’s blog</a></p><p>一般来说，我们使用代码格式化工具对浏览器插件的代码（主要是<code>.js</code>代码）进行反压缩，就可以了开始破解了。Vscode等IDE有自带的格式化方法，但是无法批量对插件的所有代码进行格式化。<del>进行这里介绍一个笔者之前写的<a href="https://github.com/shiquda/code-readable">Python脚本</a>，能够对整个项目中所有<code>.js</code>、<code>.css</code>、<code>.html</code>和<code>.json</code>文件进行<strong>代码格式化</strong>。</del></p><p>更建议使用<code>prettier</code>来进行格式化。安装<code>prettier</code>后，在插件目录下，只需要执行一行命令就可以实现格式化：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">prettier --write .</span><br></pre></td></tr></tbody></table></figure><h2 id="逆向基本流程"><a href="#逆向基本流程" class="headerlink" title="逆向基本流程"></a>逆向基本流程</h2><h3 id="下载插件并安装"><a href="#下载插件并安装" class="headerlink" title="下载插件并安装"></a>下载插件并安装</h3><h4 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h4><p>下载推荐使用 <a href="https://www.crxsoso.com/">crxsoso</a>，国内即可访问，且可以直接下载<code>.zip</code>格式的插件包。</p><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><p>测试的浏览器建议使用<strong>Chrome</strong>，可以新开一个用户资料，专门用于测试。<strong>不建议用平时的主力浏览器</strong>，这样能够排除其他插件或者脚本的影响。</p><p><img src="https://s2.loli.net/2024/10/10/e7mu8finl4zMkp9.png" alt="PixPin_2024-10-10_14-18-32" loading="lazy"></p><p>把安装包解压到一个合适的地方，然后浏览器进入<code>chrome://extensions</code>，开启开发者模式，点击“加载已解压的扩展程序”，选择解压后的插件目录即可。</p><h3 id="破解思路"><a href="#破解思路" class="headerlink" title="破解思路"></a>破解思路</h3><p>我们最核心的思路就是，找到代码中（往往是在<code>background.js</code>中）<strong>判断会员状态</strong>的代码，并且修改。</p><p>当然我们不可能靠肉眼看完几万行晦涩的代码，而是利用一些技巧，来<strong>定位</strong>关键的代码。</p><p>如果你不确定在哪个文件里面，也没关系，可以使用<strong>全局搜索</strong>功能，可以对插件目录下所有代码进行检索。</p><p>那么，如何定位关键的代码呢？</p><h3 id="定位关键代码"><a href="#定位关键代码" class="headerlink" title="定位关键代码"></a>定位关键代码</h3><p>我一般使用的思路是两个：</p><ol><li><p>全局尝试搜索<code>vip</code>、<code>会员</code>、<code>pro</code>、<code>premium</code>、<code>subscription</code>等关键词，看是否能找到相应的类的属性，以此为跳板找到核心逻辑，依次进行修改。</p></li><li><p>从<strong>字符串</strong>入手，在使用使用插件过程中找到一些和会员相关的字符串，比如说“This is a premium feature”、“您尚未开通会员”、“Free user”等，然后全局搜索这些字符串，查看这些字符串附近的代码逻辑，以此找到核心的逻辑。</p></li></ol><p>一般来说，我更推荐使用<strong>第二种方法</strong>，这样能够快速定位到关键的逻辑。第一种方法是实在没有头绪的时候，进行尝试的。</p><p>需要注意的是，如果文字是中文等非英文字符，那么有可能插件代码中的字符是转义后的字符，如果你搜不到，这时候可以<strong>对文件进行转义</strong>，或者试着搜索<strong>转义前的字符串</strong>。</p><p>这里推荐一个开发者常用的工具集合<a href="https://ctool.dev/">Ctools</a>，支持多端使用（包括在线使用、浏览器插件），开源免费，以后在也不用去网上搜xxx在线网站啦😄</p><p><img src="https://s2.loli.net/2024/10/10/2SMVli9dL3jBQzZ.png" alt="PixPin_2024-10-10_10-57-29" loading="lazy"></p><p>搜索转义后的字符串：</p><p><img src="https://s2.loli.net/2024/10/10/ag6nj4dBGUJcOXv.png" alt="PixPin_2024-10-10_11-01-58" loading="lazy"></p><h3 id="修改代码"><a href="#修改代码" class="headerlink" title="修改代码"></a>修改代码</h3><p>定位到关键代码之后，大多数修改的方法都是围绕着布尔表达式进行的。</p><p>例如，如果代码中有一段逻辑是：</p><figure class="highlight javascript"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (isVip) {</span><br><span class="line">    <span class="comment">// 执行会员逻辑</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line">    <span class="comment">// 执行非会员逻辑</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>我们可以把<code>isVip</code>直接修改为<code>true</code>或者<code>1</code>，这样就可以让插件以为你是会员了。当然上面只是一个最简单的例子，实际的代码可能复杂得多，但核心思路都是一样的。</p><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>修改完代码之后，需要进行测试。可以找到插件的官网（如有），点击价格/Pricing，此处一般有会员和非会员功能的对比。</p><p><img src="https://s2.loli.net/2024/10/10/TiBSjbnGOyYIvfm.png" alt="Pasted image 20241010141322" loading="lazy"></p><h2 id="实战演示"><a href="#实战演示" class="headerlink" title="实战演示"></a>实战演示</h2><p>我们以某插件为例，介绍一下破解流程。<a href="https://www.crxsoso.com/webstore/detail/dpphkcfmnbkdpmgneljgdhfnccnhmfig">插件下载地址</a></p><p>解压安装后，先跑一下反压缩脚本，把压缩饼干展开</p><p><img src="https://s2.loli.net/2024/10/10/SvwXUf3nGb6om1l.png" alt="PixPin_2024-10-10_15-07-14" loading="lazy"></p><p>发现<code>background.js</code>有足足十万多行。</p><p><img src="https://s2.loli.net/2024/10/10/BUavXmZRJjrihyM.png" alt="PixPin_2024-10-10_15-09-06" loading="lazy"></p><p>回到浏览器，打开插件，登录账号后，发现有一个提示，提示我们升级会员。</p><p><img src="https://s2.loli.net/2024/10/10/564WkCgZcU8ps2A.png" alt="PixPin_2024-10-10_15-03-03" loading="lazy"></p><p>搜索这个字符串，发现没有结果</p><p><img src="https://s2.loli.net/2024/10/10/3DGYAVq5Nes2TZp.png" alt="PixPin_2024-10-10_15-11-04" loading="lazy"></p><p>于是我们再尝试搜索Unicode 转义前的字符串</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\u5347\u7ea7\u4f1a\u5458\u4eab\u66f4\u591a\u9ad8\u7ea7\u6743\u76ca</span><br></pre></td></tr></tbody></table></figure><p>发现一个字符串。</p><p><img src="https://s2.loli.net/2024/10/10/lxyr5opIjZmKSCO.png" alt="PixPin_2024-10-10_15-13-35" loading="lazy"></p><p>我们再选取这个字符串的父元素名称<code>upgradeToPremiumTitle</code>，进行搜索</p><p><img src="https://s2.loli.net/2024/10/10/7zl4DaVhuctrEGf.png" alt="PixPin_2024-10-10_15-17-35" loading="lazy"></p><p>在这附近似乎并没有什么有价值的信息，于是想办法找另一个试试。打算从实际功能入手。</p><p><img src="https://s2.loli.net/2024/10/10/FwiDx2ElOLbj5hk.png" alt="PixPin_2024-10-10_15-19-58" loading="lazy"></p><p>点击新建词本，会跳转到开通会员的介绍页面。类似前面的方法，我们搜索“新建词本”，得到名称<code>creatNewWordBook</code>，再次进行搜索</p><p><img src="https://s2.loli.net/2024/10/10/5zu79einFKc6lpU.png" alt="PixPin_2024-10-10_15-22-29" loading="lazy"></p><p>看到一个<code>previlege</code>，这很可能是记录用户是否是会员信息的名称。<del>（实际上后来发现并不是，这应该是判断词书是否是会员专属的属性）</del></p><p>继续搜索，发现有可能是，因为搜到几个有和<code>"VIP"</code>进行判断的表达式。</p><p><img src="https://s2.loli.net/2024/10/10/IKHfpo2Ss7kwbdt.png" alt="PixPin_2024-10-10_15-24-27" loading="lazy"></p><p>我们现在需要把所有出现的<code>privilege</code>判断逻辑都进行修改，一个简单的方法是把<code>y.privilg</code>这样的表达式全部替换为<code>"vip"</code>。</p><p>等等，在替换之前，先在本地初始化一下Git，方便后续回溯。</p><p><img src="https://s2.loli.net/2024/10/10/aNV5f7bqSFdRzXy.png" alt="file_1728545278865_460" loading="lazy"><br><img src="https://s2.loli.net/2024/10/10/FSwOaU862573XEM.png" alt="PixPin_2024-10-10_15-27-43" loading="lazy"></p><p>直接全部提交即可。</p><p>把搜索到的判断逻辑全部修改。</p><p><img src="https://s2.loli.net/2024/10/10/KOtoCjb1Yf2nv5s.png" alt="PixPin_2024-10-10_15-35-18" loading="lazy"></p><p>保存修改之后，在扩展程序管理页面刷新一下插件<br><img src="https://s2.loli.net/2024/10/10/fux2Cz9UqWKY1sP.png" alt="PixPin_2024-10-10_15-37-15 1" loading="lazy"></p><p>测试发现，还是不能解锁功能，考虑再找一个突破口。</p><p>搜索这个字符串</p><p><img src="https://s2.loli.net/2024/10/10/4yT6SUJvQa8ZMkX.png" alt="PixPin_2024-10-10_15-50-58" loading="lazy"></p><p><img src="https://s2.loli.net/2024/10/10/Jyl1KGITOYWvaqs.png" alt="PixPin_2024-10-10_15-53-01" loading="lazy"></p><p>这是一个三元表达式，我们使用<code>Ctrl</code> + <code>左键</code>点击<code>Hr</code>函数，跳转到它的定义</p><p><img src="https://s2.loli.net/2024/10/10/fZPvtTL2eyYgaox.png" alt="PixPin_2024-10-10_15-55-19" loading="lazy"></p><p>看起来像是在验证会员是否过期，我们让它直接返回1。</p><p><img src="https://s2.loli.net/2024/10/10/17C8VNhB5yz46MP.png" alt="PixPin_2024-10-10_15-57-12" loading="lazy"></p><p>同时，我们搜索<code>expireAt</code>关键词，发现<code>index.js</code>中也有一个相同的函数，把它也改了。</p><p>刷新发现，已经显示是会员了。</p><p>假设我们准备破解到这里为止，接下来我们检查一下各项<a href="https://cn.relingo.net/zh/pricing">会员功能</a>是否能正常使用。</p><p><img src="https://s2.loli.net/2024/10/10/oVe4LMNjdAHkRf7.png" alt="PixPin_2024-10-10_15-56-30" loading="lazy"></p><p>高级翻译引擎无法使用，肯定是添加了服务端校验，在我们的意料之中。因此使用积分肯定也不行了。</p><p><img src="https://s2.loli.net/2024/10/10/ATWCzxvwPVqjXF3.png" alt="PixPin_2024-10-10_16-01-06" loading="lazy"></p><p>英英词典可以正常使用。</p><p><img src="https://s2.loli.net/2024/10/10/qcONkfzrl6dt4bx.png" alt="PixPin_2024-10-10_16-57-39 1" loading="lazy"></p><p>高级/专业词本虽然点击切换不会跳转开通会员的页面了，但是等了半天也没反应。</p><p><img src="https://s2.loli.net/2024/10/10/YpOwaoz9tyQRVFS.png" alt="PixPin_2024-10-10_16-58-24" loading="lazy"></p><p>抓包发现，有服务端校验，暂时先放弃。</p><p><img src="https://s2.loli.net/2024/10/10/bsjew8pShuHCQmY.png" alt="PixPin_2024-10-10_17-01-20" loading="lazy"></p><p>高级释义，没找到这个功能，猜测是AI释义。测试发现，服务器同样提示需要升级会员。</p><p>AI语法分析，没找到该功能。</p><p>无限存储单词这个功能，我在原先逆向的版本中(v3.9.0)，是可以无限添加的，但是该版本竟然不行，超过50个单词之后服务端返回错误信息。</p><blockquote><p>这里就要提到使用Git工具的另一个好处了：上次逆向分析的过程没有保存下来，我完全忘了怎么逆向了💦</p></blockquote><p><img src="https://s2.loli.net/2024/10/10/M63wWfLcaqRhzps.png" alt="PixPin_2024-10-10_18-11-04" loading="lazy"></p><p>我猜测原先版本可能没有进行云端校验，但是抓包分析却发现，二者竟然都需要经过云端验证。</p><p><img src="https://s2.loli.net/2024/10/10/c2Ube5sl1gkxt3z.png" alt="PixPin_2024-10-10_17-44-17" loading="lazy"></p><p>仔细分析二者发现，竟然是他们发送的api接口域名不同，<code>api.relingo.net</code>没有验证添加后是否超过50个免费用户的额度，而<code>cn.relingo.net</code>有验证。于是我搜索了关键字，发现一个关键的名称<code>endPoint</code>，它似乎代表了api的域名。</p><p><img src="https://s2.loli.net/2024/10/10/4Um6MivV7zRQprn.png" alt="PixPin_2024-10-10_17-40-35" loading="lazy"></p><p>于是试着修改相关逻辑，使得请求发出的域名固定为<code>api.relingo.net</code></p><p><img src="https://s2.loli.net/2024/10/10/flNarnqU5uXkAzd.png" alt="PixPin_2024-10-10_17-43-07 1" loading="lazy"></p><p>但是，改了之后还是不行。。。</p><p>奇怪了，两个请求的域名也一样，还有什么可能呢？</p><p>没办法，只能把两个请求的<code>cURL</code>命令用<a href="https://diffsuite.com/">字符串对比工具</a>进行对比：</p><p><img src="https://s2.loli.net/2024/10/10/IQ9fgujD2ZtBFSA.png" alt="PixPin_2024-10-10_18-24-42" loading="lazy"></p><p>发现只有几个细微的区别。不会是因为版本不同吧？我修改<code>manifest.json</code>，把新版的插件版本改回3.9.0，再测试一下，竟然真的可以了。服务端这样的判断逻辑，也是让我没想到😅</p><p>于是找到发送版本的参数的代码，将其强制改为3.9.0，测试就可以无限制添加单词了。</p><p><img src="https://s2.loli.net/2024/10/10/CgPcYnqfoUebOpF.png" alt="PixPin_2024-10-10_18-07-48" loading="lazy"></p><p>例句未测试，我们姑且猜测也可以<del>吧？</del></p><p>导出单词似乎其实是免费功能，导出到Anki需要经过服务端，暂时无法破解。</p><p>下面四个功能，创建个人单词本、开启多个词本、词义编辑、学习统计，经过测试，均可使用。</p><p>因此，总结一下能用的功能：</p><ul><li><input disabled="" type="checkbox"> 高级翻译引擎</li><li><input disabled="" type="checkbox"> 高级翻译引擎积分</li><li><input checked="" disabled="" type="checkbox"> 英英词典</li><li><input disabled="" type="checkbox"> 高级/专业词本</li><li><input disabled="" type="checkbox"> 高级释义</li><li><input disabled="" type="checkbox"> AI语法分析</li><li><input checked="" disabled="" type="checkbox"> 无限存储单词</li><li><input checked="" disabled="" type="checkbox"> 无限存储例句</li><li><input checked="" disabled="" type="checkbox"> 导入导出单词</li><li><input disabled="" type="checkbox"> 导出到Anki</li><li><input checked="" disabled="" type="checkbox"> 创建个人单词本</li><li><input checked="" disabled="" type="checkbox"> 开启多个词本</li><li><input checked="" disabled="" type="checkbox"> 词义编辑</li><li><input checked="" disabled="" type="checkbox"> 学习统计</li></ul><h2 id="逆向与反逆向"><a href="#逆向与反逆向" class="headerlink" title="逆向与反逆向"></a>逆向与反逆向</h2><h3 id="逆向“对”吗？"><a href="#逆向“对”吗？" class="headerlink" title="逆向“对”吗？"></a>逆向“对”吗？</h3><p>在文章结束之前，我还想从破解者和开发者的角度。讨论一下我对插件逆向这个行为本身的看法。</p><p>破解插件这个行为，“<strong>对</strong>”吗？从道德的角度讲，我认为<strong>当然是不对的</strong>，这显然侵犯了作者的权益。</p><p><strong>因此本教程的初衷是为了普及相关知识，仅供学习交流，不建议随意使用和模仿，甚至以此牟利，因此产生的纠纷与作者无关</strong>。</p><p>但是从实际情况上来讲，部分插件的定价不合理，导致用户负担不起价格，或是付费渠道的狭窄，使得许多优秀的软件，难以得到它们应有客户。这事实上也对开发者是不利的。在这方面，我认为<strong>简悦</strong>是一个很好的范例，它的买断制政策与合适的价格，使得很少人有动力去破解它。</p><h3 id="我是插件的开发者，怎样能减少破解这种行为？"><a href="#我是插件的开发者，怎样能减少破解这种行为？" class="headerlink" title="我是插件的开发者，怎样能减少破解这种行为？"></a>我是插件的开发者，怎样能减少破解这种行为？</h3><p>对于开发者来说，有一些建议供您参考：</p><h4 id="使用混淆工具"><a href="#使用混淆工具" class="headerlink" title="使用混淆工具"></a>使用混淆工具</h4><p>使用混淆工具，降低逆向者的破解的收益-成本比重。</p><h4 id="将产品与云端紧密结合"><a href="#将产品与云端紧密结合" class="headerlink" title="将产品与云端紧密结合"></a>将产品与云端紧密结合</h4><p>将产品的<strong>功能与云端紧密结合</strong>，并在后端设置校验，而不是云端简单地只负责校验。但这也要考虑到产品的属性，以及会增加一定的<strong>成本</strong>。</p><h4 id="合理定价"><a href="#合理定价" class="headerlink" title="合理定价"></a>合理定价</h4><p>考虑目标人群的支付能力，<strong>合理定价</strong>，设置促销、教育优惠等活动。</p><h4 id="及时更新"><a href="#及时更新" class="headerlink" title="及时更新"></a>及时更新</h4><p>不断更新吸引用户的<strong>新功能</strong>。因为逆向后的版本无法自动更新，若开发者能不断推出有吸引力的新功能，有需求的用户自然会选择订阅支持，而不是浪费时间找破解资源/进行破解。</p><h4 id="考虑开源-免费"><a href="#考虑开源-免费" class="headerlink" title="考虑开源/免费"></a>考虑开源/免费</h4><p>😊</p><hr><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions">浏览器扩展 - Mozilla | MDN</a></li><li><a href="https://developer.chrome.com/docs/extensions?hl=zh-cn">Chrome 扩展程序 &nbsp;|&nbsp; Chrome Extensions &nbsp;|&nbsp; Chrome for Developers</a></li><li><a href="http://jartto.wang/2017/10/31/js-anti-aliasing/">JS 反混淆 - Jartto’s blog</a></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第4期：工具</title>
      <link>https://shiquda.link/seeking-weekly-4/</link>
      <description>寻觅周刊 第4期：工具</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Sun, 06 Oct 2024 13:23:34 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本期是<em>寻觅周刊</em>的第4期。由于国庆假期，本期只有一些工具推荐，见谅~~</p><p>欢迎订阅本周刊的<a href="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/rss.xml">RSS</a>。</p><h2 id="信源版"><a href="#信源版" class="headerlink" title="信源版"></a>信源版</h2><p>本期无信源推荐。</p><h2 id="资源版"><a href="#资源版" class="headerlink" title="资源版"></a>资源版</h2><p>本期无资源推荐。</p><h2 id="工具版"><a href="#工具版" class="headerlink" title="工具版"></a>工具版</h2><h3 id="reqable：新一代API调试-测试与抓包工具"><a href="#reqable：新一代API调试-测试与抓包工具" class="headerlink" title="reqable：新一代API调试&#x2F;测试与抓包工具"></a>reqable：新一代API调试&#x2F;测试与抓包工具</h3><p><img src="https://reqable.com/zh-CN/assets/medias/arts_zh-68a043a67c48db92502101c1a717e99a.mp4" loading="lazy"></p><p><a href="https://reqable.com/zh-CN/">Reqable</a>是一个跨平台的HTTP开发和调试工具，旨在为程序开发和测试人员提供高效的接口测试和抓包调试功能。</p><p><img src="https://s2.loli.net/2024/10/06/jHxJprmuW5g4YP1.png" alt="Pasted image 20241006202218" loading="lazy"></p><p>这个图标是不是很眼熟？没错，这个新产品就是由原来的“<strong>小黄鸟</strong>”<strong>HttpCanary</strong>的开发团队打造的。</p><blockquote><p>Reqable是什么?<br><strong>Reqable &#x3D; Fiddler + Charles + Postman</strong></p></blockquote><p>这个工具目前有<strong>免费的社区版</strong>，还提供专业版和企业版。对于<del>心血来潮使用它来做安卓抓包的</del>笔者来说，社区版绰绰有余，而且对Android 14这样高版本的系统来说更佳友好，毕竟老牌的小黄鸟已经不再维护了。</p><h3 id="Windows触控板实现macOS的三指拖动功能"><a href="#Windows触控板实现macOS的三指拖动功能" class="headerlink" title="Windows触控板实现macOS的三指拖动功能"></a>Windows触控板实现macOS的三指拖动功能</h3><p><a href="https://github.com/ClementGre/ThreeFingerDragOnWindows">ThreeFingerDragOnWindows</a>这个开源软件能够实现使用触控板拖动窗口。该软件已经上架<a href="https://apps.microsoft.com/detail/9msx91wqcm2v?hl=zh-cn&gl=CN">微软商店</a>。</p><h3 id="spotube：无须会员的开源、跨平台Spotify客户端"><a href="#spotube：无须会员的开源、跨平台Spotify客户端" class="headerlink" title="spotube：无须会员的开源、跨平台Spotify客户端"></a>spotube：无须会员的开源、跨平台Spotify客户端</h3><p><a href="https://github.com/KRTirtho/spotube">spotube</a>是一个<strong>开源跨平台</strong>的 Spotify 客户端，它利用 Spotify 的数据 API 和 YouTube、Piped.video 或 JioSaavn 作为音频源，让用户无需购买 Spotify Premium 即可享受高品质音乐。</p><p><img src="https://s2.loli.net/2024/10/06/WRqxK5lJbmPL3gS.png" alt="Pasted image 20241006203600" loading="lazy"></p><p>支持<strong>通过Spotify登录</strong>，听你熟悉的歌单，但是更好的音质（使用YT music等其他音源），也支持<strong>匿名收听</strong>。当然<strong>没有广告</strong>。</p><p><img src="https://s2.loli.net/2024/10/06/iG5wqBxs3JhNApf.png" alt="PixPin_2024-10-06_21-17-51" loading="lazy"></p><p>缺点是不支持Spotify 节目和播客，以及似乎不支持Spotify的智能随机播放。</p><p>PS：如果你遇到代理问题，可以参考这个<a href="https://github.com/KRTirtho/spotube/issues/88">Issue</a>。</p><h3 id="Buzz：易于使用的音频转文字工具"><a href="#Buzz：易于使用的音频转文字工具" class="headerlink" title="Buzz：易于使用的音频转文字工具"></a>Buzz：易于使用的音频转文字工具</h3><p><img src="https://s2.loli.net/2024/10/06/6qAQGmEWT3Rn4tz.png" alt="Pasted image 20241006211411" loading="lazy"></p><p><a href="https://github.com/chidiwilliams/buzz">Buzz</a>是一个开源软件，使用开源的 OpenAI 的 Whisper 模型进行音频转文字。它的优点是易于使用，转换效果也不错。</p><p><img src="https://s2.loli.net/2024/10/06/qtbGkTponwJy15X.png" alt="PixPin_2024-10-06_21-18-55" loading="lazy"></p><p>支持导出为<code>txt</code>, <code>srt</code> 或者 <code>vtt</code> 格式。使用Medium模型测试，导出所需时间大概和其时长相当。</p><h3 id="json4u：JSON可视化"><a href="#json4u：JSON可视化" class="headerlink" title="json4u：JSON可视化"></a>json4u：JSON可视化</h3><p><a href="https://json4u.com/editor">JSON for you</a>是一个在线的JSON可视化工具。</p><p><img src="https://s2.loli.net/2024/10/06/ZhQvpIcUAjuE64z.png" alt="PixPin_2024-10-06_21-21-26" loading="lazy"></p><hr><p>如果您喜欢我的内容，欢迎评论，让我有继续写周刊的动力；如果您对本周刊有所建议，同样非常欢迎您的评论！</p><p>谢谢♥️！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第3期：众包</title>
      <link>https://shiquda.link/seeking-weekly-3/</link>
      <description>寻觅周刊 第3期：众包</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Sun, 29 Sep 2024 03:57:29 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本期是<em>寻觅周刊</em>的第3期。</p><h2 id="信源版"><a href="#信源版" class="headerlink" title="信源版"></a>信源版</h2><h3 id="IceBeer：独立开发与互联网的思考"><a href="#IceBeer：独立开发与互联网的思考" class="headerlink" title="IceBeer：独立开发与互联网的思考"></a>IceBeer：独立开发与互联网的思考</h3><p><a href="https://www.icebeer.top/">🍺 IceBeer - 👋输出我做独立开发和对互联网的一些思考</a></p><p>@Ivone 投稿。给<strong>程序员&#x2F;产品经理</strong>或者<strong>UX设计师</strong>写的关于独立做产品的一些想法和思考，希望能给网友带来一些帮助和新的思考。</p><h3 id="Time经济观察：宏观经济-公共政策-金融市场的独立观察"><a href="#Time经济观察：宏观经济-公共政策-金融市场的独立观察" class="headerlink" title="Time经济观察：宏观经济|公共政策|金融市场的独立观察"></a>Time经济观察：宏观经济|公共政策|金融市场的独立观察</h3><p><a href="https://t.me/s/TimeHorizonX">Time经济观察 – Telegram</a></p><p>也可以使用RSSHub订阅其RSS。</p><h2 id="资源版"><a href="#资源版" class="headerlink" title="资源版"></a>资源版</h2><h3 id="TGwiki：Telegram知识库"><a href="#TGwiki：Telegram知识库" class="headerlink" title="TGwiki：Telegram知识库"></a>TGwiki：Telegram知识库</h3><p><img src="https://s2.loli.net/2024/09/29/bE1jkzQAxCpTfio.png" alt="PixPin_2024-09-29_14-49-19" loading="lazy"></p><p><a href="https://tgnav.github.io/tgwiki/">TGwiki</a>是一个丰富的telegram知识库，包括常用功能、账号等文档，帮助用户更科学地使用Telegram。</p><h2 id="工具版"><a href="#工具版" class="headerlink" title="工具版"></a>工具版</h2><h3 id="tabout：用tab跳出括号、引号等"><a href="#tabout：用tab跳出括号、引号等" class="headerlink" title="tabout：用tab跳出括号、引号等"></a>tabout：用tab跳出括号、引号等</h3><p><a href="https://marketplace.visualstudio.com/items?itemName=albert.TabOut#review-details">TabOut</a>是一款简单但能改善写代码体验的VSCode插件，它的功能正如其名，使用<code>Tab</code>键来跳出括号、引号、斜杠等代码块，当然也支持自定义匹配的字符。</p><p><img src="https://s2.loli.net/2024/09/29/BNwCJA62rmZaGpY.png" alt="PixPin_2024-09-29_13-39-28" loading="lazy"></p><p>为什么这样能提升效率呢？道理很简单。</p><p>编写代码时，我们经常需要输入大量的括号、引号。现代IDE通常会在输入左括号时<strong>自动补全</strong>右括号。写完内部内容后，最直接的方法是用方向键跳出右括号，但这需要右手移动较远的距离（例如用小拇指按右方向键）。</p><p><img src="https://s2.loli.net/2024/09/29/wzMoKZCFd4NRhc1.png" alt="PixPin_2024-09-29_13-51-02" loading="lazy"></p><p>其实也有一种折中的方法，就是再手动写一个右括号，但是这又需要按下 <code>Shift</code> ，也需要一定时间。改用<code>Tab</code>键之后，对任何跳出的操作，都可以使用<code>Tab</code>来一键跳出，体验很好。当然适应也需要一定的时间，是否使用全凭读者个人意愿了。</p><h3 id="Nilesoft-Shell：自定义与美化Windows右键菜单"><a href="#Nilesoft-Shell：自定义与美化Windows右键菜单" class="headerlink" title="Nilesoft Shell：自定义与美化Windows右键菜单"></a>Nilesoft Shell：自定义与美化Windows右键菜单</h3><p><a href="https://nilesoft.org/">Nilesoft Shell</a>是一款免费开源的自定义与美化Windows右键菜单的软件。</p><p><img src="https://s2.loli.net/2024/09/29/zpjtIPlZ5KLHB1r.png" alt="Pasted image 20240929140543" loading="lazy"></p><p>支持自定义皮肤等功能，下面是我写的一个<a href="https://github.com/shiquda/dracula-nilesoft-shell">Dracula风格皮肤</a>。</p><p><img src="https://s2.loli.net/2024/09/29/Q12xaJ68iGyrH4T.png" alt="PixPin_2024-09-29_14-06-21" loading="lazy"></p><p>该软件还有许多其他功能，详情请参阅<a href="https://nilesoft.org/">官网</a>。</p><h3 id="SponsorBlock系列：用众包的理念来节省你看视频的时间"><a href="#SponsorBlock系列：用众包的理念来节省你看视频的时间" class="headerlink" title="SponsorBlock系列：用众包的理念来节省你看视频的时间"></a>SponsorBlock系列：用众包的理念来节省你看视频的时间</h3><p>下面是<a href="https://zh.wikipedia.org/wiki/%E4%BC%97%E5%8C%85"><strong>众包</strong></a>这个概念的介绍，不感兴趣的读者可以直接跳过。</p><blockquote><p>众包是一种分布式的问题解决和生产模式。问题以公开招标的方式传播给未知的解决方案提供者群体。<strong>众包和开源</strong>的不同在于，开源是一种通过公众的团员志愿地开创和进行合作性的行为活动，而众包中的行为活动是由某个客户提出，并且以个人或小组为基础来进行的。</p></blockquote><p><a href="https://sponsor.ajay.app/">SponsorBlock</a>是一个知名的 <strong>YouTube</strong> 增强插件，它能够按照用户标记的视频片段（如无聊的开头、结尾、付费推广等），自动跳过对应的片段，节省你的时间。</p><p><img src="https://s2.loli.net/2024/09/29/bFCH9uifGmA1Koz.png" alt="PixPin_2024-09-29_14-23-36" loading="lazy"></p><p>而这些片段都是由其用户无偿进行标记的。这种模式就是<strong>众包</strong>。理论上来说，使用的用户越多，每个用户的体验也更好。</p><blockquote><p>目前共有 13,033,165 位用户提交了 13,214,226 个跳转片段，这些片段总共节省了 5364 年零 182.59 天的时间。</p></blockquote><p>这个项目本身和其数据都是开源的，因此也帮助了例如<strong>YouTube Revance</strong>等软件，它们把该功能集成到修改过的APP客户端中。</p><p>前不久有网友做出了适用于Bilibili的<a href="https://github.com/hanydd/BilibiliSponsorBlock">插件</a>，从原插件移植而来，如果你感兴趣，也可以尝试一下。</p><h3 id="chsrc：全平台通用换源工具与框架"><a href="#chsrc：全平台通用换源工具与框架" class="headerlink" title="chsrc：全平台通用换源工具与框架"></a>chsrc：全平台通用换源工具与框架</h3><p><a href="https://github.com/RubyMetric/chsrc">chsrc</a>是一款开源好用的全平台通用换源工具与框架。</p><p>在中国的开发者应该都对“换源”这个概念不陌生。由于各种原因，访问一些软件包下载源的体验不佳，因此有一些平台（如高校、企业）提供了访问更快的镜像源。而这些镜像源在不同网络环境下的访问体验不一。</p><p>chsrc这个工具可以在全平台进行统一的换源操作，支持自动检测各个源的下载速度。</p><p><img src="https://s2.loli.net/2024/09/29/oVG1RxZHAaFS4iJ.png" alt="Pasted image 20240929142855" loading="lazy"></p><h3 id="tabGo：自动按照域名分类浏览器标签页"><a href="#tabGo：自动按照域名分类浏览器标签页" class="headerlink" title="tabGo：自动按照域名分类浏览器标签页"></a>tabGo：自动按照域名分类浏览器标签页</h3><p><a href="https://github.com/yz0812/tabGo">tabGo</a>是一款<del>刚开发</del>新鲜的浏览器插件，能够按照域名来自动对标签页分组。</p><p><img src="https://s2.loli.net/2024/09/29/Gmcy7jW3hNOIgpr.png" alt="PixPin_2024-09-29_14-36-09 1" loading="lazy"></p><ol><li>支持白名单</li><li>支持匹配方式，子域名或者是一级域名</li><li>支持分组在前</li><li>支持自定义分组名称</li></ol><p>首次发布于<a href="https://linux.do/t/topic/213344">浏览器插件（根据域名IP地址自动分组） - 资源荟萃 - LINUX DO</a>。</p><p>笔者用下来感觉体验不错，再给这个插件添加了一个分组设置名称的功能，搭配上期推荐的OneTab插件（现在改用KepTab了，功能类似），管理标签页变得非常舒适。</p><p><img src="https://s2.loli.net/2024/09/29/H73BGOrxbmaMpNe.png" alt="PixPin_2024-09-29_14-39-04" loading="lazy"></p><h3 id="您是否在使用-Clash？"><a href="#您是否在使用-Clash？" class="headerlink" title="您是否在使用 Clash？"></a>您是否在使用 Clash？</h3><p><a href="https://mikewang000000.github.io/ClashScan/">在线 Clash 检测 (mikewang000000.github.io)</a></p><p><img src="https://s2.loli.net/2024/09/29/hQD8pv9GIcZ4MB2.png" alt="PixPin_2024-09-29_14-59-03" loading="lazy"></p><p>这个开源的网站能够检测你的本地 Clash 等代理软件，看一下是否有潜在的泄露风险。如果被检测，防止泄露的方法详情可见 <a href="https://www.v2ex.com/t/1076579">V2EX帖子</a> 。</p><hr><p>如果您喜欢我的内容，欢迎评论，让我有继续写周刊的动力；如果您对本周刊有所建议，同样非常欢迎您的评论！</p><p>谢谢♥️！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第2期：信源</title>
      <link>https://shiquda.link/seeking-weekly-2/</link>
      <description>寻觅周刊 第2期：信源</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Sun, 22 Sep 2024 07:37:29 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本期是<em>寻觅周刊</em>的第2期。第一期收到的反馈还不错，因此目前打算继续分享。</p><p>与第一期有所不同的是，在原有<strong>资源版</strong>和<strong>工具版</strong>的基础上，我还将新添一个版块：<strong>信源版</strong>。俗话说得好，<strong>授人以鱼，不如授人以渔</strong>，分享笔者认为较为优质的信息源，也许对读者会有所帮助。</p><p>如果您对本周刊有所建议，非常欢迎您的评论！</p><h2 id="信源版"><a href="#信源版" class="headerlink" title="信源版"></a>信源版</h2><blockquote><p>如果你使用Follow，可以尝试它的最新功能：订阅我的<a href="https://app.follow.is/list/60577881234766848">信息源列表</a>。这里分享了我的部分信息源，包括周刊里分享的信息源。</p></blockquote><h3 id="晚点：晚一点，好一点"><a href="#晚点：晚一点，好一点" class="headerlink" title="晚点：晚一点，好一点"></a>晚点：晚一点，好一点</h3><p><a href="https://www.latepost.com/">晚点 (latepost.com)</a></p><p>笔者认为该平台的报道质量较高，有一定深度。图表绘制精良。</p><p>“晚一点，好一点”。</p><p>读者也可以关注其RSS订阅源或者<a href="https://space.bilibili.com/478559884">Bilibili</a>。</p><h3 id="有据：核查中文互联网上的流言"><a href="#有据：核查中文互联网上的流言" class="headerlink" title="有据：核查中文互联网上的流言"></a>有据：核查中文互联网上的流言</h3><p><a href="https://chinafactcheck.com/">有据 | 国际新闻事实核查 (chinafactcheck.com)</a></p><p>对中文互联网上的国际新闻流言进行事实核查。</p><p><img src="https://s2.loli.net/2024/09/22/oiflkeBvRgXq132.png" alt="PixPin_2024-09-22_14-53-16" loading="lazy"></p><p>如果你有兴趣，还可以阅读该网站编撰的<a href="https://chinafactcheck.com/?p=11465">《事实核查手册》</a>，了解基本的核查事实的方法，更好地辨别可能的谣言。</p><p>该手册采用<em>CC BY-NC-SA 4.0许可</em>，笔者认为其质量不输于一些出版物。</p><h2 id="资源版"><a href="#资源版" class="headerlink" title="资源版"></a>资源版</h2><h3 id="有用经验：不知道什么时候会帮到你的经验"><a href="#有用经验：不知道什么时候会帮到你的经验" class="headerlink" title="有用经验：不知道什么时候会帮到你的经验"></a>有用经验：不知道什么时候会帮到你的经验</h3><p><a href="https://yyjingyan.com/">有用经验</a>是一个分享生活经验的网站。可以在上面检索生活经验，或者订阅它的<a href="https://yyjingyan.com/index.php/feed/">RSS</a>。</p><p><img src="https://s2.loli.net/2024/09/22/PMt2Vs9OdevE3UY.png" alt="PixPin_2024-09-22_14-44-50" loading="lazy"></p><h3 id="AMiner：AI驱动的科研信息集合网站"><a href="#AMiner：AI驱动的科研信息集合网站" class="headerlink" title="AMiner：AI驱动的科研信息集合网站"></a>AMiner：AI驱动的科研信息集合网站</h3><p><a href="https://www.aminer.cn/">AMiner - AI赋能科技情报挖掘-学术搜索-论文检索-论文专利-文献追踪-学者画像</a></p><p><img src="https://s2.loli.net/2024/09/22/eSBsAupoyTxCfrL.png" alt="PixPin_2024-09-22_14-49-04" loading="lazy"></p><h3 id="ML-YouTube-Courses：优质机器学习-人工智能视频课程"><a href="#ML-YouTube-Courses：优质机器学习-人工智能视频课程" class="headerlink" title="ML-YouTube-Courses：优质机器学习/人工智能视频课程"></a>ML-YouTube-Courses：优质机器学习/人工智能视频课程</h3><p><a href="https://github.com/dair-ai/ML-YouTube-Courses">dair-ai/ML-YouTube-Courses: 📺 Discover the latest machine learning / AI courses on YouTube. (github.com)</a></p><p>这个文档收集了多个优质机器学习/人工智能视频课程，按照分类整理，含有每个课程的简介和链接。</p><h3 id="小林图解计算机基础：不错的图解教程"><a href="#小林图解计算机基础：不错的图解教程" class="headerlink" title="小林图解计算机基础：不错的图解教程"></a>小林图解计算机基础：不错的图解教程</h3><p><a href="https://xiaolincoding.com/">小林coding</a></p><p><img src="https://s2.loli.net/2024/09/22/5ElwtxDSOv4uJzo.png" alt="PixPin_2024-09-22_15-13-17" loading="lazy"></p><p><img src="https://s2.loli.net/2024/09/22/6ZT9PvIiYVWueta.png" alt="PixPin_2024-09-22_15-14-25" loading="lazy"></p><p>对自学者/有一定基础<del>，但不多</del>的读者比较友好。</p><p>需要<strong>微信关注其公众号</strong>才能在线阅读完整内容/下载PDF。</p><h3 id="天涯在线：在线阅读当年的“神贴”"><a href="#天涯在线：在线阅读当年的“神贴”" class="headerlink" title="天涯在线：在线阅读当年的“神贴”"></a>天涯在线：在线阅读当年的“神贴”</h3><p><img src="https://s2.loli.net/2024/09/22/L9ol8iz4QxbDk7j.png" alt="PixPin_2024-09-22_15-35-59" loading="lazy"></p><p><a href="https://tianya.at/">天涯神贴-1999~2024年度榜单-天涯 (tianya.at)</a></p><h2 id="工具版"><a href="#工具版" class="headerlink" title="工具版"></a>工具版</h2><h3 id="drawio：开源、轻量但不简陋的图表绘制器"><a href="#drawio：开源、轻量但不简陋的图表绘制器" class="headerlink" title="drawio：开源、轻量但不简陋的图表绘制器"></a>drawio：开源、轻量但不简陋的图表绘制器</h3><p><a href="https://draw.io/">Draw.io</a>是一款功能强大的在线绘图工具，广泛用于创建各种类型的图表，如流程图、思维导图、组织架构图、UML图等。开源于<a href="https://github.com/jgraph/drawio">GitHub</a>。</p><p><img src="https://s2.loli.net/2024/09/22/euTSkzrpFv4MgCQ.png" alt="PixPin_2024-09-22_14-32-39" loading="lazy"></p><p>在笔者知道这个工具之前，绘制一些流程图、架构图的时候，可能会使用微软的Visio或者是国产的<a href="https://www.processon.com/">Processon</a>，但是前者依赖臃肿的客户端，在线编辑体验不佳；后者体验不错，本土化适配很好，可惜不少功能需要付费。</p><p>drawio很好地满足了我的需求：<strong>使用简单、功能较为丰富、轻量级</strong>。</p><p>创建图表的时候，可以在其提供的众多<strong>免费模板</strong>里选择；可以在<strong>图标库</strong>中检索，任意选择需要的图标；也有<strong>自动对齐</strong>等功能，<del>强迫症狂喜</del>。😄</p><p><img src="https://s2.loli.net/2024/09/22/gxOhtHjNrfJEGsK.png" alt="PixPin_2024-09-22_14-42-27" loading="lazy"></p><p>drawio还有众多功能，例如保存到Google drive等云盘、<strong>免费无水印</strong>导出svg、pdf等等。如果读者感兴趣，可以收藏一下，有需要的时候可以亲自体验一下。</p><h3 id="今日热榜：各平台的热榜聚合"><a href="#今日热榜：各平台的热榜聚合" class="headerlink" title="今日热榜：各平台的热榜聚合"></a>今日热榜：各平台的热榜聚合</h3><p><a href="https://rebang.today/">今日热榜 - 全站热榜</a></p><p><img src="https://s2.loli.net/2024/09/22/gtzKWZVvb2xTer6.png" alt="PixPin_2024-09-22_14-57-53" loading="lazy"></p><p>该网站集合了多个平台的热门榜单，可以选择指定平台进行浏览。</p><h3 id="uBlacklist：屏蔽传统搜索引擎中的垃圾信源"><a href="#uBlacklist：屏蔽传统搜索引擎中的垃圾信源" class="headerlink" title="uBlacklist：屏蔽传统搜索引擎中的垃圾信源"></a>uBlacklist：屏蔽传统搜索引擎中的垃圾信源</h3><p><a href="https://chromewebstore.google.com/detail/ublacklist/pncfbmialoiaghdehhbnbhkkgmjanfhe">uBlacklist</a> 是一款浏览器扩展，可以帮助用户屏蔽搜索引擎结果中的低质量网站、内容农场等。</p><p>可以订阅黑名单列表：</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://raw.githubusercontent.com/cobaltdisco/Google-Chinese-Results-Blocklist/master/uBlacklist_subscription.txt</span><br></pre></td></tr></tbody></table></figure><p>也可以自行添加自己不愿意看到的网站。</p><p><img src="https://s2.loli.net/2024/09/22/yMiab6AcqXCGZ8T.png" alt="PixPin_2024-09-22_15-09-15" loading="lazy"></p><p>其实这个插件能做的不止于此。</p><p>读者可能发现了，左侧页面中还有黄色高亮内容，这是使用了该插件的高亮功能实现的，在检索的时候能够提醒：<strong>这是较为优质的信源！</strong></p><p>下面是笔者的自定义规则，比较简陋，供读者参考：</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">*://www.douyin.com/*</span><br><span class="line">*://search.bilibili.com/*</span><br><span class="line">*://gitcode.net/*</span><br><span class="line">*://gitcode.com/*</span><br><span class="line">*://gitcode.csdn.net/*</span><br><span class="line">*://www.gitcode.host/*</span><br><span class="line">*://jform2.baidu.com/*</span><br><span class="line">*://blog.csdn.net/*</span><br><span class="line">@1*://*.reddit.com/*</span><br><span class="line">@1*://*.github.com/*</span><br><span class="line">@1*://*.stackoverflow.com/*</span><br><span class="line">@1*://*.cnblogs.com/*</span><br><span class="line">@1*://*.wikipedia.org/*</span><br><span class="line">@1*://*.youtube.com/*</span><br></pre></td></tr></tbody></table></figure><h3 id="Text-Compare：字符串对比工具"><a href="#Text-Compare：字符串对比工具" class="headerlink" title="Text Compare：字符串对比工具"></a>Text Compare：字符串对比工具</h3><p><a href="https://diffsuite.com/">Text Compare: Real-Time Diff &amp; Merge Tool Online | Free (diffsuite.com)</a></p><p><img src="https://s2.loli.net/2024/09/22/u3ycUtQkpBFhXHq.png" alt="PixPin_2024-09-22_15-28-03 1" loading="lazy"></p><p>简单、美观的字符串对比工具。</p><h3 id="真实地址生成器"><a href="#真实地址生成器" class="headerlink" title="真实地址生成器"></a>真实地址生成器</h3><p><a href="https://realaddress.fuyiran.com/">Real Address Generator (fuyiran.com)</a></p><p>简单方便的真实地址生成器。支持保存使用的地址。</p><p><img src="https://s2.loli.net/2024/09/22/zAWc7jkrguKtsYB.png" alt="PixPin_2024-09-22_15-30-59" loading="lazy"></p><p><img src="https://s2.loli.net/2024/09/22/ewM9ORGW3ApHqLK.png" alt="PixPin_2024-09-22_15-31-27" loading="lazy"></p><p>开源于<a href="https://github.com/Adonis142857/Real-Address-Generator">Github</a>。</p><hr><p>欢迎订阅本周刊的<a href="/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/rss.xml">RSS</a>!</p><p>如果您喜欢我的内容，欢迎评论，让我有继续写周刊的动力；如果您对本周刊有所建议，同样非常欢迎您的评论！</p><p>谢谢♥️！</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>寻觅周刊 第1期：寻觅</title>
      <link>https://shiquda.link/seeking-weekly-1/</link>
      <description>寻觅周刊 第1期：寻觅</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/">寻觅周刊</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Mon, 16 Sep 2024 15:17:35 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>本期是 <em>寻觅周刊</em> 试运营的第1期🎉🎉🎉！</p><p>在这个<strong>信息爆炸</strong>的时代，<em>寻觅</em> 有用的资源是一件不容易的事情。再叠加上近年来各种AIGC内容的影响，学会从庞大到令人绝望的互联网中 <em>寻觅</em> 到适合自己的资源，成了一件非常重要的事情。</p><p><em>寻觅周刊</em> 致力于为读者提供 <strong>新鲜</strong>、<strong>实用</strong> 的 <strong>资源</strong> 和 <strong>工具</strong>，包含了作者一周来接触到的 <strong>实用</strong>、<strong>有趣</strong> 的资源工具，<del>也许有时也会夹带一些私货</del>。</p><p><strong>用尽可能少的时间，获取到尽可能优质的信息</strong>。</p><p>欢迎订阅本周刊的<a href="/categories/%E5%AF%BB%E8%A7%85%E5%91%A8%E5%88%8A/rss.xml">RSS</a>。</p><h2 id="资源版"><a href="#资源版" class="headerlink" title="资源版"></a>资源版</h2><h3 id="Youtube-博主推荐"><a href="#Youtube-博主推荐" class="headerlink" title="Youtube 博主推荐"></a>Youtube 博主推荐</h3><ul><li><a href="https://www.youtube.com/@veritasium">Veritasium - YouTube</a>，讲述自然科学、数学等科普知识。<del>个人比较喜欢</del></li><li><a href="https://www.youtube.com/@Fireship">Fireship - YouTube</a>，擅长在两三分钟内向你介绍计算机行业的知识，或是报道最新行业新闻。</li><li><a href="https://www.youtube.com/@xiao_lin_shuo">小Lin说 - YouTube</a>，优秀的财经博主，讲解深入浅出。</li><li><a href="https://www.youtube.com/@bigthink">Big Think - YouTube</a>，正如其名。</li><li><a href="https://www.youtube.com/@LinusTechTips">Linus Tech Tips - YouTube</a>，科技博主。</li><li><a href="https://www.youtube.com/@Vox">Vox - YouTube</a>，为你解释这个世界。World, explained.</li></ul><h3 id="Dracula：深色主题配色"><a href="#Dracula：深色主题配色" class="headerlink" title="Dracula：深色主题配色"></a>Dracula：深色主题配色</h3><p><a href="https://draculatheme.com/">Dracula — Dark theme for 300+ apps (draculatheme.com)</a></p><p>Dracula是我一直使用的一个主题配色，它包括几乎你能用到的所有软件。</p><p>我使用的就有这些：</p><ul><li>VScode</li><li>Obsidian</li><li>Windows 终端</li><li>Zsh</li><li>Zotero</li><li>Github（通过<a href="https://chromewebstore.google.com/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne">Stylus</a>实现）</li><li>Telegram</li><li>Notepad++</li><li>Discourse主题</li><li>Rime 小狼毫</li><li>代码高亮</li><li>……</li></ul><p>它让我的电脑在视觉意义上成为了一个一致、统一的系统。</p><p><img src="https://s2.loli.net/2024/09/17/x17cI8sSBkCXHp2.png" alt="PixPin_2024-09-17_00-31-31" loading="lazy"></p><p>如果你对这个主题感兴趣，不妨去<a href="https://draculatheme.com/">Dracula官网</a>查找一下你常用的软件，试用一下它的主题。</p><h2 id="工具版"><a href="#工具版" class="headerlink" title="工具版"></a>工具版</h2><h3 id="Cursor：AI和IDE的融合"><a href="#Cursor：AI和IDE的融合" class="headerlink" title="Cursor：AI和IDE的融合"></a>Cursor：AI和IDE的融合</h3><p><a href="https://www.cursor.com/">Cursor</a>是一个以<strong>AI驱动</strong>为特色的代码编辑器，基于知名的开源IDE：<strong>VSCode</strong>。</p><p>上手体验几天之后，它给我的感觉是：在<strong>IDE层面</strong>大大提升了用户在利用AI进行辅助开发的效率。</p><p>下面是Cursor的介绍视频，你也可以在官网观看完整视频：</p><video controls crossorigin playsinline preload="metadata">  <source src="https://www.cursor.com/videos/chat.mp4" type="video/mp4">  <track label="thumbnails" default kind="metadata" src="https://image.mux.com/r43MZq02SaHg7uih1xnZs5DPswDnIBFQtu1D6VISv4XE/storyboard.vtt?format=webp">  <track kind="metadata" label="cuepoints" data-removeondestroy>  Your browser does not support the video tag.</video><p>你可能会问：这和Github Copilot差别很大吗？</p><p><strong>有</strong>。在我看来，它对比Copilot的优势在于以下几点：</p><ol><li>行内代码建议（<code>Tab</code>键）</li></ol><p>熟悉的<code>Tab</code>键，但是：</p><ul><li>可以同时生成<strong>多行</strong>代码建议</li><li>可以<strong>修改</strong>已有代码</li></ul><ol start="2"><li>基于<strong>项目</strong>的代码编写与建议</li></ol><p>对于整个项目，Cursor提供了一种<strong>索引</strong>的方法，能够高效地提取本地项目的信息，嵌入问答中，增强AI回答和编写代码的精确性。</p><p><img src="https://s2.loli.net/2024/09/17/LAhuZIF1VU2MByi.png" alt="PixPin_2024-09-16_23-54-51" loading="lazy"></p><ol start="3"><li>更新代码</li></ol><p>在问答后，如果需要插入代码对原有代码进行修改，Cursor还提供了一种<code>Apply</code>的方法，能够智能创建修改代码的<em>diff</em>，你可以精确到行地选择是否接受代码。</p><p><img src="https://s2.loli.net/2024/09/17/8fi9EawRc17Gsep.png" alt="PixPin_2024-09-16_23-51-16" loading="lazy"></p><p>除了这三点外，还有很多实用的功能。如果你对Cursor感兴趣，不妨动手试一试。</p><p>不必担心适应起来非常麻烦。如果你之前使用VSCode，Cursor可以直接将你的插件等配置<strong>一键导入</strong>，无缝衔接。</p><p>目前Cursor提供15天的免费使用，无须绑定信用卡，使用邮箱注册即可。20$&#x2F;month。它还支持使用目前OpenAI最新的 <code>o1-mini</code>和<code>o1-preview</code> 模型。如果你到期了，还可以换一个邮箱注册，再次试用。</p><h3 id="Follow：新一代信息浏览器"><a href="#Follow：新一代信息浏览器" class="headerlink" title="Follow：新一代信息浏览器"></a>Follow：新一代信息浏览器</h3><p><strong>Follow</strong> 是 RSSHub 的作者打造的“新一代信息浏览器”。你可以简单理解为像 Feedly 那样的在线RSS阅读平台。</p><p>有文章、社交媒体、图片、视频、音频、通知六个板块。</p><p>支持导入OPML文件，方便从Feedly、TTRSS这样的平台或者其他阅读器迁移。借助RSSHub，订阅不同平台的博主变得异常简单。</p><p><img src="https://s2.loli.net/2024/09/17/97bclj5TP6O4I2X.png" alt="PixPin_2024-09-17_10-11-16" loading="lazy"></p><p>整合资源、脱离信息茧房、高效获取信息、拒绝信息流……这些RSS的优点自然不在话下。我认为<strong>Follow</strong>的核心优势在于它的<strong>社区功能</strong>。你可以看到和你订阅同样信息源的其他用户（前提是TA愿意公开），还关注了什么其他信息源。这是一个非常好的<strong>寻找优质信息源</strong>的方式。</p><p><img src="https://s2.loli.net/2024/09/17/pncwjVsLt6fXObP.png" alt="PixPin_2024-09-16_23-59-08" loading="lazy"></p><p><img src="https://s2.loli.net/2024/09/17/j5d7zRbieMqkLSQ.png" alt="PixPin_2024-09-17_00-00-26" loading="lazy"></p><p><a href="https://github.com/RSSNext/Follow">RSSNext&#x2F;Follow: 🧡 Next generation information browser. (github.com)</a> Github 仓库这几天猛增了很多star。</p><p>目前这个工具还处于<em>Alpha</em>测试阶段，需要邀请码才能访问。已有访问权限的用户可以签到5天兑换一个邀请码，但有邀请上限。</p><p>如果想要体验的话，可以去 Follow 的 Discord 群组蹲一下（但是很难抢！）。如果你之前参与过<strong>RSSHub</strong>项目的贡献，可以去Twitter上向作者<a href="https://x.com/DIYgod">@DIYgod</a>讨要一个。</p><h3 id="Complexity：Perplexity-增强插件"><a href="#Complexity：Perplexity-增强插件" class="headerlink" title="Complexity：Perplexity 增强插件"></a>Complexity：Perplexity 增强插件</h3><p><a href="https://cplx.vercel.app/">Complexity</a>能够增强<a href="https://www.perplexity.ai/">Perplexity</a>的功能。</p><p>如果你没听说过<a href="https://www.perplexity.ai/">Perplexity</a>，不妨让它向你自我介绍一下。</p><p><img src="https://s2.loli.net/2024/09/17/iXUvLJIkSchFpWK.png" alt="PixPin_2024-09-17_00-08-32" loading="lazy"></p><p>Complexity的部分功能如下：</p><ul><li>各种用户界面&#x2F;用户体验&#x2F;用户体验调整。</li><li>LLM&#x2F;Image gen 模型选择器；导出搜索&#x2F;对话等。</li><li>高度可定制的主题（支持自定义 css）。</li><li>提示词管理专用解决方案：提示库（开发中）。</li></ul><h3 id="OneTab：简单粗暴地管理标签页"><a href="#OneTab：简单粗暴地管理标签页" class="headerlink" title="OneTab：简单粗暴地管理标签页"></a>OneTab：简单粗暴地管理标签页</h3><p><a href="https://chromewebstore.google.com/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall">OneTab</a>是一个用于管理标签页的浏览器插件。</p><p>使用浏览器时，常常会遇到这种情况：</p><p><img src="https://s2.loli.net/2024/09/17/UwhNojOcX1gY9q6.png" alt="PixPin_2024-09-17_00-36-24" loading="lazy"></p><p>标签很多，占用不少内存。这里面有些标签我们想要关闭，有些想留着，还有些又想留以后再用。怎么办呢？</p><p>简单粗暴的方法：使用OneTab一键收纳，还能节省内存。</p><p><img src="https://s2.loli.net/2024/09/17/ZNQTYlbmKoeXGnx.png" alt="PixPin_2024-09-17_00-38-31" loading="lazy"></p><p>轻轻一点，所有的标签都被关闭，只剩下 One Tab。</p><p><img src="https://s2.loli.net/2024/09/17/RAyNBI3T9vVEwb8.png" alt="PixPin_2024-09-17_00-39-11" loading="lazy"></p><p>在这个面板里，你可以直观地看到哪些要留着以后用，哪些没用。不确定也没事，留在这个面板，下次来这边打开就行了。</p><hr><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>这是我第一次尝试以这种方式来写作：<em>周刊</em>。我认为我在发现优质信息、资源方面有一定能力，但是这种能力在过去一段时间内帮助到的人非常有限。</p><p>如果你喜欢我的内容，欢迎在下面留言，让我更有动力写下去；如果有什么建议，也请随意提出。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>微信读书已购图书下载</title>
      <link>https://shiquda.link/download-weread-books/</link>
      <description>本文介绍了一种下载微信读书图书的方式，利用微信读书的缓存功能，能够下载用户有阅读权限的书籍，并且可以转换为PDF等格式。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Mon, 16 Sep 2024 13:41:50 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文介绍了一种下载<strong>微信读书</strong>图书的方式，利用微信读书的<strong>缓存</strong>功能，能够下载用户有阅读权限的书籍，并且可以转换为PDF等格式。</p><div class="tag-plugin colorful note" ><div class="body"><p><strong>注意</strong>：该软件<strong>不含任何会员破解功能</strong>。博主不是该软件的作者，资源来自互联网，使用该软件而产生的<strong>一切风险</strong>与本博主无关，包括但不限于潜在的账号封禁风险。</p></div></div><h2 id="教程"><a href="#教程" class="headerlink" title="教程"></a>教程</h2><h3 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h3><h4 id="蓝奏云"><a href="#蓝奏云" class="headerlink" title="蓝奏云"></a>蓝奏云</h4><p><a href="https://wwrd.lanzouv.com/i1zj02a4imbi">https://wwrd.lanzouv.com/i1zj02a4imbi</a></p><h4 id="百度网盘"><a href="#百度网盘" class="headerlink" title="百度网盘"></a>百度网盘</h4><p>链接: <a href="https://pan.baidu.com/s/1CJYdGNDF9-X7nCYP4Zxjzg?pwd=ecw3">https://pan.baidu.com/s/1CJYdGNDF9-X7nCYP4Zxjzg?pwd=ecw3</a> 提取码: ecw3</p><h3 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h3><p>先把压缩包解压到合适的位置，然后双击<code>微信读书下载器.exe</code>打开软件。</p><h3 id="登录微信读书"><a href="#登录微信读书" class="headerlink" title="登录微信读书"></a>登录微信读书</h3><p><img src="https://s2.loli.net/2024/09/16/EPSXVuQOxlWvC3s.png" alt="PixPin_2024-09-16_22-16-42 1" loading="lazy"></p><p>打开软件后，点击扫码登录，然后再点击“获取登录二维码”，再使用微信扫码登录。</p><h3 id="加入书架"><a href="#加入书架" class="headerlink" title="加入书架"></a>加入书架</h3><p>把你想要下载的书在手机微信读书App中加入书架，然后刷新软件页面，点击对应的书下载即可</p><h3 id="获取电子书"><a href="#获取电子书" class="headerlink" title="获取电子书"></a>获取电子书</h3><p>打开软件文件夹下的<code>book-&gt;一串数字-&gt;下载的书目-&gt;看这里</code>里的html文件，用浏览器打开文件</p><p><img src="https://s2.loli.net/2024/09/16/MA6m189OLU5ayDv.png" alt="PixPin_2024-09-16_22-20-54" loading="lazy"></p><p><img src="https://s2.loli.net/2024/09/16/ysIoDPfVMAxvTNZ.png" alt="PixPin_2024-09-16_22-22-16" loading="lazy"></p><p>在浏览器打开后，按下 <code>Ctrl</code> + <code>P</code>，选择“另存为PDF”，然后选择保存位置，即可下载PDF。</p><p><img src="https://s2.loli.net/2024/09/16/uFM8I6jql2BmXgQ.png" alt="PixPin_2024-09-16_22-23-44" loading="lazy"></p><p>导出的PDF可以本地阅读，也可以导入微信读书等软件永久免费阅读。</p><h3 id="电子书格式转换"><a href="#电子书格式转换" class="headerlink" title="电子书格式转换"></a>电子书格式转换</h3><p>如果你需要转换为其他电子书格式，可以使用 <a href="https://convertio.co/zh/ebook-converter/">https://convertio.co/zh/ebook-converter/</a> 这个网站进行转换，上传你的pdf文件，然后选择你想要的格式，即可免费进行转换。</p><p><img src="https://s2.loli.net/2024/09/16/vMHSOQx9CTDZ7LF.png" alt="PixPin_2024-09-16_22-25-45" loading="lazy"></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Hexo!</title>
      <link>https://shiquda.link/move-to-hexo/</link>
      <description>I Love Hexo!</description>
      <author>shiquda</author>
      <pubDate>Tue, 10 Sep 2024 14:59:47 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="Hexo"><a href="#Hexo" class="headerlink" title="Hexo"></a>Hexo</h2><p><a href="https://shiquda.link/">个人博客</a>迁移到 <em>Hexo</em> 的测试。</p><h2 id="为什么要迁移？"><a href="#为什么要迁移？" class="headerlink" title="为什么要迁移？"></a>为什么要迁移？</h2><p>原来用的是Solo框架，正如其名，比较小众，而且是动态博客。今天突然想尝试一下用静态博客，于是选了Hexo框架。</p><p>最大的感受就是<strong>自定义能力强，生态丰富</strong>。折腾的时候虽然没写几行代码，但总感觉是真的在搭建一个属于自己的网站一样，这个网站就跟自己的孩子一般。<del>其实如果不是有一天空闲也不会这样想</del></p><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p><img src="https://s2.loli.net/2024/09/12/2z8XjtscDVelywk.png" alt="blog (1)" loading="lazy"></p><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><h3 id="图片测试"><a href="#图片测试" class="headerlink" title="图片测试"></a>图片测试</h3><blockquote><p>图片来自 <a href="https://shiquda.link/batch-download-high-quality-music">免费批量下载无损高音质音乐教程</a>。</p></blockquote><p><img src="https://s2.loli.net/2024/07/18/dXIgWOsnji2ZpDN.png" alt="Clip_2024-07-18_14-44-04" loading="lazy"></p><h3 id="代码块测试"><a href="#代码块测试" class="headerlink" title="代码块测试"></a>代码块测试</h3><h4 id="代码渲染"><a href="#代码渲染" class="headerlink" title="代码渲染"></a>代码渲染</h4><p>当然是 <del>我最喜欢的</del> <code>Python</code> 了！</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">hello</span>():</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">"Hello, Hexo!"</span>)</span><br></pre></td></tr></tbody></table></figure><h4 id="代码折叠"><a href="#代码折叠" class="headerlink" title="代码折叠"></a>代码折叠</h4><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">    从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">        从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">            从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                    从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                        从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                            从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                    从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                        从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                            从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                                从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                                    从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                                        从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：</span><br><span class="line">                                                            从前有座山，山上有座庙，庙里有个老和尚和一个小和尚，老和尚对小和尚说：https://www.bilibili.com/video/BV1GJ411x7h7/</span><br></pre></td></tr></tbody></table></figure><h3 id="LaTeX-测试"><a href="#LaTeX-测试" class="headerlink" title="LaTeX 测试"></a>LaTeX 测试</h3><p>$$\text{Blog framework} = \text{Hexo now!}$$</p><h3 id="callout测试"><a href="#callout测试" class="headerlink" title="callout测试"></a>callout测试</h3><div class="tag-plugin colorful note"><div class="body"><p>傻孩子们，快跑啊！！！</p></div></div><div class="tag-plugin colorful note"><div class="body"><p>不要回答！！！</p></div></div><h3 id="快捷键"><a href="#快捷键" class="headerlink" title="快捷键"></a>快捷键</h3><p>试试 <kbd>Alt</kbd>+<kbd>F4</kbd></p><h3 id="TO-DO"><a href="#TO-DO" class="headerlink" title="TO-DO"></a>TO-DO</h3><ul><li><input checked="" disabled="" type="checkbox"> to</li><li><input disabled="" type="checkbox"> do</li></ul><h3 id="表格"><a href="#表格" class="headerlink" title="表格"></a>表格</h3><div class="md-table-scroll"><table><thead><tr><th>框架</th><th>网址</th><th>备注</th></tr></thead><tbody><tr><td>Hexo</td><td><a href="https://hexo.io/">Hexo</a></td><td>个人博客框架</td></tr><tr><td>Solo</td><td><a href="https://b3log.org/solo/">Solo</a></td><td>动态博客框架</td></tr></tbody></table></div><h3 id="嵌入视频"><a href="#嵌入视频" class="headerlink" title="嵌入视频"></a>嵌入视频</h3><!-- youtube --><iframe width="560" height="315" src="https://www.youtube.com/embed/qf7ws2DF-zk" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe><h2 id="用到的主题-插件"><a href="#用到的主题-插件" class="headerlink" title="用到的主题/插件"></a>用到的主题/插件</h2><p>如你所见，我用了NexT主题，还有以下插件：</p><ul><li><code>hexo-theme-next</code></li><li><code>hexo-auto-excerpt</code></li><li><code>hexo-math</code></li><li><code>hexo-next-darkmode</code></li><li><code>mdit-plugin-callouts</code></li><li><code>hexo-next-twikoo</code></li><li><code>hexo-generator-feed</code></li><li><code>hexo-generator-search</code></li><li><code>hexo-symbols-count-time</code></li><li><code>hexo-deployer-rsync</code></li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>Windows下 Vim for VSCode 使用大小写切换键 CapsLock 代替 Esc</title>
      <link>https://shiquda.link/windows-vim-for-vscode-use-capslock-instead-of-esc/</link>
      <description>使用AutoHotkey，将CapsLock键映射为Esc键，实现VSCode中Vim模式下的键位替换，同时避免每次切换大小写状态的问题</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/AHK/">AHK</category>
      <pubDate>Fri, 02 Aug 2024 14:56:46 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><strong>使用AutoHotkey实现</strong>。</p><p>为什么不用VSCode自带的快捷键映射呢？</p><p>我按照网上的方案试了一下，结果每次按Esc返回的时候，都会同时更改大小写状态，不是很习惯。</p><h2 id="安装AutoHotkey"><a href="#安装AutoHotkey" class="headerlink" title="安装AutoHotkey"></a>安装AutoHotkey</h2><p><a href="https://www.autohotkey.com/">AutoHotkey</a></p><p>因为编写的脚本是2.0版本的，所以下载的时候请选择<strong>Download v2.0</strong>。</p><h2 id="编写脚本"><a href="#编写脚本" class="headerlink" title="编写脚本"></a>编写脚本</h2><p>在合适的地方创建<code>vscode-vim.ahk</code>脚本。如果想要开机运行，可以直接<code>shell:startup</code>下编写，或是在启动目录创建一个脚本的快捷方式。</p><figure class="highlight ahk"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#Requires AutoHotkey v2.0</span></span><br><span class="line"><span class="meta"></span></span><br><span class="line"><span class="meta">#HotIf WinActive("ahk_exe Code.exe")</span></span><br><span class="line"></span><br><span class="line"><span class="comment">; 将 Caps Lock 键映射为 Esc</span></span><br><span class="line"><span class="title">CapsLock::</span> {</span><br><span class="line">    Send(<span class="string">"{Esc}"</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">; 将 Esc 键映射为 Caps Lock</span></span><br><span class="line"><span class="title">Esc::</span> {</span><br><span class="line">    if (GetKeyState(<span class="string">"CapsLock"</span>, <span class="string">"T"</span>)) {</span><br><span class="line">        SetCapsLockState(<span class="string">"Off"</span>)</span><br><span class="line">    } else {</span><br><span class="line">        SetCapsLockState(<span class="string">"On"</span>)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"><span class="meta"></span></span><br><span class="line"><span class="meta">#HotIf</span></span><br></pre></td></tr></tbody></table></figure><p>这个脚本只会在VSCode中生效，将Caps键与Esc键互相转换。想要开启脚本，双击运行即可。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>免费批量下载无损高音质音乐教程</title>
      <link>https://shiquda.link/batch-download-high-quality-music/</link>
      <description>通过Tune My Music工具将歌单导入Qobuz，再使用streamrip工具批量下载无损音质的歌曲，满足音质需求和免费获取资源的目标。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Thu, 18 Jul 2024 10:40:41 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>先允许我唠叨几句，如果着急的话可以直接跳到正文。</p><p>这几天突然觉得Spotify的音质不怎么样，据说最高只有320K。我虽然不是发烧友，但是还是比较看重音乐的音质的。但是我又不想多充一个平台的钱，于是我想到了一个替代方案：利用Spotify优秀的推荐算法来发现新歌，然后用本地播放器播放我Spot歌单里面的歌曲。</p><p>但是，这就涉及到一个重要的问题了：我的歌单里面有好几百首歌曲，想把他们全部下下来可不容易。虽然我知道有渠道可以免费下载高质量音频，比如一些<a href="https://t.me/flacmusics">Tg群组</a>或者是大名鼎鼎的<a href="https://tools.liumingye.cn/music/#/">MyFreeMP3 (liumingye.cn)</a>，但是他们下载都比较麻烦，不好批量下载，可能适合剪视频这种临时需要找几首的情况下下载。难道这个三色图又成立了？<br><img src="https://b3logfile.com/file/2024/07/solo-fetchupload-17046710997852730394-3Oe8lyG.png" alt="Clip_2024-07-18_14-44-04" loading="lazy"></p><p>今天，偶然看到一位大佬的<a href="https://linux.do/t/topic/19035">白嫖数千万的高解析音乐曲库！下载qobuz，tidal，deezer等流媒体音乐平台资源的方法 - 常规话题 / 精华神贴 - LINUX DO</a>帖子，顺着的他思路，我试了一下，发现这三者竟然可以同时成立，很好的满足了我<del>白嫖</del>的需求，现在将我的整体流程分享一下。</p><hr><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>如果你在一些音乐平台有体量很大的歌单，又不能免费把他们全部下载成无损音质的音频，可以试一下这个方法。</p><p>注意，本教程需要Python环境，这里默认你安装了python环境。若没安装请自行搜索教程/问GPT。</p><h3 id="获取歌单列表"><a href="#获取歌单列表" class="headerlink" title="获取歌单列表"></a>获取歌单列表</h3><h4 id="国内平台（网易云-QQ音乐）"><a href="#国内平台（网易云-QQ音乐）" class="headerlink" title="国内平台（网易云/QQ音乐）"></a>国内平台（网易云/QQ音乐）</h4><p><a href="https://yyrcd.com/n2s/">迁移 网易云 / QQ 音乐到 Apple Music, Youtube Music, Spotify | yyrcd</a></p><p><img src="https://s2.loli.net/2024/07/18/TgF2euQ45RynGBd.png" alt="Clip_2024-07-18_15-02-45" loading="lazy"></p><p>按照上面网站的指引，输入歌单，然后就可以把对应歌单提取为txt文本格式。</p><h4 id="国外平台（Spotify-Apple-Music-Youtube-Music等）"><a href="#国外平台（Spotify-Apple-Music-Youtube-Music等）" class="headerlink" title="国外平台（Spotify/Apple Music/Youtube Music等）"></a>国外平台（Spotify/Apple Music/Youtube Music等）</h4><p><a href="https://www.tunemymusic.com/zh-CN/transfer">在不同的音乐服务之间迁移播放列表 | Tune My Music</a></p><p>我们使用上面的工具进行转换，如果你的歌单数目低于500（该工具免费版限制），可以直接按照网站的指引登录账户，获取歌单，然后直接选择导入目标为qobuz平台。</p><p><img src="https://b3logfile.com/file/2024/07/solo-fetchupload-2141195553151529836-eHDZ5wZ.png" alt="Clip_2024-07-18_14-56-18" loading="lazy"></p><p>如果没有该平台的账户，可以免费创建一个<a href="https://play.qobuz.com/login">Qobuz</a>账户，建议直接用google账户创建。这个平台我们不需要充值，只是作为一个方便批量下载工具下载的跳板。</p><p>如果你的歌单歌曲超过500怎么办？也没有关系，可以先选择转换为TXT下载保存，后续使用Tune My Music多次导入就行了，一次能免费导入500首歌曲。</p><h3 id="导入歌曲至Qobuz"><a href="#导入歌曲至Qobuz" class="headerlink" title="导入歌曲至Qobuz"></a>导入歌曲至Qobuz</h3><p><a href="https://www.tunemymusic.com/zh-CN/transfer">在不同的音乐服务之间迁移播放列表 | Tune My Music</a></p><p>上面一步中，如果你是国内平台或者超过500首歌曲，在选择导入的时候选择任意文本。</p><p><img src="https://s2.loli.net/2024/07/18/IW4jrAuD7ihN18M.png" alt="Clip_2024-07-18_15-03-05" loading="lazy"></p><p>然后输入你之前获取的歌单文本，如果超过500首的话就分批导入。</p><p><img src="https://b3logfile.com/file/2024/07/solo-fetchupload-7662927726149957668-STn6zsN.png" alt="Clip_2024-07-18_15-04-12" loading="lazy"></p><p>选择目的地为qobuz。</p><p>导入完成后，打开<a href="https://play.qobuz.com/user/library/playlists">歌单列表</a>，先把歌单的Private取消掉，否则工具无法公开读取你的歌单。</p><p><img src="https://b3logfile.com/file/2024/07/solo-fetchupload-16893922363331241181-xZCoPo0.png" alt="Clip_2024-07-18_15-06-57" loading="lazy"></p><p><img src="https://s2.loli.net/2024/07/18/ZvhBXnJwKEyIbtj.png" alt="Clip_2024-07-18_15-08-51" loading="lazy"></p><h3 id="批量下载"><a href="#批量下载" class="headerlink" title="批量下载"></a>批量下载</h3><p><a href="https://github.com/nathom/streamrip/tree/dev">nathom/streamrip: A scriptable music downloader for Qobuz, Tidal, SoundCloud, and Deezer (github.com)</a></p><p>我们使用这个工具来批量下载。</p><p>安装需要有python环境。执行以下命令安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install poetry</span><br></pre></td></tr></tbody></table></figure><p>安装后，打开配置文件</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rip config open</span><br></pre></td></tr></tbody></table></figure><p>可以参考我的填法配置。好心人提供的token和id可以从<a href="https://rentry.org/firehawk52#tokens">Firehawk52 Official - Saving Digital Legacy (rentry.org)</a>找到。</p><p><img src="https://s2.loli.net/2024/07/18/FbL3ovgXIMhtxZY.png" alt="Clip_2024-07-18_15-35-57" loading="lazy"></p><p>保存后，前往之前转移到qobuz的歌单链接，然后执行</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rip url https://play.qobuz.com/playlist/xxxxxxxx</span><br></pre></td></tr></tbody></table></figure><p>就会开始下载了。如果无法连接，可能需要开启全局代理或者tun模式。</p><p><img src="https://b3logfile.com/file/2024/07/solo-fetchupload-8804855553939764649-PEFlbt7.png" alt="Clip_2024-07-18_15-39-43" loading="lazy"></p><p>如果下载断开报错，只需要再执行一次就好了，已经下载的会自动跳过。</p><h2 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h2><p>虽然说大致解决<em>三色图难题</em>，但是这种方法还是有一些缺陷的。</p><ol><li>歌单转换可能不准确或者缺失。由于我听的大多数是英文歌，华语歌曲没怎么测试，可能会有缺失；部分歌曲转换后可能版本不太一致（比如原版变成了remix版或是相反），估计准确率在90%左右</li><li>qobuz里边有部分歌曲是灰色的，无法获取资源，个人猜测可能和token账号所在的国家有关。如果有部分歌曲下载失败可以换一个token试试。下载成功率大概也是90%。</li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>wereadcard：微信读书卡片生成器</title>
      <link>https://shiquda.link/weread-card-project/</link>
      <description>今天搓了个微信读书的卡片生成器，权且当作兴趣和练手，水一篇博文。欢迎Star。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A1%B9%E7%9B%AE/">项目</category>
      <category domain="https://shiquda.link/tags/Python/">Python</category>
      <category domain="https://shiquda.link/tags/%E9%A1%B9%E7%9B%AE/">项目</category>
      <pubDate>Wed, 17 Jul 2024 15:39:35 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>今天搓了个微信读书卡片生成器，权且当作兴趣和练手，水一篇博文。欢迎Star。</p><p><a href="https://github.com/shiquda/wereadcard">shiquda/wereadcard (github.com)</a></p><p>效果展示：</p><p>github：</p><p><img src="https://raw.githubusercontent.com/shiquda/wereadcard/main/output/recent_read.svg" alt="raw.githubusercontent.com/shiquda/wereadcard/main/output/recent_read.svg" loading="lazy"></p><p>如果加载不出来，还有镜像站：<br><img src="https://raw.kkgithub.com/shiquda/wereadcard/main/output/recent_read.svg" alt="raw.kkgithub.com/shiquda/wereadcard/main/output/recent_read.svg" loading="lazy"></p><p>下面是简介。当然，建议直接去<a href="https://github.com/shiquda/wereadcard">Github</a>上查看，这里的版本可能过时。</p><hr><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>本项目利用 Github Actions 自动抓取微信读书记录，并且生成 <code>.svg</code> 卡片，作为展示。</p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="使用-Github-Actions"><a href="#使用-Github-Actions" class="headerlink" title="使用 Github Actions"></a>使用 Github Actions</h3><h4 id="cookie-获取"><a href="#cookie-获取" class="headerlink" title="cookie 获取"></a>cookie 获取</h4><p>这里仅演示一种方法：</p><p>进入<a href="https://weread.qq.com/">https://weread.qq.com/</a>，扫码登陆微信读书。</p><p>使用<code>F12</code>控制台工具，打开网络/Network，刷新页面，筛选Fetch/XHR，任意选中一个请求，然后在标头/Header处找到Cookie，完整复制对应的字符串。</p><h4 id="Github-配置"><a href="#Github-配置" class="headerlink" title="Github 配置"></a>Github 配置</h4><ol><li><strong>fork</strong>本仓库。</li><li>在你的仓库，进入<code>Settings &gt; Secrets and variables &gt; Actions</code>，添加 <code>Repository secrets</code>：</li><li>【必填】：<code>WEREAD_COOKIE</code>，添加上一步复制的微信读书cookie字符串</li><li>【非选填】：<code>BOOK_COUNT</code>，默认为<code>4</code>，图片上展示的图书数量，建议不超过<code>5</code>。.</li><li>进入<code>Settings &gt; Actions &gt; General</code>，找到<code>Workflow permissions</code>，改为选择<code>Read and write permissions</code>，并点击<code>Save</code>保存。</li></ol><p>现在Github Actions默认会每间隔8个小时更新一次图像，并推送至仓库。更新的卡片在<code>/output/recent_read.svg</code>可以找到。</p><p>当然，你也可以手动触发Actions。</p><h4 id="获取图片直链"><a href="#获取图片直链" class="headerlink" title="获取图片直链"></a>获取图片直链</h4><p>在GitHub进入图片，<code>Raw</code>对应的就是直链链接。如果网络环境不好的，可以考虑使用镜像站加速，将URL中的<code>githubusercontent</code>替换为<code>kkgithub</code>，如：</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://raw.githubusercontent.com/shiquda/wereadcard/main/output/recent_read.svg</span><br></pre></td></tr></tbody></table></figure><p>替换为</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://raw.kkgithub.com/shiquda/wereadcard/main/output/recent_read.svg</span><br></pre></td></tr></tbody></table></figure><h3 id="本地使用"><a href="#本地使用" class="headerlink" title="本地使用"></a>本地使用</h3><p>克隆本仓库，然后安装依赖：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -r requirements.txt</span><br></pre></td></tr></tbody></table></figure><p>支持两种使用方式：可以直接在<code>main.py</code>中配置cookie等参数，然后直接运行，或者使用命令行参数：</p><ul><li><code>--cookie, -c</code>：cookie字符串，注意在字符串两端加上引号。</li><li><code>--number, -n</code>：生成卡片中图书的数量。</li></ul><p>运行后生成的卡片在<code>/output</code>目录中。</p><h2 id="致谢"><a href="#致谢" class="headerlink" title="致谢"></a>致谢</h2><ul><li><a href="https://github.com/malinkang/weread2notion">malinkang/weread2notion: 将微信读书划线同步到Notion (github.com)</a></li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>你真的是墙头草吗？</title>
      <link>https://shiquda.link/are-you-a-wallflower/</link>
      <description>你真的是墙头草吗？</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%9A%8F%E6%83%B3/">随想</category>
      <category domain="https://shiquda.link/tags/%E8%80%95%E8%AF%BB/">耕读</category>
      <pubDate>Mon, 08 Jul 2024 14:28:23 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="你真的是墙头草吗？"><a href="#你真的是墙头草吗？" class="headerlink" title="你真的是墙头草吗？"></a>你真的是墙头草吗？</h2><p>我们说一个人是“墙头草”，可能意思是说这个人<strong>听到别人说什么就是什么</strong>，没有主见。换一种说法，他<strong>只相信他最后听到的那种观点</strong>。</p><p><em>墙头草</em>这个词无疑带有贬义，而与之相反的另一类人也时常会被夸赞<em>坚持自我</em>、<em>有主见</em>。</p><p>等一等。如果换一种词来形容这两类人，可能情况就截然不同了。</p><blockquote><p>A是一个<em>随机应变、听得进他人意见</em>的人，而B是一个<em>刚愎自用、自以为是</em>的人。</p></blockquote><p>第一反应，A在我们心中的留下的印象就是一个开明的人，而B则是一个迂腐、目中无人的人。</p><p>有没有发现？仅仅将具有相近意思的词语的褒贬性进行反转，所表达的意思就完全不同了。</p><p>如果你认同我的观点，那么请让我再问你一次：既然你被我说服了，那么<strong>你真的是墙头草吗？</strong></p><p>你可能并不会认为自己是墙头草，至少不愿承认这一点，你想反驳，但是可能这两者之间的区别又很难说出来。</p><p>其实，两者的区别很简单。让我告诉你我的想法。</p><h2 id="只是你自己给你自己贴上了墙头草的标签"><a href="#只是你自己给你自己贴上了墙头草的标签" class="headerlink" title="只是你自己给你自己贴上了墙头草的标签"></a>只是你自己给你自己贴上了墙头草的标签</h2><p>也许，你实际上是在对你自己进行“<strong>道德绑架</strong>”，<strong>说服自己放弃相信新的信息和观点</strong>，来维护自己的“主见”。更可怕的是，这很可能是一个隐性的过程，你甚至可能还没有意识到这一点。</p><p>下面一段摘自我最近读的《学会提问》，也许会让你有新的思考。</p><blockquote><p>我们的文化对那些改变观点的人没有广博的宽容心，我们总是称他们为“墙头草”或“伪君子”，而没有认识到，当新的证据出现时，改变我们的观点不仅是自然而然的事情，而且是负责任、有担当的表现。<br>——《学会提问》by 尼尔·布朗斯图尔特·基利</p></blockquote><p>这段话让让我有一种“触动”，激发我产生了不少想法。很多时候，其实是我们自己给自己设下了道德约束，让我们对自己的行为进行过度的反思，而正是这种约束阻碍了我们进行进一步深入的分析与思考。</p><p>我一直反对简单地使用一个标签来封住他人的嘴，对他进行“盖棺定论”。更可怕的是，这种标签会在无形之中让我们的大脑按照《思考，快与慢》中的系统一行事，我们评价他人的观点的时，在不知不觉中带上了有色眼镜。</p><blockquote><p>系统一的大概意思是大脑按照已有的经验给出快速而直接的反应，简单来说就是“偷懒”了。</p></blockquote><p>在“墙头草”这个标签中，我们很可能就在无形之中给大脑加上了阻碍了思考的枷锁，毕竟，<strong>“坚持”自己原有的想法</strong>是最容易被大脑接受的一种选择。可怕的是，我们很难意识到这一点。</p><p>我想你心中应该还有一个疑问：什么时候算是“墙头草”，什么时候又算是“听得进他人意见”呢？</p><p>其实这个问题很简单。</p><p>我的想法是，好的思考方式应该是：</p><ul><li><strong>根据不断出现的新信息做出可靠判断</strong>，然后<strong>更新自己的信念</strong>；</li><li><strong>而不是按照自己的信念，选择性地接受部分信息</strong>。</li></ul><p>人无完人，没有一个人一直正确，也没有一种观点从诞生之初就能做到完美无瑕。</p><p><strong>立场和观点是从可靠的信息里诞生的，而不是本末倒置，按照已有的立场和观点对信息进行不应该的筛选。</strong></p><p>这么说，这个问题的关键在于：如何选出“可靠”的信息。这又是另一个话题了，有机会我再说说我的理解和想法。<del>挖坑</del></p><p>我们不应该“带着有色眼镜”看待其他观点或者证据，而应该保持中立的立场；同时，当我们思考支持自己观点的理由的时候，也不应该回避可能对我们已有观点不利的因素。</p><p>看到这里，你可能会问，这不就是打自己的脸吗，谁会找不支持自己观点的理由呢？</p><h2 id="求真-OR-求胜？"><a href="#求真-OR-求胜？" class="headerlink" title="求真 OR 求胜？"></a>求真 OR 求胜？</h2><p>这就要提到我们思考问题的目的了：<strong>求真 OR 求胜</strong>？</p><p>我们经常会有这种体验：两个人就某个观点进行辩论，互相都不能说服对方。二者分别从自己的观点和立场出发，寻找最能够支持自己观点的理由，并且迫不及待地说给对方。结果往往也是不了了之，双方互相都不能说服对方。</p><p>这其实有点像一场辩论赛：正方和反方都不遗余力地提出支持自己观点的理由，同时攻击对方的观点。但不同的是，辩论赛最终由裁判进行评分，选出胜利的一方；正方和反方完全不可能改变自己的立场，在赛中承认对方的观点（至少我没见过）。在这场游戏里，他们的目的是<strong>求胜</strong>。</p><p>无奈的是，生活虽然不是辩论赛，但很多时候因为各种原因，<strong>求真</strong>的机会少之又少。</p><p>但当一个人静下来时，不是为了其他而思考的时候，我希望能够放下一切，甚至包括自己的已有立场，中立性地看待问题、思考他人的观点、分析信息的可靠性……尽管这是一个几乎不可能的任务，但是“虽不能及，心向往之”也是一种不错的态度吧。</p><hr><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><p>这是我第一次真正把自己的所想整理成博文发出，以前可能只是自己脑子里想想，或是与好友交流，但是这回我希望能和更多人分享我的思考。</p><p>我给这个系列取名“<strong>耕读</strong>”。在这个越来越快的社会里，能够有阅读与思考闲暇时光真的是一件奢侈的事情。因此，尽管我不希望如此，这个系列可能只有这1篇文章。</p><p>当然，我写这篇博文不是为了说服你，只是提供一种思考问题的方向。如果你不同意我的观点，欢迎与我交流。希望以求真为目的。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>解决Windows 11下蓝牙“闪退”、搜不到设备问题</title>
      <link>https://shiquda.link/solve-annoying-bluetooth-problem-on-windows-11/</link>
      <description>博主在一次系统更新后，蓝牙面板无反应且“闪退”。将 Device Association Service 的启动类型设为“自动”即可解决问题。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Sun, 02 Jun 2024 14:33:01 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="问题简述"><a href="#问题简述" class="headerlink" title="问题简述"></a>问题简述</h2><p>这个问题困扰了我好几个月了，当时好像是发生在一次Win11系统更新之后，突然从右下角的面板点击蓝牙就没反应，点击右边的展开按钮就会“闪退”。</p><p><img src="https://b3logfile.com/file/2024/06/solo-fetchupload-7051497606968585562-eRw2iak.png" alt="Clip_2024-06-02_22-24-07" loading="lazy"></p><p>并且也无法发现新的设备，只能连接已经配对的设备。</p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>我试着Google了各种方法，但是无不例外都失效了（除了重装系统还没试）。后来发现有一个系统服务<code>Device Association Service</code>不知道为什么被我禁用了，在属性里面把它的启动类型改为“自动”就可以了。</p><p><img src="https://b3logfile.com/file/2024/06/solo-fetchupload-7192284970521405567-oCQQSl6.png" alt="Clip_2024-06-02_22-21-16 1" loading="lazy"></p><p><img src="https://b3logfile.com/file/2024/06/solo-fetchupload-5081982689478401641-Dgwm5sB.png" alt="Clip_2024-06-02_22-27-58" loading="lazy"></p><p>于是终于能看到已经有点陌生的界面了。。。</p><p><img src="https://b3logfile.com/file/2024/06/solo-fetchupload-16780743642740616569-40oy0kU.png" alt="Clip_2024-06-02_22-28-31" loading="lazy"></p><p><del>如果不是因为换耳机也不会折腾一晚上。。。。。</del></p><p>希望这篇教程对能解决你的问题，哪怕只有一个人因为我的文章少走弯路，我也觉得很满足了。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>P1120 小木棍</title>
      <link>https://shiquda.link/P1120/</link>
      <description>读题
P1120 小木棍 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

给 $n$ 个小木棍的长度 $a_i$ ，满足$1 \leq a_{i} \leq 50$ , $n \leq 650$ ，它们之间可以任意拼接，现在要让它们拼接后的长度相同，求这个相同长度的最小值。

例如：

1
2


9
5 2 1 5 2 1 5 2 1


其中最小的长度是6，分别由3个 5 1 和一个2 2 2拼成。

题目说是搜索题。

思路
这题看起来简洁易懂，但是实际操作起来却比较繁琐，我最早不信邪，使用贪心来尝试，结果不行，还是只能老老实实去写搜索。

首先分析一下题目中隐藏的数</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A2%98%E8%A7%A3/">题解</category>
      <category domain="https://shiquda.link/tags/%E9%A2%98%E8%A7%A3/">题解</category>
      <pubDate>Thu, 30 May 2024 12:06:08 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="读题"><a href="#读题" class="headerlink" title="读题"></a>读题</h2><p><a href="https://www.luogu.com.cn/problem/P1120">P1120 小木棍 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)</a></p><p>给 $n$ 个小木棍的长度 $a_i$ ，满足$1 \leq a_{i} \leq 50$ , $n \leq 650$ ，它们之间可以任意拼接，现在要让它们拼接后的长度相同，求这个相同长度的最小值。</p><p>例如：</p><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">9</span><br><span class="line">5 2 1 5 2 1 5 2 1</span><br></pre></td></tr></tbody></table></figure><p>其中最小的长度是6，分别由3个 <code>5 1</code> 和一个<code>2 2 2</code>拼成。</p><p>题目说是搜索题。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>这题看起来简洁易懂，但是实际操作起来却比较繁琐，我最早<del>不信邪</del>，使用贪心来尝试，结果不行，还是只能老老实实去写搜索。</p><p>首先分析一下题目中隐藏的数学性质：最终相同长度的木棍的数量范围是确定的，从1~n，那么木棍长度的可能取值其实是有限的，可以容易得出：<strong>长度一定能被所有木棍长度之和sum整除</strong>，且这个长度一定 ≥ 木棍长度 $a_i$ 的最大值。</p><p>因此，我们可以把答案的可能取值都先求出来，然后从小到大依次尝试能否合成。</p><p>至于如何判断能否合成，我最早使用贪心的思路是：把合成木棍看作“填充”，刚好填满则算合成一根。每一次从最大能被填入剩余空间的木棍开始填入，如果能顺利填完当然就是可以满足条件了，直接结束，返回这个长度就是最小的；如果遇到所有剩余的木棍都无法填入就说明不行，继续尝试下一个最小长度。</p><p>但是这个贪心算法有漏洞，判断为无法填入的情况，有可能有别的解。</p><p>反例：<code>3 4 7 8 18 20</code></p><p>贪心<em>45</em>分</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> fac[<span class="number">50</span>]{<span class="number">0</span>};</span><br><span class="line"><span class="type">int</span> fac_cnt = <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> max_num = <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> bucket[<span class="number">51</span>]{<span class="number">0</span>};  <span class="comment">// 统计每个长度的个数</span></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">int</span> sum = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">is_valid</span><span class="params">(<span class="type">int</span> p)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    cout &lt;&lt; p &lt;&lt; endl;</span><br><span class="line">    <span class="type">int</span> bucket_copy[<span class="number">51</span>]{<span class="number">0</span>};</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt;= max_num; i++)</span><br><span class="line">    {</span><br><span class="line">        bucket_copy[i] = bucket[i];</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; sum / p; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="type">int</span> max_num_copy = max_num;</span><br><span class="line">        <span class="type">int</span> pp = p;</span><br><span class="line">        <span class="keyword">while</span> (pp &gt; <span class="number">0</span>)</span><br><span class="line">        {</span><br><span class="line">            <span class="keyword">if</span> (bucket_copy[max_num_copy] == <span class="number">0</span> ||</span><br><span class="line">                max_num_copy &gt; pp)  <span class="comment">// 查找最低能被减的值</span></span><br><span class="line">            {</span><br><span class="line">                <span class="keyword">do</span></span><br><span class="line">                {</span><br><span class="line">                    <span class="keyword">if</span> (max_num_copy == <span class="number">0</span>)</span><br><span class="line">                    {</span><br><span class="line">                        cout &lt;&lt; <span class="string">"FAILED\n"</span>;</span><br><span class="line">                        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">                    }</span><br><span class="line">                    max_num_copy--;</span><br><span class="line">                } <span class="keyword">while</span> (bucket_copy[max_num_copy] == <span class="number">0</span> || max_num_copy &gt; pp);</span><br><span class="line">            }</span><br><span class="line">            pp -= max_num_copy;</span><br><span class="line">            bucket_copy[max_num_copy]--;</span><br><span class="line">            cout &lt;&lt; max_num_copy &lt;&lt; <span class="string">'\n'</span>;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    cin &gt;&gt; n;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; n; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="type">int</span> ai;</span><br><span class="line">        cin &gt;&gt; ai;</span><br><span class="line">        max_num = <span class="built_in">max</span>(ai, max_num);</span><br><span class="line">        sum += ai;</span><br><span class="line">        bucket[ai]++;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 对sum求因子</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = max_num; i &lt;= sum; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">if</span> (sum % i == <span class="number">0</span>)  <span class="comment">// 整除</span></span><br><span class="line">        {</span><br><span class="line">            fac[fac_cnt++] = i;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; fac_cnt - <span class="number">1</span>; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">is_valid</span>(fac[i]))</span><br><span class="line">        {</span><br><span class="line">            cout &lt;&lt; fac[i] &lt;&lt; endl;</span><br><span class="line">            <span class="built_in">system</span>(<span class="string">"pause"</span>);</span><br><span class="line">            <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    cout &lt;&lt; sum &lt;&lt; endl;  <span class="comment">// 都不满足则是sum</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">system</span>(<span class="string">"pause"</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>于是我还是老老实实地写搜索了，搜索其实思路也不难，我这边用的是dfs。每次合成木棍，写一个循环从长到短选择合适的木棍填入，然后进入下一状态，如果所有长度的木棍都试了也不行，则返回<code>false</code>；如果所有的木棍都合成完毕才返回<code>true</code>。</p><p>难在如何对搜索进行剪枝优化。剪枝操作就是<strong>在某种状态下，已经能够确定结果是什么了，就停止“递”，马上“归”的操作</strong>。</p><p>先要明白一个结论：如果需要某个长度，比如说5，而此时你还有2、3，那么选择5可以看作是选择2、3的“上位”，因为2、3合起来完全可以替代5，而反过来就不行了。因此我们要优先选择5，后面再尝试2、3，这就是从大往小搜索的原因。</p><p>这里就写几个最关键的优化，<del>至于其他无关痛痒的优化，😂👉🤡</del>：</p><ol><li>使用桶来装木棍的长度。桶的好处在于，既能按从长到短的顺序取出木棍，又能充当<code>vis</code>数组，“记录”已经访问的长度的信息。</li><li>每次查找可用木棍的时候，从上次查找到的地方继续，不用从头开始查找。因为如果填入比上次更长的木棍可以的话，就应该优先选，这样上次不应选小的木棍。</li><li>如果在剩下的长度和当前木棍的长度一样，但发现这根填进去返回<code>false</code>，直接跳出循环，判断这个分支为<code>false</code>，因为这已经是最优的选择了，如果选择用更小的木棍来补成这个长度肯定更不行。</li><li>如果一点都没填且发现失败了，也直接返回<code>false</code>，道理和上面一样，最优的填法都不能完成，更不用说更不好的了。</li></ol><p>说实话3,4这两个优化挺难想的，没看大佬的题解基本想不出来，当时自己最优就拿了50来分。还得多向大佬学习。</p><hr><h2 id="AC代码"><a href="#AC代码" class="headerlink" title="AC代码"></a>AC代码</h2><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> fac[<span class="number">50</span>]{<span class="number">0</span>};</span><br><span class="line"><span class="type">int</span> fac_cnt = <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> max_num = <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> min_num = <span class="number">100</span>;</span><br><span class="line"><span class="type">int</span> bucket[<span class="number">51</span>]{<span class="number">0</span>};  <span class="comment">// 统计每个长度的个数</span></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">int</span> sum = <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> current_fac;</span><br><span class="line"><span class="type">int</span> filled_bucket[<span class="number">50</span>]{<span class="number">0</span>};</span><br><span class="line"><span class="type">int</span> filled_bucket_cnt = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> x, <span class="type">int</span> idx)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="comment">// l是当次剩余的长度，x是次数，idx是上次搜到的索引</span></span><br><span class="line">    <span class="keyword">if</span> (l == <span class="number">0</span>)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">if</span> (x == <span class="number">2</span>)  <span class="comment">// 剩一个一定可以拼</span></span><br><span class="line">        {</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        {</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">dfs</span>(current_fac, x - <span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (l &lt; min_num)  <span class="comment">// 剩下的比最小长度还小</span></span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = idx; i &lt; filled_bucket_cnt; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">if</span> (bucket[filled_bucket[i]] &gt; <span class="number">0</span>)</span><br><span class="line">        {</span><br><span class="line">            bucket[filled_bucket[i]]--;</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">dfs</span>(l - filled_bucket[i], x, i))</span><br><span class="line">            {</span><br><span class="line">                <span class="comment">// cout &lt;&lt; i &lt;&lt; '\n';</span></span><br><span class="line">                bucket[filled_bucket[i]]++;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (l == current_fac || l == filled_bucket[i])</span><br><span class="line">            {</span><br><span class="line">                bucket[filled_bucket[i]]++;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            }</span><br><span class="line"></span><br><span class="line">            bucket[filled_bucket[i]]++;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="keyword">return</span> a &gt; b;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    cin &gt;&gt; n;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; n; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="type">int</span> ai;</span><br><span class="line">        cin &gt;&gt; ai;</span><br><span class="line">        max_num = <span class="built_in">max</span>(ai, max_num);</span><br><span class="line">        min_num = <span class="built_in">min</span>(ai, min_num);</span><br><span class="line">        sum += ai;</span><br><span class="line">        <span class="keyword">if</span> (bucket[ai] == <span class="number">0</span>)</span><br><span class="line">        {</span><br><span class="line">            filled_bucket[filled_bucket_cnt++] = ai;</span><br><span class="line">        }</span><br><span class="line">        bucket[ai]++;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="built_in">sort</span>(filled_bucket, filled_bucket + filled_bucket_cnt, cmp);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 对sum求因子</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = max_num; i &lt;= sum; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">if</span> (sum % i == <span class="number">0</span>)  <span class="comment">// 整除</span></span><br><span class="line">        {</span><br><span class="line">            fac[fac_cnt++] = i;</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; fac_cnt - <span class="number">1</span>; i++)</span><br><span class="line">    {</span><br><span class="line">        current_fac = fac[i];</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">dfs</span>(fac[i], sum / fac[i], <span class="number">0</span>))</span><br><span class="line">        {</span><br><span class="line">            cout &lt;&lt; fac[i] &lt;&lt; endl;</span><br><span class="line">            <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    cout &lt;&lt; sum &lt;&lt; endl;  <span class="comment">// 前几个都不满足则是sum</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>]]>
      </content:encoded>
    </item>
    <item>
      <title>P1434 [SHOI2002] 滑雪</title>
      <link>https://shiquda.link/P1434/</link>
      <description>读题
P1434 [SHOI2002] 滑雪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

给定一个含有海拔高度的矩形，算出从高到低“滑雪”的最大长度。

“滑雪”只能从一个格子滑到上下左右相邻，且海拔严格小于当前海拔的格子。

例如：

1
2
3
4
5


1   2   3   4   5
16  17  18  19  6
15  24  25  20  7
14  23  22  21  8
13  12  11  10  9


这里的最大路径是：



共25格。

注意，“长度”为首尾经过总的格子的个数，比如路径$1\rightarrow 2$的长度为2</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A2%98%E8%A7%A3/">题解</category>
      <category domain="https://shiquda.link/tags/%E9%A2%98%E8%A7%A3/">题解</category>
      <pubDate>Tue, 28 May 2024 13:28:37 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="读题"><a href="#读题" class="headerlink" title="读题"></a>读题</h2><p><a href="https://www.luogu.com.cn/problem/P1434">P1434 [SHOI2002] 滑雪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)</a></p><p>给定一个含有海拔高度的矩形，算出从高到低“滑雪”的最大长度。</p><p>“滑雪”只能从一个格子滑到上下<strong>左右相邻</strong>，且海拔<strong>严格小于</strong>当前海拔的格子。</p><p>例如：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1   2   3   4   5</span><br><span class="line">16  17  18  19  6</span><br><span class="line">15  24  25  20  7</span><br><span class="line">14  23  22  21  8</span><br><span class="line">13  12  11  10  9</span><br></pre></td></tr></tbody></table></figure><p>这里的最大路径是：</p><p><img src="https://b3logfile.com/file/2024/05/solo-fetchupload-6378931297264261002-9oul5dR.png" alt="Clip_2024-05-28_21-12-10" loading="lazy"></p><p>共25格。</p><p>注意，“长度”为首尾经过总的格子的个数，比如路径$1\rightarrow 2$的长度为2。</p><p>题目给出的最大矩形长宽为100，记长为c(olumns)，宽为r(ows)</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>第一想到的就是DFS（深度有限搜索），<code>dfs(int x, int y)</code>返回从<code>[x][y]</code>出发的最大长度。搜索的逻辑比较简单，就是寻找四周临近的格子的长度的最大值，加上1就是当前格子的最大长度。</p><p>但是这道题最大长宽为100，如果一个个暴力搜索肯定会超时的，最大的时间复杂度可能是$O(r^2c^2)$。</p><p>我们可以在暴力搜索的基础上进行记忆化搜索，建立一个数组<code>rec[x][y]</code>用于存储从<code>[x][y]</code>出发的最长长度，如果后续搜索到四周的格子，需要查找<code>[x][y]</code>的长度的话，直接返回这个记录的值就好了，不必再进行递归。</p><p>这样优化以后的空间复杂度和时间复杂度均仅为$O(rc)$（因为每个格子最多只要计算一次），完全能过。</p><hr><h2 id="AC代码"><a href="#AC代码" class="headerlink" title="AC代码"></a>AC代码</h2><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> block[<span class="number">110</span>][<span class="number">110</span>]{<span class="number">0</span>};</span><br><span class="line"><span class="type">int</span> rec[<span class="number">110</span>][<span class="number">110</span>]{<span class="number">0</span>};  <span class="comment">// 记忆</span></span><br><span class="line"><span class="type">int</span> r, c;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">bool</span> <span class="title">is_valid</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span>  <span class="comment">// 在范围内</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="keyword">return</span> x &gt;= <span class="number">0</span> &amp;&amp; x &lt; r &amp;&amp; y &gt;= <span class="number">0</span> &amp;&amp; y &lt; c;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span>  <span class="comment">// 返回从x, y出发的最大的值</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="keyword">if</span> (rec[x][y] &gt;= <span class="number">0</span>) <span class="keyword">return</span> rec[x][y];</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> res = <span class="number">1</span>;</span><br><span class="line">    <span class="type">int</span> max_next = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(x - <span class="number">1</span>, y) &amp;&amp; block[x - <span class="number">1</span>][y] &lt; block[x][y])</span><br><span class="line">        max_next = <span class="built_in">max</span>(<span class="built_in">dfs</span>(x - <span class="number">1</span>, y), max_next);</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(x + <span class="number">1</span>, y) &amp;&amp; block[x + <span class="number">1</span>][y] &lt; block[x][y])</span><br><span class="line">        max_next = <span class="built_in">max</span>(<span class="built_in">dfs</span>(x + <span class="number">1</span>, y), max_next);</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(x, y - <span class="number">1</span>) &amp;&amp; block[x][y - <span class="number">1</span>] &lt; block[x][y])</span><br><span class="line">        max_next = <span class="built_in">max</span>(<span class="built_in">dfs</span>(x, y - <span class="number">1</span>), max_next);</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(x, y + <span class="number">1</span>) &amp;&amp; block[x][y + <span class="number">1</span>] &lt; block[x][y])</span><br><span class="line">        max_next = <span class="built_in">max</span>(<span class="built_in">dfs</span>(x, y + <span class="number">1</span>), max_next);</span><br><span class="line">    res += max_next;</span><br><span class="line"></span><br><span class="line">    rec[x][y] = res;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">110</span>; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt; <span class="number">110</span>; j++)</span><br><span class="line">        {</span><br><span class="line">            rec[i][j] = <span class="number">-1</span>;  <span class="comment">// 初始化，-1为无记录</span></span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    cin &gt;&gt; r &gt;&gt; c;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; r; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt; c; j++)</span><br><span class="line">        {</span><br><span class="line">            cin &gt;&gt; block[i][j];</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> ans = <span class="number">1</span>;  <span class="comment">// 至少为1</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; r; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt; c; j++)</span><br><span class="line">        {</span><br><span class="line">            ans = <span class="built_in">max</span>(ans, <span class="built_in">dfs</span>(i, j));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    cout &lt;&lt; ans &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">system</span>(<span class="string">"pause"</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>]]>
      </content:encoded>
    </item>
    <item>
      <title>P1535 [USACO08MAR] Cow Travelling S</title>
      <link>https://shiquda.link/P1535/</link>
      <description>读题
P1535 [USACO08MAR] Cow Travelling S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目大概意思是说，奶牛在一个给定大小的矩形范围内走，地块有两种：草地或者树，其中树奶牛不能走。

奶牛一次可以上下左右走，不能原地不动（但是可以绕圈！），给定两个点A,B，求出奶牛从A到B的步数为T的路径总数。

这里原题表述有些问题，不知道是不是翻译的不清楚，原文说的是“在 T 秒内”，但是实际上就看的是T秒这一秒。害得我半天没找出毛病，还是看讨论版才发现的

思路
最早想的是用BFS来搜索，直到队首元素的时间到t+1位置。但是试了一下就报MLE了</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A2%98%E8%A7%A3/">题解</category>
      <category domain="https://shiquda.link/tags/%E9%A2%98%E8%A7%A3/">题解</category>
      <pubDate>Sun, 26 May 2024 13:08:39 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="读题"><a href="#读题" class="headerlink" title="读题"></a>读题</h2><p><a href="https://www.luogu.com.cn/problem/P1535">P1535 [USACO08MAR] Cow Travelling S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)</a></p><p>题目大概意思是说，奶牛在一个给定大小的矩形范围内走，地块有两种：<strong>草地</strong>或者<strong>树</strong>，其中树奶牛不能走。</p><p>奶牛一次可以上下左右走，不能原地不动（但是可以绕圈！），给定两个点A,B，求出奶牛从A到B的步数为T的路径总数。</p><p>这里原题表述有些问题，不知道是不是翻译的不清楚，原文说的是“在 T 秒内”，但是实际上就看的是T秒这一秒。<del>害得我半天没找出毛病，还是看讨论版才发现的</del></p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>最早想的是用BFS来搜索，直到队首元素的时间到t+1位置。但是试了一下就报<code>MLE</code>了，也没想再用记忆化搜索之类的优化了。</p><p>突然想到，奶牛的在每一时刻的到某点的数字就像“切片”一样，而这种不同时间、坐标直接的推导关系是非常明显的，某一时刻的路径总数等于上一时刻的四周路径总数之和。当然如果是树的话就为0。据此可以写出dp公式：</p><p>$$<br>dp[x][y][t] =<br>\begin{cases}<br>0 &amp; \text{if } \text{block}[x][y] = 1 \<br>dp[x-1][y][t-1] + dp[x+1][y][t-1] + dp[x][y-1][t-1] + dp[x][y+1][t-1] &amp; \text{otherwise}<br>\end{cases}<br>$$</p><hr><h2 id="AC代码"><a href="#AC代码" class="headerlink" title="AC代码"></a>AC代码</h2><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n, m, t;</span><br><span class="line"><span class="type">int</span> block[<span class="number">110</span>][<span class="number">110</span>]{<span class="number">0</span>};  <span class="comment">// 0未被阻挡</span></span><br><span class="line"><span class="type">int</span> dp[<span class="number">110</span>][<span class="number">110</span>][<span class="number">16</span>]{<span class="number">0</span>};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">is_valid</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="keyword">return</span> x &gt;= <span class="number">1</span> &amp;&amp; x &lt;= n &amp;&amp; y &gt;= <span class="number">1</span> &amp;&amp; y &lt;= m &amp;&amp; !block[x][y];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; m &gt;&gt; t;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= m; j++)</span><br><span class="line">        {</span><br><span class="line">            <span class="type">char</span> c;</span><br><span class="line">            cin &gt;&gt; c;</span><br><span class="line">            block[i][j] = (c == <span class="string">'*'</span> ? <span class="number">1</span> : <span class="number">0</span>);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">    <span class="type">int</span> x1, y1, x2, y2;</span><br><span class="line">    cin &gt;&gt; x1 &gt;&gt; y1 &gt;&gt; x2 &gt;&gt; y2;</span><br><span class="line"></span><br><span class="line">    dp[x1][y1][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">1</span>; k &lt;= t; k++)</span><br><span class="line">    {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">        {</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= m; j++)</span><br><span class="line">            {</span><br><span class="line">                <span class="keyword">if</span> (<span class="built_in">is_valid</span>(i, j))</span><br><span class="line">                {</span><br><span class="line">                    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(i - <span class="number">1</span>, j)) dp[i][j][k] += dp[i - <span class="number">1</span>][j][k - <span class="number">1</span>];</span><br><span class="line">                    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(i + <span class="number">1</span>, j)) dp[i][j][k] += dp[i + <span class="number">1</span>][j][k - <span class="number">1</span>];</span><br><span class="line">                    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(i, j - <span class="number">1</span>)) dp[i][j][k] += dp[i][j - <span class="number">1</span>][k - <span class="number">1</span>];</span><br><span class="line">                    <span class="keyword">if</span> (<span class="built_in">is_valid</span>(i, j + <span class="number">1</span>)) dp[i][j][k] += dp[i][j + <span class="number">1</span>][k - <span class="number">1</span>];</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// for (int i = 1; i &lt;= n; i++)</span></span><br><span class="line">    <span class="comment">// {</span></span><br><span class="line">    <span class="comment">//     for (int j = 0; j &lt; m; j++)</span></span><br><span class="line">    <span class="comment">//     {</span></span><br><span class="line">    <span class="comment">//         cout &lt;&lt; dp[i][j][1] &lt;&lt; ' ';</span></span><br><span class="line">    <span class="comment">//     }</span></span><br><span class="line">    <span class="comment">//     cout &lt;&lt; '\n';</span></span><br><span class="line">    <span class="comment">// }</span></span><br><span class="line"></span><br><span class="line">    cout &lt;&lt; dp[x2][y2][t] &lt;&lt; endl;</span><br><span class="line">    <span class="built_in">system</span>(<span class="string">"pause"</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>]]>
      </content:encoded>
    </item>
    <item>
      <title>看到一些人开始在博客上写题解，我也准备开始。</title>
      <link>https://shiquda.link/solution-project-start/</link>
      <description>嗯，就这样
准备刷的题单是luogu上的这个，不一定按顺序刷，也不一定强制自己每天/每周要写多少吧，只是想：尝试向别人解释清楚一个问题，是一种很好的学习。

同时也能留下点什么。

嗯，就这样。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E9%A2%98%E8%A7%A3/">题解</category>
      <category domain="https://shiquda.link/tags/%E9%A2%98%E8%A7%A3/">题解</category>
      <pubDate>Sat, 25 May 2024 14:32:44 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="嗯，就这样"><a href="#嗯，就这样" class="headerlink" title="嗯，就这样"></a>嗯，就这样</h2><p>准备刷的题单是luogu上的<a href="https://www.luogu.com.cn/training/9391">这个</a>，不一定按顺序刷，也不一定强制自己每天&#x2F;每周要写多少吧，只是想：<strong>尝试向别人解释清楚一个问题，是一种很好的学习。</strong></p><p>同时也能留下点什么。</p><p>嗯，就这样。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>解决imgur图片无法加载的问题</title>
      <link>https://shiquda.link/load-imgur-images/</link>
      <description>由于Imgur在中国大陆无法访问，且许多节点的IP已被Imgur列入黑名单，因此需要寻找其他方法加载图片。博主发现了一些提供图片镜像缓存服务的网站，如noobzone.ru，可以缓存图床的直链并转发给用户，使用Header Editor浏览器插件重定向所有满足某种条件的请求的解决方案。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Fri, 19 Apr 2024 13:19:21 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="为什么我imgur的图片加载不出来？"><a href="#为什么我imgur的图片加载不出来？" class="headerlink" title="为什么我imgur的图片加载不出来？"></a>为什么我imgur的图片加载不出来？</h2><p>简单来说就是黑IP了，因为imgur在大陆是无法访问的，我们需要使用科学的方法来访问，这时候你节点的IP可能就在imgur的<strong>黑名单</strong>里面，导致没办法加载，具体表现为访问<code>i.imgur.com</code>（图片直链）返回<code>429</code>，访问<code>imgur.com</code>会返回</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"data"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">        <span class="attr">"error"</span><span class="punctuation">:</span> <span class="string">"Imgur is temporarily over capacity. Please try again later."</span></span><br><span class="line">    <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"success"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"status"</span><span class="punctuation">:</span> <span class="number">403</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><h2 id="那怎么办呢？"><a href="#那怎么办呢？" class="headerlink" title="那怎么办呢？"></a>那怎么办呢？</h2><p>其实最简单的方法就是<strong>换一个节点</strong>。</p><p>但是，我发现，换了一圈我现有的（包括self-hosted）都不能正常访问！！！</p><p>有网友说，<strong>很多数据中心的IP进了imgur的黑名单</strong>了，恰巧这时我也不想再找了，于是就想着自己折腾折腾，想一个方法。</p><h3 id="灵感-1"><a href="#灵感-1" class="headerlink" title="灵感 1"></a>灵感 1</h3><p>很多网站在大陆访问比较慢，或者是被屏蔽了，这时候有一些人会做一些公益的镜像站，比如<a href="https://huggingface.co/">Hugging Face</a>的镜像站<a href="https://hf-mirror.com/">HF-Mirror</a>。</p><p>于是我就想，有没有一个imgur的镜像站呢？</p><p>答：没找到。</p><p>但是，有一些提供<strong>图片镜像缓存服务</strong>的网站，他们能够缓存图床的直链，并转发给用户。具体的可以参考<a href="https://www.1itao.com/image-anti-leech.html">这篇</a>。</p><p>这里以<code>https://img.noobzone.ru/getimg.php?url=</code>为例，把要访问的imgur图片链接直接加在网址后面（作为参数传入）即可访问，且不需要科学的方法。</p><p>例如：<code>https://img.noobzone.ru/getimg.php?url=https://i.imgur.com/TbWS0cZ.png</code></p><h3 id="灵感-2"><a href="#灵感-2" class="headerlink" title="灵感 2"></a>灵感 2</h3><p>我想到了<a href="https://chromewebstore.google.com/detail/header-editor/eningockdidmgiojffjmkdblpjocbhgh">Header Editor (google.com)</a>，这个浏览器插件可以重定向所有满足某种条件的请求。</p><p>于是写一个正则匹配<code>i.imgur.com</code>为域名的URL，重定向至<code>https://img.noobzone.ru/getimg.php?url=</code>即可。</p><p><img src="https://b3logfile.com/file/2024/05/solo-fetchupload-15941643260665077244-hDXeQ03.png" alt="Clip_2024-05-31_18-41-59" loading="lazy"></p><p><strong>更新</strong>：在热心网友的提醒下，发现该图片缓存网站似乎开启了防盗链，我们再创建一个规则，将请求头里面的<code>referer</code>去掉就可以正常获取图片了。</p><p><img src="https://b3logfile.com/file/2024/05/solo-fetchupload-16074890948498776779-UdLGQCf.png" alt="Clip_2024-05-31_18-42-19" loading="lazy"></p><p>安装插件后，可以参考我写的填，或者直接从</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://gist.githubusercontent.com/shiquda/fde8daca5c45a829d063283ba41bcca4/raw/a7b80eeb251c5175b6e4e3d2fb6f497e9df7c0f9/header-editor-imgur-config</span><br></pre></td></tr></tbody></table></figure><p>导入。</p><p>导入后开启规则应该就能生效了。</p><h2 id="局限"><a href="#局限" class="headerlink" title="局限"></a>局限</h2><p>这里只支持在浏览器中访问，如果需要在其他软件中访问，可能需要一些其他分流软件，这里不再探讨。感兴趣的读者可以自行探索实现。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="https://www.1itao.com/image-anti-leech.html">图片防盗链最终解决方案，超级简单实用的方法 | 爱淘数字资源馆 (1itao.com)</a></li><li><a href="https://hostloc.com/thread-1180833-1-1.html">imgur办掉了所有的乌龟壳ip访问图片-美国VPS综合讨论-全球主机交流论坛 - Powered by Discuz! (hostloc.com)</a></li></ol><h2 id="感谢"><a href="#感谢" class="headerlink" title="感谢"></a>感谢</h2><p><a href="https://shiquda.link/load-imgur-images#46cbb4b336094559a6debafd50772276">“游客”</a>网友的补充解决方案。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>解决OI中使用g++编译器时出现的Segmentation fault错误</title>
      <link>https://shiquda.link/solve-segmentation-fault/</link>
      <description>
        <![CDATA[背景
我习惯于使用VScode刷一些算法题，但是很多时候在本地需要开大内存的时候（具体来说是在主函数里面），运行的时候IDE会提示Segmentation fault。

比如以下代码：

1
2
3
4
5
6
7


#include <bits/stdc++.h>
using namespace std;
int main()
{
    int blocks[1001][1001]{0};
 ...
}


这时候这个数组实际上仅仅占用了1001 * 1001 * 8B ≈7.64MB的内存，但是却出现了Segmentation fault错误。但是在OJ上面是没有问题的，能够AC。]]>
      </description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <pubDate>Wed, 10 Apr 2024 15:41:31 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>我习惯于使用VScode刷一些算法题，但是很多时候在本地需要开大内存的时候（具体来说是在主函数里面），运行的时候IDE会提示<code>Segmentation fault</code>。</p><p>比如以下代码：</p><figure class="highlight cpp"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line">    <span class="type">int</span> blocks[<span class="number">1001</span>][<span class="number">1001</span>]{<span class="number">0</span>};</span><br><span class="line"> ...</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>这时候这个数组实际上仅仅占用了1001 * 1001 * 8B ≈7.64MB的内存，但是却出现了<code>Segmentation fault</code>错误。但是在OJ上面是没有问题的，能够AC。</p><p>其实解决方法也很简单，<strong>不要定义在主函数里面，而是直接开全局变量</strong>就行了。但是<del>本着打破砂锅问到底的精神</del>，我对这个现象进行了一些探索。</p><h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><p>在C++的程序中，<strong>全局变量</strong>是存储在<strong>堆</strong>上的，而<strong>局部变量</strong>是存储在<strong>栈</strong>上的。如果在主函数里面定义， 当在主函数中定义一个大数组时，由于栈空间有限，很可能会导致栈溢出，从而出现<code>Segmentation fault</code>错误。</p><h2 id="那为什么OJ上面又可以跑呢？"><a href="#那为什么OJ上面又可以跑呢？" class="headerlink" title="那为什么OJ上面又可以跑呢？"></a>那为什么OJ上面又可以跑呢？</h2><p>其实是可以通过<strong>设置连接器的传入参数</strong>，来自定义栈分配的内存大小上限的。</p><p>以我的VSCode中配置为例，在你的项目文件夹下的<code>.vscode</code>文件夹中，应该有一个<code>tasks.json</code>文件，在里面修改配置，在<code>tasks.args</code>添加以下命令：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Wl,--stack,512000000</span><br></pre></td></tr></tbody></table></figure><p>这个命令的含义：</p><ul><li><code>-Wl</code>: 表示后面是传给连接器的命令</li><li><code>--stack,512000000</code>，设置栈的内存分配上限为<code>512000000B</code></li></ul><p>改完应该像这样：</p><figure class="highlight json"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line">    <span class="attr">"tasks"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">{</span></span><br><span class="line">            <span class="attr">"type"</span><span class="punctuation">:</span> <span class="string">"cppbuild"</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"label"</span><span class="punctuation">:</span> <span class="string">"C/C++: g++.exe 生成活动文件"</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"command"</span><span class="punctuation">:</span> <span class="string">"C:\\MinGW\\bin\\g++.exe"</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"args"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                <span class="string">"-fdiagnostics-color=always"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="string">"-g"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="string">"${file}"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="string">"-o"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="string">"${fileDirname}\\${fileBasenameNoExtension}.exe"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="string">"-Wl,--stack,512000000"</span></span><br><span class="line">            <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"options"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">                <span class="attr">"cwd"</span><span class="punctuation">:</span> <span class="string">"${fileDirname}"</span></span><br><span class="line">            <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"problemMatcher"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                <span class="string">"$gcc"</span></span><br><span class="line">            <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"group"</span><span class="punctuation">:</span> <span class="punctuation">{</span></span><br><span class="line">                <span class="attr">"kind"</span><span class="punctuation">:</span> <span class="string">"build"</span><span class="punctuation">,</span></span><br><span class="line">                <span class="attr">"isDefault"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">            <span class="punctuation">}</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">"detail"</span><span class="punctuation">:</span> <span class="string">"调试器生成的任务。"</span></span><br><span class="line">        <span class="punctuation">}</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">"version"</span><span class="punctuation">:</span> <span class="string">"2.0.0"</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></tbody></table></figure><p>这样以后，就算主函数里面开<em>大内存</em>也不会报错了。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>如何免费下载Microsoft Store商店上的付费应用</title>
      <link>https://shiquda.link/how-to-download-apps-on-ms-store-for-free/</link>
      <description>通过第三方网站下载并安装微软商店的应用。步骤：获取应用的商店链接、从第三方网站下载应用安装包、破解签名。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E7%A0%B4%E8%A7%A3/">破解</category>
      <pubDate>Sat, 23 Mar 2024 12:34:19 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="重要声明"><a href="#重要声明" class="headerlink" title="重要声明"></a>重要声明</h2><p><strong>本教程出于学习目的，提到的所有软件、网站等资源均来自互联网，和作者无任何关联，作者也不对其负任何直接的或者间接的责任。若读者通过该教程下载了资源，需要在24小时内从计算机上删除下载的资源。以此产生的纠纷和作者无关。</strong></p><h2 id="大致原理"><a href="#大致原理" class="headerlink" title="大致原理"></a>大致原理</h2><ol><li>通过一个第三方网站，下载MS商店对应软件安装包</li><li>破解Windows的签名验证</li><li>enjoy~</li></ol><h2 id="详细步骤"><a href="#详细步骤" class="headerlink" title="详细步骤"></a>详细步骤</h2><p>下面以Diarium软件为例，演示一下安装的过程。</p><h3 id="获取MS商店链接"><a href="#获取MS商店链接" class="headerlink" title="获取MS商店链接"></a>获取MS商店链接</h3><p>在<a href="https://apps.microsoft.com/search?hl=zh-cn&gl=CN">Microsoft 应用</a>中搜索链接搜索你想要的应用。<br><img src="https://b3logfile.com/file/2024/03/image-27kErq5.png" alt="image.png" loading="lazy"></p><p>找到应用并点击进入，然后复制<strong>该应用</strong>的URL</p><blockquote><p>例如，Diarium对应的链接是<a href="https://apps.microsoft.com/detail/9nblggh4vzz1?hl=zh-cn&gl=CN">https://apps.microsoft.com/detail/9nblggh4vzz1?hl=zh-cn&gl=CN</a></p></blockquote><h3 id="从第三方网站检索并下载"><a href="#从第三方网站检索并下载" class="headerlink" title="从第三方网站检索并下载"></a>从第三方网站检索并下载</h3><p>打开以下网站：</p><p><a href="https://store.rg-adguard.net/">Microsoft Store - Generation Project (v1.2.3) [by @rgadguard &amp; mkuba50] (rg-adguard.net)</a></p><p>在搜索框粘贴前面复制的链接，并点击搜索。</p><p><img src="https://b3logfile.com/file/2024/03/image-bvZkyR6.png" alt="image.png" loading="lazy"></p><p>在搜索结果中，下载前几个文件中后缀为<code>.appx</code>或者<code>.msixbundle</code>的文件，一般是大小较大的那个。</p><p>下载过程中，浏览器可能会提示下载的文件有风险，点击保留在此设备。</p><p>直接打开文件，应该会显示安装按钮，点击安装即可。</p><p>安装完毕后，可能就直接可以用了，当然<strong>如果提示你不可用</strong>，请按照下面的步骤继续。</p><h3 id="破解签名"><a href="#破解签名" class="headerlink" title="破解签名"></a>破解签名</h3><p>下载 <a href="https://github.com/Wapitiii/WSAppBak/releases/tag/v1.1">Release WSAppBak v1.1 · Wapitiii&#x2F;WSAppBak (github.com)</a></p><p>下载后解压到一个合适的目录，然后打开<code>WSAppBak.exe</code>。</p><p>前面软件已被安装，但是不是无法使用吗，使用everything等软件，可以搜索<code>diarium.exe</code>文件所在位置。</p><p>定位到diarium的目录（这个目录名称可能包括一些看上去是乱七八糟的字母和数字），复制<strong>目录</strong>链接，注意不是<del><code>.exe</code></del>。</p><p>粘贴目录链接，回车</p><p><img src="https://b3logfile.com/file/2024/03/image-okOIupB.png" alt="image.png" loading="lazy"></p><p>输出目录任意，可以写<code>./output</code>。</p><p>要求填写密码，直接选择<code>None</code>。</p><p><img src="https://b3logfile.com/file/2024/03/image-UhitXF5.png" alt="image.png" loading="lazy"></p><p>打开WSAppBak目录下的<code>output</code>文件夹，或者你自定义的文件夹。分别打开<code>.pfx</code>和<code>.cer</code>文件并安装，遇到储存位置请选择“本地计算机”。</p><p><img src="https://b3logfile.com/file/2024/03/image-uqSmO0y.png" alt="image.png" loading="lazy"></p><p>要求设置密码的时候，直接跳过；其他设置不用改，直接点确认就行了。</p><p>两个文件安装完后，点击<strong>目录下生成的</strong><code>.appx</code>文件，然后点击安装（或者是点击重新安装）。</p><p>这里我安装的时候，提示安装失败，这时候可<strong>卸载先前安装的软件，然后再安装生成的<code>.appx</code>文件，就可以正常使用了</strong>。</p><hr><h2 id="Reference-Credit"><a href="#Reference-Credit" class="headerlink" title="Reference &amp; Credit"></a>Reference &amp; Credit</h2><ol><li><a href="https://www.youtube.com/watch?v=z883dh0twIo">How to get almost any paid app in the Microsoft Store for FREE? ! (youtube.com)</a></li><li><a href="https://github.com/Wapitiii/WSAppBak">Wapitiii&#x2F;WSAppBak: APPX Backupper and Repacker (github.com)</a></li><li><a href="https://store.rg-adguard.net/">Microsoft Store - Generation Project (v1.2.3) [by @rgadguard &amp; mkuba50] (rg-adguard.net)</a></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>记录一次绕过校园网限速的探索</title>
      <link>https://shiquda.link/bypass-college-network-rate-limit/</link>
      <description>文章介绍了如何通过使用IPv6协议绕过校园网限速的方法。主要通过寻找或自建支持IPv6的节点，将所有本地流量转发到IPv6，从而实现绕过限速/免流。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Wed, 20 Mar 2024 12:04:23 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>某高校的校内校园网限制速度为30Mbps(相当于3.75M&#x2F;s)，下载游戏、模型等大文件的时候非常糟心。但是日常生活中无意中发现，极小时候访问特定资源的时候没有限制，比如使用一些应用商城下载安装包的、使用anaconda安装python包的时候，能跑到20M&#x2F;s左右，这样已经完全够用了。</p><p>最近无意中看到了有人研究使用<a href="http://www.dogfight360.com/blog/">Dogfight360 – 羽翼城个人博客</a> 大佬的<a href="https://www.dogfight360.com/blog/18273/">下载CDN重定向IPV6工具包(Steam&#x2F;EPIC&#x2F;BattleNet&#x2F;UbiConnect&#x2F;XboxPC) – Dogfight360</a>软件，重定向Steam下载请求至支持IPv6的CDN，并且获得满速下载的方法。经过实验后确实可行。</p><p>于是有了一个想法：既然IPv6都没有限速，那么有没有方法能够把任意流量使用IPv6发出，从而规避限制呢？</p><blockquote><p>经过了解，一些高校对ipv6的流量不收费，也可以尝试一些这种方法。但是如果你的校园网不支持ipv6或者也限速，那么这种方法也就没有意义了。<br>测试是否支持ipv6：</p><ul><li><a href="http://v6t.ipip.net/">IPv6 test (ipip.net)</a></li><li>或者在命令行输入：<code>ping 2001:4860:4860::8888</code>，看看能否ping通。</li></ul></blockquote><h2 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h2><p>使用ipv6的<strong>节点</strong>，将所有本地流量转发到ipv6，从而达到绕过限速的方法。<del>（就是科学上网的那个）</del></p><h2 id="具体方法"><a href="#具体方法" class="headerlink" title="具体方法"></a>具体方法</h2><h3 id="直接寻找支持ip为IPv6协议的节点"><a href="#直接寻找支持ip为IPv6协议的节点" class="headerlink" title="直接寻找支持ip为IPv6协议的节点"></a>直接寻找支持ip为IPv6协议的节点</h3><p>记得之前见到过一些机场有这种节点，感兴趣的可以自行寻找一下。<del>也可能是我记错了</del></p><h3 id="自建节点"><a href="#自建节点" class="headerlink" title="自建节点"></a>自建节点</h3><p>你最好有一台闲置的VPS。注意要支持IPv6。<br>参考：</p><ul><li><a href="https://www.jixing.one/vps/v2ray-xui-v2rayn/">实现校园网IPv6免流量上网与科学上网 | V2ray教程：X-ui与v2rayN ~ 极星网 (jixing.one)</a></li></ul><p>随后导出订阅到V2rayN中使用即可。</p><p>如果你日常使用Clash，可以使用以下网站进行vmess到Clash配置文件的转换。</p><p><a href="https://v1.v2rayse.com/v2ray-clash/">v2ray转clash节点 - v2rayse.com</a></p><p><strong>记得在Clash设置中开启IPv6选项。</strong></p><hr><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="https://www.jixing.one/vps/v2ray-xui-v2rayn/">实现校园网IPv6免流量上网与科学上网 | V2ray教程：X-ui与v2rayN ~ 极星网 (jixing.one)</a></li><li><a href="https://zhuanlan.zhihu.com/p/659452359">对于Ipv6网络绕过校园网限额的尝试 - 知乎 (zhihu.com)</a></li><li><a href="https://mp.weixin.qq.com/s/oJHQ8cGpmwO4TUTTqgLEJQ">最高18MB&#x2F;s！如何打破TJ-WIFI限速3.6MB&#x2F;s的魔咒？ (qq.com)</a></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>conda 常用命令</title>
      <link>https://shiquda.link/articles/2024/02/26/1708943642988.html</link>
      <description>
        <![CDATA[以下所有命令都以在Windows上的为例。

进入conda环境
1


activate


退出
1


deactivate


创建环境
1


conda create -n <env>


如果使用python，需要用

1


conda create -n <env> python


进入指定环境
1


conda avtivate <env>


列出当前环境的包
1


conda list


安装指定的包
1


conda install <package>


可以指定版本。

1


conda install <package>=<version>


查看]]>
      </description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/%E5%AD%A6%E4%B9%A0/">学习</category>
      <category domain="https://shiquda.link/tags/Python/">Python</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <pubDate>Mon, 26 Feb 2024 10:34:03 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>以下所有命令都以在<strong>Windows</strong>上的为例。</p><h2 id="进入conda环境"><a href="#进入conda环境" class="headerlink" title="进入conda环境"></a>进入conda环境</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">activate</span><br></pre></td></tr></tbody></table></figure><h2 id="退出"><a href="#退出" class="headerlink" title="退出"></a>退出</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">deactivate</span><br></pre></td></tr></tbody></table></figure><h2 id="创建环境"><a href="#创建环境" class="headerlink" title="创建环境"></a>创建环境</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda create -n &lt;env&gt;</span><br></pre></td></tr></tbody></table></figure><p>如果使用<strong>python</strong>，需要用</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda create -n &lt;env&gt; python</span><br></pre></td></tr></tbody></table></figure><h2 id="进入指定环境"><a href="#进入指定环境" class="headerlink" title="进入指定环境"></a>进入指定环境</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda avtivate &lt;env&gt;</span><br></pre></td></tr></tbody></table></figure><h2 id="列出当前环境的包"><a href="#列出当前环境的包" class="headerlink" title="列出当前环境的包"></a>列出当前环境的包</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda list</span><br></pre></td></tr></tbody></table></figure><h2 id="安装指定的包"><a href="#安装指定的包" class="headerlink" title="安装指定的包"></a>安装指定的包</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install &lt;package&gt;</span><br></pre></td></tr></tbody></table></figure><p>可以指定版本。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda install &lt;package&gt;=&lt;version&gt;</span><br></pre></td></tr></tbody></table></figure><h2 id="查看可用版本"><a href="#查看可用版本" class="headerlink" title="查看可用版本"></a>查看可用版本</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda search numpy</span><br></pre></td></tr></tbody></table></figure><h2 id="卸载包"><a href="#卸载包" class="headerlink" title="卸载包"></a>卸载包</h2><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda uninstall &lt;package&gt;</span><br></pre></td></tr></tbody></table></figure><h2 id="删除虚拟环境"><a href="#删除虚拟环境" class="headerlink" title="删除虚拟环境"></a>删除虚拟环境</h2><p>注意，需要<strong>先退出虚拟环境</strong>，再删除。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda remove -n &lt;env&gt; --all</span><br></pre></td></tr></tbody></table></figure>]]>
      </content:encoded>
    </item>
    <item>
      <title>如何寻找电子书？</title>
      <link>https://shiquda.link/articles/2024/02/19/1708320689703.html</link>
      <description>除了通过支付一些费用，在“某宝”上搜索和购买电子书以外，其实可以利用书名、ISBN和ssid等关键信息，在一些渠道进行精确搜索。</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Mon, 19 Feb 2024 05:31:29 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="最简单的方法……"><a href="#最简单的方法……" class="headerlink" title="最简单的方法……"></a>最简单的方法……</h2><p><strong>某宝搜索：</strong></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PDF代找</span><br></pre></td></tr></tbody></table></figure><p>很多东西，其实花时间去找并不合算，花钱代找的话<strong>方便快捷</strong>，其实价格也不贵。<br>一般来说，这里面的商家渠道都差不多，如果有一两个都找不到某本书，基本上就不行了，还是去买实体书吧。<br><del>如果你不死心，不怕浪费时间的话，也可以试一试我下面的方法。</del><br>对于不愿意花钱的人，一定要看看下面的方法，只要不是很冷门的书，一般都能找到。</p><h2 id="查找依据"><a href="#查找依据" class="headerlink" title="查找依据"></a>查找依据</h2><p>查找书本其实有很多依据，而不是仅仅通过书名来盲目的找。</p><h3 id="书本名称"><a href="#书本名称" class="headerlink" title="书本名称"></a>书本名称</h3><p>一般来说这应该是查找电子书的出发点。<del>书都不知道叫什么就先搞清楚叫啥再说吧</del></p><p>值得注意的是，你<strong>并不需要搞清楚书的精确名称</strong>。当然，如果能使用精确名称搜索肯定比模糊搜索更佳。</p><p>例如：你想要查找 <em>C++ Primer Plus</em> 这本书，可以先在<a href="https://www.douban.com/search?cat=1001&amp;q=">豆瓣搜索</a>上查找，<strong>确定你想要的版本</strong>，从而获取其精确名称。</p><p><img src="https://b3logfile.com/file/2024/02/image-5bJLgsM.png" alt="image.png" loading="lazy"></p><h3 id="ISBN"><a href="#ISBN" class="headerlink" title="ISBN"></a>ISBN</h3><p>在前面的步骤中，书籍详情页还可以获取到书的<strong>ISBN</strong>。</p><p><img src="https://b3logfile.com/file/2024/02/image-ABzOUcv.png" alt="image.png" loading="lazy"></p><p><strong>ISBN</strong>是指<strong>国际标准书号</strong>，你可以理解为一本书独一无二的“<strong>身份证号</strong>”，通过它，你可以精确锁定一本书的某个版本。这在我们后续的搜索里面非常有用。</p><h3 id="ssid"><a href="#ssid" class="headerlink" title="ssid"></a>ssid</h3><p>也有可能叫做 $SS$ 码，是一个8位数的id。<br>这个是查阅某些库所用的id。<br>查找ssid方式：</p><ol><li><a href="https://findbooks.eu.org/">找书网_图书信息搜索平台！ (findbooks.eu.org)</a></li><li><a href="https://tampermonkey.getpdfnow.com/">猴哥互助 (getpdfnow.com)</a></li></ol><p>其中第二个方法里面的ssid在“编号”位置</p><p><img src="https://b3logfile.com/file/2024/02/image-7utu2Wr.png" alt="image.png" loading="lazy"></p><h2 id="查找渠道"><a href="#查找渠道" class="headerlink" title="查找渠道"></a>查找渠道</h2><p>下面罗列了我自己收集的一些好用的搜索渠道</p><div class="md-table-scroll"><table><thead><tr><th align="left">渠道</th><th align="left">名称搜索</th><th align="left">ISBN搜索</th><th>ssid搜索</th><th>备注</th></tr></thead><tbody><tr><td align="left"><a href="https://z-library.se/">Z-Library – the world’s largest e-book library. Your gateway to knowledge and culture.</a></td><td align="left">✔</td><td align="left">✔</td><td>❌</td><td>大名鼎鼎的zlib，尤其是外文电子书资源相当全面。如果请挂了可以自行寻找官方链接</td></tr><tr><td align="left"><a href="https://search.zhelper.net/">zhelper Search Page 搜索界面 🔍</a></td><td align="left">✔</td><td align="left">✔</td><td>❌</td><td>需要配合接口使用，可以参考<a href="https://tool.ssdown.org/">这个</a>。涵盖zlib的资源，有的接口还包括别的资源。</td></tr><tr><td align="left"><a href="https://www.findbooks.info/">My Book House (findbooks.info)</a></td><td align="left">✔</td><td align="left">✔</td><td>❌</td><td>下载可能需要使用科学的方式</td></tr><tr><td align="left"><a href="https://www.book123.info/">无名图书 | 一个好看的电子书网站 (book123.info)</a></td><td align="left">✔</td><td align="left">✔</td><td>❌</td><td>简单好用</td></tr><tr><td align="left"><a href="https://freembook.com/">FreeMbook Search</a></td><td align="left">✔</td><td align="left">✔</td><td>✔</td><td>好用，但是上面多是百度网盘秒传，由于接口改版可能失效。</td></tr><tr><td align="left"><a href="https://www.jiumodiary.com/">Jiumo Search 鸠摩搜索 - 文档搜索引擎 (jiumodiary.com)</a></td><td align="left">✔</td><td align="left">✔</td><td>❌</td><td>不少人推荐，但是个人感觉资源较少</td></tr><tr><td align="left"><a href="%5B%5D(https://t.me/+dLqK79lm0G40ZWQ1)%5Bhttps://t.me/+dLqK79lm0G40ZWQ1%5D(https://t.me/+dLqK79lm0G40ZWQ1)">https://t.me/+dLqK79lm0G40ZWQ1</a></td><td align="left">❌</td><td align="left">❌</td><td>✔</td><td>魔法</td></tr><tr><td align="left"><a href="https://t.me/duxiubook">https://t.me/duxiubook</a></td><td align="left">✔</td><td align="left">❌</td><td>✔</td><td>魔法</td></tr></tbody></table></div><h2 id="辅助工具"><a href="#辅助工具" class="headerlink" title="辅助工具"></a>辅助工具</h2><p>先推荐一个万能的网站，可以下载秒传，还能根据ssid<strong>查找并添加书签</strong>（有的PDF格式的书可能没有详细的书签）。</p><p><a href="https://pdg2pdf.com/">PDG to PDF 一站式工具 (pdg2pdf.com)</a></p><p>以及一个<strong>格式转换</strong>网站，如果你下载到的资源格式不是你想要的，可以通过下面的网站转换。</p><p><a href="https://convertio.co/zh/">Convertio — 文件转换器</a></p><hr><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ol><li><a href="https://ssdown.org/archives/1700482250661">超星 TG 频道/机器人汇总 - 易书计划 (ssdown.org)</a></li><li><a href="https://ssdown.org/archives/1694769328287">【持续更新】Zlibrary/Superlib 访问方式与资讯汇总 - 易书计划 (ssdown.org)</a></li><li><a href="https://www.readfree.net/bbs/thread-5902150-1-1.html">DX书籍秒链查询网站-网上读书园地 - Powered by Discuz! (readfree.net)</a></li><li><a href="https://blog.yibook.org/post/zhelper/">使用 Zhelper Search 搜索与下载书籍/ zhelper search 接口汇总 · YiBook Project 易书计划</a></li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>如何为网站或者服务添加HTTPS</title>
      <link>https://shiquda.link/articles/2024/01/31/1706670820508.html</link>
      <description>如何为网站或者服务添加HTTPS</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/Linux/">Linux</category>
      <pubDate>Wed, 31 Jan 2024 03:13:40 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><img src="https://b3logfile.com/bing/20230201.jpg?imageView2/1/w/960/h/540/interlace/1/q/100" loading="lazy"></p><h2 id="前置要求"><a href="#前置要求" class="headerlink" title="前置要求"></a>前置要求</h2><ul><li>一台服务器</li><li>安装nginx</li><li>拥有一个域名</li></ul><h2 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h2><h3 id="域名设置"><a href="#域名设置" class="headerlink" title="域名设置"></a>域名设置</h3><p>一般来说，要配置HTTPS，需要拥有一个域名。我现在这个域名是2023年在<a href="http://www.dynadot.com/?s6m836E8ED7l6L7H">dynadot</a>免费领的一年，不知道还有没有这个福利。如果你需要购买一个域名可以试一下<a href="http://www.dynadot.com/?s6m836E8ED7l6L7H">dynadot</a>的服务，也可以尝试使用一些免费的域名（一般是二级域名，且体验没那么好）。</p><p>在你的域名服务提供商，找到<strong>DNS设置</strong>。<br>如果主域名已经被占用，可以使用二级域名设置。这里以<strong>二级域名</strong>为例，一级域名同理。</p><p>在二级域名（子域名）设置中添加记录，选择 <strong>A</strong> ，目标指向你的服务器的<strong>公网IP</strong>。</p><p><img src="https://b3logfile.com/file/2024/01/Clip_2024-01-31_10-53-05-SuFAiHE.png" alt="Clip20240131105305.png" loading="lazy"></p><p>保存后可能需要<strong>几分钟</strong>的时间来传播。</p><h3 id="Nginx-配置"><a href="#Nginx-配置" class="headerlink" title="Nginx 配置"></a>Nginx 配置</h3><p>若没安装，以Ubuntu系统为例，可通过以下命令安装：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install nginx</span><br></pre></td></tr></tbody></table></figure><p>可以用以下命令验证是否安装了Nginx。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nginx -v</span><br></pre></td></tr></tbody></table></figure><p>应该会得到类似的版本号信息。</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nginx version: nginx/1.22.0 (Ubuntu)</span><br></pre></td></tr></tbody></table></figure><p>在 <code>/etc/nginx/sites-available/</code> 目录下，新建一个文件（名字随意，最好和网站或者服务相关）</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> nano /etc/nginx/sites-available/&lt;name&gt;</span><br></pre></td></tr></tbody></table></figure><p>填写以下内容（<code>&lt;&gt;</code>中的具体内容需要修改）</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">server {</span><br><span class="line">    listen 80;</span><br><span class="line">    server_name &lt;域名&gt;;</span><br><span class="line"></span><br><span class="line">    location / {</span><br><span class="line">        proxy_pass http://localhost:&lt;网站或者服务的端口&gt;;</span><br><span class="line">        proxy_set_header Host <span class="variable">$host</span>;</span><br><span class="line">        proxy_set_header X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        proxy_set_header X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>保存后，使用以下命令进行链接：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">ln</span> -s /etc/nginx/sites-available/&lt;name&gt; /etc/nginx/sites-enabled/</span><br></pre></td></tr></tbody></table></figure><h3 id="配置-Certbot"><a href="#配置-Certbot" class="headerlink" title="配置 Certbot"></a>配置 Certbot</h3><p>安装</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install certbot python3-certbot-nginx</span><br></pre></td></tr></tbody></table></figure><p>请求颁发免费证书</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> certbot --nginx -d &lt;你的域名&gt;</span><br></pre></td></tr></tbody></table></figure><p>成功后会显示：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Deploying certificate</span><br><span class="line">Successfully deployed certificate for openai.api.shiquda.link to /etc/nginx/sites-enabled/xxx</span><br><span class="line">Congratulations! You have successfully enabled HTTPS on xxx</span><br></pre></td></tr></tbody></table></figure><p>请求成功后，<del>如果一切正常</del>，当证书快到期的时候，会自动更新。</p><p>为了保险起见，可以试一下模拟更新证书（不会真正更新）</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> certbot renew --dry-run</span><br></pre></td></tr></tbody></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>现在，应该访问对应的域名，就能实现使用HTTPS了。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>免费使用gpt-4的一种方法</title>
      <link>https://shiquda.link/articles/2024/01/08/1704715752038.html</link>
      <description>利用Github Copiliot来免费使用gpt-4模型</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/Linux/">Linux</category>
      <category domain="https://shiquda.link/tags/%E5%AD%A6%E4%B9%A0/">学习</category>
      <category domain="https://shiquda.link/tags/AI/">AI</category>
      <pubDate>Mon, 08 Jan 2024 12:09:12 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><em>概括：利用Github Copiliot来免费使用gpt-4模型</em></p><div class="tag-plugin colorful note"><div class="body"><p><strong>注意</strong>：本方法已经有多个被封禁GitHub Copilot的案例，不再建议尝试。</p></div></div><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><p>你需要的：</p><h3 id="Github-Copilot"><a href="#Github-Copilot" class="headerlink" title="Github Copilot"></a>Github Copilot</h3><p>如果你是大学生，可以享有GitHub的教育福利，认证后就可以使用Github Copilot。若不是又不想花那么多钱向官方买，可以自行搜索如何白嫖/低价使用。</p><h3 id="服务器（可选）"><a href="#服务器（可选）" class="headerlink" title="服务器（可选）"></a>服务器（可选）</h3><p><a href="https://github.com/aaamoon/copilot-gpt4-service">aaamoon/copilot-gpt4-service: Convert Github Copilot to ChatGPT, free to use the GPT-4 model</a><br>这个项目通过利用copilot调用gpt模型，从而进行免费调用gpt-4。</p><p>该repo作者有部署一个公益服务，但是用的人太多，可能因为ip原因导致GitHub封禁你的copilot，如果能够自建服务会更安全。</p><h2 id="获取Copilot-Token"><a href="#获取Copilot-Token" class="headerlink" title="获取Copilot Token"></a>获取Copilot Token</h2><p><a href="https://github.com/aaamoon/copilot-gpt4-service">aaamoon/copilot-gpt4-service: Convert Github Copilot to ChatGPT, free to use the GPT-4 model</a></p><p>项目里有介绍几种获取Copilot Token的方法，嫌麻烦可以直接进入下面的网站获取，但是由于不是自建，有一定风险。<br><a href="https://cocopilot.org/copilot/token">Get Copilot Token (cocopilot.org)</a></p><p>如果不自建<a href="https://github.com/aaamoon/copilot-gpt4-service">copilot-gpt4-service</a>和<a href="https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web">ChatGPT-Next-Web</a>，可以直接在repo作者的<a href="https://gpt4copilot.tech/#/chat">NextChat (gpt4copilot.tech)</a>上使用，其中目标网址填</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://gpt4copilot.tech/</span><br></pre></td></tr></tbody></table></figure><p>apikey<strong>直接写前面获得的Copilot Token</strong><br><del>好像已经失效了，只能自建了</del></p><h2 id="搭建copilot-gpt4-service"><a href="#搭建copilot-gpt4-service" class="headerlink" title="搭建copilot-gpt4-service"></a>搭建copilot-gpt4-service</h2><p>使用docker构建</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line">  --name copilot-gpt4-service \</span><br><span class="line">  --restart always \</span><br><span class="line">  -p 8080:8080 \</span><br><span class="line">  aaamoon/copilot-gpt4-service:latest</span><br></pre></td></tr></tbody></table></figure><p>如果需要指定端口，把冒号前面的8080改为想要的就可以了，后面不需要改。<br>完成这一步，已经可以使用支持http的客户端来调用了，比如<a href="https://chatboxai.app/zh">Chatbox官网 - 办公学习的AI好助手，官方免费下载 (chatboxai.app)</a></p><h2 id="搭建ChatGPT-Next-web"><a href="#搭建ChatGPT-Next-web" class="headerlink" title="搭建ChatGPT-Next-web"></a>搭建ChatGPT-Next-web</h2><p>拉取</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull yidadaa/chatgpt-next-web</span><br></pre></td></tr></tbody></table></figure><p>如果与copilot-gpt4-service部署在一个服务器上面，<code>BASE_URL</code>参数可以指定为<code>http://copilot-gpt4-service:8080/</code></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 3000:3000 \</span><br><span class="line">   -e CODE=&lt;改为你的密码&gt; \</span><br><span class="line">-e BASE_URL=http://copilot-gpt4-service:8080/ \</span><br><span class="line">-e OPENAI_API_KEY=&lt;改为你的Copilot_Token&gt; \</span><br><span class="line">   yidadaa/chatgpt-next-web</span><br></pre></td></tr></tbody></table></figure><p>查看容器信息</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps</span><br></pre></td></tr></tbody></table></figure><p>然后将两个容器添加到一个网络里面</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建一个新的网络</span></span><br><span class="line">docker network create my_network</span><br><span class="line"><span class="comment"># 将容器添加到这个网络</span></span><br><span class="line">docker network connect my_network copilot-gpt4-service  </span><br><span class="line">docker network connect my_network &lt;改成next的bid&gt;</span><br></pre></td></tr></tbody></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>访问<code>&lt;ip&gt;:3000</code>即可使用。第一次登录要输入密码才能使用设置的密钥，然后在使用模型那边改为gpt-4就可以了。</p><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><p><a href="https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web">ChatGPTNextWeb/ChatGPT-Next-Web: A cross-platform ChatGPT/Gemini UI (Web / PWA / Linux / Win / MacOS). 一键拥有你自己的跨平台 ChatGPT/Gemini 应用。 (github.com)</a><br><a href="https://github.com/aaamoon/copilot-gpt4-service">aaamoon/copilot-gpt4-service: Convert Github Copilot to ChatGPT, free to use the GPT-4 model</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>国内服务器部署Stable Video Diffusion教程</title>
      <link>https://shiquda.link/articles/2023/12/05/1701780603849.html</link>
      <description>Reference:

How to run Stable Video Diffusion img2vid - Stable Diffusion Art (stable-diffusion-art.com)

https://video-stable-diffusion.com/install-svd-on-linux/

使用的是 SVD XT模型

SVD – trained to generate 14 frames at resolution 576×1024.

SVD XT – trained to generate 25 frames at resolution 576×1024</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/Linux/">Linux</category>
      <category domain="https://shiquda.link/tags/%E5%AD%A6%E4%B9%A0/">学习</category>
      <category domain="https://shiquda.link/tags/Python/">Python</category>
      <pubDate>Tue, 05 Dec 2023 12:50:03 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><img src="https://b3logfile.com/bing/20201218.jpg?imageView2/1/w/960/h/540/interlace/1/q/100" loading="lazy"></p><p>Reference:</p><p><a href="https://stable-diffusion-art.com/stable-video-diffusion-img2vid/">How to run Stable Video Diffusion img2vid - Stable Diffusion Art (stable-diffusion-art.com)</a></p><p><a href="https://video-stable-diffusion.com/install-svd-on-linux/">https://video-stable-diffusion.com/install-svd-on-linux/</a></p><p>使用的是 SVD XT模型</p><blockquote><p><a href="https://huggingface.co/stabilityai/stable-video-diffusion-img2vid/blob/main/svd.safetensors">SVD</a> – trained to generate 14 frames at resolution 576×1024.</p><p><a href="https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt/blob/main/svd_xt.safetensors">SVD XT</a> – trained to generate <strong>25 frames</strong> at resolution <strong>576×1024</strong>.</p></blockquote><p>本教程在Ubuntu 22.04.3 x86_64上奏效。</p><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><p>创建文件夹，把自己的项目隔离开</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> ./xxx</span><br></pre></td></tr></tbody></table></figure><p>进入刚刚创建的文件夹</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> xxx</span><br></pre></td></tr></tbody></table></figure><h2 id="克隆"><a href="#克隆" class="headerlink" title="克隆"></a>克隆</h2><p>拉取远程仓库</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/Stability-AI/generative-models</span><br><span class="line"><span class="built_in">cd</span> generative-models</span><br></pre></td></tr></tbody></table></figure><h2 id="下载模型"><a href="#下载模型" class="headerlink" title="下载模型"></a>下载模型</h2><p>（由于<a href="http://huggingface.co/">huggingface.co</a>被屏蔽，这里使用镜像）</p><p><a href="https://huggingface.co/stabilityai/stable-video-diffusion-img2vid/tree/main">stabilityai/stable-video-diffusion-img2vid at main (huggingface.co)</a></p><p><a href="https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt/tree/main">stabilityai/stable-video-diffusion-img2vid-xt at main (huggingface.co)</a></p><p>此处先下载 <code>svd.safetensors</code> 模型</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> checkpoints</span><br><span class="line"><span class="built_in">cd</span> checkpoints</span><br><span class="line">wget https://hf-mirror.com/stabilityai/stable-video-diffusion-img2vid/resolve/main/svd.safetensors</span><br></pre></td></tr></tbody></table></figure><p>下载完后返回到项目根目录</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ..</span><br></pre></td></tr></tbody></table></figure><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><h3 id="conda-与-Python"><a href="#conda-与-Python" class="headerlink" title="conda 与 Python"></a>conda 与 Python</h3><p>先安装anaconda（若已安装可以跳过）</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh</span><br><span class="line">bash Anaconda3-2023.09-0-Linux-x86_64.sh</span><br></pre></td></tr></tbody></table></figure><p>注意安装的时候要先统一协议，填yes，然后继续</p><p>安装完成可以删掉安装脚本</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> Anaconda3-2023.09-0-Linux-x86_64.sh</span><br></pre></td></tr></tbody></table></figure><p>检查是否安装成功</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda --v</span><br></pre></td></tr></tbody></table></figure><p>应该会显示版本号。</p><p>没成功的话，可以手动配置环境变量。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">". ~/anaconda3/etc/profile.d/conda.sh"</span> &gt;&gt; ~/.bashrc</span><br><span class="line"><span class="built_in">source</span> ~/.bashrc</span><br></pre></td></tr></tbody></table></figure><p>使用带有 Python 3.10 的 conda 创建 Python 环境</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda create --name svd python=3.10 -y</span><br></pre></td></tr></tbody></table></figure><h3 id="项目依赖"><a href="#项目依赖" class="headerlink" title="项目依赖"></a>项目依赖</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda activate svd</span><br></pre></td></tr></tbody></table></figure><p>此时应该会进入虚拟环境。</p><p>可以设置使用国内镜像源</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip config <span class="built_in">set</span> global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/</span><br><span class="line">pip config <span class="built_in">set</span> install.trusted-host pypi.tuna.tsinghua.edu.cn</span><br></pre></td></tr></tbody></table></figure><p>在项目根目录输入命令安装依赖：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip3 install -r requirements/pt2.txt</span><br><span class="line">pip3 install .</span><br></pre></td></tr></tbody></table></figure><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>先设置环境变量，否则会报错</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">'export PYTHONPATH=/generative-models:$PYTHONPATH'</span> &gt;&gt; ~/.bashrc</span><br><span class="line"><span class="built_in">source</span> ~/.bashrc</span><br></pre></td></tr></tbody></table></figure><p><del>（如果）由于被屏蔽了，要手动下载文件，</del><strong>不用输下面的代码</strong></p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># [已废弃] 若手动下载文件：</span></span><br><span class="line"><span class="comment"># git clone https://hf-mirror.com/laion/CLIP-ViT-H-14-laion2B-s32B-b79K ~/.cache/huggingface/hub/CLIP-ViT-H-14-laion2B-s32B-b79K</span></span><br><span class="line"><span class="comment"># wget https://openaipublic.azureedge.net/clip/models/b8cca3fd41ae0c99ba7e8951adf17d267cdb84cd88be6f7c2e0eca1737a03836/ViT-L-14.pt -P ~/.cache/clip/</span></span><br></pre></td></tr></tbody></table></figure><p>或者试一下以下的代码，设置替换镜像站。首次运行的时候加一下参数就好了，后面不需要</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HF_ENDPOINT=https://hf-mirror.com streamlit run scripts/demo/video_sampling.py  --server.address  0.0.0.0  --server.port 4801</span><br></pre></td></tr></tbody></table></figure><p>修改 <code>-server.port</code> 参数可以设置访问的端口。</p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>访问 <code>http://&lt;ip&gt;:4801</code></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>关于查找资源</title>
      <link>https://shiquda.link/articles/2023/11/29/1701227248383.html</link>
      <description>
        <![CDATA[首先明确自己为什么要找资源，从而明确要找什么样的资源，然后再分析如何去找。

为什么要搜索？
知道(Know)
搜索：陕西信达罢赛

NBL 5罚1掷

什么是NBL？和CBA什么区别和联系？5罚1掷什么意思？

学习(Learn)
例如ChatGPT的使用技巧

创作(Create)
做亿个项目

完成工作(Do)
去除PDF的水印

搜索资源的类别？
 * 信息资讯
 * 知识技能
 * 素材文件
 * 工具软件

和目的的联系
思考的角度
可以按照所要查找资源的类型思考：

 * 所需的知识最可能附着在哪类载体上？
   
    * 网页->谷歌/知乎/搜狗搜公众号文章/垂类社群（比如]]>
      </description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/%E8%B5%84%E6%BA%90/">资源</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC/">油猴脚本</category>
      <category domain="https://shiquda.link/tags/%E5%AD%A6%E4%B9%A0/">学习</category>
      <category domain="https://shiquda.link/tags/%E8%B5%84%E6%BA%90/">资源</category>
      <pubDate>Wed, 29 Nov 2023 03:07:28 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>首先明确自己<strong>为什么</strong>要找资源，从而明确要找<strong>什么样</strong>的资源，然后再分析如何去找。</p><h2 id="为什么要搜索？"><a href="#为什么要搜索？" class="headerlink" title="为什么要搜索？"></a>为什么要搜索？</h2><h3 id="知道-Know"><a href="#知道-Know" class="headerlink" title="知道(Know)"></a>知道(Know)</h3><blockquote><p>搜索：陕西信达罢赛</p><p>NBL   5罚1掷</p><p>什么是NBL？和CBA什么区别和联系？5罚1掷什么意思？</p></blockquote><h3 id="学习-Learn"><a href="#学习-Learn" class="headerlink" title="学习(Learn)"></a>学习(Learn)</h3><blockquote><p>例如ChatGPT的使用技巧</p></blockquote><h3 id="创作-Create"><a href="#创作-Create" class="headerlink" title="创作(Create)"></a>创作(Create)</h3><blockquote><p>做亿个项目</p></blockquote><h3 id="完成工作-Do"><a href="#完成工作-Do" class="headerlink" title="完成工作(Do)"></a>完成工作(Do)</h3><blockquote><p>去除PDF的水印</p></blockquote><h2 id="搜索资源的类别？"><a href="#搜索资源的类别？" class="headerlink" title="搜索资源的类别？"></a>搜索资源的类别？</h2><ul><li>信息资讯</li><li>知识技能</li><li>素材文件</li><li>工具软件</li></ul><h3 id="和目的的联系"><a href="#和目的的联系" class="headerlink" title="和目的的联系"></a>和目的的联系</h3><h4 id="思考的角度"><a href="#思考的角度" class="headerlink" title="思考的角度"></a>思考的角度</h4><p>可以按照所要查找资源的类型思考：</p><ul><li><p>所需的知识最可能附着在<strong>哪类载体</strong>上？</p><ul><li>网页-&gt;<strong>谷歌</strong>&#x2F;<strong>知乎</strong>&#x2F;<strong>搜狗搜公众号文章</strong>&#x2F;垂类社群（比如<a href="https://pkmer.cn/">PKMer</a>）&#x2F;聚合网址（比如<a href="https://hao.shejidaren.com/">设计导航 - 精选最好的设计网站大全</a>）<ul><li>获取社群或者聚合网址的方法：搜 <code>xxx必逛的网站</code>&#x2F;<code>websites xxx should visit</code></li></ul></li><li>PDF文档<ul><li>-&gt;谷歌<code>xxx filetype:pdf</code>&#x2F;<code>inurl:baogao/xxx</code>，可以进一步利用<a href="https://www.similarsites.com/">Similarsites.com - Easily Explore alternative websites</a></li></ul></li><li>学术论文<ul><li>国内<ul><li>知网</li><li>万方维普</li></ul></li><li>国际<ul><li>谷歌学术 <a href="https://scholar.google.com/">https://scholar.google.com/</a></li><li>Sci-Hub <a href="https://sci-hub.se/">Sci-Hub: 将知识带给每个人</a></li><li>web of cience <a href="https://webofscience.clarivate.cn/wos/woscc/basic-search">Web of Science</a></li></ul></li></ul></li><li>电子书<ul><li>中文<ul><li><a href="https://www.jiumodiary.com/">鸠摩搜书</a></li><li><a href="https://zlibrary-africa.se/">zlib</a></li><li><a href="https://www.book123.info/">无名图书 | 一个好看的电子书网站 (book123.info)</a> 个人推荐，上面可直接下载</li><li>微信读书<ul><li>直接搜索</li><li>全文搜索</li></ul></li></ul></li><li>英文<ul><li><a href="https://zlibrary-africa.se/">zlib</a></li><li>manybooks</li><li>pdfbooksword</li></ul></li></ul></li><li>视频教程<ul><li>B站</li><li>Youtube</li><li>网易云课堂</li><li><a href="https://zh.khanacademy.org/">可汗学院</a></li><li>……</li></ul></li><li>……</li></ul></li></ul><h3 id="素材文件"><a href="#素材文件" class="headerlink" title="素材文件"></a>素材文件</h3><h4 id="视频素材"><a href="#视频素材" class="headerlink" title="视频素材"></a>视频素材</h4><ul><li><a href="https://www.pexels.com/zh-cn/">免费素材图片</a></li><li><a href="https://pixabay.com/">4.2 million+ Stunning Free Images to Use Anywhere - Pixabay - Pixabay</a></li><li><a href="https://www.videvo.net/">Free Stock Video Footage HD 4K Download Royalty-Free Clips</a></li><li><a href="https://mixkit.co/">Mixkit - Awesome free assets for your next video project</a>从YouTube下载的便捷方法：在YouTube前面加入9x</li></ul><div class="tag-plugin colorful note" color="green"><div class="title"><strong><p>title:示例</p></strong></div><div class="body"><p><a href="https://www.9xyoutube.com/watch?v=HfACrKJ_Y2w">https://www.9xyoutube.com/watch?v=HfACrKJ_Y2w</a></p></div></div><ul><li><a href="https://save.tube/">SaveTube - Best Online Video Downloader ( 4K, 8K, FHD, 1080p, HDR )</a></li></ul><p>高清素材搜索：YouTube 搜索“4K” + 主题，然后可以进一步筛选分辨率，或者找到一些4k频道</p><h4 id="音频素材"><a href="#音频素材" class="headerlink" title="音频素材"></a>音频素材</h4><ul><li><a href="https://pixabay.com/">4.2 million+ Stunning Free Images to Use Anywhere - Pixabay - Pixabay</a></li></ul><h4 id="图片素材"><a href="#图片素材" class="headerlink" title="图片素材"></a>图片素材</h4><ul><li>谷歌搜索<code>imagesize:</code></li><li><a href="https://www.pexels.com/zh-cn/">免费素材图片</a></li></ul><h4 id="图标素材"><a href="#图标素材" class="headerlink" title="图标素材"></a>图标素材</h4><ul><li><a href="https://www.iconfont.cn/">iconfont-阿里巴巴矢量图标库</a></li></ul><h3 id="工具软件"><a href="#工具软件" class="headerlink" title="工具软件"></a>工具软件</h3><ul><li><a href="https://www.ghxi.com/">果核剥壳 - 互联网的净土 (ghxi.com)</a></li><li><a href="https://www.appinn.com/">小众软件 - 分享免费、小巧、实用、有趣、绿色的软件 (appinn.com)</a></li><li>一些tg频道（是否存在风险请<a href="https://www.virustotal.com/gui/home/upload">自行判断</a>）</li></ul><h3 id="通用途径"><a href="#通用途径" class="headerlink" title="通用途径"></a>通用途径</h3><ul><li>网盘搜索引擎</li><li>谷歌搜<code>Best site xxx</code></li><li>知乎&#x2F;B站</li></ul><h3 id="通用工具"><a href="#通用工具" class="headerlink" title="通用工具"></a>通用工具</h3><ul><li><a href="http://shiquda.link/articles/2023/11/29/1701226195433.html">谷歌高级搜索</a><ul><li>可用助手脚本（手搓）</li></ul></li><li><a href="https://greasyfork.org/zh-CN/scripts/27752-searchenginejump-%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E5%BF%AB%E6%8D%B7%E8%B7%B3%E8%BD%AC">搜索引擎跳转</a>脚本</li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>Google 高级搜索技巧+简易油猴脚本</title>
      <link>https://shiquda.link/articles/2023/11/29/1701226195433.html</link>
      <description>直达简单入门的UI：
Google 高级搜索

谷歌搜索引擎高级搜索、命令大全表格总结(完整示例说明) - EvanLi的博客

搜索思路
解决思路
 * 取词
 * 优化
 * 反推
 * 转化转换

语法
常用语法：

搜索操作符功能示例&quot; &quot;搜索包含特定单词或短语的结果。“steve jobs”OR搜索与 X 或 Y 相关的结果。jobs OR gates``与OR 功能相同。AND搜索与 X 和 Y 相关的结果。jobs AND gates-搜索不包含特定单词或短语的结果。jobs -apple*通配符，匹配任何单词或短语。steve * apple( )分组多个搜索条件。(ipad</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%B2%B9%E7%8C%B4%E8%84%9A%E6%9C%AC/">油猴脚本</category>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <pubDate>Wed, 29 Nov 2023 02:49:55 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>直达简单入门的UI：<br><a href="https://www.google.com/advanced_search">Google 高级搜索</a></p><p><a href="https://evanli.github.io/blog/2019/01/26/advanced-google-search-engine-command/">谷歌搜索引擎高级搜索、命令大全表格总结(完整示例说明) - EvanLi的博客</a></p><h2 id="搜索思路"><a href="#搜索思路" class="headerlink" title="搜索思路"></a>搜索思路</h2><h3 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h3><ul><li>取词</li><li>优化</li><li>反推</li><li>转化转换</li></ul><h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><p>常用语法：</p><div class="md-table-scroll"><table><thead><tr><th>搜索操作符</th><th>功能</th><th>示例</th></tr></thead><tbody><tr><td><code>" "</code></td><td>搜索包含特定单词或短语的结果。</td><td><a href="https://www.google.com/search?q=%22steve+jobs%22">“steve jobs”</a></td></tr><tr><td><code>OR</code></td><td>搜索与 X 或 Y 相关的结果。</td><td><a href="https://www.google.com/search?&amp;q=jobs+OR+gates">jobs OR gates</a></td></tr><tr><td>`</td><td>`</td><td>与<code>OR</code> 功能相同。</td></tr><tr><td><code>AND</code></td><td>搜索与 X 和 Y 相关的结果。</td><td><a href="https://www.google.com/search?&amp;q=jobs+AND+gates">jobs AND gates</a></td></tr><tr><td><code>-</code></td><td>搜索不包含特定单词或短语的结果。</td><td><a href="https://www.google.com/search?q=jobs+-apple">jobs -apple</a></td></tr><tr><td><code>*</code></td><td>通配符，匹配任何单词或短语。</td><td><a href="https://www.google.com/search?q=%22steve+*+apple%22">steve * apple</a></td></tr><tr><td><code>( )</code></td><td>分组多个搜索条件。</td><td><a href="https://www.google.com/search?q=(ipad+OR+iphone)+apple">(ipad OR iphone) apple</a></td></tr><tr><td><code>define:</code></td><td>搜索词语或短语的定义。</td><td><a href="https://www.google.com/search?q=define:entrepreneur">define:entrepreneur</a></td></tr><tr><td><code>cache:</code></td><td>查找网页的最新缓存。</td><td><a href="https://webcache.googleusercontent.com/search?q=cache:apple.com">cache:apple.com</a></td></tr><tr><td><code>filetype:</code></td><td>搜索特定类型的文件（如 PDF）。</td><td><a href="https://www.google.com/search?q=apple+filetype:pdf">apple filetype:pdf</a></td></tr><tr><td><code>ext:</code></td><td>与<code>filetype:</code> 功能相同。</td><td><a href="https://www.google.com/search?q=apple+ext:pdf">apple ext:pdf</a></td></tr><tr><td><code>site:</code></td><td>搜索特定网站的结果。</td><td><a href="https://www.google.com/search?q=site:apple.com">site:apple.com</a></td></tr><tr><td><code>related:</code></td><td>搜索与给定域相关的网站。</td><td><a href="https://www.google.com/search?q=related:apple.com">related:apple.com</a></td></tr><tr><td><code>intitle:</code></td><td>搜索标题标签中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=intitle:apple">intitle:apple</a></td></tr><tr><td><code>allintitle:</code></td><td>搜索标题标签中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allintitle:apple+iphone">allintitle:apple iphone</a></td></tr><tr><td><code>inurl:</code></td><td>搜索 URL 中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=inurl:apple">inurl:apple</a></td></tr><tr><td><code>allinurl:</code></td><td>搜索 URL 中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allinurl:apple+iphone">allinurl:apple iphone</a></td></tr><tr><td><code>intext:</code></td><td>搜索内容中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=intext:apple">intext:apple iphone</a></td></tr><tr><td><code>allintext:</code></td><td>搜索内容中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allintext:apple+iphone">allintext:apple iphone</a></td></tr><tr><td><code>weather:</code></td><td>搜索特定位置的天气。</td><td><a href="https://www.google.com/search?q=weather:san+francisco">weather:san francisco</a></td></tr><tr><td><code>stocks:</code></td><td>搜索股票信息。</td><td><a href="https://www.google.com/search?q=stocks:aapl">stocks:aapl</a></td></tr><tr><td><code>map:</code></td><td>强制谷歌显示地图结果。</td><td><a href="https://www.google.com/search?q=map:silicon+valley">map:silicon valley</a></td></tr><tr><td><code>movie:</code></td><td>搜索关于电影的信息。</td><td><a href="https://www.google.com/search?q=movie:steve+jobs">movie:steve jobs</a></td></tr><tr><td><code>in</code></td><td>将一个单位转换为另一个单位。</td><td><a href="https://www.google.com/search?q=$329+in+GBP">$329 in GBP</a></td></tr><tr><td><code>source:</code></td><td>从 Google News 中搜索特定来源的结果。</td><td><a href="https://www.google.com/search?q=apple+source:the_verge&amp;tbm=nws">apple source:the_verge</a></td></tr><tr><td><code>before:</code></td><td>搜索特定日期之前的结果。</td><td><a href="https://www.google.com/search?q=apple+before:2007-06-29">apple before:2007-06-29</a></td></tr><tr><td><code>after:</code></td><td>搜索特定日期之后的结果。</td><td><a href="https://www.google.com/search?q=apple+after:2007-06-29">apple after:2007-06-29</a></td></tr></tbody></table></div><p><strong>注：</strong></p><ul><li>冒号为英文冒号</li><li>冒号前没有空格</li><li>命令前要用空格隔开，如 <code>C++ filetype:pdf</code> ，filetype前面有空格</li></ul><h2 id="油猴脚本"><a href="#油猴脚本" class="headerlink" title="油猴脚本"></a>油猴脚本</h2><p>为了方便，我还搓了个简单的脚本：<br><a href="https://greasyfork.org/zh-CN/scripts/474178-advanced-search-assistant-for-google">Advanced Search Assistant for Google</a></p><h1 id="以下为原始数据"><a href="#以下为原始数据" class="headerlink" title="以下为原始数据"></a>以下为原始数据</h1><div class="md-table-scroll"><table><thead><tr><th>序号</th><th>语法</th><th>语法说明</th><th>示例</th><th>示例说明</th></tr></thead><tbody><tr><td>1</td><td><strong><code>+</code></strong></td><td>同AND，搜索包含多个关键词的结果</td><td>搜索<code>+</code> 引擎</td><td>搜索包含【搜索】和【引擎】两个词的页面</td></tr><tr><td>2</td><td><strong><code>OR</code></strong></td><td>或者</td><td>搜索<code>OR</code> 引擎</td><td>搜索包含【搜索】或【引擎】两个词的页面</td></tr><tr><td>3</td><td><strong><code>-</code></strong></td><td>减号，不包含减号后面词的页面</td><td>搜索引擎<code>-</code>百度</td><td>搜索不包括【百度】的【搜索引擎】的页面</td></tr><tr><td>4</td><td><strong><code>“”</code></strong></td><td>双引号，精确匹配</td><td>“搜索引擎”</td><td>精确匹配【搜索引擎】这个关键词的页面</td></tr><tr><td>5</td><td><strong><code>*</code></strong></td><td>星号，通配符，模糊搜索，星号代替某个字</td><td>搜<code>*</code>引擎</td><td>星号可以替代任何字</td></tr><tr><td>6</td><td><strong><code>@</code></strong></td><td>在用于搜索社交媒体的字词前加上<code>@</code></td><td>trump<code>@</code>twitter</td><td>搜索trump的twitter</td></tr><tr><td>7</td><td><strong><code>$</code></strong></td><td>在数字前加上<code>$</code>搜索特定价格</td><td>camera<code>$</code>400</td><td>搜索价格为400$的camera</td></tr><tr><td>8</td><td><strong><code>#</code></strong></td><td>搜索<code>#</code>标签</td><td><code>#</code>throwbackthursday</td><td>搜索标签throwbackthursday</td></tr><tr><td>9</td><td><strong><code>..</code></strong></td><td>两个点，在两个数字之间加上<code>..</code>执行数字范围搜索</td><td>camera 500<code>..</code>1000</td><td>搜索500到1000之间的camera</td></tr><tr><td>10</td><td><strong><code>filetype</code></strong></td><td>搜索某一种文件类型的资源</td><td>C++<code>filetype</code>:<code>pdf</code></td><td>搜索类型为pdf的C++网页资源</td></tr><tr><td>11</td><td><strong><code>site</code></strong></td><td>在指定站点搜索</td><td>C++<code>site</code>:<code>https://www.zhihu.com</code></td><td>在知乎中搜索和C++相关的网页</td></tr><tr><td>12</td><td><strong><code>cache</code></strong></td><td>查看网站的Google缓存版本，显示缓存页面</td><td><code>cache</code>:weibo.com</td><td>查看微博的谷歌快照</td></tr><tr><td>13</td><td><strong><code>info</code></strong></td><td>在网址前加<code>info:</code>，获取网站详情</td><td><code>info:</code>github.com</td><td>搜索github网站详情</td></tr><tr><td>14</td><td><strong><code>related</code></strong></td><td>搜索与某个网站有关联的页面</td><td><code>related:</code>sina.com</td><td>搜索与新浪网站内容相似的其他网站</td></tr><tr><td>15</td><td><strong><code>link</code></strong></td><td>返回所有链接到某个URL地址的网页</td><td><code>link:</code><a href="http://www.csdn.net/">www.csdn.net</a></td><td>搜索所有含指向【<a href="http://www.csdn.net】链接的网页/">www.csdn.net】链接的网页</a></td></tr><tr><td>16</td><td><strong><code>inurl</code></strong></td><td>搜索查询词出现在URL中的页面</td><td><code>inurl:</code>搜索引擎</td><td>搜索链接URL中有【搜索引擎】的网页</td></tr><tr><td>17</td><td><strong><code>intitle</code></strong></td><td>搜索查询词出现在页面标题中的页面，支持中英文</td><td><code>intitle:</code>搜索引擎</td><td>搜索页面标题中有【搜索引擎】的网页</td></tr><tr><td>18</td><td><strong><code>intext</code></strong></td><td>搜索查询词出现在页面正文中的页面，支持中英文</td><td><code>intext:</code>SEO <code>intext:</code>搜索引擎</td><td>在正文包含【搜索引擎】的网页中搜索【SEO】</td></tr><tr><td>19</td><td><strong><code>inanchor</code></strong></td><td>搜索链接锚文字中包含搜索词的页面</td><td><code>inanchor:</code>前端</td><td>搜索链接锚文字中包含【前端】的页面</td></tr><tr><td>20</td><td><strong><code>allinurl</code></strong></td><td>页面URL中包含多个关键词的页面</td><td><code>allinurl:</code>SEO 搜索引擎优化</td><td>相当于：<code>inurl:</code>SEO <code>inurl:</code>搜索引擎优化</td></tr><tr><td>21</td><td><strong><code>allintitle</code></strong></td><td>页面标题中包含多个关键词的页面</td><td><code>allintitle:</code>SEO 搜索引擎优化</td><td>相当于：<code>intitle:</code>SEO <code>intitle:</code>搜索引擎优化</td></tr><tr><td>22</td><td><strong><code>allintext</code></strong></td><td>页面正文中包含多个关键词的页面</td><td><code>allintext:</code>SEO 搜索引擎优化</td><td>相当于：<code>intext:</code>SEO <code>intext:</code>搜索引擎优化</td></tr><tr><td>23</td><td><strong><code>allinanchor</code></strong></td><td>页面链接锚文字包含多个关键词的页面</td><td><code>allinanchor:</code>SEO 搜索引擎优化</td><td>相当于：<code>inanchor:</code>SEO <code>inanchor:</code>搜索引擎优化</td></tr><tr><td>24</td><td><strong><code>weather</code></strong></td><td><code>weather/time/sunrise/sundown</code>+城市名，返回城市的天气/时间/日出时间/日落时间</td><td><code>weather:</code>beijing</td><td>显示北京的天气</td></tr><tr><td>25</td><td><strong><code>music</code></strong></td><td>或者用<code>songs</code>，歌手名字+<code>music/songs</code></td><td>周杰伦<code>music</code></td><td>返回周杰伦的各首歌曲</td></tr><tr><td>26</td><td><code>imagesize</code></td><td>限定图片尺寸—(在谷歌图片上搜索)</td><td><code>imagesize:2560x1440</code></td><td></td></tr></tbody></table></div><h3 id="有效搜索操作符"><a href="#有效搜索操作符" class="headerlink" title="有效搜索操作符"></a>有效搜索操作符</h3><div class="md-table-scroll"><table><thead><tr><th>搜索操作符</th><th>功能</th><th>示例</th></tr></thead><tbody><tr><td><code>" "</code></td><td>搜索包含特定单词或短语的结果。</td><td><a href="https://www.google.com/search?q=%22steve+jobs%22">“steve jobs”</a></td></tr><tr><td><code>OR</code></td><td>搜索与 X 或 Y 相关的结果。</td><td><a href="https://www.google.com/search?&amp;q=jobs+OR+gates">jobs OR gates</a></td></tr><tr><td>`</td><td>`</td><td>与<code>OR</code> 功能相同。</td></tr><tr><td><code>AND</code></td><td>搜索与 X 和 Y 相关的结果。</td><td><a href="https://www.google.com/search?&amp;q=jobs+AND+gates">jobs AND gates</a></td></tr><tr><td><code>-</code></td><td>搜索不包含特定单词或短语的结果。</td><td><a href="https://www.google.com/search?q=jobs+-apple">jobs -apple</a></td></tr><tr><td><code>*</code></td><td>通配符，匹配任何单词或短语。</td><td><a href="https://www.google.com/search?q=%22steve+*+apple%22">steve * apple</a></td></tr><tr><td><code>( )</code></td><td>分组多个搜索条件。</td><td><a href="https://www.google.com/search?q=(ipad+OR+iphone)+apple">(ipad OR iphone) apple</a></td></tr><tr><td><code>define:</code></td><td>搜索词语或短语的定义。</td><td><a href="https://www.google.com/search?q=define:entrepreneur">define:entrepreneur</a></td></tr><tr><td><code>cache:</code></td><td>查找网页的最新缓存。</td><td><a href="https://webcache.googleusercontent.com/search?q=cache:apple.com">cache:apple.com</a></td></tr><tr><td><code>filetype:</code></td><td>搜索特定类型的文件（如 PDF）。</td><td><a href="https://www.google.com/search?q=apple+filetype:pdf">apple filetype:pdf</a></td></tr><tr><td><code>ext:</code></td><td>与<code>filetype:</code> 功能相同。</td><td><a href="https://www.google.com/search?q=apple+ext:pdf">apple ext:pdf</a></td></tr><tr><td><code>site:</code></td><td>搜索特定网站的结果。</td><td><a href="https://www.google.com/search?q=site:apple.com">site:apple.com</a></td></tr><tr><td><code>related:</code></td><td>搜索与给定域相关的网站。</td><td><a href="https://www.google.com/search?q=related:apple.com">related:apple.com</a></td></tr><tr><td><code>intitle:</code></td><td>搜索标题标签中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=intitle:apple">intitle:apple</a></td></tr><tr><td><code>allintitle:</code></td><td>搜索标题标签中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allintitle:apple+iphone">allintitle:apple iphone</a></td></tr><tr><td><code>inurl:</code></td><td>搜索 URL 中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=inurl:apple">inurl:apple</a></td></tr><tr><td><code>allinurl:</code></td><td>搜索 URL 中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allinurl:apple+iphone">allinurl:apple iphone</a></td></tr><tr><td><code>intext:</code></td><td>搜索内容中包含特定单词的页面。</td><td><a href="https://www.google.com/search?q=intext:apple">intext:apple iphone</a></td></tr><tr><td><code>allintext:</code></td><td>搜索内容中包含多个单词的页面。</td><td><a href="https://www.google.com/search?q=allintext:apple+iphone">allintext:apple iphone</a></td></tr><tr><td><code>weather:</code></td><td>搜索特定位置的天气。</td><td><a href="https://www.google.com/search?q=weather:san+francisco">weather:san francisco</a></td></tr><tr><td><code>stocks:</code></td><td>搜索股票信息。</td><td><a href="https://www.google.com/search?q=stocks:aapl">stocks:aapl</a></td></tr><tr><td><code>map:</code></td><td>强制谷歌显示地图结果。</td><td><a href="https://www.google.com/search?q=map:silicon+valley">map:silicon valley</a></td></tr><tr><td><code>movie:</code></td><td>搜索关于电影的信息。</td><td><a href="https://www.google.com/search?q=movie:steve+jobs">movie:steve jobs</a></td></tr><tr><td><code>in</code></td><td>将一个单位转换为另一个单位。</td><td><a href="https://www.google.com/search?q=$329+in+GBP">$329 in GBP</a></td></tr><tr><td><code>source:</code></td><td>从 Google News 中搜索特定来源的结果。</td><td><a href="https://www.google.com/search?q=apple+source:the_verge&amp;tbm=nws">apple source:the_verge</a></td></tr><tr><td><code>before:</code></td><td>搜索特定日期之前的结果。</td><td><a href="https://www.google.com/search?q=apple+before:2007-06-29">apple before:2007-06-29</a></td></tr><tr><td><code>after:</code></td><td>搜索特定日期之后的结果。</td><td><a href="https://www.google.com/search?q=apple+after:2007-06-29">apple after:2007-06-29</a></td></tr></tbody></table></div><h3 id="不稳定的搜索操作符"><a href="#不稳定的搜索操作符" class="headerlink" title="不稳定的搜索操作符"></a>不稳定的搜索操作符</h3><div class="md-table-scroll"><table><thead><tr><th>搜索操作符</th><th>功能</th><th>示例</th></tr></thead><tbody><tr><td><code>#..#</code></td><td>在一系列数字范围内搜索。</td><td><a href="https://www.google.com/search?q=iphone+case+$50..$60">iphone case $50..$60</a></td></tr><tr><td><code>inanchor:</code></td><td>搜索包含特定锚文本的后向链接的页面。</td><td><a href="https://www.google.com/search?q=inanchor:apple">inanchor:apple</a></td></tr><tr><td><code>allinanchor:</code></td><td>搜索包含多个词语的锚文本的后向链接的页面。</td><td><a href="https://www.google.com/search?q=allinanchor:apple+iphone">allinanchor:apple iphone</a></td></tr><tr><td><code>AROUND(X)</code></td><td>搜索在 X 个词之间出现的两个词或短语的页面。</td><td><a href="https://www.google.com/search?q=apple+AROUND(4)">apple AROUND(4) iphone</a></td></tr><tr><td><code>loc:</code></td><td>查找特定地区的结果。</td><td>loc:”san francisco” apple</td></tr><tr><td><code>location:</code></td><td>在 Google News 中查找特定位置的新闻。</td><td><a href="https://www.google.com/search?q=loc:%22san+francisco%22+apple">location:”san francisco” apple</a></td></tr><tr><td><code>daterange:</code></td><td>搜索特定日期范围的结果。</td><td><a href="https://www.google.com/search?q=steve+jobs+daterange:11278-13278">daterange:11278-13278</a></td></tr></tbody></table></div><h3 id="不再有效的搜索操作符（弃用）"><a href="#不再有效的搜索操作符（弃用）" class="headerlink" title="不再有效的搜索操作符（弃用）"></a>不再有效的搜索操作符（弃用）</h3><p>以下搜索操作符不再有效，已被 Google 放弃：</p><div class="md-table-scroll"><table><thead><tr><th>搜索操作符</th><th>功能</th><th>示例</th></tr></thead><tbody><tr><td><code>#..#</code></td><td>在一系列数字范围内搜索。</td><td><a href="https://www.google.com/search?q=iphone+case+$50..$60">iphone case $50..$60</a></td></tr><tr><td><code>inanchor:</code></td><td>搜索包含特定锚文本的后向链接的页面。</td><td><a href="https://www.google.com/search?q=inanchor:apple">inanchor:apple</a></td></tr><tr><td><code>allinanchor:</code></td><td>搜索包含多个词语的锚文本的后向链接的页面。</td><td><a href="https://www.google.com/search?q=allinanchor:apple+iphone">allinanchor:apple iphone</a></td></tr><tr><td><code>AROUND(X)</code></td><td>搜索在 X 个词之间出现的两个词或短语的页面。</td><td><a href="https://www.google.com/search?q=apple+AROUND(4)">apple AROUND(4) iphone</a></td></tr><tr><td><code>loc:</code></td><td>查找特定地区的结果。</td><td>loc:”san francisco” apple</td></tr><tr><td><code>location:</code></td><td>在 Google News 中查找特定位置的新闻。</td><td><a href="https://www.google.com/search?q=loc:%22san+francisco%22+apple">location:”san francisco” apple</a></td></tr><tr><td><code>daterange:</code></td><td>搜索特定日期范围的结果。</td><td><a href="https://www.google.com/search?q=steve+jobs+daterange:11278-13278">daterange:11278-13278</a></td></tr></tbody></table></div>]]>
      </content:encoded>
    </item>
    <item>
      <title>Linux 常用端口</title>
      <link>https://shiquda.link/articles/2023/11/29/1701225706548.html</link>
      <description>Source
Some of the mentioned ports include:

 * 1080: SOCK Proxy
 * 2049: Network File System (NFS)
 * 2181: Apache ZooKeeper
 * 2375: Docker REST API (HTTP)
 * 2376: Docker REST API (HTTPS)
 * 3000: Development Framework Port (used by Ruby on Rails, Node frameworks, etc.)
 * 3306: MySQL
 * 3478: ST</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/%E7%AC%94%E8%AE%B0/">笔记</category>
      <category domain="https://shiquda.link/tags/Linux/">Linux</category>
      <category domain="https://shiquda.link/tags/%E8%BD%AC%E8%BD%BD/">转载</category>
      <pubDate>Wed, 29 Nov 2023 02:41:46 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><a href="https://matt-rickard.com/de-facto-ports">Source</a><br>Some of the mentioned ports include:</p><ul><li>1080: SOCK Proxy</li><li>2049: Network File System (NFS)</li><li>2181: Apache ZooKeeper</li><li>2375: Docker REST API (HTTP)</li><li>2376: Docker REST API (HTTPS)</li><li>3000: Development Framework Port (used by Ruby on Rails, Node frameworks, etc.)</li><li>3306: MySQL</li><li>3478: STUN, TURN (NAT Traversal)</li><li>4000: Phoenix, Jekyll</li><li>4001: etcd</li><li>4200: AngularJS</li><li>4567: Sinatra</li><li>5000: Other Development Framework Port (used by Flask, ASP.NET Core, etc.)</li><li>5222: XMPP (Extensible Messaging and Presence Protocol)</li><li>5349: STUN, TURN over TLS</li><li>5353: Multicast DNS</li><li>5432: PostgreSQL</li><li>5900: VNC (using a remote frame buffer, RFB)</li><li>6000: X11 (over the network)</li><li>6379: Redis</li><li>6660: IRC (Internet Relay Chat)</li><li>6881: BitTorrent</li><li>8000: Python Development Framework Port (used by Django, Python 3’s http.server, etc.)</li><li>8080: HTTP web server port</li><li>8333: Bitcoin</li><li>8888: Jupyter Notebook</li><li>8983: Apache Solr</li><li>9000: Used by various applications</li><li>25565: Minecraft</li><li>27017: MongoDB</li><li>51820: WireGuard</li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>改版后Steam令牌导出教程</title>
      <link>https://shiquda.link/articles/2023/11/29/1701219538802.html</link>
      <description>前情提要
现在导出steam令牌数据是真的麻烦
https://keylol.com/t900854-1-1
(出处: 其乐 Keylol)

论坛之前一些大佬已经发过了许多方式的教程，比如

[ROOT ANDROID] STEAM 3.0 导出令牌的思路
https://keylol.com/t854675-1-1
(出处: 其乐 Keylol)

【Android】从3.0以上版本的steam app中获取令牌文件经验小结
https://keylol.com/t901003-1-1
(出处: 其乐 Keylol)

本文就安卓模拟器+frida python调试的令牌导出提供一个比较详</description>
      <author>shiquda</author>
      <category domain="https://shiquda.link/categories/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="https://shiquda.link/tags/Python/">Python</category>
      <category domain="https://shiquda.link/tags/Steam/">Steam</category>
      <category domain="https://shiquda.link/tags/adb/">adb</category>
      <pubDate>Wed, 29 Nov 2023 00:58:59 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="前情提要"><a href="#前情提要" class="headerlink" title="前情提要"></a>前情提要</h2><p>现在导出steam令牌数据是真的麻烦<br><a href="https://keylol.com/t900854-1-1">https://keylol.com/t900854-1-1</a><br>(出处: 其乐 Keylol)</p><p>论坛之前一些大佬已经发过了许多方式的教程，比如</p><p>[ROOT ANDROID] STEAM 3.0 导出令牌的思路<br><a href="https://keylol.com/t854675-1-1">https://keylol.com/t854675-1-1</a><br>(出处: 其乐 Keylol)</p><p>【Android】从3.0以上版本的steam app中获取令牌文件经验小结<br><a href="https://keylol.com/t901003-1-1">https://keylol.com/t901003-1-1</a><br>(出处: 其乐 Keylol)</p><p>本文就安卓模拟器+frida  python调试的令牌导出提供一个比较详细的教程</p><p>优点：不需要一台root的手机只需要电脑即可实现导出，且相比一些别的方法相对安全。<br>缺点：繁琐，且要将令牌转移到模拟器上，<strong>吃2天cd</strong>。</p><h2 id="准备知识"><a href="#准备知识" class="headerlink" title="准备知识"></a>准备知识</h2><p>本教程使用<strong>安卓模拟器</strong> + <strong>adb frida 调试</strong> + <strong>python脚本</strong>导出令牌数据。</p><p><strong>操作前须知：</strong></p><ol><li>转移提取后令牌将存在于模拟器上，<strong>原有的手机上的令牌将失效，</strong>不能使用官方客户端扫码登录、确认交易等功能</li><li>转移后有<strong>两天左右的市场CD</strong></li></ol><p>需要的<strong>工具</strong>：</p><ol><li>python 以及frida库</li><li>adb调试工具</li><li>安卓模拟器（教程使用雷电模拟器）</li><li>frida-server</li></ol><h2 id="工具安装"><a href="#工具安装" class="headerlink" title="工具安装"></a>工具安装</h2><h3 id="安卓模拟器"><a href="#安卓模拟器" class="headerlink" title="安卓模拟器"></a>安卓模拟器</h3><p>模拟器安装后请自行下载并安装steam客户端备用。</p><p>安装steam客户端只需将下载的apk文件拖入即可。</p><h3 id="python安装及配置"><a href="#python安装及配置" class="headerlink" title="python安装及配置"></a>python安装及配置</h3><p><strong>如果已经安装过并配置了环境变量，可以跳转到安装frida依赖部分。</strong></p><p>安装frida依赖：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install frida frida-tools</span><br></pre></td></tr></tbody></table></figure><h2 id="adb调试工具安装"><a href="#adb调试工具安装" class="headerlink" title="adb调试工具安装"></a>adb调试工具安装</h2><p>本教程使用一键安装脚本进行安装，<a href="https://github.com/fawazahmed0/Latest-adb-fastboot-installer-for-windows/releases/tag/v1.7">GitHub</a></p><p>安装时如果提示要安装.NET，点击安装即可。<br>等待安装结束，打开命令提示符，输入以下代码</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb --version</span><br></pre></td></tr></tbody></table></figure><p>如果出现类似输出，则说明已经安装完成。</p><figure class="highlight text"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Android Debug Bridge version 1.0.41</span><br><span class="line">Version 34.0.4-10411341</span><br><span class="line">Installed as C:\Program Files\platform-tools\adb.exe</span><br><span class="line">Running on Windows 10.0.19045</span><br></pre></td></tr></tbody></table></figure><h2 id="开始调试"><a href="#开始调试" class="headerlink" title="开始调试"></a>开始调试</h2><p>安卓模拟器打开设置，打开root权限</p><p>打开后记得按提示重启模拟器</p><p>重启后打开模拟器里内置的设置应用程序，找到关于平板电脑&gt;版本号，连续点击7次打开开发者模式</p><p>返回，进入”系统”，展开“高级”，进入开发者选项，找到并开启USB调试</p><p>打开后在命令提示符里输入以下代码：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb devices</span><br></pre></td></tr></tbody></table></figure><p>如果出现类似输出，说明可以正常检查到模拟器</p><p>以使用雷电模拟器为例，在命令提示符输入以下代码：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb connect 127.0.0.1:5555</span><br></pre></td></tr></tbody></table></figure><div class="tag-plugin colorful note" color="blue"><div class="title"><strong><p>title:一些其他模拟器的连接端口:</p></strong></div><div class="body"><ul><li>夜神模拟器：<code>adb connect 127.0.0.1:62001</code></li><li>逍遥安卓模拟器：<code>adb connect 127.0.0.1:21503</code></li><li>天天模拟器：<code>adb connect 127.0.0.1:6555</code></li><li>海马玩模拟器：<code>adb connect 127.0.0.1:53001</code></li><li>网易MUMU模拟器：<code>adb connect 127.0.0.1:7555</code></li></ul></div></div><p>命令提示符输入:</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb root</span><br></pre></td></tr></tbody></table></figure><p>现在来到你下载并解压（如果在<a href="https://github.com/frida/frida/releases">GitHub</a>上下载的是压缩包）frida-server-16.1.3-android-x86_64后的文件目录</p><div class="tag-plugin colorful note" color="yellow"><div class="title"><strong><p>title:架构注意</p></strong></div><div class="body"><p>雷电模拟器使用的是 x86_64 架构，别的模拟器不一定是，要依据架构选择所需的 frida-server，可在 GitHub 上下载。</p></div></div><p>在导航栏输入cmd回车，在该目录打开命令提示符，分别输入回车以下三行代码</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb push frida-server-16.1.3-android-x86_64 /data/local/tmp/</span><br></pre></td></tr></tbody></table></figure><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell <span class="string">"chmod 755 /data/local/tmp/frida-server-16.1.3-android-x86_64"</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell <span class="string">"/data/local/tmp/frida-server-16.1.3-android-x86_64 &amp;"</span></span><br></pre></td></tr></tbody></table></figure><p>输入后，打开新的命令提示符窗口，输入</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">frida-ps -U</span><br></pre></td></tr></tbody></table></figure><p>如果出现类似输出，说明连接成功。<br><img src="https://b3logfile.com/file/2023/11/image-LtRnNCx.png" alt="image.png" loading="lazy"></p><p>打开steam移动端应用，登录要提取令牌的账号，然后点底部导航栏中间添加令牌，点击恢复令牌（如果你是已有令牌）<br>接受短信验证码，如果出现让你记录恢复码，那么说明令牌就转移到模拟器里了。<br>接着运行steamguard.py文件</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">import json</span><br><span class="line">import frida</span><br><span class="line">import sys</span><br><span class="line"></span><br><span class="line">package = "com.valvesoftware.android.steam.community"</span><br><span class="line">cmd = """</span><br><span class="line">'use strict;'</span><br><span class="line"></span><br><span class="line">if (Java.available) {</span><br><span class="line">  Java.perform(function() {</span><br><span class="line"></span><br><span class="line">    //Cipher stuff</span><br><span class="line">    const Cipher = Java.use('javax.crypto.Cipher');</span><br><span class="line"></span><br><span class="line">    Cipher.doFinal.overload('[B').implementation = function (input) {</span><br><span class="line">        var result = this.doFinal.overload('[B').call(this, input);</span><br><span class="line">        send(result);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">  }</span><br><span class="line">)}</span><br><span class="line">"""</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def parse_hook(cmd_):</span><br><span class="line">    print('[*] Parsing hook...')</span><br><span class="line">    script = session.create_script(cmd_)</span><br><span class="line">    script.on('message', on_message)</span><br><span class="line">    script.load()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def on_message(message, _):</span><br><span class="line">    try:</span><br><span class="line">        if message:</span><br><span class="line">            if message['type'] == 'send':</span><br><span class="line">                result = "".join(chr(i) for i in message['payload'])</span><br><span class="line">                print(json.dumps(json.loads(result), indent=2, ensure_ascii=False))</span><br><span class="line">    except Exception as e:</span><br><span class="line">        print(e)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line">    try:</span><br><span class="line">        print('[*] Spawning ' + package)</span><br><span class="line">        pid = frida.get_usb_device().spawn(package)</span><br><span class="line">        session = frida.get_usb_device().attach(pid)</span><br><span class="line">        parse_hook(cmd)</span><br><span class="line">        frida.get_usb_device().resume(pid)</span><br><span class="line">        print('')</span><br><span class="line">        sys.stdin.read()</span><br><span class="line"></span><br><span class="line">    except KeyboardInterrupt:</span><br><span class="line">        sys.exit(0)</span><br><span class="line">    except Exception as e:</span><br><span class="line">        print(e)</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><p>现在在你的保存了steamguard.py的目录，像之前一样在导航栏输入cmd打开命令提示符，并输入以下代码</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python steamguard.py</span><br></pre></td></tr></tbody></table></figure><p>如果你成功输出了类似结果<br><img src="https://b3logfile.com/file/2023/11/image-Vv5rEmG.png" alt="image.png" loading="lazy"><br>则说明提取成功。<br>将黄色标记部分之间的大括号部分复制来，新建一个txt文件，粘贴进去保存，.txt后缀改为.mafile，你就获得一个可以导入其他第三方软件的令牌了。<br>如果想用Steam网页的一键确认脚本，直接将复制的内容导入即可。</p><p>本文原发布在其乐论坛，<a href="https://keylol.com/t900859-1-1">Steam 安卓模拟器+frida python调试的令牌导出教程 - 平台工具 - 其乐 Keylol</a></p>]]>
      </content:encoded>
    </item>
  </channel>
</rss>
