<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>梁栋烨</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://090909.top/</id>
  <link href="https://090909.top/" rel="alternate"/>
  <link href="https://090909.top/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, 梁栋烨</rights>
  <subtitle>梁栋烨的技术笔记与生活记录，分享代码、游戏、成长的点滴</subtitle>
  <title>他说</title>
  <updated>2026-07-21T13:57:21.320Z</updated>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="纪实" scheme="https://090909.top/categories/%E7%BA%AA%E5%AE%9E/"/>
    <category term="生活感悟" scheme="https://090909.top/tags/%E7%94%9F%E6%B4%BB%E6%84%9F%E6%82%9F/"/>
    <category term="感冒" scheme="https://090909.top/tags/%E6%84%9F%E5%86%92/"/>
    <category term="夏日" scheme="https://090909.top/tags/%E5%A4%8F%E6%97%A5/"/>
    <category term="食品安全" scheme="https://090909.top/tags/%E9%A3%9F%E5%93%81%E5%AE%89%E5%85%A8/"/>
    <category term="医院经历" scheme="https://090909.top/tags/%E5%8C%BB%E9%99%A2%E7%BB%8F%E5%8E%86/"/>
    <content>
      <![CDATA[<p>不知道为什么，那种熟悉的、身体被掏空的虚弱感又悄无声息地缠上来了。明明上个月底才从医院那个充斥着消毒水味道的地方逃出来，当时还在心里暗暗发誓，一定要好好保养，再也不想经历一遍排队、抽血和漫长的等待。可这才过了多久，报应似乎就来了。我躺在床上，有气无力地回溯这几天的饮食，最大的“嫌疑人”就是上个月底在楼下超市买的那根巧乐兹。当时贪图一时冰爽，在广东这潮湿闷热的天气里，咬下第一口带着脆皮巧克力的雪糕时，确实有种得救了的快感。但现在想来，那份快感大概是用现在的难受作为代价的。全身的力气像被抽走了一样，连思考问题都变得迟缓而费劲，脑袋里像塞了一团湿透的棉花，沉甸甸的，什么念头都转不动。</p><p>在意识到自己可能又中招之后，我妈翻出了家里常备的藿香正气水。我一口闷了下去，那股浓烈而辛辣的药味瞬间在口腔里炸开。但这还不算完，药劲上来后，几乎是凭着本能从床上挣扎起来，我又给自己倒了一大杯滚烫的热水。那种温热从喉咙一路流到胃里的感觉，确实带来了一丝短暂的慰藉，仿佛能冲刷掉体内的寒气。紧接着，我开始浑身止不住地冒汗，汗水先是浸湿了额前的碎发，接着连后背的衣服也黏在了皮肤上。最夸张的是，我居然感觉到汗珠从耳朵——那个平时几乎不会出汗的部位——缓缓渗出，带着一丝痒意。那一瞬间，我恍惚觉得自己不是躺在家里，而是刚在烈日下的广场上跑完了十圈，整个人从内到外都湿透了，黏腻又虚弱。</p><p>最近这段时间，我其实已经痛改前非，不再熬夜追剧或打游戏，作息规律得像一个老年人。但我显然忽略了一个致命的环节：食品安全。我天真地以为，只要避开麦当劳那种众所周知的“高危”甜品站，不去碰它们的圆筒或新地，就能安然无恙地度过这个夏天。可我万万没想到，危机就潜伏在我家楼下的社区超市里。那根静静地躺在冰柜角落里的巧乐兹，看上去是那么无辜，谁能想到它竟是我这次痛苦的“导火索”？我现在对巧乐兹已经产生了一种近乎恐惧的心理阴影，看到那个品牌标志就下意识地喉咙发紧。在目前对病因一无所知、也无法确定是否还有其他诱因的情况下，我只能先把所有的过错都归咎于它，并发誓在未来很长一段时间里，对它敬而远之。</p><p>在喝完热水和药、发了一身大汗之后，空虚的胃突然开始强烈地抗议起来，那种饥饿感来得异常凶猛，脑子里只有一个念头：想吃一大碗热气腾腾的米饭。我这才猛然想起，因为早上起得晚没什么胃口，中午竟然赌气似的连一口饭都没吃，难怪现在胃里像火烧一样难受。于是，我赶紧央求妈妈帮我盛了一大碗刚煮好的白米饭，米粒晶莹剔透，冒着诱人的香气。然而，现实是残酷的，家里冰箱空空如也，翻遍了橱柜也只找到一包榨菜能用来下饭。我体质偏热，又生活在广东这种湿气重、气候反复无常的地方，稍微吃一点辣就容易上火，进而引发喉咙痛或感冒。所以，我只能小心翼翼地挑着榨菜里不太辣的部分，就着白饭一口口往下咽。</p>]]>
    </content>
    <id>https://090909.top/2026/07/03/%E5%A4%A7%E5%AE%B6%E8%A6%81%E6%B3%A8%E6%84%8F%E8%BA%AB%E4%BD%93%E5%95%8A/</id>
    <link href="https://090909.top/2026/07/03/%E5%A4%A7%E5%AE%B6%E8%A6%81%E6%B3%A8%E6%84%8F%E8%BA%AB%E4%BD%93%E5%95%8A/"/>
    <published>2026-07-03T07:57:16.000Z</published>
    <summary>本文描述了作者在广东潮湿闷热的天气下，因食用楼下超市购买的巧乐兹雪糕后，出现身体被掏空般的虚弱感，伴随头痛、出汗等不适症状。作者回忆起上个月底刚从医院出院，发誓好好保养，却因贪图一时冰爽再次中招。在母亲帮助下服用了藿香正气水，并喝下滚烫热水，随后全身大量出汗，甚至耳朵也渗出汗珠，感觉如同在烈日下跑步。作者反思自己虽已改善作息，却忽略了食品安全：原以为避开麦当劳等知名甜品站就能安全度夏，未料到社区超市的巧乐兹成了痛苦诱因，并因此对巧乐兹产生心理阴影。在发汗后，空虚的胃引发强烈饥饿感，作者想起中午未进食，央求母亲盛来白米饭，但因家里只有榨菜且自身体质偏热，只能挑拣不辣的部分下饭。文章通过个人经历，强调了夏季饮食安全与身体保养的重要性。</summary>
    <title>大家要注意身体啊：楼下雪糕让我身体掏空，夏季食品需警惕</title>
    <updated>2026-07-21T13:57:21.320Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="游戏" scheme="https://090909.top/categories/%E6%B8%B8%E6%88%8F/"/>
    <category term="我的世界" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="游戏体验" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E4%BD%93%E9%AA%8C/"/>
    <category term="游戏攻略" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E6%94%BB%E7%95%A5/"/>
    <category term="生存模式" scheme="https://090909.top/tags/%E7%94%9F%E5%AD%98%E6%A8%A1%E5%BC%8F/"/>
    <category term="服务器" scheme="https://090909.top/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    <content>
      <![CDATA[<p>上一期我费了不少心思，盖了那个“四面是门”的小房子，但真正让我满足的，是藏在床底下的那个地下室。我甚至特意留了一个隐蔽的出口，以备不时之需。可当我隔了几个小时再上线，踏入那个熟悉的房间时，一种说不出的怪异感就缠上了我。房子还是那个房子，但总感觉有什么东西被谁动过了。我先是发现墙角那个篝火不知为何悬在半空，心里顿时咯噔一下——这绝对不是正常现象。我赶紧转头看向存放全部家当的位置，结果整个人都僵住了：那里空空荡荡，别说里面的东西了，连箱子本身都不见了！地面干干净净，就像那里从来不曾放过任何东西一样。那一刻，我脑子里“嗡”的一声，彻底傻眼了，辛辛苦苦攒下来的钻石、末影珍珠、备用工具，全没了。</p><p><img src="/assets/images/illustrations/minecraft-89.webp"></p><p>我正对着那片空荡荡的地面发愣，公屏上突然有人嚷嚷开了，问我是不是丢了什么东西。还没等我质问，那人就笑着承认了，说东西是他拿走的，箱子他也直接敲掉带走了。接着他话锋一转，抛出条件，要我加入他那个什么“社团”，还大言不惭地说只要我点了头，就把那些东西“还”给我。我当时就气笑了，这逻辑也太霸道了，那些钻石、末影珍珠，明明是大佬送我的礼物，我舍不得用辛苦攒下来的，连箱子都是我亲手合成的。他抢走再还回来，倒像成了他的恩赐？这种强盗逻辑我实在懒得纠缠。惹不起，我总躲得起吧？我把身上仅剩的工具收拾好，头也不回地离开了那个已被盯上的屋子。这次随机传送跑得很远，眼前是一片被雪原环绕的稀疏树林，至少看起来够偏僻。</p><p><img src="/assets/images/illustrations/minecraft-90.webp"></p><p>站在新落脚点，我心里越发清楚，这种允许玩家之间互相伤害甚至抢劫的服务器，本质上就是一座“黑暗森林”。在这里，没有规则约束，弱肉强食就是唯一的道理，强者可以毫无理由地对弱者发起轰炸。更何况这服务器还开着传送和领地功能，那我的地下室干脆连门都不修了，直接把生存策略从“防守”变成“隐匿”，就像是塔科夫那种“搜打撤”游戏一样。其实回想起来，从进入二区的那一刻起，我就隐隐觉得这边的氛围不太对劲，玩家素质明显不如一区，至少一区还有热心大佬带新人。罢了，既来之则安之，我只要找到自己的节奏，苟住发育，也不是没有翻身的机会。</p><p><img src="/assets/images/illustrations/minecraft-91.webp"></p><p>我再次使用了随机传送，落地后发现了一座被白雪覆盖的村庄。这简直是雪中送炭。我小心翼翼地挨家挨户搜刮干草块，把能带的物资都装进背包，还找到了一些面包和工具。最重要的是，我在这座村庄中央的喷泉旁，郑重地设立了一个名为“Village”的村庄传送点。以后只要在服务器自带的功能菜单里轻轻一点，我就能瞬间回到这里。有这座村庄在，我就不愁补给：既可以用绿宝石和村民交易装备，必要时甚至能引来铁傀儡击杀，换取珍贵的铁锭。至少在这片冰冷的土地上，眼前的村庄给了我继续玩下去的底气。</p><p><img src="/assets/images/illustrations/minecraft-92.webp"></p><p>搜刮完村庄里所有能带走的东西后，我又一次按下了随机传送的按钮。这次我传在了一片热带草原，不过眼前并非空无一物，一个冒着气泡的岩浆湖赫然出现在前方。我立刻意识到这岩浆是重要的战略资源，不管是用来烧炼矿物，还是做成陷阱保护基地，都离不开它。为了避免被其他路过的玩家顺手牵羊，我直接调用领地插件，把这一整片岩浆湖连同周围一小块地给圈了起来。现在，在我的领地内，除了我谁也不能破坏或放置方块。看着岩浆湖上腾起的热浪，我心里总算有了点底气，至少在物资上，我已经开始积累优势了。</p><p><img src="/assets/images/illustrations/minecraft-93.webp"></p><p>逛了大半圈，背包早就塞得满满当当了，我决定先撤回之前那个雪原树林的临时落脚点。我清出一块空地，把自己珍藏的几口大箱子整整齐齐地码好，然后将从村庄和岩浆湖搜刮来的物资分门别类地放进去。不过说来还是让人不放心，之前就有人提过，这个服务器存在“矿透”允许，你可以加一个矿透材质包来挖矿，这意味着别人可能利用透视材质包直接看到地下的情况。领地能挡住破坏，但能挡住视线吗？如果哪天有个懂行的玩家直接不要命开挂穿墙进来，我这个所谓的“家”在人家眼里就跟没关门一样，所有秘密都将暴露无遗。</p><p><img src="/assets/images/illustrations/minecraft-94.webp"></p><p>为了改善这令人不安的居住环境，我决定拿出从村庄里顺来的那张经典红床，以及几个熔炉，认真地把这个临时小屋装修了一下。我把墙面换成了石砖，手感敦实，瞬间有了点“家”的温馨。红床往墙角一放，那种像素风格的视觉冲击力，就是比之前那张白床看着顺眼。看着工作台、熔炉、红床这几样最古老、最熟悉的方块重新聚在一起，我恍惚间像是回到了许多年前刚开始玩《我的世界》的时候，那种简单的快乐和安全感，真让人怀念。</p><p><img src="/assets/images/illustrations/minecraft-95.webp"></p><p>可能，这一期就是我在这片服务器里的最后一期冒险了。一方面，阿普修的期末考试不理想，整个暑假都要被练习册和补习班填满，再也抽不出时间上线联机了。没有了伙伴，这个世界的乐趣就少了一大半。另一方面，这个服务器险恶的环境也确实超出了我的预期，“黑暗森林”的生存法则让我处处提防，玩得心累。而且这个服务器允许你直接购买物品，直接传送到下界、末地等其它维度，原版的那种挑战感和服务器的竞争感都没了，只剩下了不属于这个游戏的搜打撤。我想过了，以后即使再登录，大概也只会回到一区，偶尔打理一下那个最初的樱花木民宿，算是给这段冒险留个念想吧。至于二区的这些据点，就让它留在记忆里好了。</p>]]>
    </content>
    <id>https://090909.top/2026/07/03/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E8%8D%92%E7%AC%AC%E4%B8%89%E6%9C%9F/</id>
    <link href="https://090909.top/2026/07/03/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E8%8D%92%E7%AC%AC%E4%B8%89%E6%9C%9F/"/>
    <published>2026-07-02T22:47:22.000Z</published>
    <summary>本文描述了玩家在《我的世界》服务器中的一段惊险生存经历。玩家原本精心建造了带地下室的房子，但上线后却发现自己存的全部家当——包括钻石、末影珍珠和备用工具——连箱子一起被其他玩家洗劫一空。对方甚至公然在公屏上承认，并以此要挟玩家加入所谓的“社团”。玩家意识到该服务器是一个没有规则约束的“黑暗森林”，弱肉强食是唯一法则，于是选择逃离并随机传送至一片雪原树林。在新的落脚点，玩家通过搜刮雪地村庄和占领岩浆湖领地逐步积累资源，但服务器存在“矿透”漏洞，玩家可能通过透视材质包窥视地下，让领地的防守形同虚设。尽管玩家将临时小屋装修成石砖结构并布置红床与熔炉，找回了些许早年玩《我的世界》的温馨感，但最终因服务器环境险恶、好友无法上线以及游戏机制被破坏等原因，决定结束在二区的冒险，计划回归一区打理最初的樱花木民宿。全文展现了玩家在灰心与坚持之间的挣扎，以及面对恶劣生存环境的无奈选择。</summary>
    <title>服务器开荒第三期：我的世界服务器遭遇强盗，黑暗森林生存法</title>
    <updated>2026-07-21T13:57:21.324Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="梦" scheme="https://090909.top/categories/%E6%A2%A6/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="梦" scheme="https://090909.top/tags/%E6%A2%A6/"/>
    <category term="特摄剧" scheme="https://090909.top/tags/%E7%89%B9%E6%91%84%E5%89%A7/"/>
    <category term="校园回忆" scheme="https://090909.top/tags/%E6%A0%A1%E5%9B%AD%E5%9B%9E%E5%BF%86/"/>
    <category term="友情" scheme="https://090909.top/tags/%E5%8F%8B%E6%83%85/"/>
    <content>
      <![CDATA[<p>我回到了那所学校，一切熟悉得令人恍惚。阳光斜斜地穿过老榕树的枝叶，在教学楼走廊上洒下斑驳的光影，我甚至能精准地预判每一片光斑移动的轨迹。迎面走来的黄洋还是那副吊儿郎当的模样，校服拉链只拉到胸口，露出里面皱巴巴的T恤——和我记忆里分毫不差。我们自然而然地并排走向教室，仿佛从未分离过。可我心里清楚，这份“自然而然”背后藏着怎样不可思议的秘密：我分明是从未来回溯而来的人，但此刻的时间线严丝合缝地嵌入了我过去的某一天，没有任何破绽可言。连课桌上那道我用圆规尖刻下的划痕都还在原处，甚至深浅都一模一样。更奇妙的是，那些本该在不同年级才相识的朋友，此刻竟都齐聚在这同一间教室里，像命运刻意拼凑的拼图。当上课铃响起时，我甚至下意识地想抢在老师之前说出那句口头禅，却在张嘴的瞬间猛然刹住——我不能暴露任何超前知晓的痕迹，必须像真正的“过去的我”那样，带着新鲜的好奇与懵懂，重新经历这一切。</p><p>我和黄洋的关系，从来不需要刻意维系就能自然而然地热络起来。以前上学时我们就形影不离，体育课躲在树荫下分喝一瓶汽水，晚自习传阅同一本漫画，连挨训都是一前一后地被叫进办公室。如今在这个重启的时空中，我们依然像磁铁的两极般迅速靠近。我记得他痴迷假面骑士到了走火入魔的程度——书包里永远揣着角色卡片，笔记本边角画满了变身动作分解图。而现在，我也早已不是当年那个对特摄剧一知半解的旁观者了。这些年我恶补了所有平成骑士的设定集，甚至钻研过编剧访谈中关于世界观构建的草稿。于是当黄洋随口提起某个争议性设定时，我立刻接上了话茬：“其实那个‘镜世界’的设定灵感，据说是来自《爱丽丝镜中奇遇记》和日本都市传说……”黄洋的眼睛瞬间亮了，那种找到同类的惊喜几乎要从他咧开的嘴角溢出来。我们就这样蹲在教室后排，用课本挡住老师的视线，从骑士装甲的材质构成一直聊到怪人诞生的哲学隐喻，。</p><p>来到这个新环境后，我的成绩像被施了魔法般稳步攀升，排名总是稳稳地挂在班级前列。倒不是我突然开窍变聪明了，而是这里的试题风格恰好踩中了我擅长的那根弦——它们不考死记硬背的细碎知识点，更侧重逻辑推演和综合运用，这让我原本那些零散的知识储备被彻底激活了。每当试卷发下来，看着那些熟悉的题型框架，我甚至能预判出题人的思路走向。成绩单拿回家时，父亲紧锁的眉头会肉眼可见地舒展开来，原本随时可能引爆的争吵也就此消弭于无形。那种家庭氛围的冰层裂开又缓慢愈合的感觉，是我在这个时空里最隐秘的安心来源。至于其他同学的排名起伏、老师的表扬或批评，都像隔着一层毛玻璃般模糊不清。我懒得去计较那些虚名，只要能维持住这份成绩带来的平静，让父亲在饭桌上不再摔筷子砸碗，让母亲不用红着眼眶躲进厨房，我就心满意足了。毕竟经历过未来那些鸡飞狗跳的日子，我比谁都清楚，这份用分数换来的安宁有多么脆弱，又有多么珍贵。</p><p>下楼时，我和黄洋还在为《龙骑》里那条“契约兽是否会反噬契约者”的设定争得面红耳赤。我们的脚步踏在台阶上发出咚咚的闷响，回声在狭窄的楼道里来回碰撞。这座学校的建筑结构充满时间错位的诡异感——高层是去年刚落成的新教学楼，玻璃幕墙在阳光下闪闪发亮，电梯间还散发着装修残余的化学气味；可一到低层，就瞬间切换成了世纪初的老旧风格，水磨石地面被无数双鞋底磨得光滑发亮，墙角的踢脚线剥落出深浅不一的灰绿色。但奇怪的是，这种新旧交叠并没有产生预想中的割裂感，反而像年轮般自然融合。课间时低年级的学生在高层的连廊追逐嬉闹，笑声透过落地窗传下来；而底层老教室里的读书声则带着某种沉静的韵律，两种声响在空中交汇，居然织成一种奇特的校园交响。也许这才是一所学校真正的生命力所在——它不靠光鲜的外表唬人，而是靠这些跨越年代的鲜活气息，让每个角落都充盈着热腾腾的人间烟火。</p><p>正当我试图用骑士装甲的“反射镜面”理论来论证设定合理性时，黄洋毫无预兆地一拳挥了过来。那一瞬间拳风擦过我的耳侧，带起一阵细微的凉意。我下意识地偏头躲闪，身体比大脑更快地做出了反应。黄洋的瞳孔里闪着某种近乎狂热的光芒，他居然真的相信那个特摄世界可以穿透屏幕降临现实——这家伙入戏太深了！我顺手抄起墙角的塑料板凳，将口袋里刚发的社团宣传单卡在板凳的夹角处，模仿着剧中经典的动作，大喊一声“强袭降临”！宣传单被夹住的瞬间发出“啪”的脆响，倒真有几分神似召唤兽出场的前奏。“偷袭虎是吧？”黄洋咧嘴笑着认出了这是偷袭虎，眼中斗志更盛。而我早已刹不住那股冲劲，拖着板凳划出一道弧形轨迹——当塑胶凳面实实在在地糊上黄洋面门时，我听到他闷哼一声，随即整个人仰面倒向地面。他倒地时后脑磕在台阶边缘的声响闷得吓人，我手中的板凳也脱手滚落，在寂静的楼道里弹跳了好几圈。</p><p>视野突然像被调换了频道般急剧闪烁，周围的教学楼、散落的宣传单、倒地的黄洋都在高速褪色消融。等到焦距重新聚合时，我看见的是自家卧室熟悉的天花板，上面还有些灰黑色斑点。窗外不再是梦里那个明媚的午后，而是凌晨四五点那种将亮未亮的灰蓝色。我仰面躺在床上，睡衣被汗浸得潮乎乎的黏在后背。梦境里那场激烈的打闹、黄洋倒地的闷响、楼道里的回声，都还残留在神经末梢上微微发颤。我盯着天花板愣了好一会儿，混乱的时间线才慢慢理清——梦里的我始终身处“下午放学”后的校园，阳光是斜的，影子是长的，所有人都还在课后的喧闹里。而现实中的我，其实早已离开了学校，是从上半夜睡到了天亮前。这两个时间点毫无交集，梦里那个下午的我是全然不知自己正躺在深夜的床上做梦的。直到此刻彻底醒来，窗外的天色才替我补上了那道时间裂隙——原来我是在梦里过完了别人的下午，又醒在了自己的凌晨。</p>]]>
    </content>
    <id>https://090909.top/2026/07/03/%E6%88%91%E5%92%8C%E5%A5%BD%E6%9C%8B%E5%8F%8B%E8%AE%A8%E8%AE%BA%E9%BE%99%E9%AA%91/</id>
    <link href="https://090909.top/2026/07/03/%E6%88%91%E5%92%8C%E5%A5%BD%E6%9C%8B%E5%8F%8B%E8%AE%A8%E8%AE%BA%E9%BE%99%E9%AA%91/"/>
    <published>2026-07-02T22:15:26.000Z</published>
    <summary>本文描述了主人公以时空回溯者的身份重返过去校园的离奇经历。他精准地预判着每一片光斑的轨迹，与老朋友黄洋自然而然地重聚，并发现就连课桌上的划痕都分毫不差，但本该在不同年级相识的朋友却齐聚一堂。在与黄洋相处时，他凭借对假面骑士设定的深入了解引发对方共鸣，两人从骑士装甲材质聊到哲学隐喻。成绩的稳步提升不仅源于试题风格恰好契合他的能力，更带来了家庭氛围的缓和，让争吵消弭于无形。校园建筑呈现出高层现代与底层老旧交错的独特风貌，新旧气息却和谐共生。正当主人公与黄洋为特摄设定争执并模仿剧中打斗时，黄洋一拳挥来，他抄起塑料板凳反击，却不慎将对方击倒——黄洋后脑磕在台阶上发出闷响。紧接着视野急剧闪烁，一切褪色消融，主人公惊醒后发现躺在自家床上，窗外是凌晨灰蓝色的天光。原来整个下午的校园经历只是一场由“下午放学”场景构成的梦境，而现实中的他早已离开校园，在深夜睡到了天未亮。这种时间线的割裂与梦境嵌套，揭示了记忆与现实的微妙错位。</summary>
    <title>我和好朋友讨论龙骑：校园重温特摄友情，却终究只是一场梦</title>
    <updated>2026-07-21T13:57:21.322Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="梦" scheme="https://090909.top/categories/%E6%A2%A6/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="写作风格" scheme="https://090909.top/tags/%E5%86%99%E4%BD%9C%E9%A3%8E%E6%A0%BC/"/>
    <category term="博客活动" scheme="https://090909.top/tags/%E5%8D%9A%E5%AE%A2%E6%B4%BB%E5%8A%A8/"/>
    <category term="技术写作" scheme="https://090909.top/tags/%E6%8A%80%E6%9C%AF%E5%86%99%E4%BD%9C/"/>
    <category term="文字园" scheme="https://090909.top/tags/%E6%96%87%E5%AD%97%E5%9B%AD/"/>
    <content>
      <![CDATA[<p>很明显，现在我妈妈开了一家餐厅，餐厅的日常经营已经步入正轨，每到饭点，油烟与锅铲碰撞的声响便交织成这片街角最熟悉的背景音。虽然为了追求某种原始粗犷的工业风格，墙体主要保留着水泥原本的灰扑扑的肌理，没有贴瓷砖，也没有刷上柔和的墙漆，但这丝毫没有影响客人们的兴致。傍晚时分，暖黄的灯泡一盏盏亮起，光线洒在水泥墙上，反而映出一种踏实而接地气的氛围。常有三五成群的食客围坐在餐厅中央那张厚重的大圆桌旁，桌上摆满了一盘盘冒着热气、油光锃亮的炒菜与烧烤——这就是典型的大排档风味，不拘小节，却最抚凡人心。</p><p>他们一边大口吃着麻辣鲜香的菜肴，一边举杯畅饮，谈笑声、猜拳声、还有后厨传来的爆炒滋啦声混杂在一起，让这间以水泥为底色的空间充满了鲜活的人间烟火气。而我，就住在餐厅楼上的老式居民房里，与卡瑟布尔的家相隔不过一条窄巷。卡瑟布尔是我在博客圈认识多年的挚友，我们因文字而结缘，从最初的互关、留言，到后来交换稿件、讨论段落结构，不知不觉已走过好几个春秋。如今我们都在同一座小城里生活，隔得近了，便时常约在餐厅打烊后的深夜，就着妈妈留给我们的一碟花生米和两瓶汽水，并肩坐在窗边，打开笔记本电脑，一块儿敲击键盘、雕琢词句。在这座并不喧嚣的小城，能有这样一位随时可以面对面探讨写作的朋友，于我而言，是一种踏实的幸福。</p><p>我参加了一个叫“文字园”的博客共创活动，消息刚发出来的时候，连我自己都有几分意外。说到这里，想必会有朋友忍不住发问：为什么是文字园？你以前不是从不参与这类集体活动的吗？为什么不是那个在圈内名气颇大的“十年之约”博客接力？为什么不是更偏向流量接力的“开往”计划？又为什么不是那些体量庞大、运营成熟的通用博客平台所发起的征文比赛呢？事实上，我向来对各式各样的博客集体活动抱有本能的疏离感，总觉得写作是件极其私人的事，一旦被统一的话题或限定的节奏牵着走，那股子从心底涌出的表达欲就容易变得干瘪。我更喜欢按自己的步调，在无人打扰的深夜独自面对空白文档，想到哪儿写到哪儿。</p><p>因此，当朋友们得知我竟然破天荒地交了一篇稿子给“文字园”时，纷纷瞪大了眼睛，像是看到了什么稀罕事。连我自己也承认，这算是一次破戒——但究其原因，或许是因为“文字园”在众多活动中显得有些特别。它不像其他活动那样强调严格的连续打卡、组队互评或是长周期的主题创作，它的形态更松散，也更接近一个纯粹的投稿窗口。你只需将完成的作品投递过去，剩下的审核与发布便全由他们负责。这种“交了稿便不添麻烦”的模式，让我觉得更像是一次普通的投稿尝试，而非一场需要时刻紧绷神经的社交仪式。于是，我抱着试一试也无妨的心态，从电脑文件夹里翻出了一篇旧文，简单修改了几个错字，便像扔出一封漂流瓶一般，将它投向了“文字园”的邮箱。</p><p>之后我便没再多想，转身继续忙餐厅的杂务去了。按照“文字园”的规则，你完全可以将自己的稿件同时投递到两个地方：一份留在你自己的个人网站上，作为你独立博客的日常更新，让那些习惯定期来访的老读者能第一时间读到；另一份则交由“文字园”的编辑团队，他们会将你的文章排版成统一的视觉风格，发布在他们的官方社交媒体账号上，并配上精心挑选的插图或背景音乐，让那些关注“文字园”的粉丝群体也能看到你的作品。这样一来，你的文字便拥有了两条传播路径——既能安稳地栖息在你自己的网络小窝里，供熟客细品，又有机会借由“文字园”已有的受众池，触碰到更广阔的、与你素未谋面的读者。</p><p>这原本是一种互惠共赢的良性模式，既为创作者提供了曝光窗口，又为“文字园”补充了内容来源。然而，我的情况却在这套流畅的流程中，生出了一点尴尬的波折。当“文字园”如期发布了那期共创视频，我正满心期待着看到自己的文字以声画结合的形式呈现出来时，却发现评论区里逐渐热闹起来，而其中相当一部分读者的发言，末尾都带着一个“@”符号，后面紧跟着我的博客 ID。他们急切地提醒我：“博主，我发现有个叫‘文字园’的账号拿了你的文章，你是不是被盗稿了？”那条被点赞置顶的留言里，甚至附上了我原文的链接，语气里满是替我打抱不平的焦急。</p><p>那一刻，我握着手机哭笑不得——明明我本人就在这份共创名单之中，是投稿者之一，为何大家非要这样郑重其事地艾特我来“维权”呢？想来想去，大概是因为他们并未在视频文案中仔细查看作者标注，又或是我的文风与他们印象中的我有些许出入，以至于产生了“被冒名”的误会。但这份误解背后那份沉甸甸的、来自素未谋面的读者的关心，却又让我在无奈之余，心底微微发热。其实，当初把文章投到“文字园”的时候，我压根没抱什么期望。那阵子我正被妈妈餐厅里新菜单的定价搞得焦头烂额，每天算账算到深夜，连打开博客后台的精力都没有。</p><p>之所以会从旧稿堆里翻出那篇东西，纯粹是因为它字数合适，又刚好符合那一期“技术与生活”的主题，投出去不过是完成任务般顺手一填罢了。我甚至没再仔细通读一遍，便点下了发送键。然而命运有时就爱开这种玩笑——那篇被我视作“凑数之作”的稿件，竟然真的从众多投稿中脱颖而出，被“文字园”的编辑选中，作为那一期视频阅读的主打内容来播出。当视频上线、播放量开始跳动的那一刻，我第一反应不是欣喜，而是错愕。我反复点开视频，确认文末确实署了我的名，又拉到评论区看读者的反馈，只见密密麻麻的留言里，不少人夸赞文章的角度新颖，将枯燥的 Git 操作讲得生动有趣，甚至有人表示因为这篇文而第一次弄懂了分支合并的逻辑。</p><p>可越是看到这些好评，我内心那股说不清道不明的别扭感就越是强烈。因为只有我自己清楚，那篇文章里涉及的几个关于 Git 底层存储机制的技术细节，我当初写的时候只是凭印象一笔带过，事后并没有亲自搭建环境去验证过其准确性。它就像一栋外观还看得过去的毛坯房，梁柱之间却藏着几颗松动的螺丝钉，随时可能让住在里面的人一脚踏空。我从未想过这样一篇带着技术瑕疵、写时匆忙、改时敷衍的文章，居然能轻松通过编辑的审核，还收获了如此热烈的反响。每当看到新的点赞或收藏提醒，我脑海里蹦出的第一个念头不是开心，而是心虚——万一那些被吸引来的读者中，恰好有深谙 Git 源码的硬核开发者，一眼看穿我随手写下却未经证实的推断。</p><p>那我岂不是在众目睽睽之下，成了一个靠半成品博眼球的写作者？卡瑟布尔就坐在我对面，见我盯着手机屏幕上的播放数据发呆、眉头越锁越紧，便放下手里那罐已经见底的汽水，用指节敲了敲桌面，把我从沉思中拽了回来。他歪着头，语气带着他一贯的不紧不慢：“你看啊，你平时口口声声说不参加博客活动，这回难得破例投了一篇，结果不但被选上了，播放量还比你自己博客上任何一篇文章都要高——这本身不就是个挺有意思的反差吗？你在这儿纠结那些播放量和影响力干什么？它们又不咬人。”他说着，往椅背上一靠，目光落在天花板上那盏微微晃动的吊灯上。</p><p>他继续开导我：“再说了，万一那些看了视频的人，真被你这篇文章勾起了兴趣，顺着网线摸到你的博客主页，发现了你真正用心打磨、反复考证过的那几篇更扎实、更优秀的长文呢？那你这篇‘最差’的文章，反而成了一块敲门砖，替你把读者引到了更好的作品面前——这笔账怎么算都不亏啊。”他的话像一杯温开水，缓缓流过我心口那块紧绷的疙瘩，似乎有那么一瞬间，我真觉得自己过于钻牛角尖了。然而，当我再次低头刷新评论区，那些新增的、带着技术术语的追问一条条跳出来时，那股被注视着的感觉又像潮水般涌了上来——比刚才更清晰、更具体。</p><p>我仿佛能看见，此刻正有无数双眼睛隔着屏幕盯着我的名字，其中尤其不乏那些深耕技术领域多年的老手，他们的目光冷静而挑剔，仿佛正拿着放大镜逐字审视我文中的每一处细节，随时准备指出那个被我侥幸蒙混过去的漏洞。这种感觉不是热烈的追捧，而更像一场无声的考试，考场寂静得只能听见自己的心跳。</p>]]>
    </content>
    <id>https://090909.top/2026/07/03/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%8F%82%E5%8A%A0%E6%96%87%E5%AD%97%E5%9B%AD%E6%B4%BB%E5%8A%A8/</id>
    <link href="https://090909.top/2026/07/03/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%8F%82%E5%8A%A0%E6%96%87%E5%AD%97%E5%9B%AD%E6%B4%BB%E5%8A%A8/"/>
    <published>2026-07-02T21:56:06.000Z</published>
    <summary>本文描述了作者作为 1 位餐饮业主的儿子，在妈妈经营的餐厅楼上生活，并与挚友卡瑟布尔因博客结缘、常在深夜探讨写作的故事。作者向来对博客集体活动保持疏离，却破例参加了名为“文字园”的博客共创活动，从旧稿中翻出 1 篇关于 Git 技术细节的文章投递出去。该文被编辑选中并作为视频主打内容发布，意外收获较高播放量与好评，但评论区许多读者误以为作者被盗稿，纷纷艾特其 ID 提示维权。作者内心充满矛盾：一方面感激读者的关心，另一方面深知文章中的技术细节未经实际验证，存在瑕疵，担心被硬核开发者识破。好友卡瑟布尔开导作者，指出这篇“最差”文章可能成为敲门砖，吸引读者去发现作者更用心的作品。然而，当作者看到评论区不断涌现的技术追问时，仍感到如临考场般的压力。文章展现了创作者在意外走红后对作品质量的深层焦虑，以及面对读者关注时的复杂心境。</summary>
    <title>记参加文字园活动：一篇有瑕疵的 Git 文章，入选文字园让我心虚</title>
    <updated>2026-07-21T13:57:21.327Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="杂谈" scheme="https://090909.top/categories/%E6%9D%82%E8%B0%88/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="使用体验" scheme="https://090909.top/tags/%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/"/>
    <category term="macOS" scheme="https://090909.top/tags/macOS/"/>
    <category term="Linux" scheme="https://090909.top/tags/Linux/"/>
    <category term="Windows 广告" scheme="https://090909.top/tags/Windows-%E5%B9%BF%E5%91%8A/"/>
    <content>
      <![CDATA[<p>我之前不是写过一篇文章，吐槽过我的旧电脑升级 Win11 后的各种问题吗？那台电脑本来运行 Win10 还算流畅，结果一升级到 Win11，开机速度直接翻倍——不是变快，是变慢了一倍。任务栏时不时卡死，右键菜单要等两秒才弹出，连资源管理器都学会了“未响应”这门艺术。更别提那强制合并的任务栏图标，对多任务操作简直是灾难。哪怕后来我换了性能强劲的游戏本，按理说硬件足够碾压任何系统，可我依然下意识地第一时间安装了其他系统，最次也是受不了 Linux 那无休止的驱动折腾和命令行依赖后，又灰溜溜地转回了熟悉的 Win10 系统。那种感觉就像是被 Windows 伤了心，却又找不到完美替代品的游牧民族。</p><p>直到现在，我终于用上了 macOS，才算暂时找到了一个安静而稳定的栖身之所。深夜的时候，人总是容易陷入一种放空的状态，手指机械地滑动着屏幕，刷着一个又一个短视频。就在这样的时刻，我刷到了一个标题颇有吸引力的视频，内容是关于如何关闭电脑上那些烦人的广告。视频里的博主神情十分正式，对着镜头一本正经地说——如果你升级了 Win11（你接下来是要讲性能优化的问题，还是系统卡顿的解决方案？）——那么你的锁屏界面、搜索界面、小组件界面都会出现广告，而我现在就来教你如何把它们一个个关闭掉。他的语气像是在处理一件严肃的系统底层问题，而我则抱着一种“我倒要看看有什么高招”的心态继续看了下去。</p><p>出乎意料的是，作为一个前 Linux 用户、现 macOS 用户，我大多数时间都活在 UNIX 那种干净、克制、命令行至上的温床里，脑子里早已习惯了“系统就是工具”的朴素认知。当我看到那个标题时，第一反应居然是你是不是要教我怎么调优系统性能、关闭后台进程、修改注册表来提升响应速度——完全是 Linux 时代留下的“性能焦虑”后遗症。我完全没想到电脑里居然有“广告”这一层，这个词出现在操作系统语境里，对我来说就像是在图书馆里听到广场舞音乐一样荒诞。它真的是在我的意料之外，以至于我愣了几秒才反应过来：哦，原来 Windows 用户日常还要对抗这种东西。</p><p>倒不如说，为什么我的电脑，我花钱买的电脑，为什么要有广告在这里？这明明是一台硬件设备加上一份正版操作系统的组合，我付过钱了，我是它的主人，而不是它用来向第三方展示我注意力的橱窗。我以前用 Windows 的时候，怎么就没觉得这些广告冒犯和吵闹呢？现在回头想想，那时候的我甚至觉得这些推送是一种陪伴——就像是一个人在空荡荡的电脑世界里，突然有推送弹出来告诉你天气、新闻或者某款游戏在打折，像是透过一扇窗户看到了外面的热闹人间。那种孤独中的一丝喧嚣，反而让我觉得自己还连着网、还属于这个数字社会。</p><p>但我用不超过 10 秒的时间就接受了这个事实，就像以前的自己一样，习惯性地选择了“算了”。老实说，我对那些突然弹出来的广告弹窗，尤其是当你聚精会神写代码、剪视频或者打游戏打到关键时刻时，屏幕角落突然蹦出一个闪烁的推销界面，那种感觉真的是一种赤裸裸的冒犯和侵入——像是在你专注的脑海中硬塞进一块广告牌。但如果只是软件界面、网站页面里内置一些广告横幅，我顶多会觉得这是他们要维持运营、获取收益的正常手段，可以理解，也可以忽略。可操作系统不一样，它是所有软件运行的基础，是我与电脑交互的底层语言，不该成为广告的分发渠道。</p><p>我算是知道 UNIX 系统的好处了，那种“没有消息就是好消息”的设计哲学，让我终于能在数字世界里获得一片安静。虽然目前接受 Linux 还需要一个 Wine 的时间——毕竟有些 Windows 专属软件还是离不开，得靠兼容层去跑，时不时还要忍受配置失败的崩溃感——但总归是有个好看的界面和一片自由的、让人安静的空间。不会有人在锁屏时推荐你玩游戏，也不会在搜索栏里暗示你下载某款软件。我可能现在唯一能接受的广告，就是打开某个开源软件后，屏幕上缓缓弹出的那个“为本项目捐赠”的提示窗吧，因为它真诚、克制，而且你可以选择关闭，也可以选择感激。</p>]]>
    </content>
    <id>https://090909.top/2026/07/03/%E5%86%8D%E5%AE%A1%E8%A7%86-Windows-%E8%AE%BE%E8%AE%A1/</id>
    <link href="https://090909.top/2026/07/03/%E5%86%8D%E5%AE%A1%E8%A7%86-Windows-%E8%AE%BE%E8%AE%A1/"/>
    <published>2026-07-02T17:10:05.000Z</published>
    <summary>本文介绍了作者从 Windows 10 升级到 Windows 11 后遭遇的系统卡顿、任务栏卡死、资源管理器无响应等问题，以及强制合并的任务栏图标对多任务操作的负面影响。即便后来换用性能强大的游戏本，作者仍倾向于使用 Windows 10 或 Linux，但 Linux 的驱动折腾和命令行依赖又让他返回 Windows 10。最终作者转向 macOS，才找到了稳定、安静的体验。文章重点分析了 Windows 系统中锁屏、搜索、小组件等界面内嵌的广告，指出操作系统作为基础软件不应成为广告分发渠道，这种设计对用户是一种冒犯和侵入。作者对比了 UNIX 系统“没有消息就是好消息”的哲学，认为 macOS 和 Linux 提供了干净、克制的数字环境，而 Windows 用户却需要主动关闭广告。最后作者提到，唯一能接受的是开源软件中克制的捐赠提示。文章反思了用户对系统广告的习以为常，并强调了操作系统纯净性的重要性。</summary>
    <title>再审视 Windows：从 Win11 的广告沼泽，逃向 UNIX 的清净世界</title>
    <updated>2026-07-21T13:57:21.319Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="杂谈" scheme="https://090909.top/categories/%E6%9D%82%E8%B0%88/"/>
    <category term="张雪峰" scheme="https://090909.top/tags/%E5%BC%A0%E9%9B%AA%E5%B3%B0/"/>
    <category term="张雪" scheme="https://090909.top/tags/%E5%BC%A0%E9%9B%AA/"/>
    <category term="就业选择" scheme="https://090909.top/tags/%E5%B0%B1%E4%B8%9A%E9%80%89%E6%8B%A9/"/>
    <category term="社会现象" scheme="https://090909.top/tags/%E7%A4%BE%E4%BC%9A%E7%8E%B0%E8%B1%A1/"/>
    <category term="个人奋斗" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E5%A5%8B%E6%96%97/"/>
    <content>
      <![CDATA[<p>张雪峰作为一名在“就业选择”领域做大做强的博主，已经去世很多个月了。相关的消息都在说，这家伙是在今年死去的，享年是 40 岁左右。张雪峰死后，原本这个“令人爱戴的老师”形象，如今成了人人唾弃过街老鼠。倒不是说什么，只要是名人生前都有点黑料。《念张师》什么的都听腻了，拿张雪峰来鄙视社会现象的，都看烦了。只是在想，一个强调“死了就是不强”的人，在物理上死了，凭什么会有人想拥护他？他不是死了吗？为什么我会突然想说他呢？不是恰冷饭，也不是想吃人血馒头，单纯就是今晚我爸问了我一个问题：“你现在还想读书吗？”因为我曾在博客里说过，我离开学校已经很长时间了，并且我有自己的能力，还在持续学习。我不可能抱着一个日均 400 访问量的站点不运营，回去三四线城市的垃圾技校读书的。倒不如想想，为什么那些人会上技校？为什么会有些人去上私立高中？如果让他们拿着 600 多分的成绩毕业，他们会想上那学校吗？</p><p>对比起来，我的情况反而特殊了。我原本在学校就是个成绩好的，之所以初中离开学校，单纯就是生病请假请习惯了，加上我在学校里讨厌一个人。而在家里呆着，我也不是不学习，而是继续进修我的 Linux 课程。为什么我这个有自己熟悉专业的人，要回去技校陪着那些什么都不懂、一天到晚都只是想抽烟打游戏的人，一块上学呢？我曾多次向技校的老师反映这一情况，但他们的态度都是爱答不理。很显然，到了这一阶段，我已无选择权。社会上有一句话，就叫作“如果你无法改变他人，那就改变自己”。并不是说你一定要把自己变成别人，而是当你遇到不好的环境时，要尽自己所能给自己准备最适合自己的环境。当你远离那些压力一段时间，会让自己感受很多。张雪峰就是郑州大学的“给排水科学与工程”专业毕业的学生，后来因时地利做起了教培工作。我们当时都不会想到，一个大学生居然会做出骗人的事情，到处说自己是教授，也不会想到教培这种基础工作，受众居然那么广。</p><p>他就是个信息贩子，凭借自己的影响力和别人的信息差，给别人推荐专业。在那些花了一万块钱的家长看来，这就是孩子的救星，他此刻确实就是站在黑暗里的一道光，给予了那些家长肯定的言语，以及相信的目光。倒不如说这本来就是花钱买的服务，这个所谓的“老师”不帮你找专业，不就是“不守职业操守”了吗？你给的那一万块钱，就不是你自己的东西吗？那些放出来的切片，真的对大部分普通家庭的孩子有用吗？就像我说的，你在以前都想不到教育培训就是一门收益巨大的生意，你凭什么站在今天的视角去预测未来的事情呢？张雪峰以前就建议别人读土木，可现在读出土木的那些人，正在哪里高就呢？更别提我这个连学历都没有的。更令人无语的事情是，这家伙前几年刚给别人推荐完专业，近几年又开始说自己从来没推荐任何专业。这分明就是一个伪君子，站在风口上大口大口地吃着钞票，做了什么事情自己不承认，哪怕一错再错一直到底。</p><p>相比之下，隔壁的一字之差的张雪情况就不一样了。张雪，也就是张雪机车的老板。他带着自己的摩托车，让全世界人都看到了中国制造的实力。这不就是那些“张雪峰”们看不起的制造业吗？现代中国的收入大头就是制造业啊！张雪没有学历，初中就辍学了，与张雪峰的读上大学未毕业的状况，形成了鲜明的对比。他是个赛车爱好者，媒体常常去讲张雪站在暴雨里，自己被车队拒绝的画面，可能是因为这个触动人心吧……但这一点就有待考证了。当然，正因影响力来源不同，社会上不同利益方向的媒体，对这两个“大明星”的评价不同。如果你是站在所谓新媒体带争议的“人民的视角”，你会非常想夸赞张雪峰，因为他和你的利益是一致的，他就是你观点的挡箭牌。哪怕你不知道实情，只知道张雪峰是猝死的，也会夸他是“人民的英雄”，因为你根本想象不到这家伙怎么猝死的，只会代入工人猝死。这时反而不站在网络左派们“无产阶级”的角度，去考量张雪峰这个“有产阶级”多大产业了。</p><p>我是说，任何事情都是具有两面性的。就像上面夸赞张雪峰的新媒体一样的，也有一部分新媒体不赞同张雪峰的观点。为什么呢？因为张雪峰和他们的利益不同。他们同样是站在自己的视角，可能是清醒的、可能是乐子的。张雪一样有人夸赞，一样有人批评。有人就说张雪是社会上的“个例”，试问社会上到底有多少个“张雪”，可他们毕竟是站在自己的角度，不知道在他们不涉及的领域，到底有多少张雪，甚至可能这批自媒体作者就是：“张雪”。毕竟你想，当自媒体恰烂钱，也是顶着社会上质疑的眼光，去完成自己的梦想，这难道不是一种“张雪精神”吗？只不过，张雪为社会和国际推进了“中国制造”的影响力，自媒体们损坏了自己的社会价值，但赚到了钱和韭菜。但你不得不考量的一点是，张雪和张雪峰，算得上是一队的。他们都是在追梦路上艰苦，后来享受到成功的人士，只不过因为理念被媒体簇拥成了对立面。问社会上有多少“张雪”，不如问问社会上又有多少“张雪峰”在赚大钱。</p><p>我们常说：“站在风口上连猪都会起飞。”媒体们也争相比喻张雪和张雪峰到底谁是“风口上的猪”。难道就没人想过，在张雪和张雪峰这俩“矛盾体”之前，这些风口真的轮到他们的专业了吗？他们在风口之前就没有任何努力吗？同样是教培专业，你觉得张雪峰的继任者武亮，真的有在意义上继承了张雪峰吗？如果你是一个类似旧时代刷到张雪峰切片的人，如今刷到了武亮的切片，是会被张雪峰的夸张但有点合理吸引，还是武亮的表演方式吸引？张雪峰的夸张，很大程度上是设计好的，匹配张雪峰这个人的表演方式，以及张雪峰的长相。张雪峰的面相，就很像你学校里能陪你聊到晚自习的那种人，他的讲话风格夸张恰到好处，你当然会被他的内容所吸引了。哪怕张雪峰说的不对也好，预测的专业不好也罢，你承认自己在当时，是否会被张雪峰的表演方式所吸引，并且在死后认为他是一个有趣生动的、指引别人路的“老师”？试问有多少，又是被张雪峰推荐专业并成功的呢？</p><p>你在工地上赚着一万块月薪的时候，刷视频看到 ChatGPT 在一字一句“傻傻地”讲。看着自己如今优越的生活，又看着评论区那些兴奋的开发者，你会认同 AI 才是未来的出路吗？你有放弃安稳生活的勇气，去一个你需要花时间重新学习，原本不熟悉的、甚至未来可能因为经济泡沫抛弃的专业吗？你会共情那个未来在豆包、DeepSeek 面前谈心、傻笑的自己吗？你像张雪或张雪峰一样，实现梦想了吗？就像以前那些因为照片而认为失业的画家、22 年因为 AI 画图而自认为失业的画师，你真的能预测到几年后那个“大众认为 AI 的垃圾作品一文不值，欣赏画师用 AI 加自己能力描绘美妙画面”的世界吗？如果你是因为想混一口饭而去找专业的人，你能预测到几年后你的专业根本找不到工作吗？毕竟大学说小了就 4 年，往大了说就是 7 年乃至 10 年。你真的能掌握那么大的时间成本，去投那个你没兴趣、没长处的专业吗？</p>]]>
    </content>
    <id>https://090909.top/2026/07/02/%E5%BC%A0%E9%9B%AA%E5%92%8C%E5%BC%A0%E9%9B%AA%E5%B3%B0%E7%9A%84%E4%B8%80%E5%AD%97%E4%B9%8B%E5%B7%AE/</id>
    <link href="https://090909.top/2026/07/02/%E5%BC%A0%E9%9B%AA%E5%92%8C%E5%BC%A0%E9%9B%AA%E5%B3%B0%E7%9A%84%E4%B8%80%E5%AD%97%E4%B9%8B%E5%B7%AE/"/>
    <published>2026-07-02T13:55:36.000Z</published>
    <summary>本文介绍了博主张雪峰在“就业选择”领域的影响及其去世后的舆论反转，将其与张雪机车创始人张雪进行对比，探讨了社会对成功与梦想的不同解读。文章指出，张雪峰凭借信息差和表演风格吸引家长付费推荐专业，但被质疑为伪君子，而张雪虽无学历却通过制造业展现了中国制造实力。作者反思了个人在环境中的选择，如自己离开学校后自学 Linux 课程，不愿回到技校与不求上进者为伍。同时，文章批评了媒体对两位人物的对立刻画，认为他们本质都是追梦者，只因利益不同被分化。最后，作者质疑专业选择的长期预测性，强调个人努力与适应环境的重要性，并呼吁读者思考：若无法预知未来，是否应放弃安稳去追求不确定的梦想。文章核心在于揭示社会现象背后的两面性，以及个人在风口与努力之间的抉择困境。</summary>
    <title>张雪和张雪峰的一字之差：张雪峰去世后，就业选择与教育反思</title>
    <updated>2026-07-21T13:57:21.322Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="代码展示" scheme="https://090909.top/categories/%E4%BB%A3%E7%A0%81%E5%B1%95%E7%A4%BA/"/>
    <category term="技术折腾" scheme="https://090909.top/tags/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="AI 检测" scheme="https://090909.top/tags/AI-%E6%A3%80%E6%B5%8B/"/>
    <category term="隐私泄露" scheme="https://090909.top/tags/%E9%9A%90%E7%A7%81%E6%B3%84%E9%9C%B2/"/>
    <category term="Claude Code" scheme="https://090909.top/tags/Claude-Code/"/>
    <category term="DeepSeek API" scheme="https://090909.top/tags/DeepSeek-API/"/>
    <content>
      <![CDATA[<p>最近，我把日常开发任务的主力工具切换到了 Claude Code。有人可能会疑惑：你不是一直在用 DeepSeek TUI 吗？怎么突然换了？其实这只是一次“套壳”尝鲜——我依然使用 DeepSeek 的 API 作为后端，只是前端换成了 Claude Code 这个终端交互工具。网上有非常详细的切换教程，跟着配置环境变量和 API 地址就能轻松搞定。体验下来，不得不承认 Claude Code 作为终端工具的完成度确实远超目前的开源方案，无论是响应速度、上下文管理还是交互流畅度，都给人一种“大厂出品”的扎实感。虽然 Anthropic 这家公司并非由国人创办，但它们打造的产品质量确实优秀。把这个壳套在 DeepSeek 的 API 上使用，竟然异常顺手，效率提升明显。至于注册 Claude 账号？我压根就没动过这个念头，毕竟我只是需要一个好用的终端界面，而 DeepSeek 的低价 API 才是真正的算力来源。</p><p>今天是 7 月 2 日，我像往常一样刷着技术视频，原本以为这只是一个普通用户在吐槽 A 社封禁账号的日常抱怨。结果点开一看，这位老哥直接放了个大招——他花了大量时间爬取了全网关于 Claude Code 检测机制的研究资料，从 IP 归属地到城市级别的定位，把 Anthropic 如何识别中国用户的技术手段扒了个底朝天。最让我后背发凉的是视频发布日期：不是上个月的老视频，恰恰就是 7 月 1 日，几乎就是昨天才发布的内容。那一刻我坐在电脑前，感觉自己的底裤都快被扒光了。首先，Claude Code 会读取你系统的时区代码，精准判断你身处哪个国家；其次，它会在你毫不知情的情况下对提示词做“一点点”修改，比如把 <code>2026-07-02</code> 这种标准格式，根据你的时区自动改写为 <code>2026/07/02</code> 这样的本地化格式——这种细微的调整普通用户根本不会注意到。</p><p>更隐蔽的操作还在后面。它居然会在引号上做手脚——给你的提示词里塞进四种不同类型的引号，正常用户的文本会显示为普通 ASCII 引号，而被标记为“异常”的用户则会看到其他 Unicode 变体引号，你只会天真地以为是字体渲染差异，根本没往检测手段那方面想。更令人发指的是，它还在你的申诉邮件中埋入 JavaScript 代码，用来获取你的真实 IP 地址进行二次验证。一个号称只是用来辅助编程的命令行工具，内部竟然内置了一长串域名黑名单，像百度、阿里这些国内最基本的大厂全被列了进去，唯独腾讯不在其中。有网友分析认为这根本不是黑名单，而是正版验证机制，因为名单上出现的中转域名确实会真的向 Anthropic 的服务器发起请求——这意味着它每时每刻都在验证你的“身份合法性”。</p><p>我平时在自己的网站 Umami 分析后台，都能通过 IP 看到访客来自哪个城市，甚至能猜到是哪位朋友来看我的博客。现在想想，Claude Code 拿了你那么多信息——时区、IP、系统语言、提示词格式、引号习惯、邮件行为——居然仅仅只是为了判断你是不是“合规用户”，然后给你封号处理。可万一哪天这家公司不仅仅满足于封号呢？这些数据会流向哪里？会被用来做什么？越想越觉得脊背发凉。虽然我从未注册过 Claude 账号，全程用的只是最便宜的 DeepSeek API，理论上和 Anthropic 没有任何直接关系，但那种被暗中监控的感觉依然让人极度不适。思来想去，我那些日常任务用 DeepSeek TUI 或者 iFlow 其实完全够用，何必为了那一点交互体验的提升而把自己的隐私暴露给一个不可控的闭源工具？于是我毫不犹豫地执行了卸载命令：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall -g @anthropic-ai/claude-code</span><br><span class="line">rm -rf ~/.claude</span><br><span class="line">rm -rf ~/.cache/claude-code</span><br></pre></td></tr></table></figure><p>如果你也在使用 Claude Code 并且对隐私问题有所顾虑，可以按照上面的命令彻底清理干净。至于替代方案，Codex 倒是开源的，但它是 OpenAI 旗下的项目，同样是另一个科技巨头的产物，除非你对 OpenAI 的信任度更高，否则换汤不换药。剩下的选择就是 DeepSeek TUI、OpenCode 这些纯粹的开源社区产品了，它们托管在 GitHub 仓库中，代码完全公开透明，没有任何埋点或检测逻辑——虽然功能上可能没那么花哨，但至少用着安心。毕竟在如今这个时代，隐私比那一点效率提升珍贵太多了。</p>]]>
    </content>
    <id>https://090909.top/2026/07/02/%E8%A2%AB-A-%E7%A4%BE%E5%90%93%E5%93%AD%E4%BA%86/</id>
    <link href="https://090909.top/2026/07/02/%E8%A2%AB-A-%E7%A4%BE%E5%90%93%E5%93%AD%E4%BA%86/"/>
    <published>2026-07-02T08:06:40.000Z</published>
    <summary>本文介绍了作者将日常开发工具从 DeepSeek TUI 切换到 Claude Code 的经历，虽然仅将 Claude Code 作为前端、后端仍使用 DeepSeek API，但其出色的交互体验曾令作者满意。然而，作者通过一则 7 月 1 日发布的技术视频发现，Claude Code 内部存在隐蔽的检测机制：它会读取系统时区、自动改写提示词日期格式、在文本中嵌入四种不同类型的引号以区分用户，甚至会在用户申诉邮件中植入 JavaScript 代码来获取真实 IP。此外，该工具内置包含百度、阿里等国内大厂的域名黑名单，被怀疑用于验证用户身份合法性。作者深感隐私受到严重威胁，认为 An-thropic 公司可能不仅满足于封号，还会收集时区、IP、语言等敏感数据。尽管本人从未注册 Claude 账号，仍果断执行了 npm 卸载命令并清理残留文件。文章最后建议，若顾虑隐私，应改用 DeepSeek TUI、OpenCode 等完全开源透明的终端工具，强调在当今环境下隐私价值远超工具效率的提升。</summary>
    <title>被 A 社吓哭了：Claude Code 隐私检测，让我果断卸载回归开源</title>
    <updated>2026-07-21T13:57:21.326Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="游戏" scheme="https://090909.top/categories/%E6%B8%B8%E6%88%8F/"/>
    <category term="我的世界" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="游戏攻略" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E6%94%BB%E7%95%A5/"/>
    <category term="生存模式" scheme="https://090909.top/tags/%E7%94%9F%E5%AD%98%E6%A8%A1%E5%BC%8F/"/>
    <category term="游戏探索" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E6%8E%A2%E7%B4%A2/"/>
    <category term="服务器" scheme="https://090909.top/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    <content>
      <![CDATA[<p><img src="/assets/images/illustrations/minecraft-78.webp"></p><p>大家好啊，欢迎再次来到梁栋烨的游戏世界。今天是我第二次踏入这个充满未知与惊喜的生存服务器，心里还挺期待的。昨晚下线时还担心今天登录会不会出现在什么奇怪的地方，结果一上线就放心了——我正好端端地站在昨天那位热心大佬带我落脚的樱花木宿舍里，连位置都没变。这个宿舍区整体看上去还是那么简约，四面墙壁都是那种柔和又显眼的粉色樱花木板，在一片翠绿的丛林衬托下显得格外突出。宿舍有个挺有意思的规定，就是允许大家使用告示牌作为自己的门牌号，好让邻里之间互相认识。可问题是，樱花木在这个服务器里并不是那么容易获取的，得跑老远去找专门的樱花树林，砍伐起来也挺费工夫。不过我这人做事向来喜欢未雨绸缪，昨天闲逛时顺手砍了不少樱花木囤着，这会儿正好派上用场。我打开背包，把存着的樱花木全部取出来，在合成台前忙活了一阵子，做成了一堆整整齐齐的樱花木告示牌，码放在背包里，准备挨家挨户去派发。</p><p><img src="/assets/images/illustrations/minecraft-79.webp"></p><p>哈哈，看着手里这一摞粉粉嫩嫩的樱花木告示牌，我心里冒出一个挺有意思的念头——干脆当个“门牌志愿者”，主动给那些还没挂牌的邻居们送温暖。我抱着这堆告示牌，开始挨个敲开附近那些空置或者尚未挂牌的宿舍门。这些房子大多和我那间结构差不多，都是最基础的实用风格，里面摆着床、箱子、工作台和熔炉这开局四件套，只是屋主还没顾得上给自己安个门牌。我蹑手蹑脚地走进每一间屋子，小心翼翼地把一块樱花木告示牌放进人家的箱子里，想着等他们下次上线开箱时，能惊喜地发现这份来自邻居的小礼物。不过跑了一圈下来，我注意到这整片民宿区的入住率其实并不高，空着的房间远比住了人的要多得多，放眼望去大部分房子都是静悄悄的。想来也是，这片民宿可能才开张不久，服务器也还在慢慢积累人气，毕竟一个新服务器从冷清到热闹总得有个过程。我在心里默默期望着，等那些还没露面的邻居们陆续上线入住之后，能留意到箱子里的这块粉色告示牌。</p><p><img src="/assets/images/illustrations/minecraft-80.webp"></p><p>把告示牌派发完以后，我活动了一下筋骨，决定不再局限于宿舍区这一亩三分地，而是鼓起勇气向更远的地方探索。昨天我不是提到过，在宿舍区对面似乎还有另一片风格相近的民宿吗？当时只是远远瞥了一眼，没来得及仔细看，今天正好闲着，干脆专程过去探个究竟。我背上剑，带上一些干粮和火把，踏上了穿越丛林的旅途。脚下的路先是穿过一片密不透风的树林，阳光透过层层叠叠的树叶洒下来。走了大概几分钟，一条蜿蜒的小河横在了面前，河水不深但流速还挺急的，我索性直接涉水游了过去，浑身湿漉漉地爬上岸继续赶路。走着走着，视野突然开阔起来——果然，前方出现了一片和我们现在宿舍区风格极为相似的建筑群，同样以樱花木为主材，格局也大同小异。就在我仔细打量的时候，路边突然蹿出一只不知天高地厚的僵尸，张牙舞爪地朝我扑过来，嘴里还发出低沉的嘶吼。我二话不说，拔出腰间那把亮闪闪的钻石剑，随手一挥就把它撂倒了，这种小怪根本不值一提，继续赶路要紧。</p><p><img src="/assets/images/illustrations/minecraft-81.webp"></p><p>站在这片新发现的宿舍区前，我仔细观察了一番，心里渐渐有了判断——这片地方应该就是服务器里那批更早入住的老玩家们所居住的“旧民宿”了。这也正好解释了为什么之前那位大佬要费心新建一片民宿区，大概是因为旧的这片逐渐住满了人，房源紧张，所以才需要开辟新的地方来接纳后来的萌新玩家。旧民宿的建筑风格和我们那边一脉相承，基本上都是以樱花木为主要建材，只是这里的装饰细节比新宿舍区要丰富一些。路灯直接用萤石块堆砌而成，晚上应该会发出柔和而明亮的光芒，照亮整个街道。不过说实话，从整体布局来看，这片旧民宿区其实也谈不上多么豪华气派，甚至有些角落看起来也挺简陋的，毕竟大家来玩生存模式都不是奔着建筑比赛来的。但我注意到一个很明显的区别——这边每一间宿舍的门框上方或者门板旁边，都整整齐齐地挂着一块写有名字的门牌号，没有一间是空着的。这说明住在这一带的都是些严格遵守服务器规矩的老玩家了，他们早就习惯了这种挂牌入住的默契。</p><p><img src="/assets/images/illustrations/minecraft-82.webp"></p><p>在旧宿舍区转悠了没多久，聊天框里突然弹出一条新消息——是阿普修上线了。我赶紧跟他打了声招呼，告诉他我在二区这边建了个小基地。阿普修还挺热情的，说让我切到二区的主世界，他要带我参观一下他的领地。我二话不说，进入了二区的主世界。阿普修早早就在约定地点等着我了，我就发现这边的生物群系跟我自己落脚的那片热带草原几乎一模一样——同样干枯的金合欢树、同样泛黄的草地、同样温暖干燥的空气。不过以我对《我的世界》生成机制的了解，这肯定不是同一片区域，只是恰好刷出了相同的生物群系罢了，毕竟二区的主世界辽阔得很。到了他的领地，我一眼就看到一个用木栅栏围起来的圆形圈子，里面有几块被水浸润过的耕地，几个村民正在里面勤勤恳恳地翻土种田。看来阿普修已经开始搞村民繁殖和自动化农田了，这进度比我快多了。我才是刚来这个服务器，他没准已经在这个服务器生活好久了。</p><p><img src="/assets/images/illustrations/minecraft-83.webp"></p><p>把阿普修的生电基地从头到尾参观了一遍，我算是大饱眼福了。不过总在别人家待着也不是个事儿，我便告辞回到了自己在二区的那片热带草原落脚点。今天可是个重要的日子——我打算正式给自己盖一个像样的房子，告别风餐露宿的野人生活。我站在那片枯黄的草地上环顾四周，心里盘算着该建成什么样式。琢磨来琢磨去，我决定不搞那种标准的长方体火柴盒了，那样太没创意。于是我想了个更“精致”的方案——四面墙壁全部用一扇扇木门围起来，只留一个入口供自己进出。这样一来，整个建筑的实际体积甚至比火柴盒还要小得多，几乎就像个栅栏围合。不过这屋子虽然看起来小巧得有些寒碜，但用那句老话来形容真是再合适不过了——“麻雀虽小，五脏俱全”。屋内的空间被我安排得明明白白：工作台紧挨着墙角，熔炉摆在旁边，角落里还塞进了一个小箱子存放日常用品。最关键的是，一到天黑我只要闪身钻进这个四面都是门的“门房”，外面的僵尸、骷髅和小白就全都拿我没办法了。</p><p><img src="/assets/images/illustrations/minecraft-84.webp"></p><p>正当我蹲在刚建好的小房子里整理箱子里的杂物时，游戏界面上突然弹出了一条系统提示，提醒我可以创建领地了。哦对，我差点把这事给忘了！昨天那位带我的大佬好像提过一嘴，说这个服务器装了一个叫“领地”的插件，功能非常实用。简单来说，只要我在自己盖的房子周围圈出一块地盘作为领地，那么除了我自己和被我授权的人之外，其他任何玩家都没办法在这片区域内破坏或者放置任何方块，就连挖个土都不行。这样一来，我辛辛苦苦收集来的宝贝物资就不用担心被路过的熊孩子顺手牵羊了，晚上睡觉也能睡得更踏实。更有意思的是，领地的主人还可以单独调整这片区域内的天气和时间，比如外面狂风暴雨的时候，我可以把领地内的天气调成晴天，或者把时间锁定在白天，让这片小天地和外面的游戏主世界完全独立开来，想想都觉得舒服。另外，这个领地系统还有一个特别吸引人的设定——领地可以花钱来扩大范围，只要你手里有游戏币，就可以一圈一圈地把自己的地盘往外扩。</p><p><img src="/assets/images/illustrations/minecraft-85.webp"></p><p>在二区这边待了一阵子，我又结识了一位新的大佬玩家，他的名字挺有意思的，叫 <code>hello_steve</code>，一看就是个标准的《我的世界》老玩家 ID。这位 <code>hello_steve</code> 还挺热心的，在聊天框里跟我说愿意带我一起玩生存，帮我搞搞基建什么的。他给了我一些钻石装备：一点点钻石，还有一点末影珍珠。我礼貌地谢过他，然后转身打开自己屋里那个塞得满满当当的箱子，开始仔细清点目前的全部家当。我把这几样珍贵物资挑出来，全部放到了箱子的最里面的角落，免得哪天不小心手滑给弄丢了。把这些贵重物品安置妥当之后，我回头重新打量了一下 <code>hello_steve</code>，心里暗暗做了个比较。个人感觉啊，二区这位大佬虽然人挺好的，但论“财力”和装备水平，似乎还不如我在一区遇到的那位带我去民宿的大佬。一区那位可是全身闪耀的钻石套，从头盔到靴子全都是闪闪发光的钻石材质，走起路来都带风，那才叫真正的大佬排面。</p><p><img src="/assets/images/illustrations/minecraft-86.webp"></p><p>站在这间比火柴盒还小的“门房”里转了两圈，我越看越觉得空间实在是过于局促了，连转身都得小心翼翼，生怕碰倒工作台上的东西。看来光是横向发展是远远不够的，我灵机一动——既然地上没地方了，那就往地下挖呀！说干就干，我抄起手里的钻石镐，在屋子的正中央选定了一块地砖，对准就是一顿猛挖。垂直通道伴随着叮叮当当的凿击声一点一点地向下延伸，我脚踩着梯子，一边挖一边往下放，就这样一级一级地深入地下。挖着挖着，耳边的环境音效突然起了变化——原本只有我自己镐子敲击石头的清脆回响，渐渐地，一阵若隐若现的嘶嘶声和窸窣声从更深处传了上来，而且越往下声音就越清晰，听起来像是蜘蛛在爬行时发出的那种令人头皮发麻的摩擦音。我心里咯噔一下，第一反应是糟糕，这底下该不会刚好连通着一个天然洞穴吧？要是洞穴里密密麻麻全是蜘蛛，我这单人独骑下去岂不是羊入虎口？不过好奇心最终还是战胜了恐惧，我咬咬牙继续往下挖了几格。</p><p><img src="/assets/images/illustrations/minecraft-87.webp"></p><p>结果当最后一块石头被凿穿时，眼前的景象让我整个人都愣住了——呈现在我面前的不是什么普通洞穴，而是一个货真价实的蜘蛛刷怪笼！我赶紧在聊天框里喊了几个好友过来围观，他们赶到现场探头一看，一个个全都目瞪口呆，半天说不出话来。几个朋友围在刷怪笼旁边惊叹了好一阵子，又是截图又是感叹的，热闹劲儿过去之后，也就陆陆续续各忙各的去了，毕竟每个人都有自己的建设和计划要推进，不可能一直在这儿干站着围观。看着他们走远的背影，我心里暗自盘算了一下——如果接下来我一直保持在线的话，其实还挺希望他们能把紧挨着刷怪笼隔壁的那片空间改造一下，做成一个简易的刷怪塔或者经验农场。这样一来我以后想升级附魔或者收集蜘蛛丝的时候，就只需要从地下室走过去几步路的事儿，方便得不得了，而且只要他们施工的时候注意别把我自己住的这部分给挖塌了就行。</p><p><img src="/assets/images/illustrations/minecraft-88.webp"></p><p>房子扩建这件事远比我想象的要费功夫，砌了几面墙之后，天色已经不知不觉暗了下来，我看了看屏幕左上角的时钟，意识到今天已经在游戏里泡了太久了，该下线休息了。不过在下线之前，我得给自己这个秘密基地做个巧妙的伪装才行，毕竟在服务器里，越是显眼的东西越容易招来好奇的目光。我爬上地面，来到地下室入口的位置——那里有一扇活板门紧紧盖着入口，与周围的地板几乎融为一体，不仔细看根本发现不了异常。我思索片刻，从背包里取出一棕色的床，直接端端正正地摆放在活板门上面，把整个入口遮挡得严严实实。这样一来，假如有其他玩家路过我这间小屋，探头进来一看，顶多会以为这就是个再普通不过的简陋居所：一张床、一个工作台、一个熔炉，平平无奇，毫无亮点，甚至无聊到让人提不起任何破坏或翻找的兴趣。可他们哪里想得到，这张看起来安安稳稳的床铺底下，竟然别有洞天。这种“地上陋室、地下豪宅”的反差感，让我每次想起来都忍不住偷偷乐。</p><p>这可不就是名副其实的秘密基地嘛，以后无论服务器里发生什么，我都有个谁也找不到的安身之处了。交代完了游戏里的冒险，我得再说说生活中的事。就在我准备上线游戏的时候，阿普修给我发了条消息，说这可能真的是他这个暑假里最后一天打游戏了，因为今天晚上高考成绩就要公布了，全家人都紧张兮兮地守在电脑旁边等着查分。如果成绩理想的话，他后面几天可能还会抽空上来放松一下，但如果结果不理想的话，那恐怕就另说了——毕竟今年的试卷听说特别难，他的心态也一直绷得紧紧的。我收下了他这份“暂时告别”的预告，心里却忍不住暗暗为他捏了一把汗。但愿他能在显示屏上看到一个让自己满意到跳起来的分数吧，毕竟他平时那么努力，而且心脏本来就不太好，要是成绩太出乎意料，我真怕他情绪波动太大扛不住。说起来，上一次和女孩子一起玩游戏，好像要追溯到小学五年级的时候了。</p><p>疫情时期，是我把前桌的吕芸佩带进我的世界的。可上了初中以后，我们就再也没有联系过了，哪怕我每天上学都要路过他就读的那所郊区中学，也会专门往校门口多看几眼，却始终没再看到那个曾经熟悉的背着书包的身影。</p>]]>
    </content>
    <id>https://090909.top/2026/07/02/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E8%8D%92%E7%AC%AC%E4%BA%8C%E6%9C%9F/</id>
    <link href="https://090909.top/2026/07/02/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BC%80%E8%8D%92%E7%AC%AC%E4%BA%8C%E6%9C%9F/"/>
    <published>2026-07-02T04:30:05.000Z</published>
    <summary>本文介绍了作者在《我的世界》生存服务器中的一系列冒险经历。作者首先在樱花木宿舍区担任“门牌志愿者”，用囤积的樱花木制作告示牌分发给邻居。随后探索了服务器中的旧民宿区，发现老玩家们严格遵守挂牌规则。在二区主世界，作者拜访了朋友阿普修的自动化农田基地，并结识了新玩家 hello_steve 获得钻石装备。作者用木门搭建了一个小巧的“门房”作为临时居所，并利用领地插件保护自己的地盘。在扩建地下室时意外发现一个蜘蛛刷怪笼，计划将其改造成经验农场。最后，作者用床铺巧妙伪装了秘密基地入口。文章末尾提到朋友阿普修因高考成绩即将公布而暂时告别游戏，表达了作者对过去的回忆和对朋友未来的祝福。</summary>
    <title>服务器开荒第二期：给邻居送告示牌，扩建地下发现蜘蛛刷怪笼</title>
    <updated>2026-07-21T13:57:21.324Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="游戏" scheme="https://090909.top/categories/%E6%B8%B8%E6%88%8F/"/>
    <category term="我的世界" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="友谊" scheme="https://090909.top/tags/%E5%8F%8B%E8%B0%8A/"/>
    <category term="游戏体验" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E4%BD%93%E9%AA%8C/"/>
    <category term="游戏探索" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E6%8E%A2%E7%B4%A2/"/>
    <category term="服务器" scheme="https://090909.top/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    <content>
      <![CDATA[<p>最近，我的好朋友阿普修在我个人网站上的一条动态下留了言，大意是问我最近有没有发掘到什么好玩的《我的世界》服务器，想一起探索。我回复他说，我平时玩游戏比较固定，通常都是和小芬两个人联机，自己建个房间随便玩玩，很少去大型服务器凑热闹，因为总觉得人多反而少了那份探索的乐趣。然而，就在那天晚上，阿普修像是突然想起了什么宝藏一样，给我发来了一条简短讯息，上面清晰地写着服务器的版本号和连接地址。他特意叮嘱我，这个服务器他玩了一阵子，氛围很不错，让我务必来试试。</p><p>我点开那条消息一看，服务器版本是 1.21.11，一个听起来非常经典且稳定的版本，让人瞬间安心不少。我几乎没有犹豫，就把这条消息原封不动地转发给了小芬，热情地邀请他一起来这个新世界开荒。我想着，如果能拉上小芬一起，三个人在这个陌生的服务器里相互照应，肯定比一个人瞎逛要有意思得多，大家都能玩得更开心。怀着这份期待，我顺利登录了游戏。出生点是一个古色古香的大厅，整体是中国风的设计，红墙黛瓦，挂着灯笼，很有韵味。正当我还在好奇地四处打量时，一位热心的服务器大佬主动跟我搭话，说可以带我先去他建的民宿落脚，熟悉一下环境。</p><p><img src="/assets/images/illustrations/minecraft-67.webp"></p><p>这里就是那位大佬口中提到的民宿了。说是民宿，其实从外观上看，就是一个非常标准且简洁的大型火柴盒结构，方方正正的，没有丝毫多余的装饰。整个建筑的四面墙壁都铺满了樱花木，呈现出一种柔和而又扎眼的粉色，在一片绿意中显得格外独特。我转身看向身后，房间里的陈设也是一目了然：一张白色的床、一个箱子、一个工作台，还有一个熔炉，这些都是《我的世界》玩家开局最熟悉不过的基础功能方块。怎么说呢，虽然简单得有些过分，但这种最原始的配置，却恰恰是每个MC玩家在这个方块世界开始冒险时，最能获得安全感的起点。</p><p><img src="/assets/images/illustrations/minecraft-68.webp"></p><p>毕竟初来乍到，人生地不熟的，我也不好意思一直站在家里发呆，于是决定先到四处转转，熟悉一下周边的地形。那位带我来民宿的大佬似乎也明白我是个纯萌新，特意告诉我先在附近看看环境，感受一下服务器的氛围。我推门出去，发现屋外也种着不少樱花树，风一吹，花瓣便纷纷扬扬地飘落，视线所及之处都是浪漫的粉色。不远处，一座黑曜石搭建的地狱传送门赫然矗立在那里，散发着幽幽的紫光，而旁边还放着几个箱子，我分不清那到底是公共仓库，还是哪位玩家暂时存放私人物品的地方，不敢贸然翻动。</p><p><img src="/assets/images/illustrations/minecraft-69.webp"></p><p>光看自己住的地方还不够，我决定悄悄去看看邻居们的房子都是什么风格。紧挨着我的那位邻居，我暂且在心里称他为“章鱼哥”——当然这只是个玩笑，纯粹是串台想到了《海绵宝宝》里的角色。这也是一位服务器里的大佬，他的火柴盒和我那间结构上大同小异，但气派程度却明显高了一个档次。透过窗户，我能看到他的箱子里整整齐齐地码放着原木，显然是储备了不少资源。最引人注目的是工作台上，竟然端端正正地摆放着一颗末影龙的龙头，那无声的威压感，瞬间让这个原本平平无奇的火柴盒变得充满了史诗感，处处彰显着屋主在末地征伐过的辉煌战绩。</p><p><img src="/assets/images/illustrations/minecraft-70.webp"></p><p>看完“章鱼哥”的家，我又把目光投向了更旁边的那间屋子。这位邻居的布局和我那边几乎就是一个模子刻出来的，没什么特别之处。我好奇地透过缝隙看了看里面的箱子，发现里面也没什么稀罕物件，就是什么都没有。整栋房子的内部构造依然是最基础的那一套：一张用来重置重生点的床、几个存放物品的箱子、一个基础的工作台、一个用来烧炼矿物的熔炉，以及满墙粉色的木头作为墙壁装饰。这种“极简主义”风格似乎在这里很常见，大家都不约而同地选择了最实用的设计方案。看来，在这样一片新开辟的宿舍区里，大家的起点都差不多，也难怪这里会被戏称为“宿舍”了。</p><p><img src="/assets/images/illustrations/minecraft-71.webp"></p><p>既然安顿下来了，总得开始收集资源。我找到一棵树，准备先砍点木头作为启动资金。值得一提的是，这个服务器贴心安装了一键砍树的辅助插件。当我一斧头砍下去，整棵大树的树干瞬间化为一个个掉落的方块，哗啦啦地全落在地上，看着那一整棵树就这么被轻松放倒，视觉上真的有种难以言喻的解压感，非常爽快！不过，我也在这里吃了个暗亏。这个插件的物理机制做得相当真实，那些被砍倒后的木头在掉落过程中是有实体碰撞体积和伤害判定的。我因为靠得太近，被落下来的木头砸了几下，掉了不少血量。所以在这里要特别提醒各位，如果来这个服玩，砍树时千万要保持距离，别像我一样被自己的木头给砸晕了。</p><p><img src="/assets/images/illustrations/minecraft-72.webp"></p><p>忙活了一阵，我突然想起阿普修，他不是喊我来玩的吗？怎么自己却不见人影。我打开聊天框问他人在哪里，他的回复让我愣住了——他说自己在二区玩得正欢呢。额，这就有点尴尬了，敢情我忙活了半天，结果和他不在同一个区。我在一区，他在二区，虽然是一个服务器，但世界却是隔开的。算了，反正一区这边我也已经看了个大概，就先在一区这边立个告示牌，算是正式住下了，以后想起来了还能回来看看。我掏出告示牌，琢磨着该写什么名字好呢？思来想去，最后干脆把我的个人网站名称和域名 <code>090909.top</code> 一笔一划地写了上去，算是给自己在这个方块世界里留下一份独特的印记。</p><p><img src="/assets/images/illustrations/minecraft-73.webp"></p><p>告别了一区，我来到了二区。这边的出生大厅建筑风格和一区几乎一模一样，让我有种莫名的熟悉感。我站在大厅中央，兴致勃勃地点开了随机传送主世界的功能，幻想着自己能像小说主角一样，被传送到一片风景如画、资源丰富的风水宝地。然而，系统似乎跟我开了个天大的玩笑，当加载画面结束，我眼前的景象只剩下一片刺目的白色——我居然被直接扔到了一望无际的冰原上！啊这！四面都是高耸入云的冰山，除了雪块和浮冰，视线所及之处没有任何树木，也没有任何绿色，这种光秃秃的环境，你让我在这鸟不拉屎的地方怎么开局啊？</p><p><img src="/assets/images/illustrations/minecraft-74.webp"></p><p>站在冰原上，我忍着寒冷等待传送保护时间结束。等那漫长的倒计时终于走完，我毫不犹豫地再次点开了传送按钮，心里默默祈祷着，这次一定要给我传到一个能活下去的地方。我不奢求什么富饶的蘑菇岛或者森林，只要能让我看到树，看到点能杀的动物就行。其实在上一片冰原，倒是有几只北极熊在游荡，但我尝试攻击后发现，杀死它们除了会掉落几条可怜的生鱼外，根本不会掉落任何有用的肉类或材料，完全是浪费时间和武器耐久。所以，我一刻也不想在那片不毛之地多待，满心期待着下一个坐标能带来转机。</p><p><img src="/assets/images/illustrations/minecraft-75.webp"></p><p>随着又一次屏幕闪烁和加载，我的视野终于不再是冰冷的蓝白色调了。谢天谢地，我总算来到了一个看起来能够正常生存的地方。虽然这里看起来有点过于“温暖”了——没错，我直接被空投到了一片热带草原。金合欢树稀稀拉拉地分布在大地上，草是枯黄色的，看起来有些干旱。不过，经历了刚才冰原的绝望，我对这片草原已经相当满足了。至少，这里有足够的树木让我砍来造工具和房子，有草甸上奔跑的猪和牛让我解决食物问题，生活虽然简陋，但只要能砍树、能盖房、能杀猪，日子就算过得下去了。比起刚才那个啥也干不了的冰原，这里简直就是天堂。</p><p><img src="/assets/images/illustrations/minecraft-76.webp"></p><p>天色渐渐暗了下来，夕阳的余晖将天空染成橙红色，这意味着夜晚和怪物即将来临。我像往常一样，熟练地合成了工作台，然后用收集到的羊毛和木板赶制出了一张白色的床。我把床紧挨着工作台放好，确保重生点就设在这里，然后满怀安心地点击了床，准备躺下度过这漫漫长夜。然而，游戏界面却弹出提示，说我无法入睡，并显示了一个睡觉人数的比例。我这才猛地拍了一下脑门——哎呀，我竟然忘了自己现在玩的是多人模式！在我的世界服务器里，如果不特意修改睡觉人数比例的插件设定，默认情况下是需要全服在线玩家都躺到床上，才能跳过夜晚的。看来，今晚注定要在这片陌生的草原上，提心吊胆地熬过漫长的黑夜了。</p><p><img src="/assets/images/illustrations/minecraft-77.webp"></p><p>阿普修在 QQ 里跟我道了晚安，说今天太晚了，他得去休息了，不会再上线来这边找我玩。我叹了口气，一个人玩也确实少了些热闹。我设定好了这片草原基地的传送点，方便下次直接回来，然后便准备退出服务器了。退出前，我又看了一眼这片荒芜却充满希望的土地，一时半会也想不出什么具有创意的名字来命名这个据点。于是，我索性故技重施，在系统提示框里填入了我那个熟悉的网站名称——“他说”。这也算是我在每一个服务器里留下的统一印记吧。最后，再次郑重地贴出信息：服务器地址是 <code>mc008.cn</code>，版本是 1.21.11，欢迎感兴趣的朋友一起来玩啊！</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E6%9C%8B%E5%8F%8B%E9%82%80%E8%AF%B7%E6%88%91%E7%8E%A9%E6%9C%8D%E5%8A%A1%E5%99%A8/</id>
    <link href="https://090909.top/2026/07/01/%E6%9C%8B%E5%8F%8B%E9%82%80%E8%AF%B7%E6%88%91%E7%8E%A9%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    <published>2026-07-01T15:18:38.000Z</published>
    <summary>本文介绍了作者在朋友的推荐下，进入一个名为 mc008.cn、版本 1.21.11 的《我的世界》服务器的探索经历。作者登录后出生在中国风大厅，被大佬带到一间樱花木制成的火柴盒民宿安顿，内部仅有基础工具。随后作者参观邻居的房屋，发现一位大佬的工作台上摆放着末影龙龙头，彰显战绩。作者尝试砍树时因服务器的一键砍树插件被落木砸伤，提醒玩家保持距离。作者发现朋友阿普修在二区，自己却在二区，于是留下网站域名 090909.top 的告示牌后前往二区。随机传送却将作者抛至冰原，因无法生存再次传送至热带草原。夜晚来临时作者试图睡觉，却得知服务器需全服玩家同时躺床才能跳过夜晚，被迫熬夜。最后作者设定传送点并退出，统一使用“他说”作为据点名称，并再次公开服务器信息邀请玩家加入。</summary>
    <title>朋友邀请我玩服务器：我的世界服务器开荒，冰原遇险草原安家</title>
    <updated>2026-07-21T13:57:21.324Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="代码展示" scheme="https://090909.top/categories/%E4%BB%A3%E7%A0%81%E5%B1%95%E7%A4%BA/"/>
    <category term="Python 脚本" scheme="https://090909.top/tags/Python-%E8%84%9A%E6%9C%AC/"/>
    <category term="微信支付" scheme="https://090909.top/tags/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98/"/>
    <category term="苹果日历" scheme="https://090909.top/tags/%E8%8B%B9%E6%9E%9C%E6%97%A5%E5%8E%86/"/>
    <category term="记账脚本" scheme="https://090909.top/tags/%E8%AE%B0%E8%B4%A6%E8%84%9A%E6%9C%AC/"/>
    <category term="个人项目" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E9%A1%B9%E7%9B%AE/"/>
    <content>
      <![CDATA[<p>最近做了一个小脚本，能把微信支付记录的 XLSX 导出到苹果日历，起因是我妈想要一个记账的东西。她不太会用复杂的软件，就想要个能一眼看清每天花了多少钱的工具。我以前是用一个本地部署的软件来管理账目的，但那个软件的界面实在太过丑陋，满屏都是花花绿绿的配色和生硬的排版，一股浓烈的 AI 生成味道，用起来毫无愉悦感。寻思着既然自己天天要用，不如索性重写一个，做成自己用得顺手的模样。一开始是完全没考虑过把账单放进日历里的，最初的设想很简单，就是直接导出一个 CSV 文件，方便自己在 Excel 里做分类统计和月度汇总一类的工作。</p><p>但后来实际用下来发现 CSV 的效果并不理想，主要是每次查看都得专门打开表格软件，还得手动按日期排序筛选，操作起来略显繁琐。等等，说到了日期，我忽然想起来那些老一辈人，都是习惯直接在纸质日历上写字的——今天买菜花了多少钱、明天人情往来出了多少份子，密密麻麻地记在日历格子里，翻看起来特别直观。于是我就想，能不能在电子日历上也实现类似的效果呢？苹果的 ICS 文件格式支持你预定一个提醒事项，能够自动放到系统自带的日历里面，每天打开手机就能看到当天的收支摘要，非常方便。</p><p>我还考虑到，如果全部信息（包括店名、收了多少钱、支付了多少钱）都一股脑儿导进去的话，那阅读起来还是太过辛苦，信息过载反而失去了快速浏览的意义。所以我特意设计成了仅导入支出和收入这两部分核心数据，精简掉冗余细节，只保留每天的总账目。以下是实现这一功能的完整代码，整体逻辑清晰，包含文件读取、数据解析、ICS 生成和命令行交互等模块：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python3</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">微信支付账单 XLSX → Apple ICS 日历转换脚本</span></span><br><span class="line"><span class="string">将每天的收支汇总为日历事件，导入到 macOS/iOS 日历中显示。</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"><span class="keyword">import</span> datetime</span><br><span class="line"><span class="keyword">import</span> uuid</span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> defaultdict</span><br><span class="line"><span class="keyword">from</span> pathlib <span class="keyword">import</span> Path</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">  <span class="keyword">import</span> openpyxl</span><br><span class="line"><span class="keyword">except</span> ImportError:</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;缺少 openpyxl 库，请运行: pip install openpyxl&quot;</span>)</span><br><span class="line">  exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">parse_xlsx</span>(<span class="params">path: <span class="built_in">str</span></span>) -&gt; <span class="built_in">str</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;读取 XLSX 文件，返回 (昵称, 收入总笔数/金额, 支出总笔数/金额, 按日期汇总的收支记录)&quot;&quot;&quot;</span></span><br><span class="line">  wb = openpyxl.load_workbook(path, read_only=<span class="literal">True</span>, data_only=<span class="literal">True</span>)</span><br><span class="line">  ws = wb.active</span><br><span class="line"></span><br><span class="line">  rows = <span class="built_in">list</span>(ws.iter_rows(values_only=<span class="literal">True</span>))</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 解析表头信息（前 18 行）</span></span><br><span class="line">  nick_name = <span class="literal">None</span></span><br><span class="line">  <span class="keyword">for</span> r <span class="keyword">in</span> rows[:<span class="number">6</span>]:</span><br><span class="line">    <span class="keyword">if</span> r[<span class="number">0</span>] <span class="keyword">and</span> <span class="built_in">isinstance</span>(r[<span class="number">0</span>], <span class="built_in">str</span>) <span class="keyword">and</span> r[<span class="number">0</span>].startswith(<span class="string">&quot;微信昵称&quot;</span>):</span><br><span class="line">      nick_name = r[<span class="number">0</span>].replace(<span class="string">&quot;微信昵称：&quot;</span>, <span class="string">&quot;&quot;</span>).replace(<span class="string">&quot;[&quot;</span>, <span class="string">&quot;&quot;</span>).replace(<span class="string">&quot;]&quot;</span>, <span class="string">&quot;&quot;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 第 18 行是列标题（0-indexed = 17）</span></span><br><span class="line">  <span class="comment"># 列: 交易时间, 交易类型, 交易对方, 商品, 收/支, 金额(元), ...</span></span><br><span class="line">  header_row = rows[<span class="number">17</span>]</span><br><span class="line">  col_idx = &#123;</span><br><span class="line">    <span class="string">&quot;time&quot;</span>: <span class="number">0</span>,</span><br><span class="line">    <span class="string">&quot;type&quot;</span>: <span class="number">1</span>,</span><br><span class="line">    <span class="string">&quot;income_expense&quot;</span>: <span class="number">4</span>,</span><br><span class="line">    <span class="string">&quot;amount&quot;</span>: <span class="number">5</span>,</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  daily: <span class="built_in">dict</span>[<span class="built_in">str</span>, <span class="built_in">dict</span>] = defaultdict(<span class="keyword">lambda</span>: &#123;<span class="string">&quot;income&quot;</span>: <span class="number">0.0</span>, <span class="string">&quot;expense&quot;</span>: <span class="number">0.0</span>, <span class="string">&quot;count_income&quot;</span>: <span class="number">0</span>, <span class="string">&quot;count_expense&quot;</span>: <span class="number">0</span>&#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> row <span class="keyword">in</span> rows[<span class="number">18</span>:]:</span><br><span class="line">    dt = row[col_idx[<span class="string">&quot;time&quot;</span>]]</span><br><span class="line">    io = row[col_idx[<span class="string">&quot;income_expense&quot;</span>]]</span><br><span class="line">    amt = row[col_idx[<span class="string">&quot;amount&quot;</span>]]</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> dt <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">      <span class="keyword">continue</span></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> <span class="built_in">isinstance</span>(dt, datetime.datetime):</span><br><span class="line">      <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 只取日期</span></span><br><span class="line">    date_str = dt.strftime(<span class="string">&quot;%Y-%m-%d&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> io <span class="keyword">and</span> <span class="built_in">isinstance</span>(io, <span class="built_in">str</span>):</span><br><span class="line">      <span class="keyword">try</span>:</span><br><span class="line">        amount = <span class="built_in">float</span>(amt) <span class="keyword">if</span> amt <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span> <span class="keyword">else</span> <span class="number">0.0</span></span><br><span class="line">      <span class="keyword">except</span> (ValueError, TypeError):</span><br><span class="line">        amount = <span class="number">0.0</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> io == <span class="string">&quot;收入&quot;</span>:</span><br><span class="line">        daily[date_str][<span class="string">&quot;income&quot;</span>] += amount</span><br><span class="line">        daily[date_str][<span class="string">&quot;count_income&quot;</span>] += <span class="number">1</span></span><br><span class="line">      <span class="keyword">elif</span> io == <span class="string">&quot;支出&quot;</span>:</span><br><span class="line">        daily[date_str][<span class="string">&quot;expense&quot;</span>] += amount</span><br><span class="line">        daily[date_str][<span class="string">&quot;count_expense&quot;</span>] += <span class="number">1</span></span><br><span class="line">      <span class="comment"># 中性交易跳过</span></span><br><span class="line"></span><br><span class="line">  wb.close()</span><br><span class="line">  <span class="keyword">return</span> nick_name, daily</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">escape_ics</span>(<span class="params">text: <span class="built_in">str</span></span>) -&gt; <span class="built_in">str</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;转义 ICS 文本字段的特殊字符&quot;&quot;&quot;</span></span><br><span class="line">  text = text.replace(<span class="string">&quot;\\&quot;</span>, <span class="string">&quot;\\\\&quot;</span>)</span><br><span class="line">  text = text.replace(<span class="string">&quot;;&quot;</span>, <span class="string">&quot;\\;&quot;</span>)</span><br><span class="line">  text = text.replace(<span class="string">&quot;,&quot;</span>, <span class="string">&quot;\\,&quot;</span>)</span><br><span class="line">  text = text.replace(<span class="string">&quot;\n&quot;</span>, <span class="string">&quot;\\n&quot;</span>)</span><br><span class="line">  <span class="keyword">return</span> text</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">build_ics</span>(<span class="params">nick_name: <span class="built_in">str</span>, daily: <span class="built_in">dict</span></span>) -&gt; <span class="built_in">str</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;生成 ICS 日历内容。每天一个全天事件，标题包含当天收支汇总。&quot;&quot;&quot;</span></span><br><span class="line">  now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=<span class="number">8</span>)))</span><br><span class="line">  now_utc = now.astimezone(datetime.timezone.utc)</span><br><span class="line">  timestamp = now_utc.strftime(<span class="string">&quot;%Y%m%dT%H%M%SZ&quot;</span>)</span><br><span class="line"></span><br><span class="line">  lines = [</span><br><span class="line">    <span class="string">&quot;BEGIN:VCALENDAR&quot;</span>,</span><br><span class="line">    <span class="string">&quot;VERSION:2.0&quot;</span>,</span><br><span class="line">    <span class="string">&quot;PRODID:-//xlsx2ics//微信账单日历//CN&quot;</span>,</span><br><span class="line">    <span class="string">&quot;CALSCALE:GREGORIAN&quot;</span>,</span><br><span class="line">    <span class="string">&quot;METHOD:PUBLISH&quot;</span>,</span><br><span class="line">    <span class="string">&quot;X-WR-CALNAME:支出&quot;</span>,</span><br><span class="line">    <span class="string">f&quot;X-WR-CALDESC:<span class="subst">&#123;escape_ics(nick_name <span class="keyword">or</span> <span class="string">&#x27;我的&#x27;</span>)&#125;</span>的微信支付每日收支。&quot;</span>,</span><br><span class="line">  ]</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> daily:</span><br><span class="line">    first_date = <span class="built_in">min</span>(daily.keys())</span><br><span class="line">    last_date = <span class="built_in">max</span>(daily.keys())</span><br><span class="line">    lines.append(<span class="string">f&quot;X-WR-TIMEZONE:Asia/Shanghai&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> date_str <span class="keyword">in</span> <span class="built_in">sorted</span>(daily.keys()):</span><br><span class="line">      d = daily[date_str]</span><br><span class="line">      income = d[<span class="string">&quot;income&quot;</span>]</span><br><span class="line">      expense = d[<span class="string">&quot;expense&quot;</span>]</span><br><span class="line">      net = income - expense</span><br><span class="line"></span><br><span class="line">      <span class="comment"># 构建事件标题</span></span><br><span class="line">      parts = []</span><br><span class="line">      <span class="keyword">if</span> income &gt; <span class="number">0</span>:</span><br><span class="line">        parts.append(<span class="string">f&quot;收入 ¥<span class="subst">&#123;income:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">      <span class="keyword">if</span> expense &gt; <span class="number">0</span>:</span><br><span class="line">        parts.append(<span class="string">f&quot;支出 ¥<span class="subst">&#123;expense:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">      <span class="keyword">if</span> income &gt; <span class="number">0</span> <span class="keyword">and</span> expense &gt; <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">if</span> net &gt;= <span class="number">0</span>:</span><br><span class="line">          parts.append(<span class="string">f&quot;净收入 ¥<span class="subst">&#123;net:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">          parts.append(<span class="string">f&quot;净支出 ¥<span class="subst">&#123;<span class="built_in">abs</span>(net):<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">      summary = <span class="string">&quot; | &quot;</span>.join(parts)</span><br><span class="line">      <span class="keyword">if</span> <span class="keyword">not</span> summary:</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">      <span class="comment"># 日内详情</span></span><br><span class="line">      detail_lines = [</span><br><span class="line">        <span class="string">f&quot;日期: <span class="subst">&#123;date_str&#125;</span>&quot;</span>,</span><br><span class="line">      ]</span><br><span class="line">      <span class="keyword">if</span> income &gt; <span class="number">0</span>:</span><br><span class="line">        detail_lines.append(<span class="string">f&quot;收入: ¥<span class="subst">&#123;income:<span class="number">.2</span>f&#125;</span> (<span class="subst">&#123;d[<span class="string">&#x27;count_income&#x27;</span>]&#125;</span>笔)&quot;</span>)</span><br><span class="line">      <span class="keyword">if</span> expense &gt; <span class="number">0</span>:</span><br><span class="line">        detail_lines.append(<span class="string">f&quot;支出: ¥<span class="subst">&#123;expense:<span class="number">.2</span>f&#125;</span> (<span class="subst">&#123;d[<span class="string">&#x27;count_expense&#x27;</span>]&#125;</span>笔)&quot;</span>)</span><br><span class="line">      detail = <span class="string">&quot;\\n&quot;</span>.join(detail_lines)</span><br><span class="line"></span><br><span class="line">      uid = <span class="built_in">str</span>(uuid.uuid4())</span><br><span class="line">      date_compact = date_str.replace(<span class="string">&quot;-&quot;</span>, <span class="string">&quot;&quot;</span>)</span><br><span class="line"></span><br><span class="line">      lines.extend([</span><br><span class="line">        <span class="string">&quot;BEGIN:VEVENT&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;UID:<span class="subst">&#123;uid&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;DTSTART;VALUE=DATE:<span class="subst">&#123;date_compact&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;DTEND;VALUE=DATE:<span class="subst">&#123;date_compact&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;SUMMARY:<span class="subst">&#123;escape_ics(summary)&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;DESCRIPTION:<span class="subst">&#123;escape_ics(detail)&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">f&quot;DTSTAMP:<span class="subst">&#123;timestamp&#125;</span>&quot;</span>,</span><br><span class="line">        <span class="string">&quot;TRANSP:TRANSPARENT&quot;</span>,</span><br><span class="line">        <span class="string">&quot;END:VEVENT&quot;</span>,</span><br><span class="line">      ])</span><br><span class="line"></span><br><span class="line">  lines.append(<span class="string">&quot;END:VCALENDAR&quot;</span>)</span><br><span class="line">  <span class="keyword">return</span> <span class="string">&quot;\r\n&quot;</span>.join(lines) + <span class="string">&quot;\r\n&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">  parser = argparse.ArgumentParser(description=<span class="string">&quot;微信支付 XLSX 账单 → ICS 日历&quot;</span>)</span><br><span class="line">  parser.add_argument(<span class="string">&quot;xlsx&quot;</span>, <span class="built_in">help</span>=<span class="string">&quot;微信支付账单 XLSX 文件路径&quot;</span>)</span><br><span class="line">  parser.add_argument(<span class="string">&quot;-o&quot;</span>, <span class="string">&quot;--output&quot;</span>, <span class="built_in">help</span>=<span class="string">&quot;输出 ICS 文件路径（默认: 输入文件名.ics）&quot;</span>)</span><br><span class="line">  args = parser.parse_args()</span><br><span class="line"></span><br><span class="line">  xlsx_path = Path(args.xlsx)</span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> xlsx_path.exists():</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;❌ 文件不存在: <span class="subst">&#123;xlsx_path&#125;</span>&quot;</span>)</span><br><span class="line">    exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;📖 读取: <span class="subst">&#123;xlsx_path&#125;</span>&quot;</span>)</span><br><span class="line">  nick_name, daily = parse_xlsx(<span class="built_in">str</span>(xlsx_path))</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> daily:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;❌ 未找到有效的交易记录&quot;</span>)</span><br><span class="line">    exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  total_income = <span class="built_in">sum</span>(v[<span class="string">&quot;income&quot;</span>] <span class="keyword">for</span> v <span class="keyword">in</span> daily.values())</span><br><span class="line">  total_expense = <span class="built_in">sum</span>(v[<span class="string">&quot;expense&quot;</span>] <span class="keyword">for</span> v <span class="keyword">in</span> daily.values())</span><br><span class="line">  total_net = total_income - total_expense</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;👤 昵称: <span class="subst">&#123;nick_name <span class="keyword">or</span> <span class="string">&#x27;未知&#x27;</span>&#125;</span>&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;📅 日期范围: <span class="subst">&#123;<span class="built_in">min</span>(daily.keys())&#125;</span> ~ <span class="subst">&#123;<span class="built_in">max</span>(daily.keys())&#125;</span> (<span class="subst">&#123;<span class="built_in">len</span>(daily)&#125;</span>天)&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;💰 总收入: ¥<span class="subst">&#123;total_income:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;💸 总支出: ¥<span class="subst">&#123;total_expense:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;📊 净收支: ¥<span class="subst">&#123;total_net:<span class="number">.2</span>f&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line">  ics_content = build_ics(nick_name, daily)</span><br><span class="line"></span><br><span class="line">  output_path = args.output <span class="keyword">or</span> xlsx_path.with_suffix(<span class="string">&quot;.ics&quot;</span>)</span><br><span class="line">  <span class="keyword">with</span> <span class="built_in">open</span>(output_path, <span class="string">&quot;w&quot;</span>, encoding=<span class="string">&quot;utf-8&quot;</span>) <span class="keyword">as</span> f:</span><br><span class="line">    f.write(ics_content)</span><br><span class="line"></span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;✅ 已导出: <span class="subst">&#123;output_path&#125;</span>&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;   <span class="subst">&#123;<span class="built_in">len</span>(daily)&#125;</span> 个日历事件&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>()</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;📌 双击 .ics 文件即可导入到 macOS/iOS 日历。&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">  main()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这个是<a href="https://github.com/bllyds999/xwbill-calendar">项目地址</a>，如果你对这个玩具感兴趣，可以下载来玩一下。项目后续我打算继续维护，因为我正在用着，每天导出账单、双击导入日历已经成为我日常记账的习惯流程了。我觉得它本身已经很完美了，因为它真的很简单，整个设计理念就是极简实用——没有花哨的图表分析，没有复杂的账目分类，就像是你在纸质日历上写字那样纯粹直接，打开日历就能看到每天的收入支出概况，一目了然，干净利落。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E5%B0%86%E6%94%AF%E4%BB%98%E8%AE%B0%E5%BD%95%E5%AF%BC%E5%87%BA%E5%88%B0%E8%8B%B9%E6%9E%9C%E6%97%A5%E5%8E%86/</id>
    <link href="https://090909.top/2026/07/01/%E5%B0%86%E6%94%AF%E4%BB%98%E8%AE%B0%E5%BD%95%E5%AF%BC%E5%87%BA%E5%88%B0%E8%8B%B9%E6%9E%9C%E6%97%A5%E5%8E%86/"/>
    <published>2026-07-01T07:51:42.000Z</published>
    <summary>本文介绍了 1 个将微信支付账单 XLSX 文件转换为苹果 ICS 日历事件的 Python 脚本。作者为帮助母亲实现简易记账，设计并实现了该工具。脚本读取微信导出的 XLSX 账单，解析交易时间、收支类型和金额，按日期汇总每日收入与支出，然后生成 ICS 格式日历文件。生成的事件为全天事件，标题仅包含每日收支总金额和净收支，描述中保留笔数等细节，去除了店名等冗余信息，避免信息过载。用户只需在命令行指定 XLSX 文件路径，脚本即可输出 ICS 文件，双击即可导入 macOS 或 iOS 日历，每天打开手机便可直观查看收支概况。文章提供了完整的 Python 代码，包含文件解析、ICS 构建、命令行交互等模块，并给出了项目 GitHub 地址。该脚本设计极简实用，不包含图表分析或复杂分类，就像在纸质日历上写字一样纯粹直接。</summary>
    <title>微信账单同步日历：使用 Python 脚本将支付记录导出到苹果日历</title>
    <updated>2026-07-21T13:57:21.321Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="纪实" scheme="https://090909.top/categories/%E7%BA%AA%E5%AE%9E/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="生活感悟" scheme="https://090909.top/tags/%E7%94%9F%E6%B4%BB%E6%84%9F%E6%82%9F/"/>
    <category term="情绪管理" scheme="https://090909.top/tags/%E6%83%85%E7%BB%AA%E7%AE%A1%E7%90%86/"/>
    <category term="小区故事" scheme="https://090909.top/tags/%E5%B0%8F%E5%8C%BA%E6%95%85%E4%BA%8B/"/>
    <category term="不文明行为" scheme="https://090909.top/tags/%E4%B8%8D%E6%96%87%E6%98%8E%E8%A1%8C%E4%B8%BA/"/>
    <content>
      <![CDATA[<p>6 月 30 日，我醒得格外早。平时总要赖到八九点，睡到自然醒才肯挪动身子，那一天却仿佛被什么无形的东西轻轻推了一把，六点整便睁开眼，窗外的天色才刚泛出鱼肚白。我静静躺着，看着手机里的六点十二分，心里竟生出一种久违的清明与宁静——本以为这会是一整天好心情的开端，可当我坐到餐桌前，咬下第一口热乎乎的包子时，楼上骤然传来一阵尖锐刺耳的轰鸣，像是无数砂轮同时啃噬着石面。我的心猛地一沉：装修？偏偏是今天？紧接着，一股隐约的担忧涌上来——他们现在打磨石砖，后面怕不是要刷油漆吧？那刺鼻的甲醛味一旦弥漫开来，整个楼道都会遭殃。我攥紧筷子，忽然觉得那口包子也变得索然无味了。</p><p>我越想越觉得这户人家实在不通情理。楼上那间房子常年空置，铁门紧锁，灰尘积了厚厚一层，平日里连个人影都见不着。过年时整栋楼热热闹闹，邻里互相串门拜年，那时不正是焕新家居的好时节？偏要挑 6 月 30 日——学生们正忙着期末考试的紧要关头，楼下有孩子挑灯夜读，隔壁有考生临阵磨枪，这时候动工，电钻轰鸣、粉尘飞扬，若是有学生因为吸入甲醛而头晕目眩，发挥失常，这责任到底该谁来负？他们难道从不曾为人父母，不曾经历过被噪音搅得心神不宁的焦灼吗？更何况，他们怕是压根不知道，自家空置太久，连带着我们这层楼的排水管道都出了问题——每天早晚，厕所里总会涌起咕噜咕噜的怪响，随即飘出一股难以言喻的腐臭味，像是淤泥在地底发酵了百年。</p><p>这些隐患他们不闻不问，倒先急着敲敲打打，实在让人哭笑不得。嘿，楼上的电钻声越发嚣张了，像是故意追着我不放。母亲见我皱着眉捂住耳朵，叹了口气，准许我躲进房间里开空调，好歹关上门能隔去几层噪响。可即便门窗紧闭，那嗡嗡的震动仍顺着墙壁、地板，一丝丝渗进来，钻进骨头里。我索性打开自己部署的云音乐，选了一首以前玩过游戏的插曲，把音量调到刚好盖过外头的嘈杂。耳机里吉他弦音流淌，我闭上眼，试图把自己放逐进旋律的海洋里。可说来也怪，我走到书桌边，电钻声便从天花板正中砸下来；我挪到床角，那轰鸣又跟着拐了个弯，追着我落脚的方位。</p><p>我甚至忍不住胡思乱想：怕不是这装修队在我身上装了定位吧？不然怎么我走到哪儿，哪边的动静就最大，仿佛整场装修都是为我一个人量身定制的恶作剧。荒唐之余，我只能苦笑一声，把耳机又往耳道里塞紧了些。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E6%A5%BC%E4%B8%8A%E8%A3%85%E4%BF%AE%E7%9C%9F%E6%98%AF%E7%83%A6%E6%AD%BB%E4%BA%86/</id>
    <link href="https://090909.top/2026/07/01/%E6%A5%BC%E4%B8%8A%E8%A3%85%E4%BF%AE%E7%9C%9F%E6%98%AF%E7%83%A6%E6%AD%BB%E4%BA%86/"/>
    <published>2026-07-01T03:58:08.000Z</published>
    <summary>本文描述了作者在 6 月 30 日清晨被楼上装修噪音困扰的亲身经历。作者本因早醒而获得一份久违的宁静，却在吃早餐时被尖锐刺耳的打磨声打破，随即担忧后续的油漆施工会带来甲醛污染。作者对楼上住户选择在期末考试期间动工感到愤怒，认为他们不通情理，并列举了长期空置的房屋带来的排水管道问题等隐患。即使躲进房间、开启空调、播放云音乐试图隔绝噪音，电钻声仍如影随形，仿佛故意追踪作者的移动。作者无奈地猜测装修队是否在自己身上装了定位，最终只能苦笑并塞紧耳机。全文生动展现了噪音对日常生活的侵扰以及个体在面对外部干扰时的无力感与自我调侃。</summary>
    <title>楼上装修真是烦死了：楼上装修噪音追着跑，躲进音乐也逃不掉</title>
    <updated>2026-07-21T13:57:21.324Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="杂谈" scheme="https://090909.top/categories/%E6%9D%82%E8%B0%88/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="童年时光" scheme="https://090909.top/tags/%E7%AB%A5%E5%B9%B4%E6%97%B6%E5%85%89/"/>
    <category term="家庭" scheme="https://090909.top/tags/%E5%AE%B6%E5%BA%AD/"/>
    <category term="巴巴爸爸" scheme="https://090909.top/tags/%E5%B7%B4%E5%B7%B4%E7%88%B8%E7%88%B8/"/>
    <category term="动画" scheme="https://090909.top/tags/%E5%8A%A8%E7%94%BB/"/>
    <content>
      <![CDATA[<p>巴巴爸爸，这部动画片的出身堪称一场跨国文化的奇妙邂逅：一位美国艺术家在法国挥洒创意，联邦德国的制作团队赋予它骨架，日本画师再用细腻的笔触为它填上色彩，最终在全球荧幕上绽放光芒。这个组合听起来真的很世界化，仿佛一碟融合了美式幽默、法式浪漫、德式严谨和日式精致的美味大餐，端上了冷战时代各国孩子们的餐桌。它播出于美苏冷战时期，东西方阵营剑拔弩张，卫星、核弹头与意识形态的对峙填满了新闻头条，而这部柔软、温驯、只会变形玩耍的粉色小生命，却像一阵无害的暖风，悄悄吹进了铁幕两侧的家庭客厅。听起来真的很遥远，那是黑白电视尚存、录像带还是奢侈品的年代，可正是这样的时代反差，让巴巴爸爸的存在显得愈发珍贵——它不谈论政治，不站队，只关心雨后泥坑里能不能长出新的朋友。</p><p>至于名字本身，巴巴爸爸在法语的原意为棉花糖，因为棉花糖蓬松绵软、入口即化的质感，恰似父亲清晨刚刮过胡须后残留的柔软绒毛，其实直译过来就是爸爸的胡须，带着一丝家常的、温暖的亲昵感。网上很多猜测动画片主人公是什么，有人盯着它随意拉伸、鼓胀成任意几何形状的本领，信誓旦旦地说这一定是史莱姆的早期雏形，有人看到它色彩鲜艳、可塑性强，便笃定它不过是一块会说话的橡皮泥，但唯独就是没人说是棉花糖——或许是因为棉花糖太甜腻、太脆弱，配不上它那一身随意变形、天不怕地不怕的气场，可偏偏这才是它最本真的名字源头，一个被大多数人忽略的温柔秘密。这是一块可以变形的、有自主意识的棉花糖，它的身体柔软得没有骨骼的支撑，却又坚韧得能拉成桥梁、压成圆饼、拧成绳索，仿佛物理规则在它身上只是善意的建议而非铁律。</p><p>巴巴爸爸看起来就像是植物，因为一开始的描写就像是他们种在地里，画面里它安静地蜷缩在泥土中，雨水顺着叶尖滴落，它便随每一次浇灌而膨胀一分，那种缓慢、被动、依赖自然滋养的成长模式，分明就是一棵有知觉的藤蔓或花苞。但后来生蛋那集观感更像是乌龟埋卵，它慎重地刨开土坑，将圆润的蛋体一一码放整齐，再用沙土细心掩埋，最后趴在旁边静静守候——那专注而沉默的姿态，与我在视频里看到乌龟产卵时的行为几乎如出一辙，可能我是个养龟的才会那么想，从本能里就将这一幕与爬行动物的古老习性挂钩。你其实根本不用在乎为什么它一出生就是爸爸，因为巴巴爸爸就是特指法国的棉花糖，这个称呼在法语语境里自带亲昵与幽默，并不遵循汉语中“爸爸”作为亲属称谓的逻辑，至于巴巴爸爸这个词是国内当时的翻译，译者在音译与意译之间取了个巧，恰好撞上了中文里最熟悉的家庭词汇。</p><p>如果实在不能理解，那就理解成一个人出生就叫张爸爸这个名字，这不是辈分，不是年龄，只是父母登记户口时随手写下的一个符号，他三岁时被叫张爸爸，三十岁时还是被叫张爸爸，没有人会觉得奇怪——这是最棒的解答，把语言转译中的错位轻轻放下，转而拥抱那份随性而生的可爱。老动画片就是这样，开头的几个小节就能通过最直接的方式，描写出巴巴爸爸的一系列心理变化，从破土而出时的懵懂茫然，到第一次尝试变形时的惊喜雀跃，再到帮助他人后那种笨拙而真诚的满足感，全都用夸张的动作和简单的对白铺陈开来，让你看的过程中既不会被动接受太多的信息，眼球始终被明亮的色块和流畅的形变牵引着，最后又能觉得有趣和寓教于乐——它教给孩子的不是生硬的道德训诫，而是“柔软可以战胜坚硬”“变化不可怕”“帮助别人自己也会变大”这类轻盈的哲理。</p><p>其实巴巴爸爸最开始就是起源于小漫画书，几页纸的篇幅里，画师用钢笔勾出粗略的轮廓，配上几句手写体的气泡对话框，在儿童杂志的角落里安静地躺着，后来才被搬到荧幕上做成动画的。所以你能感受到这个像儿童漫画单元剧一样的描写，每一集都是一个独立的小故事，开场快、冲突简单、收尾干净，没有连续剧的负担，也没有宏大叙事的野心，这完全是正常的描写，保留了纸质阅读的碎片感和翻页时的惊喜。但当它被搬上荧幕后，却意外地锦上添花，色彩从黑白灰跃升为饱和的粉红与嫩绿，变形过程被动画师的笔触赋予了流体般的顺畅质感，再加上配音演员赋予它的憨厚嗓音，那个纸面上的棉花糖形象瞬间活了过来，有了体温，有了情绪，有了让全世界孩子伸手想拥抱的魔力。巴巴爸爸的画风很小众，它没有迪士尼式的精致背景渲染，也没有日本动画里那种水汪汪的大眼睛和飘逸的发丝，它的线条圆润得近乎笨拙，色块填充简单得像幼儿园墙上的贴画，背景常常只是几笔勾勒的云朵和栅栏。</p><p>这种返璞归真的美学在如今高清特效轰炸的视觉环境里，显得格格不入又格外清净。名字太普通了，普通到你在搜索引擎里键入“巴巴”两个字，跳出来的可能是婴儿啼哭的拟声词或是某种甜点的别称，完全无法让人联想到一个能变成任何形状的粉色生命体，因此看的人很少，它既没有热血战斗的燃点，也没有悬疑反转的钩子，只是在平静的乡间日常里演绎着家庭成员之间的小摩擦和小温情。你周围随便找个人，说不定都不知道巴巴爸爸是个什么东西，你提起它时对方可能会礼貌性地点头，但眼神里分明写着“那是某种零食的品牌吗”的困惑，这并不奇怪，因为它的黄金时代已经过去了几十年，而新一代的动画明星们正以更快的剪辑、更响亮的音效争夺着孩子们的注意力。巴巴爸爸是个可以变形的、有生命的物体，在如今看来，更像是什么科技智能体，那种随心所欲改变自身结构的本领，恰似科幻电影里液态金属机器人的翻版，再加上它似乎拥有独立思维和情感决策能力，怕不是又要拍一部电影。</p><p>可它终究不是那块冰冷的合金，它的变形是为了给迷路的小鸟搭窝，是为了帮被卡住的猫咪脱身，是为了让哭泣的孩子破涕为笑，这种纯粹的善意让它与任何科技惊悚片的设定都南辕北辙。我直到现在都记不住，巴巴爸爸的家庭成员到底都叫什么，那些绕口的法语名字像一串串打乱的音节，在我的记忆里滑来滑去，始终找不到稳固的锚点。但是如果你给个图给我，我能给你指出这些角色都喜欢什么，比如巴巴祖喜欢动物，画面里它总是抱着受伤的兔子或坐在大象背上，眼神里全是天然的亲近与关切；巴巴拉拉喜欢音乐，它身边永远飘着音符的具象化图案，有时把自己拉长成竖琴的琴弦，有时鼓胀成一面大鼓，连打喷嚏都带着旋律的起伏。当然，外国人起的名字还是太拗口难记了，巴巴布莱特、巴巴利波、巴巴贝尔……这些音节缺乏中文语境里的联想助记符，不像“红孩儿”“蓝精灵”那样一目了然，于是我们只好绕过名字，直接记住它们的颜色、形状和癖好。</p><p>用视觉替代听觉，在脑海中为每个角色贴上一张不靠语言驱动的标签，这反倒让观看的过程变得更纯粹——我们记住的不是一串字符，而是一整片会笑会闹的、柔软的粉色宇宙。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E5%96%9C%E6%AC%A2%E5%B7%B4%E5%B7%B4%E7%88%B8%E7%88%B8/</id>
    <link href="https://090909.top/2026/07/01/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E5%96%9C%E6%AC%A2%E5%B7%B4%E5%B7%B4%E7%88%B8%E7%88%B8/"/>
    <published>2026-07-01T03:57:15.000Z</published>
    <summary>本文介绍了巴巴爸爸这部动画片的跨国文化起源与独特魅力，讲述了它由美国艺术家在法国创作、联邦德国团队制作、日本画师润色而形成的国际化背景，并在冷战时期以柔软无害的形象悄然进入东西方家庭客厅。文章解释了“巴巴爸爸”在法语中意为棉花糖，源于父亲胡须的柔软质感，但常被误认为是史莱姆或橡皮泥，而其变形能力并非冷酷的科技，而是充满善意的帮助行为。本文描述了动画从漫画书发展到荧幕的过程，保留了碎片化单元剧的风格，配以返璞归真的美学和简单温暖的哲理。虽然角色名字拗口难记，但视觉特征鲜明，每个成员都有独特爱好，如巴巴祖喜爱动物、巴巴拉拉热爱音乐。整体上，巴巴爸爸凭借跨越文化和时代的温柔力量，成为一代人心中纯真美好的记忆。</summary>
    <title>为什么我喜欢巴巴爸爸：从漫画到动画，粉色棉花糖的奇遇记</title>
    <updated>2026-07-21T13:57:21.317Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="梦" scheme="https://090909.top/categories/%E6%A2%A6/"/>
    <category term="情感回忆" scheme="https://090909.top/tags/%E6%83%85%E6%84%9F%E5%9B%9E%E5%BF%86/"/>
    <category term="校园回忆" scheme="https://090909.top/tags/%E6%A0%A1%E5%9B%AD%E5%9B%9E%E5%BF%86/"/>
    <category term="科幻故事" scheme="https://090909.top/tags/%E7%A7%91%E5%B9%BB%E6%95%85%E4%BA%8B/"/>
    <category term="时间机器" scheme="https://090909.top/tags/%E6%97%B6%E9%97%B4%E6%9C%BA%E5%99%A8/"/>
    <category term="青春" scheme="https://090909.top/tags/%E9%9D%92%E6%98%A5/"/>
    <content>
      <![CDATA[<p>午后的阳光斜斜地打在新校园的走廊上，光影斑驳得像打翻了的蜜糖罐子。我刚刚从午托班过来，书包带子还勒着肩膀，陌生的教室气息混着粉笔灰钻进鼻腔。左手边两个男生凑得很近，后脑勺几乎要贴在一起，声线压得比窗外蝉鸣还低，只偶尔蹦出“诚哥”两个字，尾音带着某种暧昧的颤栗。我数着课桌上那些前任主人留下的涂鸦，心里却像有羽毛在挠——这个被他们反复咀嚼的名字，究竟藏着怎样的故事？视线偷偷往右前方瞟，诚哥的后颈绷得僵直，连耳廓都泛着不正常的红，像被火苗舔过的纸边。我侧过身凑近诚哥耳边时，闻到他校服上淡淡的汗味混着某种青涩的躁动。他的睫毛挂满了碎钻似的泪，整张脸像被水泡过的宣纸，褶皱里全是欲言又止的惶然。</p><p>他猛地抓住我手腕，指甲几乎要嵌进皮肤：“你发誓不会说出去？”声音嘶哑得像砂纸磨过生锈的铁。窗外的梧桐叶正好簌簌落下几片，日光在叶片脉络间碎成金箔，我望着他瞳孔里自己认真点头的倒影，忽然觉得整个教室的空气都安静下来，连粉笔灰都悬在半空等待判决。诚哥把脸埋在臂弯里，声音闷得像从地底传来的回响。他说那日本来是寻常的周末，女友的发梢还沾着奶茶店的焦糖香，购物袋在指间晃荡出幸福的弧度。可柏油马路中央突然裂开光的缝隙，像有人用烧红的刀划开现实——传送门里走出来的少年顶着他五年前的寸头，眼神锋锐如淬毒的匕首。那柄恶魔屠刀在霓虹灯下泛着暗红色光泽，刀锋划过空气时带着熟悉的破风声。</p><p>“你说过要当没有弱点的修罗！”五年前的自己怒吼着，刀尖直指向吓得瘫软的女孩，血珠溅到诚哥新买的球鞋上时，他听见自己心脏裂成两半的声音。诚哥说到这儿忽然揪住自己头发，指节因用力而泛白。他说记忆像被揉皱又展开的糖纸，那些穿越时空的碎片突然拼合——原来五年前那个雨夜，未来的自己也曾这样对着穿越过来的狂妄的少年吼着：“我好不容易才让那个女孩重新相信我！”此刻教室里空调嗡嗡作响，我却觉得后背渗出冷汗，仿佛看见两个诚哥在不同年份的同一秒流泪，而那个倒在血泊里的女孩，成了永远对不上的齿轮里最无辜的牺牲品。</p><p>他停止讲述时，放学铃恰好刺破沉默。我忽然能清晰看见他描述的画面——霓虹招牌把雨丝染成粉紫色，车灯汇成流淌的星河，少年跪在湿漉漉的人行道上，怀里的玫瑰像折翼的鸟。花瓣随雨水淌成浅红色的溪流，分不清是花汁还是别的什么液体，只有路灯把影子拉得又长又薄，像一枚即将被风撕碎的邮票。诚哥的指尖在课桌下轻轻发抖，而我知道，那个场景会像用劣质墨水写的字，既模糊又顽固地印在这个午后，印在两个人共同守住的秘密里。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E4%BB%96%E9%81%87%E5%88%B0%E7%9A%84%E4%BC%A4%E5%BF%83%E4%BA%8B/</id>
    <link href="https://090909.top/2026/07/01/%E4%BB%96%E9%81%87%E5%88%B0%E7%9A%84%E4%BC%A4%E5%BF%83%E4%BA%8B/"/>
    <published>2026-07-01T03:56:56.000Z</published>
    <summary>本文描述了在午后新校园的走廊与教室中，“我”观察到两个男生低语提及“诚哥”，而后诚哥向“我”吐露了 1 段关于穿越时空的遭遇。诚哥讲述自己在某个寻常周末与女友逛街时，柏油马路中央突然裂开光的缝隙，走出 1 个顶着他五年前寸头的少年，手持恶魔屠刀指向吓瘫的女孩，血溅到他的新球鞋上。随后诚哥的记忆碎片拼合——原来五年前的雨夜，未来的自己也曾这样对着穿越过来的狂妄少年怒吼，试图阻止悲剧发生，而倒在血泊里的女孩成为两个时空永远无法对合的齿轮中最无辜的牺牲品。诚哥讲述时泪流满面，指甲几乎嵌进“我”的手腕，要求发誓不说出去。“我”在放学铃声中清晰看见他描述的画面：霓虹灯下，少年跪在湿漉漉的人行道上，怀里的玫瑰如折翼的鸟，雨水与花瓣汇成浅红溪流。这段秘密像劣质墨水写的字，既模糊又顽固地定格在那个午后。</summary>
    <title>他遇到的伤心事：诚哥时空穿越奇遇，秘密与校园午后秘密誓言</title>
    <updated>2026-07-21T13:57:21.318Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="代码展示" scheme="https://090909.top/categories/%E4%BB%A3%E7%A0%81%E5%B1%95%E7%A4%BA/"/>
    <category term="技术折腾" scheme="https://090909.top/tags/%E6%8A%80%E6%9C%AF%E6%8A%98%E8%85%BE/"/>
    <category term="B 站" scheme="https://090909.top/tags/B-%E7%AB%99/"/>
    <category term="Python 脚本" scheme="https://090909.top/tags/Python-%E8%84%9A%E6%9C%AC/"/>
    <category term="Playwright" scheme="https://090909.top/tags/Playwright/"/>
    <category term="批量拉黑" scheme="https://090909.top/tags/%E6%89%B9%E9%87%8F%E6%8B%89%E9%BB%91/"/>
    <content>
      <![CDATA[<p>我真的很喜欢在 B 站上看海绵宝宝，那些无厘头的幽默总能让我忘记一天的疲惫。但不知道从什么时候开始，我的首页推荐流里混进了越来越多奇奇怪怪的东西——二次元游戏圈的党争、键政圈的对线、小鬼圈的烂梗，这些东西像牛皮癣一样甩都甩不掉。每次我只是想安安静静看个视频，评论区却总有人在吵架、钓鱼、刷屏。我尝试过点“不感兴趣”，也试过屏蔽某些关键词，但算法似乎总能找到新的方式来恶心我。说实话，B 站让我挺失望的，那个曾经充满二次元二创、鬼畜调音和经典电视剧的地方，现在变得越来越嘈杂了。</p><p>我也不是没想过反抗。B 站其实提供了一个“拉黑”功能，只要把某个用户加入黑名单，你就再也看不到他的评论、私信和动态了——相当于这个人从你的 B 站世界里彻底消失。这本来是个很好的隔离手段，但问题在于：当你看到一条令人不适的评论时，你已经读完了它的内容，已经生气了。在这种情况下，很少有人能心平气和地再点进“更多”菜单、找到“加入黑名单”、再确认一遍弹窗。而且就算你真的拉黑了这个人，你的情绪已经被破坏了，拉黑本身并不能让你高兴起来。更别提那些视频底下动辄几百上千条评论，一个一个手动拉黑根本不现实。</p><p>所以我写了一个脚本，专门解决这个问题。它叫做 Bilibili Comment Blacklist Tool，这是<a href="https://github.com/bllyds999/bilibili-comment-blacklist-tool">项目地址</a>。这个工具的原理很简单：打开一个 B 站视频页面，自动滚动评论区，找到每条评论的“更多”按钮，点击“加入黑名单”，然后确认弹窗——全程自动化，你只需要在命令行里看着它运行就行了。最关键的是，这个过程中你只会看到被拉黑用户的昵称和 UID，完全不会看到评论内容本身。也就是说，你可以批量清理一个视频底下所有评论者，而不会在这个过程中被任何一条评论恶心到。等脚本跑完，这个视频底下的人就跟你的 B 站世界再也没有关系了：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python3</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">哔哩哔哩评论区批量拉黑工具</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">DOM 结构（关键）：</span></span><br><span class="line"><span class="string">  div#body              ← 每条评论的根容器（Light DOM）</span></span><br><span class="line"><span class="string">  a#user-avatar[data-user-profile-id]  ← 用户 UID</span></span><br><span class="line"><span class="string">  div#main</span></span><br><span class="line"><span class="string">    div#header</span></span><br><span class="line"><span class="string">    bili-comment-user-info    ← Shadow DOM → #user-name &gt; a（用户名）</span></span><br><span class="line"><span class="string">    div#content</span></span><br><span class="line"><span class="string">    bili-rich-text        ← Shadow DOM → #contents（评论正文）</span></span><br><span class="line"><span class="string">    div#footer</span></span><br><span class="line"><span class="string">    bili-comment-action-buttons-renderer  ← Shadow DOM</span></span><br><span class="line"><span class="string">      div#more</span></span><br><span class="line"><span class="string">      button           ← 「更多」按钮</span></span><br><span class="line"><span class="string">      bili-comment-menu    ← Shadow DOM → ul#options &gt; li（菜单项）</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">嵌套 Shadow DOM 穿透策略：</span></span><br><span class="line"><span class="string">  - 用 Playwright 的 &gt;&gt; 组合器找到 Shadow DOM 内的按钮</span></span><br><span class="line"><span class="string">  - 用 JS evaluate + getRootNode().host 从按钮跨越 Shadow DOM 边界到 Light DOM</span></span><br><span class="line"><span class="string">  - 用 JS evaluate + shadowRoot 穿透 bili-comment-menu 的 Shadow DOM 点击菜单项</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">使用方式：</span></span><br><span class="line"><span class="string">  source venv/bin/activate</span></span><br><span class="line"><span class="string">  python main.py</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> asyncio</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> typing <span class="keyword">import</span> <span class="type">Optional</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> playwright.async_api <span class="keyword">import</span> async_playwright, Page</span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 固定配置 — Cookie 写在这里，不用每次粘贴</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在浏览器中打开 bilibili.com，DevTools → Application → Cookies，</span></span><br><span class="line"><span class="comment"># 全选复制所有 Cookie，粘贴到下面的三引号之间。</span></span><br><span class="line">COOKIE_RAW = <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 要处理的视频 URL（可留空，每次运行时输入）</span></span><br><span class="line">VIDEO_URL = <span class="string">&quot;&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># Cookie 解析</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">parse_cookie_string</span>(<span class="params">raw: <span class="built_in">str</span></span>) -&gt; <span class="built_in">list</span>[<span class="built_in">dict</span>]:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">  解析用户粘贴的 Cookie 字符串，转为 Playwright 格式。</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">  支持格式：</span></span><br><span class="line"><span class="string">    1. 浏览器 DevTools 复制： &quot;name1=value1; name2=value2; ...&quot;</span></span><br><span class="line"><span class="string">    2. Netscape 导出格式（多行，含 \t 分隔符）</span></span><br><span class="line"><span class="string">  &quot;&quot;&quot;</span></span><br><span class="line">  cookies = []</span><br><span class="line">  domain = <span class="string">&quot;.bilibili.com&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> <span class="string">&quot;\n&quot;</span> <span class="keyword">in</span> raw.strip():</span><br><span class="line">    <span class="keyword">for</span> line <span class="keyword">in</span> raw.strip().split(<span class="string">&quot;\n&quot;</span>):</span><br><span class="line">      line = line.strip()</span><br><span class="line">      <span class="keyword">if</span> <span class="keyword">not</span> line <span class="keyword">or</span> line.startswith(<span class="string">&quot;#&quot;</span>):</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">      parts = line.split(<span class="string">&quot;\t&quot;</span>)</span><br><span class="line">      <span class="keyword">if</span> <span class="built_in">len</span>(parts) &gt;= <span class="number">7</span>:</span><br><span class="line">        name, value = parts[<span class="number">5</span>], parts[<span class="number">6</span>]</span><br><span class="line">      <span class="keyword">elif</span> <span class="string">&quot;=&quot;</span> <span class="keyword">in</span> line:</span><br><span class="line">        name, value = line.split(<span class="string">&quot;=&quot;</span>, <span class="number">1</span>)</span><br><span class="line">      <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">      cookies.append(&#123;</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: name.strip(),</span><br><span class="line">        <span class="string">&quot;value&quot;</span>: value.strip(),</span><br><span class="line">        <span class="string">&quot;domain&quot;</span>: domain,</span><br><span class="line">        <span class="string">&quot;path&quot;</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">        <span class="string">&quot;httpOnly&quot;</span>: <span class="literal">False</span>,</span><br><span class="line">        <span class="string">&quot;secure&quot;</span>: <span class="literal">True</span>,</span><br><span class="line">        <span class="string">&quot;sameSite&quot;</span>: <span class="string">&quot;Lax&quot;</span>,</span><br><span class="line">      &#125;)</span><br><span class="line">  <span class="keyword">else</span>:</span><br><span class="line">    <span class="keyword">for</span> pair <span class="keyword">in</span> raw.split(<span class="string">&quot;;&quot;</span>):</span><br><span class="line">      pair = pair.strip()</span><br><span class="line">      <span class="keyword">if</span> <span class="string">&quot;=&quot;</span> <span class="keyword">not</span> <span class="keyword">in</span> pair:</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">      name, value = pair.split(<span class="string">&quot;=&quot;</span>, <span class="number">1</span>)</span><br><span class="line">      cookies.append(&#123;</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: name.strip(),</span><br><span class="line">        <span class="string">&quot;value&quot;</span>: value.strip(),</span><br><span class="line">        <span class="string">&quot;domain&quot;</span>: domain,</span><br><span class="line">        <span class="string">&quot;path&quot;</span>: <span class="string">&quot;/&quot;</span>,</span><br><span class="line">        <span class="string">&quot;httpOnly&quot;</span>: <span class="literal">False</span>,</span><br><span class="line">        <span class="string">&quot;secure&quot;</span>: <span class="literal">True</span>,</span><br><span class="line">        <span class="string">&quot;sameSite&quot;</span>: <span class="string">&quot;Lax&quot;</span>,</span><br><span class="line">      &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> cookies:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;⚠️  未解析到任何 Cookie，请检查输入格式。&quot;</span>)</span><br><span class="line">    sys.exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="built_in">print</span>(<span class="string">f&quot;✅ 解析到 <span class="subst">&#123;<span class="built_in">len</span>(cookies)&#125;</span> 个 Cookie&quot;</span>)</span><br><span class="line">  <span class="keyword">return</span> cookies</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 获取评论信息（UID + 用户名），跨越 Shadow DOM 边界</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">get_comment_info</span>(<span class="params">button</span>) -&gt; <span class="built_in">dict</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">  从「更多」按钮出发，跨越 Shadow DOM 边界到 Light DOM，</span></span><br><span class="line"><span class="string">  提取评论的用户 UID 和用户名。</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">  返回: &#123;&quot;uid&quot;: str, &quot;username&quot;: str&#125;</span></span><br><span class="line"><span class="string">  &quot;&quot;&quot;</span></span><br><span class="line">  info = <span class="keyword">await</span> button.evaluate(<span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">    (btn) =&gt; &#123;</span></span><br><span class="line"><span class="string">      // Step 1: 从按钮所在的 Shadow DOM 跳到 Light DOM</span></span><br><span class="line"><span class="string">      const actionButtons = btn.getRootNode().host;</span></span><br><span class="line"><span class="string">      if (!actionButtons) return &#123;uid: null, username: &#x27;未知&#x27;&#125;;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      const footer = actionButtons.parentElement;</span></span><br><span class="line"><span class="string">      if (!footer) return &#123;uid: null, username: &#x27;未知&#x27;&#125;;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      const main = footer.parentElement;</span></span><br><span class="line"><span class="string">      if (!main) return &#123;uid: null, username: &#x27;未知&#x27;&#125;;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      const body = main.parentElement;</span></span><br><span class="line"><span class="string">      if (!body) return &#123;uid: null, username: &#x27;未知&#x27;&#125;;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      // Step 2: 从 div#body 的子元素中获取用户信息</span></span><br><span class="line"><span class="string">      const avatar = body.querySelector(&#x27;:scope &gt; a#user-avatar&#x27;);</span></span><br><span class="line"><span class="string">      const profileId = avatar ? avatar.getAttribute(&#x27;data-user-profile-id&#x27;) : null;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      // Step 3: 穿透 bili-comment-user-info 的 Shadow DOM 获取用户名</span></span><br><span class="line"><span class="string">      const userInfo = body.querySelector(&#x27;bili-comment-user-info&#x27;);</span></span><br><span class="line"><span class="string">      let username = &#x27;未知&#x27;;</span></span><br><span class="line"><span class="string">      if (userInfo &amp;&amp; userInfo.shadowRoot) &#123;</span></span><br><span class="line"><span class="string">        const nameLink = userInfo.shadowRoot.querySelector(&#x27;#user-name a&#x27;);</span></span><br><span class="line"><span class="string">        if (nameLink) &#123;</span></span><br><span class="line"><span class="string">          username = nameLink.textContent.trim();</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      // Step 4: 回退 — 用 bili-rich-text 中的评论内容前20字做标识</span></span><br><span class="line"><span class="string">      let snippet = &#x27;&#x27;;</span></span><br><span class="line"><span class="string">      const richText = body.querySelector(&#x27;bili-rich-text&#x27;);</span></span><br><span class="line"><span class="string">      if (richText &amp;&amp; richText.shadowRoot) &#123;</span></span><br><span class="line"><span class="string">        const contents = richText.shadowRoot.querySelector(&#x27;#contents&#x27;);</span></span><br><span class="line"><span class="string">        if (contents) &#123;</span></span><br><span class="line"><span class="string">          snippet = contents.textContent.trim().substring(0, 30);</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">      return &#123;</span></span><br><span class="line"><span class="string">        uid: profileId || (&#x27;fallback-&#x27; + snippet),</span></span><br><span class="line"><span class="string">        username: username,</span></span><br><span class="line"><span class="string">        snippet: snippet,</span></span><br><span class="line"><span class="string">      &#125;;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">  &#x27;&#x27;&#x27;</span>)</span><br><span class="line">  <span class="keyword">return</span> info</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 确认弹窗处理</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">handle_confirmation_dialog</span>(<span class="params">page: Page, timeout: <span class="built_in">float</span> = <span class="number">3.0</span></span>) -&gt; <span class="built_in">bool</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">  等待并自动点击 B 站「确定拉黑」弹窗中的确认按钮。</span></span><br><span class="line"><span class="string">  &quot;&quot;&quot;</span></span><br><span class="line">  confirm_selectors = [</span><br><span class="line">    <span class="string">&quot;text=确定&quot;</span>,</span><br><span class="line">    <span class="string">&quot;text=确认&quot;</span>,</span><br><span class="line">    <span class="string">&quot;button:has-text(&#x27;确定&#x27;)&quot;</span>,</span><br><span class="line">    <span class="string">&quot;button:has-text(&#x27;确认&#x27;)&quot;</span>,</span><br><span class="line">    <span class="string">&quot;[class*=&#x27;primary&#x27;]:has-text(&#x27;确定&#x27;)&quot;</span>,</span><br><span class="line">    <span class="string">&quot;[class*=&#x27;primary&#x27;]:has-text(&#x27;确认&#x27;)&quot;</span>,</span><br><span class="line">    <span class="string">&quot;.bili-modal button:has-text(&#x27;确定&#x27;)&quot;</span>,</span><br><span class="line">    <span class="string">&quot;[class*=&#x27;dialog&#x27;] button:has-text(&#x27;确定&#x27;)&quot;</span>,</span><br><span class="line">  ]</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">int</span>(timeout * <span class="number">10</span>)):</span><br><span class="line">    <span class="keyword">for</span> sel <span class="keyword">in</span> confirm_selectors:</span><br><span class="line">      <span class="keyword">try</span>:</span><br><span class="line">        btn = page.locator(sel).first</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">await</span> btn.is_visible(timeout=<span class="number">100</span>):</span><br><span class="line">          <span class="keyword">await</span> btn.click()</span><br><span class="line">          <span class="keyword">await</span> asyncio.sleep(<span class="number">0.5</span>)</span><br><span class="line">          <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">      <span class="keyword">except</span> Exception:</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">await</span> asyncio.sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 处理单条评论：点更多 → 点加入黑名单</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">process_one_comment</span>(<span class="params">page: Page, button</span>) -&gt; <span class="built_in">bool</span>:</span><br><span class="line">  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">  处理一条评论的拉黑操作（全程 JS evaluate，跳过 Playwright 可见性检查）：</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    1. 强制设置 CSS 让被隐藏的「更多」按钮可见</span></span><br><span class="line"><span class="string">    2. 点击「更多」按钮</span></span><br><span class="line"><span class="string">    3. 穿透 bili-comment-menu 的 Shadow DOM → 点击「加入黑名单」</span></span><br><span class="line"><span class="string">    4. 处理确认弹窗</span></span><br><span class="line"><span class="string">  &quot;&quot;&quot;</span></span><br><span class="line">  <span class="keyword">try</span>:</span><br><span class="line">    clicked = <span class="keyword">await</span> button.evaluate(<span class="string">&#x27;&#x27;&#x27;</span></span><br><span class="line"><span class="string">      async (btn) =&gt; &#123;</span></span><br><span class="line"><span class="string">        // --- 1. 强制让「更多」按钮及其容器可见 ---</span></span><br><span class="line"><span class="string">        // B 站用 CSS 变量 --bili-comment-hover-more-display 控制显隐，</span></span><br><span class="line"><span class="string">        // 默认 display:none，只有鼠标悬停才出现。</span></span><br><span class="line"><span class="string">        // 直接改 inline style 强制露出。</span></span><br><span class="line"><span class="string">        const moreDiv = btn.closest(&#x27;div#more&#x27;);</span></span><br><span class="line"><span class="string">        if (moreDiv) &#123;</span></span><br><span class="line"><span class="string">          moreDiv.style.setProperty(&#x27;display&#x27;, &#x27;block&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">          moreDiv.style.setProperty(&#x27;visibility&#x27;, &#x27;visible&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">          moreDiv.style.setProperty(&#x27;opacity&#x27;, &#x27;1&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        btn.style.setProperty(&#x27;display&#x27;, &#x27;inline-block&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">        btn.style.setProperty(&#x27;visibility&#x27;, &#x27;visible&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">        btn.style.setProperty(&#x27;opacity&#x27;, &#x27;1&#x27;, &#x27;important&#x27;);</span></span><br><span class="line"><span class="string">        // 等一帧确保样式生效</span></span><br><span class="line"><span class="string">        await new Promise(r =&gt; requestAnimationFrame(r));</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        // --- 2. 点击「更多」按钮 ---</span></span><br><span class="line"><span class="string">        btn.dispatchEvent(new MouseEvent(&#x27;click&#x27;, &#123;bubbles: true, cancelable: true&#125;));</span></span><br><span class="line"><span class="string">        await new Promise(r =&gt; setTimeout(r, 400));</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        // --- 3. 在 bili-comment-menu 的 Shadow DOM 中点击「加入黑名单」---</span></span><br><span class="line"><span class="string">        if (!moreDiv) return false;</span></span><br><span class="line"><span class="string">        const menu = moreDiv.querySelector(&#x27;bili-comment-menu&#x27;);</span></span><br><span class="line"><span class="string">        if (!menu || !menu.shadowRoot) return false;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        const items = menu.shadowRoot.querySelectorAll(&#x27;li&#x27;);</span></span><br><span class="line"><span class="string">        for (const li of items) &#123;</span></span><br><span class="line"><span class="string">          if (li.textContent &amp;&amp; li.textContent.includes(&#x27;加入黑名单&#x27;)) &#123;</span></span><br><span class="line"><span class="string">            li.dispatchEvent(new MouseEvent(&#x27;click&#x27;, &#123;bubbles: true, cancelable: true&#125;));</span></span><br><span class="line"><span class="string">            return true;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">        return false;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &#x27;&#x27;&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> clicked:</span><br><span class="line">      <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">await</span> page.get_by_text(<span class="string">&quot;加入黑名单&quot;</span>, exact=<span class="literal">True</span>).first.click(timeout=<span class="number">2000</span>)</span><br><span class="line">        clicked = <span class="literal">True</span></span><br><span class="line">      <span class="keyword">except</span> Exception:</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> clicked:</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 4. 等待并处理确认弹窗</span></span><br><span class="line">    <span class="keyword">await</span> asyncio.sleep(<span class="number">0.8</span>)</span><br><span class="line">    <span class="keyword">await</span> handle_confirmation_dialog(page, timeout=<span class="number">2.0</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;   ❌ 处理出错: <span class="subst">&#123;e&#125;</span>&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 主循环：处理一条 → 等待页面刷新 → 下一条</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">run_blacklist_loop</span>(<span class="params">page: Page</span>):</span><br><span class="line">  <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">  主循环（适配 B 站拉黑后自动刷新评论的行为）：</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    1. 找到一条未处理的评论 → 拉黑</span></span><br><span class="line"><span class="string">    2. 等待页面自动刷新（该评论消失，新评论顶上）</span></span><br><span class="line"><span class="string">    3. 继续找下一条</span></span><br><span class="line"><span class="string">    4. 当前可见的都处理完了 → 缓慢滚动加载更多</span></span><br><span class="line"><span class="string">    5. 到达底部且无新评论 → 结束</span></span><br><span class="line"><span class="string">  &quot;&quot;&quot;</span></span><br><span class="line">  processed_uids: <span class="built_in">set</span>[<span class="built_in">str</span>] = <span class="built_in">set</span>()</span><br><span class="line">  total_blacklisted = <span class="number">0</span></span><br><span class="line">  no_new_streak = <span class="number">0</span>       <span class="comment"># 连续&quot;找不到未处理评论&quot;的次数</span></span><br><span class="line">  scroll_accumulator = <span class="number">0</span>    <span class="comment"># 累计滚动距离，偶尔需要滚一下加载更多</span></span><br><span class="line"></span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;\n🚀 开始处理评论（拉黑一条 → 页面自动刷新 → 下一条）...\n&quot;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    <span class="comment"># --- 尝试找一条未处理的评论 ---</span></span><br><span class="line">    buttons = <span class="keyword">await</span> page.locator(</span><br><span class="line">      <span class="string">&quot;bili-comment-action-buttons-renderer &gt;&gt; div#more &gt; button&quot;</span></span><br><span class="line">    ).<span class="built_in">all</span>()</span><br><span class="line"></span><br><span class="line">    found_one = <span class="literal">False</span></span><br><span class="line">    <span class="keyword">for</span> i, button <span class="keyword">in</span> <span class="built_in">enumerate</span>(buttons):</span><br><span class="line">      <span class="keyword">try</span>:</span><br><span class="line">        info = <span class="keyword">await</span> get_comment_info(button)</span><br><span class="line">        uid = info.get(<span class="string">&quot;uid&quot;</span>, <span class="string">f&quot;unknown-<span class="subst">&#123;i&#125;</span>&quot;</span>)</span><br><span class="line">        username = info.get(<span class="string">&quot;username&quot;</span>, <span class="string">&quot;未知&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> uid <span class="keyword">in</span> processed_uids:</span><br><span class="line">          <span class="keyword">continue</span>  <span class="comment"># 已拉黑过</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 找到了！处理它</span></span><br><span class="line">        found_one = <span class="literal">True</span></span><br><span class="line">        processed_uids.add(uid)</span><br><span class="line"></span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;🔨 [<span class="subst">&#123;total_blacklisted + <span class="number">1</span>&#125;</span>] 正在拉黑: <span class="subst">&#123;username&#125;</span> (UID: <span class="subst">&#123;uid&#125;</span>) ...&quot;</span>)</span><br><span class="line"></span><br><span class="line">        success = <span class="keyword">await</span> process_one_comment(page, button)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> success:</span><br><span class="line">          total_blacklisted += <span class="number">1</span></span><br><span class="line">          <span class="built_in">print</span>(<span class="string">f&quot;   ✅ 已拉黑: <span class="subst">&#123;username&#125;</span>（累计 <span class="subst">&#123;total_blacklisted&#125;</span> 人）&quot;</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">          <span class="built_in">print</span>(<span class="string">f&quot;   ⚠️  跳过: <span class="subst">&#123;username&#125;</span>（菜单点击失败）&quot;</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 拉黑后 B 站会刷新评论区，等待 DOM 稳定</span></span><br><span class="line">        <span class="keyword">await</span> asyncio.sleep(random.uniform(<span class="number">1.5</span>, <span class="number">2.5</span>))</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 处理完一条就 break，重新扫描（因为页面已刷新，旧元素可能失效）</span></span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">except</span> Exception:</span><br><span class="line">        <span class="comment"># 页面刷新导致元素失效是正常的，跳过这条重新扫描</span></span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># --- 根据结果决定下一步 ---</span></span><br><span class="line">    <span class="keyword">if</span> found_one:</span><br><span class="line">      no_new_streak = <span class="number">0</span></span><br><span class="line">      <span class="keyword">continue</span>  <span class="comment"># 继续找下一条可见评论</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># --- 当前可见评论都已处理，需要滚动加载更多 ---</span></span><br><span class="line">    no_new_streak += <span class="number">1</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> no_new_streak &gt;= <span class="number">4</span>:</span><br><span class="line">      <span class="comment"># 连续多次找不到新评论，可能到底了</span></span><br><span class="line">      <span class="built_in">print</span>(<span class="string">&quot;\n⏳ 连续多次未发现新评论，尝试最后滚动...&quot;</span>)</span><br><span class="line">      <span class="keyword">await</span> page.evaluate(<span class="string">&quot;window.scrollBy(0, 1000)&quot;</span>)</span><br><span class="line">      <span class="keyword">await</span> asyncio.sleep(<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line">      <span class="comment"># 最终扫描</span></span><br><span class="line">      any_new = <span class="literal">False</span></span><br><span class="line">      final_buttons = <span class="keyword">await</span> page.locator(</span><br><span class="line">        <span class="string">&quot;bili-comment-action-buttons-renderer &gt;&gt; div#more &gt; button&quot;</span></span><br><span class="line">      ).<span class="built_in">all</span>()</span><br><span class="line">      <span class="keyword">for</span> b <span class="keyword">in</span> final_buttons:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">          info = <span class="keyword">await</span> get_comment_info(b)</span><br><span class="line">          <span class="keyword">if</span> info.get(<span class="string">&quot;uid&quot;</span>) <span class="keyword">and</span> info.get(<span class="string">&quot;uid&quot;</span>) <span class="keyword">not</span> <span class="keyword">in</span> processed_uids:</span><br><span class="line">            any_new = <span class="literal">True</span></span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        <span class="keyword">except</span> Exception:</span><br><span class="line">          <span class="comment"># 元素可能已失效（页面变化），跳过</span></span><br><span class="line">          <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> <span class="keyword">not</span> any_new:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;\n🏁 已完成！共拉黑 <span class="subst">&#123;total_blacklisted&#125;</span> 人。&quot;</span>)</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">      <span class="keyword">else</span>:</span><br><span class="line">        no_new_streak = <span class="number">0</span></span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;   发现新评论，继续处理...\n&quot;</span>)</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># --- 缓慢滚动，加载更多评论 ---</span></span><br><span class="line">    scroll_delta = random.randint(<span class="number">300</span>, <span class="number">500</span>)</span><br><span class="line">    current_scroll = <span class="keyword">await</span> page.evaluate(<span class="string">&quot;window.scrollY&quot;</span>)</span><br><span class="line">    page_height = <span class="keyword">await</span> page.evaluate(<span class="string">&quot;document.body.scrollHeight&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">await</span> page.evaluate(<span class="string">f&quot;window.scrollBy(0, <span class="subst">&#123;scroll_delta&#125;</span>)&quot;</span>)</span><br><span class="line"></span><br><span class="line">    wait_time = random.uniform(<span class="number">2.0</span>, <span class="number">3.5</span>)</span><br><span class="line">    <span class="keyword">await</span> asyncio.sleep(wait_time)</span><br><span class="line"></span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;   📜 滚动 <span class="subst">&#123;scroll_delta&#125;</span>px | 位置 <span class="subst">&#123;current_scroll&#125;</span>/<span class="subst">&#123;page_height&#125;</span> | 已拉黑 <span class="subst">&#123;total_blacklisted&#125;</span> 人&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 如果到底了</span></span><br><span class="line">    <span class="keyword">if</span> current_scroll + scroll_delta &gt;= page_height - <span class="number">100</span>:</span><br><span class="line">      <span class="keyword">await</span> asyncio.sleep(<span class="number">3</span>)  <span class="comment"># 等待可能的懒加载</span></span><br><span class="line">      new_height = <span class="keyword">await</span> page.evaluate(<span class="string">&quot;document.body.scrollHeight&quot;</span>)</span><br><span class="line">      <span class="keyword">if</span> new_height &lt;= page_height:</span><br><span class="line">        no_new_streak += <span class="number">1</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> total_blacklisted</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"><span class="comment"># 程序入口</span></span><br><span class="line"><span class="comment"># ============================================================</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;=&quot;</span> * <span class="number">60</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;  哔哩哔哩评论区 · 批量拉黑工具&quot;</span>)</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;=&quot;</span> * <span class="number">60</span>)</span><br><span class="line">  <span class="built_in">print</span>()</span><br><span class="line"></span><br><span class="line">  <span class="comment"># --- 获取 Cookie ---</span></span><br><span class="line">  cookie_str = COOKIE_RAW.strip()</span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> cookie_str:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;❌ 请先在 main.py 顶部的 COOKIE_RAW 中粘贴你的 B 站 Cookie。&quot;</span>)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;   浏览器 DevTools → Application → Cookies → 全选复制 → 粘贴到三引号之间。&quot;</span>)</span><br><span class="line">    sys.exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># --- 获取视频 URL ---</span></span><br><span class="line">  video_url = VIDEO_URL.strip()</span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> video_url:</span><br><span class="line">    video_url = <span class="built_in">input</span>(<span class="string">&quot;🔗 请输入视频页面 URL: &quot;</span>).strip()</span><br><span class="line">  <span class="keyword">else</span>:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;🔗 使用配置中的视频 URL: <span class="subst">&#123;video_url&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> <span class="keyword">not</span> video_url:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;❌ 未输入视频 URL，程序退出。&quot;</span>)</span><br><span class="line">    sys.exit(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># --- 解析 Cookie ---</span></span><br><span class="line">  cookies = parse_cookie_string(cookie_str)</span><br><span class="line"></span><br><span class="line">  <span class="comment"># --- 启动无头浏览器 ---</span></span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;\n🌐 正在启动无头浏览器...&quot;</span>)</span><br><span class="line">  <span class="keyword">async</span> <span class="keyword">with</span> async_playwright() <span class="keyword">as</span> p:</span><br><span class="line">    browser = <span class="keyword">await</span> p.chromium.launch(</span><br><span class="line">      headless=<span class="literal">True</span>,</span><br><span class="line">      args=[</span><br><span class="line">        <span class="string">&quot;--disable-blink-features=AutomationControlled&quot;</span>,</span><br><span class="line">        <span class="string">&quot;--no-sandbox&quot;</span>,</span><br><span class="line">      ],</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    context = <span class="keyword">await</span> browser.new_context(</span><br><span class="line">      viewport=&#123;<span class="string">&quot;width&quot;</span>: <span class="number">1920</span>, <span class="string">&quot;height&quot;</span>: <span class="number">1080</span>&#125;,</span><br><span class="line">      user_agent=(</span><br><span class="line">        <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) &quot;</span></span><br><span class="line">        <span class="string">&quot;AppleWebKit/537.36 (KHTML, like Gecko) &quot;</span></span><br><span class="line">        <span class="string">&quot;Chrome/131.0.0.0 Safari/537.36&quot;</span></span><br><span class="line">      ),</span><br><span class="line">      locale=<span class="string">&quot;zh-CN&quot;</span>,</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="keyword">await</span> context.add_cookies(cookies)</span><br><span class="line"></span><br><span class="line">    page = <span class="keyword">await</span> context.new_page()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 自动接受原生 alert/confirm 弹窗（备用）</span></span><br><span class="line">    page.on(<span class="string">&quot;dialog&quot;</span>, <span class="keyword">lambda</span> dialog: asyncio.ensure_future(_accept_dialog(dialog)))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># --- 打开视频页面 ---</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;📄 正在加载: <span class="subst">&#123;video_url&#125;</span>&quot;</span>)</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">      <span class="keyword">await</span> page.goto(video_url, wait_until=<span class="string">&quot;domcontentloaded&quot;</span>, timeout=<span class="number">30000</span>)</span><br><span class="line">    <span class="keyword">except</span> Exception:</span><br><span class="line">      <span class="built_in">print</span>(<span class="string">&quot;⚠️  页面加载超时，尝试继续...&quot;</span>)</span><br><span class="line">      <span class="keyword">await</span> page.wait_for_timeout(<span class="number">3000</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">      <span class="keyword">await</span> page.wait_for_load_state(<span class="string">&quot;load&quot;</span>, timeout=<span class="number">15000</span>)</span><br><span class="line">    <span class="keyword">except</span> Exception:</span><br><span class="line">      <span class="keyword">pass</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;✅ 页面加载完成&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 等待评论区渲染</span></span><br><span class="line">    <span class="keyword">await</span> asyncio.sleep(<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 先滚一下，触发评论区懒加载</span></span><br><span class="line">    <span class="keyword">await</span> page.evaluate(<span class="string">&quot;window.scrollBy(0, 800)&quot;</span>)</span><br><span class="line">    <span class="keyword">await</span> asyncio.sleep(<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># --- 主循环 ---</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">      total = <span class="keyword">await</span> run_blacklist_loop(page)</span><br><span class="line">      <span class="built_in">print</span>(<span class="string">f&quot;\n🎉 程序运行完毕，共拉黑 <span class="subst">&#123;total&#125;</span> 人。&quot;</span>)</span><br><span class="line">    <span class="keyword">except</span> KeyboardInterrupt:</span><br><span class="line">      <span class="built_in">print</span>(<span class="string">f&quot;\n⏹️  用户中断。&quot;</span>)</span><br><span class="line">    <span class="keyword">finally</span>:</span><br><span class="line">      <span class="keyword">await</span> browser.close()</span><br><span class="line">      <span class="built_in">print</span>(<span class="string">&quot;👋 浏览器已关闭。&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">_accept_dialog</span>(<span class="params">dialog</span>):</span><br><span class="line">  <span class="string">&quot;&quot;&quot;自动接受浏览器原生弹窗&quot;&quot;&quot;</span></span><br><span class="line">  <span class="keyword">try</span>:</span><br><span class="line">    <span class="keyword">await</span> dialog.accept()</span><br><span class="line">  <span class="keyword">except</span> Exception:</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">  asyncio.run(main())</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>说起来简单，但实际写这个脚本的时候遇到了不少麻烦。首先，B 站的评论组件使用了嵌套的 Shadow DOM，里面包着 <code>bili-comment-menu</code>，常规的 DOM 选择器根本拿不到里面的按钮。其次，B 站的“更多”按钮默认是隐藏的，它通过一个 CSS 变量控制显隐，只有鼠标悬停在评论上才会出现。Playwright 的可见性检查在这种元素上会直接超时。我的解决方案是全部在 JavaScript 层面操作：用 <code>element.evaluate()</code> 强制覆盖 CSS 样式让按钮可见，再用 <code>dispatchEvent</code> 模拟点击事件——即使元素是 <code>display:none</code> 也能正常工作。</p><p>另外，每次拉黑一个人之后 B 站会自动刷新评论区，脚本需要实时重新扫描，并且按 UID 去重，避免重复拉黑同一个人。如果你想自己试试这个工具，部署流程并不复杂，但需要一点命令行基础。首先把项目克隆到本地，然后创建 Python 虚拟环境并激活——我推荐用虚拟环境，这样所有依赖都装在项目目录里，不会污染系统。接着安装依赖：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">python3 -m venv .venv</span><br><span class="line">.venv/bin/pip install -r requirements.txt</span><br><span class="line">.venv/bin/playwright install chromium</span><br></pre></td></tr></table></figure><p>下载 Playwright 所需的 Chromium 浏览器近 200MB，如果网络好的话不需要等待多久。最关键的一步是配置 Cookie：打开 B 站网页，按 F12 打开开发者工具，复制所有 Cookie（这一步在网络上很多人写教程，可自行向 AI 提问该步骤，或者在搜索引擎搜索“如何提取页面 Cookie”），粘贴到 <code>main.py</code> 里 COOKIE_RAW 的三引号中间。这个 Cookie 包含了你的登录状态，非常重要，千万不要提交到 Git 或者分享给任何人，最后在 <code>main.py</code> 里填上你要处理的视频链接。一切配置好之后，在终端里激活虚拟环境，运行这段命令就行了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.venv/bin/python main.py</span><br></pre></td></tr></table></figure><p>脚本会启动一个无头浏览器（你看不到窗口），自动打开视频页面，然后开始缓慢滚动评论区，等待 2 到 3.5 秒让评论加载出来。每找到一条未处理的评论，脚本就会执行拉黑操作，然后 B 站刷新评论区，脚本继续处理下一条。命令行里会实时输出进度。当所有可见评论都处理完后，脚本会继续滚动加载更多，直到到达评论区底部，然后自动退出。整个过程你只需要看着屏幕，什么都不用做。</p><p>最后必须强调一点：使用这个脚本有封号风险。因为脚本用到了你的 B 站 Cookie，相当于模拟你在浏览器里的操作，B 站的风控系统可能会检测到异常行为。为了降低风险，我在脚本里加入了随机延迟——操作之间间隔 0.5 到 1.5 秒，滚动间隔 2 到 3.5 秒——尽可能模仿人类的操作节奏。这个工具仅供学习研究使用，我会根据实际需求持续维护，未来计划增加按关键词拉黑、按用户名拉黑等更精细的功能，让大家能更精准地过滤掉不想看到的内容，还大家一个清净的 B 站。欢迎大家收藏和提交反馈。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E6%89%B9%E9%87%8F%E6%8B%89%E9%BB%91-B-%E7%AB%99%E8%AF%84%E8%AE%BA%E5%8C%BA%E8%B4%A6%E5%8F%B7/</id>
    <link href="https://090909.top/2026/07/01/%E6%89%B9%E9%87%8F%E6%8B%89%E9%BB%91-B-%E7%AB%99%E8%AF%84%E8%AE%BA%E5%8C%BA%E8%B4%A6%E5%8F%B7/"/>
    <published>2026-07-01T03:56:46.000Z</published>
    <summary>本文介绍了作者为解决 B 站评论区充斥不适内容而开发的 Bilibili Comment Blacklist Tool 脚本。该工具基于 Playwright 框架，能够自动滚动评论、点击“更多”按钮并执行“加入黑名单”操作，全程不显示评论内容，避免用户情绪污染。文章详细阐述了脚本面临的两大技术挑战：嵌套 Shadow DOM 的结构穿越以及默认隐藏的“更多”按钮，并给出通过 JavaScript evaluate 强制覆写 CSS 样式、使用 dispatchEvent 模拟点击的解决方案。同时，脚本处理了拉黑后评论区自动刷新的情况，通过 UID 去重避免重复拉黑。部署步骤包括克隆项目、创建 Python 虚拟环境、安装依赖及 Playwright 的 Chromium 浏览器，并需将 B 站 Cookie 粘贴到配置中。文章最后强调该工具仅供学习研究，存在封号风险，作者通过加入随机延迟（0.5 - 3.5 秒）模拟人类操作以降低检测概率，并计划未来增加按关键词或用户名拉黑等精细功能，帮助用户过滤不良内容。</summary>
    <title>批量拉黑 B 站评论区账号：评论区太乱？这个脚本帮你批量拉黑</title>
    <updated>2026-07-21T13:57:21.323Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="游戏" scheme="https://090909.top/categories/%E6%B8%B8%E6%88%8F/"/>
    <category term="我的世界" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="游戏攻略" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E6%94%BB%E7%95%A5/"/>
    <category term="我的世界攻略" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C%E6%94%BB%E7%95%A5/"/>
    <category term="游戏趣味玩法" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E8%B6%A3%E5%91%B3%E7%8E%A9%E6%B3%95/"/>
    <category term="物品模型" scheme="https://090909.top/tags/%E7%89%A9%E5%93%81%E6%A8%A1%E5%9E%8B/"/>
    <content>
      <![CDATA[<p><img src="/assets/images/illustrations/minecraft-62.webp"></p><p>注意看，这是一个存在于我的世界中的钻石物品。它看起来晶莹剔透，表面折射着标志性的淡蓝色光泽，名字也叫“钻石”，它竟可以像雪球一样被用力向前投掷出去。纹理依旧是那个玩家们再熟悉不过的钻石纹理，边缘锋利，棱角分明，但它的行为逻辑却完整地继承了雪球的所有特性：抛出时呈抛物线轨迹，命中生物没有伤害，还能触发投掷类物品特有的音效。这样一个昂贵的矿物被漫不经心地抛向天空时，场面显得格外荒诞，仿佛一个暴发户把价值连城的钻石当作廉价石子，肆意地朝着天际线挥霍炫耀，让人在好笑之余又忍不住心疼。</p><p><img src="/assets/images/illustrations/minecraft-63.webp"></p><p>而这是一把三叉戟，它是于 1.13 版本正式加入《我的世界》的投掷类远程武器，拥有着独特的海洋主题纹理和充满力量感的造型。你看它的纹理完全正常，名字也保持着系统默认的标准字体，而不是那种被铁砧修改后显示的斜体字，一切看起来都再正常不过。但当我蓄力准备投掷这根三叉戟时，诡异的事情发生了：我的手臂并没有做出三叉戟特有的后拉动作，反而是拉起了弓弦，呈现出弓类武器独有的蓄力姿态，而且从弓弦上飞出去的也并非三叉戟本身，而是一支再普通不过的箭矢。这种视觉与逻辑上的割裂感令人困惑不已，仿佛游戏机制被彻底打乱重组。</p><p><img src="/assets/images/illustrations/minecraft-64.webp"></p><p>这可不是我修改了材质文件，也不是在资源包里塞入了什么偷偷替换行为的配置文件，更不是借助任何第三方模组或作弊工具实现的障眼法。这就是《我的世界》于今年正式加入的全新指令语法，它是 <code>give</code> 指令配套的一个 NBT 标签，名字叫作 <code>item_model</code>，直译过来就是“物品模型”的意思，后面可以跟着任意合法的物品 ID。这个新语法的诞生意味着玩家不再受限于原版的固定外观，而是能够自由地将一种物品的模型套用在另一种物品之上，从而创造出无数种视觉与功能错位的奇妙组合。它彻底颠覆了以往必须通过材质包或模组才能改变模型外观的传统路径，将自定义权力直接交到了每一个普通玩家的手中。</p><p><img src="/assets/images/illustrations/minecraft-65.webp"></p><p>我们先正常输入一个获取物品的指令，然后在物品 ID 后面加上一对中括号以声明 NBT 标签列表。紧接着，在中括号里填入 <code>item_model=&quot;diamond_sword&quot;</code>，将这件钻石矛的外观模型指定为钻石剑的经典造型，再用逗号分隔，添加上 <code>item_name=&quot;钻石剑&quot;</code> 来修改物品显示的名称。通过这一行简洁的指令，我们就能实现物品外观与内在属性的彻底分离，既保留了原物品的功能，又赋予它全新的视觉身：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">give @s diamond_spear[item_model=&quot;diamond_sword&quot;,item_name=&quot;钻石剑&quot;]</span><br></pre></td></tr></table></figure><p><img src="/assets/images/illustrations/minecraft-66.webp"></p><p>按下回车执行指令后，我们即可获得一个模型为钻石剑的物品，但请注意，我获取的是一把钻石矛。这个物品虽然一眼看去和普通的钻石剑毫无区别，拥有相同的剑刃形状和握柄细节，但它的物品 ID 可是实打实的钻石矛，所有矛类专属的机制都完好无损地保留着。攻击方式既可以是近距离的戳刺，也可以是通过蓄力后疾跑触发的穿刺攻击。而最重要的一点在于，长矛特有的附魔对它全部有效，这意味着你可以打造出一把外表像剑、却能做到近距离戳刺和疾跑穿刺，为战斗策略增添了前所未有的趣味和变数。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E5%A6%82%E4%BD%95%E7%94%A8%E6%8C%87%E4%BB%A4%E6%9B%BF%E6%8D%A2%E7%89%A9%E5%93%81%E6%9D%90%E8%B4%A8/</id>
    <link href="https://090909.top/2026/07/01/%E5%A6%82%E4%BD%95%E7%94%A8%E6%8C%87%E4%BB%A4%E6%9B%BF%E6%8D%A2%E7%89%A9%E5%93%81%E6%9D%90%E8%B4%A8/"/>
    <published>2026-07-01T03:56:09.000Z</published>
    <summary>本文介绍了《我的世界》游戏中的一项全新指令语法 —— item_model NBT 标签，它作为 give 指令的配套功能，允许玩家将任意一种物品的模型套用在另一种物品之上，从而实现视觉与功能的完全错位。文章通过两个荒诞的场景作为引子：钻石被当作雪球投掷，三叉戟蓄力时却拉弓射箭，揭示了这一机制带来的奇妙效果。随后详细说明了指令的书写格式，例如 give @s diamond_spear[item_model=&quot;diamond_sword&quot;,item_name=&quot;钻石剑&quot;]，即可获得一把外观为钻石剑但内部逻辑依然是钻石矛的物品，既可近距离戳刺又能疾跑穿刺，且所有矛类附魔均有效。这一语法彻底颠覆了以往依赖材质包或模组才能改变模型外观的传统路径，将自定义权力直接交给普通玩家，为战斗策略和创意玩法带来了前所未有的可能性。</summary>
    <title>如何用指令替换物品材质：我的世界全新指令，物品模型随心换</title>
    <updated>2026-07-21T13:57:21.321Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="杂谈" scheme="https://090909.top/categories/%E6%9D%82%E8%B0%88/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="评论系统" scheme="https://090909.top/tags/%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F/"/>
    <category term="网络安全" scheme="https://090909.top/tags/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/"/>
    <category term="隐私泄露" scheme="https://090909.top/tags/%E9%9A%90%E7%A7%81%E6%B3%84%E9%9C%B2/"/>
    <category term="数据泄露" scheme="https://090909.top/tags/%E6%95%B0%E6%8D%AE%E6%B3%84%E9%9C%B2/"/>
    <content>
      <![CDATA[<p>之前我不是写过，阿普修的最新网站主题到底有多抽象吗？包括但不限于：虽然是用 AI 调的，但是深亮色模式没做好（那你别做不就行了）；虽然是用 AI 写的，但语法混乱到像个实习生，代码块背景在暗色模式下白得能当手电筒用。最近这位”独立开发者”又来最新力作了，猜猜是什么？不是新的 UI 框架，也不是优化了什么性能——他把用户评论区当成了公共数据库，把所有人的邮件地址大大方方地躺在了 GitHub 仓库里，就像在自家门口摆了个摊，上面写着”路过瞧一瞧，这里有 36 位网友的隐私”。发现这事儿的时候我血压都上来了，我让 AI 写了个正则脚本，严格筛选仅获取里面完全包含名字、邮箱、网站的信息（不包括匿名但有邮箱、全名有网站但没邮箱，有名字和邮箱但没网站），就像用筛子过滤石头里的金沙——结果您猜怎么着？足足筛出了 36 位完整信息，其中就包括我的大名和常用邮箱在内。那一刻我脑子里只有一个想法：这不叫开源，这叫开盒。</p><p>单独有名字，可能不算什么，毕竟互联网上叫张三李四的没有一万也有八千，谁还不是个重名受害者呢；单独有邮箱，也仅仅只是给我发送垃圾短信，我一天收十封“GNU 某大学社团邀请您加入”的邮件轰炸也不差这一封；单独有网站地址？这就是我们现在正在做的，我还希望我的网站有热度呢，巴不得有人顺着网线过来看看我写的流水账。但是如果全部包含，就是一笔不错的资产了——姓名、联系方式、个人网站三位一体，简直就是一份现成的社交关系图谱，拿去社工还是搞精准营销，那都够喝一壶的。更何况评论系统里躺着的，不仅有个人信息，还有你的首次评论哦！那多少会暴露你的性格——是爽朗地打个”哈哈博主说得对”，又或是懦弱地只敢留个”支持”，还是蔑视众人地来一句”就这？”。字里行间的语气词、标点习惯、表情符号偏好，都在无声地画着你的心理画像。现在，让我们有请长得像彭于晏和范冰冰的受害者们（虽然这并不是值得欢庆的颁奖典礼），名单如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">Morin莫琳</span><br><span class="line">reimu</span><br><span class="line">Hary</span><br><span class="line">吴蛋蛋</span><br><span class="line">石猫</span><br><span class="line">初然忆</span><br><span class="line">永恒末匕</span><br><span class="line">無境</span><br><span class="line">imba97</span><br><span class="line">AeYunDian</span><br><span class="line">年华</span><br><span class="line">xingwangzhe</span><br><span class="line">Jackie</span><br><span class="line">喵拉蒂奇</span><br><span class="line">crqgxs</span><br><span class="line">克喵</span><br><span class="line">Jack</span><br><span class="line">mxdyeah</span><br><span class="line">Liseezn</span><br><span class="line">蜜蜂QWQ</span><br><span class="line">inkss</span><br><span class="line">梁栋烨</span><br><span class="line">Yuer6327</span><br><span class="line">wmbk</span><br><span class="line">旺东</span><br><span class="line">涵哲子</span><br><span class="line">HEISEN黑森</span><br><span class="line">Liseezn&#x27;blog</span><br><span class="line">Wudarensheng</span><br><span class="line">fqzlr</span><br><span class="line">yuqi</span><br><span class="line">安泽</span><br><span class="line">涵哲子</span><br><span class="line">SkyCeria</span><br><span class="line">Chen</span><br><span class="line">Sfcore</span><br></pre></td></tr></table></figure><p>如果你恰好是他们的朋友，麻烦你动动手指转发一下这篇文章，告诉他们个人信息正躺在别人的仓库里晒太阳呢。告诉他们下次去别人网站评论最好小心点，谁也拿不准下一个”开源”的会不会是自己的身份证号——这年头，你永远不知道网站作者是把评论当社交功能，还是当数据库采集器。知道这件事后，我也是第一时间告诉了我的朋友小芬，也没什么别的意思，就是纯粹吐槽几句：”你看这哥们，写主题写得稀碎也就算了，现在连用户隐私都开始往外扔了。”那份邮件列表里没有小芬的名字，他逃过一劫，但他还是惊呼，这根本就不好玩，甚至有点十分不成熟，语气里带着那种被冒犯到的震惊。我第一次感受到，原来所谓的开你盒子的黑客，是真的不需要什么高深技巧——不用写什么SQL注入，不用搞什么零日漏洞，也不用在暗网里像特工一样接头交易。去捡垃圾桶里的快递盒，或者蹲在 GitHub 上等一个粗心大意的开发者把评论区的邮件地址一起提交上去，还不简单吗？</p><p>技术最恐怖的地方从来不是它有多复杂，而是它门槛低到连防范都显得像个笑话。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E7%BB%A7%E6%8A%BD%E8%B1%A1%E7%BD%91%E7%AB%99%E7%9A%84%E6%9C%80%E6%96%B0%E5%8A%9B%E4%BD%9C/</id>
    <link href="https://090909.top/2026/07/01/%E7%BB%A7%E6%8A%BD%E8%B1%A1%E7%BD%91%E7%AB%99%E7%9A%84%E6%9C%80%E6%96%B0%E5%8A%9B%E4%BD%9C/"/>
    <published>2026-07-01T03:55:52.000Z</published>
    <summary>本文介绍了阿普修网站最新主题存在的问题及更严重的用户隐私泄露事件。该网站主题虽由 AI 辅助开发，但深亮色模式未完善，代码混乱且存在明显缺陷。更令人震惊的是，网站评论区被当作公共数据库，作者发现 36 位用户的完整个人信息（包括姓名、邮箱、网站地址）被直接公开在 GitHub 仓库中。文章指出，单独的名称或邮箱影响有限，但三者组合可形成社交关系图谱，极易被用于社工攻击或精准营销。作者通过正则脚本筛选出包含自己及多位网友的隐私列表，并强调这种泄露源自开发者的粗心而非复杂黑客技术。文章最后提醒用户警惕网站评论功能的安全风险，并指出技术门槛降低反而使隐私保护变得困难。</summary>
    <title>继抽象网站的最新力作：继抽象网站后，他泄露了 36 个邮件地址</title>
    <updated>2026-07-21T13:57:21.325Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="纪实" scheme="https://090909.top/categories/%E7%BA%AA%E5%AE%9E/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="生活感悟" scheme="https://090909.top/tags/%E7%94%9F%E6%B4%BB%E6%84%9F%E6%82%9F/"/>
    <category term="交通安全" scheme="https://090909.top/tags/%E4%BA%A4%E9%80%9A%E5%AE%89%E5%85%A8/"/>
    <category term="监控摄像头" scheme="https://090909.top/tags/%E7%9B%91%E6%8E%A7%E6%91%84%E5%83%8F%E5%A4%B4/"/>
    <category term="隐私泄露" scheme="https://090909.top/tags/%E9%9A%90%E7%A7%81%E6%B3%84%E9%9C%B2/"/>
    <content>
      <![CDATA[<p>大概是 2015 年还是 2016 年的年头吧，具体年份的记忆已经有些模糊，但那份晦气和惊悚却像刻在骨子里一样清晰。当时正是大年初一，我们一家从老家赶回来，满心都还是过年的喜庆和团圆的余温。然而，就在离家不远的一条路上，我妈开的摩托车被一辆黑色轿车从后面狠狠追尾了。巨大的冲击力让我整个人瞬间失去平衡，半边身子重重地砸在冰冷粗糙的地面上，摩擦的疼痛和耳鸣一起袭来。我记得最清楚的一个画面，就是我头上那顶迪迦奥特曼的头盔——那是我最心爱的宝贝，当时年幼的我非常喜欢奥特曼这类特摄作品，更别提这顶印着奥特曼的头盔，平时都舍不得磕碰一下——它的面罩玻璃在撞击中碎了一地，零星的碎片在路面上反射着惨淡的阳光。那一幕，比身上的擦伤和头疼更让我感到一种说不出的后怕。也正是因为亲身经历过那次意外，如今的我才会如此病态般地注重交通安全，甚至到了有些神经质的地步。</p><p>每次刷短视频看到那些载着巨型钢卷的重型卡车，我脑海里总会不受控制地浮现出一个极其具体的幻想场景：假如我妈正开着摩托车载着我行驶在公路上，前面那辆钢卷车上的钢卷突然因为捆绑不牢而滚落下来，那么我妈会如何凭借她多年的驾驶经验，在千钧一发之际急转车头，带着我寻找一条能避开那庞然大物的逃生路线。或者，我又会自我安慰地想，我平时回家常走的那条路路况复杂，应该不会有那种体型的重型货车冒险驶入。这些看似荒唐的胡思乱想，其实都是我内心深处对那次车祸创伤的应激反应，它让我明白，道路上的安全容不得半点侥幸。当时，我爸和我哥是骑着另外那台摩托车走在前面，他们先一步回到了家。我爸听到我妈在电话里带着哭腔的求救后，火急火燎地赶到了事故现场。这本是一起责任清晰的追尾事故，肇事方撞了我们，我妈虽然惊魂未定，但还是冷静地提出赔偿一千块私了，这已经是很合理的修车和医药费了。</p><p>可对方司机却是个斤斤计较的人，硬是压价，说少给五百块钱就完事。正当双方僵持不下时，我爸赶到了，可他非但没有站在我们这边据理力争，反而像吃错了药一样，突然帮着那个加害者说话，声称是我们自己不小心撞上去的，是我们理亏。那一刻，我满心委屈和不解，看着父亲与外人站在一起的背影，第一次觉得大人的世界是那么复杂和难以理解。如果是现在这个在网上嬉笑怒骂、习惯用幽默化解尴尬的博主我，面对同样荒谬的场景，我一定会抢在他们所有人开口之前，用一种极尽夸张和反讽的语气打趣道：“是啊，是我们撞的你们。都怪我们太守规矩了，老老实实地走在前面，结果我们的车后备箱不长眼，非要撞上你们那威风凛凛的车前盖，然后我们连人带车摔倒在地，是我们自己活该受伤了。”说完，我还会特意伸手指着我爸，补上一句：“你们别找我理论，找我爸赔偿吧，我爸钱多的是，他最讲道理了。”</p><p>或许在那一刻，被我如此抢白和架在火上烤的爸爸，才会瞬间回过神来，重新变得立场坚决，咬定是他们撞的我们，那一千块赔偿也理应归我们。我是真的不想再经历这种车祸了，尤其在万家团圆的喜庆年节，大家平平安安、规规矩矩出行，比什么都强。2015 年和 2016 年那阵子，大城市正忙着学习西方的城市规划理念，到处兴建高楼大厦、霓虹闪烁，试图把自己包装得荣华富贵，一派国际化景象。可像我们茂名这样的小城市，发展就滞后多了，很多路段连个像样的路灯和监控摄像头都没有，这些基础设施都是近几年才慢慢补齐安装的。所以在那个监控盲区遍地的年代，一旦出了事，几乎全凭一张嘴，谁的气势更足、谁更会胡搅蛮缠，结果往往就按照谁说的来定。我们这些普通老百姓，毫无办法，只能被动接受。哪像现在，路面上密布的电子眼和卡口监控，形成了几乎无死角的“天网”，事故是谁的错，调出录像一看便知，铁证如山。</p><p>谁没牌照敢上路，摄像头拍下脸部就能精准识别；谁在路上不文明地吐了口痰，数据库一比对也能找到人。所以每当看到有些媒体不分青红皂白地指责国内监控太多、侵犯隐私时，我总是心理暗自骂回去，因为这些冷冰冰的摄像头，恰恰是在关键时刻能保护我们普通人的无声守护者。美国那种社区式的房屋布局，家家户户都是独栋矮房，社区内的道路又窄又曲折，视野却因为房子低矮而显得开阔。如果在那种路旁边装监控，摄像头广角一开，很容易就透过低矮的窗户，把居民家里的日常活动拍得一清二楚，确实存在隐私泄露的风险。但国内的居住环境完全是另一种模式，大多是封闭式的楼房小区，道路宽敞，主干道动辄双向四车道或六车道。监控安装在路面上的路灯杆或高架上，镜头角度是专门调试好的，视野范围内除了车道、人行道和绿化带，根本拍不到居民住宅内部。即便是小区内部安装的安防监控，也因为楼房主体的遮挡，通常只能捕捉到一楼的公共区域或单元门入口。</p><p>这两种截然不同的居住形态，决定了监控的应用效果完全不同，我们完全没必要对国内合理且必要的公共安全监控指指点点。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E5%B9%B4%E5%88%9D%E5%9B%9E%E5%AE%B6%E9%82%A3%E5%9C%BA%E8%BD%A6%E7%A5%B8/</id>
    <link href="https://090909.top/2026/07/01/%E5%B9%B4%E5%88%9D%E5%9B%9E%E5%AE%B6%E9%82%A3%E5%9C%BA%E8%BD%A6%E7%A5%B8/"/>
    <published>2026-07-01T03:55:39.000Z</published>
    <summary>本文描述了作者在 2015 或 2016 年大年初一亲身经历的一场追尾车祸：母亲驾驶摩托车被轿车撞击，作者受伤，心爱的迪迦奥特曼头盔碎裂。这次意外给作者留下了深刻的心理创伤，导致后来对交通安全产生近乎病态的重视，甚至时常幻想躲避钢卷车等极端场景。事故后，肇事方试图压价私了，而父亲到场却反常地站在肇事者一边指责自家人，让作者感到委屈和不解。作者由此反思，在当年监控缺失的小城市，事故责任常靠气势和胡搅蛮缠判定；而今遍布路面的电子眼与卡口监控形成了“天网”，能提供铁证，保护普通人权益。作者还对比了中美居住环境差异，指出国内道路监控因楼房小区结构合理，不会侵犯住宅隐私，因此认为对国内合理公共监控的指责是不必要的。整篇文章借个人经历表达了对交通安全、家庭关系以及监控技术社会价值的深刻思考。</summary>
    <title>年初回家那场车祸：亲身经历车祸，让我明白安全和监控的重要</title>
    <updated>2026-07-21T13:57:21.321Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="梦" scheme="https://090909.top/categories/%E6%A2%A6/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="我的世界" scheme="https://090909.top/tags/%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="校园回忆" scheme="https://090909.top/tags/%E6%A0%A1%E5%9B%AD%E5%9B%9E%E5%BF%86/"/>
    <category term="游戏回忆" scheme="https://090909.top/tags/%E6%B8%B8%E6%88%8F%E5%9B%9E%E5%BF%86/"/>
    <category term="泰拉瑞亚" scheme="https://090909.top/tags/%E6%B3%B0%E6%8B%89%E7%91%9E%E4%BA%9A/"/>
    <content>
      <![CDATA[<p>有一次郊游，我坐在大巴靠窗的位置，窗外掠过的田野和村庄让我突然意识到，自己已经很久没去过学校了。具体有多久？我掰着手指算了算，却发现自己根本数不清——好像已经缺席了好几个学期。到了学校，我鬼使神差地走进空荡荡的教室，径直坐到了全班第三排最中央的位置。阳光透过窗户斜斜地洒在桌面上，我抚摸着熟悉的课桌纹理，心里莫名笃定：这个位置天生就是属于我的，而不是那个被遗忘的最后一排。周围同学们的笑闹声渐渐远去，我只觉得四周安静得能听见自己的心跳，仿佛整个校园都在等我归来。好朋友吴珏华不知何时凑了过来，她歪着头打量我，眼中满是疑惑：“梁栋烨，你那么久没来学校，天天待在家里到底在忙些什么啊？”</p><p>我回过神来，语气里带着几分自豪：“我啊，我在家里搞了个网站，正在写文章。”她眼睛一亮，立刻掏出平板电脑，迫不及待地追问：“是什么网站啊？快给我看看！”手指已经悬在屏幕上，准备输入网址。我望着她兴奋的样子，心里忽然有些紧张，就像把自己的日记本递给了别人翻阅。她平板的浏览器是个陌生的系统自带程序，界面简洁得让我一时叫不上名字。我瞥见默认搜索引擎是必应，心里顿时踏实了不少——因为我知道，自己网站在必应的权重特别高。于是我教她直接搜索我的名字，第一个结果就是关于页，再点进去就能直达网站。她按照我的指示操作着，指尖在屏幕上轻轻滑动，我心里暗暗期待着她看到我那些文字时的反应。</p><p>就在即将点击搜索键时，她突然停住了，一脸为难地转过头：“我忽然用不惯拼音输入法了，你能帮我操作吗？”我愣了一下，觉得这请求有些刻意——她可是班上的优等生啊，怎么可能突然不会用拼音呢？说不定她整天偷偷浏览那些我不知道的小网站呢！我接过平板，手指灵活地输入自己的名字，心里却暗暗琢磨着她这奇怪的理由。她认真地翻阅着我的文章，不时发出轻声赞叹。除了记录日常琐事，我还写了不少关于《我的世界》的心得。她忽然指着屏幕问：“为什么我的游戏里没有这个特性啊？”“可能是你的版本不够新吧。”我随口答道，顺手点开了她桌面上的《我的世界》国际版图标。</p><p>加载画面出现的瞬间，我立刻认出了那个熟悉的版本号——这分明就是去年秋天我亲手给她下载的旧版本。“这不是去年秋季我给你下载的版本吗？你怎么从来没更新过？”我忍不住提高了声音，带着几分难以置信地质问她。她眨了眨眼睛，一脸茫然地反问：“原来还要手动更新的吗？我一直以为它会自己悄悄更新呢，就像手机应用那样。”我无奈地叹了口气，决定直接帮她下载新版，免得她继续用这个落后版本错失那么多有趣的特性。下载游戏需要些时间，我便拿出自己的笔记本电脑，熟练地打开了《泰拉瑞亚》。因为缺几种稀有材料，我特意创建了一个只有岩浆的世界。</p><p>我骑上 UFO 坐骑，在漫天火红的岩浆上空缓缓向右飞行，放眼望去尽是无边无际的灼热液态岩，完全找不到那种岩浆与陆地交错的地形。直到飞过一片长满发光蘑菇的水域——那是这片火海里唯一的蓝色——才终于看到了心心念念的交界地带。据说在新版本中，这种交界处会刷新大量特殊怪物。作为一位装备齐全的召唤师，我召唤出所有随从，又在旅途模式里把刷怪速度调到最高，准备挂机等材料。就在这时，我忽然意识到不对劲——泰拉棱镜的攻击速度明显跟不上怪物的刷新频率，因为我把难度调到了大师级，涌来的全是精英怪甚至 BOSS。不过我倒也不慌，毕竟开了无敌模式，那些张牙舞爪的怪物根本伤不到我分毫。</p><p>我只需悠闲地悬浮在空中，看着屏幕上不断跳出的伤害数字，等着那边《我的世界》安装完成就好。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E7%BB%99%E4%BD%A0%E4%B8%8B%E4%B8%AA%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/</id>
    <link href="https://090909.top/2026/07/01/%E7%BB%99%E4%BD%A0%E4%B8%8B%E4%B8%AA%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <published>2026-07-01T03:55:25.000Z</published>
    <summary>本文介绍了作者在一次郊游途中，因回校而意识到自己已缺席多个学期，并走进空荡荡的教室坐到第三排中央位置的故事。好朋友吴珏华询问作者在家忙碌的原因，作者自豪地告知自己在家里创建了网站并撰写文章。吴珏华立即用平板电脑搜索，作者指导她在必应中直接搜索自己的名字即可找到网站。然而在即将点击时，吴珏华以不习惯拼音输入法为由让作者代劳，作者虽感疑惑但仍协助操作。吴珏华浏览文章后对作者关于《我的世界》的心得表示好奇，作者发现她使用的游戏版本竟然是去年秋季自己帮忙下载的旧版，且从未更新。作者无奈之下决定帮她下载新版，同时打开自己的笔记本电脑玩《泰拉瑞亚》，在创造的世界中寻找岩浆与陆地交界处刷特殊怪物，开启旅途模式并调高刷怪速度，利用无敌模式挂机等待材料，同时等待《我的世界》安装完成。文章通过细腻的校园回忆与游戏互动，展现了作者对数字创作与游戏世界的投入。</summary>
    <title>给你下个我的世界：在家做网站写文章，帮同学更新游戏最新版</title>
    <updated>2026-07-21T13:57:21.325Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="梦" scheme="https://090909.top/categories/%E6%A2%A6/"/>
    <category term="生活感悟" scheme="https://090909.top/tags/%E7%94%9F%E6%B4%BB%E6%84%9F%E6%82%9F/"/>
    <category term="家庭" scheme="https://090909.top/tags/%E5%AE%B6%E5%BA%AD/"/>
    <category term="梦" scheme="https://090909.top/tags/%E6%A2%A6/"/>
    <category term="情感回忆" scheme="https://090909.top/tags/%E6%83%85%E6%84%9F%E5%9B%9E%E5%BF%86/"/>
    <category term="梦境对话" scheme="https://090909.top/tags/%E6%A2%A6%E5%A2%83%E5%AF%B9%E8%AF%9D/"/>
    <content>
      <![CDATA[<p>我突然发现，自己正牵着一个约莫四五岁的小女孩，走在灯火通明的商场里。我下意识地低头凝视她——那张圆润的小脸，眉眼间既有一丝我的轮廓，又掺杂着某个我辨认不出的神韵。就在那一瞬间，一个荒唐却笃定的念头击中了我：她是我的女儿。可紧接着，一股巨大的荒诞感从心底升起——我结婚了？我什么时候结的婚？我拼命调动记忆，试图从过往的碎片中打捞出婚礼、孕检、产房里的哭声，然而脑海一片空白，像被橡皮擦去了一整段人生。那些本该温暖而琐碎的点点滴滴，竟全都缺席，仿佛从未存在。我牵着她的手，却像牵着一个凭空落入我世界的陌生人。</p><p>小女孩拉着我停在一个摆满玩具的货架前，仰起头，眼睛发亮地盯着一只毛绒熊。我本想脱口说“不买”，话到嘴边却忽然顿住了。我隐约想起自己小时候，也曾这样眼巴巴地望着橱窗，渴望某件廉价却珍贵的玩具，却被大人轻描淡写地拒绝。那瞬间的失落，像一枚碎玻璃嵌在记忆里，至今隐隐作痛。于是我没有犹豫，弯腰取下那只熊，放进购物车。小女孩欢呼一声，又飞快地指向另一侧的罐装奥利奥——包装上印着诱人的巧克力花纹。我拿起罐子端详了片刻，脑子里却忽然冒出一个现实的问题：吃了这么多甜腻的饼干，会不会“热气”？我于是蹲下来，用尽量温和的语气跟她说：“咱们先买这个试试咸淡，要是好吃，下次再多买，好不好？”她抿着嘴想了想，用力点了点头，笑容灿烂得像夏日午后的阳光。</p><p>扫码支付时，机器发出清脆的“滴”声，我拎起购物袋，牵着她走出超市自动门。夜风迎面扑来，我正准备辨认方向，余光却瞥见门口倚着一个穿哥特风服饰的女孩——黑色蕾丝裙、银色链条、浓重的烟熏妆，脚上踩着一双厚底靴，整个人散发着一种与周遭格格不入的凌厉气息。她看见我，竟自然地扬了扬下巴，像打招呼，随即不紧不慢地迈开步子，跟在了我身旁。我的心猛地一沉：她不会是我的妻子吧？我难道真的在某种失智的状态下，娶了一个看起来游手好闲、沉浸在自己暗黑世界里的人？我试图回忆她的名字、她的声音、她与我之间可能存在的任何交集，但大脑依旧一片死寂。就在这时，我注意到女儿正不自觉地往她身侧靠，两人之间的距离近得像有某种天然的牵引。我既恐惧她拐走孩子，又怀疑自己是否错过了她们之间本该存在的亲子纽带。</p><p>走到斑马线前，红灯还在闪烁，街对面的车流如幻影般滑过。我忽然感觉到一种异常——周围的色彩开始褪去，声音变得遥远而模糊，像信号不良的收音机。一个清醒的认知像冷水浇头：这是梦，我正要醒来。可就在现实即将拽回我的前一秒，我心中涌起强烈的求救欲望。我朝那个方向张开嘴，声音干涩而虚弱：“能扶我一下吗？我感觉快要倒下了……”我以为至少会有一双手伸过来，或是一句关切的询问。然而没有人转头，那个哥特女孩的步伐依旧不紧不慢，女儿的小手没有握紧我，甚至没有回望。我只觉得眼皮越来越沉，膝盖发软，整个人像被抽去了筋骨。在意识彻底坠入黑暗之前，我满心只剩下后悔——后悔不该跟她结婚，后悔没有守住那份清醒。而就在彻底失去意识的那一瞬，一个更清晰的声音在我心底升起：或许她不是我的妻子，我的妻子在家等我。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E5%90%8E%E6%82%94%E5%92%8C%E5%A5%B9%E7%BB%93%E5%A9%9A%E4%BA%86/</id>
    <link href="https://090909.top/2026/07/01/%E5%90%8E%E6%82%94%E5%92%8C%E5%A5%B9%E7%BB%93%E5%A9%9A%E4%BA%86/"/>
    <published>2026-07-01T03:55:03.000Z</published>
    <summary>本文描述了“我”在商场中牵着一个约莫四五岁的小女孩，下意识认定她是自己的女儿，却对结婚、孕检等记忆一片空白。女孩想要毛绒熊和奥利奥，“我”因童年失落而满足她，却担忧她吃甜饼“热气”。扫码后走出超市，遇到一位哥特风女孩，“我”怀疑她是妻子，内心抗拒且恐惧，但女孩与女儿间似有天然牵引。过马路时，“我”感知到梦境即将苏醒，在意识模糊前呼喊求助却无人回应，女儿和哥特风女孩都未回头。“我”在后悔中坠入黑暗，最后一瞬又怀疑妻子或许在家等待。文章通过虚实交织的梦境，探讨记忆缺失、亲子关系、自我身份与悔恨等主题，以超现实笔触呈现主人公对家庭责任的矛盾与觉醒。</summary>
    <title>后悔和她结婚了：商场梦中牵女儿购物，回家遇哥特妻子后悔</title>
    <updated>2026-07-21T13:57:21.320Z</updated>
  </entry>
  <entry>
    <author>
      <name>梁栋烨</name>
    </author>
    <category term="纪实" scheme="https://090909.top/categories/%E7%BA%AA%E5%AE%9E/"/>
    <category term="个人经历" scheme="https://090909.top/tags/%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86/"/>
    <category term="童年时光" scheme="https://090909.top/tags/%E7%AB%A5%E5%B9%B4%E6%97%B6%E5%85%89/"/>
    <category term="蛋糕" scheme="https://090909.top/tags/%E8%9B%8B%E7%B3%95/"/>
    <category term="甜品" scheme="https://090909.top/tags/%E7%94%9C%E5%93%81/"/>
    <category term="怀旧" scheme="https://090909.top/tags/%E6%80%80%E6%97%A7/"/>
    <content>
      <![CDATA[<p>6 月 21 日晚上，妈妈终于松口答应带我去买蛋糕了。傍晚的热浪还未完全散去，马路上的车笛声响个不停，但我心里却像藏了一块冰镇樱桃蛋糕，丝丝凉意带着甜。我描述的蛋糕样子具体得几乎能画出来——必须是戚风蛋糕做底，那种蓬松得像云朵、咬下去又带一点弹性的质地；奶油要厚厚地抹上去，不是那种植物奶油轻飘飘的甜，而是带着乳脂香气的、能在舌尖化开的浓郁；最上面一定要铺满深红色的樱桃，切成六分之一圆的扇形，每一块边缘都挂着晶莹的果汁。而且必须放进冰箱里冰过，让奶油微微凝固，蛋糕体吸收一点潮气，吃起来像夏天傍晚吹过的一阵冷风。我絮絮叨叨地说着这些，仿佛多说一遍，就能在货架上多一分找到它的希望。小时候，每逢傍晚从学校放学回家，妈妈都会带我去嘉豪轩，玻璃柜里那一排排整齐的扇形樱桃蛋糕，是我的童年里最明亮的标记。</p><p>可如今，那座城市里再也找不到嘉豪轩的招牌了，就像某些旧时光，悄无声息地退出了生活的地图。没有嘉豪轩，我们只能去周围的个人西饼店碰运气。附近就一家店离得近，它店铺门面不大，甚至连门都没有，只有展示食物的剥离柜台，玻璃柜里摆着些看起来花哨却叫不上名字的甜品。这些店平时都没什么人光顾，东西像是隔夜的。更让我哭笑不得的是，这些店里卖的东西，几乎跟我记忆中的蛋糕毫无关系——什么芋圆奶茶杯，底下铺着黑糖珍珠，上面堆着芋泥和奶盖；什么豆乳盒子，一层蛋糕一层豆浆奶油，撒着黄豆粉；还有各种千层，榴莲的、芒果的、抹茶红豆的，层层叠叠像布匹堆砌。它们看起来精致时髦，适合拍照发朋友圈，但我心里清楚，这些甜品吃下去，肚子凉一阵，随后肠胃开始翻涌，第二天准要拉肚子，再严重一点就是感冒发烧，整个人蔫上好几天。我要的不是这些“莫名其妙”的东西，我只是想要一块简单、冰凉的樱桃蛋糕而已。</p><p>我记得凯都那边有一家合伙开的西饼店，店面比个人店大不少，玻璃柜也宽敞，以前路过时瞥见过里面摆着几款传统样式的蛋糕。可问题是，凯都离我们这儿实在太远了，更何况现在已经快晚上八点，来回折腾一趟至少一个半小时。我站在街边，汗水顺着鬓角往下淌，晚风都是热的，柏油路面蒸腾着白天的余温。我心里开始打鼓：要不要放弃？要不要就让妈妈随便买个什么甜品算了？可嘴巴不答应，脑子里那个冰过的戚风蛋糕一直在晃。妈妈看出我的犹豫，她没催我，只是拍了拍我的肩膀说，先就近找找，实在没有，至少还能在附近买碗桂林米粉当夜宵，不至于空着肚子回家。她这么一说，我虽觉得心理有些许落差，但做好准备总比没有好——桂林米粉是热的跟我想象中那一口冰凉绵密的奶油完全是两个世界。但我还是点了点头，顶着炎热，跟着妈妈走向下一家亮着灯的西饼店。</p><p>推开那家西饼店的玻璃门，一阵冷气扑面而来，像是终于扎进了一潭凉水里，浑身的燥热瞬间收敛了不少。店里灯光明亮，柜台上方挂着暖黄色的射灯，照得每一块甜点都油光水滑。我快步走到主柜台前，弯下腰仔细扫过每一层玻璃格——确实有很多看起来像蛋糕的东西，圆形的、方形的、心形的，上面堆着水果、淋着酱汁、撒着糖粉，摆盘精致得像艺术品。可越看越不对劲，那些标注着“芋圆大福”、“芝士盒子”、“焦糖千层”的名字，没有一个是我叫得出口的旧相识。我伸手隔着玻璃指了指其中一块，想问这是什么底，仔细看照片上写着是海绵蛋糕配麻薯。我摇摇头，心里那点期待又沉下去一分。我要的是蓬松的戚风，不是扎实的海绵；我要的是整块扇形切好的樱桃奶油，不是麻薯和焦糖堆出来的花哨组合。它们好看，但都不是我的。</p><p>我又说了一遍——我只想要那种经典的戚风蛋糕，加很多奶油，切成六分之一圆的扇形，上面有樱桃，最好还冰过的那种。我还是觉得不甘心，扭头看向另一边的冷藏柜台，那里的灯光偏冷白色，玻璃面上凝着一层薄薄的水雾。我凑过去，瞳孔一下子放大了——里面整整齐齐地摆着几盒蛋糕，底胚正是我熟悉的戚风，浅黄色的糕体细腻均匀，边缘光滑，像是刚从模具里脱出来的。我几乎要叫出声来，可当我弯下腰仔细看时，心又凉了半截。每一盒上面都贴着手写的小单子，写着“小丸子预订”、“周一取”、“六寸双层戚加鲜奶油”之类的字样，还有一盒甚至已经用丝带扎好了，旁边放着一张生日贺卡（非生日情况下就不能散装卖吗）。那些蛋糕确实是我想要的底，但它们不属于我，它们只是路过我眼前的别人的期待。我知道，今晚大概是找不到那块属于我的樱桃蛋糕了。</p>]]>
    </content>
    <id>https://090909.top/2026/07/01/%E5%8F%97%E4%B8%8D%E4%BA%86%E8%9B%8B%E7%B3%95%E9%82%A3%E4%B9%88%E5%A4%9A%E5%90%8D%E5%A0%82/</id>
    <link href="https://090909.top/2026/07/01/%E5%8F%97%E4%B8%8D%E4%BA%86%E8%9B%8B%E7%B3%95%E9%82%A3%E4%B9%88%E5%A4%9A%E5%90%8D%E5%A0%82/"/>
    <published>2026-07-01T03:54:54.000Z</published>
    <summary>本文介绍了作者在 6 月 21 日晚上央求妈妈带自己去买蛋糕的经历，展现了对童年记忆里嘉豪轩扇形樱桃蛋糕的执着追寻。作者心中理想的蛋糕必须是戚风底、厚奶油、铺满扇形樱桃并冰过的经典款式，但城市里嘉豪轩早已消失，周边的个人西饼店只售卖芋圆奶茶杯、豆乳盒子、千层等时髦却容易导致肠胃不适的网红甜品。面对凯都较远的老式西饼店，作者在炎热中一度犹豫，妈妈提议找不到就买桂林米粉。最终在一家灯光明亮的西饼店，作者发现了冷藏柜里戚风底蛋糕，却全是他人预订的生日蛋糕，不能散卖。整篇文章细腻刻画了作者从满怀期待到一次次落空的心理变化，对比了传统质朴与当下花哨甜品的差异，流露出对逝去旧时光和简单美味的深切怀念。</summary>
    <title>受不了蛋糕那么多名堂：那个夏天傍晚，再也找不到的樱桃蛋糕</title>
    <updated>2026-07-21T13:57:21.320Z</updated>
  </entry>
</feed>
