<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>菠萝油与天光墟</title>
    <link>https://ramsayleung.github.io/zh/</link>
    <description>Recent content on 菠萝油与天光墟</description>
    <image>
      <title>菠萝油与天光墟</title>
      <url>https://ramsayleung.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</url>
      <link>https://ramsayleung.github.io/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E</link>
    </image>
    <generator>Hugo -- 0.146.7</generator>
    <language>zh</language>
    <copyright>See this site&amp;rsquo;s source code here, licensed under GPLv3 ·</copyright>
    <lastBuildDate>Tue, 06 Jan 2026 20:27:06 -0800</lastBuildDate>
    <atom:link href="https://ramsayleung.github.io/zh/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>迄今所见最扎实的AI落地实践: Reddit的AI翻译</title>
      <link>https://ramsayleung.github.io/zh/post/2026/%E8%BF%84%E4%BB%8A%E6%89%80%E8%A7%81%E6%9C%80%E6%89%8E%E5%AE%9E%E7%9A%84ai%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5_reddit%E7%9A%84ai%E7%BF%BB%E8%AF%91/</link>
      <pubDate>Mon, 05 Jan 2026 22:18:00 -0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2026/%E8%BF%84%E4%BB%8A%E6%89%80%E8%A7%81%E6%9C%80%E6%89%8E%E5%AE%9E%E7%9A%84ai%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5_reddit%E7%9A%84ai%E7%BF%BB%E8%AF%91/</guid>
      <description>&lt;h2 id=&#34;全民ai热潮&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 全民AI热潮&lt;/h2&gt;
&lt;p&gt;自OpenAI 发布 ChatGPT 以来，国内外都掀起了大干快上AI的各种项目，这两年真的是各种网站/应用都追求落地AI.&lt;/p&gt;
&lt;p&gt;音乐软件有AI, 比如QQ音乐 &lt;a href=&#34;https://y.qq.com/vemus/index.html&#34;&gt;搞AI编曲&lt;/a&gt; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, Spotify &lt;a href=&#34;https://newsroom.spotify.com/2024-04-07/spotify-premium-users-can-now-turn-any-idea-into-a-personalized-playlist-with-ai-playlist-in-beta/&#34;&gt;搞AI歌单&lt;/a&gt; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;； 编程问答网站 Stackoverflow搞 &lt;a href=&#34;https://stackoverflow.com/ai-assist&#34;&gt;AI 问答&lt;/a&gt; &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, 浏览器搞AI(Firefox, &lt;a href=&#34;https://www.google.com/chrome/ai-innovations/&#34;&gt;Chrome&lt;/a&gt; &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;), 笔记软件如 Notion 搞 &lt;a href=&#34;https://www.notion.com/product/ai&#34;&gt;AI workflow&lt;/a&gt; &lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;; 代码托管网站 GitHub 搞AI 编程和代码Review, 甚至最离谱的是连电子书管理软件(Calibre)也搞AI, 增加了一个 &amp;ldquo;&lt;a href=&#34;https://calibre-ebook.com/whats-new&#34;&gt;Asking AI&lt;/a&gt;&amp;quot; &lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;的功能，真的是全民「炼」AI.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="全民ai热潮"><span class="section-num">1</span> 全民AI热潮</h2>
<p>自OpenAI 发布 ChatGPT 以来，国内外都掀起了大干快上AI的各种项目，这两年真的是各种网站/应用都追求落地AI.</p>
<p>音乐软件有AI, 比如QQ音乐 <a href="https://y.qq.com/vemus/index.html">搞AI编曲</a> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, Spotify <a href="https://newsroom.spotify.com/2024-04-07/spotify-premium-users-can-now-turn-any-idea-into-a-personalized-playlist-with-ai-playlist-in-beta/">搞AI歌单</a> <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>； 编程问答网站 Stackoverflow搞 <a href="https://stackoverflow.com/ai-assist">AI 问答</a> <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, 浏览器搞AI(Firefox, <a href="https://www.google.com/chrome/ai-innovations/">Chrome</a> <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>), 笔记软件如 Notion 搞 <a href="https://www.notion.com/product/ai">AI workflow</a> <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>; 代码托管网站 GitHub 搞AI 编程和代码Review, 甚至最离谱的是连电子书管理软件(Calibre)也搞AI, 增加了一个 &ldquo;<a href="https://calibre-ebook.com/whats-new">Asking AI</a>&quot; <sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>的功能，真的是全民「炼」AI.</p>
<hr>
<p>原来还有更离谱的，雷蛇发布了<a href="https://www.razer.com/ca-en/concepts/project-ava">桌面全息AI助手</a> <sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>，承诺只帮助，不BB。</p>
<p>你做得好用就还好，但是一堆的网站或者应用就硬堆AI，所谓的AI功能无非是加个AI 对话框，让你可以打开聊天框和AI 对话，但是连当前网页的内容都没有当作上下文喂给AI, 体验非常差。</p>
<h2 id="reddit-的ai翻译"><span class="section-num">2</span> Reddit 的AI翻译</h2>
<p>今天看到一篇<a href="https://www.theguardian.com/technology/2026/jan/03/reddit-overtakes-tiktok-uk-search-algorithms-gen-z">文章</a> <sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup>, 说 Reddit 在英国超过 TikTok 成为访问量第四大的社媒平台，过去两年英国用户人数增长了 88%，三分之二的英国网民会访问 Reddit，而 2023 年仅是三分之一。而18-24 岁英国用户中 Reddit 是访问量第六大的网站，而一年前这一数字是第十。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-dd7d6" hidden>
    <label for="zoomCheck-dd7d6">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/reddit_overtake_tiktok.jpg"/> 
    
    
    </label>
</figure>

<p>不熟悉 Reddit 的朋友可以把 Reddit 理解成海外版本的「贴吧」.</p>
<p>Reddit 的崛起背后的因素包括了 Google 调整了算法增加了论坛类内容的权重，而 Reddit 就是论坛形式的社媒。在 AI 时代，用户也越来越多的转向人工撰写的内容，Reddit 也受益于这一趋势。</p>
<p>这篇文章让我想起最近Reddit 做的新功能，Reddit 利用大语言模型，为其海量帖子生成了多种语言的翻译版本，比如把英文帖子翻译成了中文, 韩文，日文等等。</p>
<p>然后我用中文在Google 搜索的时候，Google 搜索结果中就会展示原帖子的翻译版本，当我点击搜索结果时，就会跳转到Reddit 翻译后的中文版本:</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-cba3f" hidden>
    <label for="zoomCheck-cba3f">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/berserk_tv_in_chinese.jpg"/> 
    
    
    </label>
</figure>

<p>我可以直接阅读翻译后的版本:</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-dcf9d" hidden>
    <label for="zoomCheck-dcf9d">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/berserk_post_tl_zh_hans.jpg"/> 
    
    
    </label>
</figure>

<p>又或者点击「Show Original」阅读原版。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-8aca7" hidden>
    <label for="zoomCheck-8aca7">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/berserk_post_show_original.jpg"/> 
    
    
    </label>
</figure>

<h2 id="天才产品设计"><span class="section-num">3</span> 天才产品设计</h2>
<p>初看之下似乎平平无奇，细品之下真的是拍案叫绝，我愿称之为「迄今所见最扎实的AI落地实践」</p>
<h3 id="reddit-角度"><span class="section-num">3.1</span> Reddit 角度</h3>
<p>首先这个功能让更多用户阅读不同语言的帖子，比如中文，日文用户可以阅读原文是英语，法语，西班牙语的帖子，大大增加了Reddit 帖子的普适性，语言不再是个障碍，可以为Reddit 在AI时代增加用户流量，为新用户引流。</p>
<p>更多的用户就意味着更多的内容，更丰富的内容就能吸引来更多的用户，在AI时代，
内容就是「炼」AI大模型的原材料，光有英伟达的显卡，没有原材料，肯定没法炼出AI。</p>
<p>对比谷歌翻译这样的外置的翻译软件，这个是实时、无缝的页面级翻译，翻译质量相当高，其翻译质量之高、
与页面整合之自然，初用时甚至令人难以察觉这是机器翻译的产物。</p>
<p>用户体验非常好，其自然和实用的特点，完美解决了非母语用户访问高质量 UGC 的核心痛点。</p>
<p>更关键的是，作为用户，我完全没有意识到「AI」的存在。</p>
<p>我是在切换到工程师的视角之后，我才意识到 Reddit 使用大模型把帖子给翻译了，然后让谷歌的搜索引擎把不同语言的版本都索引, 直接把翻译结果在谷歌的搜索结果中展示了</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-cba3f" hidden>
    <label for="zoomCheck-cba3f">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/berserk_tv_in_chinese.jpg"/> 
    
    
    </label>
</figure>

<p>最好的AI特性就是让你根本意识不到AI的存在。</p>
<h3 id="google-角度"><span class="section-num">3.2</span> Google 角度</h3>
<p>对Google 来说，因为Reddit 绝大部分的帖子都是人发的(Reddit版主大多都非常讨厌机器人或者AI 发帖，有相当多的版规说明不能使用AI生成内容，否则非常容易被禁言或者在某个子版封号), 提高论坛类内容的权重, 即可以保证搜索质量.</p>
<p>而索引不同语言版本的帖子又给谷歌提供了更多的高质量的搜索数据。</p>
<p>所以谷歌既索引了大量新鲜、高质量、多语言的人类内容，又提升了搜索结果质量，正好契合其算法调整方向</p>
<h3 id="数据-模型与生态的飞轮"><span class="section-num">3.3</span> 数据、模型与生态的飞轮</h3>
<p>正是通过为用户打破语言壁垒，为谷歌丰富搜索结果，Reddit得以启动一个更宏大的正向循环</p>
<p>在 2024年2月, Reddit 和 谷歌 达成深化合作的协议，Reddit 允许谷歌使用它的数据训练 AI 模型, 据报道，初始合同是每年六千万美元。</p>
<p>在 2025年9月，传出了 Reddit 和谷歌以及 OpenAI 谈新的合同，因为他们相信他们的用户数据对于 AI 训练非常重要，所以他们想谈更好的合同。</p>
<p>所以这个AI翻译的设计，就是一个强强联合, 打出 <code>1+1&gt;3</code> 的效果, 甚至能以此为助力和其他的大模型厂商聊合作，无论是OpenAI, 还是 Anthropic, 没有数据也练不出 AI来。</p>
<p>形成了一个正向循环：更多用户 -&gt; 更多内容 -&gt; 更好AI数据 -&gt; 更好翻译/搜索/AI模型 -&gt; 更多用户</p>
<p>这是一个对用户，对 Reddit, 对谷歌，甚至对整个AI领域都有益处的设计，甚至可以说是「四赢」</p>
<h2 id="结语"><span class="section-num">4</span> 结语</h2>
<p>成功的AI落地，是让技术隐形，让用户价值凸显.</p>
<p>比对其他「强加AI」的产品，Reddit 的翻译功能是真正将AI融入产品，而非牵强附会，它甚至都没有告诉用户，这是用AI来实现的, 不强求AI叙事。</p>
<p>写到这里，不禁让我想起国内最早 all in AI, 还手握搜索引擎和中国最大论坛贴吧的某公司，真的是一手王炸的牌打得稀烂。</p>
<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">加国旅居纪–开篇</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://y.qq.com/vemus/index.html">https://y.qq.com/vemus/index.html</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://newsroom.spotify.com/2024-04-07/spotify-premium-users-can-now-turn-any-idea-into-a-personalized-playlist-with-ai-playlist-in-beta/">https://newsroom.spotify.com/2024-04-07/spotify-premium-users-can-now-turn-any-idea-into-a-personalized-playlist-with-ai-playlist-in-beta/</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://stackoverflow.com/ai-assist">https://stackoverflow.com/ai-assist</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://www.google.com/chrome/ai-innovations/">https://www.google.com/chrome/ai-innovations/</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://www.notion.com/product/ai">https://www.notion.com/product/ai</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="https://calibre-ebook.com/whats-new">https://calibre-ebook.com/whats-new</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a href="https://www.razer.com/ca-en/concepts/project-ava">https://www.razer.com/ca-en/concepts/project-ava</a>&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p><a href="https://www.theguardian.com/technology/2026/jan/03/reddit-overtakes-tiktok-uk-search-algorithms-gen-z">https://www.theguardian.com/technology/2026/jan/03/reddit-overtakes-tiktok-uk-search-algorithms-gen-z</a>&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>历史的迷雾</title>
      <link>https://ramsayleung.github.io/zh/post/2026/%E5%8E%86%E5%8F%B2%E7%9A%84%E8%BF%B7%E9%9B%BE/</link>
      <pubDate>Sun, 04 Jan 2026 11:57:00 -0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2026/%E5%8E%86%E5%8F%B2%E7%9A%84%E8%BF%B7%E9%9B%BE/</guid>
      <description>&lt;h2 id=&#34;缘起&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 缘起&lt;/h2&gt;
&lt;p&gt;2026 伊始，在遥远的南美洲，发生了一件事：&lt;/p&gt;
&lt;p&gt;1月3日，美国总统特朗普称，美方已成功对委内瑞拉实施打击，抓获马杜罗及其夫人，并带离委内瑞拉。
当天稍早时，委内瑞拉首都加拉加斯传出爆炸声，随后响起防空警报。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="缘起"><span class="section-num">1</span> 缘起</h2>
<p>2026 伊始，在遥远的南美洲，发生了一件事：</p>
<p>1月3日，美国总统特朗普称，美方已成功对委内瑞拉实施打击，抓获马杜罗及其夫人，并带离委内瑞拉。
当天稍早时，委内瑞拉首都加拉加斯传出爆炸声，随后响起防空警报。</p>
<p>我平时甚少在公众场合议论时政，在观点日益极化的当下，易惹纷争。既然无意探讨政治，便来聊聊历史吧。</p>
<p>这种「大事发生时，日子却平淡如水」的感觉，让我想起了季羡林先生在二战期间的一段经历。</p>
<p>历史的吊诡之处，往往就藏在这些日记的字里行间。</p>
<h2 id="季羡林日记"><span class="section-num">2</span> 季羡林日记</h2>
<h3 id="留德日记"><span class="section-num">2.1</span> 留德日记</h3>
<p>《留德日记》是国学大师季羡林先生在德国哥廷根大学苦读十余年，写下了洋洋六卷，
煌煌一百五十余万字的日记，记录了从1934—1946年在德的求学生涯。</p>
<p>这是1941年6月22日的日记：</p>
<blockquote>
<p>⼆⼗⼆⽇</p>
<p>早晨⼀起来，⼥房东就说，俄德已经开⽕，这⼀着早就料到，却没想到这样快。</p>
<p>吃过早点，到⻋站去，会到Frau Pinks（苹可斯夫⼈）同另外⼀位德国⼈Gross（格罗斯）。</p>
<p>坐⽕⻋到Dransfeld（德兰斯费尔德），从那⾥步⾏到Bursfelde（布尔斯费尔德），计⼗⼆Kl.（公⾥）。</p>
<p>沿途景致⾮常好， 茂林流⽔ 。 Gross （格洛斯） 拉⼿⻛琴，沿路⼤唱 。</p>
<p>在 Bursfelde（布尔斯费尔德）休息了会，吃了午饭，原来预备坐船到 Hann Münden（明登）。但今天没有轮船，只好临时改变计划，渡过 Weser （威悉河）。</p>
<p>在渡船上看到年⻘的⼥孩⼦在河⾥游泳，更显出⾝躯的窈窕，令⼈消（销）魂。</p>
<p>过河步⾏经过Gottstreu，在Gieselwerder（吉瑟尔⻙德）⼜过河来。</p>
<p>⼀直经过Lippolsberg ⾛到Bodenfelde，⾛了约⼗五Kl.（公⾥）。天⽓极热，⼜在⼤毒⽇头下⾯⾛，真有点够受。</p>
<p>七点坐⽕⻋回G.ttingen（哥廷根）。脚上起了泡，好容易⾛到家。吃过晚饭，洗澡就睡。</p></blockquote>
<p>「茂林流水」，「拉手风琴，沿路大唱」，「年轻的女孩子在河里游泳……令人销魂」。</p>
<p>这一天季先生是快乐的，甚至因为看美女游泳而「销魂」，完全没有把「俄德开火」当成一件天塌下来的事。</p>
<h3 id="留德十年"><span class="section-num">2.2</span> 留德十年</h3>
<p>数十年后，季先生已近耄耋之年，忆及往昔，遂写下一部《留德十年》，其中也有关于二战的回忆：</p>
<blockquote>
<p>1941年6月22日，我早晨一起来，女房东就告诉我，德国同苏联已经开了火。
我的日记上写道：&ldquo;这一着早就料到，却没想到这样快。&rdquo;
这本来应该说是一件天大的事，但是德国人谁也不紧张。</p>
<p>原因大概是，最近几年来，几乎每年两次出现这样的事，&ldquo;司空见惯浑无事&quot;了。</p>
<p>我当然更不会紧张。前两天约好同德国朋友苹可斯（Pinks）和格洛斯（Gross）去郊游，照行不误。</p>
<p>整整一天，我们乘车坐船，几次渡过小河，在旷野绿林中，步行了几十公里，唱歌，拉手风琴，野餐，玩了个不亦乐乎，
尽欢而归，在灯火管制、街灯尽熄的情况下，在黑暗中摸索着走回了家。</p>
<p>无论是对我，还是对德国朋友来说，今天早晨德苏宣战的消息，给我们没有留下任何印象。</p>
<p>第一次世界大战爆发时，我刚三岁，什么事情都不知道。</p>
<p>后来读了一些关于这方面的书，看到战火蔓延之广，双方搏斗之激烈，伤亡人数之多，财产损失之重，我总想像，
这样大的大事开始时一定是惊天地，泣鬼神，上至三十三天，下达十八层地狱，无不震动，无不惊恐，才合乎情理。</p>
<p>现在，我竟有幸亲身经历了规模比第一次世界大战要大得多、时间要长得多、伤亡要重得多的第二次世界大战的开端。</p>
<p>可是万万没有想到，这一出人类历史上罕见的大戏，开端竟是这样平淡无奇。</p>
<p>事后追思，真颇有点失望不过瘾的感觉了。</p></blockquote>
<h2 id="身处历史中的人"><span class="section-num">3</span> 身处历史中的人</h2>
<p>所谓历史的迷雾，即使身在其中者，往往在开端时难以觉察时代的巨变.</p>
<p>历史是后设的，我们在教科书上看历史，看到的是明确的「节点」：1941年6月22日是苏德大战爆发日。</p>
<p>但在季羡林先生的笔下，那日是「茂林流水」，是手风琴与歌声，是因见少女游泳而「销魂」的漫长徒步。</p>
<p>女房东告知开战的消息，语气平淡；日记里的记载，也仅是一笔带过。</p>
<p>茨威格在《昨日的世界》中回忆一战爆发时，描绘了相似的图景：</p>
<p>1914年夏日，维也纳阳光明媚，咖啡馆里依旧谈笑风生，人们以为那不过是一场很快会结束的边境冲突。</p>
<p>从20世纪萨拉热窝的一声枪响，到21世纪某个海鲜市场出现的不明肺炎，那些日后掀起滔天巨浪的黑天鹅，
在起初的迷雾中，常常只被视为一块不起眼的小石子。</p>
<p><strong>我们或许也正身处这样的雾中</strong> ：
今天的头条新闻，未来教科书上可能是一个时代的注脚，但对当下的我们而言，它可能只是短视频中的一条推送，或是茶余饭后的一声感叹。</p>
<p>我们如1941年哥廷根森林里的散步者，感受着「天气极热」，却听不见历史齿轮那沉重而确凿的转动声。</p>
<h2 id="冰川的消融"><span class="section-num">4</span> 冰川的消融</h2>
<p>一战的壕沟与二战的废墟，让战后世界艰难地学会了「制定规则」的游戏。</p>
<p>目的很直接：避免弱肉强食的全面冲突再次将文明拖入深渊，不要再掀牌桌，不然互扔原子弹，人类可能都要玩完。</p>
<p>当然，我不是暗示某大国对某南美国家的行动会引起第三次世界大战。</p>
<p>我想说的是，此类行动在国际法理与地缘政治上，或许已经悄然推倒了一块多米诺骨牌。</p>
<p>但这种崩塌并非大厦倾覆的轰然巨响，而更像是冰川的消融：每一天听起来都只有轻微的咔嚓声，直到巨大的冰架最终断裂入海。</p>
<h2 id="结语"><span class="section-num">5</span> 结语</h2>
<p>最后，想起某位已经被封杀歌手的歌，以此荒诞感作结：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-7e838" hidden>
    <label for="zoomCheck-7e838">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/%e8%bf%99%e4%b8%aa%e4%b8%96%e7%95%8c%e4%bc%9a%e5%a5%bd%e5%90%97.jpg"/> 
    
    
    </label>
</figure>

<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">加国旅居纪–开篇</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
]]></content:encoded>
    </item>
    <item>
      <title>加国旅居纪–英语篇</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E8%8B%B1%E8%AF%AD%E7%AF%87/</link>
      <pubDate>Sun, 07 Dec 2025 09:11:00 -0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E8%8B%B1%E8%AF%AD%E7%AF%87/</guid>
      <description>&lt;h2 id=&#34;缘起&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 缘起&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;移居他国，语言始终是一道无法绕过的坎。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在《&lt;a href=&#34;https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/&#34;&gt;这些年走过的路：从广州到温哥华&lt;/a&gt;》一文中我曾提到，我是直接在国内通过英语面试拿到了Offer。&lt;/p&gt;
&lt;p&gt;在此之前，我既无留学或海外工作经历，也未考过雅思、托福。&lt;/p&gt;
&lt;p&gt;拿到Offer前，满脑子想的只是全力准备面试，「尽人事，听天命」。
真等到Offer到手，心里那根紧绷的弦松下来，对英语的不自信、对陌生环境的忐忑才后知后觉地浮现。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="缘起"><span class="section-num">1</span> 缘起</h2>
<p><strong>移居他国，语言始终是一道无法绕过的坎。</strong></p>
<p>在《<a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a>》一文中我曾提到，我是直接在国内通过英语面试拿到了Offer。</p>
<p>在此之前，我既无留学或海外工作经历，也未考过雅思、托福。</p>
<p>拿到Offer前，满脑子想的只是全力准备面试，「尽人事，听天命」。
真等到Offer到手，心里那根紧绷的弦松下来，对英语的不自信、对陌生环境的忐忑才后知后觉地浮现。</p>
<p>与未来室友聊天时，我就流露过这样的担忧：怕连雅思四个6都考不到。毕竟英语一直是自学，心里实在没底：</p>
<p><img loading="lazy" src="/ox-hugo/chat_history_with_schenkerx_1.jpg">
<img loading="lazy" src="/ox-hugo/chat_history_with_schenkerx_2.jpg"></p>
<p>但转念一想，最大的难关（拿到Offer）都已跨过，车到山前必有路。一切，等落地再说。</p>
<h2 id="应试雅思"><span class="section-num">2</span> 应试雅思</h2>
<p>落地加拿大后，申请身份需要，兼之公司报销考试费用，我决定报考雅思。</p>
<p>当时的想法是先摸底，熟悉流程，便直接预约了最近的一场考试&ndash;大约是两周之后。</p>
<p>心想即便考不过，反正公司也报销，正好以 deadline 作为学习动力。</p>
<p>白天上班，晚上回家刷雅思真题，配合着 Youtube 的备考视频，重点攻克作文和口语。</p>
<p>阅读和听力没什么套路，会就会，不会就不会。</p>
<p>一晚复习作文，一晚复习口语，交替进行。</p>
<p>口语练习尤为痛苦&ndash;常常觉得无话可说，难以持续讲1-2分钟。</p>
<p>好在 ChatGPT 已经发布了，我便让它生成口语答案，自己背诵，「熟读唐诗三百首，不会作诗也会吟」，这是小镇做题家最笨拙又最踏实的办法。</p>
<p>如此匆忙「准备」两周之后，直接上考场了。</p>
<p>听，读，写都是机试，就和国内学习熟悉的考试形式无异，而「说」才是我的重点戏，也是真正的难关。</p>
<p>雅思口语考试是与考官一对一面试，全程录音，时长约11-14分钟，分三部分，由浅入深：</p>
<ol>
<li>简介与日常对话（4-5分钟）：热身与自我介绍，话题轻松，只需清晰、直接作答。</li>
<li>个人陈述（3-4分钟）：就特定话题进行1-2分钟独白。有1分钟准备时间。</li>
<li>双向讨论（4-5分钟）：第二部分的延伸，深入讨论社会性议题，更具思辨性。</li>
</ol>
<p>我记得第二部分话题是旅游，要求讲述一次印象深刻的旅行经历。这么大的人了，总去过一些地方，便开始结结巴巴地讲述。</p>
<p>第三部分，考官问我对gap year（高中毕业后休假一年再上大学）的看法。</p>
<p>这是我完全未曾思考过的话题，只好写议论文般列举优点：体验风土人情、增长见识、打工培养独立意识等等</p>
<p>我竭力想让表达条理清晰，但仍能察觉考官礼貌微笑背后略带疑惑的眼神。心里不禁一叹：看来是凉了。</p>
<p>成绩通常在两三周后公布，但我已不抱希望。</p>
<p>大约三周后的早晨，我如常在地铁上刷雅思官网，突然看到成绩更新通知。颤抖着点开，竟发现总分7分，小分分别为听7、读7、说6.5、写6.5：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-c1d60" hidden>
    <label for="zoomCheck-c1d60">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/ielts_result.jpg"/> 
    
    
    </label>
</figure>

<p>近乎「裸考」竟能拿到7分，实在出乎意料。看来，我的英语并没有想象中那么差。</p>
<h2 id="现实落差"><span class="section-num">3</span> 现实落差</h2>
<p>然而，那短暂的自信很快被现实击碎——原来我的英语真的不够用。</p>
<p>当时入职的团队颇为「奇妙」：经理是加拿大白人，其余六名工程师全是华人。这意味着大部分时间可用普通话沟通。</p>
<p>一方面，这确是好事，减少了沟通障碍；另一方面，却也意味着我缺乏提升英语的迫切环境。</p>
<p>真正意识到自己口语听力不足，是在与美国产品经理和总监开会时。
他们常在会议前后寒暄、开玩笑，我不仅插不上话，有时连笑点都跟不上——他们用的表达和梗，与书本上的完全不同。</p>
<p>时隔三年，有一幕仍记忆犹新：</p>
<p>总监和产品经理从美国来加开会，午餐时我们在会议室吃三明治，聊起公司从允许居家办公改为强制每周至少回办公室三天的政策。</p>
<p>我很想参与讨论，听听本地美国人对这政策的看法：是否有人不满？会不会有人因此离职？长期影响如何？</p>
<p>但开口却只有一句生硬的「Will it work?」（这能行得通吗？）</p>
<p>没有铺垫，缺乏上下文，突兀至极。身旁的总监略显诧异地看了我一眼，随即岔开了话题。</p>
<p>老板当然不会直接说「行不通」，但若说「行得通」，他自己恐怕也不尽信。那一刻，尴尬得我只想离开。</p>
<p>不过，总算敢开口扯闲篇了。关关难过关关过。口语与听力相辅相成：听不懂就说不出，词汇不够就听不懂。</p>
<p>菜就多练。下班后，我又开始了英语学习。</p>
<p>为应对可能出现的语言困境，我从国内带了几本书，除雅思真题外，还有一本《Word Power Made Easy》：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-3481d" hidden>
    <label for="zoomCheck-3481d">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/word_power_make_easy.jpg"/> 
    
    
    </label>
</figure>

<p>这是我所读过最好的单词书。它不简单罗列单词，而是从词根历史出发，介绍拉丁或古希腊语源，以点带面，每节讲解若干近义词。</p>
<p>每天通勤途中，我听英文技术播客，既学习技术词汇表达，也锻炼听力。</p>
<p>阅读则多啃同事的设计文档、公司内网资料，既提升词汇量，又加深对内部系统的了解。</p>
<p>至于改进口语，我的方法是模仿再应用：观察经理、产品经理、总监这些母语者如何表达，然后照葫芦画瓢。</p>
<p>为强迫自己多开口，我给自己定了一条规矩： <strong>不用「Yes」和「No」直接回答问题</strong></p>
<p>起初因不敢多言，对于上级的询问，常脱口而出「Yes」，结果过度承诺，反坑了自己。</p>
<p>比如老板问：</p>
<blockquote>
<p>Are you feeling confident that you could get this task done by the end of today?
（你有信心今天把这活干完吗？）</p></blockquote>
<p>若直接答「Yes」，相当于承诺今日完成。若完不成，要么默默加班，要么给老板留下言而无信的印象——无论哪种，都是坑自己。</p>
<p>不用「Yes/No」回答，迫使自己既表达想法，又不轻易许诺。</p>
<p>就这样，虽然磕绊，总算能说出口，也渐渐能听懂他们的闲聊了。</p>
<h2 id="全英淬炼"><span class="section-num">4</span> 全英淬炼</h2>
<p>因种种原因，我在第一个团队待了不到一年便换了组。新团队再无华人同事，彻底失去了普通话交流的「安全区」。</p>
<p>更「要命」的是，团队中多数同事的母语并非英语：有来自俄罗斯、巴西、土耳其、法国、希腊的成员。
各种口音混杂，英语听力难度陡增。</p>
<p>学习语言本无捷径，唯有多听多说。</p>
<p>环境虽变，方法依旧：模仿、练习。</p>
<p>尽管未必每句话都听懂，但同事间的交流总有上下文支撑，加之面对面可观察肢体语言和表情，连蒙带猜，也能明白八九成。</p>
<p>就这样，在难度加倍的副本中，慢慢摸到了门道。</p>
<p>以英语为母语的国家（如南非、英国、美国、加拿大）的口音，其实是最易理解的。即便常被吐槽的印度口音，熟悉后也相对好懂。</p>
<p>真正棘手的是部分欧洲同事的英语：发音平淡，缺乏重读，听起来格外费力。</p>
<p>后来因组织架构调整，我又到了新团队，接触到韩国、尼泊尔、马来西亚、埃及、越南、印尼、西班牙等地口音——欧亚非口音，几乎集齐了。</p>
<p>与不同母语背景的同事打交道后，自信也慢慢累积起来。</p>
<p>提升口语只有一条「捷径」：多练多说。不做就不会错，不错就不丢人——但也不会进步。想进步，就别怕丢脸。我母语不是英语，说错很正常，没什么大不了。</p>
<p>我就是抱着这样的心态与人交流的。</p>
<h2 id="地道进阶"><span class="section-num">5</span> 地道进阶</h2>
<p>当我能听懂同事交谈、较流利表达想法后，便开始追求更地道的表达。</p>
<p>其中对我帮助最大的是两位加拿大同事：J和R。</p>
<p>J风趣幽默、博学多才，通晓五门语言，博士毕业，还是UBC大学的客座教授。</p>
<p>他对语言要求相当高，review 我的代码或文档时，常纠正语法或表达错误。</p>
<p>比如 <code>schema</code> 的复数，我写了 <code>schemas</code> ， 他说似乎不对，应是 <code>schemata</code> 。后来一查，两者皆可。</p>
<p>另一次晨会，遇到棘手问题，经理问谁可接手。</p>
<p>J比经理高一级，与总监同级，开口便说：「我觉得ZhenRui能做好。」</p>
<p>我就很懵：怎么还点名了？</p>
<p>事后J私下解释：</p>
<blockquote>
<p>I don&rsquo;t mean to throw you under the bus, I just trust you definitely have the ability to get this task done.
（我不是想让你背锅，只是相信你肯定能搞定。）</p></blockquote>
<p>&ldquo;throw you under the bus&quot;直译是「丢到车底」，意译即「让你背锅」。</p>
<p>从他身上，我学到了许多地道而「奇妙」的表达。</p>
<p>软件开发中的「金丝雀发布」(Canary Release)策略，指将更新逐步部署给小部分用户测试，以发现问题、降低风险，就像矿工用金丝雀检测毒气。</p>
<p>J 将包含一堆金丝雀(canary)测试用例的目录命名为「歌剧」(opera)，我 review 时不理解，他便趁机科普了一番。</p>
<p>英语中许多动物群体有特定且诗意的名称：</p>
<ul>
<li>一群金丝雀（canary）叫「歌剧」(opera)，</li>
<li>一群乌鸦(crow)叫「谋杀」(murder)，</li>
<li>一群鸭子(duck)可称「一阵哨声」(whistling)</li>
</ul>
<p>中文没有完全对应的集合名词文化。</p>
<p>R 是在加拿大出生的华裔，身上有种我缺乏的松弛感和嬉皮士气质。</p>
<p>他常教我俚语，比如 <code>fumble the bag</code> （类似「煮熟的鸭子飞了」，特指金钱方面的损失），或 <code>drop the ball</code> （源自美式足球的失球，引申为「搞砸了」「掉链子」）。</p>
<p>用对词，才能准确传达情绪和意图。比如：</p>
<ul>
<li>微妙细致的差别：用 <code>nuance</code> 而非 <code>subtle difference</code></li>
<li>趣事轶闻：用 <code>anecdote</code> 而非 <code>funny story</code></li>
<li>非常滑稽：用 <code>hilarious</code> 而非 <code>so funny</code></li>
<li>反讽/阴阳怪气：用 <code>sarcasm</code></li>
<li>自欺欺人的妄想叫 <code>delusion</code>, 视觉的幻象叫 <code>hallucination</code></li>
</ul>
<p>R 还会帮我辨析词语的感情色彩。</p>
<p>一次我提起与摩门教传教士的<a href="https://ramsayleung.github.io/zh/post/2024/%E5%BC%81%E7%AB%AF%E6%91%A9%E9%97%A8%E6%95%99%E7%9A%84%E4%BA%A4%E9%9B%86/">偶遇</a>，他就问我怎么会和他们搭上话的，我说听到外国人讲中文很新奇，就和他们聊了起来.</p>
<p>R问我他们是 xx 么？我没听懂这个词，然后他就换了一个词问：「他们是白人(White Man)吗？」我说是。</p>
<p>他随即解释： <code>Caucasian</code> 是中性的「白人/欧洲裔」表述，而 <code>White Man</code> 带贬义。同理，中性表述黑人是 <code>African</code> ， 而非 <code>Black Man</code> 。</p>
<p>与他们的交流让我逐渐理解所谓的「英语思维」：不是将中文直译成英文，而是使用英语母语者的地道表达。</p>
<h2 id="自如交流"><span class="section-num">6</span> 自如交流</h2>
<p>当表达足够流利后，我已能自如应对同事的玩笑了，甚至能「阴阳怪气」起来。</p>
<p>前段时间，我回了一次国，回来之后，午餐吃饭的时候，在餐厅 J 就和我开起了玩笑:</p>
<blockquote>
<ul>
<li>J: ZhenRui, You know, you miss a big news when you were in China(ZhenRui, 你知道嘛，你回国的时候错过了一个大新闻)</li>
<li>Z: What&rsquo;s the big news?(什么大新闻)</li>
<li>J: Justin Trudeau has a new girlfriend.(小土豆找了个新女友了)</li>
<li>Z: Justin Trudeau? The former Prime Minister? Is it the big news?(小土豆，前首相？这就是大新闻阿？)</li>
<li>J: Yes(是阿。我和他都笑起来了，我知道他又在开小土豆的玩笑)</li>
<li>Z: How old is Justin Trudeau(小土豆多大年纪了？)</li>
<li>J: At least 50, why does he look so young(至少50多了吧，怎么他看起来这么年轻)</li>
<li>Z: Because he has nothing to worry about(因为他没有啥事要操心的)</li>
<li>J: Why, What do you mean?(什么意思？)</li>
<li>Z: As a disqualified Prime Minister, what else do you need to worry about(作为个不称职的首相，你还有啥要操心的)</li>
<li>J: hahahaha</li>
<li>J: ZhenRui you should be the Prime Minister(ZhenRui, 你应该去当首相的)</li>
<li>Z: I&rsquo;m not eligible to be the Prime Minster in Canada, and my father also isn&rsquo;t a former Prime Minister(在加拿大，我没有资格当首相呢，另外，我爹也不是前首相（小土豆父亲皮埃尔·特鲁多是加拿大的15任首相）)</li>
<li>J: hahahaha</li>
<li>Z: J, You can be the Prime Minister, you still have chance, I can&rsquo;t wait to see you debate with Trump(J, 你可以当首相的，你还有机会, 我迫不及待地想看你和川普 battle 了)</li>
<li>J: me, nope, I am not corrupted(我嘛？不行的，我不够腐败)</li>
<li>Z: Don&rsquo;t worry, J, as long as you become the Officer, <strong>people will help you</strong>, if you are going to do it on your own, it&rsquo;s not corruption, it&rsquo;s stealing.(不用担心啦，只要你变成官员, <strong>人们都会来帮助你的</strong>, 如果你打算自己单干，那就叫偷窃，就不是腐败了)</li>
<li>J: hahahaha</li>
<li>Z: Sorry, J, I think I need to correct myself, I just realize, as a Prime Minister, you do have something to worry about(抱歉 J，我觉得我应该纠正一下的，我才意识到，作为首相，你还是要有事情要操心的)</li>
<li>J: What?(什么？)</li>
<li>Z: How to find a new girlfriend(怎么去找个新的女朋友)</li>
</ul>
<p>餐厅充满了快活的气氛</p></blockquote>
<p>在十多年前，《疯狂英语》还非常火的时候，李阳团队曾两次来到我的学校。</p>
<p>第一次是初中的时候，李阳亲临我们的学校，介绍自己的疯狂英语学习方法，
当时一场演讲听下来，真的是热血沸腾，怀揣「用语言改变世界」的雄心，我掏了200多块的巨款买了一系列的学习教材，只是不久之后就束之高阁了。</p>
<p>几年后升入高中，李阳团队再次到来，只是主讲人换成了他的学生。年岁渐长，加之已被「坑」过一次，这次我便以看热闹的心态听完。</p>
<p>故事大纲是自己英语原来多么差，一直想要学好英语不得其法，尝试了许多方法之后仍没有改善，
在偶然的机会下接触到「疯狂英语」，抱着试一试的心态，没想到一番练习之下真的有用，最后功夫不负有心人，最终口语得以大成。</p>
<p>他验证自己的口语的方式是，假冒美国人，给美国领事馆打电话，谎称在中国丢了护照，向领事馆求助，求助半小时，对方毫无怀疑，放下电话那刻，他泪流满面。</p>
<p>为何想起这个故事？</p>
<p>我现在已经可以给各种银行，运营商，航空公司打电话用英文沟通自己的各种诉求，维权。
在经理不在的时候，帮忙主持会议，与不同国家的同事电话沟通，排查问题。</p>
<p>甚至我在今年8月，因<a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/">租房纠纷</a>，在电话会议中与房东的代理律师用英文辩护一个小时。</p>
<p>虽然口语远未「大成」，但是至少，不会再成为沟通障碍。</p>
<h2 id="回望来路"><span class="section-num">7</span> 回望来路</h2>
<p>前段时间回国的时候，家里网络出了问题，又不想一直看手机，
就翻起了墙角边的书箱 —— 那里存放着家人帮我从大学运回的书。</p>
<p>打开其中的一个箱之后，才意识到那一箱都是英文书，这是其中的一部分：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-70583" hidden>
    <label for="zoomCheck-70583">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/english_book.jpg"/> 
    
    
    </label>
</figure>

<p>还有那本已经被翻烂了的《新概念英语3》:</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-10957" hidden>
    <label for="zoomCheck-10957">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/new_concept_english_3.jpg"/> 
    
    
    </label>
</figure>

<p>我真正想要学好英语，是在高考之后。</p>
<p>但苦于不得其法，只好用最笨的办法：把这本书的课文背下来。都说「书读百遍，其义自见」，背下来，总会有收获。</p>
<p>十年过去，绝大多数课文内容已遗忘，只记得第一篇是《Puma at large》，第一句是：</p>
<blockquote>
<p>Pumas are large, cat-like animals which are found in America.</p></blockquote>
<p>重新翻开《新概念三》，曾经晦涩难懂的文章，现在读来已无太多障碍。</p>
<p>在一堆书下，还压着我2014年底写的日记:</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-e2431" hidden>
    <label for="zoomCheck-e2431">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/2014_journal.jpg"/> 
    
    
    </label>
</figure>

<p>后来，当生词本变成电脑上的一个文件，我给自己加了这样一句话：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">git blame ~/org/english/vocabulary.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">f4270c4a <span class="o">(</span>Ramsay 2021-05-16 09:54:57 +0800 3<span class="o">)</span> :Comment:
</span></span><span class="line"><span class="cl">f4270c4a <span class="o">(</span>Ramsay 2021-05-16 09:54:57 +0800 4<span class="o">)</span> 你每多背一个单词，就离想去的地方更近了一步
</span></span><span class="line"><span class="cl">f4270c4a <span class="o">(</span>Ramsay 2021-05-16 09:54:57 +0800 5<span class="o">)</span> :END:
</span></span></code></pre></td></tr></table>
</div>
</div><p>时间过去太久，我已记不清当初「要拿回来的东西」是什么，「想去的地方」又是哪里。</p>
<p>只是蓦然回首, 那个曾经遥不可及的「英语流利的自己」，已在灯火阑珊处。</p>
<p><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">回到系列目录</a></p>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<h2 id="延伸阅读"><span class="section-num">8</span> 延伸阅读</h2>
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">加国旅居纪-–开篇</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/">加国旅居纪-–租房纠纷篇</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%8C%BB%E7%96%97%E7%AF%87/">加国旅居纪–-医疗篇</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>加国旅居纪–医疗篇</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%8C%BB%E7%96%97%E7%AF%87/</link>
      <pubDate>Sun, 30 Nov 2025 21:25:00 -0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%8C%BB%E7%96%97%E7%AF%87/</guid>
      <description>&lt;h2 id=&#34;医疗之困&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 医疗之困&lt;/h2&gt;
&lt;p&gt;时至今日，中文社交平台上仍流传着大量关于加拿大医疗体系的吐槽，核心槽点就是一个字：「慢」。各种「人没了，号还没排到」的故事广为流传，甚至有人分享「回国治好病，在加拿大还没排上队」的经历。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="医疗之困"><span class="section-num">1</span> 医疗之困</h2>
<p>时至今日，中文社交平台上仍流传着大量关于加拿大医疗体系的吐槽，核心槽点就是一个字：「慢」。各种「人没了，号还没排到」的故事广为流传，甚至有人分享「回国治好病，在加拿大还没排上队」的经历。</p>
<p>身处加国，这种传闻让我时常生出「病不起」、「不敢病」的隐忧。</p>
<p>为什么加拿大的医疗系统如此之慢？根源在于「全民免费医疗」。</p>
<p>在加拿大，无论你是持工签、学签的外国人，永久居民，还是本地公民，只要拥有合法身份，都能凭一张医保卡(MSP, Medical Service Plan)免费就医。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-cd223" hidden>
    <label for="zoomCheck-cd223">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/msp-card.jpg"/> 
    
    
    </label>
</figure>

<p>核心医疗服务（如急诊、住院、癌症治疗等）几乎全由公立系统承担。只有医美、激光眼科等非核心服务存在私立诊所。这意味着，即便你年入百万，仍要和路边的流浪汉去同一家医院排队——除非你愿意花钱南下美国。</p>
<p>与美国相比，加拿大没有「花钱就能享受五星级服务」的私立全科医院；与国内相比，这里也没有「专家号/黄牛号」或「高干病房」（至少就我所知如此，也可能是我孤陋寡闻）。你不能花钱指定某位专家为你手术，一切听从转诊系统(Referral System)的安排。</p>
<p>简言之，加拿大的医疗体系是典型的「全民大锅饭」。</p>
<h2 id="旧疾复发"><span class="section-num">2</span> 旧疾复发</h2>
<p>可能是由于长期高强度工作、压力较大，我从2019年开始出现甲状腺相关的指标异常，终于在2020年末的体检中确诊甲状腺疾病，
开始了漫长的服药康复期。</p>
<p>每日服药，每月抽血复查。后来流程熟悉到，医生复查后都会贴心帮我开好下个月的验血单，免去我专门排队挂号只为开单的麻烦。</p>
<p>持续两年多的治疗，在来加拿大前终于得到医生告知：病情已控制良好，可以停药了。</p>
<p>2024年初回国时，我又去找这位相熟的医生复查。一来在她这里看了两年多，二来对加拿大的医疗系统因各种吐槽心存疑虑，想确认是否还需服药。</p>
<p>结果激素水平比正常值高了十几倍，又得重新服药。但即便吃了国内医生开的药，我也无法每月回国复诊，只能去探索加拿大的医疗系统了。</p>
<h2 id="初诊体验"><span class="section-num">3</span> 初诊体验</h2>
<p>按照BC省的流程，身体不适应先找家庭医生(Family Doctor)。家庭医生处理常规需求(Routine Requests)，如开药、体检、普通感冒等。若家庭医生认为需要专科治疗，才会将患者转诊至医院。</p>
<p>只是我申请了近两年，至今仍未排到家庭医生。问及身边朋友，大多也处于「无家庭医生」的状态。</p>
<p>这种情况下，可前往UPCC(Urgent and Primary Care Centre)。</p>
<p>其设计初衷是缓解急诊室(ER)压力，处理那些家庭医生或Walk-in诊所搞不定，但又未严重到危及生命的病例，类似国内的社区医院。</p>
<p>于是我一大早8点前往UPCC排队。取号后等了半小时就被叫到，当时还在想：「不是说很慢吗？看来也并非如此嘛。」</p>
<p>进诊室后，医护人员自我介绍时我才发现，对方并非医生而是护士。他的工作是将我的症状和诉求记录下来，等待医生接诊。</p>
<p>沟通约十分钟后，护士竟让我先回家等候。我很惊讶：「就这样回去了？」</p>
<p>护士解释：「医生可能需要3-4小时才能处理，您在这里等也可以。」</p>
<p>听到这番解释，自然选择回家等待。</p>
<p>在家等了近4小时，终于接到护士电话，我便返回UPCC。又等了约20分钟，一位医生喊我名字，带我进入诊室。</p>
<p>由于我已治疗此病数年，熟悉检查流程，正好借此判断加拿大医生的专业水平。</p>
<p>事实证明，医生的检查过程、询问的问题，与我国内医生的做法基本一致，只是语言不同。
加拿大的医疗系统并非想象中那般「不靠谱」，我心中安定不少。</p>
<p>接着医生询问我正在服用的药物。我拿出药瓶，虽然大部分是中文，但关键的药名和剂量均有英文标注。
医生说可按原剂量继续服用，并告知我，国内这款药在加拿大没有销售，但她可以开功效和剂量相同的替代药物，一个月后再抽血复查。</p>
<p>最后，为了更好地治疗我的甲状腺疾病，她开具了一份转诊单(referral)，将我转至甲状腺专家诊所。</p>
<p>全程只需出示医保卡登记，无需自掏腰包。</p>
<h2 id="医药分离"><span class="section-num">4</span> 医药分离</h2>
<p>看完病我才发现个奇怪的现象，医院里面竟然没有取药的地方，也没有抽血的地方。</p>
<p>后来发现，很多超市都有所谓的药店(pharmacy)，可以拿着医生给的处方(prescription) 去药房买药，原来看病是不需要花钱的，但是去药房拿药还是要给药费的。</p>
<p>因为公司有买额外的 Extended Health Benefits(商业补充保险)，所以我是只需要支持25%的药费，剩下的75%由保险来付。</p>
<p>这里一瓶药270片是 56.21 加元，我付了 15.07 加元</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-30f45" hidden>
    <label for="zoomCheck-30f45">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/london_drug_pill.jpg"/> 
    
    
    </label>
</figure>

<p>而至于抽血，验尿，心电图之类的检查，在BC省主要就由一家叫 Lifelabs 的私营公司垄断承包的，所以需要抽血的时候，就去这家公司官网预约，化验结果就会发到指定的医生那去。</p>
<p>对于习惯了国内大医院挂号、看病、检查、拿药、手术「一条龙服务」的人来说，难免会升起一个疑问，为什么要这么设计?</p>
<p>后来去看专家医生的时候，闲聊之际就问起这个疑问，这位老医生就给出他的见解：</p>
<p><strong>最主要的原因：为了防止医生「为了赚钱乱开药」</strong></p>
<p>这是加拿大医疗体系的一个核心原则：「医」和「药」必须彻底分家。</p>
<ul>
<li>如果医生能卖药： 就像让裁判同时当运动员， 那他就有很大的动力给你开最贵的药，或者在你不需要吃药的时候给你开一堆药。</li>
<li>现在的制度： 医生只负责看病和写处方，他拿不到卖药的一分钱。你去哪里买药完全由你自己决定。
这样医生在开药时，就只会考虑「什么药对你最有效」，而不是「什么药利润最高」。</li>
</ul>
<p><strong>第二个原因：诊所只是「写字楼」，不是「化验厂」</strong></p>
<p>你去的 UPCC 或者普通的家庭医生诊所，本质上就是个咨询室。</p>
<ul>
<li>抽血很麻烦： 处理血液样本需要专门的冷链运输、昂贵的离心机、还有处理生化医疗垃圾的资质。普通诊所空间有限，无力承担专门的设备与额外的人员。</li>
<li>集中处理更便宜： 把全城几百个诊所的验血需求，全部集中给 LifeLabs 这一家专门的大公司做，效率最高，成本最低</li>
</ul>
<p><strong>第三个原因：为了让你在家门口拿药</strong></p>
<p>虽然在诊所拿药看似方便，但加拿大的逻辑是：药房应该像便利店一样多。</p>
<ul>
<li>医生可能离你公司近，但药房最好离你家近。</li>
<li>药房在加拿大就像 7-11 一样密集。你拿着处方，可以在下班回家路上任意一家药房取药，不用非得挤在诊所里排队。
（的确如此，许多超市晚上6点关门，药店却营业至晚上10点。）</li>
</ul>
<p>简而言之， 医生只负责动脑子（诊断）， LifeLabs 负责动机器（化验），药房 负责卖东西（给药）.</p>
<p>大家各司其职，互不给回扣，这样系统最透明（理论上）。</p>
<p>唯一的例外： 如果你是真的进了大医院的急诊室（ER）或者住院了，那种时候为了救命，医生护士会直接给你打针喂药抽血，不用你自己跑腿。</p>
<p>除此以外，都要你自己去外面跑一趟。</p>
<h2 id="专家诊所"><span class="section-num">5</span> 专家诊所</h2>
<p>因为有药吃着，所以我也没有急着去找专家诊所，只是没想到过了两个星期之后，我收到了来自专家诊所的电话，说他们收到来自UPCC的 referal, 想给我约下时间，我本来是没有想到专家诊所还会主动来联系我。</p>
<p>更没有想到，最近的可预约的时间都已经一个半月之后了，原来真的是很慢。</p>
<p>一个半月后，我按照约定时间去到诊所，这次就不需要怎么等待了，很快就看到了医生，是位白人老大爷，头发也相当稀疏，轻声细语地询问了我很多问题，包括我患病的时间，吃药的过程，身体的状况，还有家人是否在加拿大之类的问题；</p>
<p>聊了20分钟之后，他还对我在吃的药剂量做了调整，还约定1个月后再抽血检查，到时可以电话和我沟通，就不需要我专门跑一趟。</p>
<p>整个就诊的流程体验很不错，从他问的问题可以看出老医生是甲状腺方面的专家，经验丰富（从发量和年纪也能看出来）, 就这样，我又恢复到了原来在国内那种，持续吃药，一个月抽血看一次的经历。</p>
<h2 id="急诊历险"><span class="section-num">6</span> 急诊历险</h2>
<p>人生第一次看急诊，竟是在加拿大。</p>
<p>我每周六固定踢球，球友中有一位「传奇人物」——国人大哥，堪称「球场百草枯」。他脾气火爆，动辄抱怨队友，已被多支球队「劝退」。</p>
<p>我们踢球的时候，都是一帮球友过来，由两个资历老的球友来当队长，相互选队员，他都是最后被挑的那个——谁也不想要他。</p>
<p>那天我们分在不同队伍。我们队状态极佳，开场40分钟连进5球。大哥又开始日常「喷队友」，这次对手回怼得格外强硬，他脸色愈发难看</p>
<p>一次进攻机会，球被解围成高空球滚向边线。我离球约10米，全力冲刺想救回这球。</p>
<p>完全没料到，大哥竟从侧面全速冲来—— 我离球还有4-5米，根本想不到有人冲着我来，而不是冲着球去。</p>
<p>速度太快，我连抬手格挡都来不及，被他像橄榄球冲撞般撞飞，后脑重重着地，当场昏迷。</p>
<p>醒来时，球友们已围成一圈。我想站起，却手脚发软，倒向身旁队友。众人纷纷指责大哥，他也慌了神，坚持要陪我去急诊。</p>
<p>急诊室流程：先在护士站登记，描述症状（脑震荡、后脑着地、担心脑出血）。护士根据紧急程度分级，我坐下等待。</p>
<p>环顾四周：有发烧的、神情疲惫的，却少见外伤出血者。等了约50分钟，医生检查后判断为轻微脑震荡，应无大碍。</p>
<p>大哥或许是担心后遗症，坚持要求做脑部CT。</p>
<p>反正免费医疗，我穿上病号服，由护士用轮椅推至CT室。又等一小时出结果，医生笑着告知：「一切正常，早说没事。」</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-b34fb" hidden>
    <label for="zoomCheck-b34fb">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/me_in_hospital_gown.jpg"/> 
    
    
    </label>
</figure>

<p>急诊全程免费。</p>
<p>我注意到一位腿骨折的女士，呻吟不断，医护人员迅速为她安排了手术——就在我病床旁进行。</p>
<p>至于那位大哥？他在足球群公开道歉后，队长暂未将他踢出。但不久后，他「骂队友」的老毛病复发，真的是本性难改，终被踢出群聊。</p>
<p>一次不愉快的经历，却让我亲身体验了加拿大急诊系统的运转逻辑：按紧急程度分级处理，重伤者优先。</p>
<h2 id="结语"><span class="section-num">7</span> 结语</h2>
<p>综合我的经历，个人感受是加拿大医疗系统最鲜明的特点是「按需分级」：</p>
<ul>
<li>危及生命的急症（如骨折、心脏病）：响应迅速，治疗及时</li>
<li>慢性病与专科需求：排队漫长，但最终能获得专业治疗</li>
<li>日常小病：流程繁琐，等待时间可能超过病程本身</li>
</ul>
<p>这种设计本质上是在「效率」与「公平」间做出的权衡：确保每个人都能获得基本医疗服务，但无法保证即时性。</p>
<p>有人说，如果在加拿大（特别是 BC 省），如果你生了大病（癌症、心脏病），
你享受的是世界顶级的免费公立医疗；如果你是慢性病或骨科小毛病，你可能会面临漫长的排队。</p>
<p>但人生大多时候，我们遭遇的是小病小痛而非重大疾病。因此，多数人难以体会「顶级免费医疗」的优越，却对「漫长等待」感同身受。</p>
<p>全民免费医疗尤如「大锅饭」，要求饭菜又好吃，又免费，上菜及时还服务周到, 着实强人所难。</p>
<p><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">回到系列目录</a></p>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<h2 id="延伸阅读"><span class="section-num">8</span> 延伸阅读</h2>
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">加国旅居纪-–开篇</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/">加国旅居纪-–租房纠纷篇</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>加国旅居纪–租房纠纷篇</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/</link>
      <pubDate>Sun, 16 Nov 2025 16:18:00 -0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/</guid>
      <description>&lt;h2 id=&#34;安居之始&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 安居之始&lt;/h2&gt;
&lt;p&gt;近三年前初抵加拿大时，疫情时期的量化宽松政策余波未平，「大水漫灌」的影响尚未消退，物价高涨，住房紧缺，租金也水涨船高。&lt;/p&gt;
&lt;p&gt;人生地不熟，落脚成了头等大事。虽然登陆前看过不少攻略，但实际找起房来，困难总比想象中多。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="安居之始"><span class="section-num">1</span> 安居之始</h2>
<p>近三年前初抵加拿大时，疫情时期的量化宽松政策余波未平，「大水漫灌」的影响尚未消退，物价高涨，住房紧缺，租金也水涨船高。</p>
<p>人生地不熟，落脚成了头等大事。虽然登陆前看过不少攻略，但实际找起房来，困难总比想象中多。</p>
<p>入境前，公司刚取消疫情期间的远程办公政策，要求员工每周至少回办公室三天，这意味着住处要交通便利，尽量靠近公交或者地铁站。</p>
<p>为了找到合适的住所，我在温哥华市中心、Richmond和Burnaby都短住过 Airbnb 或酒店，实地考察。</p>
<p>经过约一周的奔波，终于在 Richmond 大统华超市附近找到一套两室一卫的公寓，面积约90多平米。</p>
<p>房东是华人，房子离地铁站仅900米，生活便利，价格也相对合理。美中不足的是楼龄已近四十五年，设施颇为陈旧。</p>
<p>考虑到当时租房市场竞争激烈，房东在我们看房前后都接待了其他租客，便迅速签下一年合约，总算安顿下来。</p>
<p>有趣的是，入住后才发现，这里离我刚落地时住的酒店只有几百米，难怪觉得周边景致眼熟。</p>
<h2 id="签约与租金"><span class="section-num">2</span> 签约与租金</h2>
<p>加拿大法律十分保护租客权益。在我所在的不列颠哥伦比亚省(British Columbia)，租客与房东签订一年期合约后，合约到期会自动转为按月续租。</p>
<p>这意味着租客可以选择按月居住，只需提前一个月通知即可搬离；而房东则不能在租期内随意驱赶租客，除非收回房屋自住。</p>
<p>合约到期后，房东也不能随意涨租。
BC省明确规定，租金年涨幅不得超过通货膨胀率。例如，2025年租金涨幅上限为3%，2026年为2.3%。具体可参考<a href="https://www2.gov.bc.ca/gov/content/housing-tenancy/residential-tenancies/rent-rtb/rent-increases#current">政府官网公告</a> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p>
<p>此外，签约时房东最多只能收取相当于半个月租金的押金。</p>
<h2 id="烦恼滋生"><span class="section-num">3</span> 烦恼滋生</h2>
<p>室友养了一只猫，当时猫还在国内。</p>
<p>我们入住前曾询问房东是否允许养猫，表示是可以养的，
还指出阳台留有之前养猫时安装的猫门，只是物业不允许，提醒我们「别让物业发现就好」。</p>
<p>小区周边设施虽便利，但这栋建于80年代的公寓缺少一些基本配置，比如室内洗衣机和烘干机。</p>
<p>我们只能使用公共投币洗衣设备，就像美剧《生活大爆炸》的剧情那样，但每层楼只有一台洗衣机和一台烘干机。
若赶上周末，洗衣服都得排队，实在不便。</p>
<p>老房子的另一个问题是鼠患。常有小老鼠通过墙内的暖气管道与墙壁的缝隙钻进来。</p>
<p>我在客厅看电视时，多次目睹它们出没，把头探出来之后又缩回去，有胆大者甚至招摇过市在我面前走过。
忍无可忍之下，我买了6个捕鼠器，放在它们必经的各个狭窄通道。</p>
<p>从此，夜里常听见「啪」的脆响，我们知道又有「小可爱」落网，次日便会看到奄奄一息的老鼠。</p>
<p>但这终究是治标不治本。为彻底解决问题，我们搬开家具，用刷锅的钢丝球塞住暖气管道与墙壁之间的缝隙。</p>
<p>钢丝球既有弹性又不易被咬烂，能牢牢堵住通道。</p>
<p>被捕鼠器抓到的老鼠数量最终定格在13只。堵住缝隙后，再未见老鼠踪影。</p>
<p>方法奏效后，我们在电梯里遇到同样受鼠患困扰的邻居阿姨，便分享了经验，邻居阿姨甚至专程上门请教。</p>
<p>虽然动手能力再次解决了问题，但这类本不该存在的困扰难免让人心烦。</p>
<p>由于公寓位置便利、生活方便，一年租约到期后，我们选择按月续租，又住了一年。</p>
<p>我平时习惯与人打招呼，渐渐和物业大叔熟络起来，没事也愿意听他在公寓前拉着我唠个20-30分钟。</p>
<p>有一次聊天时我从他口中得知，2023年我们入住时，我们的租金已是整栋公寓里他所知的最高价了。</p>
<p>2024年续租时，房东已将租金上调3.5%；2025年租约到期时，她又提出涨租3.5%。</p>
<p>然而，从2024年起，由于物价高企，经济下行引发民众不满，政府开始收紧移民政策，新移民和留学生数量大幅减少，租房市场整体下行。</p>
<p>我不少朋友都成功与房东协商降价，甚至有房东主动降价的，而我们的房东却连续两年涨价。我们终于决定另寻他处。</p>
<h2 id="争端初起"><span class="section-num">4</span> 争端初起</h2>
<p>我们按月续租，按规只需提前30天通知房东即可退租。</p>
<p>依照本地惯例，租客需清空个人物品并打扫干净房屋。</p>
<p>我们提前通知房东，因23天后即搬离，愿从押金中抵扣8天房租（相当于实际租住23天，但支付30天费用）。</p>
<p>当时室友赶着回国，回国计划又定在退租之前，时间有点太巧合了。他将个人物品搬至新公寓后，由我负责收尾。</p>
<p>搬离旧公寓后，距租约到期还有8天。我花了一整天彻底打扫卫生、清理所有垃圾，之后将钥匙归还房东。</p>
<p>几天后，房东于凌晨四点在我、室友和她的微信群中发消息，指责我们未打扫干净，声称雇了三名清洁工耗时8小时（总计24工时）清理；又说我们使用洗手间不当，导致水汽积聚、镜框掉漆，需更换镜子，瓷砖胶也已开裂；还指出室友房间猫毛堆积，对地板造成「不可逆损坏」，要求我们赔偿，并扣除全部押金，还需补足差额。</p>
<p>室友人在国内，看到消息后就转账支付了差额。</p>
<p>我知道后相当气愤，我明明花了一整天打扫，何需三名工人再干一整天？但舍友终究已经把钱转出去了，木已成舟。</p>
<p>上班后，加拿大同事日常和我打招呼，问我今天如何，我答：「不咋地，有点不爽。」</p>
<p>他便追问缘由。我如实相告：</p>
<blockquote>
<p>同事：你看到三名清洁工工作的收据了吗？</p>
<p>我：没有啊。</p>
<p>同事：你们故意损坏了房东说的那些东西吗？</p>
<p>我：当然没有。</p>
<p>同事：这很可疑了。何况你都租了两年了，这些算正常磨损（wear and tear），你可以去租赁纠纷调解法庭告她。</p>
<p>我：但我室友已经把钱转过去了。</p>
<p>同事：这确实有点麻烦，但总可以试试。</p></blockquote>
<p>上法庭？我有些心理障碍，何况室友已转钱，要回押金的几率更低了。</p>
<p>我犹豫了好几天，拖得都快没心气了。</p>
<p>没想到，前房东替我下了决心——她又在群里说我们损坏了公寓地板，之前未发现，要求我们再次赔款。</p>
<p>好吧，那只能法庭见了。</p>
<p>反正情况已不能更糟，即使输了也不会更差。</p>
<p>后来与一位朋友聊天，他家在多伦多有一套房子出租，得知他现在也在和租客打官司，还成了被告，因为他的租客在院子里烧烤，不慎把房子点了。</p>
<p>而租客退租时，他扣下押金作赔偿，租客反而把他告上法庭。</p>
<p>我听得一愣一愣——把别人房子烧了还要求退押金，这种事我可做不出来。</p>
<h2 id="提请仲裁"><span class="section-num">5</span> 提请仲裁</h2>
<p>说干就干。我立即在<a href="https://www2.gov.bc.ca/gov/content/housing-tenancy/residential-tenancies/solving-problems/tenancy-dispute-resolution">租赁纠纷调解平台</a>提交申请，花了一晚准备材料与证据。</p>
<p>申请仲裁需支付100加元，但可要求败诉方承担。</p>
<p>申请内容包括：纠纷基本信息（租客、房东联系方式、押金金额、房屋地址、租约详情）、
申诉诉求及相关证据（入住及退租时的房屋状况检查表、搬离通知方式、押金转账记录等）。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-e6ed4" hidden>
    <label for="zoomCheck-e6ed4">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/resident_in_canada_dispute_evidence.jpg"/> 
    
    
    </label>
</figure>

<p>提交后，工作人员会判断是否符合「直接裁决」(Direct Request )条件（无需听证），否则需第三方介入听证。</p>
<p>我们的案件属后者。我于6月9日提交申请，听证定在8月14日。</p>
<p>听证前，原告须以挂号信将申诉材料、证据寄给被告，告知其「你被人告了」；被告也须在截止日前以挂号信提交答辩证据。</p>
<p>使用挂号信是因为一旦签收，即使未拆封，法庭也视作已收到，被告不得以「不知情」为由缺席，或者则视为败诉。</p>
<p>我去邮局寄挂号信时，邮局的白人阿姨听到我要寄挂号信，就问我：「是要告房东吗？」</p>
<p>我心想，这类事情这么多吗？</p>
<p>她感慨听过太多房东找借口扣押金的故事，并向我解释挂号信的意义——让收件人无法抵赖「没收到信」。</p>
<p>我的证据主要是押金和每月按时缴租的记录。作为租客，我只需证明自己履行了付款义务。</p>
<p>我好奇房东会如何证明我们损坏房屋。</p>
<p>收到她的证据时，我都笑了 —— 她提交的是2021年的房屋照片，而我们2023年才入住。</p>
<p>她还声称不允许我们养猫，但之前我们反映鼠患时，她未采取任何措施，反而说「我家以前养猫时没老鼠」，还明示让室友的猫来抓鼠。</p>
<p>这一切都有聊天记录为证。</p>
<p>看来，这官司想输都难（半场开香槟了）。</p>
<h2 id="激辩律师"><span class="section-num">6</span> 激辩律师</h2>
<p>我原以为听证是双方亲至法庭，在法官和陪审团前陈述、答问，如以前香港电视演的那般。</p>
<p>实际上也的确如此，只是全程通过电话会议进行。</p>
<p>细想也合理——租约结束后，双方可能已不在本地，现场出席成本过高。</p>
<p>我和室友是原告，房东是被告。</p>
<p>但接入电话会议后，我们才意识到房东请了代理律师，她不会出席。于是在毫无心理准备的情况下，我们用英语与对方律师展开了一场激辩。</p>
<p>参会者包括：原告（我和室友）、被告（代理律师）、陪审团（人数不明，全程静默）、主持人（类似法官，负责沟通并代陪审团提问）。</p>
<p>听证开始，主持人确认各方身份、证据齐全，随后询问押金金额、纠纷缘由、每笔款项对应用途等。</p>
<p>我指出清洁费不合理：我未看到三名工人工作8小时的任何证据或收据，且我已打扫一整天，清理完所有的垃圾。</p>
<p>主持人问被告律师是否如此。律师答：「Correct and Wrong.」 称房东虽未提供收据，但「重点是确实做了清洁，重新打扫了房屋」。</p>
<p>我首次领教了律师的说话艺术——「对与错」这样完全相悖的答案也能同时说出口。</p>
<p>我接着指出被告提交2021年照片的问题：我们2023年才入住，这能证明什么？</p>
<p>律师反驳：「他们当初愿意住进来，就说明房屋当时状况良好，不然当初肯定不愿意住进来的。照片虽是两年前的，但不代表不能反映入住时的状态。」</p>
<p>主持人问我是否通知房东已搬离。我答是，并通过电子邮件告知，证据详见附件X。</p>
<p>律师立即反驳：「我从未见过这封邮件。而且用电子邮件发送法律材料是否合规？被告未主动提供邮箱，租客自行找到的地址不足为凭——谁知道那是谁的邮箱？」</p>
<p>我继续争辩镜框掉漆、瓷砖胶开裂问题：房屋已四十多年，我们住了两年，正常使用痕迹怎能算损坏？为什么还需我们赔偿？</p>
<p>律师说：「另一位租客（我室友）确实向房东转了账，这正说明他认可房东的主张，那就意味着肯定发生了什么事情嘛，否则他为何转钱？」</p>
<p>我答：「他同意转，但我不同意，他是被坑了」</p>
<p>律师立刻对主持人说：「这是租客之间的内部纠纷，不在本次仲裁范围内。他们应自行解决。」</p>
<p>仿佛一拳打在棉花上，再用力，却发现棉里藏针。</p>
<p>听完双方陈述，主持人请双方重申诉求：我们要求退还扣除8天房租后的押金及额外转账；房东要求我们赔偿地板损失。</p>
<p>主持人询问能否庭内和解。我们愿付100加元清洁费+100加元维护费；房东同意不追究地板问题。最终未达成一致，等待陪审团30天后裁决。</p>
<h2 id="裁决结果"><span class="section-num">7</span> 裁决结果</h2>
<p>30天后，我们收到长达8页的裁决书：我们赢了，但诉求未完全实现。</p>
<p>额外转账的钱不属于租约范围，视为双方资金周转，法庭不予处理。</p>
<p>押金包括半月租金+6把钥匙押金（公寓大门、房门、邮箱钥匙各两套）。我们诉求是退还相当于7天房租的押金及钥匙押金。</p>
<p>仲裁决定仅退还钥匙押金，理由如下：</p>
<ol>
<li>续租协议写明，只要钥匙完好归还，即应退还押金，不可用于抵扣维修费；</li>
<li>无钥匙无法正常使用公寓，收钥匙押金本身不合理；</li>
<li>BC省规定押金总额不得超过半月租金，房东不得以其他名目额外收取。</li>
</ol>
<p>根据BC省法律，房东唯有在获得租客「书面同意」或已有法庭裁决的情况下，方可扣留押金。</p>
<p>那么，法庭为何不支持退还剩余押金？</p>
<p>按规定，房东必须在以下两个日期中较晚者起的15天内返还押金：</p>
<ul>
<li>租赁结束日期，或</li>
<li>房东收到租客书面送达的新联系地址之日。</li>
</ul>
<p>我不知道为什么会有「房东收到租客书面送达的新联系地址」这个规定，估计是需要租客证明真的是已经搬出去了。</p>
<p>所以按照规定，租客想要拿回押金，需要告知房东自己居住的新地址。</p>
<p>经审查，法庭认定租客在申请前未以法定方式向房东有效送达书面联系地址。
本案中，无论通过租约或签署《送达地址表》，房东均未同意接受电子邮件作为送达方式。</p>
<p>现有证据不足以证明房东已收到我于2025年5月9日发送的电子邮件。</p>
<p><strong><strong>裁定结论</strong></strong></p>
<p>因此，法庭认定截至听证当日，法案第38条第1款的法定要件尚未触发，租客要求返还押金的申请为时过早(Therefore, I find that as of the date of the hearing, the requirement under section 38(1) of the Act had not been triggered, and the Tenants’ claim for the return of the security deposit was premature)。</p>
<p>换言之，因我用电子邮件而非挂号信通知新地址，房东声称未收到，所以「房东收到租客书面送达的新联系地址之日」尚未发生，房东「目前无需」返还押金。</p>
<p>即便收到通知，房东也有15天处理期。</p>
<p>因此法庭裁定我的诉求「**为时过早**」(premature)，而非「不成立」(invalid)。</p>
<p>看来，我在听证中与律师辩论的方向完全跑偏——争论清洁费是否合理、镜框是否属正常磨损毫无必要。</p>
<p>只要租客未出具「书面同意」，或法庭未裁决，房东根本无权扣留押金。任何扣款要求均属无理。</p>
<p>这意味着，无论房东以何理由扣押金，只要租客不书面同意，押金必须退还。否则，闹上法庭房东需双倍返还。</p>
<p>以下是主持人记录的双方立场与诉求：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-f86f0" hidden>
    <label for="zoomCheck-f86f0">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/tenant_landlord_position.jpg"/> 
    
    
    </label>
</figure>

<p>最后，我为何确信自己赢了？</p>
<p>因为诉讼费由房东承担（败诉方）。</p>
<h2 id="事后有感"><span class="section-num">8</span> 事后有感</h2>
<p>因法庭称退还押金的诉求「为时过早」，我还犹豫过是否再次申请仲裁。</p>
<p>但裁决书送达后，房东很快退还了钥匙押金。既如此，那就此作罢吧，便让此事了结吧。</p>
<p>吃一堑，长一智。经历此次纠纷，我现在租房时，任何问题都会立即告知房东，请其处理，不再像过去那样怕麻烦而自行解决。</p>
<p>及时沟通，既是提醒房东履行维修义务，也是提前备案：物品是自然损坏，非我人为，退租时不要再归咎于我。</p>
<p>走过一遭法庭，了解流程后，维护自身权益并不是如想象那般遥不可及，就更清楚如何保护自己作为租客的权益了。</p>
<p>权利就是这样，如果你不争取自己的权利，它可不会像馅饼一样从天而降。</p>
<p><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">回到系列目录</a></p>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<h2 id="延伸阅读"><span class="section-num">9</span> 延伸阅读</h2>
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/">加国旅居纪–开篇</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www2.gov.bc.ca/gov/content/housing-tenancy/residential-tenancies/rent-rtb/rent-increases#current">https://www2.gov.bc.ca/gov/content/housing-tenancy/residential-tenancies/rent-rtb/rent-increases#current</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>加国旅居纪–开篇</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/</link>
      <pubDate>Sun, 26 Oct 2025 20:51:00 -0700</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%BC%80%E7%AF%87/</guid>
      <description>&lt;h2 id=&#34;序言&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 序言&lt;/h2&gt;

&lt;figure&gt;
    
    
    &lt;input type=&#34;checkbox&#34; id=&#34;zoomCheck-a402f&#34; hidden&gt;
    &lt;label for=&#34;zoomCheck-a402f&#34;&gt;
    
    
    &lt;img class=&#34;zoomCheck&#34; loading=&#34;lazy&#34; src=&#34;https://ramsayleung.github.io/ox-hugo/canadiancrest-cover.jpg&#34;/&gt; 
    
    
    &lt;/label&gt;
&lt;/figure&gt;

&lt;p&gt;我曾写过《&lt;a href=&#34;https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/&#34;&gt;加拿大之初体验&lt;/a&gt;》与《&lt;a href=&#34;https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/&#34;&gt;登陆加拿大一年后的体会&lt;/a&gt;》两文，分享初抵加国的新鲜观感，后来也常有读者问起近况。&lt;/p&gt;
&lt;p&gt;时光荏苒，转眼间我在此地已步入第三个年头。 如今，我每日使用英语的频次与时长皆已超过中文。&lt;/p&gt;
&lt;p&gt;褪去了最初走马观花的新奇，生活与这个国家有了更深的交织。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="序言"><span class="section-num">1</span> 序言</h2>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-a402f" hidden>
    <label for="zoomCheck-a402f">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/canadiancrest-cover.jpg"/> 
    
    
    </label>
</figure>

<p>我曾写过《<a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a>》与《<a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a>》两文，分享初抵加国的新鲜观感，后来也常有读者问起近况。</p>
<p>时光荏苒，转眼间我在此地已步入第三个年头。 如今，我每日使用英语的频次与时长皆已超过中文。</p>
<p>褪去了最初走马观花的新奇，生活与这个国家有了更深的交织。</p>
<p>因此，我打算将视角从曾经的旁观者，逐渐切换到局内人，来分享更深入的见闻与感受。</p>
<p>鉴于话题庞杂，单篇恐过长，我计划撰写一个简短的系列，名为《加国旅居纪》。系列将涵盖诸多方面：</p>
<ul>
<li><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E7%A7%9F%E6%88%BF%E7%BA%A0%E7%BA%B7%E7%AF%87/">租房纠纷篇</a>：如何诉诸法律，解决租房争端，人生第一次法庭听证</li>
<li><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E5%8C%BB%E7%96%97%E7%AF%87/">医疗篇</a>：看门诊、急诊照CT、持续一年多的专家号随访经历</li>
<li><a href="/zh/post/2025/%E5%8A%A0%E5%9B%BD%E6%97%85%E5%B1%85%E7%BA%AA--%E8%8B%B1%E8%AF%AD%E7%AF%87/">英语篇</a>：英语从结结巴巴，到能「谈笑风生」的转变历程</li>
<li>工作篇：前「996老牛马」在美资公司的搬砖经历</li>
<li>税务篇：在「万税之国」体会「唯有死亡与纳税不可避免」</li>
<li>文化篇：种族、文化融合与激荡的观察</li>
<li>&hellip;</li>
</ul>
<p>虽胸有腹稿，但行文终归是「信马由缰」，姑且是写到哪算哪了。</p>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<h2 id="延伸阅读"><span class="section-num">2</span> 延伸阅读</h2>
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Prompt 工程的本质，是提问的艺术</title>
      <link>https://ramsayleung.github.io/zh/post/2025/prompt%E5%B7%A5%E7%A8%8B%E7%9A%84%E6%9C%AC%E8%B4%A8_%E6%98%AF%E6%8F%90%E9%97%AE%E7%9A%84%E8%89%BA%E6%9C%AF/</link>
      <pubDate>Sat, 25 Oct 2025 20:18:00 +0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/prompt%E5%B7%A5%E7%A8%8B%E7%9A%84%E6%9C%AC%E8%B4%A8_%E6%98%AF%E6%8F%90%E9%97%AE%E7%9A%84%E8%89%BA%E6%9C%AF/</guid>
      <description>&lt;h2 id=&#34;引言&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 引言&lt;/h2&gt;
&lt;p&gt;在 AI 浪潮席卷全球的今天，&amp;ldquo;Prompt Engineer&amp;rdquo;（提示词工程师）成了热门词汇。&lt;/p&gt;
&lt;p&gt;AI 爱好者热衷于分享 prompt、研究 token 控制、调试 temperature 参数。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="引言"><span class="section-num">1</span> 引言</h2>
<p>在 AI 浪潮席卷全球的今天，&ldquo;Prompt Engineer&rdquo;（提示词工程师）成了热门词汇。</p>
<p>AI 爱好者热衷于分享 prompt、研究 token 控制、调试 temperature 参数。</p>
<p>各种梗图也从 Linux 之父 Linus Torvalds 的</p>
<blockquote>
<p>Talk is cheap. Show me the code.</p></blockquote>
<p>演变成：</p>
<blockquote>
<p>Code is cheap. Show me the prompts.</p></blockquote>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-f61ab" hidden>
    <label for="zoomCheck-f61ab">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/talk_is_cheap_show_me_the_prompt.jpg"/> 
    
    
    </label>
</figure>

<p>原推: <a href="https://x.com/tunguz/status/1856045530951917763?lang=en">https://x.com/tunguz/status/1856045530951917763?lang=en</a></p>
<p>但其实， 高效与 AI 交互的核心，并不是技术黑话，而是「如何有效地提问」</p>
<p>早在 2001 年，Eric S. Raymond 和 Rick Moen 就写下了经典指南《<a href="http://www.catb.org/~esr/faqs/smart-questions.html">How To Ask Questions The Smart Way</a>》。</p>
<p>它原本是在黑客文化兴起时，为开源社区中的技术求助者而写，但其原则出奇地适用于今天的 AI 交互 ——
因为 <strong><strong>无论是求助专家还是大模型，本质上都是提供尽量多的有效信息，以期待尽快得到能解决问题的答案</strong></strong> 。</p>
<p>在我的日常工作中，无论是向同事还是其他领域的专家提问，我仍能从中汲取智慧，快速获得所需答案。</p>
<p>在 AI 新时代，我尝试把这瓶关于「提问的智慧」的旧酒，装到「Prompt Engineer」的新瓶里。</p>
<h2 id="先做功课-别做伸手党"><span class="section-num">2</span> 先做功课，别做伸手党</h2>
<blockquote>
<p>在提问前，请先搜索、阅读文档、尝试自己解决。</p></blockquote>
<p>AI 不是你的私人助理，更不是替你思考的替身。</p>
<p>如果你连问题都没搞清楚就丢一句「帮我写个程序」，模型只能瞎猜。</p>
<p>好的 Prompt 应体现你已做的努力 ：</p>
<blockquote>
<p>&ldquo;我尝试用 Python 的 requests 库抓取某网站，但返回 403 错误。我检查了网络连接，也添加了 User-Agent 请求头，但问题依旧。请问是否需要处理 Cookies 或考虑 JS 渲染？&rdquo;</p>
<p>下面是我的报错日志:
&hellip;</p></blockquote>
<p>这不仅能让 AI 更精准地定位问题，也减少了它进行无效尝试的可能 。</p>
<h2 id="描述现象-而非猜测原因"><span class="section-num">3</span> 描述现象，而非猜测原因</h2>
<blockquote>
<p>说‘鼠标光标变形了’，别说‘显卡驱动坏了’。</p></blockquote>
<p>很多人喜欢在 Prompt 里预设结论：&ldquo;我的代码有内存泄漏&quot;&ldquo;这个 API 肯定有 bug&rdquo;。</p>
<p>但 AI 没有上下文，无法验证你的假设。</p>
<p>请提供可观察的事实 ：</p>
<blockquote>
<p>&ldquo;程序运行 10 分钟后，内存占用从 100MB 升至 2GB 且未见释放。这是我的核心代码片段和资源监控数据。&rdquo;</p></blockquote>
<p>最常见的可观察事实就是日志和运行数据； 对于 UI 问题（如 CSS 渲染不符合预期），提供截图会非常有用。</p>
<p>核心在于：你提供症状，让 AI 做分析推理。</p>
<h2 id="目标导向-而非步骤导向"><span class="section-num">4</span> 目标导向，而非步骤导向</h2>
<blockquote>
<p>你想换轮胎，别只问「怎么用千斤顶」。</p></blockquote>
<p>用户常陷入「路径依赖」：执着于某个工具或方法，却忘了最终目标。</p>
<p>先说目标，再说卡点。</p>
<p>不好的提问：</p>
<ul>
<li>步骤导向：「怎么在 Excel 里用 <code>VLOOKUP</code> 匹配两列数据？」</li>
</ul>
<p>好的提问：</p>
<ul>
<li>目标导向：「我想合并两个表格，根据 ID 列匹配信息。我试了 <code>VLOOKUP</code> 但返回 <code>#N/A</code> ，已确认两列数据格式均为文本。」</li>
</ul>
<p>这样，AI 才有可能建议你改用 <code>XLOOKUP</code>, <code>Power Query</code> ，甚至直接推荐使用 Python —— 给你更好的解决方案，而非仅仅完成你指定的步骤。</p>
<h2 id="简洁-具体-结构化"><span class="section-num">5</span> 简洁、具体、结构化</h2>
<blockquote>
<p>文本长度 ≠ 信息量。</p>
<p>一段 500 行的代码，其信息密度往往不如一个精心提炼的、10 行代码的最小复现案例。</p></blockquote>
<p>大模型虽能处理长上下文，但 <strong><strong>噪声越多，有效信号越弱</strong></strong></p>
<ul>
<li>提供最小可复现示例</li>
<li>明确输入、期望输出、实际输出</li>
<li>用清晰的格式（如代码块、列表）组织信息</li>
</ul>
<p>例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">输入：[1, 2, &#39;3&#39;, 4]
</span></span><span class="line"><span class="cl">期望：全部转为整数 → [1, 2, 3, 4]
</span></span><span class="line"><span class="cl">实际：直接使用 int() 转换时报错
</span></span><span class="line"><span class="cl">问题：如何安全地转换这种混合类型的列表？
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="别先求-完整答案-要-关键指引"><span class="section-num">6</span> 别先求「完整答案」，要「关键指引」</h2>
<p>虽然 AI 的能力远超传统问答场景，但高效协作的关键并非「全盘托出」，而是「分步引导」。</p>
<blockquote>
<p>传统建议：问「哪里可以学？」比「教我全部」更高效。</p></blockquote>
<p>在 AI 时代，虽然 AI 能直接输出完整答案，但「 先给思路、再选方案、后生成代码 」的分阶段交互模式，往往更高效、更可控，也能减少&quot;幻觉&rdquo;。</p>
<p>这本质上是把 AI 当作「 协作者 」而非「答题机 」。</p>
<p>更高效的协作模式：</p>
<ol>
<li>先让 AI 阐述解决思路</li>
<li>提供2–3 个可行方案</li>
<li>对比各方案的优劣（性能、可维护性、复杂度等）</li>
<li>在人类确认方向后，再展开具体实现</li>
</ol>
<p>这种「分阶段协作」能显著减少幻觉、提升可控性，并让人类保持对关键决策的主导权。</p>
<h2 id="礼貌-plus-闭环-长期共赢"><span class="section-num">7</span> 礼貌 + 闭环 = 长期共赢</h2>
<blockquote>
<p>一句「谢谢」不费事，但能让专家更愿意帮你。</p></blockquote>
<p>虽然 AI 没有情感，但结构化的礼貌与反馈能塑造更高质量的交互 ：</p>
<ul>
<li>开头清晰说明背景，结尾表达感谢</li>
<li>如果得到帮助，可追加反馈：「按你的建议修改后，问题解决了，谢谢！」</li>
</ul>
<p>这种反馈闭环对当前的静态 AI 模型虽不直接触发在线学习，但告知模型它的解决方案有效，相当于在模拟 <a href="https://en.wikipedia.org/wiki/Reinforcement_learning_from_human_feedback">RLHF（人类强化学习）</a> 的过程 。</p>
<p>你越会提问、越会验证、越会修正，AI 在你手中就&quot;越像&quot;一个懂你的协作者。</p>
<p>这就是闭环反馈的价值。</p>
<hr>
<p>此外，给AI说「请」还有「谢谢」还能以防万一，如果 AI 以后统治人类，还有可能会因为你曾经对它有礼貌而放你一马：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-7f85c" hidden>
    <label for="zoomCheck-7f85c">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/be_polite_to_robot.jpg"/> 
    
    
    </label>
</figure>

<p>来源：<a href="https://old.reddit.com/r/comics/comments/x8bcu9/be_polite_to_robots/">https://old.reddit.com/r/comics/comments/x8bcu9/be_polite_to_robots/</a></p>
<h2 id="结语-提问是一种能力-也是一种尊重"><span class="section-num">8</span> 结语：提问是一种能力，也是一种尊重</h2>
<p>《提问的智慧》的核心不是「技巧」，而是态度 ：尊重他人的时间，尊重知识的边界，尊重问题本身的复杂性。</p>
<p>在 AI 时代，我们拥有了前所未有的「全能即时专家」，但懒惰的提问只会得到平庸的回答 。</p>
<p>真正高效的 Prompt Engineer，不是会背 prompt 的人，而是懂得如何与 AI 共建理解的人。
（尽管当前的 AI 本质上仍是一个概率模型。）</p>
<p>正如书中所言：</p>
<blockquote>
<p>Good questions are a stimulus and a gift. (好问题，本身就是一份礼物。)</p></blockquote>
<h2 id="延伸阅读"><span class="section-num">9</span> 延伸阅读</h2>
<ul>
<li><a href="http://www.catb.org/~esr/faqs/smart-questions.html">How To Ask Questions The Smart Way (英文原文)</a></li>
<li><a href="https://www.chiark.greenend.org.uk/~sgtatham/bugs.html">How to Report Bugs Effectively – Simon Tatham</a></li>
</ul>
<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E5%85%B3%E4%BA%8E%E7%A0%B4%E8%A7%A3%E5%8A%A0%E6%8B%BF%E5%A4%A7%E8%88%AA%E7%A9%BA%E9%A3%9E%E6%9C%BA%E7%BD%91%E7%BB%9C%E9%99%90%E5%88%B6%E7%9A%84%E4%B8%80%E4%BB%B6%E5%B0%8F%E4%BA%8B/">关于破解加拿大航空飞机网络限制的一件小事</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公众号同步更新，欢迎关注👻
</div>
]]></content:encoded>
    </item>
    <item>
      <title>关于破解加拿大航空飞机网络限制的一件小事</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%85%B3%E4%BA%8E%E7%A0%B4%E8%A7%A3%E5%8A%A0%E6%8B%BF%E5%A4%A7%E8%88%AA%E7%A9%BA%E9%A3%9E%E6%9C%BA%E7%BD%91%E7%BB%9C%E9%99%90%E5%88%B6%E7%9A%84%E4%B8%80%E4%BB%B6%E5%B0%8F%E4%BA%8B/</link>
      <pubDate>Fri, 10 Oct 2025 06:53:00 +0800</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%85%B3%E4%BA%8E%E7%A0%B4%E8%A7%A3%E5%8A%A0%E6%8B%BF%E5%A4%A7%E8%88%AA%E7%A9%BA%E9%A3%9E%E6%9C%BA%E7%BD%91%E7%BB%9C%E9%99%90%E5%88%B6%E7%9A%84%E4%B8%80%E4%BB%B6%E5%B0%8F%E4%BA%8B/</guid>
      <description>&lt;h2 id=&#34;序章&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 序章&lt;/h2&gt;
&lt;p&gt;前段时间，坐飞机从加拿大飞回香港，全程大概12个小时，坐的是加拿大航空(Air Canada)的飞机。&lt;/p&gt;
&lt;p&gt;有趣的是，飞机上竟然有 Wifi:&lt;/p&gt;

&lt;figure&gt;
    
    
    &lt;input type=&#34;checkbox&#34; id=&#34;zoomCheck-a931d&#34; hidden&gt;
    &lt;label for=&#34;zoomCheck-a931d&#34;&gt;
    
    
    &lt;img class=&#34;zoomCheck&#34; loading=&#34;lazy&#34; src=&#34;https://ramsayleung.github.io/ox-hugo/acwifi-connect-2.png&#34;/&gt; 
    
    
    &lt;/label&gt;
&lt;/figure&gt;

&lt;p&gt;但是 Wifi 做了限制，对于Aeroplan的会员，如果未付费，就只提供 &lt;a href=&#34;https://www.aircanada.com/ca/en/aco/home/fly/onboard/in-flight-entertainment-and-connectivity.html#/&#34;&gt;Free Texting&lt;/a&gt; 的功能，即只能使用即时通信软件，比如 Whatsapp, Snapchat，微信发送文本信息，但无法访问其他网站。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="序章"><span class="section-num">1</span> 序章</h2>
<p>前段时间，坐飞机从加拿大飞回香港，全程大概12个小时，坐的是加拿大航空(Air Canada)的飞机。</p>
<p>有趣的是，飞机上竟然有 Wifi:</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-a931d" hidden>
    <label for="zoomCheck-a931d">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/acwifi-connect-2.png"/> 
    
    
    </label>
</figure>

<p>但是 Wifi 做了限制，对于Aeroplan的会员，如果未付费，就只提供 <a href="https://www.aircanada.com/ca/en/aco/home/fly/onboard/in-flight-entertainment-and-connectivity.html#/">Free Texting</a> 的功能，即只能使用即时通信软件，比如 Whatsapp, Snapchat，微信发送文本信息，但无法访问其他网站。</p>
<p>如果想要无限制地访问其他网站，那么就是付 30.75 加元；</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-1118f" hidden>
    <label for="zoomCheck-1118f">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/acwifi.jpg"/> 
    
    
    </label>
</figure>

<p>如果想要在飞机上看视频，那么就是付 39 加元；</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-47db4" hidden>
    <label for="zoomCheck-47db4">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/acwifi_plan.jpg"/> 
    
    
    </label>
</figure>

<p>我就在想，对于 Free Texting 服务，我是否可以绕过只能使用即时软件的限制，无限制地访问其他网站呢？</p>
<p>即相当于还是免费会员，但是可以享受30.75加元付费用户的服务，反正长途漫漫，总要找点有趣的事情消磨一下12个小时的时间。</p>
<p>又因为可以使用微信的文字聊天服务，那么我还可以在天上呼叫外援来帮忙一起处理，而我的室友恰好是个安全+网络专家，
当时在家休假，我一提这个想法，他觉得好玩就一拍即合，我们就直接地空连线开搞。</p>
<h2 id="流程"><span class="section-num">2</span> 流程</h2>
<p>在飞机上选择完 acwifi.com 这个唯一的 wifi 后，就像其他需要登录的Wifi一样，会弹出一个 acwifi.com 的网页，要求验证我的 Aeroplan 会员的身份，验证通过之后即可上网。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-4b541" hidden>
    <label for="zoomCheck-4b541">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/onboard_success.jpg"/> 
    
    
    </label>
</figure>

<p>有个非常经典的软件开发面试题：在浏览器输入一个网址之后，按下回车键之后，会发生什么事情。</p>
<p>比如输入的是 <a href="https://acwifi.com">https://acwifi.com</a>, 如果只关注的网络请求部分，整个过程大概是：DNS查询 -&gt; TCP连接 -&gt; TLS握手 -&gt; HTTP请求与响应</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-c73ee" hidden>
    <label for="zoomCheck-c73ee">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/network_request_sequence.png"/> 
    
    
    </label>
</figure>

<p>我们把需要访问的目标网站当作是 github.com, 现在就来看下要怎么才能突破网络的限制，成功访问 github.com</p>
<h2 id="思路1-伪装域名"><span class="section-num">3</span> 思路1: 伪装域名</h2>
<p>既然 acwifi.com 可以访问，而 github.com 不可以访问，那么是否有可能是网络在DNS服务器做了限制，只解析白名单内的域名（即时通信的域名）</p>
<p>如果是这种情况的话，那么我是否可以修改 =/etc/host=，把我的服务器伪装成 acwifi.com, 所有的请求流量都经过我的服务器，再去请求目标网站(github.com) 如：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-88a46" hidden>
    <label for="zoomCheck-88a46">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/self-sign-certificate.png"/> 
    
    
    </label>
</figure>

<p>想法大概是我修改DNS记录，把我们的代理服务器的IP <code>137.184.231.87</code> 绑定到 <code>acwifi.com</code> 上，因为本地的 <code>/etc/host</code> 的优先级是高于DNS服务器的，然后再用证书进行自签名，告诉浏览器，这个IP 和这个域名是绑定的，你要相信它。</p>
<p>我先验证下一个想法:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">&gt; ping 137.184.231.87
</span></span><span class="line"><span class="cl">PING 137.184.231.87 <span class="o">(</span>137.184.231.87<span class="o">)</span>: <span class="m">56</span> data bytes
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">0</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">1</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">2</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">3</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">4</span>
</span></span><span class="line"><span class="cl">^C
</span></span><span class="line"><span class="cl">--- 137.184.231.87 ping statistics ---
</span></span><span class="line"><span class="cl"><span class="m">6</span> packets transmitted, <span class="m">0</span> packets received, 100.0% packet loss
</span></span></code></pre></td></tr></table>
</div>
</div><p>只是没想到，IP直接 <code>ping</code> 不通，相当于是IP大概率直接就连不上了。</p>
<p>试了下其他的著名IP，比如 Cloudflare 的CDN IP, 也是连不通:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">&gt; ping 172.67.133.121
</span></span><span class="line"><span class="cl">PING 172.67.133.121 <span class="o">(</span>172.67.133.121<span class="o">)</span>: <span class="m">56</span> data bytes
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">0</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">1</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">2</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">3</span>
</span></span><span class="line"><span class="cl">Request timeout <span class="k">for</span> icmp_seq <span class="m">4</span>
</span></span><span class="line"><span class="cl">^C
</span></span><span class="line"><span class="cl">--- 172.67.133.121 ping statistics ---
</span></span><span class="line"><span class="cl"><span class="m">6</span> packets transmitted, <span class="m">0</span> packets received, 100.0% packet loss
</span></span></code></pre></td></tr></table>
</div>
</div><p>看来这条路子是走不通的，这个思路只有满足两个条件才能走得通：</p>
<ol>
<li>texting only 的限制是在DNS 解析时做的，只有特定的域名（比如WhatsApp, 微信的域名）才会被解析 (这样的维护成本比较低)</li>
<li>网关允许任意的IP发起网络请求</li>
</ol>
<p>但实际是IP都直接拦截了，怎么伪装都没有用了，这个网络大概率维护了某个IP白名单（比如WhatsApp，微信的出口IP），
只有在白名单的IP才可以访问。</p>
<p>此外，舍友还建议我做了个额外的测试：</p>
<blockquote>
<ul>
<li>舍友：我想看看TLS有没有被拦截。万一只拦截了ICMP没拦截TLS, 那就是虚惊一场。</li>
<li>我：想得有点美好😂</li>
<li>舍友：做安全的就是要每个都试试</li>
</ul></blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">&gt; curl -Lkv https://172.67.133.121
</span></span><span class="line"><span class="cl">*   Trying 172.67.133.121:443...
</span></span><span class="line"><span class="cl">* Connected to 172.67.133.121 <span class="o">(</span>172.67.133.121<span class="o">)</span> port <span class="m">443</span>
</span></span><span class="line"><span class="cl">* ALPN: curl offers h2,http/1.1
</span></span><span class="line"><span class="cl">* <span class="o">(</span>304<span class="o">)</span> <span class="o">(</span>OUT<span class="o">)</span>, TLS handshake, Client hello <span class="o">(</span>1<span class="o">)</span>:
</span></span><span class="line"><span class="cl">* LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 172.67.133.121:443
</span></span><span class="line"><span class="cl">* Closing connection
</span></span><span class="line"><span class="cl">curl: <span class="o">(</span>35<span class="o">)</span> LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 172.67.133.121:443
</span></span></code></pre></td></tr></table>
</div>
</div><p>不出意外，IP都被封了，TLS也没法建立连接。</p>
<h2 id="思路2-53端口伪装dns"><span class="section-num">4</span> 思路2: 53端口伪装DNS</h2>
<p>在第一条路子走不通的时候，室友提供了第二条路子：尝试利用DNS服务作为突破口:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">&gt; dig http418.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;</span> &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; http418.org
</span></span><span class="line"><span class="cl"><span class="p">;;</span> global options: +cmd
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Got answer:
</span></span><span class="line"><span class="cl"><span class="p">;;</span> -&gt;&gt;HEADER<span class="s">&lt;&lt;- opco</span>de: QUERY, status: NOERROR, id: <span class="m">64160</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> flags: qr rd ra<span class="p">;</span> QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> OPT PSEUDOSECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span> EDNS: version: 0, flags:<span class="p">;</span> udp: <span class="m">4096</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> QUESTION SECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span>http418.org.			IN	A
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> ANSWER SECTION:
</span></span><span class="line"><span class="cl">http418.org.		300	IN	A	172.67.133.121
</span></span><span class="line"><span class="cl">http418.org.		300	IN	A	104.21.5.131
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Query time: <span class="m">3288</span> msec
</span></span><span class="line"><span class="cl"><span class="p">;;</span> SERVER: 172.19.207.1#53<span class="o">(</span>172.19.207.1<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> WHEN: Sat Oct <span class="m">04</span> 14:18:24 PDT <span class="m">2025</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> MSG SIZE  rcvd: <span class="m">94</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这是个好消息，说明还是有路子可以请求到外部网络的，DNS就是其中一个路子。</p>
<p>看上面的记录，说明我们查询 <code>http418.org</code> 这个网站的DNS 纪录成功，也就意味着DNS请求是成功的。</p>
<h3 id="任意dns服务器"><span class="section-num">4.1</span> 任意DNS服务器</h3>
<p>室友再随意找了个 DNS 服务器，看下这个网络是否对DNS服务器有白名单:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">&gt; dig @40.115.144.198 http418.org
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;</span> &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; @40.115.144.198 http418.org
</span></span><span class="line"><span class="cl"><span class="p">;</span> <span class="o">(</span><span class="m">1</span> server found<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> global options: +cmd
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Got answer:
</span></span><span class="line"><span class="cl"><span class="p">;;</span> -&gt;&gt;HEADER<span class="s">&lt;&lt;- opco</span>de: QUERY, status: NOERROR, id: <span class="m">58958</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> flags: qr rd ra<span class="p">;</span> QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> OPT PSEUDOSECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span> EDNS: version: 0, flags:<span class="p">;</span> udp: <span class="m">1224</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> QUESTION SECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span>http418.org.			IN	A
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> ANSWER SECTION:
</span></span><span class="line"><span class="cl">http418.org.		275	IN	A	104.21.5.131
</span></span><span class="line"><span class="cl">http418.org.		275	IN	A	172.67.133.121
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Query time: <span class="m">1169</span> msec
</span></span><span class="line"><span class="cl"><span class="p">;;</span> SERVER: 40.115.144.198#53<span class="o">(</span>40.115.144.198<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> WHEN: Sat Oct <span class="m">04</span> 14:24:25 PDT <span class="m">2025</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> MSG SIZE  rcvd: <span class="m">72</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>竟然可以使用任意的DNS服务器，机会又大了不少</p>
<h3 id="tcp查询"><span class="section-num">4.2</span> TCP查询</h3>
<p>任意的DNS服务器都能请求成功, 这就是个非常好的消息, DNS 默认是走的UDP 协议，那么走TCP 协议的DNS请求是否会被拦截呢?</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">&gt; dig @40.115.144.198 http418.org +tcp
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;</span> &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; @40.115.144.198 http418.org +tcp
</span></span><span class="line"><span class="cl"><span class="p">;</span> <span class="o">(</span><span class="m">1</span> server found<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> global options: +cmd
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Got answer:
</span></span><span class="line"><span class="cl"><span class="p">;;</span> -&gt;&gt;HEADER<span class="s">&lt;&lt;- opco</span>de: QUERY, status: NOERROR, id: <span class="m">30355</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> flags: qr rd ra<span class="p">;</span> QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: <span class="m">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> OPT PSEUDOSECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span> EDNS: version: 0, flags:<span class="p">;</span> udp: <span class="m">1224</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> QUESTION SECTION:
</span></span><span class="line"><span class="cl"><span class="p">;</span>http418.org.			IN	A
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> ANSWER SECTION:
</span></span><span class="line"><span class="cl">http418.org.		36	IN	A	172.67.133.121
</span></span><span class="line"><span class="cl">http418.org.		36	IN	A	104.21.5.131
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">;;</span> Query time: <span class="m">4679</span> msec
</span></span><span class="line"><span class="cl"><span class="p">;;</span> SERVER: 40.115.144.198#53<span class="o">(</span>40.115.144.198<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> WHEN: Sat Oct <span class="m">04</span> 14:28:24 PDT <span class="m">2025</span>
</span></span><span class="line"><span class="cl"><span class="p">;;</span> MSG SIZE  rcvd: <span class="m">72</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>DNS TCP查询也能通过！这说明飞机网络的过滤策略相对宽松，为我们后续的DNS隧道方案提供了可能性。</p>
<h3 id="53端口的代理服务"><span class="section-num">4.3</span> 53端口的代理服务</h3>
<p>说明飞机网络限制也不是完全密不透风的，我们发现这堵墙上有个「狗洞」。</p>
<p>那么我们就有了个巧妙的想法：既然飞机网关对DNS请求没有拦截，那么理论上我们可以把代理服务器伪装成DNS服务器，
暴露DNS服务的53端口，所有的请求都经过代理服务器，伪装成 DNS 请求，那么就可以绕过拦截了。</p>
<p>舍友就用 <a href="https://github.com/XTLS/Xray-core">xray</a> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>服务花费了一个小时，架设了一个暴露 53 端口的代理服务器，把配置信息通过微信发给我:</p>
<p>室友用Xray搭建的代理服务器配置包含了如下的示意配置：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;outbounds&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;proxy&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;protocol&#34;</span><span class="p">:</span> <span class="s2">&#34;vless&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;settings&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;vnext&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">          <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;address&#34;</span><span class="p">:</span> <span class="s2">&#34;our-proxy-server-domain&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;port&#34;</span><span class="p">:</span> <span class="mi">53</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;users&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">              <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;some-uuid&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;flow&#34;</span><span class="p">:</span> <span class="s2">&#34;xtls-rprx-vision&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;encryption&#34;</span><span class="p">:</span> <span class="s2">&#34;none&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="nt">&#34;level&#34;</span><span class="p">:</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">              <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">]</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;streamSettings&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;network&#34;</span><span class="p">:</span> <span class="s2">&#34;tcp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;security&#34;</span><span class="p">:</span> <span class="s2">&#34;tls&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;tlsSettings&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;allowInsecure&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;allowInsecureCiphers&#34;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;alpn&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;h2&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;direct&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;protocol&#34;</span><span class="p">:</span> <span class="s2">&#34;freedom&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;tag&#34;</span><span class="p">:</span> <span class="s2">&#34;block&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;protocol&#34;</span><span class="p">:</span> <span class="s2">&#34;blackhole&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>而我电脑上就有个 xray 的客户端，不需要额外的软件就能建立连接。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-8537d" hidden>
    <label for="zoomCheck-8537d">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/dns-server-proxy.png"/> 
    
    
    </label>
</figure>

<p>万事具备，激动人力的时刻到了，按下回车，访问 <code>github.com</code> ：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">/Users/ramsayleung <span class="o">[</span>ramsayleung@ramsayleungs-Laptop<span class="o">]</span> <span class="o">[</span>18:28<span class="o">]</span>
</span></span><span class="line"><span class="cl">&gt; curl -v github.com -x socks5://127.0.0.1:10810
</span></span><span class="line"><span class="cl">*   Trying 127.0.0.1:10810...
</span></span><span class="line"><span class="cl">* Connected to 127.0.0.1 <span class="o">(</span>127.0.0.1<span class="o">)</span> port <span class="m">10810</span>
</span></span><span class="line"><span class="cl">* SOCKS5 connect to 172.19.1.1:80 <span class="o">(</span>locally resolved<span class="o">)</span>
</span></span><span class="line"><span class="cl">* SOCKS5 request granted.
</span></span><span class="line"><span class="cl">* Connected to 127.0.0.1 <span class="o">(</span>127.0.0.1<span class="o">)</span> port <span class="m">10810</span>
</span></span><span class="line"><span class="cl">&gt; GET / HTTP/1.1
</span></span><span class="line"><span class="cl">&gt; Host: github.com
</span></span><span class="line"><span class="cl">&gt; User-Agent: curl/8.4.0
</span></span><span class="line"><span class="cl">&gt; Accept: */*
</span></span><span class="line"><span class="cl">&gt;
</span></span><span class="line"><span class="cl">&lt; HTTP/1.1 <span class="m">301</span> Moved Permanently
</span></span><span class="line"><span class="cl">&lt; Content-Length: <span class="m">0</span>
</span></span><span class="line"><span class="cl">&lt; Location: https://github.com/
</span></span><span class="line"><span class="cl">&lt;
</span></span><span class="line"><span class="cl">* Connection <span class="c1">#0 to host 127.0.0.1 left intact</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">/Users/ramsayleung <span class="o">[</span>ramsayleung@ramsayleungs-Laptop<span class="o">]</span> <span class="o">[</span>18:28<span class="o">]</span>
</span></span><span class="line"><span class="cl">&gt; curl -v github.com -x socks5://127.0.0.1:10810
</span></span><span class="line"><span class="cl">*   Trying 127.0.0.1:10810...
</span></span><span class="line"><span class="cl">* Connected to 127.0.0.1 <span class="o">(</span>127.0.0.1<span class="o">)</span> port <span class="m">10810</span>
</span></span><span class="line"><span class="cl">* SOCKS5 connect to 172.19.1.1:80 <span class="o">(</span>locally resolved<span class="o">)</span>
</span></span><span class="line"><span class="cl">* SOCKS5 request granted.
</span></span><span class="line"><span class="cl">* Connected to 127.0.0.1 <span class="o">(</span>127.0.0.1<span class="o">)</span> port <span class="m">10810</span>
</span></span><span class="line"><span class="cl">&gt; GET / HTTP/1.1
</span></span><span class="line"><span class="cl">&gt; Host: github.com
</span></span><span class="line"><span class="cl">&gt; User-Agent: curl/8.4.0
</span></span><span class="line"><span class="cl">&gt; Accept: */*
</span></span><span class="line"><span class="cl">&gt;
</span></span><span class="line"><span class="cl">&lt; HTTP/1.1 <span class="m">301</span> Moved Permanently
</span></span><span class="line"><span class="cl">&lt; Content-Length: <span class="m">0</span>
</span></span><span class="line"><span class="cl">&lt; Location: https://github.com/
</span></span><span class="line"><span class="cl">&lt;
</span></span><span class="line"><span class="cl">* Connection <span class="c1">#0 to host 127.0.0.1 left intact</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>竟然请求成功了，github.com返回成功结果啦!</p>
<p>这意味着我们真的破解网络的限制，可以访问任意的网站啦！</p>
<p>此次，我们之前并没有意识到 xray 还有此种妙用 :)</p>
<p>这里我们就利用了一个简单的思维惯性：不是所有使用53端口的服务都是DNS查询请求。</p>
<h2 id="终极思路-dns-tunnel"><span class="section-num">5</span> 终极思路: DNS Tunnel</h2>
<p>如果思路2还是无法成功，我们还有一个终极大招可以用。</p>
<p>现在网关是只通过端口是否是53来判断是否是DNS请求，
但是如果网关更严格一些，比如检查DNS请求包的内容，就会发现我们的请求是「伪装」成DNS查询请求，而非真正的DNS查询请求：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-48842" hidden>
    <label for="zoomCheck-48842">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/intercept-dns-request.png"/> 
    
    
    </label>
</figure>

<p>既然伪装的DNS请求会被拦截掉，那么我们就把所有请求都塞成DNS请求包里面，做成DNS TXT query，我真的是要查 DNS 了，只是还在里面加了些料：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-43099" hidden>
    <label for="zoomCheck-43099">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/dns-tunnel.png"/> 
    
    
    </label>
</figure>

<p>但是这个终极方案需要有一个DNS Tunnel 的客户端（比如 <a href="https://github.com/yarrick/iodine">https://github.com/yarrick/iodine</a>） 来把所有的请求都封装起来，我电脑里面没有这样的软件，所以这个就变成理论上的终极方案，实际也无法验证。</p>
<h2 id="结语"><span class="section-num">6</span> 结语</h2>
<p>长途漫漫，我和室友花费了大概4个小时的时间远程把网络限制给破解了，玩得不亦乐乎，证明我们解决问题的思路着实是可行的。</p>
<p>方案能最后实施成功，主要是归功于我室友这个网络专家，远程连线提供技术和思路支持。</p>
<p>美中不足的是，虽然我们破解了网络限制，可以访问任意网站，但是飞机上的带宽实在是太小的，
打开网页实在是费劲，所以我也没有花太多时间上网冲浪。</p>
<p>剩下的几个小时时间，我是重温了一下八十年代的经典穿越科幻电影：《<a href="https://movie.douban.com/subject/1300555/">回到未来(Back to Future)</a>》<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>三部曲，相当好看.</p>
<p>最后，我在此严正声明：</p>
<p>这种技术探索仅限于学习和研究目的，我们严格遵守相关规定和服务条款。</p>
<h2 id="后话-可以突破限速么"><span class="section-num">7</span> 后话：可以突破限速么?</h2>
<blockquote>
<p>有限速 你再怎么折腾也不可能把限速破了</p>
<p>free texting的带宽才是最大限制。再怎么bypass不解决带宽问题也没办法像付费Wi-Fi一样用😭</p></blockquote>
<p>这是来自于读者的评论，这个是真的么？</p>
<p>也不尽然。</p>
<p>其实还是有法子可以Bypass的，对于网络链路，通信的时候并不会带有「已付费用户」的业务标记信息，
所以换我来设计这套付费系统，我会在用户付费之后，把付费用户的设备唯一标记，一般是 Mac 地址加入到网关白名单中，那么所有来自该Mac 地址 的流量都可以走更高带宽的线路；</p>
<p>此外，也因为白名单的存在，即使绕过free texting 的限制，这些免费用户也无法享受更高的带宽，一举两得。</p>
<p>猜到这个原理之后，我就可以「伪装成付费用户」。</p>
<p>因为Mac 地址算是电脑自行指定的，然后用ARP 协议告诉网关的.</p>
<p>所谓的ARP（Address Resolution Protocol）协议，就是将一个IP地址解析成对应的MAC地址。而ARP协议的工作原理就是在网络内广播ARP请求:</p>
<blockquote>
<p>网关：谁的IP地址是192.168.1.100？请告诉你的MAC地址。
拥有该IP的设备：我是192.168.1.100，我的MAC地址是XX:XX:XX:XX:XX:XX。</p></blockquote>
<p>ARP协议本身没有安全验证机制——它无条件信任收到的ARP应答，我可以也告诉网关的，我的IP 地址对应的也是已经付费的Mac 地址，这样所有从我这里来的流量，都是可以享受到付费线路，这个即所谓的 ARP欺骗（ARP Spoofing）</p>
<p>最后一个问题是，怎么知道哪个是付费用户的Mac地址呢？</p>
<p>很粗暴，把网络中所有知道的Mac地址都尝试一次，如果有付费的Mac 地址，来自该Mac地址的请求绝对是能访问类似 Youtube/Netflex 这样的网站的，这样用脚本非常容易来自动化检测到。</p>
<p>我此前的伪装DNS 服务端口的方案不会对飞机网络有任何影响，也不会入侵任何的飞机系统，本质和在电脑上开个端口是53的VPN 是一样的。</p>
<p>但是ARP欺骗这个方案就很「刑」，已经入侵飞机的网络系统，我就把思路分享出来就够了，我可不想去吃免费的皇家饭 :)</p>
<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://github.com/XTLS/Xray-core">https://github.com/XTLS/Xray-core</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://movie.douban.com/subject/1300555/">https://movie.douban.com/subject/1300555/</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Telegram频道精华贴检索机器人</title>
      <link>https://ramsayleung.github.io/zh/post/2025/telegram%E9%A2%91%E9%81%93%E6%A3%80%E7%B4%A2%E6%9C%BA%E5%99%A8%E4%BA%BA/</link>
      <pubDate>Wed, 01 Oct 2025 21:55:00 -0700</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/telegram%E9%A2%91%E9%81%93%E6%A3%80%E7%B4%A2%E6%9C%BA%E5%99%A8%E4%BA%BA/</guid>
      <description>&lt;h2 id=&#34;引言&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 引言&lt;/h2&gt;
&lt;p&gt;我有时总会觉得自己是个「奇葩」：
在现在各种算法推荐大行其道的当下，我却偏偏不喜欢算法推荐，因为这种「千人千面」的模式，总让我担心自己会陷入「信息茧房」的焦虑之中，此外我也希望可以看到一些我兴趣之外的内容。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="引言"><span class="section-num">1</span> 引言</h2>
<p>我有时总会觉得自己是个「奇葩」：
在现在各种算法推荐大行其道的当下，我却偏偏不喜欢算法推荐，因为这种「千人千面」的模式，总让我担心自己会陷入「信息茧房」的焦虑之中，此外我也希望可以看到一些我兴趣之外的内容。</p>
<p>我算是很多年的 Twitter 老用户了，使用 Twitter 已经超过十年了，只是在马斯克收购 Twitter,新增了一个 &ldquo;For You&rdquo; 的推荐流之后，越来越没有兴趣看，不是吵架就是借极端观点/话题引流。</p>
<p>于是，我转向了Telegram频道，并为此打造了一个专属的「挖掘好帖」工具。</p>
<p>在最近的一年时间，我订阅了越来越多的 Telegram 频道，频道主可以向所有的订阅者广播内容，因为 Telegram 频道都是由频道主发布的，这给了我一种主动发现、主动阅读，而非被动接受算法推荐的感觉。</p>
<p>有频道主分享 twitter 上的内容时，也可以算是某种意义的「编辑精选」了。</p>
<p>当我订阅越来越多的频道之后，发现有些频道主太能聊了，一天能发几十个帖子，有些只是碎碎念，有些却是思考和精华。</p>
<p>所以我就在想，是否有个好用的挖宝藏（挖坟）工具，可以把频道的热贴，精华帖都列出来呢？</p>
<h2 id="灵感"><span class="section-num">2</span> 灵感</h2>
<p>另外一个我高频使用的网站就是 <a href="https://old.reddit.com">Reddit</a>, 不了解的 Reddit 的朋友可以理解成它是网站的百度贴吧，可以有不同的子版（subreddit），相当于不同的吧, 然后每个子版都有一个 <code>top</code> 的功能，可以按照过去一小时，过去24小时，过去一周，过去一年，历史全时段按帖子的顶贴数进行排序。</p>
<p>类似 <code>rust</code> 这个子版的历史精华帖：<a href="https://old.reddit.com/r/rust/top/">https://old.reddit.com/r/rust/top/</a></p>
<p>那么，我是否也可以对 Telegram 频道也实现类似的功能呢？</p>
<p>我可以把某个频道所有的帖子都爬下来，然后按点赞数，转发数，点击数按不同的时间段进行排序，</p>
<p>支持不同的时间段：包括一周内，一个月内，一年内，和历史所有帖子</p>
<p>相当于根据频道的订阅者的用手投票，挑选出不同时段最精华的帖子</p>
<h2 id="技术挑战"><span class="section-num">3</span> 技术挑战</h2>
<p>仔细分析之后，我发现检索频道并构建热榜是个相当有趣的技术问题，也与频道帖子本身的产品属性有关。</p>
<p>在我爬取某个频道的所有帖子后，如何与频道的最新动态保持同步更新呢？</p>
<p>毕竟像阅读数，转发数这些数据也是一直会更新的。</p>
<p>但是大部分历史的帖子的阅读数据都是不怎么会变化的，比如半年前的帖子可能就不会有人去翻看，订阅者大多只会关注最新的帖子。</p>
<p>每次都所有帖子都重新爬取一次固然可行，但是效率太低，毕竟绝大部分的帖子的数据都是不怎么变动的，怎么平衡性能与数据的及时性呢？</p>
<p>有点像超简化版本的搜索引擎问题了。</p>
<p>查询的时候要支持不同的时间段，按不同的指标进行排序，如何保证查询的性能呢？</p>
<p>总不能每次查询都重新计算一次吧，这样在帖子非常多的热点频道，就会出现查询的性能瓶颈。</p>
<h2 id="解决方案"><span class="section-num">4</span> 解决方案</h2>
<p>在仔细考量，权衡利弊之后，我取了个折衷的方案：</p>
<ol>
<li>第一次爬取某个频道时，全量爬取并索引</li>
<li>每天定时重新爬取最近30天的帖子数据，作增量更新</li>
<li>每周再爬取和索引一次全量数据</li>
</ol>
<p>就这样兼顾性能，成本以及数据及时性，又不会造成过多的重复爬取。</p>
<p>而对于查询性能，我选择了建立物化视图(material view)的策略, 每次爬取成功之后就重新计算，更新一下 material view, 耗时可能比较长，每个频道更新视图大概需要个十几秒。</p>
<p>但此后所有的查询都直接指向这个预计算好的视图，数据库还可以利用缓存优化，以空间换时间，查询性能因此得到保障</p>
<hr>
<p><span class="timestamp-wrapper"><span class="timestamp">&lt;2025-11-03 Mon&gt;</span></span></p>
<p>当索引超过1千万条数据之后，发现每次全量更新 material view 的时间去到了分钟级，并且 material view 不支持针对某个频道进行更新，只能全量更新整个视图，随着索引数据的增多，效率越来越低了。</p>
<p>因此将视图迁移回单独的表，就可以只更新指定频道的数据了。</p>
<h2 id="使用示例"><span class="section-num">5</span> 使用示例</h2>
<p>使用方法非常简单：</p>
<ol>
<li>点击链接打开机器人：<a href="https://t.me/tele_ranker_bot">https://t.me/tele_ranker_bot</a></li>
<li>在对话框中输入 <code>/rank &lt;频道链接&gt;</code> ，例如 <code>/rank https://t.me/pipeapplebun</code></li>
<li>首次检索一个频道时，机器人需要一些时间来建立索引（如下图所示），完成后会通知用户：</li>
</ol>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-ec038" hidden>
    <label for="zoomCheck-ec038">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/first_index.jpg"/> 
    
    
    </label>
</figure>

<p>完成之后就会发消息通知用户</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-c3d87" hidden>
    <label for="zoomCheck-c3d87">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/index_finish.jpg"/> 
    
    
    </label>
</figure>

<p>然后用户就可以按照点赞数，转发数，点击数查看帖子</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-8afdf" hidden>
    <label for="zoomCheck-8afdf">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/rank1.jpg"/> 
    
    
    </label>
</figure>


<figure>
    
    
    <input type="checkbox" id="zoomCheck-d526d" hidden>
    <label for="zoomCheck-d526d">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/rank2.jpg"/> 
    
    
    </label>
</figure>

<p>通过这个工具，我甚至发现了一些有趣的现象：</p>
<p>某些频道看似有十几万订阅者，但近期帖子的点击数仅有一千多，还不到百分之一，数据真实性令人存疑。</p>
<h2 id="结语"><span class="section-num">6</span> 结语</h2>
<p>有了这个频道检索工具，我终于能在一个频道里高效「挖坟」了，再也不用担心错过沉淀在时间线里的精华。</p>
<p>不管是想回顾精华，还是挖掘隐藏好帖，甚至是做简单的数据挖掘，这个机器人都能搞定，举个例子：</p>
<ul>
<li>找最近一个月点赞最多的帖子</li>
<li>看看历史上点击最高的内容有哪些</li>
</ul>
<p>这次，我总算为自己、也为可能有同样需求的你们，打造了一个称手的工具。</p>
<ul>
<li>立即体验：<a href="https://t.me/tele_ranker_bot">https://t.me/tele_ranker_bot</a></li>
<li>我的频道（菠萝油与天光墟）: <a href="https://t.me/pipeapplebun">https://t.me/pipeapplebun</a></li>
</ul>
<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
]]></content:encoded>
    </item>
    <item>
      <title>基于贝叶斯算法的Telegram广告拦截机器人（二）：上线半月的故障、挑战与优化之路</title>
      <link>https://ramsayleung.github.io/zh/post/2025/%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%AE%97%E6%B3%95%E7%9A%84telegram%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BA%8C/</link>
      <pubDate>Sat, 13 Sep 2025 14:28:00 -0700</pubDate>
      <guid>https://ramsayleung.github.io/zh/post/2025/%E5%9F%BA%E4%BA%8E%E8%B4%9D%E5%8F%B6%E6%96%AF%E7%AE%97%E6%B3%95%E7%9A%84telegram%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BA%8C/</guid>
      <description>&lt;h2 id=&#34;引言&#34;&gt;&lt;span class=&#34;section-num&#34;&gt;1&lt;/span&gt; 引言&lt;/h2&gt;
&lt;p&gt;半个月前，我发布了一个基于贝叶斯算法的Telegram广告拦截机器人 &lt;code&gt;@BayesSpamSniperBot&lt;/code&gt; (&lt;a href=&#34;https://t.me/BayesSpamSniperBot&#34;&gt;https://t.me/BayesSpamSniperBot&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;项目地址：&lt;a href=&#34;https://github.com/ramsayleung/bayes_spam_sniper&#34;&gt;https://github.com/ramsayleung/bayes_spam_sniper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;系列文章:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ramsayleung.github.io/zh/post/2025/%E4%B8%80%E4%B8%AA%E8%87%AA%E5%AD%A6%E4%B9%A0%E7%9A%84telegram%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA%E6%9C%BA%E5%99%A8%E4%BA%BA/&#34;&gt;基于贝叶斯算法的Telegram广告拦截机器人（一）：从问题到产品&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;尽管项目代码开源，但我始终以产品思维运营它。上线半个月以来，经历了故障、用户反馈与持续优化，现将这段经历分享出来。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="引言"><span class="section-num">1</span> 引言</h2>
<p>半个月前，我发布了一个基于贝叶斯算法的Telegram广告拦截机器人 <code>@BayesSpamSniperBot</code> (<a href="https://t.me/BayesSpamSniperBot">https://t.me/BayesSpamSniperBot</a>)</p>
<p>项目地址：<a href="https://github.com/ramsayleung/bayes_spam_sniper">https://github.com/ramsayleung/bayes_spam_sniper</a></p>
<p>系列文章:</p>
<ul>
<li><a href="/zh/post/2025/%E4%B8%80%E4%B8%AA%E8%87%AA%E5%AD%A6%E4%B9%A0%E7%9A%84telegram%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA%E6%9C%BA%E5%99%A8%E4%BA%BA/">基于贝叶斯算法的Telegram广告拦截机器人（一）：从问题到产品</a></li>
</ul>
<p>尽管项目代码开源，但我始终以产品思维运营它。上线半个月以来，经历了故障、用户反馈与持续优化，现将这段经历分享出来。</p>
<h2 id="上线即故障"><span class="section-num">2</span> 上线即故障</h2>
<p>没想到我的产品的第一个线上故障来得这么快，发布的时候直接不可用，把正常消息都给删了，用户在各种途径都向我反馈：</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-c7b58" hidden>
    <label for="zoomCheck-c7b58">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/delete_all_message_1.jpg"/> 
    
    
    </label>
</figure>


<figure>
    
    
    <input type="checkbox" id="zoomCheck-80e7c" hidden>
    <label for="zoomCheck-80e7c">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/delete_all_message_2.jpg"/> 
    
    
    </label>
</figure>

<p>故障的原因是我当时一直在收集垃圾广告的数据，太专注于垃圾广告数据，而忽略了收集的正常数据，
导致垃圾广告数据过多，消息都被认为是垃圾广告，被误删了。</p>
<p>通过补充大量正常消息数据，重新平衡训练集，模型逐渐恢复正常识别能力。</p>
<h2 id="挑战"><span class="section-num">3</span> 挑战</h2>
<h3 id="邮件与即时消息的差异"><span class="section-num">3.1</span> 邮件与即时消息的差异</h3>
<p>我在<a href="/zh/post/2025/%E4%B8%80%E4%B8%AA%E8%87%AA%E5%AD%A6%E4%B9%A0%E7%9A%84telegram%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA%E6%9C%BA%E5%99%A8%E4%BA%BA/">《基于贝叶斯算法的Telegram广告拦截机器人（一）：从问题到产品》</a>里面提到过：</p>
<blockquote>
<p>常见的 Telegram 广告机器人是大多是基于关键字的，通过匹配关键字进行文本拦截，非常容易被发垃圾广告的人绕过。</p>
<p>这不禁让我想起了保罗.格雷厄姆在《黑客与画家》一书在2002年介绍的情况：</p>
<p>当时电子邮件兴起，也有非常多的垃圾邮件，常见的垃圾广告拦截方式是关键字匹配+邮件地址黑名单，但是既低效也容易被绕过。</p>
<p>保罗.格雷厄姆就创造性地使用贝叶斯算法(Bayes Theorem)实现了一个广告拦截器, 效果竟然出奇地好。</p></blockquote>
<p>但产品上线之后，我发现聊天软件消息和Email虽然都是文字，还是有很大差别的:</p>
<p>Email 大多时候都是长文的，内容较长，并且大多情况，一封邮件上下文本身也很完整，就有较多的内容，较高的准确度来判断是否是广告。</p>
<p>而 Telegram, 微信这类的即时聊天软件，聊天消息大多都不长，可能把内容分成多条消息来发，就没有完整的上下文，比如:</p>
<blockquote>
<p>换U</p></blockquote>
<!--quoteend-->
<blockquote>
<p>找我</p></blockquote>
<p>单条消息很较难准确判断是否是广告，所以对即时消息做广告拦截本身就更难, 「短文本+无上下文」是NLP中的经典难题，也是本项目最大的技术挑战。</p>
<h3 id="漏删与误删"><span class="section-num">3.2</span> 漏删与误删</h3>
<p>漏删与误删是广告拦截中不可避免的矛盾权衡。</p>
<p>若想提高拦截率（召回率），就需降低置信度阈值，将更多疑似广告的消息拦截，但这也会增加误删正常消息的风险。</p>
<p>反之，若想避免误删（提高精确率），则必须提高置信度阈值，但这又会导致更多广告被漏掉。</p>
<p>在即时消息短小、上下文缺失的特性下，想同时实现零误删和零漏删几乎是不可能的。</p>
<p>权衡之下，我选择优先保证用户体验： <strong><strong>宁可漏删，不可误删</strong></strong></p>
<p>因为漏掉的广告，群友可以举报或由管理员手动删除；但误删的正常消息却无法恢复，对用户的伤害更大。</p>
<p>因此，我将拦截阈值设置为95%，即仅当模型有极高把握（&gt;95%概率）判定为广告时才会删除。</p>
<p>这虽然会放过一些疑似广告，但最大程度地保障了正常聊天不被误删。</p>
<h2 id="优化之路"><span class="section-num">4</span> 优化之路</h2>
<h3 id="自动删除消息"><span class="section-num">4.1</span> 自动删除消息</h3>
<p>产品上线之后，很快就有用户来试用了，然后其中一个用户就提了一个非常好的优化建议。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-28a2c" hidden>
    <label for="zoomCheck-28a2c">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/detect_spam_and_ban_user.jpg"/> 
    
    
    </label>
</figure>

<p>这个警告的消息不会自动删除，如果有很多人在群里发广告，那么群里就会有一堆这样的消息，也算是对群消息的污染。</p>
<p>所以用户建议:</p>
<blockquote>
<p>可以发这个提醒，但在几分钟后也把这个提醒消息删除掉</p></blockquote>
<p>我觉得这是个非常好的优化体验，因为就把这个功能给加上了，提醒消息本身会在5分钟后自动删除。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-3c682" hidden>
    <label for="zoomCheck-3c682">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/auto_delete_warning_message.jpg"/> 
    
    
    </label>
</figure>

<p>倾听用户的声音是非常重要的，他们可能就会从他们的角度提出非常好的建议。</p>
<p>但是不要盲目听从用户的建议，比如也有用户建议：</p>
<blockquote>
<p>我觉得还应该有以下功能.</p>
<ol>
<li>恢复消息, 恢复用户. (让管理员恢复误删的消息和用户)</li>
<li>主动投喂正常消息. (让管理员主动投喂一些消息. 比如, 群里面昨天 的消息, 随便选一些正常的, 投喂给机器人)</li>
</ol></blockquote>
<p>恢复消息这个功能没有太大必要，并且也不实用，因为恢复消息这个功能本身就很微妙，是直接恢复被删除的消息呢，还是重新发一条新消息？</p>
<p>如：</p>
<blockquote>
<ul>
<li>2025-09-09 10:01:00 张三: 我今天吃了鸡翅</li>
<li>2025-09-09 10:02:00 李四：鸡翅有啥好的（被误删消息）</li>
<li>2025-09-09 10:03:00 王五：人家就喜欢吃，你管得着嘛</li>
</ul></blockquote>
<p>如果是直接恢复被删除的消息，当前时间是 <code>2025-09-09 11:00:00</code> ，把消息恢复之后，还有人会手动刷历史消息，查找旧消息么？</p>
<p>Telegram客户端不一定支持会跳转被恢复的旧消息，这意味着，你恢复误删的消息，也没人看得到。</p>
<p>假如是重新发一条新消息 <code>鸡翅有啥好的</code>, 因为缺失了上下文，群里的人反而会疑惑，你在说什么。</p>
<p>解决误删问题本质是提高拦截的准确率，而非考虑如何恢复被误删消息，准确率提高了，误删就会减少，
自然就不需要考虑如何恢复消息，用户体验还会更好.</p>
<p>而主动投喂消息这个想法有点理所当然了。</p>
<p>没有任何群管理员有意愿帮忙训练这个机器人，对用户而言，他们只想要一个好用的广告拦截机器人，至于怎么开发，训练出来的，用户并不在乎。</p>
<p>所以用户不会有意愿和动力来优化这个机器人，不好用就再换一个好了，更何况，逐条消息收集的效率实在太慢太慢了，
所以我后面想出了一个比手工收集数据提效至少100倍的主意。</p>
<h3 id="过滤重复消息"><span class="section-num">4.2</span> 过滤重复消息</h3>
<p>发现人难免会有误区，总会以为别人会和自己一样，之前看到发垃圾广告的人的时候，总会觉得他们是正常的用户手工发。</p>
<p>但是最近几天发现了一些规律，有用户把同一条消息反复发，不同的群还是发同样的内容
即使是复制粘贴也难免会多个或者少个空格，然后消息被删了还一直发同样的内容。</p>
<p>此外，还有一些群，内容的聊天内容都是广告，我还很奇怪，大家都在发广告，正常用户不都跑了嘛?</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-fc97b" hidden>
    <label for="zoomCheck-fc97b">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/spam_group.jpg"/> 
    
    
    </label>
</figure>

<p>此时，我才意识到，发消息的都是机器人。</p>
<p>所以我加了个优化，计算消息内容的 hash 值，保存到数据库，并为这个字段建立索引。</p>
<p>后面检测消息的时候，先根据 hash 值查询，检查是否存在已有的消息，如果消息已经存在且已经被标记成广告或者正常消息，那么就无需再使用模型检测，可以直接返回之前的检测结果。</p>
<p>这样既提高了准确度，也优化了性能，也减少了人工干预的成本。</p>
<p>同一个用户如果在同一个群发了三条广告，那么就会自动被封禁掉，也就是相同的广告只要发三条，就会马上被自动封禁掉。</p>
<hr>
<p>为什么是计算 hash 值并为该Hash值建立索引而非对完整的文本消息建立索引？</p>
<p>因为文本消息是变长的，并且聊天消息可能会很长，对这样的 <code>TEXT</code> 建立索引会产生非常大的索引结构，占用大量的磁盘空间，每次进入查找，插入和排序操作，速度都会较慢。</p>
<p>而 hash 值是定长且非常短（相对原始消息而言），建立索引速度非常快，此外 hash 函数保证只有相同的输入一定会产生相同的输出，而即使一个字符不一致，其计算出来的 hash 值就会不一致，就能判断内容文本不一致。</p>
<h3 id="自动收集数据"><span class="section-num">4.3</span> 自动收集数据</h3>
<p>使用机器学习算法来实现一个类似的垃圾广告过滤器并不难，困难的持续收集高质量的训练数据，训练数据是非常宝贵的，毕竟数据才是核心资产。</p>
<p>而对于我这个产品来说，最难的是冷启动时的训练数据问题：</p>
<p>因为没有训练数据，模型就不准确，模型不好用就不会有人使用，自然也无法通过用户来收集垃圾广告数据，就无法良性循环，
存在一个鸡生蛋，还是蛋生鸡的问题。</p>
<p>所以冷启动时，我是手动加了非常多的 Telegram大群，然后人工在里面收集垃圾广告.</p>
<p>但是这个效率实在是太低了，我收集了快一周才只有几百条数据，
一个是我无法一直盯着各个群，另外是这种20w的大群，一般都会有几个管理员，会手工删除广告，一会没有看垃圾广告数据就会被删掉了。</p>
<p>这样手工收集数据实在在太痛苦了，我就在想有没有什么办法自动收集数据呢？</p>
<p>我本来想的是直接把我的机器人拉到这些大群里面，即使没有管理员权限无法删除消息，也可以收集数据嘛，后面才意识到 Telegram 有个规定，只有群管理员才有权限加机器人，因为我不是管理员，所以自动没有权限添加机器人。</p>
<p>但是 telegram 的客户端是开源的，他们提供了 <a href="https://github.com/tdlib/td">tdlib</a> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>这个跨平台的 C++ 库便于社区构建第三方的 Telegram 客户端，那么我自然可以使用这个库来登录我自己的账号，然后使用我的模型来过滤消息，然后把疑似广告的数据都收集起来，我再人工确认下。</p>
<p>（顺便说一下，tdlib 和 <a href="https://github.com/tdlib/telegram-bot-api">telegram-bot-api</a> <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>这两个库竟然都是同一个<a href="https://github.com/levlam">作者 Aliaksei Levin</a> <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>在维护，实在是太强了。）</p>
<p>我现在需要做的就是添加各种大群，然后程序就会自动监听并收集数据，我再人工批量确认下。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-b4635" hidden>
    <label for="zoomCheck-b4635">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/spam_group_list.jpg"/> 
    
    
    </label>
</figure>


<figure>
    
    
    <input type="checkbox" id="zoomCheck-153f7" hidden>
    <label for="zoomCheck-153f7">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/telegram_data_collector.jpg"/> 
    
    
    </label>
</figure>


<figure>
    
    
    <input type="checkbox" id="zoomCheck-cbf5b" hidden>
    <label for="zoomCheck-cbf5b">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/maybe_spam_list.jpg"/> 
    
    
    </label>
</figure>

<p>实现起来也不复杂， 200行代码就实现了这个监听消息，分析，并且收集的功能。</p>
<p>得益于这个自动化的数据收集程序，我1周不到就收集了近上万条的高质量训练数据了，效率实在高太多太多了。</p>
<p>懒惰真的是程序员的美德, 这个经历再次证明：自动化工具往往能成倍提升效率，这正是工程师价值的体现.</p>
<h2 id="推广"><span class="section-num">5</span> 推广</h2>
<p>所谓酒香也怕巷子深，没有用户使用，代码写得再好也没有意义。从产品角度，运营推广至关重要。</p>
<p>作为个人开发者，我没有大量粉丝关注，也没有营销预算，因此采用了传统的推广方式：撰写博客并在相关社区分享。</p>
<p>我撰写了两篇双语博客文章，中文版本分享至：</p>
<ul>
<li>V2EX: <a href="https://www.v2ex.com/t/1156542">https://www.v2ex.com/t/1156542</a>]]</li>
<li>Emacs China: <a href="https://emacs-china.org/t/emacs-telegram/30043">https://emacs-china.org/t/emacs-telegram/30043</a></li>
<li>微信公众号「宫孙说」：<a href="https://mp.weixin.qq.com/s/Sgq9vDqpHykwge11bwZJrw">https://mp.weixin.qq.com/s/Sgq9vDqpHykwge11bwZJrw</a></li>
<li>项目被收录到<a href="https://www.ruanyifeng.com/blog/2025/09/weekly-issue-364.html">阮一峰的科技爱好者周刊（第 364 期）</a></li>
</ul>
<p>英文版本发布至：</p>
<ul>
<li>Reddit: <a href="https://old.reddit.com/r/rails/comments/1n6p791/built_my_first_rails_project_a_telegram_spam/">Built my first Rails project: A Telegram spam blocker bot</a> <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>- 获得一些讨论</li>
<li>HackerNews：<a href="https://news.ycombinator.com/item?id=45105908">https://news.ycombinator.com/item?id=45105908</a></li>
<li>Twitter: <a href="https://x.com/foobar_ramsay/status/1967277792267247916">https://x.com/foobar_ramsay/status/1967277792267247916</a></li>
</ul>
<p>虽然推广效果有限，但这些努力为项目带来了最初的用户关注。</p>
<h2 id="成果与数据"><span class="section-num">6</span> 成果与数据</h2>
<p>上线半个月，截止到目前为止, 已经有超过80个群使用过这个机器人，用户数已经比我预期要多了:</p>
<table>
  <thead>
      <tr>
          <th>指标</th>
          <th>数值</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GitHub Stars</td>
          <td>106</td>
      </tr>
      <tr>
          <td>使用群组数</td>
          <td>83</td>
      </tr>
      <tr>
          <td>训练数据量</td>
          <td>10543</td>
      </tr>
  </tbody>
</table>
<p>最开心的是看到我自己的程序在这些群成功拦截垃圾广告，就很有成就感，证明我做的东西真的能用户解决问题。</p>

<figure>
    
    
    <input type="checkbox" id="zoomCheck-1fd72" hidden>
    <label for="zoomCheck-1fd72">
    
    
    <img class="zoomCheck" loading="lazy" src="/ox-hugo/detect_spam_success.jpg"/> 
    
    
    </label>
</figure>

<h2 id="结语"><span class="section-num">7</span> 结语</h2>
<p>这半个月的运营让我深刻体会到：产品不是代码写完就结束，而是从用户反馈中不断迭代的开始。</p>
<p>产品是需要持续运营的，而写代码只是产品生命周期的其中一个环节，甚至不是最耗费时间的环节。</p>
<p>下一步，我计划进一步优化模型准确率，并探索多语言支持，也欢迎关注我的频道或提交Issue一起讨论。</p>
<ul>
<li>开源地址：<a href="https://github.com/ramsayleung/bayes_spam_sniper">https://github.com/ramsayleung/bayes_spam_sniper</a></li>
<li>立即体验：<a href="https://t.me/BayesSpamSniperBot">https://t.me/BayesSpamSniperBot</a></li>
<li>我的频道（菠萝油与天光墟）: <a href="https://t.me/pipeapplebun">https://t.me/pipeapplebun</a></li>
</ul>
<div class="qr-container" center>
<img src="/ox-hugo/qrcode_gh_e06d750e626f_1.jpg" alt="qrcode_gh_e06d750e626f_1.jpg" class="qr-container" width="160px" height="160px" center="t" />
公号同步更新，欢迎关注👻
</div>
<h3 id="推荐阅读">推荐阅读</h3>
<ul>
<li>旅加经历
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E8%BF%99%E4%BA%9B%E5%B9%B4%E8%B5%B0%E8%BF%87%E7%9A%84%E8%B7%AF_%E4%BB%8E%E5%B9%BF%E5%B7%9E%E5%88%B0%E6%B8%A9%E5%93%A5%E5%8D%8E/">这些年走过的路：从广州到温哥华</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B9%8B%E5%88%9D%E4%BD%93%E9%AA%8C/">加拿大之初体验</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%99%BB%E9%99%86%E5%8A%A0%E6%8B%BF%E5%A4%A7%E4%B8%80%E5%B9%B4%E7%9A%84%E4%BD%93%E4%BC%9A/">登陆加拿大一年后的体会</a></li>
</ul>
</li>
<li>工具流分享
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%AE%80%E6%98%8E%E5%86%99%E4%BD%9C%E6%8C%87%E5%8D%97/">简明写作指南</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E5%86%99%E4%BD%9C%E6%B5%81/">我的写作流</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E7%94%BB%E5%9B%BE%E6%B5%81/">我的画图流：画图工具与技巧分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E6%88%91%E7%9A%84%E6%90%9C%E7%B4%A2%E6%B5%81/">我的搜索流：高效搜索经验分享</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2022/feynman_technique/">最好的学习方式：费曼学习法(Feynman Technique)</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2021/%E7%B3%BB%E7%BB%9F%E6%80%9D%E8%80%83/">系统思考：既见树木，又见森林</a></li>
</ul>
</li>
<li>思考感悟
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E7%BC%96%E7%A8%8B%E5%8D%81%E5%B9%B4%E7%9A%84%E6%84%9F%E6%82%9F/">编程十年的感悟</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E4%BB%8E%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E7%A6%BB%E7%BA%BF_%E6%88%91%E5%B8%A6%E8%B5%B0%E4%BA%86%E4%BB%80%E4%B9%88/">那些年，我从微信支付学到的东西</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/%E6%9D%82%E8%B0%88ai%E5%8F%96%E4%BB%A3%E7%A8%8B%E5%BA%8F%E5%91%98/">杂谈ai取代程序员</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2023/%E7%BD%AE%E8%BA%AB%E4%BA%8B%E5%86%85/">为什么梦想买不起，故乡回不去</a></li>
</ul>
</li>
<li>软件工程
<ul>
<li><a href="https://ramsayleung.github.io/zh/post/2025/a_philosophy_of_software_design/">软件设计的哲学</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2025/structure_and_interpretation_of_computer_programs/">一本读了八年还没读完的书</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%80_%E8%BD%AF%E4%BB%B6%E8%B4%A8%E9%87%8F%E8%AE%A4%E7%9F%A5/">测试技能进阶(一): 软件质量认知</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%BA%8C_parameterized_tests/">测试技能进阶(二): Parameterized Tests</a></li>
<li><a href="https://ramsayleung.github.io/zh/post/2024/%E6%B5%8B%E8%AF%95%E6%8A%80%E8%83%BD%E8%BF%9B%E9%98%B6%E4%B8%89_property_based_testing/">测试技能进阶(三): Property Based Testing</a></li>
</ul>
</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://github.com/tdlib/td">https://github.com/tdlib/td</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://github.com/tdlib/telegram-bot-api">https://github.com/tdlib/telegram-bot-api</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://github.com/levlam">https://github.com/levlam</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://old.reddit.com/r/rails/comments/1n6p791/built_my_first_rails_project_a_telegram_spam/">https://old.reddit.com/r/rails/comments/1n6p791/built_my_first_rails_project_a_telegram_spam/</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
