<?xml version="1.0" encoding="UTF-8"?><rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Sherioc&#39;s Blog</title>
    <link>http://sherioc.online/</link>
    <description><![CDATA[nothing]]></description>
    <language>zh-CN</language>
    <managingEditor>sherioc@qq.com (sherioc)</managingEditor>
    <pubDate>Sat, 04 Apr 2026 02:50:25 +0000</pubDate>
    <lastBuildDate>Sat, 04 Apr 2026 02:50:25 +0000</lastBuildDate>
    <generator>grtblog vlocal</generator>
    <image>
      <url>https://avatars.githubusercontent.com/u/130974708?v=4</url>
      <title>Sherioc&#39;s Blog</title>
      <link>http://sherioc.online/</link>
    </image>
    <atom:link href="http://sherioc.online/feed" rel="self" type="application/rss+xml"/><item>
      <title>Python 导入与 sys.path 复盘</title>
      <link>http://sherioc.online/posts/python-dao-ru-yu-syspath--fu-pan</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/python-dao-ru-yu-syspath--fu-pan">http://sherioc.online/posts/python-dao-ru-yu-syspath--fu-pan</a></p></blockquote><h2><img src="/uploads/pictures/2026-04-04-02:53:14-b7.png" alt="image.png"></h2>
<h2>一、Python 导入的核心规则</h2>
<ol>
<li>
<p><strong>Python 找模块只看一个地方：<code>sys.path</code></strong></p>
<ul>
<li><code>sys.path</code> 是一个<strong>路径列表</strong></li>
<li>执行 <code>import</code> 时，Python 按顺序在这些目录里查找包/模块</li>
<li>第三方库（PyQt6、numpy 等）都在 <code>site-packages</code>，它默认就在 <code>sys.path</code> 里</li>
</ul>
</li>
<li>
<p><strong>绝对导入 vs 相对导入</strong></p>
<ul>
<li><strong>绝对导入</strong>：<code>from a.b import c</code>
从 <code>sys.path</code> 里的某个目录开始找，<strong>最稳定、最推荐</strong></li>
<li><strong>相对导入</strong>：<code>from .a import c</code>
仅用于<strong>包内部文件之间互相导入</strong>，<strong>不能用于直接运行的脚本</strong></li>
</ul>
</li>
</ol>
<hr>
<h2>二、相对导入 <code>.</code> 的使用限制</h2>
<ul>
<li>
<p><strong><code>.</code> 代表“当前包目录”</strong></p>
</li>
<li>
<p><strong>直接运行的文件（python main.py）不能用相对导入</strong>
原因：运行时该文件被视为顶层脚本 <code>__main__</code>，<strong>不属于任何包</strong>，Python 不知道 <code>.</code> 指向谁
报错：<code>attempted relative import with no known parent package</code></p>
</li>
<li>
<p><strong>适用场景</strong>：包内部模块互相引用</p>
<pre><code class="language-python"># controller/main_controller.py
from .utils import helper  # 正确
</code></pre>
</li>
</ul>
<hr>
<h2>三、<code>sys.path.insert(0, ...)</code> 到底做什么</h2>
<pre><code class="language-python">sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
</code></pre>
<ol>
<li><code>__file__</code>：当前 <code>.py</code> 文件的完整路径</li>
<li><code>os.path.dirname(...)</code>：获取<strong>所在文件夹</strong></li>
<li>套两层 → 拿到<strong>项目上级目录</strong></li>
<li><code>sys.path.insert(0, 路径)</code>：把该目录<strong>加到 Python 搜索路径最前面</strong></li>
<li>目的：让 <code>from pointcloud_gui.controller...</code> 这种<strong>包式导入可以找到</strong></li>
</ol>
<hr>
<h2>四、直接运行脚本的标准写法</h2>
<pre><code class="language-python">import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))

from pointcloud_gui.controller.main_controller import MainController
</code></pre>
<ul>
<li>入口文件：<strong>不用 <code>.</code>，只用绝对导入</strong></li>
<li>手动把根目录加入搜索路径，保证在哪运行都不报错</li>
</ul>
<hr>
<h2>五、简要</h2>
<ol>
<li><strong>直接运行 → 不能用 <code>.</code></strong></li>
<li><strong>包内引用 → 可以用 <code>.</code></strong></li>
<li><strong>import 只看 sys.path</strong></li>
<li><strong>找不到模块就把目录加进 sys.path</strong></li>
</ol>
<hr>
<pre><code class="language-python">&quot;&quot;&quot;Entry point for the point cloud GUI application.&quot;&quot;&quot;

import sys
import os


# =====================调试=====================
print(&quot;当前文件 __file__ =&quot;, __file__) # E:\Desktop\Project\Project_CAGE\CAGE_ReBuild\GUI\pointcloud_gui\main.py

# 第一层 dirname：当前文件所在文件夹（pointcloud_gui）
dir1 = os.path.dirname(__file__)
print(&quot;第一层 os.path.dirname(__file__) =&quot;, dir1) # E:\Desktop\Project\Project_CAGE\CAGE_ReBuild\GUI\pointcloud_gui 

# 第二层 dirname：上级文件夹（GUI 文件夹）
dir2 = os.path.dirname(dir1)
print(&quot;第二层 os.path.dirname(...) =&quot;, dir2) # E:\Desktop\Project\Project_CAGE\CAGE_ReBuild\GUI

# print(sys.path)
# ['E:\\Desktop\\Project\\Project_CAGE\\CAGE_ReBuild\\GUI\\pointcloud_gui', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\python310.zip', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\DLLs', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\lib', 'C:\\Users\\Administrator\\.conda\\envs\\build3d', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\lib\\site-packages', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\.conda\\envs\\build3d\\lib\\site-packages\\Pythonwin'] 
# =========================================================

sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))

from PyQt6.QtWidgets import QApplication
from pointcloud_gui.controller.main_controller import MainController


def main():
    app = QApplication(sys.argv)
    app.setStyle(&quot;Fusion&quot;)

    controller = MainController()
    controller.show()

    sys.exit(app.exec())


if __name__ == &quot;__main__&quot;:
    main()

</code></pre>]]></description>
      <author>sherioc</author>
      <guid>article-9</guid>
      <pubDate>Sat, 04 Apr 2026 02:50:25 +0000</pubDate>
    </item>
    <item>
      <title>两兄弟坐在灯下叙旧  &#xA;那些旧事  &#xA;好像被时间悄悄合上了  &#xA;石珍珠在院子里溜...</title>
      <link>http://sherioc.online/thinkings#thinking-4</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/thinkings#thinking-4">http://sherioc.online/thinkings#thinking-4</a></p></blockquote><p>两兄弟坐在灯下叙旧<br>
那些旧事<br>
好像被时间悄悄合上了<br>
石珍珠在院子里溜达<br>
还找来了瓦片和废纸箱<br>
在院子里给小猫搭了个窝<br>
等猫钻进去<br>
她蹲在旁边乐呵呵地笑<br>
眼睛眯成了一条线<br>
一个被世人说啥了一辈子的女人<br>
懂的事情却比很多人都多<br>
春天一到<br>
风声散了<br>
厉百程带着石珍珠重新回到了燕郊<br>
准备赶一年一度的庙会<br>
他翻出了压箱底的马前课转盘<br>
那是当年他跟着瞎子师傅偷学来的看家本领<br>
平时不轻易拿出来<br>
去庙会的路上<br>
遇到了一家人停灵<br>
对方认出厉百程是算命先生<br>
让他上前表一下<br>
给他五块钱<br>
厉百程爽快地答应了<br>
并表示自己不是为了要钱才过来的<br>
在口诵一番令文后<br>
厉百程虽然收下了对方塞来的钱<br>
但还是一再表示自己不是图那钱来的<br>
在他看来<br>
那是一个算命先生应尽的本分<br>
也是对亡人的一份尊重<br>
奇怪的是<br>
厉百程并没有直奔庙会<br>
而是先去了城里的寺庙<br>
在为自己祈求平安健康的时候<br>
也没有忘记给芸芸众生祈福<br>
虔诚地为妻子的健康和世人的平安上香祈福<br>
——《算命》</p>]]></description>
      <author>sherioc</author>
      <guid>thinking-4</guid>
      <pubDate>Thu, 26 Mar 2026 18:23:09 +0000</pubDate>
    </item>
    <item>
      <title>这个网站的点点滴滴</title>
      <link>http://sherioc.online/about-site</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/about-site">http://sherioc.online/about-site</a></p></blockquote><p>::: link-card href=&quot;https://github.com/SheriocCode/grtblog&quot; title=&quot;SheriocCode/grtblog&quot; desc=&quot;&quot; newtab=&quot;true&quot;</p>
<p>:::</p>
<p>魔改于<code>grtsinry43</code>的<code>https://github.com/grtsinry43/grtblog</code>，本站地址<code>https://github.com/SheriocCode/grtblog</code></p>
<p>::: timeline title=&quot;一些历史&quot; sub=&quot;HISTORY&quot;</p>
<p>2026-03-21|添加日常Gallery模块|https://github.com/SheriocCode/grtblog/commit/f00ef654e592bb3e6e26494ff6fbdf3bb708482c
2026-03-14|Starting the Blog!|Fork &amp; Init仓库
:::</p>]]></description>
      <guid>page-10</guid>
      <pubDate>Sat, 21 Mar 2026 07:35:12 +0000</pubDate>
    </item>
    <item>
      <title>关于我</title>
      <link>http://sherioc.online/about</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/about">http://sherioc.online/about</a></p></blockquote>]]></description>
      <guid>page-9</guid>
      <pubDate>Mon, 16 Mar 2026 03:33:43 +0000</pubDate>
    </item>
    <item>
      <title>Windows11+Linux双系统安装-Ubuntu24.04</title>
      <link>http://sherioc.online/posts/windows11linuxshuang-xi-tong-an-zhuang-ubuntu2404</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/windows11linuxshuang-xi-tong-an-zhuang-ubuntu2404">http://sherioc.online/posts/windows11linuxshuang-xi-tong-an-zhuang-ubuntu2404</a></p></blockquote><blockquote>
<p>参考链接：
<a href="https://blog.csdn.net/2401_84064328/article/details/137232169">Windows11 + Linux (Ubuntu22.04) 双系统最简安装详细避坑版_win11安装linux双系统-CSDN博客</a> (2025.12.22链接有效)<br>
<a href="https://geek-blogs.com/blog/dual-boot-linux-win-10/">双系统安装指南：Linux 与 Windows 10 共存全攻略 — geek-blogs.com</a><br>
b站相关视频教程：
<a href="https://www.bilibili.com/video/BV1Cc41127B9">https://www.bilibili.com/video/BV1Cc41127B9</a></p>
</blockquote>
<h1>1、Ubuntu24.04安装</h1>
<ol>
<li>
<p>首先
我们有一个安装了Windows11系统的电脑，准备一个8G以上的U盘（或者移动硬盘）</p>
</li>
<li>
<p>查看/更改引导方式
--Win+R呼出运行界面，输入：msinfo32，确定，会弹出一个系统信息的面板（或者直接搜索系统信息）。
<img src="/uploads/pictures/2026-03-18-15:09:12-66.png" alt="image.png">
--在项目栏找到BIOS模式，看对应的值，是否为UEFI，如果是就OK！跳到准备工作第三点~
--如果BIOS模式的值不是UEFI，而是显示传统（Legacy），那么就要改成UEFI，重启电脑狂按对应按键进入BIOS模式（如果不知道按哪个可以看看下面这个表，一般电脑开机的时候也会很快闪过按什么键的提示）
--比如鱼鱼用的Thinkbook16+是要在启动的时候狂按回车，然后出现一个Startup Interrupt Menu，再按F1就可以进入BIOS启动设置界面了。
--进入BIOS后开启UEFI，不同的电脑可能操作方法不同，下面的操作有对应的就按着修改没有就换一个：
Boot，选择UEFI Boot回车选择Enabled；
Startup，Boot，UEFI/Legacy Boot旁边的选项选择修改为UEFI Only；
Boot mode select选择修改为UEFI；
Boot Type选择修改为UEFI Boot Type；
Launch CSM选择修改为Disabled。
改完了记得保存并退出！不要忘记保存！！！</p>
</li>
<li>
<p>查看/更改磁盘的分区格式
避免安装Ubuntu到最后了却因为引导器安装失败功亏一篑：
--右键开始按钮选择磁盘管理
--在Windows所在的磁盘（图中的磁盘0）左边灰色块右键，选择属性
<img src="/uploads/pictures/2026-03-18-15:09:24-b5.png" alt="image.png">
--在卷这栏可以看到磁盘分区形式，是否为GPT格式，如果是就OK！跳到准备工作第四点~
<img src="/uploads/pictures/2026-03-18-15:09:32-d1.png" alt="image.png">
--如果磁盘分区形式显示的是：主启动记录(MBR)，那么就要修改为GPT格式
（pass）</p>
</li>
<li>
<p>关闭BitLocker加密
避免装双系统过程中进入BitLocker恢复模式：
--如果有BitLocker加密，在设置-隐私和安全性里找到设备加密（或者直接搜索bitlocker打开设备加密设置），把设备加密的开关关闭就好。（不过，磁盘已存储的数据越多，关闭设备加密耗时越长，如果电脑里面东西比较多的话最好合理安排一段空闲时间并接通电源再进行哦！）</p>
</li>
</ol>
<p>--关闭后再进入磁盘管理就会发现没有 (BitLocker 已加密) 这行信息了。</p>
<ol start="5">
<li>
<p>压缩分区
在磁盘管理中挑选一个分区压缩给Ubuntu，右键选择压缩卷，如果发现可以输入的可压缩空间大小远小于磁盘剩余空间，可以使用DiskGenius工具先进行分区压缩。鱼鱼压缩了200000MB，压缩后会发现多出来一个不到200GB的未分配分区。</p>
</li>
<li>
<p>关闭独显直连（未用到）
如果电脑有配备独立显卡并且有独显直连的功能，最好先关闭，以避免安装Ubuntu系统时遇到显卡驱动问题，安装好双系统再启用独显直连功能。鱼鱼没有这样的电脑，如果有这个问腿可以搜一搜如何关闭独显直连功能。</p>
</li>
<li>
<p>制作Ubuntu安装盘 、启动盘制作
--首先下载Ubuntu的映像文件
<a href="https://ubuntu.com/">https://ubuntu.com/</a>
rufus启动盘制作软件
<a href="https://rufus.ie/en/">https://rufus.ie/en/</a>
--确认一下盘符容量大小显示的是要用到的U盘，在配置选项中选择分区类型，改为GPT</p>
</li>
</ol>
<p>--弄好后就可以开始安装啦，会弹出两次格式化提示，都选择是，绿条加载完成弹出安装成功的提示框就完成了，接下来打开把下载好的Ubuntu映像文件粘贴到这个U盘里（如果U盘剩余空间够多，还可以放进去一些其他的系统安装映像文件，当然，放进去其他的文件当作正常U盘使用也是可以的。</p>
<p>--接着重启电脑（U盘不要拔下来哦）狂按对应按键进入BIOS模式（如果不知道按哪个可以看看下面这个表，一般电脑开机的时候也会很快闪过按什么键的提示）</p>
<p>--比如鱼鱼用的Thinkbook16+是要在启动的时候狂按回车，然后出现一个Startup Interrupt Menu，再按F1就可以进入BIOS启动设置界面了。</p>
<p>--先关闭安全启动（Secure Boot），避免启动安装盘时出现Verification failed错误，在鱼鱼电脑的BIOS设置界面中安全启动的设置在这个位置，其他电脑基本也会在类似security，boot，startup这类菜单里找到，然后选择关闭</p>
<p>--接下来关闭Intel RST，避免Ubuntu安装过程出现Turn off RST的问题，找一找SATA Controller Mode这个磁盘的SATA管理器选项，选择设置为AHCI就可以了，有些电脑比如鱼鱼的没有这个选项就没有问题不用管啦（未用到）</p>
<p>--最后把U盘设置为最优先引导项，避免要进入U盘的Ubuntu安装程序时，电脑自动返回到Windows系统启动。在BIOS设置界面找到Boot启动顺序列表，把要用的U盘设备按提示移到最前面，鱼鱼的电脑是F6上移，有些电脑可以直接鼠标拖动的</p>
<p>--最重要的！做完所有修改后记得保存再退出！！！</p>
<p>--接下来进行U盘启动，出现这个Ventoy映像文件列表，选择Ubuntu22.04，启动(Boot in normal mode)，进入Ubuntu映像文件的引导菜单</p>
<p>--选择Try or Install Ubuntu，就进入Ubuntu的安装程序了，没有问题的话就OK！跳到安装程序第一点~</p>
<p>--如果确定BIOS设置里启动顺序保存成功后，还是会直接进入Windows系统，不从U盘启动无法进入Ventoy映像文件列表的话，在设置-&gt;系统-&gt;恢复里，找到恢复选项的高级启动，选择立即重新启动</p>
<p>安装程序
选择Try or Install Ubuntu后等待进入Ubuntu界面，弹出安装程序。
此时如果无法使用键鼠功能可以尝试有线外接鼠标键盘，等之后各类驱动安装完毕就可以用了。
默认正常安装，其他选项中建议取消选择“安装Ubuntu时下载更新”，减少耗时；<strong>可以勾上“为图形或无线硬件，以及其他媒体格式安装第三方软件”。</strong></p>
<p>选择继续，安装类型选择其他选项，选择继续，出现一个磁盘列表，找到设备为空闲且大小较我们之前磁盘分区大小稍大的那条，选中，点左下角的‘+’号，挂载点选择‘/’，点击‘OK’；再找到类型为efi分区的设备那条，看对应的设备号，在下面‘安装启动引导器的设备’下拉找到并选中（一般是Windows Boot Manager）。</p>
<ol start="8">
<li>分区方案
可参考，rtx6000使用的是8G用于swap，其余全部挂载到 / 下
<img src="/uploads/pictures/2026-03-18-15:09:51-ce.png" alt="image.png">
最后点击现在安装，继续，选时区选择Shanghai，继续。</li>
</ol>
<p>接下来设置姓名，计算机名，用户名和密码。名字建议简短一点的英文，登录时是否需要密码按自己需要选择。继续。</p>
<p>等待安装完毕，出现安装完成的提示框后点击现在重启。重启时会看到‘Please remove the installation medium then press ENTER'，这时把U盘拔掉，然后敲回车。按回车电脑如果没反应直接按电源强制重启也可以。</p>
<p>简单配置
BIOS
重启电脑后可能直接进入的还是Windows系统，接下来还要进入一次BIOS启动设置界面，然后将启动顺序里的Ubuntu移动到第一个，还是要记得保存并退出！（有的电脑硬盘引导项有独立子菜单，配置的优先项如果没有找到Ubuntu，先选包括Windows的选项，再找有没有类似UEFI硬盘BBS优先权选项的二级菜单，能够切换成Ubuntu）</p>
<h1>2、中文输入法安装</h1>
<p>输入法安装 点击链接查看和 Kimi 的对话  (采用方案A)
<a href="https://kimi.moonshot.cn/share/d54goh76rtpcgorbp72g">https://kimi.moonshot.cn/share/d54goh76rtpcgorbp72g</a>
<img src="/uploads/pictures/2026-03-18-15:10:01-1a.png" alt="image.png"></p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y ibus-libpinyin
</code></pre>
<h1>3、向日葵远程控制安装（使用PC远程连接一直显示正在建立远程连接，Ubuntu-22.04bug）</h1>
<h3>3.1 dpkg -i安装报错解决（缺少gconf2库）</h3>
<p>可以装，但有 90% 概率第一次 <code>dpkg -i</code> 会报依赖错误，按下面“先补依赖再重装”的顺序 30 秒就能搞定。</p>
<ol>
<li>
<p>进入 deb 包所在目录（假设文件名是 <code>SunloginClient_15.2.0.xxxxx_amd64.deb</code>） cd ~/下载</p>
</li>
<li>
<p>先一次性把可能缺的旧库补齐（Ubuntu 22.04/24.04 官方仓库已移除 gconf，必须手动装） sudo apt update sudo apt -y install gconf2-common libgconf-2-4 libappindicator3-1 libindicator3-7</p>
</li>
<li>
<p>正式安装向日葵 sudo dpkg -i SunloginClient_15.2.0.xxxxx_amd64.deb # 此时如仍报 missing sudo apt --fix-broken install # 自动把剩余依赖拉齐 sudo dpkg -i SunloginClient_15.2.0.xxxxx_amd64.deb # 再次安装，0 报错</p>
</li>
<li>
<p>装完就能在“活动”里搜到 <strong>Sunlogin Client</strong>，第一次启动会要求设置 访问密码，设完即可用识别码远控。</p>
</li>
<li>
<p>如果以后被控端黑屏/断连，再执行下面两行（官方 workaround）<br>
sudo wget <a href="https://sunlogin.oray.com/conf/50-slscreenagrentsvr.conf">https://sunlogin.oray.com/conf/50-slscreenagrentsvr.conf</a> -P /usr/share/lightdm/lightdm.conf.d/<br>
sudo reboot</p>
</li>
</ol>
<p>Ubuntu 22.04/24.04 已经把旧的 gconf 系列包移出官方仓库，所以 <code>apt</code> 直接装会提示 “Unable to locate”。<br>
办法只有一个——<strong>手动把 20.04 时代的两个古董 deb 装回来</strong>，再装向日葵即可。</p>
<pre><code class="language-bash"># 1. 先抓回 gconf2-common 和 libgconf-2-4（3.2.6-6ubuntu1 版本最稳）
wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gconf/gconf2-common_3.2.6-6ubuntu1_all.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gconf/libgconf-2-4_3.2.6-6ubuntu1_amd64.deb

# 2. 一次性装上（顺序已排好）
sudo dpkg -i gconf2-common_3.2.6-6ubuntu1_all.deb libgconf-2-4_3.2.6-6ubuntu1_amd64.deb

# 3. 如果还提示缺 libappindicator3-1、libindicator3-7 等，再补一句
sudo apt --fix-broken install -y

# 4. 现在可以正常装向日葵了
sudo apt install ./SunloginClient_*.deb      # 推荐用 apt，依赖自动补齐
# 或者 sudo dpkg -i SunloginClient_*.deb &amp;&amp; sudo apt --fix-broken install
</code></pre>
<p>装完 <code>systemctl status runsunloginclient.service</code> 看到 active 即 OK，桌面也会弹出“向日葵”图标。<br>
以后系统升级不会影响这两个旧包，放心用。</p>
<h3>3.2 解决一直“正在建立远程连接”</h3>
<p><a href="https://kimi.moonshot.cn/share/d54hbt5e09nb76lq38lg">https://kimi.moonshot.cn/share/d54hbt5e09nb76lq38lg</a>
<strong>Ubuntu 24.04 默认使用的 gdm3 + Wayland 与向日葵存在兼容性问题</strong>，这是导致“一直卡在正在建立远程连接”的根本原因。
解决方案：<strong>切换为 lightdm 显示管理器</strong></p>
<pre><code class="language-bash">sudo apt update
sudo apt install lightdm
sudo dpkg-reconfigure lightdm  # 选择 lightdm 后回车确认
sudo reboot
</code></pre>
<h1>（硬件安装）4、加装机械硬盘</h1>
<p><a href="https://www.kimi.com/share/d54m44fhq49t3uog8av0">https://www.kimi.com/share/d54m44fhq49t3uog8av0</a>
b站相关视频
<a href="https://www.bilibili.com/video/BV1kY411K75H">https://www.bilibili.com/video/BV1kY411K75H</a>
<img src="/uploads/pictures/2026-03-18-15:10:14-1c.png" alt="image.png"></p>]]></description>
      <author>sherioc</author>
      <guid>article-8</guid>
      <pubDate>Mon, 22 Dec 2025 15:08:34 +0000</pubDate>
    </item>
    <item>
      <title>WSL2配置代理</title>
      <link>http://sherioc.online/posts/wsl2pei-zhi-dai-li</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/wsl2pei-zhi-dai-li">http://sherioc.online/posts/wsl2pei-zhi-dai-li</a></p></blockquote><p>1、关闭小猫🐱</p>
<p>2、设置为mirrored模式</p>
<p><img src="/uploads/pictures/2026-03-16-13:56:12-c3.png" alt="image.png"></p>
<blockquote>
<p>该设置会生成 C:/Users/<code>&lt;username&gt;</code>/.wslconfig</p>
</blockquote>
<p>【可选】修改.wslconfig文件内容如下</p>
<pre><code class="language-shell">[experimental]
autoMemoryReclaim=gradual  
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
</code></pre>
<p>3、打开cmd并执行wsl --shutdown
4、重新启动🐱、wsl</p>
<blockquote>
<p>参考 :</p>
<p><a href="https://blog.csdn.net/heromps/article/details/137889499">使用WSL2时控制台输出“wsl: 检测到 localhost 代理配置，但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理“_wsl: 使用镜像网络模式时,wsl2.localhostforwarding 设置无效-CSDN博客</a></p>
</blockquote>]]></description>
      <author>sherioc</author>
      <guid>article-7</guid>
      <pubDate>Fri, 17 Jan 2025 13:58:51 +0000</pubDate>
    </item>
    <item>
      <title>CUDA配置</title>
      <link>http://sherioc.online/posts/cudapei-zhi</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/cudapei-zhi">http://sherioc.online/posts/cudapei-zhi</a></p></blockquote><blockquote>
<p>ref :https://zhuanlan.zhihu.com/p/10747333168</p>
</blockquote>
<h3>1、GPU准备</h3>
<p>1、查看GPU类型
GeForce RTX 3060
<img src="/uploads/pictures/2026-03-16-13:40:15-9c.png" alt="image.png"></p>
<p>2、查看算力</p>
<blockquote>
<p><a href="https://en.wikipedia.org/wiki/CUDA#GPUs_supported">https://en.wikipedia.org/wiki/CUDA#GPUs_supported</a></p>
</blockquote>
<p>算力8.6
<img src="/uploads/pictures/2026-03-16-13:40:25-ba.png" alt="image.png"></p>
<p>3、确定CUDA Runtime
支持的CUDA SDK为11.1-12.5
<img src="/uploads/pictures/2026-03-16-13:40:36-f1.png" alt="image.png"></p>
<p>4、查看驱动的Driver Version
CUDA Version 为12.3
<img src="/uploads/pictures/2026-03-16-13:40:47-a9.png" alt="image.png"></p>
<p>所以适用的CUDA 11.1-12.3</p>
<h3>2、更新显卡驱动</h3>
<p>1、下载了最新显卡驱动
<img src="/uploads/pictures/2026-03-16-13:40:59-6c.png" alt="image.png">
<img src="/uploads/pictures/2026-03-16-13:41:12-8f.png" alt="image.png">
<code>C:\NVIDIA\DisplayDriver\560.94\Win11_Win10-DCH_64\International</code></p>
<p>2、查看最新驱动的Driver Version
CUDA Version为12.6
<img src="/uploads/pictures/2026-03-16-13:41:21-cf.png" alt="image.png"></p>
<h3>3、项目环境搭建（示例）</h3>
<p><img src="/uploads/pictures/2026-03-16-13:41:29-09.png" alt="image.png"></p>]]></description>
      <author>sherioc</author>
      <guid>article-5</guid>
      <pubDate>Tue, 10 Sep 2024 13:38:11 +0000</pubDate>
    </item>
    <item>
      <title>CORS跨域</title>
      <link>http://sherioc.online/posts/corskua-yu</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/corskua-yu">http://sherioc.online/posts/corskua-yu</a></p></blockquote><h2>什么是跨域</h2>
<blockquote>
<p>浏览器的同源策略：浏览器为确保资源安全，而遵循的一种策略，该策略对访问资源进行了一些限制
<a href="https://www.w3.org/Security/wiki/Same_Origin_Policy">https://www.w3.org/Security/wiki/Same_Origin_Policy</a>
<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS</a></p>
</blockquote>
<h3>1、发生跨域后会出现的问题：</h3>
<!-- raw HTML omitted -->
<pre><code>&lt;!-- &lt;iframe id=&quot;framePage&quot; src=&quot;./demo.html&quot;&gt;&lt;/iframe&gt; --&gt;
&lt;iframe id=&quot;framePage&quot; src=&quot;https://www.baidu.com&quot;&gt;&lt;/iframe&gt;

&lt;script type=&quot;text/javascript&quot; &gt;
  function showDOM(){
    const framePage = document.getElementById('framePage')
    console.log(framePage.contentWindow.document) //同源的可以获取，非同源的无法获取
  }
&lt;/script&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;iframe id=&quot;baidu&quot; src=&quot;http://www.baidu.com&quot; width=&quot;500&quot; height=&quot;300&quot;&gt;&lt;/iframe&gt;

&lt;script type=&quot;text/javascript&quot; &gt;
  // 访问的是当前源的cookie，并不是baidu的cookie
  console.log(document.cookie)
&lt;/script&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
let result = await fetch(url)
let data = await result.json();
console.log(data)
</code></pre>
<!-- raw HTML omitted -->
<h3>2、注意点</h3>
<p>1、跨域限制仅存在浏览器端，服务端不存在跨域限制
2、即使跨域了，Ajax 请求也可以正常发出，但响应数据不会交给开发者
<img src="/uploads/pictures/2026-03-16-13:33:17-65.png" alt="image.png"></p>
<p>3、<code>&lt;link&gt;</code>、<code>&lt;script&gt;、&lt;img&gt;</code>...... 这些标签发出的请求也可能跨域，只不过浏览器对标签跨域不做严格限制，对开发几乎无影响</p>
<h2>跨域的解决方案</h2>
<h3>1、解决方案一：CORS</h3>
<blockquote>
<p>CORS 全称：Cross-Origin Resource Sharing（跨域资源共享），是用于控制浏览器校验跨域请求的一套规范，服务器依照 CORS 规范，添加特定响应头来控制浏览器校验，大致规则如下：
● 服务器明确表示拒绝跨域请求，或没有表示，则浏览器校验不通过。
● 服务器明确表示允许跨域请求，则浏览器校验通过</p>
</blockquote>
<p>（1）处理简单请求</p>
<blockquote>
<p>简单请求</p>
</blockquote>
<ul>
<li>请求方法为：GET、HEAD、POST</li>
<li>请求头的Content-Type的值只能是以下三种：
● text/plain
● multipart/form-data
● application/x-www-form-urlencoded</li>
</ul>
<p>服务器响应时候，添加 <code>Access-Control-Allow-Origin</code>响应头，声明允许某个源发起跨域请求，浏览器校验通过
<img src="/uploads/pictures/2026-03-16-13:33:39-d0.png" alt="image.png"></p>
<!-- raw HTML omitted -->
<pre><code>// 处理跨域中间件
function corsMiddleWare(req,res,next){
  // 允许 http://127.0.0.1:5500 这个源发起跨域请求
  // res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')
  
  // 允许所有源发起跨域请求
  res.setHeader('Access-Control-Allow-Origin','*')
  next()
}

// 配置路由并使用中间件
app.get('/',corsMiddleWare,(req,res)=&gt;{
  res.send('hello!')
})
</code></pre>
<!-- raw HTML omitted -->
<p>（2）处理复杂请求</p>
<blockquote>
<p>复杂请求：不是简单请求的请求就是复杂请求，比如application/json
复杂请求会自动发送预检请求</p>
</blockquote>
<p><img src="/uploads/pictures/2026-03-16-13:33:54-46.png" alt="image.png"></p>
<blockquote>
<p>解决方案</p>
</blockquote>
<p>第一步：服务器先通过浏览器的预检请求，服务器需要返回如下响应头：</p>
<p><img src="/uploads/pictures/2026-03-16-13:34:07-f5.png" alt="image.png"></p>
<p>第二步：处理实际的跨域请求（与处理简单请求跨域的方式相同）
<img src="/uploads/pictures/2026-03-16-13:33:39-d0.png" alt="image.png"></p>
<!-- raw HTML omitted -->
<pre><code>// 处理预检请求
app.options('/students', (req, res) =&gt; {
  // 设置允许的跨域请求源
  res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  // 设置允许的请求方法
  res.setHeader('Access-Control-Allow-Methods', 'GET')
  // 设置允许的请求头
  res.setHeader('Access-Control-Allow-Headers', 'school')
  // 设置预检请求的缓存时间（可选）
  res.setHeader('Access-Control-Max-Age', 7200)
  // 发送响应
  res.send()
})

// 处理实际请求
app.get('/students', (req, res) =&gt; {
  // 设置允许的跨域请求源
  res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  // 随便设置一个自定义响应头
  res.setHeader('abc',123)
  // 设置允许暴露给客户端的响应头
  res.setHeader('Access-Control-Expose-Headers', 'abc')
  // 打印请求日志
  console.log('有人请求/students了')
  // 发送响应数据
  res.send(students)
})
</code></pre>
<!-- raw HTML omitted -->
<h3>2、解决方案二：使用cors库等</h3>
<!-- raw HTML omitted -->
<pre><code>// 配置cors库
app.use(cors())
// cors中间件配置
const corsOptions = {
  origin: 'http://127.0.0.1:5500', // 允许的源
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
  allowedHeaders: ['school'], // 允许的自定义头
  exposedHeaders: ['abc'], // 要暴露的响应头
  optionsSuccessStatus: 200 // 预检请求成功的状态码
};

app.use(cors(corsOptions)); // 使用cors中间件
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>INSTALLED_APPS = [
    'django.contrib.admin',
	...
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 处理跨域
    'corsheaders',
]

MIDDLEWARE = [
	...
    'django.contrib.sessions.middleware.SessionMiddleware',
    # 处理跨域
    &quot;corsheaders.middleware.CorsMiddleware&quot;,
	...
]
</code></pre>
<!-- raw HTML omitted -->
<h3>3、解决方案三、JSONP</h3>
<ol>
<li>JSONP 概述： JSONP 是利用了 <code>&lt;script&gt;</code>标签可以跨域加载脚本，且不受严格限制的特性，可以说是程序员智慧的结晶，早期一些浏览器不支持 CORS 的时，可以靠 JSONP 解决跨域。</li>
<li>基本流程：
○ 第一步：客户端创建一个 <code>&lt;script&gt;</code>标签，并将其src属性设置为包含跨域请求的 URL，同时准备一个回调函数，这个回调函数用于处理返回的数据。
○ 第二步：服务端接收到请求后，将数据封装在回调函数中并返回。
○ 第三步：客户端的回调函数被调用，数据以参数的形势传入回调函数。
<img src="/uploads/pictures/2026-03-16-13:34:44-5d.png" alt="image.png"></li>
</ol>
<!-- raw HTML omitted -->
<pre><code>&lt;button onclick=&quot;getTeachers()&quot;&gt;获取数据&lt;/button&gt;

&lt;script type=&quot;text/javascript&quot; &gt;
  function callback(data){
    console.log(data)
  }

  function getTeachers(url){
    // 创建script元素
    const script = document.createElement('script')
    // 指定script的src属性
    script.src= 'http://127.0.0.1:8081/teachers'
    // 将script元素添加到body中触发脚本加载
    document.body.appendChild(script)
    // script标签加载完毕后移除该标签
    script.onload = ()=&gt;{
      script.remove()
    }
  }
&lt;/script&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>$.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=&gt;{
  console.log(data)
})
</code></pre>
<!-- raw HTML omitted -->
<h3>4、配置代理解决跨域</h3>
<h4>4.1 自己配置代理服务器</h4>
<!-- raw HTML omitted -->
<pre><code>const { createProxyMiddleware } = require('http-proxy-middleware');

app.use('/api',createProxyMiddleware({
  target:'https://www.toutiao.com',
  changeOrigin:true,
  pathRewrite:{
    '^/api':''
  }
}))
</code></pre>
<!-- raw HTML omitted -->
<h4>4.2</h4>
<p>基于nginx搭建代理服务器，基于Vue等脚手架搭建代理服务器（本质上是对4.1的封装）</p>]]></description>
      <author>sherioc</author>
      <guid>article-4</guid>
      <pubDate>Tue, 16 Jul 2024 13:36:07 +0000</pubDate>
    </item>
    <item>
      <title>文本抄袭自动检测分析</title>
      <link>http://sherioc.online/posts/wen-ben-chao-xi-zi-dong-jian-ce-fen-xi</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/wen-ben-chao-xi-zi-dong-jian-ce-fen-xi">http://sherioc.online/posts/wen-ben-chao-xi-zi-dong-jian-ce-fen-xi</a></p></blockquote><h1>任务描述</h1>
<p>如果你是某新闻单位工作人员（这里假设source=新华社），为了防止其他媒体抄袭你的文章，做一个抄袭自动检测分析的工具：</p>
<p>一、定义可能抄袭的文章来源</p>
<p>二、与原文对比定位抄袭的地方</p>
<h1>数据预处理</h1>
<p>本次实验涉及的数据预处理</p>
<pre><code class="language-python">- 数据清洗，针对content字段为空的情况，进行dropna
- 分词，使用jieba进行分词
- 数据集切分，70%训练集，30%测试集
- 分词并保存分词结果到 corpus.pkl
</code></pre>
<h1>需求分析及实现路线</h1>
<h3>需求分析</h3>
<pre><code class="language-python">- 实现对大量文本数据的快速加载和处理
- 有效地提取文本特征以进行抄袭检测
- 使用分类模型预测文章风格是否与源文章一致
- 对疑似抄袭文章进行聚类和相似度比对
- 通过编辑距离进行精确比对确认抄袭情况
</code></pre>
<h3>实现路线</h3>
<pre><code class="language-python">- 数据加载与预处理：加载数据库导出的文章数据，进行数据清洗、分词等预处理操作。
- 特征提取与分类模型训练：提取TF-IDF特征，并使用分类模型（如MultinomialNB）训练数据集。
- 聚类降维：对全量文本进行聚类降维，减少比对复杂度。
- 相似度比对：基于TF-IDF相似度矩阵找出相似文章，并利用编辑距离进行精确比对。
</code></pre>
<h3>算法设计如下</h3>
<pre><code class="language-python">数据加载与预处理：
a. 加载包含文本内容的CSV文件（如sqlResult.csv）和停用词表（如chinese_stopwords.txt）。
b. 清洗数据，移除空值（如content字段为空的情况）。
c. 使用分词工具（如jieba）对文本进行分词。
d. 将处理后的分词结果保存到corpus.pkl以便后续使用。
e. 将数据集划分为训练集（70%）和测试集（30%）。
特征提取：
a. 计算文本的TF-IDF特征。
预测文章风格：
a. 使用分类算法（如MultinomialNB）基于文本特征（如TF-IDF）和标签（是否为新华社）进行训练。
寻找可能的抄袭文章：
a. 找到预测标签为1（属于新华社）但实际标签为0的文章。
聚类降维：
a. 如果需要比对的文本数量较大，可以使用k-means算法对文本进行聚类降维，例如将文本分为25个类别。
检索相似文章：
a. 对于一篇可能的抄袭文章，从相同标签中找到对应新华社的文章。
b. 根据TF-IDF相似度矩阵，按相似度从大到小排序，取Top N（如Top 10）相似文章。
计算编辑距离：
a. 使用编辑距离（editdistance）算法计算疑似抄袭文章与原文之间的编辑距离。
逐句比对：
a. 对疑似抄袭文章与原文进行逐句比对，计算每个句子的编辑距离。
</code></pre>
<h1>模块设计及实现</h1>
<h2>总体模块设计</h2>
<p>使用pandas进行数据预处理、特征工程提取TF-IDF特征、基于MultinomialNB进行分类模型训练，并基于K-Means聚类桶进行分组后使用模型进行结果预测，最后使用编辑距离进行文章对比，总体模块设计如下：</p>
<p><img src="https://img2023.cnblogs.com/blog/3205713/202406/3205713-20240618103732995-543640111.png" alt="image-20240618092036207"></p>
<h2>1、数据集加载</h2>
<p>导包</p>
<pre><code class="language-python">import pickle, os
import jieba
import pandas as pd
from icecream import ic
from sklearn.cluster import KMeans
from collections import defaultdict
from sklearn.preprocessing import Normalizer # 把tfidf归一化为单位向量
from sklearn.naive_bayes import MultinomialNB # 多项式贝叶斯模型
from sklearn.model_selection import train_test_split # 拆分数据集
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 统计词频、计算tfidf
from sklearn.metrics import classification_report # 分类报告 评估模型
from sklearn.metrics.pairwise import cosine_similarity # 计算余弦相似度
import editdistance # 计算编辑距离
</code></pre>
<p>加载停用词</p>
<pre><code class="language-python">with open('dataset/chinese_stopwords.txt','r',encoding='utf-8') as file:
    stopwords = [line.strip() for line in file]
</code></pre>
<pre><code class="language-python">stopwords[:10]
</code></pre>
<pre><code>['，', '的', '。', '、', '在', '了', '是', '', '“', '”']
</code></pre>
<p>加载数据集</p>
<pre><code class="language-python"># gb18030编码收录的中文字符更全，对中文文档兼容性更好
df = pd.read_csv('dataset/sqlResult.csv',encoding='gb18030')
</code></pre>
<pre><code class="language-python">df.head(2)
</code></pre>
<!-- raw HTML omitted -->
<pre><code>.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</code></pre>
<p><!-- raw HTML omitted --></p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code class="language-python">df.info()
</code></pre>
<pre><code>&lt;class 'pandas.core.frame.DataFrame'&gt;
RangeIndex: 89611 entries, 0 to 89610
Data columns (total 7 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   id       89611 non-null  int64
 1   author   79396 non-null  object
 2   source   89609 non-null  object
 3   content  87054 non-null  object
 4   feature  89611 non-null  object
 5   title    89577 non-null  object
 6   url      87144 non-null  object
dtypes: int64(1), object(6)
memory usage: 4.8+ MB
</code></pre>
<p>可以看到，content 存在缺失数据，需要进行缺失值处理
而 source 中也存在缺失数据（无源数据），需要单独去除</p>
<h2>2、数据预处理</h2>
<p>缺失值处理</p>
<pre><code class="language-python"># 去除content列存在缺失值的行
df.dropna(subset=['content'],inplace=True)
# 去除
df.dropna(subset=['source'],inplace=True)
df.info()
</code></pre>
<pre><code>&lt;class 'pandas.core.frame.DataFrame'&gt;
Index: 87052 entries, 0 to 89610
Data columns (total 7 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   id       87052 non-null  int64
 1   author   76925 non-null  object
 2   source   87052 non-null  object
 3   content  87052 non-null  object
 4   feature  87052 non-null  object
 5   title    87052 non-null  object
 6   url      87052 non-null  object
dtypes: int64(1), object(6)
memory usage: 5.3+ MB
</code></pre>
<p>分词，使用 jieba 分词</p>
<pre><code class="language-python">def split_text(text):
    text = text.replace(' ', '').replace('\n','').replace('\r','')
    text2 = jieba.cut(text)
    # 去掉停用词
    result = ' '.join([w for w in text2 if w not in stopwords])
    return result
</code></pre>
<pre><code class="language-python">temp = df.iloc[0].content
print('测试数据：',temp)
print('测试分词结果：',split_text(temp))
</code></pre>
<pre><code>Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\Administrator\AppData\Local\Temp\jieba.cache

测试数据： 此外，自本周（6月12日）起，除小米手机6等15款机型外，其余机型已暂停更新发布（含开发版/体验版内测，稳定版暂不受影响），以确保工程师可以集中全部精力进行系统优化工作。有人猜测这也是将精力主要用到MIUI 9的研发之中。
MIUI 8去年5月发布，距今已有一年有余，也是时候更新换代了。
当然，关于MIUI 9的确切信息，我们还是等待官方消息。

Loading model cost 0.488 seconds.
Prefix dict has been built successfully.

测试分词结果： 此外 本周 除 小米 手机 款 机型 外 机型 暂停 更新 发布 含 开发 版 体验版 内测 稳定版 暂不受 影响 确保 工程师 集中 全部 精力 进行 系统优化 工作 有人 猜测 精力 主要 用到 MIUI9 研发 之中 MIUI8 去年 发布 距今已有 一年 有余 更新换代 当然 MIUI9 确切 信息 等待 官方消息
</code></pre>
<p>分词并保存分词结果到 corpus.pkl</p>
<pre><code class="language-python"># 假如路径存在，则直接读取，否则进行分词，并保存到本地
if os.path.exists('dataset/corpus.pkl'):
    with open('dataset/corpus.pkl', 'rb') as file:
        corpus = pickle.load(file)
else:
    corpus = df['content'].map(split_text)
    # 将处理好的分词保存到 corpus.pkl，方便下次调用
    with open('dataset/corpus.pkl', 'wb') as file:
        pickle.dump(corpus, file)

</code></pre>
<pre><code class="language-python">print(corpus.shape)
print(type(corpus[0]))
print(corpus[0])
print(len(set(corpus[0].split())))
</code></pre>
<pre><code>(87052,)
&lt;class 'str'&gt;
此外 本周 除 小米 手机 款 机型 外 机型 暂停 更新 发布 含 开发 版 体验版 内测 稳定版 暂不受 影响 确保 工程师 集中 全部 精力 进行 系统优化 工作 有人 猜测 精力 主要 用到 MIUI9 研发 之中 MIUI8 去年 发布 距今已有 一年 有余 更新换代 当然 MIUI9 确切 信息 等待 官方消息
45
</code></pre>
<p>查看所有新闻对应的 source</p>
<pre><code class="language-python">df['source'].value_counts().head()
</code></pre>
<pre><code>source
新华社          78661
中国新闻网          523
中国证券报?中证网      510
参考消息网          385
环球网            308
Name: count, dtype: int64
</code></pre>
<p>查看含有新华社的 source</p>
<pre><code class="language-python">df[df['source'].str.contains('新华')]['source'].value_counts()
</code></pre>
<pre><code>source
新华社                                                                                78661
新华网                                                                                  172
新华社新媒体专线                                                                              10
新华日报1                                                                                  3
新华国际                                                                                   2
新华社@                                                                                   1
新华通讯社                                                                                  1
新华社@http://tech.163.com/17/0619/15/CNA7J2EJ00097U7T.html                               1
新华社@http://tech.huanqiu.com/intelligent/2017-06/10868069.html?qq-pf-to=pcqq.c2c        1
新华网@                                                                                   1
新华网@http://tech.163.com/17/0620/15/CNCQ8UH500097U81.html                               1
新华国际微博                                                                                 1
Name: count, dtype: int64
</code></pre>
<p>认为上面类似‘新华社@’，‘新华社新媒体专线’等都属于新华社</p>
<p>进行 0 1 标记 source 为新华社的新闻和其他新闻</p>
<pre><code class="language-python">label = df['source'].copy()
target = label.str.contains('新华') * 1 # series.str.contains() 返回布尔索引，用*1转为 0 1
target[:5]
</code></pre>
<pre><code>0    0
1    0
2    0
3    1
4    0
Name: source, dtype: int32
</code></pre>
<h2>3、逆向文档率 TF-IDF 特征提取</h2>
<pre><code class="language-python">corpus
</code></pre>
<pre><code>0        此外 本周 除 小米 手机 款 机型 外 机型 暂停 更新 发布 含 开发 版 体验版 内测...
1        骁龙 835 唯一 Windows10 桌面 平台 认证 ARM 处理器 高通 强调 不会 ...
2        此前 一加 3T 搭载 3400mAh 电池 DashCharge 快充 规格 5V 4A ...
3        这是 18 葡萄牙 中部 佩德罗 冈 地区 拍摄 森林 大火 烧毁 汽车 新华社 记者 张立 云摄
4        原 标题 44 岁 女子 跑 深圳 约会 网友 拒 暴雨 裸身 奔走 … … @ 深圳 交警...
                               ...
89606    新华社 照片 多伦多 2017 \ n 体育 冰球 国家 女子 冰球队 海外 选秀 多伦多 ...
89607    新华社 兰州 日电 王衡 徐丹 记者 甘肃省 交通运输 厅 获悉 甘肃 近日 集中 开建 高...
89608    \ n \ n2017 29 法国巴黎 郊外 凡尔赛宫 法国 总统 马克 龙 出席 新闻 发...
89609    \ n \ n2017 25 美国 马萨诸塞州 剑桥市 哈佛大学 毕业生 毕业典礼 欢呼 新...
89610    新华社 德国 杜塞尔多夫 ６ ６ 日电 题 乒乓 女球迷 \ n 新华社 记者 王子江 张寒...
Name: content, Length: 87052, dtype: object
</code></pre>
<p>计算词频矩阵 TF</p>
<pre><code class="language-python">countvectorizer = CountVectorizer(encoding='gb18030',min_df=0.015)
</code></pre>
<pre><code class="language-python">countvector = countvectorizer.fit_transform(corpus) # 学习词频稀疏矩阵
print(countvector.shape)
print(countvector[:1]) # 查看第一个文档的词频向量（只显示非零元素及其索引）

</code></pre>
<pre><code>(87052, 884)
  (0, 590)	1
  (0, 461)	1
  (0, 271)	2
  (0, 416)	1
  (0, 432)	1
  (0, 669)	1
  (0, 860)	1
  (0, 184)	1
  (0, 822)	1
  (0, 385)	1
  (0, 103)	1
  (0, 667)	1
  (0, 263)	1
  (0, 44)	1
  (0, 174)	1
</code></pre>
<pre><code class="language-python">countvector_arr = countvector.toarray() # 转换稀疏矩阵为数组
print(countvector_arr.shape)
countvector_arr
</code></pre>
<pre><code>(87052, 884)

array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 6, 0]], dtype=int64)
</code></pre>
<p>将词频矩阵转为 TF-IDF 矩阵</p>
<pre><code class="language-python">tfidftransformer = TfidfTransformer()
# 拟合后返回tfidf稀疏矩阵
tfidf = tfidftransformer.fit_transform(countvector)
print(tfidf.shape)
print(tfidf[0])

</code></pre>
<pre><code>(87052, 884)
  (0, 44)	0.2622676107691569
  (0, 103)	0.20106899736814415
  (0, 174)	0.23459189038564443
  (0, 184)	0.2468108139475762
  (0, 263)	0.22918780918486897
  (0, 271)	0.4315609902828978
  (0, 385)	0.18500978673205756
  (0, 416)	0.2635573764739399
  (0, 432)	0.21737704053822574
  (0, 461)	0.28783155518886216
  (0, 590)	0.2377411770105167
  (0, 667)	0.28309620126453316
  (0, 669)	0.2671380200521529
  (0, 822)	0.15081444348966608
  (0, 860)	0.2674007239601568
</code></pre>
<p>拆分数据集（70%训练集，30%测试集）</p>
<pre><code class="language-python"># train_test_split(数据集，标签（source），测试集比例)
x_train,x_test,y_train,y_test = train_test_split(tfidf.toarray(),target,test_size=0.3)
x_train.shape,x_test.shape,y_train.shape,y_test.shape
</code></pre>
<pre><code>((60936, 884), (26116, 884), (60936,), (26116,))
</code></pre>
<h2>4、MultinomialNB 分类模型进行训练</h2>
<p>初始化分类模型 MultinomialNB</p>
<pre><code class="language-python">estimator = MultinomialNB()
estimator
</code></pre>
<p>对于文本的特征（TF-IDF）和label（0-1是否为新华社）进行训练</p>
<pre><code class="language-python">estimator.fit(x_train,y_train)
</code></pre>
<p>评估模型</p>
<pre><code class="language-python">y_pred = estimator.predict(x_test)
print(classification_report(y_test,y_pred,labels=[0,1],target_names=['others','新华']))

</code></pre>
<pre><code>precision    recall  f1-score   support

others       0.45      0.65      0.54      2530
          新华       0.96      0.92      0.94     23586

accuracy                           0.89     26116
   macro avg       0.71      0.78      0.74     26116
weighted avg       0.91      0.89      0.90     26116
</code></pre>
<p>模型的整体精确度达到了 0.89，说明模型在大多数情况下能够正确分类文本</p>
<h2>5、基于模型进行风格预测并找出可能抄袭的文章</h2>
<pre><code class="language-python"># compare_news_df中，prediction1代表预测文章的风格是新华社风格；labels1说明实际为新华社
prediction = estimator.predict(tfidf.toarray())
compare_news_df = pd.DataFrame({&quot;prediction&quot;:prediction,'labels':target.values})
print(compare_news_df.head(2))

# 在实际非新华社的文章中找出预测为新华社风格的文章
copy_news_index = compare_news_df[(compare_news_df['labels'] == 0) &amp; (compare_news_df['prediction'] == 1)]
print(copy_news_index.head(10))
print(&quot;模型预测结果与实际标签不符（即判定为抄袭嫌疑）的文章数:{}&quot;.format(len(copy_news_index)))

</code></pre>
<pre><code>prediction  labels
0           0       0
1           0       0
    prediction  labels
4            1       0
15           1       0
24           1       0
28           1       0
30           1       0
32           1       0
35           1       0
37           1       0
38           1       0
43           1       0
模型预测结果与实际标签不符（即判定为抄袭嫌疑）的文章数:2823
</code></pre>
<p>有 2814 则新闻预测 source 为新华社，但是 label 却不是，所以这些与新华社新闻风格相似的有抄袭嫌疑
可以看到，4 和 24 号文章都有抄袭嫌疑</p>
<pre><code class="language-python"># 实际为新华社和非新华社新闻的index
xinhuashe_news_index = compare_news_df[compare_news_df['labels'] == 1].index
no_xinhuashe_news_index = compare_news_df[compare_news_df['labels'] == 0].index
print(xinhuashe_news_index)
print(no_xinhuashe_news_index)
</code></pre>
<pre><code>Index([    3,    17,    25,    27,    39,    51,    65,    95,   102,   111,
       ...
       87042, 87043, 87044, 87045, 87046, 87047, 87048, 87049, 87050, 87051],
      dtype='int64', length=78855)
Index([   0,    1,    2,    4,    5,    6,    7,    8,    9,   10,
       ...
       8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553],
      dtype='int64', length=8197)
</code></pre>
<h2>6、使用 K-Means 对文章进行聚类</h2>
<pre><code class="language-python">&quot;&quot;&quot;
sklearn中的k-means算法只支持欧氏距离计算相似度
在文本的相似度比较中我们一般使用余弦距离。

欧氏距离衡量的是空间各点的绝对距离，跟各个点所在的位置坐标直接相关；
而余弦距离衡量的是空间向量的夹角，更加体现在方向上的差异，而不是位置。
&quot;&quot;&quot;
</code></pre>
<pre><code>'\nsklearn中的k-means算法只支持欧氏距离计算相似度\n在文本的相似度比较中我们一般使用余弦距离。\n\n欧氏距离衡量的是空间各点的绝对距离，跟各个点所在的位置坐标直接相关；\n而余弦距离衡量的是空间向量的夹角，更加体现在方向上的差异，而不是位置。\n'
</code></pre>
<p>对全量文本的 TF-IDF 进行范式归一化</p>
<pre><code class="language-python"># 对特征向量进行L2范数归一化后，欧氏距离和余弦距离等价，便于进行k-means聚类
transfer = Normalizer()
scaled_array = transfer.fit_transform(tfidf.toarray())

</code></pre>
<p>对全量文本进行 K-Means 聚类</p>
<pre><code class="language-python"># 使用K-Means进行聚类降维，嫌疑新闻只和相同堆中的新华社新闻进行计算
estimator2 = KMeans(n_clusters=25)
estimator2.fit(scaled_array)
k_labels = estimator2.predict(scaled_array)
</code></pre>
<p>建立聚类类别与实为新华社文章的 index 之间的映射关系</p>
<pre><code class="language-python">k_labels_sr = pd.Series(k_labels)
</code></pre>
<pre><code class="language-python">class_id = defaultdict(set)

for index,value in k_labels_sr.items():
    # 对真实为新华社的新闻index分组
    if index in xinhuashe_news_index:
        class_id[value].add(index)

class_id.keys()

</code></pre>
<pre><code>dict_keys([13, 12, 6, 10, 24, 11, 2, 7, 15, 17, 20, 21, 4, 18, 22, 1, 16, 23, 5, 0, 14, 19, 8, 3, 9])
</code></pre>
<p>将聚类结果保存在 label.pkl 中</p>
<pre><code class="language-python"># 假如路径存在，则直接读取，否则进行分词，并保存到本地
import os
if os.path.exists('dataset/label.pkl'):
    with open('dataset/label.pkl', 'rb') as file:
        label = pickle.load(file)
else:
    label = df['content'].map(class_id)
    # 将处理好的分词保存到 label.pkl，方便下次调用
    with open('dataset/label.pkl', 'wb') as file:
        pickle.dump(label, file)
</code></pre>
<h2>7、查看相似文章(测试结果)</h2>
<pre><code class="language-python">def find_similar_text(copy_index,top=10):
    # 只在新华社发布的文章中查找
    label = k_labels_sr[copy_index]
    dist_dict = {i:cosine_similarity(tfidf[copy_index],tfidf[i]) for i in class_id[label]}

    # 从大到小排序
    return sorted(dist_dict.items(),key=lambda x:x[1][0], reverse=True)[:top]

</code></pre>
<pre><code class="language-python">copy_index = 3352
</code></pre>
<p>抄袭嫌疑新闻与相似 Top10 新华社新闻</p>
<pre><code class="language-python">similar_list = find_similar_text(copy_index)

ic(len(similar_list))
similar_list

</code></pre>
<pre><code>ic| len(similar_list): 10

[(3134, array([[0.96848961]])),
 (63509, array([[0.94642972]])),
 (29439, array([[0.94283134]])),
 (3218, array([[0.87621302]])),
 (980, array([[0.87534597]])),
 (29613, array([[0.86935867]])),
 (29886, array([[0.8621539]])),
 (64044, array([[0.85277574]])),
 (29775, array([[0.84875245]])),
 (64756, array([[0.73394623]]))]
</code></pre>
<p>查看抄袭新闻与新华社原文</p>
<pre><code class="language-python">print('抄袭嫌疑新闻内容:\n',df.iloc[copy_index].content)
</code></pre>
<pre><code>抄袭嫌疑新闻内容:
 　　中国5月份56座城市新建商品住宅价格环比上涨，4月份为58座上涨。5月份15个一线和热点二线城市房地产市场基本稳定，5月份房地产调控政策效果继续显现。
　　统计局：15个一线和热点二线城市房价同比涨幅全部回落
　　国家统计局城市司高级统计师刘建伟解读5月份房价数据
　　5月份一二线城市房价平均涨幅继续回落
　　国家统计局今日发布了2017年5月份70个大中城市住宅销售价格统计数据。对此，国家统计局城市司高级统计师刘建伟进行了解读。
　　一、15个一线和热点二线城市新建商品住宅价格同比涨幅全部回落、9个城市环比下降或持平
　　5月份，因地制宜、因城施策的房地产调控政策效果继续显现，15个一线和热点二线城市房地产市场基本稳定。从同比看，15个城市新建商品住宅价格涨幅均比上月回落，回落幅度在0.5至6.4个百分点之间。从环比看，9个城市新建商品住宅价格下降或持平；5个城市涨幅在0.5%以内。
　　二、70个大中城市中一二线城市房价同比涨幅持续回落
　　5月份，70个城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有29和18个。其中，一二线城市同比涨幅回落尤其明显。据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续8个月回落，5月份比4月份分别回落2.2和1.7个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续6个月和4个月回落，5月份比4月份分别回落0.8和0.5个百分点。
　　三、70个大中城市中房价环比下降及涨幅回落城市个数均有所增加
　　5月份，70个城市中新建商品住宅价格环比下降的城市有9个，比上月增加1个；涨幅回落的城市有26个，比上月增加3个。二手住宅价格环比下降的城市有7个，比上月增加2个；涨幅回落的城市有30个，比上月增加8个。
</code></pre>
<pre><code class="language-python"># 找一篇相似的新华社原文
similar2 = similar_list[0][0]
print('新华社相似原文:\n',df.iloc[similar2].content)

</code></pre>
<pre><code>新华社相似原文:
 　　国家统计局19日发布数据，5月份，15个一线和热点二线城市新建商品住宅价格同比涨幅全部回落，其中9个城市环比下降或持平。这9个价格环比下降或持平的城市为：北京、上海、南京、杭州、合肥、福州、郑州、深圳、成都。
　　“5月份，因地制宜、因城施策的房地产调控政策效果继续显现，15个一线和热点二线城市房地产市场基本稳定。”国家统计局城市司高级统计师刘建伟说，从同比看，15个城市新建商品住宅价格涨幅均比上月回落，回落幅度在0.5至6.4个百分点之间。从环比看，9个城市新建商品住宅价格下降或持平；5个城市涨幅在0.5%以内。
　　国家统计局当天还发布了5月份70个大中城市住宅销售价格统计数据。刘建伟介绍，5月份，70个大中城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有29和18个。其中，一二线城市同比涨幅回落尤其明显。据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续8个月回落，5月份比4月份分别回落2.2和1.7个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续6个月和4个月回落，5月份比4月份分别回落0.8和0.5个百分点。
　　此外，70个大中城市中房价环比下降及涨幅回落城市个数均有所增加。统计显示，5月份，70个大中城市中新建商品住宅价格环比下降的城市有9个，比上月增加1个；涨幅回落的城市有26个，比上月增加3个。二手住宅价格环比下降的城市有7个，比上月增加2个；涨幅回落的城市有30个，比上月增加8个。
</code></pre>
<pre><code class="language-python"># 找一篇相似的新华社原文
similar3 = similar_list[1][0]
print('新华社相似原文:\n',df.iloc[similar3].content)
</code></pre>
<pre><code>新华社相似原文:
 　　新华社北京5月18日电国家统计局18日发布的数据显示，4月份，15个一线和热点二线城市新建商品住宅价格同比涨幅回落，9个城市环比下降或持平。\n　　这9个价格环比下降或持平的城市是天津、上海、南京、合肥、福州、杭州、厦门、深圳、成都。\n　　“4月份，因地制宜、因城施策的房地产调控政策继续发挥作用。”国家统计局城市司高级统计师刘建伟说，从同比看，15个城市新建商品住宅价格涨幅均比上月回落，回落幅度在0.7至7.4个百分点之间。从环比看，9个城市新建商品住宅价格下降或持平；5个城市涨幅回落，回落幅度在0.2至1.1个百分点之间。\n　　国家统计局当天还发布了4月份70个大中城市住宅销售价格统计数据。刘建伟介绍，从同比看，4月份70个城市中有30个城市新建商品住宅价格涨幅比上月回落，比3月份增加6个，回落城市中23个为一二线城市。初步测算，一线城市新建商品住宅价格同比涨幅连续7个月回落，4月份比3月份回落2.8个百分点；二线城市新建商品住宅价格同比涨幅连续5个月回落，4月份比3月份回落1.0个百分点；三线城市新建商品住宅价格同比涨幅略有扩大，4月份比3月份扩大0.4个百分点。\n　　从环比看，4月份70个城市中有23个城市新建商品住宅价格涨幅比上月回落，比3月份增加13个；7个城市由上月上涨转为持平或下降；3个城市降幅扩大。（完）
</code></pre>
<h2>8、基于编辑距离进行文章对比</h2>
<p>嫌疑文章和新华社原文整体编辑距离</p>
<pre><code class="language-python">editdistance.eval(df.iloc[copy_index].content, df.iloc[similar2].content)
</code></pre>
<pre><code>299
</code></pre>
<pre><code class="language-python">import editdistance
from IPython.display import display, HTML

# 示例疑似文章和原文
suspected_article = df.iloc[copy_index].content
original_article = df.iloc[similar2].content

# 分句函数
def split_into_sentences(text):
    return text.split('。')

# 对齐句子
def align_sentences(sentences1, sentences2):
    max_len = max(len(sentences1), len(sentences2))
    sentences1 += [''] * (max_len - len(sentences1))
    sentences2 += [''] * (max_len - len(sentences2))
    return sentences1, sentences2

# 分句
suspected_sentences = split_into_sentences(suspected_article)
original_sentences = split_into_sentences(original_article)

# 对齐句子
aligned_suspected, aligned_original = align_sentences(suspected_sentences, original_sentences)

# 设置编辑距离阈值
threshold = 100

# 逐句比对并显示彩色文本
html_output = &quot;&quot;
for suspected_sentence, original_sentence in zip(aligned_suspected, aligned_original):
    distance = editdistance.eval(suspected_sentence, original_sentence)
    if distance &lt;= threshold:
        html_output += f&quot;&lt;p&gt;&lt;span style='color:red;'&gt;{suspected_sentence}&lt;/span&gt; vs &lt;span style='color:red;'&gt;{original_sentence}&lt;/span&gt; (编辑距离为：{distance})&lt;/p&gt;&quot;
    else:
        html_output += f&quot;&lt;p&gt;{suspected_sentence} vs {original_sentence} (编辑距离为：{distance})&lt;/p&gt;&quot;

display(HTML(html_output))
</code></pre>
<!-- raw HTML omitted -->
<p>统计局：15 个一线和热点二线城市房价同比涨幅全部回落</p>
<p>国家统计局城市司高级统计师刘建伟解读 5 月份房价数据</p>
<p>5 月份一二线城市房价平均涨幅继续回落</p>
<p>国家统计局今日发布了 2017 年 5 月份 70 个大中城市住宅销售价格统计数据 vs</p>
<p>“5 月份，因地制宜、因城施策的房地产调控政策效果继续显现，15 个一线和热点二线城市房地产市场基本稳定 (编辑距离为：108)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code>对此，国家统计局城市司高级统计师刘建伟进行了解读 vs <code>&lt;span style='color:red;'&gt;</code>”国家统计局城市司高级统计师刘建伟说，从同比看，15 个城市新建商品住宅价格涨幅均比上月回落，回落幅度在 0.5 至 6.4 个百分点之间 (编辑距离为：50)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code></p>
<p>一、15 个一线和热点二线城市新建商品住宅价格同比涨幅全部回落、9 个城市环比下降或持平</p>
<p>5 月份，因地制宜、因城施策的房地产调控政策效果继续显现，15 个一线和热点二线城市房地产市场基本稳定 vs <code>&lt;span style='color:red;'&gt;</code>从环比看，9 个城市新建商品住宅价格下降或持平；5 个城市涨幅在 0.5%以内 (编辑距离为：79)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code>从同比看，15 个城市新建商品住宅价格涨幅均比上月回落，回落幅度在 0.5 至 6.4 个百分点之间 vs <code>&lt;span style='color:red;'&gt;</code></p>
<p>国家统计局当天还发布了 5 月份 70 个大中城市住宅销售价格统计数据 (编辑距离为：44)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code>从环比看，9 个城市新建商品住宅价格下降或持平；5 个城市涨幅在 0.5%以内 vs <code>&lt;span style='color:red;'&gt;</code>刘建伟介绍，5 月份，70 个大中城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有 29 和 18 个 (编辑距离为：38)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code></p>
<p>二、70 个大中城市中一二线城市房价同比涨幅持续回落</p>
<p>5 月份，70 个城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有 29 和 18 个 vs <code>&lt;span style='color:red;'&gt;</code>其中，一二线城市同比涨幅回落尤其明显 (编辑距离为：65)<code>&lt;/p&gt;&lt;p&gt;</code>其中，一二线城市同比涨幅回落尤其明显 vs 据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续 8 个月回落，5 月份比 4 月份分别回落 2.2 和 1.7 个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续 6 个月和 4 个月回落，5 月份比 4 月份分别回落 0.8 和 0.5 个百分点 (编辑距离为：102)<code>&lt;/p&gt;&lt;p&gt;</code>据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续 8 个月回落，5 月份比 4 月份分别回落 2.2 和 1.7 个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续 6 个月和 4 个月回落，5 月份比 4 月份分别回落 0.8 和 0.5 个百分点 vs</p>
<p>此外，70 个大中城市中房价环比下降及涨幅回落城市个数均有所增加 (编辑距离为：106)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code></p>
<p>三、70 个大中城市中房价环比下降及涨幅回落城市个数均有所增加</p>
<p>5 月份，70 个城市中新建商品住宅价格环比下降的城市有 9 个，比上月增加 1 个；涨幅回落的城市有 26 个，比上月增加 3 个 vs <code>&lt;span style='color:red;'&gt;</code>统计显示，5 月份，70 个大中城市中新建商品住宅价格环比下降的城市有 9 个，比上月增加 1 个；涨幅回落的城市有 26 个，比上月增加 3 个 (编辑距离为：40)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code>二手住宅价格环比下降的城市有 7 个，比上月增加 2 个；涨幅回落的城市有 30 个，比上月增加 8 个 vs <code>&lt;span style='color:red;'&gt;</code>二手住宅价格环比下降的城市有 7 个，比上月增加 2 个；涨幅回落的城市有 30 个，比上月增加 8 个 (编辑距离为：0)<code>&lt;/p&gt;&lt;p&gt;``&lt;span style='color:red;'&gt;</code></p>
<p>vs <code>&lt;span style='color:red;'&gt;</code></p>
<p>(编辑距离为：0)<code>&lt;/p&gt;</code></p>
<pre><code class="language-python">import editdistance
from IPython.display import display, HTML

# 示例疑似文章和原文
suspected_article = df.iloc[copy_index].content
original_article = df.iloc[similar2].content

# 分句函数
def split_into_sentences(text):
    return text.split('。')

# 对齐句子
def align_sentences(sentences1, sentences2):
    max_len = max(len(sentences1), len(sentences2))
    sentences1 += [''] * (max_len - len(sentences1))
    sentences2 += [''] * (max_len - len(sentences2))
    return sentences1, sentences2

# 分句
suspected_sentences = split_into_sentences(suspected_article)
original_sentences = split_into_sentences(original_article)

# 对齐句子
aligned_suspected, aligned_original = align_sentences(suspected_sentences, original_sentences)

# 设置编辑距离阈值
threshold = 50

# 创建用于颜色标注的HTML标记
def create_colored_sentence(sentence, color='red'):
    return f&quot;&lt;span style='color:{color};'&gt;{sentence}&lt;/span&gt;&quot;

# 初始化标记后的句子列表
marked_original_sentences = []
marked_suspected_sentences = []

# 逐句比对并在原文和疑似抄袭文章中进行颜色标注
for i, (suspected_sentence, original_sentence) in enumerate(zip(aligned_suspected, aligned_original)):
    distance = editdistance.eval(suspected_sentence, original_sentence)
    if distance &lt;= threshold:
        marked_sentence_original = create_colored_sentence(original_sentences[i])
        marked_sentence_suspected = create_colored_sentence(suspected_sentences[i])
    else:
        marked_sentence_original = original_sentences[i]
        marked_sentence_suspected = suspected_sentences[i]

    marked_original_sentences.append(marked_sentence_original)
    marked_suspected_sentences.append(marked_sentence_suspected)

# 将标记后的句子重新组合成原文和疑似抄袭文章
marked_original_article = '。'.join(marked_original_sentences).strip()
marked_suspected_article = '。'.join(marked_suspected_sentences).strip()

# 显示颜色标注后的原文和疑似抄袭文章
print(&quot;原文：&quot;)
display(HTML(marked_original_article))
print(&quot;\n疑似抄袭文章：&quot;)
display(HTML(marked_suspected_article))
</code></pre>
<pre><code>原文：
</code></pre>
<p><code>&lt;span style='color:red;'&gt;</code>　　国家统计局 19 日发布数据，5 月份，15 个一线和热点二线城市新建商品住宅价格同比涨幅全部回落，其中 9 个城市环比下降或持平。<code>&lt;span style='color:red;'&gt;</code>这 9 个价格环比下降或持平的城市为：北京、上海、南京、杭州、合肥、福州、郑州、深圳、成都。</p>
<p>“5 月份，因地制宜、因城施策的房地产调控政策效果继续显现，15 个一线和热点二线城市房地产市场基本稳定。<code>&lt;span style='color:red;'&gt;</code>”国家统计局城市司高级统计师刘建伟说，从同比看，15 个城市新建商品住宅价格涨幅均比上月回落，回落幅度在 0.5 至 6.4 个百分点之间。从环比看，9 个城市新建商品住宅价格下降或持平；5 个城市涨幅在 0.5%以内。<code>&lt;span style='color:red;'&gt;</code></p>
<p>国家统计局当天还发布了 5 月份 70 个大中城市住宅销售价格统计数据。<code>&lt;span style='color:red;'&gt;</code>刘建伟介绍，5 月份，70 个大中城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有 29 和 18 个。其中，一二线城市同比涨幅回落尤其明显。据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续 8 个月回落，5 月份比 4 月份分别回落 2.2 和 1.7 个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续 6 个月和 4 个月回落，5 月份比 4 月份分别回落 0.8 和 0.5 个百分点。</p>
<p>此外，70 个大中城市中房价环比下降及涨幅回落城市个数均有所增加。<code>&lt;span style='color:red;'&gt;</code>统计显示，5 月份，70 个大中城市中新建商品住宅价格环比下降的城市有 9 个，比上月增加 1 个；涨幅回落的城市有 26 个，比上月增加 3 个。<code>&lt;span style='color:red;'&gt;</code>二手住宅价格环比下降的城市有 7 个，比上月增加 2 个；涨幅回落的城市有 30 个，比上月增加 8 个。<code>&lt;span style='color:red;'&gt;</code></p>
<!-- raw HTML omitted -->
<pre><code>疑似抄袭文章：
</code></pre>
<p><code>&lt;span style='color:red;'&gt;</code>　　中国 5 月份 56 座城市新建商品住宅价格环比上涨，4 月份为 58 座上涨。<code>&lt;span style='color:red;'&gt;</code>5 月份 15 个一线和热点二线城市房地产市场基本稳定，5 月份房地产调控政策效果继续显现。</p>
<p>统计局：15 个一线和热点二线城市房价同比涨幅全部回落</p>
<p>国家统计局城市司高级统计师刘建伟解读 5 月份房价数据</p>
<p>5 月份一二线城市房价平均涨幅继续回落</p>
<p>国家统计局今日发布了 2017 年 5 月份 70 个大中城市住宅销售价格统计数据。<code>&lt;span style='color:red;'&gt;</code>对此，国家统计局城市司高级统计师刘建伟进行了解读。</p>
<p>一、15 个一线和热点二线城市新建商品住宅价格同比涨幅全部回落、9 个城市环比下降或持平</p>
<p>5 月份，因地制宜、因城施策的房地产调控政策效果继续显现，15 个一线和热点二线城市房地产市场基本稳定。<code>&lt;span style='color:red;'&gt;</code>从同比看，15 个城市新建商品住宅价格涨幅均比上月回落，回落幅度在 0.5 至 6.4 个百分点之间。<code>&lt;span style='color:red;'&gt;</code>从环比看，9 个城市新建商品住宅价格下降或持平；5 个城市涨幅在 0.5%以内。</p>
<p>二、70 个大中城市中一二线城市房价同比涨幅持续回落</p>
<p>5 月份，70 个城市中新建商品住宅和二手住宅价格同比涨幅比上月回落的城市分别有 29 和 18 个。其中，一二线城市同比涨幅回落尤其明显。据测算，一线城市新建商品住宅和二手住宅价格同比涨幅均连续 8 个月回落，5 月份比 4 月份分别回落 2.2 和 1.7 个百分点；二线城市新建商品住宅和二手住宅价格同比涨幅分别连续 6 个月和 4 个月回落，5 月份比 4 月份分别回落 0.8 和 0.5 个百分点。<code>&lt;span style='color:red;'&gt;</code></p>
<p>三、70 个大中城市中房价环比下降及涨幅回落城市个数均有所增加</p>
<p>5 月份，70 个城市中新建商品住宅价格环比下降的城市有 9 个，比上月增加 1 个；涨幅回落的城市有 26 个，比上月增加 3 个。<code>&lt;span style='color:red;'&gt;</code>二手住宅价格环比下降的城市有 7 个，比上月增加 2 个；涨幅回落的城市有 30 个，比上月增加 8 个。<code>&lt;span style='color:red;'&gt;</code></p>
<!-- raw HTML omitted -->
<h1>参考文献</h1>
<p>[1] <a href="https://www.cnblogs.com/zhaop8078/p/13676158.html">https://www.cnblogs.com/zhaop8078/p/13676158.html</a></p>
<p>[2] <a href="https://blog.csdn.net/qq_36667170/article/details/121656279">https://blog.csdn.net/qq_36667170/article/details/121656279</a></p>
<h1>附：完整代码</h1>
<pre><code class="language-python">import pickle, os
import jieba  
import pandas as pd
from icecream import ic 
from sklearn.cluster import KMeans 
from collections import defaultdict
from sklearn.preprocessing import Normalizer # 把tfidf归一化为单位向量
from sklearn.naive_bayes import MultinomialNB # 多项式贝叶斯模型
from sklearn.model_selection import train_test_split # 拆分数据集
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 统计词频、计算tfidf
from sklearn.metrics import classification_report # 分类报告 评估模型
from sklearn.metrics.pairwise import cosine_similarity # 计算余弦相似度
import editdistance # 计算编辑距离

with open('dataset/chinese_stopwords.txt','r',encoding='utf-8') as file:
    stopwords = [line.strip() for line in file]

stopwords[:10]

# gb18030编码收录的中文字符更全，对中文文档兼容性更好
df = pd.read_csv('dataset/sqlResult.csv',encoding='gb18030')

df.head(2)

df.info()

# 去除content列存在缺失值的行
df.dropna(subset=['content'],inplace=True)
# 去除
df.dropna(subset=['source'],inplace=True)
df.info()

def split_text(text):
    text = text.replace(' ', '').replace('\n','').replace('\r','')
    text2 = jieba.cut(text) 
    # 去掉停用词
    result = ' '.join([w for w in text2 if w not in stopwords])
    return result

temp = df.iloc[0].content
print('测试数据：',temp)
print('测试分词结果：',split_text(temp))

# 假如路径存在，则直接读取，否则进行分词，并保存到本地
if os.path.exists('dataset/corpus.pkl'):
    with open('dataset/corpus.pkl', 'rb') as file:
        corpus = pickle.load(file)
else:
    corpus = df['content'].map(split_text)
    # 将处理好的分词保存到 corpus.pkl，方便下次调用
    with open('dataset/corpus.pkl', 'wb') as file:
        pickle.dump(corpus, file)


print(corpus.shape)
print(type(corpus[0]))
print(corpus[0])
print(len(set(corpus[0].split())))

df['source'].value_counts().head()

df[df['source'].str.contains('新华')]['source'].value_counts()

label = df['source'].copy()
target = label.str.contains('新华') * 1 # series.str.contains() 返回布尔索引，用*1转为 0 1
target[:5]

corpus

countvectorizer = CountVectorizer(encoding='gb18030',min_df=0.015)

countvector = countvectorizer.fit_transform(corpus) # 学习词频稀疏矩阵
print(countvector.shape)
print(countvector[:1]) # 查看第一个文档的词频向量（只显示非零元素及其索引）


countvector_arr = countvector.toarray() # 转换稀疏矩阵为数组
print(countvector_arr.shape)
countvector_arr

tfidftransformer = TfidfTransformer()
# 拟合后返回tfidf稀疏矩阵
tfidf = tfidftransformer.fit_transform(countvector)
print(tfidf.shape)
print(tfidf[0])


# train_test_split(数据集，标签（source），测试集比例)
x_train,x_test,y_train,y_test = train_test_split(tfidf.toarray(),target,test_size=0.3)
x_train.shape,x_test.shape,y_train.shape,y_test.shape

estimator = MultinomialNB()
estimator

estimator.fit(x_train,y_train)

y_pred = estimator.predict(x_test)
print(classification_report(y_test,y_pred,labels=[0,1],target_names=['others','新华']))


# compare_news_df中，prediction1代表预测文章的风格是新华社风格；labels1说明实际为新华社
prediction = estimator.predict(tfidf.toarray())
compare_news_df = pd.DataFrame({&quot;prediction&quot;:prediction,'labels':target.values})
print(compare_news_df.head(2))

# 在实际非新华社的文章中找出预测为新华社风格的文章
copy_news_index = compare_news_df[(compare_news_df['labels'] == 0) &amp; (compare_news_df['prediction'] == 1)]
print(copy_news_index.head(10))
print(&quot;模型预测结果与实际标签不符（即判定为抄袭嫌疑）的文章数:{}&quot;.format(len(copy_news_index)))


# 实际为新华社和非新华社新闻的index
xinhuashe_news_index = compare_news_df[compare_news_df['labels'] == 1].index
no_xinhuashe_news_index = compare_news_df[compare_news_df['labels'] == 0].index
print(xinhuashe_news_index)
print(no_xinhuashe_news_index)

&quot;&quot;&quot;
sklearn中的k-means算法只支持欧氏距离计算相似度
在文本的相似度比较中我们一般使用余弦距离。

欧氏距离衡量的是空间各点的绝对距离，跟各个点所在的位置坐标直接相关；
而余弦距离衡量的是空间向量的夹角，更加体现在方向上的差异，而不是位置。
&quot;&quot;&quot;

# 对特征向量进行L2范数归一化后，欧氏距离和余弦距离等价，便于进行k-means聚类
transfer = Normalizer()
scaled_array = transfer.fit_transform(tfidf.toarray())


# 使用K-Means进行聚类降维，嫌疑新闻只和相同堆中的新华社新闻进行计算
estimator2 = KMeans(n_clusters=25)
estimator2.fit(scaled_array)
k_labels = estimator2.predict(scaled_array)

k_labels_sr = pd.Series(k_labels)

class_id = defaultdict(set)

for index,value in k_labels_sr.items():
    # 对真实为新华社的新闻index分组
    if index in xinhuashe_news_index:
        class_id[value].add(index)

class_id.keys()


# 假如路径存在，则直接读取，否则进行分词，并保存到本地
import os
if os.path.exists('dataset/label.pkl'):
    with open('dataset/label.pkl', 'rb') as file:
        label = pickle.load(file)
else:
    label = df['content'].map(class_id)
    # 将处理好的分词保存到 label.pkl，方便下次调用
    with open('dataset/label.pkl', 'wb') as file:
        pickle.dump(label, file)

def find_similar_text(copy_index,top=10):
    # 只在新华社发布的文章中查找
    label = k_labels_sr[copy_index]
    dist_dict = {i:cosine_similarity(tfidf[copy_index],tfidf[i]) for i in class_id[label]}
  
    # 从大到小排序
    return sorted(dist_dict.items(),key=lambda x:x[1][0], reverse=True)[:top]


copy_index = 3352

similar_list = find_similar_text(copy_index)

ic(len(similar_list))
similar_list


print('抄袭嫌疑新闻内容:\n',df.iloc[copy_index].content)

# 找一篇相似的新华社原文
similar2 = similar_list[0][0]
print('新华社相似原文:\n',df.iloc[similar2].content)


# 找一篇相似的新华社原文
similar3 = similar_list[1][0]
print('新华社相似原文:\n',df.iloc[similar3].content)

editdistance.eval(df.iloc[copy_index].content, df.iloc[similar2].content)

import editdistance
from IPython.display import display, HTML

# 示例疑似文章和原文
suspected_article = df.iloc[copy_index].content
original_article = df.iloc[similar2].content

# 分句函数
def split_into_sentences(text):
    return text.split('。')

# 对齐句子
def align_sentences(sentences1, sentences2):
    max_len = max(len(sentences1), len(sentences2))
    sentences1 += [''] * (max_len - len(sentences1))
    sentences2 += [''] * (max_len - len(sentences2))
    return sentences1, sentences2

# 分句
suspected_sentences = split_into_sentences(suspected_article)
original_sentences = split_into_sentences(original_article)

# 对齐句子
aligned_suspected, aligned_original = align_sentences(suspected_sentences, original_sentences)

# 设置编辑距离阈值
threshold = 100

# 逐句比对并显示彩色文本
html_output = &quot;&quot;
for suspected_sentence, original_sentence in zip(aligned_suspected, aligned_original):
    distance = editdistance.eval(suspected_sentence, original_sentence)
    if distance &lt;= threshold:
        html_output += f&quot;&lt;p&gt;&lt;span style='color:red;'&gt;{suspected_sentence}&lt;/span&gt; vs &lt;span style='color:red;'&gt;{original_sentence}&lt;/span&gt; (编辑距离为：{distance})&lt;/p&gt;&quot;
    else:
        html_output += f&quot;&lt;p&gt;{suspected_sentence} vs {original_sentence} (编辑距离为：{distance})&lt;/p&gt;&quot;

display(HTML(html_output))

import editdistance
from IPython.display import display, HTML

# 示例疑似文章和原文
suspected_article = df.iloc[copy_index].content
original_article = df.iloc[similar2].content

# 分句函数
def split_into_sentences(text):
    return text.split('。')

# 对齐句子
def align_sentences(sentences1, sentences2):
    max_len = max(len(sentences1), len(sentences2))
    sentences1 += [''] * (max_len - len(sentences1))
    sentences2 += [''] * (max_len - len(sentences2))
    return sentences1, sentences2

# 分句
suspected_sentences = split_into_sentences(suspected_article)
original_sentences = split_into_sentences(original_article)

# 对齐句子
aligned_suspected, aligned_original = align_sentences(suspected_sentences, original_sentences)

# 设置编辑距离阈值
threshold = 50

# 创建用于颜色标注的HTML标记
def create_colored_sentence(sentence, color='red'):
    return f&quot;&lt;span style='color:{color};'&gt;{sentence}&lt;/span&gt;&quot;

# 初始化标记后的句子列表
marked_original_sentences = []
marked_suspected_sentences = []

# 逐句比对并在原文和疑似抄袭文章中进行颜色标注
for i, (suspected_sentence, original_sentence) in enumerate(zip(aligned_suspected, aligned_original)):
    distance = editdistance.eval(suspected_sentence, original_sentence)
    if distance &lt;= threshold:
        marked_sentence_original = create_colored_sentence(original_sentences[i])
        marked_sentence_suspected = create_colored_sentence(suspected_sentences[i])
    else:
        marked_sentence_original = original_sentences[i]
        marked_sentence_suspected = suspected_sentences[i]
  
    marked_original_sentences.append(marked_sentence_original)
    marked_suspected_sentences.append(marked_sentence_suspected)

# 将标记后的句子重新组合成原文和疑似抄袭文章
marked_original_article = '。'.join(marked_original_sentences).strip()
marked_suspected_article = '。'.join(marked_suspected_sentences).strip()

# 显示颜色标注后的原文和疑似抄袭文章
print(&quot;原文：&quot;)
display(HTML(marked_original_article))
print(&quot;\n疑似抄袭文章：&quot;)
display(HTML(marked_suspected_article))
</code></pre>]]></description>
      <author>sherioc</author>
      <guid>article-6</guid>
      <pubDate>Tue, 18 Jun 2024 02:40:50 +0000</pubDate>
    </item>
    <item>
      <title>“陈哥，你说我们抓了这个人，到底对不对?”  &#xA;“怎么了?”  &#xA;……  &#xA;“你...</title>
      <link>http://sherioc.online/thinkings#thinking-2</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/thinkings#thinking-2">http://sherioc.online/thinkings#thinking-2</a></p></blockquote><p>“陈哥，你说我们抓了这个人，到底对不对?”<br>
“怎么了?”<br>
……<br>
“你心里觉得难受了?是因为死的那个病人?”<br>
“嗯，是有点，如果我们晚几天抓他，是不是那条命就不会没了?”<br>
“谁让他做坏事呢?”<br>
“但这也不是杀人放火的事情啊?”<br>
“你别钻牛角尖，不是杀人放火，就不是犯罪了?就不抓了吗?”<br>
“嗯……那这个病人呢?”<br>
“这就是命。”<br>
“嗯。”</p>
<p>——刘喆 《检察官日记》</p>]]></description>
      <author>sherioc</author>
      <guid>thinking-2</guid>
      <pubDate>Tue, 28 May 2024 13:02:05 +0000</pubDate>
    </item>
    <item>
      <title>支付宝沙箱流程</title>
      <link>http://sherioc.online/posts/zhibubaoshaxiangliuchen</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/zhibubaoshaxiangliuchen">http://sherioc.online/posts/zhibubaoshaxiangliuchen</a></p></blockquote><blockquote>
<p>引子：软件杯智能编辑器添加支付宝付费功能</p>
</blockquote>
<h2>fastapi支付宝沙箱</h2>
<p>.env环境变量</p>
<p><img src="/uploads/pictures/2026-03-16-15:01:32-b0.png" alt="image.png"></p>
<p>数据库
<img src="/uploads/pictures/2026-03-16-15:01:40-a6.png" alt="image.png"></p>
<p>接口
<img src="/uploads/pictures/2026-03-16-15:01:54-b6.png" alt="image.png"></p>
<blockquote>
<p>按照sql补充recharge数据库表，下载支付宝沙箱手机应用app，然后填我的账号就行（或者你自己的需要改环境变量，见下面的详细介绍）</p>
<p>post请求携带充值金额，后端返回url前端进行回调到达扫码页面：
<img src="/uploads/pictures/2026-03-16-15:02:01-68.png" alt="image.png"></p>
</blockquote>
<h2>支付宝沙箱</h2>
<h3>支付页面流程</h3>
<p>1、进入<a href="https://open.alipay.com/">支付宝开放平台 (alipay.com)</a>
<img src="/uploads/pictures/2026-03-16-15:02:15-be.png" alt="image.png"></p>
<p>开发接入——网页/移动应用开发</p>
<p>2、开发文档进入支付流程</p>
<p><img src="/uploads/pictures/2026-03-16-15:02:29-43.png" alt="image.png">
<img src="/uploads/pictures/2026-03-16-15:02:36-71.png" alt="image.png"></p>
<p>3、进入alipay.trade.page.pay（单独打开该页面）
<img src="/uploads/pictures/2026-03-16-15:02:46-f2.png" alt="image.png">
进入pypi项目依赖</p>
<p><img src="/uploads/pictures/2026-03-16-15:03:15-1b.png" alt="image.png"></p>
<p>安装sdk并看example</p>
<p><img src="/uploads/pictures/2026-03-16-15:03:23-b6.png" alt="image.png"></p>
<p>4、支付宝配置
<img src="/uploads/pictures/2026-03-16-15:03:30-53.png" alt="image.png">
alipay.trade.page.pay接口
<img src="/uploads/pictures/2026-03-16-15:03:50-dc.png" alt="image.png"></p>
<h3>环境变量配置</h3>
<p>沙箱应用中配置环境变量(.env文件)【回调url和异步通知url跑不通，不用配置】
<img src="/uploads/pictures/2026-03-16-15:04:01-f9.png" alt="image.png">
<img src="/uploads/pictures/2026-03-16-15:04:35-7c.png" alt="image.png"></p>
<p>下载手机支付宝（沙箱测试版，并使用沙箱账号密码登录）
<img src="/uploads/pictures/2026-03-16-15:05:17-9d.png" alt="image.png"></p>
<h3>代码</h3>
<p>发起支付接口实现
<img src="/uploads/pictures/2026-03-16-15:05:33-f1.png" alt="image.png"></p>
<p>前端请求支付宝支付接口
<img src="/uploads/pictures/2026-03-16-15:05:40-05.png" alt="image.png">
后端返回拉起支付页面url
<img src="/uploads/pictures/2026-03-16-15:05:50-89.png" alt="image.png">
前端进行继续访问跳转到支付页面</p>
<p><img src="/uploads/pictures/2026-03-16-15:05:59-a8.png" alt="image.png"></p>
<p>用户使用支付宝沙箱程序扫码支付，完成付款
<img src="/uploads/pictures/2026-03-16-15:06:10-c7.png" alt="image.png"></p>
<p>【后面还需要异步验签/商家主动验签订单，再进行数据库操作】</p>]]></description>
      <author>sherioc</author>
      <guid>article-1</guid>
      <pubDate>Sat, 30 Mar 2024 11:07:38 +0000</pubDate>
    </item>
    <item>
      <title>AJAX、XHR、Axios、Fetch API</title>
      <link>http://sherioc.online/posts/ajaxxhraxiosfetchapi</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/posts/ajaxxhraxiosfetchapi">http://sherioc.online/posts/ajaxxhraxiosfetchapi</a></p></blockquote><blockquote>
<p>摘要：</p>
<ul>
<li><strong>AJAX</strong> 是一种==技术概念，用于实现网页的异步交互==。<strong>XHR</strong> 是==实现== AJAX 功能的具体==工具==之一。</li>
<li><strong>Axios</strong>库是对XHR的封装，<strong>Fetch API</strong> 是 XHR 的现代替代方案。</li>
</ul>
</blockquote>
<p>AJAX（Asynchronous JavaScript and XML）和 XHR（XMLHttpRequest）之间有着紧密的关系，但它们并不是完全相同的概念。以下是它们之间的关系和区别：</p>
<ul>
<li>
<p><strong>AJAX</strong>：</p>
<ul>
<li><strong>全称</strong>：Asynchronous JavaScript and XML（异步 JavaScript 和 XML）。</li>
<li><strong>定义</strong>：AJAX 是一种用于创建动态网页的技术，允许网页在不重新加载整个页面的情况下，与服务器进行异步交互，从而更新部分页面内容。</li>
<li><strong>核心思想</strong>：通过 JavaScript 在后台与服务器进行数据交换，而不需要重新加载整个页面。</li>
</ul>
</li>
<li>
<p><strong>XHR</strong>：</p>
<ul>
<li><strong>全称</strong>：XMLHttpRequest。</li>
<li><strong>定义</strong>：XHR 是一个 JavaScript 对象，用于与服务器进行异步通信。它是实现 AJAX 功能的核心工具之一。</li>
<li><strong>用途</strong>：通过 XHR，JavaScript 可以在后台向服务器发送请求并接收响应，而不会影响页面的显示。</li>
</ul>
</li>
<li>
<p><strong>XHR 是实现 AJAX 的核心工具</strong>：</p>
<ul>
<li>==AJAX 是一种<!-- raw HTML omitted -->技术概念<!-- raw HTML omitted -->，而 XHR 是实现这种技术的具体工具之一==。</li>
<li>通过 XHR，可以实现 AJAX 的异步交互功能。</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">// 创建一个 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();

// 配置请求类型、URL 以及是否异步处理
xhr.open('GET', 'https://api.example.com/data', true);

// 设置请求完成的处理函数
xhr.onload = function () {
  if (xhr.status &gt;= 200 &amp;&amp; xhr.status &lt; 300) {
    // 请求成功，处理返回的数据
    const data = JSON.parse(xhr.responseText);
    console.log(data);
  } else {
    // 请求失败
    console.error('Request failed with status:', xhr.status);
  }
};

// 设置请求失败的处理函数
xhr.onerror = function () {
  console.error('Request failed');
};

// 发送请求
xhr.send();
</code></pre>
<h3><strong>现代替代方案</strong></h3>
<ul>
<li><strong><code>axios</code></strong>：
<ul>
<li>基于 <code>XMLHttpRequest</code>。</li>
<li>提供了丰富的功能，如拦截器、超时处理、自动 JSON 解析等。</li>
<li>是一个==第三方库==，需要单独引入。</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">axios.get('https://api.example.com/data')
  .then(response =&gt; console.log(response.data))
  .catch(error =&gt; console.error(error));
</code></pre>
<ul>
<li><strong><code>fetch</code></strong>：
<ul>
<li>是浏览器的原生 API，不是基于 <code>XMLHttpRequest</code>。</li>
<li>提供了简洁的 API，支持现代的异步编程模式。</li>
<li>不需要额外引入库，但功能相对简单。</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">fetch('https://api.example.com/data')
  .then(response =&gt; response.json())
  .then(data =&gt; console.log(data))
  .catch(error =&gt; console.error(error));
</code></pre>]]></description>
      <author>sherioc</author>
      <guid>article-2</guid>
      <pubDate>Fri, 15 Mar 2024 13:46:42 +0000</pubDate>
    </item>
    <item>
      <title>北巷回忆</title>
      <link>http://sherioc.online/moments/2023/08/19/bei-xiang-hui-yi</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/moments/2023/08/19/bei-xiang-hui-yi">http://sherioc.online/moments/2023/08/19/bei-xiang-hui-yi</a></p></blockquote><h2>卷一 大河浦里</h2>
<h3>第一章 社庙</h3>
<p>记不清，不记得。</p>
<p>山头头上有个什么庙。</p>
<p>不知道什么日子，全村老少男女都要上去。供香火，放炮，给佛像磕头。</p>
<p>大河浦的河，从村里唯一的小卖铺旁边那条山路流出来。</p>
<p>流向哪里，不知道。</p>
<p>河上四五米处跨着桥。桥就是路。</p>
<p>两侧没小腿高的铁栏杆。</p>
<p>老汉们坐在栏杆上，抽着烟。</p>
<p>桥这边是斜坡，上头长满了树，高耸入天。</p>
<p>下头是数不清的大石头，像迷宫。</p>
<p>孩子们几个在石头上耍。</p>
<p>老奶们倚靠在石头上，穿的鲜艳的衣服。手里拿着篮子。还有撑着拐棍子。</p>
<p>斜坡是个山坡坡。也是靠近河这一侧，上庙的路。</p>
<p>太阳出来，快晌午了。</p>
<p>扛着东西和炮的，叫鬃鬃。村里的哑巴。胡子总是刮不净。一脸胡茬。</p>
<p>“……叫那鬃鬃扛上……”</p>
<p>一担子东西摞上去，像往驴身上摞。</p>
<p>“摁~……“，鬃鬃从喉咙里冒出哼哼声。像牛叫。东西已经扛上去了。</p>
<p>”赶紧上搁哇！“老奶们朝鬃鬃叫着。</p>
<p>”摁~……“，脸上露出笑，眼里明溜溜的。使劲扛起东西来，沿着山坡往上爬。</p>
<p>哼哧哼哧…哼…哼哧…不时发出那牛一样的叫声。</p>
<p>……</p>
<p>弯弯曲曲的土路，上来再往下看，大河浦、小卖铺、水房、小观音庙、大表姑家、奶奶家、右面的山。</p>
<p>一大片蓝天。</p>
<p>还得再往上走。沿着坡坡，躲开土壕疙瘩。</p>
<p>庙像个四合院。外头能看见里面那棵大树。</p>
<p>庙门开着，能望见里头的佛像。</p>
<p>“放下哇……”</p>
<p>鬃鬃把扛着的东西放下，喘着粗气，哼哼着。牛叫声。</p>
<p>“嗯~……”比划着手脚，脸上是笑的，不停点着头。</p>
<p>“去歇咯哇……”</p>
<p>鬃鬃又比划着手脚，往下走。山坡坡起伏，他那身体一上一下。</p>
<p>庙门前有个鼎，里头是沙子。</p>
<p>上头插着细香，黄的刚点上，红的剩下半截。</p>
<p>还有粗棒香，一只手也握不住。三五根插在沙子里头，烧的高高低低。</p>
<p>怕这口鼎，怕这种粗香。</p>
<p>奶奶们说那和尚，教剃了头发，就拿这粗棒子香，往头上点。</p>
<p>横三个，竖着点三排。</p>
<p>穿上那布衣裳，就再也不长头发了。</p>
<p>……</p>
<p>往里头走，不进去，往右面拐就看见那个树了。</p>
<p>这是庙里头的树，高的看不见顶子，整个树好像都是香火的味道。</p>
<p>下头分叉，有人能躺上去睡。</p>
<p>不会爬树，上不去。</p>
<p>往里面进就是内院。</p>
<p>外头能看见半个佛头。</p>
<p>叫大人引进来，佛像面前有三个桌子，上头开了的罐头、饼子、苹果、橘子梨子、饼干、干馍馍。</p>
<p>桌上打火机。盒子里有香。</p>
<p>中间是佛像，左面观音、右面文殊。</p>
<p>地下是黄垫子。圆的。中间的高，两边低。</p>
<p>从篮子里掏出香，点上，拿三根。</p>
<p>拜三下，上香。插进小香灶。里头装的是小米。</p>
<p>“磕头……”</p>
<p>大人跪下了，赶紧跪在黄垫子上。</p>
<p>双手合十。朝佛，磕头。</p>
<p>一拜。二拜。三拜。</p>
<p>大人嘴里念叨着。</p>
<p>……</p>
<p>出来那口鼎上的粗棒香还在烧。高高低低。</p>
<p>香烧完的灰落在沙子上。</p>
<p>外头地上是大拇炮放完的皮。半截纸筒子。</p>
<p>远处是天。人家。</p>
<p>庙旁边。树，地下长满杂草。狗尾巴草，绿叶子草。蒲公英。像蒲公英的东西，只不过吹不动。</p>
<p>……</p>
<p>树上有人躺着，好像睡着了。</p>
<p>太阳从树叶子缝缝里流出来。地下一堆圆点点。</p>
<p>……</p>
<p>庙后面是什么。</p>
<p>不知道。</p>
<p>什么时候结束。供奉的啥。</p>
<p>不知道。</p>
<p>……</p>
<p>不知道。</p>
<p>……</p>
<h3>第二章 镰豆、马圈和后山</h3>
<p>从大河浦上一直往上走。</p>
<p>最上头那户，奶奶家。</p>
<p>木头门。锈了的锁子，挂着一根红绳子。左手边。土坷垃房沿下放着钥匙。</p>
<p>咯吱咯吱……吱吱…石头疙瘩抵住门。</p>
<p>左边菜院子。踏石头上去。</p>
<p>左半。白菜。茴子白、油菜、生菜。土壕壕。</p>
<p>围栏。树叶子。</p>
<p>右半。几棵杏儿树。不好，好的在后山。</p>
<p>出来。</p>
<p>左边水缸子。叫不上缸子。挖机的前面那东西倒过来，里头黑黑的水。</p>
<p>后山再往里头走。</p>
<p>前头一条窄路。右面一棵树。猫会上去。</p>
<p>左前方旧房子。荒废的。土坷垃堆起来的，房顶上全是草。</p>
<p>几步台阶。</p>
<p>“汪，汪汪！……”</p>
<p>一条黄色窜出来，扑上来。</p>
<p>两条腿一下子就从衣服上窜到肩膀上了。伸着舌头。摇着尾巴。“……汪汪……”</p>
<p>黄黄。</p>
<p>一下子就认出人来了。</p>
<p>还有条白的。叫白白。</p>
<p>白白哪去了。</p>
<p>被卖了。村里来了买狗的。100块。</p>
<p>“起来…”奶奶叫喊着，揪过黄黄。</p>
<p>“回来了……”</p>
<p>……</p>
<p>院子右面。</p>
<p>围栏。柿子。白的。绿的。半红的。黄瓜。</p>
<p>左面。</p>
<p>两间偏房。左侧的没东西。饼干、方便面、大拇炮在右侧。</p>
<p>前头是两间正房。坐北朝南。</p>
<p>台阶下种的菊花。黄的。粉的。</p>
<p>后头。</p>
<p>围栏。黄瓜。有一根最长的。</p>
<p>……</p>
<p>镰豆。厚厚的铺满一地的镰豆。晒干了的豆荚。黑红的，黑白的。</p>
<p>“……去打镰豆咯哇……”</p>
<p>扁担的杆子。一侧穿了孔，上的钉子，吊着一根短一点的棍子。</p>
<p>干镰踩上去噼里啪啦。噼里啪啦的。</p>
<p>捉着杆子甩起来，上头的棍子跟着转。</p>
<p>狠狠地砸到地上。</p>
<p>啪……啪……啪……</p>
<p>打累了，丢了杆子。</p>
<p>在铺满的镰豆荚上踩来踩去，也能踩出豆子。</p>
<p>啪……啪……啪……</p>
<p>豆子红的。白的。青的。豆子很硬，踩不烂。</p>
<p>黄黄听见，也过来踩。</p>
<p>噼里啪啦……啪……啪……</p>
<p>……</p>
<p>院子里的大杏树，背后就是后山。</p>
<p>水库后面是马圈。没马了。里面还有干草，成了鸡圈了。</p>
<p>一只母鸡。喂一两颗米。鸡窝不像样。</p>
<p>“……母鸡把鸡蛋吃了……”</p>
<p>“……鸡妈妈饿的……把娃娃也给吃了……”</p>
<p>捡出一个鸡蛋。</p>
<p>很漂亮。上面挂着黑乎乎的泥土。</p>
<p>阳光下看不清里面有没有蛋黄。</p>
<p>放到狗窝的棉被上面。想孵小鸡。</p>
<p>……</p>
<p>孵不出来。</p>
<p>鸡蛋哪去了。</p>
<p>不知道。</p>
<p>……</p>
<p>蒸鸡蛋好吃。鸡蛋打进去。用筷子搅和散，放上盐、</p>
<p>花椒还是茴香。</p>
<p>不知道，黑的面面，不是红的那个。</p>
<p>扳水龙头，就上一碗水，搅和搅和。</p>
<p>灶里永远有火。</p>
<p>座锅。</p>
<p>蒸。</p>
<p>碗里的糊糊变色，变黑，变得坑坑洼洼，密密麻麻的小洞洞。</p>
<p>疏散了。孔变大了。半碗鸡蛋变成一碗蛋羹了。</p>
<p>……</p>
<p>扳开铁门，就进来后山了。</p>
<p>左面是两棵杏树，矮的能上去。</p>
<p>那棵在山坡上头。</p>
<p>山坡不好走。只有一条小路往上爬。</p>
<p>半山腰有杏树。</p>
<p>干的，不大。</p>
<p>大老老悉心照顾着的。</p>
<p>再往上还能进去，里面连着大山。看不到另一头。</p>
<p>山最里头好像有水，好像有。一堆树。</p>
<p>上头有大棚，蓝色的。山腰上阳光足。种菜好。</p>
<p>除了踩出来的小路，旁边都是杂草。有深不见底的洞。</p>
<p>山能往里进去，里面有些什么东西。</p>
<p>记不得了。</p>
<p>……</p>
<h3>第三章 过年</h3>
<p>“小孩小孩你别馋，过了腊八就是年……”</p>
<p>腊八不在这里过。</p>
<p>年在村子里过。</p>
<p>什么都不用管，大人们就买来了花炮、糖豆、零食和准备好的压岁钱。</p>
<p>花炮什么样式的都有。大地开花、点着了闪着电光的电光棒、鞭炮、各式各样的小筒子炮、好几板子甩炮、黑老大、七匹狼……</p>
<p>糖豆和零食应有尽有。扁核桃、隔着袋子都能闻到酒味的酒心巧克力、玉米糖、瑞士糖、酥糖、黄纸包的高粱饴、不好吃的红红绿绿的果冻一样的糖、话梅糖、还有炭烧的薄饼、里面夹着软糖软糖一样的饼（茯苓饼）、苏打饼干、红枣膜片、上面裹着白芝麻的酥球……</p>
<p>不知道什么时候贴对子。</p>
<p>大铁锅里头熬的白糊糊，又稠又粘。</p>
<p>那是糨糊。</p>
<p>奶奶手里拿的搅和的那个锅刷子。</p>
<p>两只手抱不住，一大把竹篾靠近顶部箍着铁圈，底下早就被磨成一边斜的。</p>
<p>锅刷子在糨糊里搅来搅去，一头粘满了白糊糊。流下来，流进锅里。</p>
<p>白乎乎的，咕噜……咕噜……地冒着大泡泡。</p>
<p>……</p>
<p>不知道什么时候晾凉了，也不知道粘稠的糊糊往碗里头倒时候有没有拉丝。</p>
<p>对子听说是村里老人写的，用毛笔写的。</p>
<p>红纸摸起来沙沙的。</p>
<p>比那有刺的白纸好摸。</p>
<p>五六幅对子，要贴在木头大门上、两件偏房上、两件正房上、马圈那间房上。</p>
<p>门都是木头做的。</p>
<p>不用那个锅刷子。</p>
<p>用刷油的刷子，扁扁的，黑乎乎的把子，前头整整齐齐的刷毛。</p>
<p>蘸上糨糊，往撕了旧对子的门两侧上面刷。</p>
<p>一层……两层……</p>
<p>捏住对子上面，对正了。按上去，两只手顺着往下捋。</p>
<p>“贴好了……”</p>
<p>上联，下联，横批。</p>
<p>……</p>
<p>糨糊不多不少。正好贴完最后一幅对子。</p>
<p>窗花。</p>
<p>红纸，折。折。剪几个窟窿。几道弯弯。展开。</p>
<p>年年有余、数不清多少瓣的花……</p>
<p>窗户。早就擦的明亮亮的了。</p>
<p>倒过来的福字。</p>
<p>……</p>
<p>耍完回来，大人们已经搭好旺火了。</p>
<p>黑的发亮的碳，大块大块的。</p>
<p>一圈又一圈堆起来。</p>
<p>堆的比人高。</p>
<p>旺火顶上放个三尖尖碳。</p>
<p>中间偏上两块碳之间压着一张黄纸。</p>
<p>写的什么。</p>
<p>不知道。</p>
<p>有没有写东西。</p>
<p>不知道。</p>
<p>……</p>
<p>天黑了。年开始过了。</p>
<p>旺火点起来，火苗子从碳之间的缝隙里头窜出来。红的，黄的。忽上忽下，越烧越旺。</p>
<p>正房、偏房的门。都敞开着，灯火都点着。</p>
<p>……</p>
<p>到了什么时候。</p>
<p>接财神。</p>
<p>大门口挂的鞭炮，从门上耷拉到地下。引子在底下。引子很短，只有一小截。</p>
<p>不用香点。拿打火机。</p>
<p>点。</p>
<p>没点着。</p>
<p>点，“噼里啪啦……噼里啪啦……”拿起鞭炮从大门口跑进来。</p>
<p>炸不到手。</p>
<p>财神迎接进来了。</p>
<p>旺火烧着，轰轰地烧。</p>
<p>家里灯点着。黄的灯，白的灯，全亮着。</p>
<p>给土地爷爷上香。</p>
<p>给观音菩萨上香。</p>
<p>苹果、橘子罐头摆上。</p>
<p>……</p>
<p>电视机开着。</p>
<p>大圆桌子。黑红的，圆的，果盘子。里面像切月饼一样切开，分开装着瓜子、花生、糖、果干、核桃和大人们买回来的稀罕吃的。</p>
<p>……</p>
<p>大砂锅端到桌子最中间。底下铺的土豆、豆腐。中间放的白菜。上头铺的白肉片子。大片大片的白肉片子。</p>
<p>一桌子的菜、肉。</p>
<p>碟子里的花生米。金黄金黄的。</p>
<p>白酒。老白干、还有长方形的浅盖盖的白酒、红盒盒里头的红盖子汾酒。</p>
<p>饮料。沙棘汁。装油桶子那么大的，满满一桶。雪碧、橙汁。全是好喝的。</p>
<p>新咯锃锃的玻璃杯，沙棘汁倒上满满一大杯。</p>
<p>咕噜……咕噜。</p>
<p>大人们吵杂的，不停地说的什么。</p>
<p>笑声。叫喊声。做饭声。</p>
<p>……</p>
<p>吃一两口出来。</p>
<p>红塑料袋。掏出炮。</p>
<p>在大人裤道擦（裤兜）里头摸打火机。</p>
<p>叫喝一小盖盖白酒，倒进瓶盖里头。</p>
<p>舔了一点。辣。</p>
<p>没打火机。</p>
<p>旺火烧着。圪啾（蹲）下点香。</p>
<p>大地开花。半指头那么长。引子一点，嗖的一下在地上窜起来。红的、黄的、蓝的在地上窜，撞来撞去。绕了几圈，不转了。</p>
<p>电光棒棒。一根铁丝上灰色的东西面面裹起来。一点，闪着黄色的星星。</p>
<p>甩炮，小花炮。噼里啪啦，噼啪。</p>
<p>……</p>
<p>饺子端出来。</p>
<p>好几轮。</p>
<p>每轮里头有钢镚儿。</p>
<p>一块的、五毛的、一毛的。</p>
<p>筷子一夹，大概就清楚有没有了。</p>
<p>咬到一口硬。</p>
<p>“哎呀……咬住钢蹦子了！……”</p>
<p>……</p>
<p>压岁钱。</p>
<p>压在枕头下。</p>
<p>过了十二点。</p>
<p>挤在炕头上。炕上、地下。一地的瓜子皮、花生皮。</p>
<p>……</p>
<p>”……爷爷背上你睡咯哇……“</p>
<p>背起来。头挡住灯泡子，落下一个半影子。</p>
<p>正房的另一间。</p>
<p>罗马珠珠在柜子上爬。</p>
<p>观音前面的香烧了一半。</p>
<p>……</p>
<h3>第四章 野、坟</h3>
<p>天永远是蓝的。上面飘着几片白云。</p>
<p>从被鹅咬的那个巷子进去，不多远就见一条小溪。</p>
<p>从石头上流下来，石头是青色的。</p>
<p>手放在高低不齐的两块石头中间，一会儿就能捞到小鱼儿。</p>
<p>抬头。树叶遮盖了天空。</p>
<p>水哗啦哗啦流着。</p>
<p>空气是潮湿的，像刚下过雨一样。</p>
<p>树很高，比其他地方都高。又细又高。</p>
<p>时不时有鸟叫声。</p>
<p>这里最清净。</p>
<p>沿着小溪往上走，是进山的路。</p>
<p>沿着小溪往下，就到了大河浦。</p>
<p>水从哪里出来。</p>
<p>不知道。</p>
<p>过了大河浦水流向哪。</p>
<p>不清楚。</p>
<p>水隔开了里外。</p>
<p>踩着石头跨过水，便进山了。</p>
<p>山下永远是潮湿的。阴凉阴凉的。</p>
<p>这座山不高。但是大。望不见尽头的大。</p>
<p>山上平地多，上山得爬。</p>
<p>两个人高的断层。弯弯曲曲一条土道道。</p>
<p>不知道哪只大脚踩出来的坑，便成了落脚的地方。</p>
<p>山上有田地，种着土豆。有没有红薯。不知道。</p>
<p>山是好几座。</p>
<p>有的连着。能过去。</p>
<p>有的只能望向对面，从这座山越走越下。突然就是一堆杂草乱树和灌木。然后就是陡坡。</p>
<p>有没有人从坡滑下去。</p>
<p>不知道。</p>
<p>坡边边上黄红黄红的，长满刺的矮树。</p>
<p>叫醋溜溜，也叫沙棘。</p>
<p>使劲撇下几只来。不小心被刺划破了胳膊。</p>
<p>腿上、鞋上早已粘满了绿绿的小圆球球，上头的小钩子牢牢地抓着。</p>
<p>把醋溜溜枝子撕开，撕好的一小条条枝枝上，密密麻麻的黄红的小球球。</p>
<p>不用洗。不用擦。</p>
<p>囫囵放进嘴里，使劲地嗦。</p>
<p>酸甜酸甜的。</p>
<p>大枝子上有刺，撇下小条条，没啥刺。</p>
<p>酸甜酸甜的。</p>
<p>……</p>
<p>地里种的东西，白萝卜。水萝卜。土豆。都是绿叶子。</p>
<p>浇地的水从哪来。不知道。</p>
<p>戴着草帽子的老奶们，胳膊挽着篮子。</p>
<p>里头放的什么。不知道。</p>
<p>谁家的地。有没有边界。</p>
<p>不知道。</p>
<p>……</p>
<p>“挖山ye咯哇……”</p>
<p>扛起锄头。一人长的杆子。</p>
<p>还是这片地。</p>
<p>抡起来。朝着那叶子方向。挥下去。</p>
<p>清脆的声音。</p>
<p>锄子提出来。锄头带着半个白色的。</p>
<p>一个。两个。</p>
<p>不全是好的。也有出来就是朽的。和锄烂的一起扔掉。</p>
<p>半麻袋。混着土坷拉。</p>
<p>……</p>
<p>什么时候的碳火。</p>
<p>不知道。</p>
<p>烧着了又灭了的。</p>
<p>里头还是滚烫的。</p>
<p>拿树枝子搁搅，翻开里头。黑。红。白。热的。</p>
<p>土豆就在里头埋着。</p>
<p>烤出来就是黑的。</p>
<p>拿根树枝扒拉出来一个。烫手。石头上擦擦。</p>
<p>钢丝圈。擦。擦擦。</p>
<p>外面的皮黄黑黄黑的。焦了的皮。</p>
<p>小的直接啃。</p>
<p>大的两只手倒着掰开。</p>
<p>白。绵。冒着热气。</p>
<p>篮子里有个塑料袋。里头装着面面。</p>
<p>不是孜然调料。</p>
<p>专门蘸山ye的，黑黄黑黄的。面粉一样细。</p>
<p>咬一口，蘸满面面。</p>
<p>一口。又一口。</p>
<p>……</p>
<p>碳火慢慢就熄了。脚上去抹几下。</p>
<p>山还是原来那样。</p>
<p>……</p>
<p>过了大河浦的桥，走上几百米。前面那座山。</p>
<p>庄稼。种的什么。不知道。</p>
<p>沿着山往上走。</p>
<p>弯弯曲曲。拐东拐西。</p>
<p>山很大。很高。</p>
<p>山腰坡上没什么树。</p>
<p>起起伏伏的一些鼓包。</p>
<p>坟。</p>
<p>……</p>
<p>”来，磕头……“</p>
<p>大人先跪下。</p>
<p>坟头在斜坡上。</p>
<p>隆起的土堆。前面有块立着的石头。前面还有块长方形的石头。扁扁的，一半嵌在土里。</p>
<p>磕完头。大人往那块长方形石头上摆东西。拧开的罐头、一个苹果。橘子剥去了皮。</p>
<p>怀里掏出一个酒樽。</p>
<p>食指和中指伸进去。绕着酒樽使劲擦两圈。</p>
<p>摆在坟头前。</p>
<p>白酒。</p>
<p>……最后一杯。洒在石头上。</p>
<p>纸钱。</p>
<p>白的。黄的。花花绿绿的纸衣服。</p>
<p>火一直烧到了指尖。灰白的纸烬。</p>
<p>坟头边上有树。从陡坡侧面长出来。</p>
<p>杨树还是柳树。不记得。</p>
<p>只记得有说法。</p>
<p>……</p>
<p>地是荒的。没有杂草的荒。</p>
<p>地上是苔藓还是什么。</p>
<p>不知道。</p>
<p>灰绿灰绿色的。摸起来滑滑的。抠不起来。</p>
<p>远远地挖了一个小坑。</p>
<p>一个大拇炮。两响。</p>
<p>“走了！”……</p>
<p>山谷里。高高低低的杂草。</p>
<p>……</p>
<h2>卷二 东寨镇上</h2>
<h3>第五章 小镇</h3>
<p>东寨镇是一条。</p>
<p>一长条。</p>
<p>大河浦在村沟沟里。</p>
<p>三轮轮车。一根弯的铁棍子往车头侧面插进去。摇…摇…摇……</p>
<p>突。突突。突突突突突……</p>
<p>往车后面的卡子里头一坐。</p>
<p>大人有直接坐的。有的屁股底下垫着麻袋，里头装着东西红薯、土豆。坐不下的就坐在卡子上，半个屁股露在空中。</p>
<p>大都是两个胳膊张开。扶着车边。</p>
<p>一颠一颠的。车拐弯能把我甩出去。大人们屁股牢牢地粘在车上。</p>
<p>呼呼的风声。大人们的谈笑声。</p>
<p>村子出来，沿着马路颠上几百米，就到了镇上了。</p>
<p>拐个弯。不远处有桥。</p>
<p>过了桥。</p>
<p>要么左拐。要么继续往前走。</p>
<p>左拐。去往旅游处。芦芽山、万年冰洞、情人谷。都在那一块。</p>
<p>往前走。一条。</p>
<p>豆腐坊、月饼坊、镇上的中医……</p>
<p>沿着这一条一直走。就去了城里了。</p>
<p>……</p>
<p>镇子上有豆腐作坊。</p>
<p>两间小屋子。窗户。白纸糊的。陈旧的玻璃片子。</p>
<p>进来有个高高的架子。</p>
<p>大的一块纱布。吊起来。里面是豆浆。</p>
<p>布子吊成了倒锥形。底下的尖尖一点一点往外渗透。</p>
<p>纱布和笼厨下头垫的布子一个样。</p>
<p>下面有大锅。里面熬的什么。</p>
<p>好像是豆浆。</p>
<p>纱布里头的豆浆，最后怎么做成豆腐的。</p>
<p>不知道。</p>
<p>只听说什么卤水。</p>
<p>点豆腐。</p>
<p>里屋有黑色的大缸子。比奶奶家的大缸子还大。只不过底下没有黄的、白的钢镚儿。</p>
<p>豆腐工工整整地码在缸子里。外面是细密的纱布印子。</p>
<p>也有切开的。切开的没有印子，白的。嫩的。</p>
<p>……</p>
<p>镇子上还有打月饼的。也做麻花。饼子。</p>
<p>大铁皮桌子。光亮光亮的。</p>
<p>上面摆些什么。不记得。</p>
<p>只记得，比和好的糕面的颜色浅的一大团面团放在桌子上。</p>
<p>地下大袋子的五仁馅、什么馅儿。</p>
<p>桌子上放着几个铁家伙。连着管子。</p>
<p>揪好的面团包进去馅子。往那模具里头一放。</p>
<p>呲……地挤出来。</p>
<p>上面已经有那月饼的花花了。</p>
<p>几十个月饼整整齐齐地码在长方形的铁盘子里。</p>
<p>身后就是大烤箱。透过玻璃窗子能看见里面烤香肠机子一样的铁柱子，一排排。好几层。</p>
<p>月饼放进去，拧上火。</p>
<p>烤多长时间。不知道。</p>
<p>烤出来金黄金黄的。</p>
<p>掰开一半。五仁馅露出来。掉到地上一块。</p>
<p>烫手烫手的。才好吃。</p>
<p>……</p>
<p>镇子另一头边边上。</p>
<p>是那家中医。</p>
<p>村子镇子里头得大病的人来看。</p>
<p>城里头得了怪病治不好的人来看。</p>
<p>是个院子。</p>
<p>墙角有煤炭。堆成小山的碳。黑亮黑亮的。</p>
<p>墙边边上南瓜。绿皮的、黄皮的老南瓜。</p>
<p>泡沫箱子里头种的几根黄瓜、西红柿。</p>
<p>房子外头木头桌子上。一个小黑板靠在墙上。</p>
<p>用白粉笔写的几行字：“……星期三休息……”</p>
<p>从来没擦过。</p>
<p>一直就是那样。</p>
<p>等候室永远都是满人的。</p>
<p>里屋坐着那位神医。不停给病人看病、把脉……</p>
<p>外屋比里屋黑。</p>
<p>四面墙上。</p>
<p>挂满了红的、黄的锦旗。</p>
<p>一层叠一层。靠近房顶的旗子落满了灰。</p>
<p>看过几回病。</p>
<p>不记得。</p>
<p>姐姐看过一次。十根指头上扎的针。</p>
<p>我腿弯上的硬疙瘩，去城里说要动手术。后来到这里，说把仙人掌切开取出肉，就那样敷上去。</p>
<p>后来再也没起来。</p>
<p>……</p>
<p>与病有关的。</p>
<p>是听奶奶说以前我被村子里狗咬了，连夜跑遍全村借的二百块钱。</p>
<p>去城里打的狂犬。</p>
<p>记不得。</p>
<p>只记得被鹅咬过。每次路过那看起来快要塌下来的土坷垃房子，都得躲在大人后面。</p>
<p>不是怕房塌。是怕这儿的鹅。</p>
<p>……</p>
<h3>第六章 向日葵、烟囱、井</h3>
<p>向日葵。</p>
<p>记不清在哪里了。</p>
<p>种一院子的向日葵。几十个头从白天到黑夜跟着太阳转过去。</p>
<p>是不是每天都是这样。不知道。</p>
<p>晚上偷偷地转回来迎接明天的太阳吗。</p>
<p>或许是这样吧。</p>
<p>……</p>
<p>不知道什么时候。</p>
<p>要收瓜子了。</p>
<p>原来白白的、又软又瘪的。现在已经黑白黑白的、满了。</p>
<p>从头砍下一个大花盘子。里面满满的都是瓜子。</p>
<p>原来是黄色的一圈花瓣，早已不见了踪影，只看见中间镶着黄黑的花籽一样东西的一盘瓜子外面，是一圈枯了的绿叶子。</p>
<p>瓜子密密麻麻排在上面。不好抠下来。</p>
<p>抠下的瓜子还是软的。里面也没什么味道。</p>
<p>要晒干了炒的。</p>
<p>黑乎乎的大铁锅里，炒出来的瓜子烫手烫手的。</p>
<p>两大塑料袋，提回家。</p>
<p>大人们边打扑克，边嗑着瓜子。</p>
<p>也有炒糊的几颗，苦。酸。像是吃了一口碳。</p>
<p>还有炒的大豆，棕黄的皮子上黑的一道子，许多裂开了口。</p>
<p>门外窗沿上晾着南瓜籽、葫芦籽。</p>
<p>白的。扁的。</p>
<p>没啥味道。</p>
<p>底下垫着一张报纸。上面粘着有南瓜的黄丝丝。</p>
<p>……</p>
<p>烟囱。</p>
<p>从房子中央的炉子上升起，快到房顶时拐了个弯，从房子的侧面穿了出去。</p>
<p>炉子上大小不同的三圈铁环子。</p>
<p>有根铁丝棍子用来勾这几个铁环子。</p>
<p>炉子里总是有火。</p>
<p>炉子边边上时不时烤着半个馍馍。</p>
<p>有时候，也会热上几罐八宝粥。</p>
<p>……</p>
<p>炉子熄了火。</p>
<p>大人扶着靠墙的烟囱。下面的被子上垫着几张白纸。</p>
<p>中央炉子上的烟囱往上一推。</p>
<p>靠墙的烟囱往外拉。黑灰撒落在白纸上。</p>
<p>四截烟囱。</p>
<p>一截直弯弯的。</p>
<p>从外面往里头望。黑乎乎的。</p>
<p>扛着。出外面到了垃圾堆前。</p>
<p>扶起到快到肩膀的位置，带着手套。</p>
<p>铛……铛铛……铛……</p>
<p>满地黑色的粉末。</p>
<p>一条狗跑过来，在旁边的电线杆底下张开腿撒了一泡尿……</p>
<p>………</p>
<p>院子里有花圃。</p>
<p>与其说种的花，不如说是种的菜。</p>
<p>大大小小的南瓜、葫芦。</p>
<p>竹竿子上缠绕的豆角。</p>
<p>细长花叶子的水萝卜。</p>
<p>生菜还是油菜。记不得。</p>
<p>偏房旁边就是水井。</p>
<p>看起来很深。</p>
<p>有没有底。不知道。</p>
<p>望下去十几米清的水反着光。</p>
<p>有水管子从井里出来。</p>
<p>黑长黑长的橡胶管子</p>
<p>就一盆水，有时会看见小虾。</p>
<p>比虾米还小。</p>
<p>……</p>
<p>拧开闸。</p>
<p>使劲捏着前面的软胶管子，水就从两边的缝缝里喷射出来。</p>
<p>能喷射到对面房上。</p>
<p>往花园子里面浇水。</p>
<p>水向高处的天空喷出去。</p>
<p>在阳光的照射下，像一层薄薄的水桥。</p>
<p>透过天空的水面。</p>
<p>还能看见彩虹。</p>
<p>彩虹。红的。黄的。蓝的。紫的。</p>
<p>水洒落在南瓜叶子上。</p>
<p>挂在豆角杆子上。</p>
<p>水萝卜上面的那片土地，早已湿润了。</p>
<p>院子里这么大的一片土地。有没有蚯蚓。</p>
<p>不知道，好像没见着。</p>
<p>肯定有的吧。</p>
<p>……</p>
<p>院子中央里有个方方的、突起的砖。</p>
<p>上面画的东西。</p>
<p>好像是八卦。不知道。</p>
<p>大人不让踩。</p>
<p>……</p>]]></description>
      <author>sherioc</author>
      <guid>moment-2</guid>
      <pubDate>Sat, 19 Aug 2023 05:42:51 +0000</pubDate>
    </item>
    <item>
      <title>“我们能画出的圆圈总是不够圆，但没有人会因此想取消圆圈。”&#xA;&#xA;——罗翔 《圆圈正...</title>
      <link>http://sherioc.online/thinkings#thinking-3</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/thinkings#thinking-3">http://sherioc.online/thinkings#thinking-3</a></p></blockquote><p>“我们能画出的圆圈总是不够圆，但没有人会因此想取消圆圈。”</p>
<p>——罗翔 《圆圈正义》</p>]]></description>
      <author>sherioc</author>
      <guid>thinking-3</guid>
      <pubDate>Fri, 19 May 2023 13:22:29 +0000</pubDate>
    </item>
    <item>
      <title>今人不见古时月，今月曾经照古人</title>
      <link>http://sherioc.online/moments/2023/02/28/jin-ren-bu-jian-gu-shi-yue-jin-yue-ceng</link>
      <description><![CDATA[<blockquote><p>该内容由 RSS 渲染生成，最佳阅读体验请前往：<a href="http://sherioc.online/moments/2023/02/28/jin-ren-bu-jian-gu-shi-yue-jin-yue-ceng">http://sherioc.online/moments/2023/02/28/jin-ren-bu-jian-gu-shi-yue-jin-yue-ceng</a></p></blockquote><p>今人不见古时月，今月曾经照古人。</p>
<p>大唐盛世，纵横天下的雄心壮志；儒者气魄，兼济苍生的广阔胸襟。李白与杜甫，风骨永存，流芳千古。</p>
<p>“终与安社稷，功成去五湖。”渴望像范蠡携西施隐去，亦自比留侯功成身退。酒入豪肠，吞吐一生的放荡；十步杀一，挥洒豪迈与不羁。李白，渴望纵横天下，实现自己心中的抱负。“谁能书阁下，白首太玄经。”他轻视扬雄，看不起那些至死还在儒家烟海中挣扎的老头；他崇拜墨侠，赞颂侠客不计得失的蹈火赴汤。“紫燕枥下嘶，青萍匣中鸣”与“休言女子非英物，夜夜龙泉壁上鸣”有着何等相似之孤傲！他耻学琅琊人，诸葛孔明为他唾弃；风云际会，大厦将倾时力挽狂澜才是他真正的追求。</p>
<p>谁奈，“点额不成龙，归来伴凡鱼。”半生功名都难以企求，济时之策又献于谁呢？“风涛倘相见，更欲凌昆墟。”试借崔侍郎之力步入朝廷，却终成烟涛；又道“精诚动天，长虹贯日，直度易水，不以为寒—膝行于前—”李白，为了实现自己的理想，低三下四的恭维与乞怜却也只徒然成空。</p>
<p>忆天宝二年，玄宗召白进京，四十三岁的他终于高歌“仰天大笑出门去，我辈岂是蓬蒿人。”白酒新熟，黄鸡啄黍，“高歌取杯欲自慰，起舞落日争光辉。”时来运转，岂能不痛饮高歌？笑，大笑，乃至仰天大笑，何等之得意，何等之狂放！然而朝廷毕竟是朝廷，“沐猴而冠”之下也只能“牛滞东鲁”罢了。昔日之繁华，浩如烟云，永王之变，远谪夜郎，与辛判官对饮的慷慨高歌，那份忧愁又有谁能真正懂得？梦游天姥，将进之酒，李白在消极之中，将自己的豪迈与洒脱，放飞天地之间，于睥睨一切的狂放与飘逸之中。</p>
<p>回顾李白的一生，既有远大的抱负，又执着与理想，欲力挽狂澜，功成去五湖，隐居观世变。侠气也罢，仙骨也罢，虽都难免于俗，毕竟纵横之思想，在天下统一之时举步维艰，但李白用自己的一生去追求心中的理想，追求属于自己的巅峰。</p>
<p>“性豪业嗜酒，嫉恶怀钢肠。”壮游时期的杜甫，有着与李白不相上下的狂傲。“检书烧烛短，看剑饮杯长。”烛光之下，樽斗之间，溢散着诗人的豪情壮志。“痛饮狂欢空度日，飞扬跋扈为谁雄？”纵然年华不在，也记得年少轻狂。</p>
<p>长安十年日，肥马轻尘于权贵之门，却也仅仅是酒鱼之宴，谁感受得到“残杯冷炙”的无奈，谁又托得起他心中才华无法施展的悲哀？“窃效贡公喜，难甘原宪贫。”自己不甘于贤士的安贫乐道，因为心中那份信仰——真正的儒者的信仰，兼济天下的抱负与胸襟。“以兹吾事理，独耻事干谒。”——可他怎能不干谒？世俗如此，正如李白“安能摧眉折腰事权贵”不过气话，抱负实现怎能不摧眉折腰？所在李白为自己纵横天下而奋斗，杜甫也为自己兼济天下而努力。他的胸襟，永远阔大开朗，无边落木，江流涌动，星河乾坤之间沉浮着他的壮情与超然。纵然飘零天地，却也在时光掠影间听从自己内心的呼唤。</p>
<p>俯仰杜甫的一世，心怀天下，举目民艰，但他未曾退却，茅屋所破，却仍心念寒颜。纵飘零如孤鸟，仍感受生命。乐观旷达，是儒者的坚韧；凭轩涕泗，是诗人的深爱。</p>
<p>“拟把疏狂图一醉，对酒当歌，强乐还无味。”李白与杜甫，或豪迈，或卑贱，但他们用自己的一生，为了心中的理想而奋斗，明知不可为而为之，即使最后只能泛舟挂罥，涕泗横流，但也仍长歌当哭，抒发那份愁，那片大爱。这就是他们的一生，或心酸，或悲苦，却充实而豪迈。</p>
<p>李白与杜甫，扶摇而去；支离破碎的影子，泛起湖中月，沉入如墨的天穹。</p>
<p><del>作于2020年12月，曾在681班的时光</del></p>]]></description>
      <author>sherioc</author>
      <guid>moment-1</guid>
      <pubDate>Tue, 28 Feb 2023 06:34:20 +0000</pubDate>
    </item>
  </channel>
</rss>