<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Cpiz&#39;s blog</title>
  <icon>https://www.gravatar.com/avatar/337120e7d01c42fe9153e3238f107941</icon>
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://cpiz.com/"/>
  <updated>2019-01-23T14:11:37.821Z</updated>
  <id>http://cpiz.com/</id>
  
  <author>
    <name>Cpiz</name>
    <email>cpiz@qq.com</email>
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>编译Windows 64bit平台pysqlcipher3 for Python3.7</title>
    <link href="http://cpiz.com/2019/01/23/windows-64bit-pysqlcipher3-for-python37/"/>
    <id>http://cpiz.com/2019/01/23/windows-64bit-pysqlcipher3-for-python37/</id>
    <published>2019-01-23T12:57:39.000Z</published>
    <updated>2019-01-23T14:11:37.821Z</updated>
    
    <content type="html"><![CDATA[<h2 id="编译与安装"><a href="#编译与安装" class="headerlink" title="编译与安装"></a>编译与安装</h2><ol start="0"><li><p>安装Python3 64bit</p><p> <a href="https://www.python.org/ftp/python/3.7.2/python-3.7.2-amd64.exe" target="_blank" rel="noopener">https://www.python.org/ftp/python/3.7.2/python-3.7.2-amd64.exe</a></p></li><li><p>安装OpenSSL</p><p> <a href="https://slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="noopener">https://slproweb.com/products/Win32OpenSSL.html</a></p><p> 这里使用了<code>Win64 OpenSSL v1.0.2q</code>版本。</p><p> 注意需要将OpenSSL的dll安装到系统目录，如果只是安装在OpenSSL的bin目录的话，使用的时候需要将bin目录加入系统PATH，或者自行拷贝相关dll到调用程序目录。<br> <img src="http://static.zybuluo.com/caipiz/i81q7y6ilef78p3c4zuyssxp/image.png" alt="image.png-21.2kB"></p></li><li><p>安装Tcl Windows(64-bit, x64)</p><p> <a href="https://www.activestate.com/products/activetcl/downloads/" target="_blank" rel="noopener">https://www.activestate.com/products/activetcl/downloads/</a></p><p> 我使用了<code>8.6.8.0</code>版本。</p></li><li><p>安装 VisualStudio 2017</p><p> <a href="https://visualstudio.microsoft.com/zh-hans/downloads/" target="_blank" rel="noopener">https://visualstudio.microsoft.com/zh-hans/downloads/</a></p><p> 社区版即可，只须安装“使用C++的桌面开发”相关工具集。</p><p> <img src="http://static.zybuluo.com/caipiz/umgjq7si65mx0xr9d0y2izyn/image.png" alt="image.png-130kB"></p></li><li><p>下载 sqlcipher</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop&gt;git clone https://github.com/sqlcipher/sqlcipher.git</span><br></pre></td></tr></table></figure></li><li><p>生成sqlite3源码</p><p> 从开始菜单找到<code>适用于 VS 2017 的 x64 本机工具命令提示</code>，启动，打开附带了VS工作环境的控制台。</p><p> <img src="http://static.zybuluo.com/caipiz/0s8k17yd3ps2fw7ewwahkq95/image.png" alt="image.png-9.9kB"></p><p> 切换到sqlcipher源码目录，执行</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\sqlcipher&gt;nmake /f Makefile.msc</span><br></pre></td></tr></table></figure><p> 结果</p> <figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">Microsoft (R) 程序维护实用工具 14.16.27026.1 版</span><br><span class="line">版权所有 (C) Microsoft Corporation。  保留所有权利。</span><br><span class="line"></span><br><span class="line">        copy .\tool\lempar.c .</span><br><span class="line">已复制         1 个文件。</span><br><span class="line">        cl -nologo -W4   -MT -DNDEBUG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -O2 -Zi -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 -Daccess=_access  -Felemon.exe .\tool\lemon.c /link /DEBUG</span><br><span class="line">lemon.c</span><br><span class="line">        del /Q parse.y parse.h parse.h.temp 2&gt;NUL</span><br><span class="line">        copy .\src\parse.y .</span><br><span class="line">已复制         1 个文件。</span><br><span class="line">        .\lemon.exe  -DSQLITE_MAX_TRIGGER_DEPTH=100  -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_STMTVTAB=1 -DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_INTROSPECTION_PRAGMAS=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_COLUMN_METADATA=1   parse.y</span><br><span class="line">        move parse.h parse.h.temp</span><br><span class="line">移动了         1 个文件。</span><br><span class="line">        tclsh .\tool\addopcodes.tcl parse.h.temp &gt; parse.h</span><br><span class="line">        type parse.h .\src\vdbe.c | tclsh .\tool\mkopcodeh.tcl &gt; opcodes.h</span><br><span class="line"></span><br><span class="line">parse.h</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">.\src\vdbe.c</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        tclsh .\tool\mkopcodec.tcl opcodes.h &gt; opcodes.c</span><br><span class="line">        cl -nologo -W4   -MT -DNDEBUG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -O2 -Zi -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 -Femkkeywordhash.exe  -DSQLITE_MAX_TRIGGER_DEPTH=100  -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_STMTVTAB=1 -DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_INTROSPECTION_PRAGMAS=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_COLUMN_METADATA=1    .\tool\mkkeywordhash.c /link /DEBUG</span><br><span class="line">mkkeywordhash.c</span><br><span class="line">        .\mkkeywordhash.exe &gt; keywordhash.h</span><br><span class="line">        tclsh .\tool\mkshellc.tcl &gt; shell.c</span><br><span class="line">        cl -nologo -W4   -MT -DNDEBUG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -O2 -Zi -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 -Femksourceid.exe .\tool\mksourceid.c /link /DEBUG</span><br><span class="line">mksourceid.c</span><br><span class="line">        tclsh .\tool\mksqlite3h.tcl . &gt; sqlite3.h</span><br><span class="line">        copy .\ext\fts5\fts5parse.y .</span><br><span class="line">已复制         1 个文件。</span><br><span class="line">        del /Q fts5parse.h 2&gt;NUL</span><br><span class="line">        .\lemon.exe  -DSQLITE_MAX_TRIGGER_DEPTH=100  -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_STMTVTAB=1 -DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_INTROSPECTION_PRAGMAS=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_COLUMN_METADATA=1   fts5parse.y</span><br><span class="line">        tclsh .\ext\fts5\tool\mkfts5c.tcl</span><br><span class="line">        copy .\ext\fts5\fts5.h .</span><br><span class="line">已复制         1 个文件。</span><br><span class="line">        rmdir /Q/S tsrc 2&gt;NUL</span><br><span class="line">        mkdir tsrc</span><br><span class="line">        for %i in (.\src\crypto.c  .\src\crypto_cc.c  .\src\crypto_impl.c  .\src\crypto_libtomcrypt.c  .\src\crypto_openssl.c  .\src\crypto.h  .\src\sqlcipher.h  .\src\alter.c  .\src\analyze.c  .\src\attach.c  .\src\auth.c  .\src\backup.c  .\src\bitvec.c  .\src\btmutex.c  .\src\btree.c  .\src\build.c  .\src\callback.c  .\src\complete.c  .\src\ctime.c  .\src\date.c  .\src\dbpage.c  .\src\dbstat.c  .\src\delete.c  .\src\expr.c  .\src\fault.c  .\src\fkey.c  .\src\func.c  .\src\global.c  .\src\hash.c  .\src\insert.c  .\src\legacy.c  .\src\loadext.c  .\src\main.c  .\src\malloc.c  .\src\mem0.c  .\src\mem1.c  .\src\mem2.c  .\src\mem3.c  .\src\mem5.c  .\src\memdb.c  .\src\memjournal.c  .\src\mutex.c  .\src\mutex_noop.c  .\src\mutex_unix.c  .\src\mutex_w32.c  .\src\notify.c  .\src\os.c  .\src\os_unix.c  .\src\os_win.c) do copy /Y %i tsrc</span><br><span class="line"></span><br><span class="line">......略</span><br><span class="line"></span><br><span class="line">NMAKE : fatal error U1077: “&quot;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64\cl.EXE&quot;”: 返回代码“0x2”</span><br><span class="line">Stop.</span><br></pre></td></tr></table></figure><p> 最终编译会报错，不过没关系，我们这里并不需要真正的编译，只需要中间生成的<code>sqlite3.h</code>和<code>sqlite3.c</code>就够了。</p><p> 中间过程如果执行有其他差错，可以clean一下再重试：</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\sqlcipher&gt;nmake /f Makefile.msc clean</span><br></pre></td></tr></table></figure></li><li><p>编译正式的sqlcipher控制台程序（非必须）</p><p> 这并不是 pysqlcipher3 需要的，但如果自己想成功编译一份 sqlcipher 的 Windows 程序，可以参考这篇 <a href="https://github.com/sqlitebrowser/sqlitebrowser/wiki/Win64-setup-%E2%80%94-Compiling-SQLCipher%20Win64%20setup%20%E2%80%94%20Compiling%20SQLCipher" target="_blank" rel="noopener">Win64 setup — Compiling SQLCipher</a>，修改Makefile.msc再构建。</p></li><li><p>下载 pysqlcipher3</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/rigglemania/pysqlcipher3.git</span><br></pre></td></tr></table></figure></li><li><p>在<code>pysqlcipher3</code>目录下创建<code>amalgamation</code>目录，拷贝上一步 sqlcipher 项目目录中生成的<code>sqlite3.h</code>和<code>sqlite3.c</code>文件到其中。并在其下创建一个<code>sqlcipher</code>目录，且再次拷贝一份<code>sqlite3.h</code>文件到<code>sqlcipher</code>目录中。</p></li><li><p>执行编译</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\pysqlcipher3&gt;python setup.py build_amalgamation</span><br></pre></td></tr></table></figure><p> 结果</p> <figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\pysqlcipher3&gt;python setup.py build_amalgamation</span><br><span class="line">running build_amalgamation</span><br><span class="line">Builds a C extension using a sqlcipher amalgamation</span><br><span class="line">building &apos;pysqlcipher3._sqlite3&apos; extension</span><br><span class="line">creating build\temp.win-amd64-3.7</span><br><span class="line">creating build\temp.win-amd64-3.7\Release</span><br><span class="line">creating build\temp.win-amd64-3.7\Release\src</span><br><span class="line">creating build\temp.win-amd64-3.7\Release\src\python3</span><br><span class="line">creating build\temp.win-amd64-3.7\Release\amalgamation</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\module.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\module.obj</span><br><span class="line">module.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\connection.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\connection.obj</span><br><span class="line">connection.c</span><br><span class="line">src\python3\connection.c(1546): warning C4090: “=”: 不同的“const”限定符</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\cursor.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\cursor.obj</span><br><span class="line">cursor.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\cache.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\cache.obj</span><br><span class="line">cache.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\microprotocols.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\microprotocols.obj</span><br><span class="line">microprotocols.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\prepare_protocol.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\prepare_protocol.obj</span><br><span class="line">prepare_protocol.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\statement.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\statement.obj</span><br><span class="line">statement.c</span><br><span class="line">src\python3\statement.c(138): warning C4090: “=”: 不同的“const”限定符</span><br><span class="line">src\python3\statement.c(158): warning C4244: “函数”: 从“Py_ssize_t”转换到“int”，可能丢失数据</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\util.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\util.obj</span><br><span class="line">util.c</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcsrc\python3\row.c /Fobuild\temp.win-amd64-3.7\Release\src\python3\row.obj</span><br><span class="line">row.c</span><br><span class="line">src\python3\row.c(101): warning C4090: “=”: 不同的“const”限定符</span><br><span class="line">src\python3\row.c(111): warning C4090: “=”: 不同的“const”限定符</span><br><span class="line">src\python3\row.c(168): warning C4244: “=”: 从“Py_ssize_t”转换到“int”，可能丢失数据</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -DMODULE_NAME=\&quot;pysqlcipher3.dbapi2\&quot; -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_LOAD_EXTENSION=1 -DSQLITE_HAS_CODEC=1 -DSQLITE_TEMP_STORE=2 -Dinline=__inline -Iamalgamation -Id:\Work\OpenSSL-Win64\include -ID:\work\Python37\include -ID:\work\Python37\include &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\include&quot; &quot;-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt&quot; &quot;-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt&quot; /Tcamalgamation\sqlite3.c /Fobuild\temp.win-amd64-3.7\Release\amalgamation\sqlite3.obj</span><br><span class="line">sqlite3.c</span><br><span class="line">amalgamation\sqlite3.c(23097): warning C4996: &apos;fopen&apos;: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.</span><br><span class="line">C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h(208): note: 参见“fopen”的声明</span><br><span class="line">C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\HostX86\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:D:\work\Python37\libs /LIBPATH:D:\work\Python37\PCbuild\amd64 &quot;/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\ATLMFC\lib\x64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x64&quot; &quot;/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64&quot; /EXPORT:PyInit__sqlite3 build\temp.win-amd64-3.7\Release\src\python3\module.obj build\temp.win-amd64-3.7\Release\src\python3\connection.obj build\temp.win-amd64-3.7\Release\src\python3\cursor.obj build\temp.win-amd64-3.7\Release\src\python3\cache.obj build\temp.win-amd64-3.7\Release\src\python3\microprotocols.obj build\temp.win-amd64-3.7\Release\src\python3\prepare_protocol.obj build\temp.win-amd64-3.7\Release\src\python3\statement.obj build\temp.win-amd64-3.7\Release\src\python3\util.obj build\temp.win-amd64-3.7\Release\src\python3\row.obj build\temp.win-amd64-3.7\Release\amalgamation\sqlite3.obj /OUT:build\lib.win-amd64-3.7\pysqlcipher3\_sqlite3.cp37-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.7\Release\src\python3\_sqlite3.cp37-win_amd64.lib libeay32.lib /LIBPATH:d:\Work\OpenSSL-Win64\lib</span><br><span class="line">  正在创建库 build\temp.win-amd64-3.7\Release\src\python3\_sqlite3.cp37-win_amd64.lib 和对象 build\temp.win-amd64-3.7\Release\src\python3\_sqlite3.cp37-win_amd64.exp</span><br><span class="line">正在生成代码</span><br><span class="line">已完成代码的生成</span><br></pre></td></tr></table></figure></li><li><p>安装至python环境</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\pysqlcipher3&gt;python setup.py install</span><br></pre></td></tr></table></figure><p> 结果</p> <figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">running install</span><br><span class="line">running bdist_egg</span><br><span class="line">running egg_info</span><br><span class="line">writing pysqlcipher3.egg-info\PKG-INFO</span><br><span class="line">writing dependency_links to pysqlcipher3.egg-info\dependency_links.txt</span><br><span class="line">writing top-level names to pysqlcipher3.egg-info\top_level.txt</span><br><span class="line">reading manifest file &apos;pysqlcipher3.egg-info\SOURCES.txt&apos;</span><br><span class="line">reading manifest template &apos;MANIFEST.in&apos;</span><br><span class="line">warning: no previously-included files matching &apos;*~&apos; found anywhere in distribution</span><br><span class="line">warning: no previously-included files matching &apos;*.pyc&apos; found anywhere in distribution</span><br><span class="line">writing manifest file &apos;pysqlcipher3.egg-info\SOURCES.txt&apos;</span><br><span class="line">installing library code to build\bdist.win-amd64\egg</span><br><span class="line">running install_lib</span><br><span class="line">running build_py</span><br><span class="line">running build_ext</span><br><span class="line">Builds a C extension linking against libsqlcipher library</span><br><span class="line">creating build\bdist.win-amd64</span><br><span class="line">creating build\bdist.win-amd64\egg</span><br><span class="line">creating build\bdist.win-amd64\egg\pysqlcipher3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\dbapi2.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\dump.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3</span><br><span class="line">creating build\bdist.win-amd64\egg\pysqlcipher3\test</span><br><span class="line">creating build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\dbapi.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\dump.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\factory.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\hooks.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\regression.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\sqlcipher.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\transactions.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\types.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\userfunctions.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\python3\__init__.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test\python3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\test\__init__.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3\test</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\_sqlite3.cp37-win_amd64.pyd -&gt; build\bdist.win-amd64\egg\pysqlcipher3</span><br><span class="line">copying build\lib.win-amd64-3.7\pysqlcipher3\__init__.py -&gt; build\bdist.win-amd64\egg\pysqlcipher3</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\dbapi2.py to dbapi2.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\dump.py to dump.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\dbapi.py to dbapi.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\dump.py to dump.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\factory.py to factory.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\hooks.py to hooks.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\regression.py to regression.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\sqlcipher.py to sqlcipher.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\transactions.py to transactions.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\types.py to types.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\userfunctions.py to userfunctions.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\python3\__init__.py to __init__.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\test\__init__.py to __init__.cpython-37.pyc</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\__init__.py to __init__.cpython-37.pyc</span><br><span class="line">creating stub loader for pysqlcipher3\_sqlite3.cp37-win_amd64.pyd</span><br><span class="line">byte-compiling build\bdist.win-amd64\egg\pysqlcipher3\_sqlite3.py to _sqlite3.cpython-37.pyc</span><br><span class="line">creating build\bdist.win-amd64\egg\EGG-INFO</span><br><span class="line">copying pysqlcipher3.egg-info\PKG-INFO -&gt; build\bdist.win-amd64\egg\EGG-INFO</span><br><span class="line">copying pysqlcipher3.egg-info\SOURCES.txt -&gt; build\bdist.win-amd64\egg\EGG-INFO</span><br><span class="line">copying pysqlcipher3.egg-info\dependency_links.txt -&gt; build\bdist.win-amd64\egg\EGG-INFO</span><br><span class="line">copying pysqlcipher3.egg-info\top_level.txt -&gt; build\bdist.win-amd64\egg\EGG-INFO</span><br><span class="line">writing build\bdist.win-amd64\egg\EGG-INFO\native_libs.txt</span><br><span class="line">zip_safe flag not set; analyzing archive contents...</span><br><span class="line">pysqlcipher3.__pycache__._sqlite3.cpython-37: module references __file__</span><br><span class="line">creating dist</span><br><span class="line">creating &apos;dist\pysqlcipher3-1.0.3-py3.7-win-amd64.egg&apos; and adding &apos;build\bdist.win-amd64\egg&apos; to it</span><br><span class="line">removing &apos;build\bdist.win-amd64\egg&apos; (and everything under it)</span><br><span class="line">Processing pysqlcipher3-1.0.3-py3.7-win-amd64.egg</span><br><span class="line">creating d:\work\python37\lib\site-packages\pysqlcipher3-1.0.3-py3.7-win-amd64.egg</span><br><span class="line">Extracting pysqlcipher3-1.0.3-py3.7-win-amd64.egg to d:\work\python37\lib\site-packages</span><br><span class="line">Adding pysqlcipher3 1.0.3 to easy-install.pth file</span><br><span class="line"></span><br><span class="line">Installed d:\work\python37\lib\site-packages\pysqlcipher3-1.0.3-py3.7-win-amd64.egg</span><br><span class="line">Processing dependencies for pysqlcipher3==1.0.3</span><br><span class="line">Finished processing dependencies for pysqlcipher3==1.0.3</span><br></pre></td></tr></table></figure><p> 中间过程如果执行有差错，可以clean一下再重试：</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop\pysqlcipher3&gt;python setup.py clean</span><br></pre></td></tr></table></figure></li></ol><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>至此pysqlcipher3编译安装完毕，写个程序测试一下：</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pysqlcipher3 <span class="keyword">import</span> dbapi2 <span class="keyword">as</span> sqlite</span><br><span class="line"></span><br><span class="line">conn1 = sqlite.connect(<span class="string">"test.db"</span>)</span><br><span class="line">c1 = conn1.cursor()</span><br><span class="line">c1.execute(<span class="string">"PRAGMA key='123456'"</span>)</span><br><span class="line">c1.execute(<span class="string">"""create table stocks (date text, trans text, symbol text, qty real, price real)"""</span>)</span><br><span class="line">c1.execute(<span class="string">"""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)"""</span>)</span><br><span class="line">conn1.commit()</span><br><span class="line">c1.close()</span><br><span class="line"></span><br><span class="line">conn2 = sqlite.connect(<span class="string">"test.db"</span>)</span><br><span class="line">c2 = conn2.cursor()</span><br><span class="line">c2.execute(<span class="string">"PRAGMA key='123456'"</span>)</span><br><span class="line">print(c2.execute(<span class="string">"""select * from stocks"""</span>).fetchall())</span><br><span class="line">c2.close()</span><br></pre></td></tr></table></figure><p>结果</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">D:\work\Python37\python.exe</span><br><span class="line">C:/Users/caipi/IdeaProjects/wechat_db_decrypt/test.py [(&apos;2006-01-05&apos;,</span><br><span class="line">&apos;BUY&apos;, &apos;RHAT&apos;, 100.0, 35.14)]</span><br><span class="line"></span><br><span class="line">Process finished with exit code 0</span><br></pre></td></tr></table></figure><p>也可能执行失败，提示</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">D:\work\Python37\python.exe</span><br><span class="line">C:/Users/caipi/IdeaProjects/wechat_db_decrypt/test.py Traceback (most</span><br><span class="line">recent call last):   File</span><br><span class="line">&quot;C:/Users/caipi/IdeaProjects/wechat_db_decrypt/test.py&quot;, line 1, in</span><br><span class="line">&lt;module&gt;</span><br><span class="line">    from pysqlcipher3 import dbapi2 as sqlite   File &quot;D:\work\Python37\lib\site-packages\pysqlcipher3-1.0.3-py3.7-win-amd64.egg\pysqlcipher3\dbapi2.py&quot;,</span><br><span class="line">line 33, in &lt;module&gt;</span><br><span class="line">    from pysqlcipher3._sqlite3 import * ImportError: DLL load failed: 找不到指定的模块。</span><br></pre></td></tr></table></figure><p>最有可能的原因是上面提到的 OpenSSL 问题，没有拷贝到 Windows 系统目录，或者没有将 OpenSSL-Win64\bin 目录增加到环境变量PATH。</p><h2 id="关于sqlcipher版本问题"><a href="#关于sqlcipher版本问题" class="headerlink" title="关于sqlcipher版本问题"></a>关于sqlcipher版本问题</h2><p>编译完成后，自己测试创建一个db再读取没问题，但可能打开其他现成的加密db会失败，提示<code>file is not a database</code>，实际错误是解密失败，最大的可能性是我们clone的sqlcipher当前是4.x版本，而要打开的db是由3.x版本创建的。</p><p>参考<a href="https://www.zetetic.net/blog/2018/11/30/sqlcipher-400-release/" target="_blank" rel="noopener">SQLCipher 4的更新说明</a></p><blockquote><p>SQLCipher Core</p><ul><li>Default page size for databases increased to 4096 bytes (up from 1024)</li><li>Default PBKDF2 iterations increased to 256,000 (up from 64,000)</li><li>Default KDF algorithm is now PBKDF2-HMAC-SHA512 (from PBKDF2-HMAC-SHA1)</li><li>Default HMAC algorithm is now HMAC-SHA512 (from HMAC-SHA1)</li><li>…</li></ul></blockquote><p>使用最新版本的DB Browser for SQLCipher也无法打开测试代码创建的test.db，原因也是如此</p><p><img src="http://static.zybuluo.com/caipiz/itzr00wb790eb1jgf5ujw4la/image.png" alt="image.png-38.3kB"></p><p>想要使用Python打开sqlcipher3版本的数据库，可以在调用代码里指定加密算法</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></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">cur.execute(<span class="string">"PRAGMA cipher_page_size = 1024"</span>)</span><br><span class="line">cur.execute(<span class="string">"PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1"</span>)</span><br><span class="line">cur.execute(<span class="string">"PRAGMA cipher_hmac_algorithm = HMAC_SHA1"</span>)</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>如果完全不需要sqlcipher4的支持，可以在<code>第5步</code>时指定切换到sqlcipher3编译（目前最新的是3.4.2版本）：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">D:\MyDocs\Desktop&gt;git clone https://github.com/sqlcipher/sqlcipher.git</span><br><span class="line">D:\MyDocs\Desktop&gt;git checkout tags/v3.4.2</span><br></pre></td></tr></table></figure><p>这样生成的<code>test.db</code>也可以用DB Browser for SQLCipher来打开编辑了。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;编译与安装&quot;&gt;&lt;a href=&quot;#编译与安装&quot; class=&quot;headerlink&quot; title=&quot;编译与安装&quot;&gt;&lt;/a&gt;编译与安装&lt;/h2&gt;&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;&lt;p&gt;安装Python3 64bit&lt;/p&gt;
&lt;p&gt; &lt;a href=&quot;https:
      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="Python" scheme="http://cpiz.com/tag/Python/"/>
    
  </entry>
  
  <entry>
    <title>试遍淘宝手机辅助按键，看谁才是真·吃鸡神器</title>
    <link href="http://cpiz.com/2018/06/26/%E8%AF%95%E9%81%8D%E6%B7%98%E5%AE%9D%E6%89%8B%E6%9C%BA%E8%BE%85%E5%8A%A9%E6%8C%89%E9%94%AE%EF%BC%8C%E7%9C%8B%E8%B0%81%E6%89%8D%E6%98%AF%E7%9C%9F%C2%B7%E5%90%83%E9%B8%A1%E7%A5%9E%E5%99%A8/"/>
    <id>http://cpiz.com/2018/06/26/试遍淘宝手机辅助按键，看谁才是真·吃鸡神器/</id>
    <published>2018-06-26T12:49:00.000Z</published>
    <updated>2019-01-23T12:47:38.921Z</updated>
    
    <content type="html"><![CDATA[<h2 id="手残党的怨念"><a href="#手残党的怨念" class="headerlink" title="手残党的怨念"></a>手残党的怨念</h2><p>本人多年FPS玩家，水平虽然不高，但从Delta Force玩到CS、COD、守望先锋、绝地求生，自认为游戏见识还算丰富。自从Steam吃鸡火爆，国内各厂争先往手机端移植，一开始我是不看好的：不相信通过触摸屏也能还原FPS的体验，因为通常手游最多只能用左右手各一根手指操作，而FPS需要同时控制移动、视角、射击三个变量，必然操作不便。然而接下来很快被刺激战场打脸，这可能是手游史上将端游FPS还原得最好的一款游戏，提供了双射击键、陀螺仪、3D Touch，还有很方便的探头操作方案，这些设计让没有高性能PC的玩家也能很大程度上体验到吃鸡的乐趣。</p><p>随着对操作的熟悉和游戏理解的加深，很快发现搓屏的操作方式终究还是限制了我的战绩，主要两个问题：</p><ol><li>被偷袭时，一紧张经常不能准确地按中射击键反击，气得想摔手机。</li><li>通常习惯左手按射击键，方便精准瞄准，但交火时左手占用无法左右横移，发挥不了身法优势，而这在PC或主机FPS游戏中只是基本操作。</li></ol><p>当时想到解决这两个问题最好的方案就是键鼠，也发现已经有PC模拟器提供了现成解决方案，但失去了手机移动优势，还不如玩端游吃鸡，而且光子也很快发宣布将模拟器玩家隔离排位。</p><p>第二个方案就是手柄。认真调研后购买了价格最贵的飞智八爪鱼，体验了半天就彻底放弃。首次配置极其繁琐，上手困难，按键手感奇差，转身速度和瞄准精度都不如手机搓，虽然也提供了陀螺仪瞄准，但灵敏度和精度也远不如手机原生陀螺仪。</p><p>第三个方案就是辅助按键了，也是本文的主角。之前偶然看到一个用口香糖铝箔制作辅助射击键的视频，心想到这么简单的原理，应该会有商家做出成熟的产品吧。在万能的淘宝一找果然有很多款，设计各不相同，价位大多十几二十元。</p><p><img src="http://static.zybuluo.com/caipiz/7buwta6078sw4lj05f6a4xex/image.png" alt="image.png-722.8kB"></p><p>在购买了一款尝试后，虽然发现有诸多不便，但的确能显著提升射击速度，很可能是最有效的方案。为了找到最好用的那款辅助按键，我干脆把淘宝热门的款式都买了回来（反正加起来也没到一个手柄钱），并记录下各自的体验结果，在这里分享给大家。</p><h2 id="辅助按键的原理"><a href="#辅助按键的原理" class="headerlink" title="辅助按键的原理"></a>辅助按键的原理</h2><p>先说一下手机电容屏的原理：</p><blockquote><p>一片四边形绝缘片的单面被涂上传导层。给传导层施加微小的电压后，产生了一个均匀的静电场。当一个导体，如人的手指接触到没有涂层的（绝缘）表面时，一个电容就动态的形成了。感应器的控制器将能够从绝缘片的四个角测量到电容量，从而能够得知触摸的位置。</p></blockquote><p>摘自<a href="https://zh.wikipedia.org/wiki/%E7%94%B5%E5%AE%B9%E5%BC%8F%E6%84%9F%E5%BA%94" target="_blank" rel="noopener">维基百科：电容式感应</a></p><p>正常操作手机游戏，需要眼睛的协助才能准确点击中屏幕上的射击、瞄准键，但拇指只有两根，想同时操作移动、视角、射击至少需要三根手指。利用电容屏导电的原理，通过在屏幕按键位置固定两个电极，将电极另一端固定在手机的上沿靠近左右手食指的位置，食指按下电极时相当于触摸了屏幕上对应的虚拟按键，而且左右食指只各自负责一个按键（射击与开镜），触发距离很小，完全可以盲操。这使得我们可以用最多四只手指同时操作游戏，分别实现移动、视角、开镜、射击，互相独立，分工和主流游戏机手柄一样，达到效率最高。</p><p>提前说明一个辅助按键的缺点：按键安装上手机之后本身就会破坏屏幕电感的平衡，手机可能误以为已经有两根手指压在屏幕上而产生“误触”，这时候再点击物理按键是无法模拟点击屏幕的。因此，<strong>安装好按键后必须先对手机进行锁屏（熄屏）再重新解锁（亮屏）</strong>，这会对触摸定位算法进行重置，建立一个新的平衡，辅助按键才可以正常响应。初次体验辅助按键的用户往往没注意到商品页面上的说明（如我），以为买了个骗人玩意，也有不少淘宝卖家因此获得了糟糕的商品评价。</p><h2 id="考察标准"><a href="#考察标准" class="headerlink" title="考察标准"></a>考察标准</h2><p>具体介绍每一款按键之前，先说一下考察的标准。在没接触之前，本以为做一款辅助按键很简单，后来发现要考虑的细节其实很多，这也是为什么淘宝上有多款不同的设计。</p><p>按重要性逐个说明：</p><ol><li><p><strong>可靠性</strong></p><p>正因为手指触屏易失误，所以才需要物理“外挂”来提升可靠性，灵敏度是一款按键最重要的指标，但太过灵敏的话又有误触风险（容易走火也是原生触屏操作的一大缺点），所以需要的是可靠的灵敏，开火的时候快速响应，停火的时候快速中止，跑毒的时候不易误触。</p></li><li><p><strong>兼容性</strong></p><p>手机那么多型号，苹果/安卓、全面屏/非全面屏，带壳/不带壳、贴膜/不贴膜，是否容易安装和卸下，是否牢固稳定。</p><p>有可能你期待满满的吃鸡神器收到后根本装不上手机，设计不良的辅助按键，轻可能夹坏贴膜、刮花屏幕，重可能损伤摄像头。</p></li><li><p><strong>舒适性</strong></p><p>安装后按键位置是否合理，长期持握是否舒适，是否会遮挡太多屏幕内容，是否影响手指进行其他操作。</p></li><li><p><strong>工艺性</strong></p><p>是否坚固耐久，是否精致美观，做工太差的产品，可能还没开始装机调试就开始怀疑自己很SB。</p></li></ol><h2 id="谁是终极神器？"><a href="#谁是终极神器？" class="headerlink" title="谁是终极神器？"></a>谁是终极神器？</h2><p>开始进入正题，先晒下订单，然后按我的体验顺序逐个介绍，并会在每一个体验的感受中总结。</p><p><img src="http://static.zybuluo.com/caipiz/vyqq7pyovtr69i5v24mdbswh/image.png" alt="image.png-1225.5kB"></p><p><img src="http://static.zybuluo.com/caipiz/nrnzb91o1prqbegsnp58q7bl/image.png" alt="image.png-14953.8kB"></p><p><strong>注意，我主要使用的手机是iPhoneX，也用iPhone 6 Plus及小米6进行了简单试用，仅仅是个人观点，不一定代表你手上机器的真正体验。</strong></p><hr><h3 id="1-原始经典款"><a href="#1-原始经典款" class="headerlink" title="1. 原始经典款"></a>1. 原始经典款</h3><p>这可能是手游吃鸡辅助按键的鼻祖，是2018春节前能在淘宝搜到的唯一款式。因为正在评估考察的时候朋友已经先下单了，就直接借来体验了一下，但最后并没有真正购买。</p><p><img src="http://static.zybuluo.com/caipiz/aetbvy1p0txrbxydy6vm267b/image.png" alt="image.png-670kB"></p><p><img src="http://static.zybuluo.com/caipiz/z3w9ymgsw28y4bwq3x7l30y6/image.png" alt="image.png-270.9kB"></p><p>从细节图上可以看到吃鸡按键的基本结构：电容导电棉用于接触屏幕模拟手指，金属触点用于食指按压触发，金属导线连接导电棉与金属触点，通过三者实现指尖电场的延伸。</p><p>按键其他部分都是塑料，没有任何活动件，用塑料本身的弹性夹住手机。出于稳固需要，包括导电棉的一脚外共有四爪前后固定。</p><ul><li><p>可靠性：★★★★</p><p>响应迅速可靠</p><p>初代产品触点可能存在氧化问题，后期产品使用了紫铜触点改进</p></li><li><p>兼容性：★★</p><p>对手机厚度有要求。目前大多数手机的裸机可直接安装（如iPhone 6 Plus），对戴保护套且贴膜的手机较难兼容。而对iPhone X这样本来比较厚，且摄像头凸起还正好在左上方（横屏时）的手机则彻底无法安装。有人说把手机倒过来就不冲突摄像头了，确实是，但有带来了另外3个缺点。一、倒置横屏需要开启手机横竖屏重力感应，对于不需要这个功能的人（如我）在每次安装时又多了一步操作。二、iPhone X正常横持时辅助按键会包围左侧电源键，电源键在游戏进行中是不需要使用的，影响不大。倒置横持右侧辅助按键会包围音量控制键，音量在游戏过程中经常需要操作。三、边玩边充电的情况下，正常横持时充电线在右侧，影响开镜还可以忍受，倒置时充电线在左侧，影响射击不能忍受。</p><p>二、iPhone正常横持时，充电口在右侧，右手负责</p><p>双爪设计，多余的爪子对非全屏手机正好在屏幕外不影响视线，但在全面屏手机吃鸡时多余的爪分别会挡住队友名称和游戏地图，严重破坏游戏体验。</p><p>安装位置与手机电源键或音量键（反向持握）冲突，对于安装后需要锁屏重置非常不便。另外稍用力按下可能触发锁屏/音量调节，导致成盒悲剧。</p></li><li><p>舒适性：★★★</p><p>触点位置在手机的顶部两角，待机与射击时时食指都需要保持一个弓形的姿势，长时间下来容易疲劳，在小屏手机上更加明显（因为侧边更短）。</p></li><li><p>工艺性：★★</p><p>存在毛边、接缝和裸露的导线，做工较简陋。</p></li></ul><p><strong>点评</strong>：创意与执行力值得敬佩。整体中规中矩，初代产品选用最稳妥的方案无可厚非，做到了“让一部分鸡友先用起来”。<a href="https://s.click.taobao.com/lONAFQw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="2-按键触摸双模款"><a href="#2-按键触摸双模款" class="headerlink" title="2. 按键触摸双模款"></a>2. 按键触摸双模款</h3><p>使用螺丝调节压力固定，对保护膜和手机壳友好。</p><p>使用物理按键按压触发，便于手指待机时停放。提供按压与触摸双模式，左右键调换使用则方便切换为触摸触发。</p><p><img src="http://static.zybuluo.com/caipiz/c6jj0o2j3mfongwx2uitnbj8/image.png" alt="image.png-264.4kB"></p><p><img src="http://static.zybuluo.com/caipiz/wngn7e71n1olrrgm555ql8na/image.png" alt="image.png-405.1kB"></p><p><img src="http://static.zybuluo.com/caipiz/3f3dtirc08rdw73kv346ui7l/image.png" alt="image.png-194.9kB"></p><ul><li><p>可靠性：★★★</p><p>食指可停放在按键上待机，开镜射击响应快。</p><p>按压阻尼偏大，导致手感不清晰，不易掌握触发力度，偶尔出现按下无触发。</p><p>存在金属触点，容易腐蚀氧化，长久可靠性会下降。</p></li><li><p>兼容性：★★★★☆</p><p>最大支持厚度11mm，兼容所有手机，兼容全屏与非全屏。</p><p>单爪设计，对屏幕遮挡极小。</p><p>精心设计了顶部凹槽，完美防误触电源键。</p><p>顶部全包围设计，安装后锁屏重置稍有不便。</p></li><li><p>舒适性：★★★</p><p>按键水平位置可调，按压式设计，食指悬停在手机上沿舒展自然。</p><p>按键面积太小，阻尼偏大，导致手感差，也影响响应速度。</p></li><li><p>工艺性：★★★☆</p><p>集成了塑料、橡胶、铜、铝多种材质，工艺设计出彩，堆料扎实，但加工精度稍逊。</p></li></ul><p><strong>点评</strong>：优秀的创意与工艺设计，可惜按键手感功亏一篑，期待改进（加大按键面积，优化阻尼）。<a href="https://item.taobao.com/item.htm?spm=a1z09.2.0.0.3a482e8dG1Kt9E&amp;id=567353220195&amp;_u=vh56pkd181" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="3-销量明星C9"><a href="#3-销量明星C9" class="headerlink" title="3. 销量明星C9"></a>3. 销量明星C9</h3><p>单爪设计，预留一定空间嵌入手机，使用翻转扣挤压手机背面固定。</p><p>按键式，采用导电塑料作为手指电极，用塑料弯曲提供按键回弹。</p><p>可能是淘宝分销做得最成功的款式，众多店铺代理销售。</p><p><img src="http://static.zybuluo.com/caipiz/23dvhvq1h7fc1gkh11dqpmnh/image.png" alt="image.png-195.3kB"></p><ul><li><p>可靠性：★★★★</p><p>按键式的优点，食指自然停放待机，开镜射击响应快。</p><p>按下时导电塑料与导电棉的接触不完全可靠，偶现无触发。</p></li><li><p>兼容性：★★</p><p>对手机厚度要求高，最大支持厚度8mm，不兼容较厚或带壳手机。iPhone 6 Plus裸机可使用，尝试上iPhone X时夹坏了我的玻璃膜，不敢再试。</p><p>同样设计有顶部凹槽，防误触电源键。</p></li><li><p>舒适性：★★★★☆</p><p>待机悬停舒展自然，按键面积大，弹性适当，使用体验接近手柄。</p></li><li><p>工艺性：★★★★</p><p>设计简单巧妙，精细度较高。</p></li></ul><p><strong>点评</strong>：兼顾功能与成本的巧妙设计，可惜一体化结构带来的兼容性短板，对手机厚度有严格要求。<a href="https://s.click.taobao.com/GwWHCQw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="4-无语米形"><a href="#4-无语米形" class="headerlink" title="4. 无语米形"></a>4. 无语米形</h3><p>一体化单爪设计，通过弹簧加多个不同厚度的海绵垫片兼容不同手机。</p><p>专业的产品介绍页面，夸张的销量数字（可惜期望越大，失望也越大）。</p><p><img src="http://static.zybuluo.com/caipiz/kgrpnmgcziydwfcuix4fizse/image.png" alt="image.png-279.1kB"></p><p><img src="http://static.zybuluo.com/caipiz/rcyjfx69mag1po0hk242014k/image.png" alt="image.png-154.3kB"></p><p><img src="http://static.zybuluo.com/caipiz/elno148f7w2vnftqpaqefy8k/image.png" alt="image.png-143.7kB"></p><ul><li><p>可靠性：★★</p><p>手指直接按压一个尾端伸出来的不锈钢丝圈触发，触发可靠性OK。</p><p>单爪固定设计加长度夸张的主体，安装在iPhone 6 Plus这种正常厚度手机上时，按键的一端容易绕单爪固定点为轴心产生滑动，是所有试验过的辅助按键中稳定性最差的一款。</p></li><li><p>兼容性：★★★</p><p>弹簧提供了一定的余量，通过随机附送的不同厚度的3M不干胶贴配合，最大可兼容厚度10mm的手机，iPhone X加手机壳也不在话下。</p><p>顶部全包围设计，与锁屏激活操作存在冲突，用力按下主体时会传递到电源键导致游戏中锁屏。</p></li><li><p>舒适性：★★</p><p>触点不是按键也不是金属片，而是一个从主体中伸出7~8mm的U型的钢丝圈电极，手指按压在U型圈底部触发。钢丝直径0.5mm，按下后手指被顶出凹印，有明显不适感。</p><p>安装位置固定，无法调节。</p><p>触点位置在手机上沿两角，待机姿势极其别扭，时间稍长易疲劳。</p></li><li><p>工艺性：★</p><p>硬塑料廉价感明显；不对称设计和夸张比例带来奇怪的重心，永远无法在一个平面稳定摆放。</p><p>应该是为了照顾部分非全屏手机两侧非屏幕区高度不一致在《终结者》这款游戏中不好适配的问题，设计了左键52mm、右侧59mm的长度。但面对全面屏对称屏手机越来越普及，《终结者》已凉的现在，这样不对称的设计极其丑陋。</p></li></ul><p><strong>点评</strong>：卖家秀和买家秀的惨痛教训。<a href="https://item.taobao.com/item.htm?spm=2013.1.w4023-18248156073.2.3c541de7K73p4x&amp;id=566874272318" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="5-微动诱惑"><a href="#5-微动诱惑" class="headerlink" title="5. 微动诱惑"></a>5. 微动诱惑</h3><p>双爪一体化，背面卡扣翻转用于固定；使用机械微动开关实现按键式触发，手感清晰。</p><p><img src="http://static.zybuluo.com/caipiz/3alkubhac3wsjlr08yiu4brn/image.png" alt="image.png-370.8kB"></p><p><img src="http://static.zybuluo.com/caipiz/vvntwynlpn0xcn9ge9mg6zu3/image.png" alt="image.png-206.6kB"></p><ul><li><p>可靠性：★★★</p><p>与鼠标按键一样，通过微动开关按下和释放产生清脆的咔哒声带来了清晰的反馈。但因为增加了微动开关，相比之前介绍的按键式额外增多了一个传导触点，可能带来更多的不稳定性。</p></li><li><p>兼容性：★★★</p><p>一体化设计的缺陷，兼容手机范围有限。勉强支持iPhone X不带壳，安装过程容易碎膜。这种依赖塑料弹性嵌住手机的按键，在插入过程中都容易顶压贴膜边缘，这是贴膜最脆弱的位置。</p><p>窄爪对屏幕遮挡小，但双爪设计对全面屏不友好。</p><p>顶部全包围设计，与锁屏激活操作存在冲突，用力按下主体时会传递到电源键导致游戏中锁屏。</p></li><li><p>舒适性：★★</p><p>可能由于微动装置体积较大，并没有设计在主体的上沿，而是附加在主体背面。这导致持握手机时食指不是自然包围手机边沿，而是呈一定角度上的斜错（如下图），这降低了持握的安全感，姿势也极容易疲劳。</p><p><img src="http://static.zybuluo.com/caipiz/2hru4dg7tz50wo1nhmrfs8xr/image.png" alt="image.png-282.3kB"></p><p>通过压下不锈钢制的一个杠杆片触发微动，触发键程较大，反而对微动带来的优点产生了抵销。</p><p>手指触点虽然做了一定的弧形弯折提高舒适度，但不锈钢片边缘切割锐利，未经打磨极其硌手。</p></li><li><p>工艺性：★★</p><p>塑料廉价感明显，触点切割锐利，工艺粗糙。</p></li></ul><p><strong>点评</strong>：机械微动开关是很好的创意，败在设计与工艺。<a href="https://s.click.taobao.com/kz4e9Qw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="6-平板也吃鸡"><a href="#6-平板也吃鸡" class="headerlink" title="6. 平板也吃鸡"></a>6. 平板也吃鸡</h3><p>因为iPad的大屏幕更易发现和瞄准敌人，平时偶尔也会用iPad吃鸡，这款辅助按键就是专为iPad而设计。</p><p>不同于其他辅助按键设计，这款按键很像一个晾衣夹，用的时候直接夹在平板上。一个导电圆柱体既作为屏幕电极，同时也是手指电极。食指平时停放在夹子正面，射击时直接按压柱体的侧面来连导屏幕。</p><p><img src="http://static.zybuluo.com/caipiz/ssq0hr13s3v49r4vlmbktqfp/image.png" alt="image.png-673.8kB"></p><p><img src="http://static.zybuluo.com/caipiz/40dtmuygqhr166z1hyk9ll82/image.png" alt="image.png-68.4kB"></p><ul><li><p>可靠性：★★★</p><p>电极简单可靠，响应灵敏。</p><p>夹子力臂较长，无法提供足够的弹力，游戏过程中用例稍大就容易移位，导致开镜射击无响应。</p></li><li><p>兼容性：★★☆</p><p>理论上兼容所有平板，但夹子深度有限，在iPad上电极无法完全覆盖到屏幕区域，大约有1/4的电极落在屏幕外框，加上夹子弹力不足，稍稍一位移就功能失效。</p></li><li><p>舒适性：★★☆</p><p>一般持握iPad时食指通常放平板背面，但此套装置要求食指放屏幕正面，相当于用双手食指与中指夹住iPad，姿势与高玩们的四指操作非常接近，手残党感觉非常别扭，容易疲劳，</p></li><li><p>工艺性：★★★★★</p><p>主体塑料上镀有一层亲肤材质，带来了非常舒适的手感，各种边角圆滑光润，做工极其精致。</p></li></ul><p><strong>点评</strong>：相比起玩耍，更适合收藏。<a href="https://s.click.taobao.com/JCAm6Qw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="7-铁的教训款"><a href="#7-铁的教训款" class="headerlink" title="7. 铁的教训款"></a>7. 铁的教训款</h3><p>试过这么多塑料结构后，突然想试试金属一体式的，这套设计简洁美观，屏幕遮挡少，应该会不错，然而……</p><p><img src="http://static.zybuluo.com/caipiz/qoirh3vqp1mrcpdrpvqggzg8/image.png" alt="image.png-511.3kB"></p><ul><li>可靠性：☆<br>在iPhone X和iPhone 6 Plus上完全无法触发，与卖家沟通后毫不惊讶表示给你退货，但懒得寄快递了。目前卖家共9个评价，其中1个中评和1个差评。</li><li>兼容性：★★★</li><li>舒适性：★★☆</li><li>工艺性：★★☆</li></ul><p><strong>点评</strong>：不做太多评价，就当买了个教训。<a href="https://item.taobao.com/item.htm?spm=a1z09.2.0.0.67002e8djRtInJ&amp;id=566619586909&amp;_u=1h56pk598e" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="8-转角遇真爱"><a href="#8-转角遇真爱" class="headerlink" title="8. 转角遇真爱"></a>8. 转角遇真爱</h3><p>受上一款金属版伤害后继续寻觅，被这款价格所吸引，随便买了一对，没想遇到真爱。</p><p><img src="http://static.zybuluo.com/caipiz/1p5bhhtnvuictnsdpkerfw4k/image.png" alt="image.png-329.2kB"></p><ul><li><p>可靠性：★★★★☆</p><p>结构简单，全部拆开也就是铝合金主体、海绵垫、固定螺丝、螺丝垫脚4个元件。铝合金主体展开的话（如果能）是十字结构，四瓣分别充当屏幕电极x1、手指电极x2、后背固定脚x1。手指按在主体任意位置都能够触发开镜/射击。</p><p>一个小缺陷是是螺丝上的橡胶垫脚是用3M不干胶粘在螺丝上的，螺丝旋紧时本身会受到一定扭力，游戏过程中手指推移也可能导致脚垫松脱失去固定。解决办法是用一滴502来替代不干胶，一劳永逸。</p></li><li><p>兼容性：★★★★☆</p><p>按键主体不可形变，通过调整螺丝深浅顶住手机后背来固定，最高12mm的厚度理论上兼容所有手机，iPhone X + 贴膜 + 厚保护套不在话下。</p><p><img src="http://static.zybuluo.com/caipiz/kxn5dcis8fyi6kloujowje6r/image.png" alt="image.png-377.8kB"></p><p>主体内侧贴有一块5mm厚的海绵垫，一开始我认为这个设计很奇葩，装上手机像一双厚厚的松糕鞋。但随后发现这能分散手指压力，避免力量传导到电源键上触发锁屏。海绵垫形状跟主体一致呈8字形，内凹的区域正好给下面的电源键留出了一点点空间，于是可以在安装完毕后用指甲按到电源键，方便锁屏激活。这个矛盾的电源键竟然通过一块海绵垫解决，实在有点巧妙。</p><p>虽然是单爪设计，但遮挡屏幕面积稍大，未能完美。</p></li><li><p>舒适性：★★★★☆</p><p>按键位置可调，食指自然围绕手机边沿，持握舒适稳固。</p><p>按键面积适当，所有棱面都进行过打磨，按键操作舒适。</p><p>左右键完全对称，安装方便。</p></li><li><p>工艺性：★★★★</p><p>按键主体加工整齐，漆面细致。结构简单，不易损坏。</p><p>固定螺丝精细度稍逊，不干胶贴保护垫方案稳定性不足。</p><p>第一次买的时候没的挑，收货后发现正面印刷的Logo非常不美观，后来复购了一对银色无Logo版本。</p></li></ul><p><strong>点评</strong>：无心插柳，简单的却是最好的。<a href="https://s.click.taobao.com/rTKq7Qw" target="_blank" rel="noopener">淘宝链接</a> <a href="https://mobile.yangkeduo.com/goods2.html?goods_id=2067446328" target="_blank" rel="noopener">拼多多链接</a></p><h3 id="9-金属收藏款"><a href="#9-金属收藏款" class="headerlink" title="9. 金属收藏款"></a>9. 金属收藏款</h3><p>受到<code>第6款</code>失败刺激后与<code>第7款</code>同日购买，结构也类似。工艺极其优秀，甚至怀疑是整块CNC切削而来。</p><p><img src="http://static.zybuluo.com/caipiz/e4yfsjkyygrfjjcq8j3sj1d6/image.png" alt="image.png-302.1kB"></p><ul><li><p>可靠性：★★☆</p><p>金属电极响应可靠，但后背爪与固定螺丝体积巨大，持握手机时一般中指贴在手机后背，游戏时中指容易碰触背爪或金属螺丝而误触发，哭笑不得。</p></li><li><p>兼容性：★★★★</p><p>左右位置可调，最大支持厚度11mm，兼容各种手机。</p></li><li><p>舒适性：★★☆</p><p>按键面积太小，金属棱角锋利，硌手。</p></li><li><p>工艺性：★★★★★</p><p>无论是主体还是螺丝，都精细漂亮，无可挑剔。</p></li></ul><p><strong>点评</strong>：一个华丽的鸡肋，我会好好收藏。<a href="https://s.click.taobao.com/2HLo7Qw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="10-ZNNCO"><a href="#10-ZNNCO" class="headerlink" title="10. ZNNCO"></a>10. ZNNCO</h3><p>这是评论区<code>@一笑</code>朋友极力推荐的，价格不贵16.9元一对包邮，我也下单了一副来体验。ZNNCO可能只是京东卖家的一个渠道号，淘宝上还有大量的无牌同款产品。</p><p><img src="http://static.zybuluo.com/caipiz/nqj05oizv2grafj50d6n8cum/image.png" alt="image.png-19.4kB"></p><p>京东发货物流神速，凌晨下单当天即达。</p><p><img src="http://static.zybuluo.com/caipiz/b2ucs1fgyssmia7qncv57lyu/image.png" alt="image.png-664.3kB"></p><p>外形与第3款C9很像，单爪一体化+卡口嵌入式，主体采用透明塑料，视觉上更精致。</p><p>触发结构非常巧妙，与C9完全不同。顶部是一副桥式对称按键，桥片两端分别卡在主体上，底部中心的突起被一片中央拱起的圆形金属簧片顶住，呈三点式临时固定。桥片两端都可以作为按键按下，压力传导至簧片，簧片先是提供按下的阻力，在反曲变形瞬间阻力会反向变成助力，迅速连通电路到底部的电极，这本身就是一个典型的微动开关结构。另外，所有的电路包括电极都是纯铜的薄片。</p><p><img src="http://static.zybuluo.com/caipiz/p8bswd0r6ylaxo10ul9x65qu/image.png" alt="image.png-468.3kB"></p><ul><li><p>可靠性：★★★☆</p><p>我收到的两个按键其中一个很正常，而另一个不需要按下，只要手指触摸按键上的电极就会触发开枪。拆开后了解了它的结构原理，发现就是簧片底部的铜片弹起太高，直接接触簧片的底部导致了上下连通。重新调整了底部的铜片高度后问题解决，这个问题估计会比较普遍，显然与设计和装配工艺有关。</p><p>3层金属带来2个开关点，随着铜电极的氧化和簧片反复弯折积累的金属疲劳，预计未来的可靠性会显著下降。</p></li><li><p>兼容性：★★★☆</p><p>卡口结构与第<code>5</code>款非常相似，在塑料主体上实现了较大的兼容性，最佳厚度是8mm左右手机，但iPhone X带壳带膜（10mm）可以非常勉强地装配上去（注意碎膜风险）。而且这种透明塑料应该脆性比较大，操作不当容易断裂，翻京东的评价得到了证实。</p><p>左右对称，位置可调；单爪设计，对屏幕遮挡小，好评。</p></li><li><p>舒适性：★★★★☆</p><p>待机悬停舒展自然，按键面积大，弹性适当，使用体验接近手柄。</p><p>键程稍涩，随着簧片老化，会逐渐严重。</p></li><li><p>工艺性：★★★☆</p><p>设计巧妙，外观讨喜，但用料与工艺精度一般，从实拍图上已经可以看到铜片的氧化情况，对寿命不太有信心。</p></li></ul><p><strong>点评</strong>：价格厚道，可以尝试，不差钱可以多买几副。<a href="https://union-click.jd.com/jdc?d=dx1T2t" target="_blank" rel="noopener">京东连接</a></p><h3 id="11-第三代金属按键版"><a href="#11-第三代金属按键版" class="headerlink" title="11. 第三代金属按键版"></a>11. 第三代金属按键版</h3><p>这是一位知友<code>@千城暮雪</code>给我私信发来的体验，按天猫页面的描述应该是第<code>1</code>款的三代升级版本，获得知友同意后，我把它补充进来，供大家参考。</p><p><img src="http://static.zybuluo.com/caipiz/cseu8gq63b52vun8u5u8pnk6/image.png" alt="image.png-598.2kB"></p><p>这款按键采用了两个杠杆联动作为触发，因为安装时没有导电体在屏幕上，按下后模拟手指点击，所以安装完不需要重新亮屏。Mix的id设计大家都知道，我习惯把下巴放左边玩，能够完美的避开音量键，这款按键屏幕上要卡两个地方做支撑，一个是模拟按键的，需要放到射击键上，另外一边为了防滑用了硅胶，所以我们可以在不用的时候把按键往上面一拉，这样就能完美的不挡住屏幕了。</p><ul><li><p>可靠性：★★★★</p><p>因为使用了铜上镀铬的处理。使用了两个联动杠杆。虽然杠杆用了两个，可能会降低可靠性，但是我仍然能给他四星，因为表面镀了铬没那么容易氧化。我用了差不多一个月了，到现在为止没有出现过失灵或者走火的现象。</p></li><li><p>兼容性：暂缺</p><p>本人手机裸奔，所以不在乎卡不卡的上的问题，不过Mix2的厚度大家也都知道。应该能兼容主流的大部分手机的。</p><p>这个按钮目前我发现的缺点就是，当你开枪的时候，你不知道到底有没有按下去，没有鼠标按键的那种段落感。</p></li><li><p>舒适性：暂缺</p><p>这个按键金属部分使用了铸造的铜构件。表面看起来是镀铬处理，所以手感十分的顺滑，不会像金属片那样割到手。按键位置比较适中，做了圆弧处理。</p></li><li><p>工艺性：暂缺</p></li></ul><p>作者点评：通过杠杆结构将开关触点移到离屏幕最近的地方，避免了安装后需要重新激活屏幕的问题，这是非常聪明的设计。但双爪结构会带来对全屏的遮挡，也因为双爪结构按键只能在最顶两端，持握不舒适。作者尝试在淘宝找到了它的单爪版本，正在物流途中，回头继续补充。<a href="https://s.click.taobao.com/cP4xwPw" target="_blank" rel="noopener">天猫链接</a></p><h3 id="12-单脚透明杠杆式"><a href="#12-单脚透明杠杆式" class="headerlink" title="12. 单脚透明杠杆式"></a>12. 单脚透明杠杆式</h3><p>这是看了知友的第11款评价后，作者另行购买的改进版。基本原理和结构都与第10款一样，但从双脚变为了单脚。理论上与第10款性能相当，但经过我自己的亲手测试，感受更真切。</p><p><img src="http://static.zybuluo.com/caipiz/qh9kco4mcy6lq0h486ccmmm9/image.png" alt="image.png-542.3kB"></p><p><img src="http://static.zybuluo.com/caipiz/xboggyqg8dgfbtzsvamw6sc7/image.png" alt="image.png-362.9kB"></p><p>双杠杆联动结构，平常没有任何电极与屏幕接触，因此完全不存在锁屏重置的麻烦。按下扳机时（这个手感相比按键确实更像扳机），抬起杠杆1的另一端，顶起杠杆2，杠杆2的另一端是电极，被撬动往下压接触到屏幕，完成整个感应电路。</p><ul><li><p>可靠性：★★☆</p><p>杠杆联动设计解决了锁屏重置问题，但带来了非常机械的手感，按下的前半段有虚位而后半段艰涩。有时轻轻一按即可触发射击，有时却需要更大的大量，缺乏清晰的手感，无法提供强烈的射击信心。<code>@千城暮雪</code>在第10款的兼容性部分也有提到。</p></li><li><p>兼容性：★★★</p><p>塑料嵌入式，勉强可支持iPhone X带壳，意味着可兼容市面绝大多数手机。</p><p>单脚设计避免了双脚带来的额外遮蔽，但单脚塑料结构在夹住双面玻璃手机（iPhone X）时无法提供稳定的固定，会出现类似第4款的晃动，极其影响游戏体验。其他材质手机应该有改善。</p></li><li><p>舒适性：★★★★</p><p>按键水平位置可任意调整，按键圆润不硌手。</p><p>全物理联动，需要按键力气偏大，久易疲劳。</p></li><li><p>工艺性：★★★</p><p>设计巧妙，既是机械结构，也是电路结构。</p><p>透明材质讨喜，防滑考虑不足。</p></li></ul><p><strong>点评</strong>：设计巧妙，为电子游戏提供了扳机手感，成也在此，亏也在此。<a href="https://s.click.taobao.com/4f0gjPw" target="_blank" rel="noopener">淘宝链接</a></p><h3 id="13-鸡霸·屏后扳机式"><a href="#13-鸡霸·屏后扳机式" class="headerlink" title="13. 鸡霸·屏后扳机式"></a>13. 鸡霸·屏后扳机式</h3><p>这是评论区<code>@悲伤的闪光</code>推荐的产品，基本原理与第11、12款一样，双杠杆联动、扳机手感，但第一节杠杆的方向不是水平的，而是垂直于屏幕方向，因此扳机位于屏幕背后。</p><p><img src="http://static.zybuluo.com/caipiz/6zav417i9is7tgsv40uqa14c/image.png" alt="image.png-455.7kB"></p><p><img src="http://static.zybuluo.com/caipiz/mtryw7pgxpq4rzpv4vhi2ino/image.png" alt="image.png-155.1kB"></p><p>由于大部分机构在屏后，装上手机后，这是目前所有按键中屏上面积最小的一款。</p><ul><li><p>可靠性：★★☆</p><p>与第12款同样的原理，也存在同样的问题，而且第一节杠杆是垂直屏幕，由于重力的原因平常处于下垂状态导致了近3mm的虚位，按下3mm后须要再进一步用力才可触发第二节杠杆触点触屏，手感极其模糊。</p></li><li><p>兼容性：★★☆</p><p>最大支持9mm厚度手机，只能支持不戴壳的iPhone X，但由于结构以及纯塑料材质的原因，无论是iPhone X还是小米6，安装后都容易发生滑动。商家随机附送了两个防滑贴纸，有一定效果，但未能彻底解决。</p><p>对于iPhone X这样两面光滑的手机，必须倒持安装，避开锁屏与音量键一侧，否则极其容易按下时触发锁屏/音量键。</p></li><li><p>舒适性：★★☆</p><p>在第5款的介绍中我提到了屏后按键会带来持握不稳定以及疲劳，再一次得到了验证。为了确定不是我自己手残，我观察了周围6个以上朋友玩吃鸡的姿势，无一不是双手食指呈90度卡在屏幕顶部两角，以提供最大的稳定性。屏后扳机每次按下时会产生一个从屏幕部朝向自己的作用力，带来手机一定的翻转，为了减小翻转幅度又不得不将双手拇指更用力顶在屏幕上，这降低了拇指动作的精确性，时间一长也带来了疲劳。XBox与PS手柄之所以能将按钮置于手柄背面，是因为游戏机手柄提供了两个握把，按压背部按键时，通过抓紧握把可以完全保持住手柄水平稳定性。而在手机上，其余的手指只能提供简单的支撑，难以水平稳定。因此，以后不会再尝试屏后按键式了。</p><p>需要按键力气偏大，久易疲劳。</p></li><li><p>工艺性：★★★☆</p><p>屏后扳机很有创意，既是机械结构，也是电路结构。</p><p>透明材质讨喜，防滑考虑不足。</p></li></ul><p><strong>点评</strong>：好的创意没有带来好的体验，可惜可惜。<a href="https://s.click.taobao.com/LzCahPw" target="_blank" rel="noopener">淘宝链接</a></p><hr><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>作为一个物理“外挂”，吃鸡辅助按键原理简单，但要兼容不同的手机、不同的游戏、乃至不同的用户习惯，挑战并不简单。做好了是帮助，没做好就是累赘，这很需要创意、设计与工艺的完美结合。</p><p>合适的产品能够提升战绩，但目前无论哪一款辅助按键，都有以下所有的缺点：</p><ol><li>携带累赘，拆卸繁琐</li><li>大部分产品初次安装后须要锁屏激活才可使用</li><li>阻碍手机侧面物理按键的操作：电源、音量</li><li>存在视野遮蔽</li><li>存在操作阻碍，可能影响跳伞跟随，语音，视野等屏幕上半区的小操作</li><li>必须将开镜、射击键设置在屏幕顶部，正好也是横屏时Push通知弹出的区域，这时候要是按开枪可能就进微信了</li></ol><p>想尝鲜的朋友，请提前做好心理预期。</p><p>最后分享一个我用辅助按键操作吃鸡的小视频：</p><p>瘾大时间少，水平一般，目前星钻，但六种模式基本都有S+/SS，80以上的评分，有时间应该能上皇冠，大神们看了轻点吐槽。</p><h2 id="答网友问"><a href="#答网友问" class="headerlink" title="答网友问"></a>答网友问</h2><p>评论区不少疑问，我更新统一回答在这里。</p><h3 id="到底哪款好？"><a href="#到底哪款好？" class="headerlink" title="到底哪款好？"></a>到底哪款好？</h3><p>文章的目的尽可能全面的介绍我用过的这些玩意，给想尝试的同学一些信息。但每个人使用习惯不同，每人手机也不同，我在意的地方你可能不在意，在我手机上不方便在你手机可能没问题，而且目前所有的按键都不完美，直接给一个推荐是不太负责的。我个人常用的是第8款，觉得游戏体验还不错，缺点也还能接受。目前正在体验第10款，是评论区一位朋友推荐的，体验也很好，解决了第8款的一些缺点，但也有它的新问题。</p><p>这里也列一下我个人的选择标准，结合上面各款的案例，各位的理解应该会更准确。</p><ul><li>兼容性必须满足，装不上就只能送垃圾桶。最好是不需要倒置才能安装，安装后一定不能容易误触电源键，要出人命的。</li><li>可靠性必须满足，这一方结构越简单越可靠，金属触摸款完全不存在该问题，按键款由于多了电路开关，存在触电氧化问题，可靠性会逐渐降低。</li><li>持握舒适度。必须保证按键位置在手机上沿，持握更舒适，按压时也不影响水平稳定性。有时一玩就两个小时，持握姿势别扭、端不稳手机会手指发僵，有这耐力不如去苦练三指四指。</li><li>按键舒适度。手指触点必须光滑、宽大。理论上按键式会提供更好的反馈，手指自然悬停在按键上，也能提升持握舒适度和响应时间，但按键阻尼的微调是门技术活，用料不当的话弹性元件还存在老化问题，而成本只有几块钱又只能选择廉价方案……</li><li>安装便利度。螺丝式固定式安装稍麻烦，但兼容性广。弹性嵌入式安装相对简便，但要特别小心手机插入时易碎膜。两者各有优劣。</li><li>屏幕遮挡。应越小越好，不管是不是全面屏手机，只选择单爪式。大多数单爪式都是左右对称设计，安装更方便且水平方向上位置可调整，能找到个人最舒适的位置。</li><li>单个 or 双个？可以只安装一个左键用于开枪，但我仍推荐用双键模式，缩短开镜开枪时间。</li><li>工艺，实用、不丑陋即可。</li></ul><p>以我的标准，给了3星的选项表示还能接受，但有些扣分项是因为我的iPhone X特征，你可以根据自己手机情况参考评分。</p><p>最后购买之前，你可以仔细观察一下自己平常是用什么姿势持握手机游戏，尤其是食指一般放在哪里。再想象一下如果买了某款按键，它会安装在你手机上的什么位置，安装后持握是什么姿势，食指是否能够灵活操作，持机是否稳定。总之好的辅助按键应该让你在游戏的时候忘记它，把注意力全部投入到战场上，而不是让你觉得是在为了战绩而忍受。</p><h3 id="有3D-Touch还需要这个？"><a href="#有3D-Touch还需要这个？" class="headerlink" title="有3D Touch还需要这个？"></a>有3D Touch还需要这个？</h3><p>3D Touch只支持部分设备，手机不支持的朋友没得选。</p><p>刺激战场在支持3D Touch的版本发布后我立即尝试过，但也很快放弃了。我认为跟真枪操作一样，瞄准与射击操作应该是分离开的，这样最自然，效率也最高。3D Touch操作模式要求右手拇指兼顾瞄准和射击，在刚枪走位时确实方便，但远程狙击时需要精确操作，瞄准（移动）和射击（按下）动作可能互相干扰，无法提供信心。</p><p>另外，人和人的差异确实是存在的，我玩游戏的时候容易兴奋，手指力量忽大忽小，3D Touch模式走火率奇高。</p><h3 id="为什么用这个？我两指-四指操作比这6多了"><a href="#为什么用这个？我两指-四指操作比这6多了" class="headerlink" title="为什么用这个？我两指/四指操作比这6多了"></a>为什么用这个？我两指/四指操作比这6多了</h3><p>这个问题不是很有争论的必要，为什么大家都有眼睛而有的人却要戴眼镜？每个人情况不同，接触游戏时间不同，玩游戏的目的也不一样，我的目的是在工作之余得到快乐和放松，不是做主播打职业上天梯。辅助按键能让我专注在游戏本身，而不是如何搓屏幕上，我觉得更适合我而已。</p><p>发我的游戏视频只是一个小演示，不是炫耀技术。发我的游戏视频只是一个小演示，不是炫耀技术。觉得自己不用按键水平高的朋友，欢迎回答这题<a href="https://www.zhihu.com/question/266950585" target="_blank" rel="noopener">《绝地求生：刺激战场》有哪些吃鸡技巧？</a>，不用在本文评论浪费时间。</p><h3 id="辅助按键算不算开挂？"><a href="#辅助按键算不算开挂？" class="headerlink" title="辅助按键算不算开挂？"></a>辅助按键算不算开挂？</h3><p>我对开挂的定义是使用电子设备通过软件或硬件手段，读取或修改游戏数据，而实现游戏正常规则之外的行为。</p><p>辅助按键没有外接其他的电子设备，没有任何数据的读取和修改，只是实现了人类肢体的延伸。就像我们现在不会说赤裸才是人类，而指责穿衣穿鞋的人不是人。</p><p>对于手游来说，物理上的绝对公平是不存在的，苹果安卓、大屏小屏，性能和视觉的表现就不一样。游戏本身还给苹果手机提供了独有的3D Touch支持，说明官方也对目前的射击操作也不满意，希望能用尽硬件的潜能，给玩家提供方便。即使对于模拟器+键鼠游戏，腾讯官方也没定性为开挂，甚至提供了官方模拟器支持，但是心里过意不去，而做了匹配隔离。放大到整个电子游戏的领域，有条件的玩家追逐性能更强的CPU显卡、更大更高刷新率的显示器、更精准的鼠标、更精准的耳机，和普通的玩家相比，这也不能算是开挂吧？</p><p>辅助按键合理优化了手指分工，让玩家可以更专注在游戏而不是操作冲突上，若是发展足够好，出现了更完美的装置，会得到腾讯的官方推荐也不一定。</p><p>还是觉得不公平的话就向腾讯举报吧，腾讯只要发篇公告给辅助按键下定论我就删文章。官方要想屏蔽此“外挂”也很容易，下一个版本禁止射击瞄准按钮放置在屏幕上半区，所有按钮就全部做废了。</p><h2 id="声明"><a href="#声明" class="headerlink" title="声明"></a>声明</h2><ul><li>以上的评价完全出于个人的主观体验，不代表其他人的操作习惯与感受。</li><li>所有结果仅代表当时购买的商家版本或产品个体，不代表其他外观类似或后续改进版本。</li><li>大部分图片来源于淘宝介绍，页面链接附在各款点评尾部，侵删。</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;手残党的怨念&quot;&gt;&lt;a href=&quot;#手残党的怨念&quot; class=&quot;headerlink&quot; title=&quot;手残党的怨念&quot;&gt;&lt;/a&gt;手残党的怨念&lt;/h2&gt;&lt;p&gt;本人多年FPS玩家，水平虽然不高，但从Delta Force玩到CS、COD、守望先锋、绝地求生，自认为游戏
      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
  </entry>
  
  <entry>
    <title>小程序周记</title>
    <link href="http://cpiz.com/2017/01/17/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%91%A8%E8%AE%B0/"/>
    <id>http://cpiz.com/2017/01/17/小程序周记/</id>
    <published>2017-01-17T12:49:00.000Z</published>
    <updated>2018-05-24T07:04:32.253Z</updated>
    
    <content type="html"><![CDATA[<p>截止今日，微信小程序正式开放一周。作为一个参与者，同时也是观察者，我来回顾一下这周微信小程序见闻与体验。</p><h2 id="前夜"><a href="#前夜" class="headerlink" title="前夜"></a>前夜</h2><p>1月8日，小程序发布前夜。我加入的两个小程序微信群开始热闹起来，大家纷纷猜测小程序究竟会当夜开放还是次日开放，或者是延期。有部分觉悟慢的同学还在临时抱佛脚，问一些很基础的问题。我当时猜测应该会等到9号白天上班后发布，理由是系统太庞大，夜里发布如果出了问题，可能不好找人解决。</p><p>9日0点，群里突然炸开，连续出现了小程序的分享名片，微信小程序踩着0点正式开放了！捂着热辣辣的脸，我只能佩服微信团队艺高胆大，半夜发布意味着整个鹅厂与此相关的员工都在待命。</p><p>匆忙打开电脑进入小程序后台，原来不可用的发布按钮已经可以点击了，接下来扫描二维码确认身份，发布了我的小程序「100房贷助手」几天前的已过审版本，然后又把最近提的一个体验版本提交了审核。由于微信审核的不可测原理，估计很多开发者都和我一样：尽早提审了第一个版本来确保赶上9号的发布，等到通过审核时，第二个版本也准备好了，只能Hold着等首个版本发出后再提。</p><p>微信群里越来越热，大家都在发自己的小程序名片，也分享在别处看到的小程序，还有抱着不同目的的人迅速组织了更多的微信群，我进了两三个，质量都不高。这两天读了一篇某个小程序项目团队的分享，说他们当晚加了200多个微信群和300多个QQ群来做产品曝光，这确实给我上了一课。</p><p>微信半夜小程序发布的好处是夜里用户量少，对系统冲击也少。让一批开发者和IT媒体们提前体验正好相当于灰度，也能趁天亮前有时间做些调整。更大的好处是：大多数小程序开发者都在等零点可能发布，媒体们也在摩拳擦掌，等普通用户们第二天起床处于信息饥饿状态时，新鲜的小程序资讯正好送上。</p><h2 id="发布日"><a href="#发布日" class="headerlink" title="发布日"></a>发布日</h2><p>9日早晨，我起床注意到的第一条消息不是新闻，而是昨晚提交的版本已经审核通过的通知。<br><img src="http://static.zybuluo.com/caipiz/3nm8fcqtv5cdmjebk67x9434/image_1b6jp9kru1tdl36j15lfrsokph9.png" alt="image_1b6jp9kru1tdl36j15lfrsokph9.png-90.6kB"><br>之前两次审核分别用了6天值1天，这次竟然8小时神速过审，应该是微信预料了发布日的拥挤，安排了加班甚至是通宵在处理审核。</p><p>我擦了擦眼睛，迅速进行了发布。同时注意到，不同于首个版本的发布即可见，当已经有旧版本在线上时，新版本发布大概要延后3分钟生效。当然这比我们传统的APP发布要等待用户逐渐升级快速多了。</p><p>媒体果然爆炸了，朋友圈和知乎里到处是小程序的话题。得益于赶上了首批发布，我在几个微信群里做了入口分享，而且发布的前几天我在<code>知晓程序</code>的小程序商店(minapp.com)里提交了产品介绍。「100房贷助手」在当天很多小程序新闻稿中得到了曝光，后台监控到不断有新用户进来体验，为此我赶紧多加了一个服务节点避免过载。</p><p>其实首日发布的小程序并不多，微信在9月份开放了200个小程序内测名额，这些公司也成了首日为微信小程序站台的主体。我个人看来，除了通过微信分享卡片式的小程序页面能提升一些体验，其他惊喜并不多，很少有H5做不到只能小程序才能完成的场景。</p><p>更大的尴尬是：越有影响力的大厂们越能更早开发出更完善的小程序，也有更大的吸引力来让用户体验他们的小程序。但往往这样的大厂都是通过线上来变现的，当把用户吸引进了一个他们无法变现的小程序黑洞中，那自己也就没了生路。很多低频的APP被用户卸载，这让厂家很心痛，但却合理至极。</p><h2 id="后续"><a href="#后续" class="headerlink" title="后续"></a>后续</h2><p>第一天结束时媒体们傻眼了，昨天通宵赶文章还写微信即将要统治手机，看了一天下来发现不是这么回事，只能拿点段子交差。</p><p>接下来几天小程序热度明显下降，开有有少数公司停止了微信小程序的服务，还有部分类目被监管叫停。现在又有媒体出来泼冷水了，嘲笑微信没格局不开放。</p><p>其实微信也很委屈，本来期望的场景是线下，但反应最快传播也最快的总是线上，他们来了不爽就走。而线下的企业反应慢一些，服务铺开也需要时间，这需要更多的耐心来栽培。媒体自作多情，怪我咯？</p><h2 id="数据分享"><a href="#数据分享" class="headerlink" title="数据分享"></a>数据分享</h2><p>目前在小程序后台已经可以看到一周的数据统计，拿「100房贷助手」两个数据做一个简单的解读。</p><p><img src="http://static.zybuluo.com/caipiz/br6yxtxml02vzm9ot10d6cj0/image_1b6k0bi911m9iehh1j2d1gtf4qi13.png" alt="image_1b6k0bi911m9iehh1j2d1gtf4qi13.png-81.7kB"></p><p>第一天因为赶上首发名单得到了不错的曝光，用户量较高，但第二天数据则出现大幅下降，直到第6、7天开始趋稳。对于一个没有持续投放的小工具产品来说，这个趋势是很正常的。但这无疑也吻合了微信小程序的热度，即5天后该来尝鲜的用户已经来得差不多了。</p><p><img src="http://static.zybuluo.com/caipiz/cu3x76xxs3ofp05plmq3klzj/image_1b6k19kct1j0d8ng1gl0oek4v51g.png" alt="image_1b6k19kct1j0d8ng1gl0oek4v51g.png-173.3kB"></p><p>以上是小程序的百度指数，趋势接近。</p><p>虽然大部分用户是尝鲜游客，而且其中大部分并没有真正的使用（无有效数据录入），但也值得高兴。正是因为程序赶上了首发，获得了一定的曝光，才带来的这波“蜜蜂”。这些尝鲜的用户会帮忙分享给有需要的朋友，以后自已有需求了也可能再来。</p><p>另一个数据是平均停留时长<br><img src="http://static.zybuluo.com/caipiz/7xbmsxxw8sgzfhjqw29g9l4b/image_1b6m50srbuqektnr1nob1166e9.png" alt="image_1b6m50srbuqektnr1nob1166e9.png-86kB"><br>总体在缓慢增长，说明用户开始在正在的使用产品，这是好的现象。</p><p>微信可能在用完即走这个概念上走太极端了，后台竟然不支持最关键的用户存留分析，希望未来能够加入。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>一点经验和教训，如果再重来一次，怎么低成本让小程序在发布首日后获得更多用户呢？</p><ol><li>前期和发布日的大范围分享、投递。这会带来首批媒体稿中较高的曝光。</li><li>精美图标 + 有趣的名字。最好让人一看到就痒，产品曝光后更容易被尝鲜客试用。</li><li>有趣的内容，促使用户强烈的分享冲动（我相信分享是未来小程序的革命级特性）。</li><li>持续的价值 + 精美的制作。必须有持续的价值才能长久，精美制作有助于第二波的曝光与用户分享。</li></ol><p>最后再自问自答一次：小程序有没有红利？<br>没有通常意义的流量红利，只能算一次热点事件，而且已经结束了。我相信更长远的红利是有的，可能需要等待下一个杀手级小程序的引爆。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;截止今日，微信小程序正式开放一周。作为一个参与者，同时也是观察者，我来回顾一下这周微信小程序见闻与体验。&lt;/p&gt;
&lt;h2 id=&quot;前夜&quot;&gt;&lt;a href=&quot;#前夜&quot; class=&quot;headerlink&quot; title=&quot;前夜&quot;&gt;&lt;/a&gt;前夜&lt;/h2&gt;&lt;p&gt;1月8日，小程序发布
      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="小程序" scheme="http://cpiz.com/tag/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
    
      <category term="微信" scheme="http://cpiz.com/tag/%E5%BE%AE%E4%BF%A1/"/>
    
      <category term="房贷助手" scheme="http://cpiz.com/tag/%E6%88%BF%E8%B4%B7%E5%8A%A9%E6%89%8B/"/>
    
  </entry>
  
  <entry>
    <title>小程序「100房贷助手」诞生记</title>
    <link href="http://cpiz.com/2017/01/10/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E3%80%8C100%E6%88%BF%E8%B4%B7%E5%8A%A9%E6%89%8B%E3%80%8D%E8%AF%9E%E7%94%9F%E8%AE%B0/"/>
    <id>http://cpiz.com/2017/01/10/小程序「100房贷助手」诞生记/</id>
    <published>2017-01-10T13:40:00.000Z</published>
    <updated>2018-05-24T06:52:43.661Z</updated>
    
    <content type="html"><![CDATA[<img src="/2017/01/10/小程序「100房贷助手」诞生记/Mortgage_Calculator_title.png"><blockquote><p>把自己的爱好作为职业是怎么样的体验？</p></blockquote><p>知乎有很多类似的讨论，我算是很符合要求的一人吧。从高中开始，编程就是我的爱好，因为爱好，选择了大学专业，选择了最终的职业。</p><p>做自己喜欢的事当然开心，但职业中的选择有限，很多的时候只能重复无聊或执行并不认同的工作。累觉不爱的时候就得找点真心想做的项目来弥补一下，所以对我来说编程既是工作，也是消遣。</p><p>11年的时候由于自己有需求，写了一个<a href="http://cpiz.com/post/blog/2011/07/mortgage_loan_calculator_excel_edition/">Excel版贷款计算器</a>，解决了<strong>利率变更</strong>和<strong>提前还款计算</strong>两个痛点，程序发布在网上也收获了不少用户的好评。但现在已经是移动互联网时代，经常只是想看一眼数据却得掏出PC和Excel这种重武器，还是不太方便，如果改成APP就好了。我把这个想法告诉了我的用户，他们也表示了很大的期待。</p><p>前阵子学习Android的新语言Kotlin，正好拿这个项目练手。Kotlin很赞，我很快上手并完成了核心算法，开始写界面。然后微信小程序来了，经过短暂的了解，我决定转向用小程序来实现。</p><h2 id="为什么用小程序？"><a href="#为什么用小程序？" class="headerlink" title="为什么用小程序？"></a>为什么用小程序？</h2><p>能力上，小程序基于阉割的H5，但微信提供了丰富的组件和API并保证了足够的性能，体验上和原生应用几乎无异，足够支持大部分的功能型应用。</p><p>成本上，它天生解决了跨平台的问题，意味着开发工作量可以减少一半，或者开发人员可以减掉一半。</p><p>交付上，有微信这个国民应用做Runtime，小程序只需要打包核心的代码逻辑，可以做到秒下秒开，将传统的APP扫码下载安装过程中的流失减到最低。直接发布的特性同时也解决了传统APP多平台、多版本兼容的问题。</p><p>推广上，微信已经占有了线上（消息）和线下（二维码）最大的渠道和入口，传统应用都不可避免要支持分享到微信和微信扫码。而小程序天然内置在微信中，基于微信好友和群的现成关系，很容易被传播分享。</p><p>以上都是我们传统APP开发者多年梦寐以求的特性，虽然小程序也有很多限制和不足，但对于我要做的这个小工具，它是完美的选择。</p><h2 id="我能收获什么？"><a href="#我能收获什么？" class="headerlink" title="我能收获什么？"></a>我能收获什么？</h2><p>我不打算在最短的时间内把它搞定然后不管，否则这比赶工作还更无趣，我更希望把它当做一次有趣的实践，尽可能体验从0到1这个过程中相关的一切。</p><p>JavaScript是现在最活跃的编程语言，不仅跨过了Web页和服务端，近一年大热的React Native和Weex已经开始攻占移动端的地盘。移动端开发者如果还不主动了解，那就太迟钝了。从小程序入门，正好是一个机会。</p><p>小程序是微信近两年最大的动作，目标和特性都昭示了巨大的野心。它究竟能做到什么程度，未来会如何发展，只有参与了才有可靠的判断。</p><p>工作中我负责客户端，跟产品磨跟UI磨跟后端跟测试磨，大量的时间用在沟通和等待上，最终的交付也有很多不甘的妥协。这次我一人全栈，终于有机会做一个只让自己满意的产品，顺便体验一下不同职能的思考，对未来工作也有益处。</p><p>从未接触过产品的运营和推广，想在小程序的生态中探索一下盈利模式。先定一个小目标：收回成本！</p><p>张小龙对微信的寄托是“做一款伟大的产品取悦自己”，不知道此生我有没有这样的机会，至少目前我还可以<strong>做一款满意的小程序取悦自己</strong>。</p><h2 id="「100房贷助手」的目标"><a href="#「100房贷助手」的目标" class="headerlink" title="「100房贷助手」的目标"></a>「100房贷助手」的目标</h2><p>买房是成家的必经之路，贷款又是买房的必经之路，起码中国如此。我经历过在银行办贷款签几十个名字的激动与担忧，合同还没看清楚就欠了上百万的负债，每月省吃俭用担心破产，央行降息让我暗暗开心，好不容易存了点钱去提前还款，又被银行大姐问到蒙圈。直到我认真研究了一下贷款的机制，开启了对理财的新认识。</p><p>我将我对贷款的知识与经验，装进这个小程序，并赋予它随时访问，轻松分享的能力。希望这个小工具，能<strong>帮助要购房和已购房的年轻人做点决策，清楚掌握自己的债务情况，做好财务规划，维持信用</strong>。</p><p>目前已经完成了基础的功能，还在继续打磨。如果你有更多的需要和建议，可以给我反馈。</p><p>谢谢！</p><hr><blockquote><p>准备贷款，想知道能承受多高的额度，月供多少。</p><p>已经贷款，央行宣布利息下/上调xx点，想知道月供会如何变化。</p><p>提前还款，想知道能缩短多少期限，节约多少利息。</p><p>用100房贷助手，让一切简单！</p></blockquote><p><img src="http://static.zybuluo.com/caipiz/0vyts9drr28iqbridxhdttpp/gh_1786c7d53423_258.jpg" alt="gh_1786c7d53423_258.jpg-29.7kB"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;img src=&quot;/2017/01/10/小程序「100房贷助手」诞生记/Mortgage_Calculator_title.png&quot;&gt;
&lt;blockquote&gt;
&lt;p&gt;把自己的爱好作为职业是怎么样的体验？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;知乎有很多类似的讨论，我算是
      
    
    </summary>
    
      <category term="项目" scheme="http://cpiz.com/category/%E9%A1%B9%E7%9B%AE/"/>
    
    
      <category term="小程序" scheme="http://cpiz.com/tag/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
    
      <category term="微信" scheme="http://cpiz.com/tag/%E5%BE%AE%E4%BF%A1/"/>
    
      <category term="房贷助手" scheme="http://cpiz.com/tag/%E6%88%BF%E8%B4%B7%E5%8A%A9%E6%89%8B/"/>
    
  </entry>
  
  <entry>
    <title>我看微信小程序</title>
    <link href="http://cpiz.com/2016/12/21/%E6%88%91%E7%9C%8B%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
    <id>http://cpiz.com/2016/12/21/我看微信小程序/</id>
    <published>2016-12-20T17:38:00.000Z</published>
    <updated>2018-05-24T06:54:41.319Z</updated>
    
    <content type="html"><![CDATA[<p>今年的互联网媒体们可能不太容易，大行业不景气，风投退缩，巨头抱团，新概念泡沫，没什么话题好挖掘。9月，微信宣布小程序的概念，开始内测，媒体们仿佛鲨鱼闻到血，东西还没看见就炸开了锅，漫天评论：“微信要成操作系统了”、“没必要再开发APP了”、“H5要一统天下了”……</p><p>技术圈子也被点炸，这两年iOS和Android系统趋于稳定，大家终于踩完了坑开始琢磨造点新轮子，突然发现又要被前端抢饭碗，这怎么坐得住。</p><p>我对此也挺感兴趣，之前一直想业余做个贷款计算的小APP，又嫌兼顾iOS和Android麻烦一直没动手。小程序如果真能跨平台，这是最好的时机，正好也了解一下这项可能要“抢饭碗”的技术。</p><p>11月，微信开始小程序公测，经过了一番波折的注册与开发，目前我的程序已经通过审核，我也算对这个新平台有了真切的认识，可以谈谈看法了。</p><h2 id="小程序与微信"><a href="#小程序与微信" class="headerlink" title="小程序与微信"></a>小程序与微信</h2><p>先说结论：<strong>短期来看，小程序对于微信的价值远大于对企业的价值</strong>。</p><p>微信早已稳坐国内社交工具的头把交椅，基础功能已经很久没什么大革新，更多的努力在营造生态上，通过统一登录、二维码、支付、公众号等等把自己打造为联接一切的入口。</p><p>小程序对于微信，不是从0到1的新内容，它本身的能力并没有和之前的内嵌H5有本质的飞越。此时推出小程序平台，是因为<strong>微信对自己的生态的过去和未来都有了更清晰的洞见</strong>。</p><h3 id="不是红利，是清流"><a href="#不是红利，是清流" class="headerlink" title="不是红利，是清流"></a>不是红利，是清流</h3><p>2013年8月，微信推出公众号，打开了生态的大门。无数媒体、商家和机构的涌入，将微信从基础的工具建设为繁荣的平台。从市场的结果上来说这是巨大的成功，但从产品的角度上微信并不满意。第一次承担规则的制定者，微信已经足够谨慎，但仍然低估了商家无孔不入的手段。</p><p><strong>微信希望商家提供服务，用户用完即走</strong>，而<strong>商家希望用户订阅，以便日后勾搭</strong>。往往一个扫码 + H5的就能搞定的服务，却得通过扫码 + 关注 + 菜单来达成。繁琐的操作影响了用户的即时体验，后续的广告又伤害了长期的用户体验。</p><p>2016年1月11微信公开课Pro，张小龙首次公开演讲谈微信4大价值观，很不留情地指出商家过度营销实际伤害了微信，并在最后曝光了正在构思的应用号（即小程序）。<strong>小程序通过更强的能力来吸引商家支持，无须下载且无法关注（故意），并进一步限制了推送</strong>。</p><p>前两天的2017公开课上，张小龙提到小程序的启动日是16年1月9日，这就是说他在项目启动两天后就迫不及待地进行了宣布，可见当时他对小程序的期待。</p><p>我大胆揣测一下他的愿景：</p><ul><li>小程序搞定所有服务</li><li>卡券维持商家与用户的关系</li><li>订阅号专心做阅读</li><li>服务号老子不要了</li></ul><p>所以小程序不是什么操作系统和新红利，它目标是成为服务号与部分订阅号的升级替代，天生就带着限制商家的使命，是一股净化环境的清流。</p><h3 id="关键入口：二维码"><a href="#关键入口：二维码" class="headerlink" title="关键入口：二维码"></a>关键入口：二维码</h3><p>二维码其实是个古老的发明，早在Windows Mobile时代就出现在智能手机。当时在日本和台湾有一点应用，但在大陆还很鲜见，偶有新潮人士用来印在名片上别人也看不懂。</p><p>微信在11年底的3.5版本中就引入了二维码，是国内大厂里启动最早的，扫一扫加好友和登录Web微信都还是很新鲜的体验。12年5月，张小龙已经在朋友圈称二维码将是移动互联网的入口。当时我还没有太在意，如今，看见身边各种商品、广告和公共设施上都印上了二维码，中国成为世界上二维码最便利的国家，不得不佩服他的判断和感谢微信的推广。</p><p><img src="http://oi7ynvrxf.bkt.clouddn.com/snap/20161222004453.png" alt="张小龙朋友圈"></p><p><img src="http://oi7ynvrxf.bkt.clouddn.com/snap/20161222010152.png" alt="二维码百度指数"></p><p>从摇一摇到扫一扫，每一次入口的抢占与打通，都是微信的一次超越。小程序这次做的，就是进一步打通微信与服务，而且其关键的入口将仍然是二维码。</p><p>通过扫描二维码，我们通常能够到达：</p><ol><li>人（用户/群名片）</li><li>信息、服务的提供者（订阅号、服务号）</li><li>信息、服务（网页）</li><li>其他微信内置功能，如授权、支付</li></ol><p>小程序将改进第3点的体验与能力，让其达到与原生功能（第4点）相近的程度。尽管通过网页也能实现大部分的服务，但这种量变的影响很可能带来质变的反应。一旦成功，那微信将成为一切服务的入口</p><h3 id="线上入口在哪里"><a href="#线上入口在哪里" class="headerlink" title="线上入口在哪里"></a>线上入口在哪里</h3><p>官方的说法是仅提供有限的搜索和消息转发，结合小程序注册要求的命名推荐和唯一性要求，应该可以确定小程序搜索逻辑将和目前公众号的搜索区别不大。微信只提供运行的环境，用户应该由服务商自己去搞定。而且以小程序用完即走的目标，不急着用服务的用户根本不应该被打扰，所以干脆连分享到朋友圈的口子都不开。</p><p>我挺喜欢这个逻辑，简单又粗暴，微信从技术的角度也只能做到如此。只是等到1月9号开闸之后，一定有无数的公众号开始发布小程序的推荐和榜单，因为还有二维码这个口子在，朋友圈也难逃轰炸。</p><p>当用户使用过小程序之后，会有一个地方存放它们的图标，可以通过它们再次使用。而且这次安卓用户有特别的福利，如果你喜欢一个小程序，可以为它建立桌面图标，像普通应用一样运行。</p><p>对于这一点我倒是持保留意见，这增加了不同平台体验的差异，而且对小程序用完即走的精神是个反面的引导。</p><h2 id="什么样的小程序是好程序"><a href="#什么样的小程序是好程序" class="headerlink" title="什么样的小程序是好程序"></a>什么样的小程序是好程序</h2><p>任何对开发小程序有兴趣的公司或机构都应该先阅读这篇<a href="https://mp.weixin.qq.com/debug/wxadoc/product/index.html" target="_blank" rel="noopener">微信小程序平台运营规范</a>，有空的话再去看看张小龙这两届公开课上的演讲。我提炼后的大白话是只要<strong>能立即给用户带来价值的服务</strong>，关键字是<strong>立即</strong>和<strong>价值</strong>。</p><p>微信努力把小程序做到小而迅速，就是为了让用户能直达目标，所以<strong>应该努力避免让用户在小程序里做选择，而将这个过程前移，让用户看到二维码或链接名称的时候就知道将得到什么</strong>，经典的榜样是二维码支付。用户进入小程序后，最好在一两个页面内解决问题（原则上就不允许你超过5个页面），然后赶紧离开（每个页面都强制增加了关闭按钮）。</p><p>小程序发布前必须提交微信审核，提审时要求开发者选择一个类目。目前小程序类目的开放非常有限（<a href="http://www.wxapp-union.com/article-811-1.html" target="_blank" rel="noopener">参考</a>），而且审核非常严格，一旦不符就可能耽误近一周的审核时间（我的亲历）。还有，小程序最多圈定5个类目，这个范围每个月才允许修改一次。最近看到一些同学开发了不少社区类的小程序，我没有找到对应的类目，不知道到时候上不了线是怎样一种心情。</p><p>从诸多的限制上看，微信对于小程序的开发秉持了异常谨慎的态度。小程序的类目未来一定会逐渐开放，但现在不欢迎的东西以后也不会欢迎，很多厂商现在就可以死心了。</p><h2 id="适合小程序的业务场景"><a href="#适合小程序的业务场景" class="headerlink" title="适合小程序的业务场景"></a>适合小程序的业务场景</h2><p>首先繁荣的是将会是线下，一切你需要信息、服务、联接的场景的都可能有小程序需求，无脑列举一批</p><ul><li>生活、交通、旅游、餐饮类信息与服务获取（当你需要的时候，身边可能就有二维码）</li><li>医务、政务、商务的指引和办理（以前微信内的城市服务，很可能会被导出）</li><li>企业自己的办公小程序，家庭自己的内务小程序</li><li>智能硬件的控制类小程序，甚至任何商品上可能有服务类小程序（没准这才是物联网的第一阶段）</li></ul><p>线上入口更多会集中资讯、电商、工具类，我个人特别期待在教育类方向会出现一些新创新。</p><h2 id="小程序的未来"><a href="#小程序的未来" class="headerlink" title="小程序的未来"></a>小程序的未来</h2><p>距离小程序发布还有10来天，目前舆论的声音都是欣喜多于担忧，跌了好久的腾讯股票也在公开课后抬头。但就如我之前的结论：短期内小程序对于微信的价值大于企业，它的设计目标偏重用户单向索取服务，对于的收费服务这是利好，对于占大头的免费服务，却看得见用户摸不着钱包。如何满足这类企业的胃口，是微信下一个课题。</p><p>根据后续的反馈，小程序未来肯定会开放更多的类目，也有可能向个人开发者开放。我最期待的是增加盈利的途径，如广点通、捐赠，喂饱了开发者的平台才是好平台。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;今年的互联网媒体们可能不太容易，大行业不景气，风投退缩，巨头抱团，新概念泡沫，没什么话题好挖掘。9月，微信宣布小程序的概念，开始内测，媒体们仿佛鲨鱼闻到血，东西还没看见就炸开了锅，漫天评论：“微信要成操作系统了”、“没必要再开发APP了”、“H5要一统天下了”……&lt;/p&gt;

      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="小程序" scheme="http://cpiz.com/tag/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
    
      <category term="微信" scheme="http://cpiz.com/tag/%E5%BE%AE%E4%BF%A1/"/>
    
  </entry>
  
  <entry>
    <title>使用IDEA单步调试LeanCloud云引擎服务（Java）</title>
    <link href="http://cpiz.com/2016/12/16/%E4%BD%BF%E7%94%A8IDEA%E5%8D%95%E6%AD%A5%E8%B0%83%E8%AF%95Leancloud%E4%BA%91%E5%BC%95%E6%93%8E%E6%9C%8D%E5%8A%A1/"/>
    <id>http://cpiz.com/2016/12/16/使用IDEA单步调试Leancloud云引擎服务/</id>
    <published>2016-12-15T16:19:00.000Z</published>
    <updated>2018-05-24T06:48:43.399Z</updated>
    
    <content type="html"><![CDATA[<p>最近在使用LeanCloud的云引擎服务，我使用了Java版SDK，在IDEA中进行项目开发（实际上写的是Kotlin语言）。LeanCloud云引擎提供了一个<code>lean.exe</code>的命令行工具，使用<code>lean up</code>命令可以启动一个http服务，非常方便本地测试。代码修改后使用IDEA重新编译一下即可热更新，不用重新执行命令。</p><p>如果业务复杂一些，可能需要加点日志来调查。但如果想跟进一步直接用IDEA单步调试，找遍了它们文档和社区都没有方法，也没有其他的网友分享过，所以今天研究了一下。</p><p>因为LeanCloud的Java版运行的是一个Jetty服务，我先尝试不用lean命令行，自己在IDEA中配置了Jetty来运行。结果是能显示Web页，但真正想要调试的API接口都返回404。</p><p>研究了一下lean.exe的工作方式，发现它执行lean up后，该进程自己启动了3001端口，提供了一个快速调用API的web页。真正的云业务页面和API服务是它调用<code>mvn jetty:run</code>来运行的，默认是3000端口。而maven是用的开发者自己配置的路径，实际上执行的<code>mvn.cmd jetty:run</code>启用了一串如下java命令：</p><figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"D:\Program Files\Java\jdk1.<span class="number">8</span>.<span class="number">0</span>_92\bin\java.exe" -classpath "d:\work\maven\bin\..\boot\plexus-classworlds-<span class="number">2</span>.<span class="number">5</span>.<span class="number">2</span>.jar" "-Dclassworlds.conf=d:\work\maven\bin\..\bin\m2.conf" "-Dmaven.home=d:\work\maven\bin\.." "-Dmaven.multiModuleProjectDirectory=D:\svnwork\playground\loanassistant-cloud" org.codehaus.plexus.classworlds.launcher.Launcher jetty:run</span><br></pre></td></tr></table></figure><p>分析到这里就有办法了：<strong>java是可以通过参数开启远程调试的，只要把java的调试参数配置在<code>mvn.cmd</code>中，应该就可以调试真正的业务接口了</strong>。</p><p>打开<code>mvn.cmd</code>文件，其中这行是真正的执行语句</p><figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">%MAVEN_JAVA_EXE%</span> <span class="variable">%JVM_CONFIG_MAVEN_PROPS%</span> <span class="variable">%MAVEN_OPTS%</span> <span class="variable">%MAVEN_DEBUG_OPTS%</span> -classpath <span class="variable">%CLASSWORLDS_JAR%</span> "-Dclassworlds.conf=<span class="variable">%M2_HOME%</span>\bin\m2.conf" "-Dmaven.home=<span class="variable">%M2_HOME%</span>" "-Dmaven.multiModuleProjectDirectory=<span class="variable">%MAVEN_PROJECTBASEDIR%</span>" <span class="variable">%CLASSWORLDS_LAUNCHER%</span> <span class="variable">%MAVEN_CMD_LINE_ARGS%</span></span><br></pre></td></tr></table></figure><p>在其上增加一条java调试参数<code>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005</code>然后加入命令行中</p><figure class="highlight bat"><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"><span class="built_in">set</span> EXT_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=<span class="number">5005</span>"</span><br><span class="line"></span><br><span class="line"><span class="variable">%MAVEN_JAVA_EXE%</span> <span class="variable">%JVM_CONFIG_MAVEN_PROPS%</span> <span class="variable">%MAVEN_OPTS%</span> <span class="variable">%MAVEN_DEBUG_OPTS%</span> -classpath <span class="variable">%CLASSWORLDS_JAR%</span> "-Dclassworlds.conf=<span class="variable">%M2_HOME%</span>\bin\m2.conf" "-Dmaven.home=<span class="variable">%M2_HOME%</span>" "-Dmaven.multiModuleProjectDirectory=<span class="variable">%MAVEN_PROJECTBASEDIR%</span>" <span class="variable">%EXT_OPTS%</span> <span class="variable">%CLASSWORLDS_LAUNCHER%</span> <span class="variable">%MAVEN_CMD_LINE_ARGS%</span></span><br></pre></td></tr></table></figure><p>大功告成</p><p>这时候运行<code>lean up</code>发现多了一行提示，表示已经打开了<code>5005</code>端口用于调试java<br><img src="/2016/12/16/使用IDEA单步调试Leancloud云引擎服务/00-47-20.jpg"></p><p>接下来在IDEA中增加Run Remote的配置，其默认的参数即是<code>5005</code>端口<br><img src="/2016/12/16/使用IDEA单步调试Leancloud云引擎服务/00-50-03.jpg"><br>运行刚才的配置<br><img src="/2016/12/16/使用IDEA单步调试Leancloud云引擎服务/00-51-13.jpg"><br>在想要调试的函数中加个断点，通过<code>http://localhost:3001</code>页面测试调用<br><img src="/2016/12/16/使用IDEA单步调试Leancloud云引擎服务/00-53-00.jpg"><br>断点成功，舒服了！</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;最近在使用LeanCloud的云引擎服务，我使用了Java版SDK，在IDEA中进行项目开发（实际上写的是Kotlin语言）。LeanCloud云引擎提供了一个&lt;code&gt;lean.exe&lt;/code&gt;的命令行工具，使用&lt;code&gt;lean up&lt;/code&gt;命令可以启动一
      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="IDEA" scheme="http://cpiz.com/tag/IDEA/"/>
    
      <category term="LeanCloud" scheme="http://cpiz.com/tag/LeanCloud/"/>
    
  </entry>
  
  <entry>
    <title>使用Kotlin语言写LeanCloud云后台服务</title>
    <link href="http://cpiz.com/2016/12/15/%E4%BD%BF%E7%94%A8Kotlin%E8%AF%AD%E8%A8%80%E5%86%99Leancloud%E4%BA%91%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1/"/>
    <id>http://cpiz.com/2016/12/15/使用Kotlin语言写Leancloud云后台服务/</id>
    <published>2016-12-15T15:53:00.000Z</published>
    <updated>2018-05-24T06:49:03.149Z</updated>
    
    <content type="html"><![CDATA[<p>最近在玩微信小程序，有一部分业务需要部署后端，为了省事我选择了LeanCloud。它有多种语言支持，文档也很完善，能快速搭建服务，正好合适。其后端云引擎支持Node.js、Python、Java、Php四种语言，因为我近来写Android多一些，所以采用了更熟悉的Java。</p><p>下载了SDK来一看，是基于maven构建，用法挺简单。但我的云服务需要用到的一个算法是我以前在Android上用Kotlin写的，为了避免重新翻译，我尝试将Kotlin也引入云引擎项目，果然可行。在这记录分享一下。</p><p>整个修改分为三步</p><h2 id="1-pom配置"><a href="#1-pom配置" class="headerlink" title="1. pom配置"></a>1. pom配置</h2><p>增加kotlin的依赖与maven-plugin的配置<br><figure class="highlight xml"><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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">    ...</span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        ...</span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.jetbrains.kotlin<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>kotlin-stdlib<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        ...</span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            ...</span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.jetbrains.kotlin<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>kotlin-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">id</span>&gt;</span>compile<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goals</span>&gt;</span> <span class="tag">&lt;<span class="name">goal</span>&gt;</span>compile<span class="tag">&lt;/<span class="name">goal</span>&gt;</span> <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">sourceDirs</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">sourceDir</span>&gt;</span>$&#123;project.basedir&#125;/src/main/kotlin<span class="tag">&lt;/<span class="name">sourceDir</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">sourceDirs</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">id</span>&gt;</span>test-compile<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goals</span>&gt;</span> <span class="tag">&lt;<span class="name">goal</span>&gt;</span>test-compile<span class="tag">&lt;/<span class="name">goal</span>&gt;</span> <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">sourceDirs</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">sourceDir</span>&gt;</span>$&#123;project.basedir&#125;/src/test/kotlin<span class="tag">&lt;/<span class="name">sourceDir</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">sourceDirs</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">            ...</span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure></p><p>所以工程的文件结构是这样的<br><img src="/2016/12/15/使用Kotlin语言写Leancloud云后台服务/1.png"></p><h2 id="2-翻译AppInitListener类为Kotlin语言版"><a href="#2-翻译AppInitListener类为Kotlin语言版" class="headerlink" title="2. 翻译AppInitListener类为Kotlin语言版"></a>2. 翻译AppInitListener类为Kotlin语言版</h2><figure class="highlight kotlin"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.cpiz.loanassistant.cloud</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cn.LeanCloud.LeanEngine</span><br><span class="line"><span class="keyword">import</span> com.avos.avoscloud.AVOSCloud</span><br><span class="line"><span class="keyword">import</span> com.avos.avoscloud.<span class="keyword">internal</span>.impl.JavaRequestSignImplementation</span><br><span class="line"><span class="keyword">import</span> org.apache.logging.log4j.LogManager</span><br><span class="line"><span class="keyword">import</span> javax.servlet.ServletContextEvent</span><br><span class="line"><span class="keyword">import</span> javax.servlet.ServletContextListener</span><br><span class="line"><span class="keyword">import</span> javax.servlet.<span class="keyword">annotation</span>.WebListener</span><br><span class="line"></span><br><span class="line"><span class="meta">@WebListener</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AppInitListener</span> : <span class="type">ServletContextListener &#123;</span></span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">val</span> appId = System.getenv(<span class="string">"LeanCloud_APP_ID"</span>)</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">val</span> appKey = System.getenv(<span class="string">"LeanCloud_APP_KEY"</span>)</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">val</span> appMasterKey = System.getenv(<span class="string">"LeanCloud_APP_MASTER_KEY"</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">override</span> <span class="function"><span class="keyword">fun</span> <span class="title">contextDestroyed</span><span class="params">(arg0: <span class="type">ServletContextEvent</span>)</span></span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">override</span> <span class="function"><span class="keyword">fun</span> <span class="title">contextInitialized</span><span class="params">(arg0: <span class="type">ServletContextEvent</span>)</span></span> &#123;</span><br><span class="line">        logger.info(<span class="string">"LeanEngine app init."</span>)</span><br><span class="line">        logger.info(<span class="string">"Environment: <span class="subst">$&#123;System.getenv("LeanCloud_APP_ENV")&#125;</span>"</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 初始化AVOSCloud，请保证在整个项目中间只初始化一次</span></span><br><span class="line">        LeanEngine.initialize(appId, appKey, appMasterKey)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 在请求签名中使用masterKey以激活云代码的最高权限</span></span><br><span class="line">        JavaRequestSignImplementation.instance().setUseMasterKey(<span class="literal">true</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 向云引擎注册云函数</span></span><br><span class="line">        <span class="comment">// com.cpiz.loanassistant.cloud.CloudKt即为云函数的实现</span></span><br><span class="line">        LeanEngine.register(Class.forName(<span class="string">"com.cpiz.loanassistant.cloud.CloudKt"</span>))</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (System.getenv(<span class="string">"LeanCloud_APP_ENV"</span>) == <span class="string">"development"</span>) &#123;</span><br><span class="line">            <span class="comment">// 打开 debug 日志</span></span><br><span class="line">            AVOSCloud.setDebugLogEnabled(<span class="literal">true</span>)</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 如果是开发环境，则设置 AVCloud.callFunction 和 AVCloud.rpcFunction 调用本地云函数实现</span></span><br><span class="line">            <span class="comment">// 如果需要本地开发时调用云端云函数实现，则注释掉下面语句。</span></span><br><span class="line">            LeanEngine.setLocalEngineCallEnabled(<span class="literal">true</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">companion</span> <span class="keyword">object</span> &#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">val</span> logger = LogManager.getLogger(AppInitListener::<span class="class"><span class="keyword">class</span>.<span class="title">java</span>)</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-开始使用Kotlin写云函数"><a href="#3-开始使用Kotlin写云函数" class="headerlink" title="3. 开始使用Kotlin写云函数"></a>3. 开始使用Kotlin写云函数</h2><figure class="highlight kotlin"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.cpiz.loanassistant.cloud</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> cn.LeanCloud.EngineFunction</span><br><span class="line"><span class="keyword">import</span> cn.LeanCloud.EngineFunctionParam</span><br><span class="line"><span class="keyword">import</span> ......</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 class="meta">@EngineFunction</span></span><br><span class="line"><span class="function"><span class="keyword">fun</span> <span class="title">hello</span><span class="params">()</span></span>: String &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">"Hello world!"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>至此结束，原本的目的只是想让算法那部分直接用Kotlin的实现，但最终做到了使用Kotlin编写整个项目，开发效率可比Java高多了。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;最近在玩微信小程序，有一部分业务需要部署后端，为了省事我选择了LeanCloud。它有多种语言支持，文档也很完善，能快速搭建服务，正好合适。其后端云引擎支持Node.js、Python、Java、Php四种语言，因为我近来写Android多一些，所以采用了更熟悉的Java。
      
    
    </summary>
    
      <category term="技术" scheme="http://cpiz.com/category/%E6%8A%80%E6%9C%AF/"/>
    
    
      <category term="LeanCloud" scheme="http://cpiz.com/tag/LeanCloud/"/>
    
      <category term="Kotlin" scheme="http://cpiz.com/tag/Kotlin/"/>
    
  </entry>
  
  <entry>
    <title>博客迁移至Farbox平台</title>
    <link href="http://cpiz.com/2016/12/15/moved_to_farbox/"/>
    <id>http://cpiz.com/2016/12/15/moved_to_farbox/</id>
    <published>2016-12-15T11:49:00.000Z</published>
    <updated>2018-05-24T07:30:56.279Z</updated>
    
    <content type="html"><![CDATA[<p>最近几年，空闲的时间越来越少，已经很少再写博客，只是偶然会翻起。从2005至2016，12年一晃而过，因为有博客，那些记忆和心情还冻结在那里，仿佛是昨天。</p><p>玩了十二年博客，它曾经属于微软（MsnSpace）、Google（Blogger），然后是自己搭的PJBlog、Wordpress，我从一个充满好奇跃跃欲试的青年，终于变成了一个仍然好奇但再无法在时间上奢侈的中年。我不想再要什么模板、动态、图片，能安安静静想点东西，趁它们没那么快健忘，来得及记录就好。所以越来越喜欢Markdown，可以让人先把东西写下来，再去管格式。</p><p>最近突然想重新开始记录，不愿意再面对WP那个愚蠢的编辑器，又舍不得以前那么多老文章，发现Farbox迁移成本最低。虽然丢失了评论，一些文章的图片和下载有问题，但没关系，最宝贵的是文字。</p><p>Farbox肯定也不是折腾的终点，我大胆的预测一下：未来的互联网，不管用户使用了哪公司的服务，用户创造的内容是会永远跟随他自己的。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;最近几年，空闲的时间越来越少，已经很少再写博客，只是偶然会翻起。从2005至2016，12年一晃而过，因为有博客，那些记忆和心情还冻结在那里，仿佛是昨天。&lt;/p&gt;
&lt;p&gt;玩了十二年博客，它曾经属于微软（MsnSpace）、Google（Blogger），然后是自己搭的PJB
      
    
    </summary>
    
      <category term="建站" scheme="http://cpiz.com/category/%E5%BB%BA%E7%AB%99/"/>
    
    
      <category term="博客" scheme="http://cpiz.com/tag/%E5%8D%9A%E5%AE%A2/"/>
    
      <category term="建站" scheme="http://cpiz.com/tag/%E5%BB%BA%E7%AB%99/"/>
    
  </entry>
  
  <entry>
    <title>菜鸟追车记，3个月尊瑞驾驶感受</title>
    <link href="http://cpiz.com/2014/01/29/%E8%8F%9C%E9%B8%9F%E8%BF%BD%E8%BD%A6%E8%AE%B0%EF%BC%8C3%E4%B8%AA%E6%9C%88%E5%B0%8A%E7%91%9E%E9%A9%BE%E9%A9%B6%E6%84%9F%E5%8F%97/"/>
    <id>http://cpiz.com/2014/01/29/菜鸟追车记，3个月尊瑞驾驶感受/</id>
    <published>2014-01-29T15:32:34.000Z</published>
    <updated>2018-05-25T12:22:13.670Z</updated>
    
    <content type="html"><![CDATA[<p>这是我投在汽车之家的作业贴，应该算是13年唯一比较正式的一篇东西，贴到博客上来保存记录</p><h1 id="立念"><a href="#立念" class="headerlink" title="立念"></a><strong>立念</strong></h1><p>按家乡风俗，男人通常在逢九那年过大生日，我生于八四零九，日前已三十而立。在生日的前一个月，我收获了人生的第一部车——凯美瑞尊瑞2.5HG。这是份宝贵的大礼，抢在了下一代还没落地之前，给生活注入了新的激情和色彩。</p><p>身为一个理工宅，在28岁之前对汽车没一点追求，这让一毕业就拿了驾照的老婆觉得很奇怪，笑我“兴（趣）取向”不正常。我在回忆里搜索了一下，这大概和我儿时强烈的晕车毛病有关，也受到了身边因车祸而改变了人生的两个亲友的影响，玩赛车游戏我可以热血沸腾，拥有一辆的想法却被束之高阁，总觉着很遥远。</p><p>明日复明日，毕业了、结婚了、买房了，房子和我公司的路程才十五分钟，而我和我老婆的公司才相距不到百米，在别人挤公交挤地铁各自发誓一定要买车不再受气的时候，我俩天天牵手上下班，再远点的距离就租个免费自行车好不悠哉。</p><p>可在大城市，人不可能在一家公司干一生，公司也不可能在一栋楼租到永远，度过了两年我认为人生最自在的时光后，空间的问题终于开始困扰我们。</p><p>我换了更好的单位，依旧十五分钟路程，但必须得两轮。朝暮骑行身影虽矫健，也难免风雨里狼狈。坐公交？可惜走三趟转两道反而时间数倍。</p><p>老婆单位也将要换更好的大楼，依旧十五分钟路程，还得四轮才行……趁没搬离，有时我下班绕来载她，自以为甜蜜蜜，直到一天大概是将她颠坏，说“我不想三十岁了还坐自行车后座”，将我一厢情愿打碎。</p><p>好好想了想，是该买个车了，方便接送老婆，以后还会有孩子，父母来广州玩也不用再带他们转公交钻地铁。对自己而言，车是腿的延伸，从此广州不是只有天河体育中心一个商圈，一天内广佛东深随便来回，一个周末便能享受广东大部分的景点。</p><h1 id="学车"><a href="#学车" class="headerlink" title="学车"></a><strong>学车</strong></h1><p>等产生买车的念头，早已过了最佳学车的时机。如果当年读大学时花愿意两千块和一个星期，如果刚来广州时愿意花四千块和三个月，怎会沦到当下要花六千块加近一年的繁琐。</p><p>去年10月，通过朋友的推荐，找到一位好教练，愿意认真地教授车内车外各种知识。只是因为工作紧张，只有周末有空闲，平时都到凌晨两点多才睡，周六早晨7点半起床实在苦不堪言，迷迷糊糊的脑子用一杯咖啡浇醒，车子怎么起步都得回忆半天。</p><p>幸好手脑还算灵光，理工男品质也发挥出来，很快喜欢上操控这种四轮机械的感觉，开始希望能拥有一台自己的车。只是学车靠自己，排考靠大家，每训练好一个环节，后面都是一两个月的等待，只能心里干灼急……</p><h1 id="摇号，选车"><a href="#摇号，选车" class="headerlink" title="摇号，选车"></a><strong>摇号，选车</strong></h1><p>广州从去年7月份开始限购，从路人到车主的路上，拦在面前的除了驾照，还有指标书一张。报名学车的同时，我用老婆的驾照申请了摇号，估摸着按当时1/16的概率，只要运气不是太差，等我拿到驾照之后，指标也应该到手了。</p><p>老天开了一个善意的玩笑，只用了3个月我们就获得了指标，13年8月26号之前必须购车。这结果让我们哭笑不得，太早买的话用不着（后来证明这想法是太Simple了），放弃的话老婆两年内不能再参加摇号，等我自己的驾照出来再摇不知得等到猴年马月了。</p><p>好，那就开始选车。</p><p>最初想主要用于日常代步，节假出游，又是新手，买个十五六万的A级车差不多了，过几年再换更好的。向身边有车的朋友征求建议，结果几乎所有人都推荐一步到位上B级车。其中有一个理由动摇了我：反正早晚是要升级，就是差个几万块钱，但一年后宽裕了再想换车到时候肯定舍不得，开几年再换又心理不甘，而且当时还有换车后排量能降不能升的担忧。最后老婆鼓励了一下：”买个好点的吧，30w以内都可以，当作给你30岁的生日礼物“，遂美滋滋更换目标。</p><p>当时我对汽车的了解仅限于认识车标，这才开始泡汽车之家、新车评，恶补知识。在学车的同时，也开始了漫长反复的看车之路。</p><p>我们初定的筛选的标准：</p><blockquote><p>落地30W以内，尽量别太贵</p><p>只在城市活动，相比SUV，更倾向轿车</p><p>不考虑韩国品牌，缺乏信心</p><p>不考虑国产品牌，缺乏信心</p><p>尽量非日本品牌，我不仇日，但怕仇日的愤怒青年<br>以上无论如何，车必须有亮点，可以是最帅、最精致、性能最好、最经济、最有科技感……总之拒绝平庸。</p></blockquote><p>实际证明，选车过程很难做到完全理性，也没有完美的车，最后的结果往往偏离预期很大。这其中，就留给了汽车软文、广告、销售人员很大的影响空间。</p><p>最开始，我看中了朋友推荐的新蒙迪欧。当时只有图片可看，一眼就被它潇洒的线条所吸引，还有那犀利的大灯，憨憨的大嘴。接着看了新车评关于老蒙的视频与文章，知道机械性能也很强大，符合理工宅要求。决定将看车的处女行献给福特，先看看老蒙情况，也打听打听新蒙消息。找了一个周末下午来到黄埔大道东的翰福，可能我们穿着太屌丝（我平常都是T恤短裤拖鞋、老婆每天双肩包牛仔裤），完全没工作人员来搭理。转了一圈展厅没见老蒙，只好主动咨询销售，感觉不是很热情，在我表露出对新蒙有意后也没想着主动建立联系，而且一问三不知。好，那等有新消息再来。</p><p>相信朋友们都有经历，伴随买车的念头从无到有，人走在路上，也有一个从对汽车毫不在意到念念不忘的变化。以前那些看起来都差不多的铁壳盖轮子，一下变成了缤纷的奥迪、丰田、现代、小型车、中型车、SUV……，人也会开始去记忆车的品牌和型号。某天骑行路上，看见个好漂亮的SUV屁股，只记住了本田和一个单词Cross。后来查到它叫歌诗图(Crosstour)，也不是SUV，是介于SUV和轿车的旅行车。找个周末拉上老婆逛本田4S，不等我指引，她也瞬间被这车所吸引，我也是第一次近距离感受它。这车前脸大气、后尾性感、拉丝内饰精致、座舱和后尾空间都超赞，完全给人一个豪华车的感觉，竟然只卖26w。原来对日本车的那份担心，在如此的触手可及面前立即变得薄如轻烟，而且瞬间找好了理由：广州是日本车的大本营（广丰、广本），而且广州素来开放，没那么容易有事的……（节操啊）</p><p>新蒙有了对手，我的心思也活了起来：既然不再介意日本车，那再考虑考虑尊瑞？尊瑞首次印象是去年年底在电梯里看到的广告，而且内容还全都记得，百分百中签、厂家优惠3w、政府还补贴1w，省油环保而且还堪比3.0发动机的动力，这车有这么神？一了解真吃了一惊，这是新车评网史上评价最高的长测车，丰田的混合动力技术已经经过国外市场检验可以不用担心，电池也给8年20w公里保修，而且广州有全国最高的3.6w优惠加1w政府补贴，太有诱惑力了。瞬间我又找到了放弃歌诗图的理由：太长太宽不适合我新手，而且车重油耗高……（节操）</p><p>中间还关注了一阵迈腾，为它的精致内饰和空间所倾倒，不过315曝光DSG问题后大众大事化小小事化了的表现让我觉得很不放心，不敢考虑。</p><h1 id="购车"><a href="#购车" class="headerlink" title="购车"></a><strong>购车</strong></h1><p>五月份时候，在另一家福特4S得到新蒙七月份即将上市的消息，出于对老蒙的信心和新车配额与指标期限的担忧，在没见过样车甚至不知道定价的情况下，我预定了新蒙200P豪华版（协议要求必须保证七月份提车否则全额退订金），开始天天在之家新蒙版块守望。不知是因为水军多还是脑残太多，新蒙论坛每天乌烟瘴气，各种口水谩骂，偶尔出几个理性分析的帖子也被黑成车托，最后导致了回帖必须附上一段“车托全家火葬场”的诅咒才能证明自身清白。偶尔到凯美瑞版块潜水倒是一片和谐，搜索关键字“故障”找到的结果也不算多，尊瑞更是一片赞声。考虑到新蒙跳票的风险，将尊瑞作为备胎倒是一个不错的选择，起码它是广州生产、货源充足，订车不用等太久而导致指标过期。</p><p>期间又反复读了新车评的尊瑞长测，也更多的了解了能量回收、动力策略还有ECVT变速箱的工作原理，越发觉得精妙，在真正的新能源技术还遥遥无期的情况下，丰田这套混动的机理简直就是唯一正确的设计！抽空去丰田4S看了展车，虽然感觉外观实在没个性，但对它的内饰和空间都非常满意，很喜欢那仿碳纤维面板的材质颜色（相比普凯的桃木风格则完全不能接受）。销售蔡M的表现非常专业，很干脆地解答了我们所有疑惑，包括优惠、能否享受政府补贴、提车时间、贷款方案，回家后我们正式确定将尊瑞HG列为第一备胎。</p><p>不知是不幸还是有幸，新蒙上市的时间果然越推越迟，销售终于打电话通知我正式提车时间为八月底，我是第一批，但这个结果已毫无意义。</p><p>新蒙无缘，只好买尊瑞了！7月6号，再次来到丰田第一店，参照网友们的购车价格，很快谈到尊瑞HG珍珠白加装4S的那套科技版套装（包括导航、CMMB电视、液晶头枕、日行灯、座椅通风、中置喇叭、后视镜自动翻转折叠）、人保保险、送贴膜抱枕地毯方向盘锁，最终含政府补贴落地价25.4w（后来还是发现亏了先不表），销售承诺一个月内到车。</p><p>以上，终于完成了我的选车之路，而整个过程，我因为一直没拿到驾照，只能试乘，未能试驾过任何一辆。</p><h1 id="提车"><a href="#提车" class="headerlink" title="提车"></a><strong>提车</strong></h1><p>7月31号终于等来了电话，通知我8月2号可以提车，而这一天，正好是我驾考最后一个科目以及发证的时间，这不得不说是一个奇妙的巧合。就这样，我上午去车管所考安全文明、宣誓、领证，随后打车到4S见我爱车第一面。</p><p>一店的车库原来是在麦德龙停车场的最顶层，停满了新车，我那辆就静静地趴在那，那么普通，那么特别。蔡M给了钥匙让我验车，我一驾照还没揣热的人又紧张又懵懂，只知道一定不能松驻刹不能乱挂档，手忙脚乱搞一通加上车子暴晒一上午炎热无比很快就满身大汗的出来了。</p><p>回到店里交好尾款，理论上这车已经完全归我，可以当天开走。考虑到对新车不熟悉，办牌手续和加装配置没有完成，还是留在了店里。</p><p>8月12号，应4S安排跟一批丰田新车主到水荫路车管所集体办牌，尝试N次后选了一个对自己有意义的牌号。</p><p>8月14号，4S来电通知自选的配置已加装完毕，终于可以正式提车！约了朋友翘班来帮忙，刚好赶上台风，匆匆到店后销售给给了一叠文件讲了一堆东西也没太听进去，没有很激动，只是感觉不太真实，就这样我就车主了？</p><p>车开回家后我两天没敢动，等到周末才把朋友再约出来带我练练。好在驾校还是学了点东西，很快就顺手了。</p><h1 id="用车感受"><a href="#用车感受" class="headerlink" title="用车感受"></a><strong>用车感受</strong></h1><p>不知不觉尊瑞已经开了三个多月，期间上下班通勤、周末出游、国庆来回一趟江西老家，目前里程将近5000公里，刚做完了首保。这篇作业也拖拖拉拉写了两个多月，因为各种原因和借口一直没有提交。这里再结合我一个菜鸟司机的成长历程，写一点尊瑞感受：</p><p>最深刻的感受是安逸，这一点不得不夸。</p><p>坛子里有朋友发过各种算法：一年要开多少公里，多少年后能把尊瑞相比普凯的溢价赚回来。买车前我也结合自己的情况计算过，但开过一段时间后，发现这个念头完全可以抛开。混合动力是比普凯省油，但这个省油不是冷冰冰的数字，而是相比其他2.5L的汽油车主来说完全不一样的轻松心情。</p><p>咱这个收入级别的人，身边朋友也大都开30w以内的车，油耗免不了是日常的话题之一，君不见每次油价调整都会激起Q群里大片的讨论。相比起其他车友的敏感，尊瑞车主确实淡定很多。就算不谈油价，每个月少去一次加油站排队也省心不少。</p><p>尊瑞的仪表设计其实很有心机，取消了发动机转速表，却有中控动力示意图、行车电脑小屏、右侧的油耗表、左测的动力表至少4个地方全方位暗示你我在省油我很省油，到达目的地后还发一朵“燃油经济性优”的小红花鼓励，就差学360再提示一个“你的油耗打败了全国XX%车主”。在这种暗示下，新车主都会经过一个改善驾驶习惯挑战极限油耗的“自我培训”过程，一段时间后新鲜劲过了可能不再理会，但这时候已经建立起了对尊瑞省油能力的信任，同时养成了对油耗完全不在乎的心态。这种心态带给我的是想去哪就去哪的自由，没事也愿意去阅江路兜个风散散步，走错路也毫无负担。</p><p>省油还好说，而尊瑞纯电动行驶时的安静却是不好形容。汽车发明了一百多年，我们对它的印象就是应该嗡嗡作响，性能跑车们甚至以此为荣，突然遇到一辆光滑行不出声的车，这种感觉是很新鲜的，每一个初次试驾我车的朋友都会疑问：”这真的启动了？“，当我习惯了这种设定之后，很快感受到它带来的好处。</p><p>路上堵车、等红灯，车窗外其他的车嗡嗡颤抖，尊瑞却悄悄熄了火，安逸。前车一动则悄然起步，从容。</p><p>小区路窄，行人背后尊瑞静静跟随，也许是自我陶醉，总觉得路人惊觉后瞥来的目光里带着温暖。没它之前，我也做了近30年路人，也希望多遇到点这样的车治愈一下惊吓过的心灵。</p><p>驾驶尊瑞，我愿意做个好司机，我文明礼让，你低碳环保。</p><h2 id="无图无真相"><a href="#无图无真相" class="headerlink" title="无图无真相"></a>无图无真相</h2><p>尊瑞的外观从开始就感觉平平无奇，买来后看得多了变得稍微顺眼，但仍不算一辆漂亮的车，提不起拍照的欲望。只是偶尔它讨好心情时，用手机记录一张。就喜欢它静静地趴在那里，随时带我去想去的地方。</p><img src="/2014/01/29/菜鸟追车记，3个月尊瑞驾驶感受/500_9968_abd19adc_abd19adc.jpg"><p>到手的第二个周末，它带我去南沙吃海鲜，从此游玩终于不再受限。</p><img src="/2014/01/29/菜鸟追车记，3个月尊瑞驾驶感受/500_9683_efa0873e_efa0873e.jpg"><p>小区车位紧张，一直停在外面，这是第一次带它回家时拍的。</p><img src="/2014/01/29/菜鸟追车记，3个月尊瑞驾驶感受/500_8155_db9f1614_db9f1614.jpg"><p>第一次从这个角度看广州的桥</p><img src="/2014/01/29/菜鸟追车记，3个月尊瑞驾驶感受/500_89d0_3db08c10_3db08c10.jpg"><p>国庆的时候，起个大早，它带我奔行800公里回老家，再也不为买票愁</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这是我投在汽车之家的作业贴，应该算是13年唯一比较正式的一篇东西，贴到博客上来保存记录&lt;/p&gt;
&lt;h1 id=&quot;立念&quot;&gt;&lt;a href=&quot;#立念&quot; class=&quot;headerlink&quot; title=&quot;立念&quot;&gt;&lt;/a&gt;&lt;strong&gt;立念&lt;/strong&gt;&lt;/h1&gt;&lt;p&gt;按家
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="旅行" scheme="http://cpiz.com/tag/%E6%97%85%E8%A1%8C/"/>
    
      <category term="车" scheme="http://cpiz.com/tag/%E8%BD%A6/"/>
    
  </entry>
  
  <entry>
    <title>一把$100的刷子——Clarisonic Mia拆解与修复</title>
    <link href="http://cpiz.com/2013/01/20/%E4%B8%80%E6%8A%8A$100%E7%9A%84%E5%88%B7%E5%AD%90%E2%80%94%E2%80%94Clarisonic%20Mia%E6%8B%86%E8%A7%A3%E4%B8%8E%E4%BF%AE%E5%A4%8D/"/>
    <id>http://cpiz.com/2013/01/20/一把$100的刷子——Clarisonic Mia拆解与修复/</id>
    <published>2013-01-20T09:24:00.000Z</published>
    <updated>2018-05-24T07:04:32.429Z</updated>
    
    <content type="html"><![CDATA[<img src="/2013/01/20/一把$100的刷子——Clarisonic%20Mia拆解与修复/Clarisonic-Mia-lgn.jpg"><p>家里有把叫Clarisonic Mia的刷子，是LP大人花100刀从美帝淘回来的宝贝。这宝贝的毛刷据说能以声波的频率振动，清毛孔去黑头什么什么的就跟橡皮擦一样，手感扎实线条性感全身防水，还是时髦的无线充电技术，LP大人每天刷脸爱不释手。</p><p>好景不长，用了三个月，昨天充电时开始出现约每秒一次的振动，指示灯也不闪，十几个小时之后毫无效果。一搜发现这问题还比较普遍，有的运气好充一会儿就恢复了，有的就此Over。海淘有海淘的风险，Clarisonic不支持全球联保，来回美国一趟又得花去300大洋。</p><p>看着LP大人一脸的不开心，也为了钱包考虑，我尝试着拆解修复一下。可惜找遍国内国外，没有发现任何关于拆解的介绍（果然是女人用的东西），只能硬着头皮上。</p><p>过程记录如下，希望对苦逼的男同胞们有帮助。事后补录，中间忘了拍照。</p><p>——————– 我是撬不开的分割线 ———————</p><p>Clarisonic Mia全身没一个螺钉，从边缝撬了半天纹丝不动，干脆打了个孔。结果发现外壳厚度至少有4mm，前后盖之间是极其完美的粘接。遂改方法为热切割：将美工刀片用燃气烧热，垂直切割边缝一周。完成后仍然无法分离，强行撬开后发现内部还用了多处白色的胶体来粘结。</p><p>所有元件均附着在前盖，头部是两片交叉成X形的簧片，上两端固定，下两端是铁件并连接一根曲柄输出。中部是一个W形的电磁铁，顶部两极与X簧片的铁件隔空对应。刷子的工作原理应该是快速变换电磁铁的两级来驱动簧片左右摆动，最后输出至曲柄连接的刷头。下部是两节串联的白色平头电池，型号为NiMh-AA-2-900-PB3（镍氢！怎么不用锂电？），电池极点是钢焊。</p><p>拆下电池用万用表测量电压才零点几伏，换上一对南孚后刷子又开始嗡嗡工作（试过外接电源，振动频率异常，推测应该是整流不干净），说明机器本身没问题。折腾了一下这一对小白，重新接入，粘上无线充电器，竟然恢复充电了！看来之前应该就是电池过放造成的无法充入。100刀的东西如果是为了安全使用镍氢电池可以理解，但无线充电都用上了，充放保护怎么这么差？</p><p>充电一夜后可以恢复工作，基本判断问题已解决，开始复原。手头上可用的胶水只有热熔枪，先将电池粘牢在电路板，然后用美工刀将前后盖的外缘削出斜面，使两盖合并后接缝呈外宽内窄的沟状，便于胶水深入。再用热熔胶填满一周，最后打磨边缘、削去凸出的胶水。还有之前撕掉了开关处的胶片，重新粘回去。至此——密封应该凑合了吧……最后是这个样子</p><img src="/2013/01/20/一把$100的刷子——Clarisonic%20Mia拆解与修复/2013-02-19-21.42.53-11.jpg"><img src="/2013/01/20/一把$100的刷子——Clarisonic%20Mia拆解与修复/2013-02-19-22.25.27-1.jpg"><img src="/2013/01/20/一把$100的刷子——Clarisonic%20Mia拆解与修复/IMG_0168.jpg"><p>一些后话：</p><ol><li>Clarisonic的外形设计、注塑工艺、表面处理、内部粘焊都是精工细致，无可挑剔</li><li>Clarisonic这种一体化的工艺，压根就没考虑过维修问题，保修只能换新</li><li>女人的钱好赚，就算它如此牛逼的工艺和设计卖$100还是太贵了，￥200差不多</li></ol><p>2013/06/16 update：</p><p>这问题后来又折腾了我两次，其实很好解决，拆开后用个3-5v电源（比如锂电或USB）接触电池对应两极3-5秒进行激活，然后就能正常无线充电了。最后我干脆接了两条引线出来，丑虽丑点，一劳永逸。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;img src=&quot;/2013/01/20/一把$100的刷子——Clarisonic%20Mia拆解与修复/Clarisonic-Mia-lgn.jpg&quot;&gt;
&lt;p&gt;家里有把叫Clarisonic Mia的刷子，是LP大人花100刀从美帝淘回来的宝贝。这宝贝的毛刷据说能以声波的频
      
    
    </summary>
    
      <category term="项目" scheme="http://cpiz.com/category/%E9%A1%B9%E7%9B%AE/"/>
    
    
      <category term="Clarisonic" scheme="http://cpiz.com/tag/Clarisonic/"/>
    
      <category term="DIY" scheme="http://cpiz.com/tag/DIY/"/>
    
      <category term="修理" scheme="http://cpiz.com/tag/%E4%BF%AE%E7%90%86/"/>
    
  </entry>
  
  <entry>
    <title>漂洋过海去看你·沙巴（三）</title>
    <link href="http://cpiz.com/2012/11/05/%E6%BC%82%E6%B4%8B%E8%BF%87%E6%B5%B7%E5%8E%BB%E7%9C%8B%E4%BD%A0%C2%B7%E6%B2%99%E5%B7%B4%EF%BC%88%E4%B8%89%EF%BC%89/"/>
    <id>http://cpiz.com/2012/11/05/漂洋过海去看你·沙巴（三）/</id>
    <published>2012-11-04T16:20:07.000Z</published>
    <updated>2018-05-26T03:44:48.780Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Day-2-亚庇-–-环滩岛"><a href="#Day-2-亚庇-–-环滩岛" class="headerlink" title="Day 2 亚庇 – 环滩岛"></a>Day 2 亚庇 – 环滩岛</h1><p>五点半被闹钟叫醒，开门看天，有戏！</p><p>来到海边，静静等待。<br><img src="http://pic.yupoo.com/cpiz/CnO8lHQd/medium.jpg" alt="日将出"></p><p>地平线上的云层太厚，看不到日出水，只能等日出云了。</p><p><img src="http://pic.yupoo.com/cpiz/CnO8mzIQ/medium.jpg" alt="思考？不，补觉"></p><p>等！</p><p><img src="http://pic.yupoo.com/cpiz/CnO8mNm2/medium.jpg" alt="来了"></p><p>天空被点燃，快来了！</p><p><img src="http://pic.yupoo.com/cpiz/CnO8ohJp/medium.jpg" alt="幸福的码头"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8oK0a/medium.jpg" alt="1/8000快门，最小光圈，相机极限"></p><p>一出生则不可直视。</p><p><img src="http://pic.yupoo.com/cpiz/CojMGA4H/medium.jpg" alt="跳跃"></p><p>太阳底下没有新鲜事，所以有装逼青年↑，也一定会有二逼青年↓</p><p><img src="http://pic.yupoo.com/cpiz/CojNhvC7/medium.jpg" alt="二逼青年"></p><p><img src="http://pic.yupoo.com/cpiz/CojNVujb/medium.jpg" alt="装逼青年"></p><p><img src="http://pic.yupoo.com/cpiz/CojNMH0X/medium.jpg" alt="阳光下走来"></p><p><img src="http://pic.yupoo.com/cpiz/CojOwtFs/medium.jpg" alt="可怜的摄影师"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8piHA/medium.jpg" alt="睡醒了吗？"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8pFNi/medium.jpg" alt="装酷"></p><p>早晨后，5人开始环岛一周的壮举。</p><p><img src="http://pic.yupoo.com/cpiz/Colni1MQ/medium.jpg" alt="123跳"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8qkeq/medium.jpg" alt="大跃进青年"></p><p>环岛一周全是海滩，遇到各种活物死物。无论是何者，和不息的海浪相比都显得无比寂寞，好像怀着无数的故事，在等待愿意倾听且有足够耐心的听众，却不是我们这样的过客。</p><p><img src="http://pic.yupoo.com/cpiz/CnO8qTzl/medium.jpg" alt="携家而行的小蟹"><br>携家而行的勤蟹</p><p><img src="http://pic.yupoo.com/cpiz/CnO8qvLK/medium.jpg" alt="疑似睡着的螃蟹"><br>疑似宿醉的懒蟹</p><p><img src="http://pic.yupoo.com/cpiz/CnO8qRZN/medium.jpg" alt="曾经也是一条好汉"><br>一节巨鱼（鲸？）的脊骨，曾经也是一条好汉</p><p><img src="http://pic.yupoo.com/cpiz/CnO8racJ/medium.jpg" alt="朽木"><br>被小蚌寄生的朽木</p><p>终于，过客们要离开这块净土，返回亚庇。<br><img src="http://pic.yupoo.com/cpiz/ColHTlJb/medium.jpg" alt="再见"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Day-2-亚庇-–-环滩岛&quot;&gt;&lt;a href=&quot;#Day-2-亚庇-–-环滩岛&quot; class=&quot;headerlink&quot; title=&quot;Day 2 亚庇 – 环滩岛&quot;&gt;&lt;/a&gt;Day 2 亚庇 – 环滩岛&lt;/h1&gt;&lt;p&gt;五点半被闹钟叫醒，开门看天，有戏！&lt;/p&gt;

      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="摄影" scheme="http://cpiz.com/tag/%E6%91%84%E5%BD%B1/"/>
    
      <category term="旅行" scheme="http://cpiz.com/tag/%E6%97%85%E8%A1%8C/"/>
    
      <category term="沙巴" scheme="http://cpiz.com/tag/%E6%B2%99%E5%B7%B4/"/>
    
  </entry>
  
  <entry>
    <title>漂洋过海去看你·沙巴（二）</title>
    <link href="http://cpiz.com/2012/11/04/%E6%BC%82%E6%B4%8B%E8%BF%87%E6%B5%B7%E5%8E%BB%E7%9C%8B%E4%BD%A0%C2%B7%E6%B2%99%E5%B7%B4%EF%BC%88%E4%BA%8C%EF%BC%89/"/>
    <id>http://cpiz.com/2012/11/04/漂洋过海去看你·沙巴（二）/</id>
    <published>2012-11-04T14:32:21.000Z</published>
    <updated>2018-05-26T03:45:02.235Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Day-2-亚庇-–-环滩岛"><a href="#Day-2-亚庇-–-环滩岛" class="headerlink" title="Day 2 亚庇 – 环滩岛"></a>Day 2 亚庇 – 环滩岛</h1><p>第二天早早起床第一件事就是看天气，似乎不错。洪叔的小弟7点半钟准时到酒店门口接我们去码头，这时天已大亮，一切完美。<br><img src="http://pic.yupoo.com/cpiz/CnO8c1w2/medium.jpg" alt="码头"></p><p>终于见到了传说中的洪叔，很精神很Nice的一个阿叔。同行的还有另一个11人的朋友团，登上他的快船，以每小时60公里速度开向环滩岛。轰鸣的引擎+迎面的劲风+飞溅的水花+透亮的蓝天+清澈的海水=飞一般的感觉。</p><p><img src="http://pic.yupoo.com/cpiz/CnO8clb8/medium.jpg" alt="抵达环滩岛"><br>靠近环滩岛的时候因为海水变浅，颜色也由蓝转绿。</p><p>环滩岛正经的名字是Pulau Mengalum（孟加伦岛），距离亚庇56公里，叫环滩岛估计因为全岛地势很低，整个边缘都是海滩的缘故。这是个私人岛屿，据洪叔说岛主正想出售，你要有6000w马币（1.2亿人民币）就可将岛屿和所有设施全部接手，当时我没带那么多钱，想想算了。</p><p><img src="http://pic.yupoo.com/cpiz/CojdB3pD/medium.jpg" alt="登岛后受到冰毛巾与冰橙汁接待"></p><p>登岛后受到冰毛巾和冰橙汁的招待，正是雪中送炭的享受。两个工作人员接过我们的行李，领我们到各自的住所——五个人两栋木屋，实在奢侈。<br><img src="http://pic.yupoo.com/cpiz/CojMXlDb/medium.jpg" alt="木屋小径"><br><img src="http://pic.yupoo.com/cpiz/CnO8oYXP/medium.jpg" alt="晨中木屋"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8cqZz/medium.jpg" alt="岛上木屋，客厅"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8cEis/medium.jpg" alt="房间B"></p><p><img src="http://pic.yupoo.com/cpiz/CojMjUp6/medium.jpg" alt="面朝大海，春暖花开"></p><p>换装完毕，准备第一次浮潜。</p><p><img src="http://pic.yupoo.com/cpiz/CnO8cUtC/medium.jpg" alt="浮潜去"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8dsqb/medium.jpg" alt="LP"></p><p>重新登上洪叔的船，慢慢开到不远的近海，洪叔一手抓缆绳稳稳的站在船头，手搭凉棚查看合适的浮潜地点，用手势通知舵手。到位，抛锚落定。大家戴上浮潜面罩，逐个下水。水深两三米，就像很多次从电视里看到的一样，底部各种奇形怪状的珊瑚礁，穿梭着各种海鱼。我找洪叔要了条饵鱼，在水里慢慢撕碎，很快就有一群聚了上来围绕我转，可惜没有准备水下相机。</p><p><img src="http://pic.yupoo.com/cpiz/CojRCeXk/medium.jpg" alt="浮潜"><br><img src="http://pic.yupoo.com/cpiz/CojRnrPT/medium.jpg" alt="浮潜收获"></p><p>浮潜到后程，因为吞了不少海水，感觉想吐，提前翻上船休息。<br><img src="http://pic.yupoo.com/cpiz/CnO8dCvO/medium.jpg" alt="水手哥"></p><p>回到岛上自助午餐，这时候才注意到，除了几个工作人员，整个岛上才我们十几个游客……除了尝点特色食品外，我的所有精力都用在了咖喱蟹上，直到所有人都放下筷子我还在继续。后来我才知道，什么叫吃海鲜吃到吐……</p><p><img src="http://pic.yupoo.com/cpiz/CojRRkou/medium.jpg" alt="海鲜自助餐"><br><img src="http://pic.yupoo.com/cpiz/CnO8e9Rq/medium.jpg" alt="螃蟹吃到吐啊"></p><p>饱餐后恢复体力的众人开始了一套饭后小清新</p><p><img src="http://pic.yupoo.com/cpiz/CnO8efqO/medium.jpg" alt="饭后小清新"><br><img src="http://pic.yupoo.com/cpiz/CnO8fbOm/medium.jpg" alt="饭后小清新"></p><p>小清新专用二逼摄影师是也↓<br><img src="http://pic.yupoo.com/cpiz/CojDlZv5/medium.jpg" alt="_1080891"></p><p>继续在海边发呆，发现一艘疑似美帝航母的军舰，舷号6，兴奋。</p><p><img src="http://pic.yupoo.com/cpiz/CnO8fZ0L/medium.jpg" alt="美帝？"></p><p>回来后查资料发现这是美帝的黄蜂级两栖登陆攻击舰USS Bonhomme Richard，排水量45000吨，确实很像航母。</p><p>下午继续出浮潜，我游了一会感觉还是晕得不行爬回了船，不过这次没坚持住，哇一声把中午的螃蟹都吐海里了，立刻一大群鱼聚集过来，分享了这顿盛宴……囧rz。</p><p>因为当天是个伊斯兰节日，早市上没买到什么海鲜，洪叔决定出海去钓鱼来补充晚餐，愿意的可以一起跟去，不愿意的可回岛自由活动，我们选择了跟随。洪叔凭经验再加声纳找了个好地方，几个助手很快抛出了钩子。钓具很简单，一个线轴、一个鱼钩、一个铅垂，饵是提前准备的小鱿鱼，我们也有样学样跟着摆弄。<br><img src="http://pic.yupoo.com/cpiz/CnO8gvfU/medium.jpg" alt="寻找晚餐"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8hAW5/medium.jpg" alt="重新上饵"></p><p><img src="http://pic.yupoo.com/cpiz/CojQkJ5f/medium.jpg" alt="IMG_0895"></p><p>当水手钓起了第一石斑，全船欢呼。</p><p>我一开始根本站不稳，得一只手扶着栏杆放钓，后来大着胆子上了船头，慢慢适应了波动，半蹲着身子也能站住。这里大概6米深度，海底的珊瑚让我钓上来好几块，也有不小心卡住最后丢了钩子或铅垂的时候，不过最后还是让我也钓上来一条石斑。</p><p><img src="http://pic.yupoo.com/cpiz/Col076f3/medium.jpg" alt="_1080974"></p><p>太阳即将落下的时候，开始回岛，欣赏了一场美丽的日落。</p><p><img src="http://pic.yupoo.com/cpiz/CojPe51L/medium.jpg" alt="自拍夕阳"><br><img src="http://pic.yupoo.com/cpiz/CnO8j4na/medium.jpg" alt="鸡蛋黄"></p><p><img src="http://pic.yupoo.com/cpiz/CnO8jKHF/medium.jpg" alt="水也改了颜色"><br>云层开始堆积，水也改了颜色，莫非要下雨？</p><p><img src="http://pic.yupoo.com/cpiz/CnO8jUiC/medium.jpg" alt="即将出炉的晚餐"></p><p>晚餐的主题是烧烤，食物端上桌后，暴雨同时来临。餐厅是个凉棚性质的建筑，巨风卷着雨雾穿堂而过，很快打湿了所有人的皮肤，但仍然没有破坏我们美食的心情。<br><img src="http://pic.yupoo.com/cpiz/CnO8llme/medium.jpg" alt="风雨无阻的美食心情"></p><p>回到了木屋，大家早早睡下，期待暴雨过后还有日出黎明。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Day-2-亚庇-–-环滩岛&quot;&gt;&lt;a href=&quot;#Day-2-亚庇-–-环滩岛&quot; class=&quot;headerlink&quot; title=&quot;Day 2 亚庇 – 环滩岛&quot;&gt;&lt;/a&gt;Day 2 亚庇 – 环滩岛&lt;/h1&gt;&lt;p&gt;第二天早早起床第一件事就是看天气，似乎不错。
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="摄影" scheme="http://cpiz.com/tag/%E6%91%84%E5%BD%B1/"/>
    
      <category term="旅行" scheme="http://cpiz.com/tag/%E6%97%85%E8%A1%8C/"/>
    
      <category term="沙巴" scheme="http://cpiz.com/tag/%E6%B2%99%E5%B7%B4/"/>
    
  </entry>
  
  <entry>
    <title>漂洋过海去看你·沙巴（一）</title>
    <link href="http://cpiz.com/2012/11/04/%E6%BC%82%E6%B4%8B%E8%BF%87%E6%B5%B7%E5%8E%BB%E7%9C%8B%E4%BD%A0%C2%B7%E6%B2%99%E5%B7%B4%EF%BC%88%E4%B8%80%EF%BC%89/"/>
    <id>http://cpiz.com/2012/11/04/漂洋过海去看你·沙巴（一）/</id>
    <published>2012-11-04T10:10:58.000Z</published>
    <updated>2018-05-26T03:45:44.584Z</updated>
    
    <content type="html"><![CDATA[<blockquote><h4 id="旅行归来第6天"><a href="#旅行归来第6天" class="headerlink" title="旅行归来第6天"></a><strong>旅行归来第6天</strong></h4><h4 id="那些欢快的记忆"><a href="#那些欢快的记忆" class="headerlink" title="那些欢快的记忆"></a><strong>那些欢快的记忆</strong></h4><h4 id="像梦的片段"><a href="#像梦的片段" class="headerlink" title="像梦的片段"></a><strong>像梦的片段</strong></h4><h4 id="还时常跳出脑海"><a href="#还时常跳出脑海" class="headerlink" title="还时常跳出脑海"></a><strong>还时常跳出脑海</strong></h4><h4 id="黝黑的皮肤，还有晒伤的肩膀"><a href="#黝黑的皮肤，还有晒伤的肩膀" class="headerlink" title="黝黑的皮肤，还有晒伤的肩膀"></a><strong>黝黑的皮肤，还有晒伤的肩膀</strong></h4><h4 id="是摔倒的陀螺"><a href="#是摔倒的陀螺" class="headerlink" title="是摔倒的陀螺"></a><strong>是摔倒的陀螺</strong></h4><h4 id="告诉我"><a href="#告诉我" class="headerlink" title="告诉我"></a><strong>告诉我</strong></h4><h4 id="那是已过去的真实"><a href="#那是已过去的真实" class="headerlink" title="那是已过去的真实"></a><strong>那是已过去的真实</strong></h4><h4 id="Good-times-Crazy-friends-Amazing-memories"><a href="#Good-times-Crazy-friends-Amazing-memories" class="headerlink" title="Good times + Crazy friends = Amazing memories"></a><em>Good times + Crazy friends = Amazing memories</em></h4><h4 id="欢乐时光＋疯子般的朋友＝最棒的回忆"><a href="#欢乐时光＋疯子般的朋友＝最棒的回忆" class="headerlink" title="欢乐时光＋疯子般的朋友＝最棒的回忆"></a><em>欢乐时光＋疯子般的朋友＝最棒的回忆</em></h4></blockquote><p>他们说关于旅行，当你决定要出发的时候，最困难的那部分其实就已经完成了。我们的决定很简单，3月份LP看到亚航的Big Sale不舍得错过，约上几个朋友，很快订下了10月份广州-吉隆坡-亚庇-吉隆坡-广州的4飞机票，每人总价才1400+。</p><p>太长的计划其实是种折磨，虽然Junior同学早早的做好了攻略，护照、签证办理也按部就班，但积累的期待总让人担心有变数，怕LP会怀孕、怕请不到假期。临行前获知小强同学因为户口问题最终没能搞定护照，吉隆坡和亚庇的天气预报又不太理想，最后5人带着兴奋、遗憾、担心开始上路……</p><h1 id="Day-1-广州-–-吉隆坡-–-亚庇-–-Weston红树林"><a href="#Day-1-广州-–-吉隆坡-–-亚庇-–-Weston红树林" class="headerlink" title="Day 1 广州 – 吉隆坡 – 亚庇 – Weston红树林"></a>Day 1 广州 – 吉隆坡 – 亚庇 – Weston红树林</h1><p><img src="http://pic.yupoo.com/cpiz/CnO85uhn/medium.jpg" alt="凌晨1点，下一站吉隆坡"></p><p>机票便宜，所以凌晨一点多起飞不奇怪，大半夜在白云机场找不到吃的也很自然，5个人饿着肚子上了飞机。作为廉价航空公司的典范，亚航的飞机不提供免费的食物和水，幸好有准备，带了些零食。还没起飞，旁边的大叔已经呼噜震天，很是羡慕。</p><p>飞机五点半降落吉隆坡亚航LCCT机场，出舱门就立刻感受到湿热的热带空气。过关检的时候自然着跟随大部队去排队，这时旁边一位同行的大爷问了一句：“你们是外国人吗？”，众人愣。“外国人从那边过”，大爷指了指另一边空荡荡的外国人入境柜台。这是在马来西亚感受的第一笔热情，也提醒了我们这是个有很多华人的国家，不必太紧张。</p><p>确定好中转的航班后，换了点马币，在马来西亚的第一顿选择了麦当劳，热烘烘的食物给疲惫的队伍增加了一点活力。</p><p><img src="http://pic.yupoo.com/cpiz/CnO85xEp/medium.jpg" alt="饿，LCCT 麦当劳拯救我们"></p><p>在吉隆坡至亚庇的飞机上终于睡着了，醒来时被窗外的蓝天和蓝水打动，这是第一次在海上的飞行。</p><p><img src="http://pic.yupoo.com/cpiz/CnO85NJH/medium.jpg" alt="上面上蓝天，下面是蓝水"></p><p>即将降落亚庇，好像在下雨？</p><p><img src="http://pic.yupoo.com/cpiz/CnO865Ai/medium.jpg" alt="水黄成这样，看来没少下雨"><br><img src="http://pic.yupoo.com/cpiz/CnO860Xk/medium.jpg" alt="即将落亚庇，天气不好，有点担心"></p><p>我们在亚庇的活动都包给了当地华人旅游圈中很有口碑的洪叔，出机场的时候他家的工作人员小林已经在外面等着了。小林是祖籍福建的华人 ，酷似马来西亚羽毛球巨星李宗伟，在车上给我们介绍了当地的风土人情以及亚庇热门的吃喝去处。亚庇看样子刚下完雨，我们问及这几天的天气，小林说现在是沙巴的雨季，最近都在下雨，他们当天的一趟美人鱼岛安排就因为天气不好已经取消，至于第二天我们的环滩岛之旅能不能成行，得到时候看天才知道。</p><p>我们预订的酒店叫eden54，后缀54其实是它的门牌号码，不远处还有家新一点的Sixty3也一样。eden54不豪华但很舒适，充满旅行的情调，从老板娘到工作人员都很Nice。</p><p><img src="http://pic.yupoo.com/cpiz/CoiIZWTq/medium.jpg" alt="eden54"></p><p>下午的计划是去红树林看长鼻猴和萤火虫，不过之前要先找点吃的，来到了这家家嫂板面。他乡的华人都很亲近华人游客，老板不耐其烦地向我们介绍他们的特色饮食，跟我们聊中国，聊戏曲。抱着体验的心态，我们尽量点了不同的东西。<br><img src="http://pic.yupoo.com/cpiz/CoiQABhx/medium.jpg" alt="榴莲布丁"><br><img src="http://pic.yupoo.com/cpiz/CnO87COY/medium.jpg" alt="家嫂XX面"></p><p>榴莲布丁很香，粽子也不错，橘子冰更是当地的特色。这种本地特长的小橘子，有一种特别的酸味，当地人似乎将它当做柠檬使用，用于制作饮料和调味。香菇板面也不错，但印象更深的里面香喷喷的小鱼干。餐饮物价和广州差不多，一碗面人民币10元出头，消费无压力。</p><p><img src="http://pic.yupoo.com/cpiz/CojaHMxd/medium.jpg" alt="亚庇"></p><p>回到酒店，启程Weston红树林。<br><img src="http://pic.yupoo.com/cpiz/Coj3lPD5/medium.jpg" alt="至Weston中途遇雨"><br>路上遇雨，担心啊。中途在一家巧克力店停留了十来分钟，没有强制消费，店员还为我们上下车提供了雨伞。</p><p>Weston湿地在亚庇的西南方100多公里处，近3小时路程，这有一种特有的长鼻猴，已经濒危，晚上则能看到很多萤火虫。</p><p>这似乎没受下雨影响，由车换船，高速飞驰把心情也带High了起来。<br><img src="http://pic.yupoo.com/cpiz/CnO87SOL/medium.jpg" alt="红树林"><br><img src="http://pic.yupoo.com/cpiz/CnO88DgF/medium.jpg" alt="Weston红树林，当地下午茶"><br>来到接待码头稍作休整，品尝了当地下午茶，只是味道一般，然后出发去看长鼻猴。车上的导游开始当上了船长，一本正经还挺有范儿。<br><img src="http://pic.yupoo.com/cpiz/CnO89Ery/medium.jpg" alt="船长小胖"><br><img src="http://pic.yupoo.com/cpiz/CojiTBvU/medium.jpg" alt="DSC_0103"></p><p>运气不错，遇到几群长鼻猴，但距离太远又不能互动，互相参观了一阵，掉头去看夕阳。<br><img src="http://pic.yupoo.com/cpiz/CnO8aVWh/medium.jpg" alt="传说中的长鼻猴"><br>夕阳美，但比起我们后面几天看到的，实在不算什么，略过不言。<br><img src="http://pic.yupoo.com/cpiz/CnO8bvT5/medium.jpg" alt="快日落了"></p><p>日落后回到码头吃完一顿简单的晚饭，天已经黑得差不多，再次坐船出去看萤火虫。白天普通水中树木晚上则是萤火虫的乐土，只是荧光不比日光，加上船一直在荡，出不来好片。<br><img src="http://pic.yupoo.com/cpiz/CnO8bXFN/medium.jpg" alt="萤火虫"></p><p>回到岸上乘车转返，一路睡到亚庇。大家意犹未尽出门逛荡一番，可惜这边不兴夜生活，没多少东西可看。回到酒店躺下，期待第二天的好天气。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;h4 id=&quot;旅行归来第6天&quot;&gt;&lt;a href=&quot;#旅行归来第6天&quot; class=&quot;headerlink&quot; title=&quot;旅行归来第6天&quot;&gt;&lt;/a&gt;&lt;strong&gt;旅行归来第6天&lt;/strong&gt;&lt;/h4&gt;&lt;h4 id=&quot;那些欢快的记忆&quot;&gt;&lt;a hre
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="摄影" scheme="http://cpiz.com/tag/%E6%91%84%E5%BD%B1/"/>
    
      <category term="旅行" scheme="http://cpiz.com/tag/%E6%97%85%E8%A1%8C/"/>
    
      <category term="沙巴" scheme="http://cpiz.com/tag/%E6%B2%99%E5%B7%B4/"/>
    
  </entry>
  
  <entry>
    <title>让Dropbox准实时同步文件（定时重启法）</title>
    <link href="http://cpiz.com/2012/09/20/%E8%AE%A9Dropbox%E5%87%86%E5%AE%9E%E6%97%B6%E5%90%8C%E6%AD%A5%E6%96%87%E4%BB%B6%EF%BC%88%E5%AE%9A%E6%97%B6%E9%87%8D%E5%90%AF%E6%B3%95%EF%BC%89/"/>
    <id>http://cpiz.com/2012/09/20/让Dropbox准实时同步文件（定时重启法）/</id>
    <published>2012-09-19T16:18:00.000Z</published>
    <updated>2018-05-24T07:02:07.178Z</updated>
    
    <content type="html"><![CDATA[<p>到现在可选择的网盘产品已经很多，老牌的Dropbox一直没发布什么激动人心的新功能，而且依然承受着GFW的污染，可我偏偏还是对它情有独钟，这也许是一种爱受虐的贱，也许是种念旧，也许是种怕麻烦。</p><p>不管如何，现在比以前还是好多了，起码能https访问web、能实时上传，就差一个云端文件更新后客户端自动同步功能，经常不得已人肉重启进程来触发更新。原因在<a href="http://giveuptech.com/post/the-solution-of-dropbox-syncronize-automatically-in-china" title="解决Dropbox中国无法及时自动同步的问题" target="_blank" rel="noopener">《解决Dropbox中国无法及时自动同步的问题》</a>中有解释，也提供了一种解决办法，但它的要求比较高，找不到公共机器的话就得在每台终端机上都自建一个Python的Web服务，又涉及端口占用、修改Host、隐藏到后台什么麻烦。</p><p>相比起来重启Dropbox进程触发更新是一种比较野蛮但更简单有效的方式，要灵活的话可以人肉重启，要省事的话可以定时重启。按照一懒到底的习惯，写了一个全自动化的VBS脚本。<br><figure class="highlight"><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"><span class="comment">'''''''''''''''''''''''''''</span></span><br><span class="line"><span class="comment">'Dropbox定时重启脚本</span></span><br><span class="line"><span class="comment">'</span></span><br><span class="line"><span class="comment">'由于Dropbox的文件更新通知使用的http服务被GFW限制不可用，须要重启Dropbox进程才能触发获取文件的更新。</span></span><br><span class="line"><span class="comment">'特编写此脚本自动进行定时重启操作，运行后添加一项Windows定时任务，每隔指定的时间重启Dropbox.exe</span></span><br><span class="line"><span class="comment">'''''''''''''''''''''''''''</span></span><br><span class="line"></span><br><span class="line"><span class="comment">'在这里设定重启的间隔时间</span></span><br><span class="line"><span class="comment">'如果只想立即重启Dropbox，不想要定时执行，则把它配置为0</span></span><br><span class="line">interval = 30</span><br><span class="line"></span><br><span class="line"><span class="comment">''''''''''''''''''''''''''''''''''''''''''''</span></span><br><span class="line">Set fso = CreateObject("Scripting.FileSystemObject")</span><br><span class="line">set ws = Wscript.createobject("Wscript.Shell")</span><br><span class="line"></span><br><span class="line"><span class="comment">'生成真正执行的Bat文件，放在TEMP目录执行</span></span><br><span class="line">Set WshSysEnv = ws.Environment("Process") </span><br><span class="line">batPath = WshSysEnv.Item("TEMP") &amp; "\restart_dropbox.bat"</span><br><span class="line">Set bat = fso.CreateTextFile(batPath, True)</span><br><span class="line"></span><br><span class="line"><span class="comment">'用于创建定时任务</span></span><br><span class="line">if interval &gt; 0 then</span><br><span class="line">    scriptPath = fso.GetFile(Wscript.ScriptFullName).path</span><br><span class="line">    '将使用schtasks命令创建定时任务</span><br><span class="line">    bat.WriteLine("schtasks /create /f /tn ""Dropbox定时重启"" /ru %username% /tr """ &amp; scriptPath &amp; """ /sc minute /mo " &amp; interval)</span><br><span class="line">end if</span><br><span class="line"></span><br><span class="line"><span class="comment">'用于杀死老的Dropbox</span></span><br><span class="line">bat.WriteLine("taskkill /f /im Dropbox.exe")</span><br><span class="line"></span><br><span class="line"><span class="comment">'用于创建新的Dropbox</span></span><br><span class="line">bat.WriteLine("start %appdata%\Dropbox\bin\Dropbox.exe")</span><br><span class="line">bat.Close</span><br><span class="line"></span><br><span class="line"><span class="comment">' 执行Bat</span></span><br><span class="line">ws.run batPath &amp; " /start", 0</span><br></pre></td></tr></table></figure></p><p>另存为 restart_dropbox.vbs 后，双击运行，注意运行后不要再移动vbs文件。</p><p>此方法的缺点是：</p><ol><li>定时更新毕竟不是实时更新</li><li>重启可能打断正在上传的进程，影响上传效率</li><li>重启后老进程托盘图标将残留，新进程又会创建一个，时间久了图标会越来越多，鼠标移上去才会更新<img src="/2012/09/20/让Dropbox准实时同步文件（定时重启法）/YY截图20120920093315.png"></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;到现在可选择的网盘产品已经很多，老牌的Dropbox一直没发布什么激动人心的新功能，而且依然承受着GFW的污染，可我偏偏还是对它情有独钟，这也许是一种爱受虐的贱，也许是种念旧，也许是种怕麻烦。&lt;/p&gt;
&lt;p&gt;不管如何，现在比以前还是好多了，起码能https访问web、能实时
      
    
    </summary>
    
      <category term="项目" scheme="http://cpiz.com/category/%E9%A1%B9%E7%9B%AE/"/>
    
    
      <category term="GFW" scheme="http://cpiz.com/tag/GFW/"/>
    
      <category term="Dropbox" scheme="http://cpiz.com/tag/Dropbox/"/>
    
      <category term="VBS" scheme="http://cpiz.com/tag/VBS/"/>
    
      <category term="Script" scheme="http://cpiz.com/tag/Script/"/>
    
  </entry>
  
  <entry>
    <title>海与星——9月15陆丰观音滩露营记</title>
    <link href="http://cpiz.com/2012/09/17/%E6%B5%B7%E4%B8%8E%E6%98%9F%E2%80%94%E2%80%949%E6%9C%8815%E9%99%86%E4%B8%B0%E8%A7%82%E9%9F%B3%E6%BB%A9%E9%9C%B2%E8%90%A5%E8%AE%B0/"/>
    <id>http://cpiz.com/2012/09/17/海与星——9月15陆丰观音滩露营记/</id>
    <published>2012-09-16T17:01:01.000Z</published>
    <updated>2018-05-26T03:44:48.766Z</updated>
    
    <content type="html"><![CDATA[<h2 id="备"><a href="#备" class="headerlink" title="备"></a>备</h2><p>9月10号驴群提议周末到行者老大的根据地——陆丰海滩露营，饥渴的驴子们就像见到了磨一样刷刷开转，迅速成立了活动临时QQ群，确定行程、分工、装备、联系租车加上各种YY，恨不得立刻穿越到星期六，班都不想上了。</p><p>我一从没露过营的菜驴，赶紧到淘宝补充了防潮垫与抓绒睡袋。苦熬到周五下班，收拾打包妥当，凌晨1点钟才在兴奋与不安中睡去，中间梦见自己各种迟到，不停地怀疑人生和……闹钟。</p><h2 id="行"><a href="#行" class="headerlink" title="行"></a>行</h2><p><img src="http://pic.yupoo.com/cpiz/CgSKbNMm/medium.jpg" alt="" title="出发"></p><p>6点45分，闹钟终于被我等醒！洗漱早饭出门，自行车转BRT，到奥体北门下车瞎找到集合点地铁黄村B出口刚好8点。我接过水浸街的600D，装上我的18-135，负责全程摄影。</p><p>8点10分，最后的湖南仔穿着皮鞋、拎个皮包赶到，让众人大跌眼镜。</p><p>8点15分，出发！</p><p>司机师傅开车很稳，12点顺利到达陆丰。</p><h2 id="歇"><a href="#歇" class="headerlink" title="歇"></a>歇</h2><p>和老大接上头，登上了他家宝宅。一进门我靠豁然开朗，宽敞的四合院，绿树茵茵儿女满堂，客厅里竖着个充气艇，没事就爬爬山游游水踩踩单车，这不就是我的理想生活么？老大不经意又丢出一句“这后面一千多平也是我的”，当时差点就给跪了……</p><p><img src="http://pic.yupoo.com/cpiz/CgSKfulR/medium.jpg" alt=""></p><p>老大早早给我们准备了当地非常有特色的海陆丰雷茶，引用当前热门的“中国好声音体”评价就是“好吃！”。</p><p><img src="http://pic.yupoo.com/cpiz/CgSKihto/medium.jpg" alt="啥饭来着？太好吃了！"><br><img src="http://pic.yupoo.com/cpiz/CgSKl4oO/medium.jpg" alt="擂茶"><br><img src="http://pic.yupoo.com/cpiz/CgSKAoZj/medium.jpg" alt="IMG_0901"></p><p>饭茶带着清香，我呼噜呼噜两大碗下去，还不小心呛进了气管。</p><p>饭后装补充物资，先游玄武山元山寺，再到观音滩驻扎。</p><p><img src="http://pic.yupoo.com/cpiz/CgSKSBDR/medium.jpg" alt=""><br><img src="http://pic.yupoo.com/cpiz/CgSL0w4c/medium.jpg" alt=""></p><p>咱这车开起来回头率可高啊！</p><h2 id="游"><a href="#游" class="headerlink" title="游"></a>游</h2><p>去元山寺所在的碣石镇中途要经过一个小小的村庄，也是中国最著名的村庄——乌坎。曾经被偷卖的土地，现在用矮墙圈起，喷上“已收回为村集体所有”的大字，里面长满了茅草和芦苇。曾经被拆的派出所，可见被新修葺的痕迹。老大讲起当时封锁和斗阵的情景，方知这小小的民主来之不易，希望它是颗能发芽成长的种子，而不是一片浪花。</p><p><img src="http://pic.yupoo.com/cpiz/CgSL4ppe/medium.jpg" alt=""></p><p>在元山寺， 算是见识了潮汕人信佛的传统，也从侧面看到了此地的富有，不然小小的一个镇上不会有这么大一座寺庙。</p><p><a href="http://ditu.google.cn/?ie=UTF8&amp;hq=&amp;hnear=%E5%B9%BF%E4%B8%9C%E7%9C%81%E5%B9%BF%E5%B7%9E%E5%B8%82&amp;t=m&amp;brcurrent=3,0x340fc8bba2e31509:0xd0d5bd7ac31192ea,0,0x340fdf5757e3e8ab:0x2b87f4727cd66390%3B5,0,0&amp;ll=22.905748,115.914474&amp;spn=0.009488,0.01369&amp;z=15&amp;source=embed" target="_blank" rel="noopener">查看大图</a></p><p><img src="http://pic.yupoo.com/cpiz/CgSMglEr/medium.jpg" alt="IMG_0937"></p><p><img src="http://pic.yupoo.com/cpiz/CgSNMEfN/medium.jpg" alt="IMG_0956"></p><p><img src="http://pic.yupoo.com/cpiz/CgSPWbTP/medium.jpg" alt="IMG_0998"></p><p>寺庙我不太懂，反正这是块好地，到处是几人合抱的榕树，打理程度也毫不逊色于广州的公园。</p><h2 id="驻"><a href="#驻" class="headerlink" title="驻"></a>驻</h2><p>在碣石镇补给了潮汕特色的肉丸和虾，开车到到金厢镇观音滩南面，步行到观音滩营地。见到海滩一帮人立马兴奋了起来，各自鸟兽散，各种不见人，到达营地支起帐篷忍不住的就先下水了。</p><p><img src="http://pic.yupoo.com/cpiz/CgSXhNhg/medium.jpg" alt="IMG_1149"><br><img src="http://pic.yupoo.com/cpiz/CgSYtBd0/medium.jpg" alt="IMG_1174"></p><h2 id="烹"><a href="#烹" class="headerlink" title="烹"></a>烹</h2><p><img src="http://pic.yupoo.com/cpiz/CgSYFMYp/medium.jpg" alt="IMG_1180"><br><img src="http://pic.yupoo.com/cpiz/CgSYUb6N/medium.jpg" alt="IMG_1192"></p><p>太阳慢慢落下，光线和温度很快在下降。有了留岸的GGMM们辛勤劳作，水鱼们上岸后一切都已妥当，火锅大餐热辣登场，潮汕肉丸鱼面都不是盖的，现在写着写着都在流口水。</p><p><img src="http://pic.yupoo.com/cpiz/CgSZvXrn/medium.jpg" alt="IMG_1227"><br><img src="http://pic.yupoo.com/cpiz/CgSZZMMp/medium.jpg" alt="IMG_1243"></p><h2 id="眠"><a href="#眠" class="headerlink" title="眠"></a>眠</h2><p>餐后MM们下起了飞行棋，GG们坐石头上听涛喝酒发呆。海风带来了凉意，也卷走了天空的薄云，多年未见的漫天星空慢慢展开，上一次这样记忆好像还在童年。</p><p>老大聊起了他家业的故事，简单的生意经背后是我等打工仔不及的嗅觉与果敢……</p><p>1点，涛声伴入眠。</p><h2 id="醒"><a href="#醒" class="headerlink" title="醒"></a>醒</h2><p>可能是初次露营，睡得并不安好，等天开始发亮就更躺不住，爬起来继续发呆。</p><p>朝阳里，面朝大海，脚底花开。</p><p><img src="http://pic.yupoo.com/cpiz/CgT0Xsbn/medium.jpg" alt="IMG_1273"><br><img src="http://pic.yupoo.com/cpiz/CgT20fMk/medium.jpg" alt="IMG_1290"></p><p>开炉泡面，打扫拔营。</p><h2 id="归"><a href="#归" class="headerlink" title="归"></a>归</h2><p>回到老大家，又是一顿很有特色的饺子，浑沦塞下肚好多个。<br>下午2点出发，6点回到广州。最后结算每人支付222元，其中175是车费，其他才花不到50……<br>感谢行者的热情招待，感谢回忆的组织与财务，感谢生火的GGs，备菜收尾的MMs，真是美好的两天，期待下一次的重聚。</p><p>本次活动我拍摄照片的相册地址：<br><a href="http://www.yupoo.com/photos/cpiz/albums/4874387" target="_blank" rel="noopener">http://www.yupoo.com/photos/cpiz/albums/4874387</a><br>请在又拍上添加我为好友获得访问权限</p><p>各位的精彩瞬间<br><img src="http://pic.yupoo.com/cpiz/CgSQSTLW/medium.jpg" alt="IMG_1012"><br><img src="http://pic.yupoo.com/cpiz/CgSTVUc1/medium.jpg" alt="IMG_1089"><br><img src="http://pic.yupoo.com/cpiz/CgSReNby/medium.jpg" alt="IMG_1018"><br><img src="http://pic.yupoo.com/cpiz/CgSQIWRq/medium.jpg" alt="IMG_1007"><br><img src="http://pic.yupoo.com/cpiz/CgSOMEne/medium.jpg" alt="IMG_0976"><br><img src="http://pic.yupoo.com/cpiz/CgSTneDP/medium.jpg" alt="IMG_1071"><br><img src="http://pic.yupoo.com/cpiz/CgSSPUUS/medium.jpg" alt="IMG_1060"><br><img src="http://pic.yupoo.com/cpiz/CgSTcfOl/medium.jpg" alt="IMG_1069"><br><img src="http://pic.yupoo.com/cpiz/CgT1pvFz/medium.jpg" alt="IMG_1281"></p><p>还漏了一位MM，实在不好意思……没有抓拍到<br>自古有云：“上摄者不留影”，摄影师的自拍一张：<br><img src="http://pic.yupoo.com/cpiz/CgSRDsxb/square.jpg" alt="IMG_1039"><br>小一点，低调一点</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;备&quot;&gt;&lt;a href=&quot;#备&quot; class=&quot;headerlink&quot; title=&quot;备&quot;&gt;&lt;/a&gt;备&lt;/h2&gt;&lt;p&gt;9月10号驴群提议周末到行者老大的根据地——陆丰海滩露营，饥渴的驴子们就像见到了磨一样刷刷开转，迅速成立了活动临时QQ群，确定行程、分工、装备、联系
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="户外" scheme="http://cpiz.com/tag/%E6%88%B7%E5%A4%96/"/>
    
      <category term="旅游" scheme="http://cpiz.com/tag/%E6%97%85%E6%B8%B8/"/>
    
      <category term="海" scheme="http://cpiz.com/tag/%E6%B5%B7/"/>
    
      <category term="露营" scheme="http://cpiz.com/tag/%E9%9C%B2%E8%90%A5/"/>
    
      <category term="驴友" scheme="http://cpiz.com/tag/%E9%A9%B4%E5%8F%8B/"/>
    
  </entry>
  
  <entry>
    <title>用Python实现QQ找茬游戏外挂工具</title>
    <link href="http://cpiz.com/2012/03/18/%E7%94%A8Python%E5%AE%9E%E7%8E%B0QQ%E6%89%BE%E8%8C%AC%E6%B8%B8%E6%88%8F%E5%A4%96%E6%8C%82%E5%B7%A5%E5%85%B7/"/>
    <id>http://cpiz.com/2012/03/18/用Python实现QQ找茬游戏外挂工具/</id>
    <published>2012-03-18T11:27:00.000Z</published>
    <updated>2018-05-28T14:32:48.993Z</updated>
    
    <content type="html"><![CDATA[<p>(原创作品，转载请注明出处)<br>好久没写技术相关的博文，这次写篇有意思的，关于一个有意思的游戏——QQ找茬，关于一种有意思的语音——Python，关于一个有意思的库——Qt。</p><p>这是一个用于QQ大家来找茬（美女找茬）的辅助外挂，开发的原因是看到老爸天天在玩这个游戏，分数是惨不忍睹的负4000多。他玩游戏有他的乐趣，并不很在意输赢，我做这个也只是自我娱乐，顺便讨他个好，毕竟我们搞编程的实在难有机会在父辈面前露露手。本来是想写个很简单的东西，但由于过程中老爸的多次嘲讽，逼得我不得不尽力完善，最后形成了一个小小的产品。</p><p>接触Python是2010年，相见恨晚，去年拿它写了些小玩意，离职前给前公司留下了一个Python+wxPython的工作工具，还挺受欢迎。换公司后努力学习C++&amp;Qt，很后悔当初选择了wxPython而不是PyQt，没能一脉相承。使用Qt越久，不得不越来越喜欢，写这个东西正好就用上了。</p><p>话不多说，进入正题。这不是一篇完整的代码讲解，只是过程中的一些技术做个分享，包括后来被放弃的一些技术点。当初搜索这些东西也挺费力的，在这做个笔记，后来者也许能搜到收益。</p><p>先上个图：</p><p><img src="http://pic.yupoo.com/cpiz/BOTyq2xX/medium.jpg" alt="QQ找茬助手" title="QQ找茬助手"></p><p>辅助工具在游戏中增加了两个按钮，点击“对比”则自动找“茬”，用蓝色小框标识，点击“擦除”清除标识。<br><a id="more"></a></p><h2 id="游戏窗口探查"><a href="#游戏窗口探查" class="headerlink" title="游戏窗口探查"></a>游戏窗口探查</h2><p>这得用PyWin32库，它是对windows接口的Python封装，VC能做的它基本都行。</p><p>下载地址：<a href="http://sourceforge.net/projects/pywin32/" target="_blank" rel="noopener">http://sourceforge.net/projects/pywin32/</a>，但不能直接点Download图标，不然下下来是一个Readme.txt，点“<a href="http://sourceforge.net/projects/pywin32/files/" title="Browse All Files" target="_blank" rel="noopener">Browse All Files</a>”寻找需要的版本。<br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">#coding=gbk</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> win32gui</span><br><span class="line"></span><br><span class="line">game_hwnd = win32gui.FindWindow(<span class="string">"#32770"</span>, <span class="string">"大家来找茬"</span>)</span><br><span class="line"><span class="keyword">print</span> game_hwnd</span><br></pre></td></tr></table></figure></p><p>QQ找茬是个对话框窗口，Class是“#32770”，这种窗口桌面上有很多，所以还配合了标题“大家来找茬”匹配，又因为是中文，所以第一行指定了使用gbk编码，否则要么找不到，要么运行出错。</p><h2 id="游戏图片提取"><a href="#游戏图片提取" class="headerlink" title="游戏图片提取"></a>游戏图片提取</h2><p>提取图片采用了截屏的方式，找到窗口后将窗口提到最前，再作窗口截屏。截屏使用了大名鼎鼎的<a href="http://www.pythonware.com/products/pil/" title="PIL" target="_blank" rel="noopener">Python Imaging Library (PIL)</a>库。<br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> ImageGrab</span><br><span class="line"><span class="keyword">import</span> win32con</span><br><span class="line"></span><br><span class="line">win32gui.ShowWindow(game_hwnd, win32con.SW_RESTORE)    <span class="comment"># 强行显示界面后才好截图</span></span><br><span class="line">win32gui.SetForegroundWindow(game_hwnd)                <span class="comment"># 将游戏窗口提到最前</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 裁剪得到全图</span></span><br><span class="line">game_rect = win32gui.GetWindowRect(game_hwnd)</span><br><span class="line">src_image = ImageGrab.grab((game_rect[<span class="number">0</span>] + <span class="number">9</span>, game_rect[<span class="number">1</span>] + <span class="number">190</span>, game_rect[<span class="number">2</span>] - <span class="number">9</span>, game_rect[<span class="number">1</span>] + <span class="number">190</span> + <span class="number">450</span>))</span><br><span class="line"><span class="comment"># src_image.show()</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 分别裁剪左右内容图片</span></span><br><span class="line">left_box = (<span class="number">9</span>, <span class="number">0</span>, <span class="number">500</span>, <span class="number">450</span>)</span><br><span class="line">right_box = (<span class="number">517</span>, <span class="number">0</span>, <span class="number">517</span> + <span class="number">500</span>, <span class="number">450</span>)</span><br><span class="line">image_left = src_image.crop(left_box)</span><br><span class="line">image_right = src_image.crop(right_box)</span><br><span class="line"><span class="comment"># image_left.show()</span></span><br><span class="line"><span class="comment"># image_right.show()</span></span><br></pre></td></tr></table></figure></p><p>上面用到的坐标都为为了演示代码简单填的，实际上使用了变量参数，而且要区分分辨率什么的。<br>PIL是一个强大的Python图形库（<a href="http://www.pythonware.com/library/pil/handbook/index.htm" title="PIL文档" target="_blank" rel="noopener">使用文档</a>），待会的对比分析也须要用到。ImageGrab是PIL的一个模块，用于图像的抓取。不带参数的<code>ImageGrab.grab()</code>进行全屏截屏，返回一个<code>Image</code>对象，也可使用一个元组作为参数指定要截取的范围（左上与右下两点的坐标），这两种截屏都是不带鼠标指针的，还有一个<code>ImageGrab.grabclipboard()</code>可从系统剪贴板采集图像。</p><p>得到Image图像后可用<code>show()</code>方法，使用系统默认的图像查看工具打开，方便调试，也可以用<code>save(filename)</code>保存成文件，对应的可以<code>Image.open(filename)</code>打开获得。</p><p>grab得到了一个包含左右图片的Image对象后，用crop(box)方法可裁剪得到其中指定的区域，分别拿到左右两个游戏图片。</p><h2 id="对比获得两图内容不同的区域"><a href="#对比获得两图内容不同的区域" class="headerlink" title="对比获得两图内容不同的区域"></a>对比获得两图内容不同的区域</h2><p>很自然想到把两图裁剪成N个小图片分别对比，左右统一区域对应的小图片不相等则为“茬”区，唯一的问题是怎么判断两个图片内容不一致？</p><p>一开始以为很会有些麻烦，直到发现了<code>Image.histogram()</code>函数，该函数用于得到图像的颜色直方图。我平常也爱好摄影，知道直方图可以表示一张图片中各种亮度（或颜色）的数量，两张<strong>自然图片</strong>的直方图基本是不一样的，除非两图对称、颜色一致但排列不一，但就算如此，将两图继续分割下去，其子图的直方图也会不一样。直方图就是一种图形到数值的转换，对比两图的颜色数值就可知是否存在差异。</p><p>一张用RBG颜色格式的图像，<code>histogram()</code>函数将返回一个长度为768的数组，第0-255表示红色的0-255，第256-511表色绿色的0-255，第512-767表色蓝色的0-255，数值表示该颜色像素的个数。因此，histogram()列表所有成员之和等于改图像的像素值 x 3。</p><p>写了一个函数，用来获得两图比较的数值差：<br><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">compare</span><span class="params">(image_a, image_b)</span>:</span></span><br><span class="line">    <span class="string">'''返回两图的差异值</span></span><br><span class="line"><span class="string">    返回两图红绿蓝差值万分比之和'''</span></span><br><span class="line">    histogram_a = image_a.histogram()</span><br><span class="line">    histogram_b = image_b.histogram()</span><br><span class="line">    <span class="keyword">if</span> len(histogram_a) != <span class="number">768</span> <span class="keyword">or</span> len(histogram_b) != <span class="number">768</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">None</span></span><br><span class="line"></span><br><span class="line">    red_a = <span class="number">0</span></span><br><span class="line">    red_b = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">256</span>):</span><br><span class="line">        red_a += histogram_a[i + <span class="number">0</span>] * i</span><br><span class="line">        red_b += histogram_b[i + <span class="number">0</span>] * i</span><br><span class="line">    diff_red = <span class="number">0</span></span><br><span class="line">    <span class="keyword">if</span> red_a + red_b &amp;gt; <span class="number">0</span>:</span><br><span class="line">        diff_red = abs(red_a - red_b) * <span class="number">10000</span> / max(red_a, red_b)</span><br><span class="line"></span><br><span class="line">    green_a = <span class="number">0</span></span><br><span class="line">    green_b = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">256</span>):</span><br><span class="line">        green_a += histogram_a[i + <span class="number">256</span>] * i</span><br><span class="line">        green_b += histogram_b[i + <span class="number">256</span>] * i</span><br><span class="line">    diff_green = <span class="number">0</span></span><br><span class="line">    <span class="keyword">if</span> green_a + green_b &amp;gt; <span class="number">0</span>:</span><br><span class="line">        diff_green = abs(green_a - green_b) * <span class="number">10000</span> / max(green_a, green_b)</span><br><span class="line"></span><br><span class="line">    blue_a = <span class="number">0</span></span><br><span class="line">    blue_b = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">256</span>):</span><br><span class="line">        blue_a += histogram_a[i + <span class="number">512</span>] * i</span><br><span class="line">        blue_b += histogram_b[i + <span class="number">512</span>] * i</span><br><span class="line">    diff_blue = <span class="number">0</span></span><br><span class="line">    <span class="keyword">if</span> blue_a + blue_b &amp;gt; <span class="number">0</span>:</span><br><span class="line">        diff_blue = abs(blue_a - blue_b) * <span class="number">10000</span> / max(blue_a, blue_b)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> diff_red, diff_green, diff_blue</span><br></pre></td></tr></table></figure></p><p>将函数返回的红绿蓝差值相加，如果超过了预定定的阀值2000，则表示该区域不同。这个计算方式有点“土”，但对这次要解决的问题很有效，就没再继续改进。<br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">#将左右大图裁剪成多个小图分别进行对比</span></span><br><span class="line">result = [[<span class="number">0</span> <span class="keyword">for</span> a <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">50</span>)] <span class="keyword">for</span> b <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">45</span>)]</span><br><span class="line"><span class="keyword">for</span> col <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">50</span>):</span><br><span class="line">    <span class="keyword">for</span> row <span class="keyword">in</span> xrange(<span class="number">0</span>, <span class="number">45</span>):</span><br><span class="line">        clip_box = (col * <span class="number">10</span>, row * <span class="number">10</span>, (col + <span class="number">1</span>) * <span class="number">10</span>, (row + <span class="number">1</span>) * <span class="number">10</span>)</span><br><span class="line">        clip_image_left = image_left.crop(clip_box)</span><br><span class="line">        clip_image_right = image_right.crop(clip_box)</span><br><span class="line">        clip_diff = self.compare(clip_image_left, clip_image_right)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> sum(clip_diff) &amp;gt; <span class="number">2000</span>:</span><br><span class="line">            result[row][col] = <span class="number">1</span></span><br></pre></td></tr></table></figure></p><p>大图是500x450，分隔成10x10的小块，定义一个50x45的二位数组存储结果，分别比较后将差值大于阀值的数组区域标记为1.</p><h2 id="在游戏上标记两边不同的区域"><a href="#在游戏上标记两边不同的区域" class="headerlink" title="在游戏上标记两边不同的区域"></a>在游戏上标记两边不同的区域</h2><p>最初我用了PyWin32的一些函数，获得游戏窗口句柄后直接在上面绘制，但我不太熟悉Windows编程，不知道如何解决游戏自身重绘后将我的标记擦除的问题，然后搬来了Qt。用Qt创建了一个和游戏大小一样透明的QWidget窗口，叠加在游戏窗口上，用遮罩来绘制标记。标记数据已记录在result数组中，在指定的位置绘制一个方格则表示该区域左右不同，要注意两个方格间的边界不要绘制，避免格子太多干扰了游戏。除标记外，还绘制了两个按钮来触发对比与擦除。<br><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">paintEvent</span><span class="params">(self, event)</span>:</span></span><br><span class="line">    <span class="comment"># 重置遮罩图像</span></span><br><span class="line">    self.pixmap.fill()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 创建绘制用的QPainter，笔画粗细为2像素</span></span><br><span class="line">    <span class="comment"># 事先已经在Qt窗体上铺了一个蓝色的背景图片，因此投过遮罩图案看下去标记线条是蓝色的</span></span><br><span class="line">    p = QPainter(self.pixmap)</span><br><span class="line">    p.setPen(QPen(QBrush(QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)), <span class="number">2</span>))</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> row <span class="keyword">in</span> xrange(len(self.result)):</span><br><span class="line">        <span class="keyword">for</span> col <span class="keyword">in</span> xrange(len(self.result[<span class="number">0</span>])):</span><br><span class="line">            <span class="keyword">if</span> self.result[row][col] != <span class="number">0</span>:</span><br><span class="line">                <span class="comment"># 定一个基点，避免算数太难看</span></span><br><span class="line">                base_l_x = self.ANCHOR_LEFT_X + self.CLIP_WIDTH * col</span><br><span class="line">                base_r_x = self.ANCHOR_RIGHT_X + self.CLIP_WIDTH * col</span><br><span class="line">                base_y = self.ANCHOR_Y + self.CLIP_HEIGHT * row</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> row == <span class="number">0</span> <span class="keyword">or</span> self.result[row - <span class="number">1</span>][col] == <span class="number">0</span>:</span><br><span class="line">                    <span class="comment"># 如果是第一行，或者上面的格子为空，画一条上边</span></span><br><span class="line">                    p.drawLine(base_l_x, base_y, base_l_x + self.CLIP_WIDTH, base_y)</span><br><span class="line">                    p.drawLine(base_r_x, base_y, base_r_x + self.CLIP_WIDTH, base_y)</span><br><span class="line">                <span class="keyword">if</span> row == len(self.result) - <span class="number">1</span> <span class="keyword">or</span> self.result[row + <span class="number">1</span>][col] == <span class="number">0</span>:</span><br><span class="line">                    <span class="comment"># 如果是最后一行，或者下面的格子为空，画一条下边</span></span><br><span class="line">                    p.drawLine(base_l_x, base_y + self.CLIP_HEIGHT, base_l_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)</span><br><span class="line">                    p.drawLine(base_r_x, base_y + self.CLIP_HEIGHT, base_r_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)</span><br><span class="line">                <span class="keyword">if</span> col == <span class="number">0</span> <span class="keyword">or</span> self.result[row][col - <span class="number">1</span>] == <span class="number">0</span>:</span><br><span class="line">                    <span class="comment"># 如果是第一列，或者左边的格子为空，画一条左边</span></span><br><span class="line">                    p.drawLine(base_l_x, base_y, base_l_x, base_y + self.CLIP_HEIGHT)</span><br><span class="line">                    p.drawLine(base_r_x, base_y, base_r_x, base_y + self.CLIP_HEIGHT)</span><br><span class="line">                <span class="keyword">if</span> col == len(self.result[<span class="number">0</span>]) - <span class="number">1</span> <span class="keyword">or</span> self.result[row][col + <span class="number">1</span>] == <span class="number">0</span>:</span><br><span class="line">                    <span class="comment"># 如果是第一列，或者右边的格子为空，画一条右边</span></span><br><span class="line">                    p.drawLine(base_l_x + self.CLIP_WIDTH, base_y, base_l_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)</span><br><span class="line">                    p.drawLine(base_r_x + self.CLIP_WIDTH, base_y, base_r_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 在遮罩上绘制按钮区域，避免按钮被遮罩挡住看不见</span></span><br><span class="line">    p.fillRect(self.btn_compare.geometry(), QBrush(QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)))</span><br><span class="line">    p.fillRect(self.btn_toggle.geometry(), QBrush(QColor(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>)))</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 将遮罩图像作为遮罩</span></span><br><span class="line">    self.setMask(QBitmap(self.pixmap))</span><br></pre></td></tr></table></figure></p><p>这里我没有替换变量，太麻烦了，能看清楚算法就行。</p><h2 id="让PyQt程序在任务栏隐藏"><a href="#让PyQt程序在任务栏隐藏" class="headerlink" title="让PyQt程序在任务栏隐藏"></a>让PyQt程序在任务栏隐藏</h2><p>为了让PyQt程序不出现在任务栏，构造QWidget设置了这些属性<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Popup | Qt.Tool)</span><br></pre></td></tr></table></figure></p><h2 id="让PyQt程序加入系统托盘、资源文件使用"><a href="#让PyQt程序加入系统托盘、资源文件使用" class="headerlink" title="让PyQt程序加入系统托盘、资源文件使用"></a>让PyQt程序加入系统托盘、资源文件使用</h2><p>PyQt添加托盘菜单非常容易，几行代码就可以<br><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建托盘</span></span><br><span class="line">self.icon = QIcon(<span class="string">":\icon.png"</span>)</span><br><span class="line"></span><br><span class="line">self.trayIcon = QSystemTrayIcon(self)</span><br><span class="line">self.trayIcon.setIcon(self.icon)</span><br><span class="line">self.trayIcon.setToolTip(<span class="string">u"QQ找茬助手"</span>)</span><br><span class="line">self.trayIcon.show()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 托盘气泡消息</span></span><br><span class="line">self.trayIcon.showMessage(<span class="string">u"QQ找茬助手"</span>, <span class="string">u"QQ找茬助手已经待命，进入游戏即可激活"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 托盘菜单</span></span><br><span class="line">self.action = QAction(<span class="string">u"退出QQ找茬助手"</span>, self, triggered = sys.exit) <span class="comment"># 触发点击后调用sys.exit()命令，即退出</span></span><br><span class="line">self.menu = QMenu(self)</span><br><span class="line">self.menu.addAction(self.action)</span><br><span class="line">self.trayIcon.setContextMenu(self.menu)</span><br></pre></td></tr></table></figure></p><p><img src="http://pic.yupoo.com/cpiz/BPaTsP88/uhP9C.png" alt="托盘效果" title="托盘效果"><br>最初我是用的托盘图标是一个.ico文件，执行脚本可以正常显示，但打包成exe后执行在托盘上显示为一个空白图标，用Python的idle工具编译运行也是空白。尝试多次后发现：PyQt的托盘图标不能使用.ico文件，否则会显示空白，换成png格式素材就没问题！</p><h2 id="PyQt资源文件打包"><a href="#PyQt资源文件打包" class="headerlink" title="PyQt资源文件打包"></a>PyQt资源文件打包</h2><p>Qt使用一个.qrc格式的xml文件管理素材，代码用可用:\xxx\xxx.png的方式引用资源文件中的素材，这在PyQt中同样支持。<br>这里我创建了一个resources.qrc文件</p><figure class="highlight xml"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE RCC&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">RCC</span> <span class="attr">version</span>=<span class="string">"1.0"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">qresource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">file</span>&gt;</span>icon.png<span class="tag">&lt;/<span class="name">file</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">qresource</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">RCC</span>&gt;</span></span><br></pre></td></tr></table></figure><p>然后用<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pyrcc4 resources.qrc &amp;gt; resources.py</span><br></pre></td></tr></table></figure></p><p>命令，将资源文件转成一个python模块，在代码中import resources，则可以用这样的方式使用图像素材<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">self.icon = QIcon(&quot;:\icon.png&quot;)</span><br></pre></td></tr></table></figure></p><h2 id="打包成可执行程序"><a href="#打包成可执行程序" class="headerlink" title="打包成可执行程序"></a>打包成可执行程序</h2><p>这个工具是给别人用的，肯定不能以py脚本的形式发布，我使用了<a href="http://cx-freeze.sourceforge.net/" title="cx_Freeze" target="_blank" rel="noopener">cx_Freeze</a>来打包为可执行程序。<br>为此要写一个打包命令脚本convert2exe.py<br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">#!Python</span></span><br><span class="line"><span class="comment">#coding=gbk</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># python转exe脚本</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># 安装cx_Freeze</span></span><br><span class="line"><span class="comment"># 执行 python convert2exe.py build</span></span><br><span class="line"><span class="comment"># 将自动生成build目录, 其下所有文件都必须打包</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> cx_Freeze <span class="keyword">import</span> setup, Executable</span><br><span class="line"></span><br><span class="line">base = <span class="keyword">None</span></span><br><span class="line"><span class="keyword">if</span> sys.platform == <span class="string">"win32"</span>:</span><br><span class="line">    base = <span class="string">"Win32GUI"</span></span><br><span class="line"></span><br><span class="line">buildOptions = dict(</span><br><span class="line">    compressed = <span class="keyword">True</span>)</span><br><span class="line"></span><br><span class="line">setup(</span><br><span class="line">        name = <span class="string">"ZhaoChaAssistant"</span>,</span><br><span class="line">        version = <span class="string">"1.0"</span>,</span><br><span class="line">        description = <span class="string">"ZhaoChaAssistant"</span>,</span><br><span class="line">        options = dict(build_exe = buildOptions),</span><br><span class="line">        executables = [Executable(<span class="string">"zhaochaassistant.py"</span>, base = base, icon = <span class="string">"icon.ico"</span>)])</span><br></pre></td></tr></table></figure></p><p>最后执行一个命令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python convert2exe.py build</span><br></pre></td></tr></table></figure></p><p>则会在当前路径下创建个build目录，打包的程序就在其中一个exe.win-amd64-2.7的目录中，运行exe即可执行，与Python无二。可惜这个包太大了一些，整个目录达到了30M。<br>为了让exe程序也有一个好看的图标，在最后一行中的executables参数中指定了icon = “icon.ico”，这个图标就最好使用多页的.ico格式(16x16,32x32,48x48…)，让程序在各种显示环境下（桌面、文件夹）都有原生的显示。<br>如果打包的时候必须使用独立的资源，可在buildOptions字典参数中增加一条include_files = [‘xxx.dat’]配置，这样在打包时会将python脚本目录中的xxx.dat文件拷贝到exe目录中，不写的话就得人工拷贝了。</p><h2 id="小技巧：Python获得自己的绝对路径"><a href="#小技巧：Python获得自己的绝对路径" class="headerlink" title="小技巧：Python获得自己的绝对路径"></a>小技巧：Python获得自己的绝对路径</h2><p>Python中有个魔术变量可以得到脚本自身的名称，但转换成exe后该变量失效，这时得改用sys.executable获得可执行程序的名称，可用hasattr(sys, “frozen”)判断自己是否已被打包，下面是一个方便取绝对路径的函数：</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">module_path</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="keyword">if</span> hasattr(sys, <span class="string">"frozen"</span>):</span><br><span class="line">        <span class="keyword">return</span> os.path.dirname(os.path.abspath(unicode(sys.executable, sys.getfilesystemencoding())))</span><br><span class="line">    <span class="keyword">return</span> os.path.dirname(os.path.abspath(unicode(__file__, sys.getfilesystemencoding())))</span><br></pre></td></tr></table></figure><h2 id="结束语"><a href="#结束语" class="headerlink" title="结束语"></a>结束语</h2><p>Python可能是程序员最好的玩具，什么都能粘起来，日常写点小工具再合适不过了。</p><p>文中的第三方模块都可以Google获得下载地址，有些库没有Win7 64位的原始版本(比如PIL)，但可到<br><a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/" title="http://www.lfd.uci.edu/~gohlke/pythonlibs/" target="_blank" rel="noopener">http://www.lfd.uci.edu/~gohlke/pythonlibs/</a><br>下载别人编译好的，也很方便。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;(原创作品，转载请注明出处)&lt;br&gt;好久没写技术相关的博文，这次写篇有意思的，关于一个有意思的游戏——QQ找茬，关于一种有意思的语音——Python，关于一个有意思的库——Qt。&lt;/p&gt;
&lt;p&gt;这是一个用于QQ大家来找茬（美女找茬）的辅助外挂，开发的原因是看到老爸天天在玩这个游戏，分数是惨不忍睹的负4000多。他玩游戏有他的乐趣，并不很在意输赢，我做这个也只是自我娱乐，顺便讨他个好，毕竟我们搞编程的实在难有机会在父辈面前露露手。本来是想写个很简单的东西，但由于过程中老爸的多次嘲讽，逼得我不得不尽力完善，最后形成了一个小小的产品。&lt;/p&gt;
&lt;p&gt;接触Python是2010年，相见恨晚，去年拿它写了些小玩意，离职前给前公司留下了一个Python+wxPython的工作工具，还挺受欢迎。换公司后努力学习C++&amp;amp;Qt，很后悔当初选择了wxPython而不是PyQt，没能一脉相承。使用Qt越久，不得不越来越喜欢，写这个东西正好就用上了。&lt;/p&gt;
&lt;p&gt;话不多说，进入正题。这不是一篇完整的代码讲解，只是过程中的一些技术做个分享，包括后来被放弃的一些技术点。当初搜索这些东西也挺费力的，在这做个笔记，后来者也许能搜到收益。&lt;/p&gt;
&lt;p&gt;先上个图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://pic.yupoo.com/cpiz/BOTyq2xX/medium.jpg&quot; alt=&quot;QQ找茬助手&quot; title=&quot;QQ找茬助手&quot;&gt;&lt;/p&gt;
&lt;p&gt;辅助工具在游戏中增加了两个按钮，点击“对比”则自动找“茬”，用蓝色小框标识，点击“擦除”清除标识。&lt;br&gt;
    
    </summary>
    
      <category term="项目" scheme="http://cpiz.com/category/%E9%A1%B9%E7%9B%AE/"/>
    
    
      <category term="cx_Freeze" scheme="http://cpiz.com/tag/cx-Freeze/"/>
    
      <category term="PIL" scheme="http://cpiz.com/tag/PIL/"/>
    
      <category term="PyQt4" scheme="http://cpiz.com/tag/PyQt4/"/>
    
      <category term="Python" scheme="http://cpiz.com/tag/Python/"/>
    
      <category term="QQ游戏" scheme="http://cpiz.com/tag/QQ%E6%B8%B8%E6%88%8F/"/>
    
      <category term="外挂" scheme="http://cpiz.com/tag/%E5%A4%96%E6%8C%82/"/>
    
      <category term="大家来找茬" scheme="http://cpiz.com/tag/%E5%A4%A7%E5%AE%B6%E6%9D%A5%E6%89%BE%E8%8C%AC/"/>
    
  </entry>
  
  <entry>
    <title>我的手机编年史</title>
    <link href="http://cpiz.com/2012/02/26/%E6%88%91%E7%9A%84%E6%89%8B%E6%9C%BA%E7%BC%96%E5%B9%B4%E5%8F%B2/"/>
    <id>http://cpiz.com/2012/02/26/我的手机编年史/</id>
    <published>2012-02-26T08:54:29.000Z</published>
    <updated>2018-05-24T06:44:42.905Z</updated>
    
    <content type="html"><![CDATA[<p>小米弄了个<a href="http://kong.miui.com/" title="手机编年史" target="_blank" rel="noopener">手机编年史的页面</a>，让我借机回忆了一下自己的手机历史，但那个页面有文字限制，干脆借了点图片，发到博客上来。</p><p>从我拥有有手机起，这就是我最常用的工具，也是最爱的玩具。它影响了我的学习、改变了我的爱好，甚至还可能改变我的事业，关于手机的回忆，也关于自己的回忆。</p><p><strong>波导S1820：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/10/10356.jpg" alt="" title="波导S1820"></p><p>大一读了几个月后从老妈手里继承而来，走的是双屏翻盖路线，银色外壳、绿光单色屏、单音铃声，典型女式手机外形。极小的短信容量，容易掉漆的塑料外壳，后来因电池问题经常自动关机。那会儿正是国产手机最火爆的时候，但它严重打击了我对国产的信心，没多久爸妈的联想海尔也相继阵亡。</p><p>换新机后150元处理给了手机贩子</p><p><strong>诺基亚3108：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/13/13664.jpg" alt="" title="诺基亚3108"></p><p>04年10月购入，我真正拥有的第一台手机。128*128彩屏、MIDI铃声，没有摄像头，但有风骚的手写输入且稳定可靠，此机多次从一米八的床上摔落成数片而原地满血复活，从此开始向每一个人推荐诺基亚。最重要的是它支持j2me，尽管程序体积最大仅允许64k，游戏也都很烂，但看看电子书还是可以的，从此阅读小说成了它最主要的工作。后来我还自学j2me，并按自己的需求开发了一套手机电子书及制作软件<a href="http://cpiz.net/blog/2007/03/cbook-222/" title="CBook" target="_blank" rel="noopener">CBook&amp;CBookBuilder</a>，收到了很多机友的赞誉。独乐乐不如众乐乐，这目前仍是我最得意的事情之一。</p><p><strong>SPV E200</strong>：</p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/13/13880.jpg" alt="" title="SPV E200"></p><p>05年12月950购入，我的第一台智能机，水货+二手。那时候大家都没听过HTC，跟人得说这是多普达535。WindowsMobile 5.0系统，又厚又重，使用MMC存储卡，这卡现在好像已经绝迹了。能拍照、听音乐、看视频、QQ、MSN，还能用VNC走蓝牙遥控电脑，更二逼的是可以开着电脑用蓝牙共享宽带躲被窝里手机上网，这些确实让我大开了眼界。但由于微软的定式思维，WM的结构和交互都照搬桌面Windows，不友好也不稳定，基本的电话短信功能都不好用。拿着它就像是带了台有电话功能的旧电脑，很怕误事，这让对WM很失望，智能手机必须先是手机，否则就是舍本逐末。</p><p>此机后来因工艺与年龄问题，存储卡槽、按键、振动均出现问题，被300块转出，此后我继续使用以前的3108，并开发了上面提到的CBook。</p><p><strong>诺基亚6070：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/16/16038.jpg" alt="" title="诺基亚6070"></p><p>06年10月1000块购入，以前的3108转给老爸。被E200折腾后破碎的心需要一台稳定可靠的手机来安慰，Symbian价格超出承受，这款6070各方面都及其适合：有摄像头，128*160的分辨率看书时比以前的3108能多显示两行文字，java程序最大体积达到128k，红外接口正好与当时新购的笔记本电脑交互数据。</p><p>因为自学过j2me，毕业设计课题分配时被学院人气最高的万老师点名要走，在这台手机上移植了当时火热的泡泡堂游戏，以一种写教程的要求完成并公开了论文与源码，从被盗用及被咨询的次数来看，确实也帮助了一些人。毕业后曾有公司邀我去做手机开发，但因我当时并不看好j2me而没有接受，后来果然。</p><p>这是我目前为止使用时间最长的一台手机。</p><p><strong>诺基亚E51：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/18/18472.jpg" alt="" title="诺基亚E51"></p><p>08年7月1950购入，缘于和Potter的一次闲谈。Potter大学高我一级，又是老乡，超级手机控，技术好，从经典的西门子6188开始玩起，后来开发过WM平台上著名的来电归属软件<a href="http://wstart.cn/bbs/article.php?filename=2&amp;extra=page%3D1" target="_blank" rel="noopener">CallerLoc</a>。我之前的E200就是他推荐，写CBook时也曾受他帮助。</p><p>那时候我毕业一年多，很久不见Potter，约了个时间出来吃饭聊天，他给我秀了下WM手机中基于基站定位的Google地图，又让我开了回眼界。那天我们讨论了很多基于基站定位的服务，觉得这能吸引人，很想做点东西出来玩（但没能想出如何免于被腾讯抄袭）。他WM开发拿手，我就去学Symbian平台，当晚就挑下了这款E51并淘宝下单，可惜后来因为工作折腾将这事完全搁置，此后我再也没能出过像当年CBook一样有意义的业余作品。</p><p>今天，有个叫LBS的热词就是用来指代我们当时所设想的那些业务，而Potter当时最有意思的那个想法现在也有了实现——一个叫“飘信”的LBS交友服务。不知道我们当时铁了心做下去会是什么样子……很可能会失败，但应该很有意思。</p><p>回到E51，这手机我当时写过一个入手一周评测，列了一些不足，但它是我用过最舒服的一台手机。纤薄小巧、显示细腻、操作流畅、电力持久，最重要是保持了诺基亚产品一贯的稳定。与WM相比，这是一台带了电脑功能的手机，而且S60 V3系统应用繁多，根本想不出须要我自己开发的需求。</p><p>E系列是诺基亚Symbian最后的经典，特别是E71、E72，抢了不少原属于黑莓的风光。可惜诺基亚没有正视自己与苹果的差距，后来的S60 V5系统惨败于触屏时代，大家甚至开始担心它要破产。</p><p><strong>HTC Magic（G2）：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/21/21473.jpg" alt="" title="HTC G2(MAGIC)"></p><p>10年1月，当在同事的G1上看到触控操作的Google地图、重力感应的Google星空后，我立刻中了Android的毒。实际上我一直就在等着好用的Android触屏手机问世，因为之前给老婆买的5800让我对诺基亚很失望，S60 V5与电阻触摸屏结合非常低劣，是个诺基亚搪塞V3粉丝的作品。</p><p>G2的设计时尚漂亮，以至于网络上很长一段时间都在用它的形象来代表Android手机。从2010年开始，Android呈井喷式发展，曾经作为第二款Android手机风光无限的它很快就被后来者超越，新出的应用也越来越吃资源，后来除了乖乖看书看地图，我连游戏都不敢装。</p><p>这是我最享受的一台手机，外观与颜色曾吸引了不少人的注目，GPS地图带我过去很多陌生的地方，单手持握大小刚好，可惜生得太早。</p><p><strong>iPhone4：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/23/23850.jpg" alt="" title="iPhone4"></p><p>11年7月，追了那么多年的手机后拿上IP4，立刻就能意识到——这已是终点。苹果几乎把你可能想到的都做好了，纵使别家花样万千，我以一款敌之足矣。苹果的胜利是全方位的，显示、性能、操控、平台、工艺、成本，虽然满街都是IP4，但我仍然觉得它与这世界格格不入，它来自未来。</p><p><strong>小米M1：</strong></p><p><img src="http://attach.bbs.miui.com/forum/phone_imgsall/90/90000.jpg" alt="" title="小米M1"></p><p>人生奇妙，小米出生的时候，雷军学乔布斯做了一场盛大的发布会，我觉得这手机不错，但雷军很遥远。过两个月我换了份工作，管雷军得改口叫雷总，还能有机会一睹真容。我的这台小米，是为产品挑了不少Bug被公司质量部奖励得来的。</p><p>关于小米，想说的东西很多，改天另写一篇。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;小米弄了个&lt;a href=&quot;http://kong.miui.com/&quot; title=&quot;手机编年史&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;手机编年史的页面&lt;/a&gt;，让我借机回忆了一下自己的手机历史，但那个页面有文字限制，干脆借了点图片，发到博客上来
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="手机" scheme="http://cpiz.com/tag/%E6%89%8B%E6%9C%BA/"/>
    
  </entry>
  
  <entry>
    <title>年度2011</title>
    <link href="http://cpiz.com/2012/01/02/%E5%B9%B4%E5%BA%A62011/"/>
    <id>http://cpiz.com/2012/01/02/年度2011/</id>
    <published>2012-01-02T15:42:59.000Z</published>
    <updated>2018-05-26T03:44:48.720Z</updated>
    
    <content type="html"><![CDATA[<p>2011过去了，《Diablo III》仍没发布，GFW依旧嚣张，改变完世界的本拉登与乔布斯已经不在，我还没二够不愿奔三。</p><p>这一年发生了那么多的事，摘录一点点与自己的相关：</p><h3 id="年度人生——完婚"><a href="#年度人生——完婚" class="headerlink" title="年度人生——完婚"></a>年度人生——完婚</h3><blockquote><p>09年领的结婚证，受房子、工作及各种迷信的影响，11年的5月、6月才分别在妻与我的老家摆酒完婚。一个江西的独子与一个福建的独女结合在广州，一路酸甜苦辣，不由得感叹命运无常。</p><p><img src="http://pic.yupoo.com/cpiz/B9ZhR5br/medium.jpg" alt="" title="喜糖"></p></blockquote><h3 id="年度事业——转职-amp-换行"><a href="#年度事业——转职-amp-换行" class="headerlink" title="年度事业——转职&amp;换行"></a>年度事业——转职&amp;换行</h3><blockquote><p>这一年，妻在我的鼓动下成功转职，从黑盒测试变成了产品经理。而我也在她的推荐下成功转行，从电信换到了互联网。我们都相信勤劳上进的聪明人理当获得体面的生活 ，没有李刚、金正日这样的名爹，我们也不能让儿女失望，只是宝贝对不起，你得迟一点再出来闯荡。</p></blockquote><h3 id="年度生活——跑步与登山"><a href="#年度生活——跑步与登山" class="headerlink" title="年度生活——跑步与登山"></a>年度生活——跑步与登山</h3><blockquote><p>10个IT工人为了50元买到Nike衫，组个队叫“复杂体力劳动者”，竟然完成了10公里的挑战。感叹奇迹的同时，现在锻炼应该不算太晚。跑步、登攀，甩掉肮脏的汗，见见各处的山，也许真的有世界末日，得有点力气才能逃票上船。</p><p><img src="http://pic.yupoo.com/cpiz/Bw3mfecQ/medium.jpg" alt=""></p></blockquote><h3 id="年度人物——筷子兄弟、罗永浩、韩寒"><a href="#年度人物——筷子兄弟、罗永浩、韩寒" class="headerlink" title="年度人物——筷子兄弟、罗永浩、韩寒"></a>年度人物——筷子兄弟、罗永浩、韩寒</h3><blockquote><p>有理想的青年，在有理想的国度叫普通青年，在没理想的国度叫傻逼青年。别人怎么想你不重要，不当咸鱼的滋味，只有你自己知道。筷子兄弟、罗永浩、韩寒，2011感谢同行有你。</p><p><img src="http://pic.yupoo.com/cpiz/BDEiju7s/medium.jpg" alt="" title="老男孩"><br>[anyplayer:url=<a href="http://www.119yy.com/mp3/laonanhai.mp3" target="_blank" rel="noopener">http://www.119yy.com/mp3/laonanhai.mp3</a> title=筷子兄弟-《老男孩》 type=MP3]</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;2011过去了，《Diablo III》仍没发布，GFW依旧嚣张，改变完世界的本拉登与乔布斯已经不在，我还没二够不愿奔三。&lt;/p&gt;
&lt;p&gt;这一年发生了那么多的事，摘录一点点与自己的相关：&lt;/p&gt;
&lt;h3 id=&quot;年度人生——完婚&quot;&gt;&lt;a href=&quot;#年度人生——完婚&quot; c
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="工作" scheme="http://cpiz.com/tag/%E5%B7%A5%E4%BD%9C/"/>
    
      <category term="总结" scheme="http://cpiz.com/tag/%E6%80%BB%E7%BB%93/"/>
    
      <category term="青春" scheme="http://cpiz.com/tag/%E9%9D%92%E6%98%A5/"/>
    
      <category term="理想" scheme="http://cpiz.com/tag/%E7%90%86%E6%83%B3/"/>
    
      <category term="生活" scheme="http://cpiz.com/tag/%E7%94%9F%E6%B4%BB/"/>
    
  </entry>
  
  <entry>
    <title>深圳世界之窗</title>
    <link href="http://cpiz.com/2011/11/21/%E6%B7%B1%E5%9C%B3%E4%B8%96%E7%95%8C%E4%B9%8B%E7%AA%97/"/>
    <id>http://cpiz.com/2011/11/21/深圳世界之窗/</id>
    <published>2011-11-20T16:53:10.000Z</published>
    <updated>2018-05-26T03:40:56.085Z</updated>
    
    <content type="html"><![CDATA[<p>随老婆参加在深圳世界之窗举行的腾讯13周年嘉年华。</p><p>十几年前做小孩的时候去过一次长沙世界之窗，当时觉得那些模拟建筑都像玩具，没感觉出什么特别，也许深圳的会更好一些。这回真去深圳看了一次，感觉仍然一样，终于绝望。</p><p>那些建筑确实是人类的艺术精华，但都是和当地的文明背景互相成就的，就像树与大地的关系。我们能搬来树，但搬不了它生长的大地，那它也只是棵普通的植物而已，何况还是年久失修的猥琐微缩版……逛了一天没留下多少照片，还是贴几张。</p><p><img src="http://pic.yupoo.com/cpiz/Bx6Sdmpu/medium.jpg" alt="IMG_5630"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6RWEHw/medium.jpg" alt="IMG_5625"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6SijLI/medium.jpg" alt="IMG_5640"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6SqYce/medium.jpg" alt="IMG_5648"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6SNkif/medium.jpg" alt="IMG_5669"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6TJ5ay/medium.jpg" alt="IMG_5682"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6U7CQk/medium.jpg" alt="IMG_5694"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6UT9ZC/medium.jpg" alt="IMG_5704"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6VNiMU/medium.jpg" alt="IMG_5713"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6XnHBG/medium.jpg" alt="IMG_5738"></p><p><img src="http://pic.yupoo.com/cpiz/Bx6Y6ck4/medium.jpg" alt="IMG_5755"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;随老婆参加在深圳世界之窗举行的腾讯13周年嘉年华。&lt;/p&gt;
&lt;p&gt;十几年前做小孩的时候去过一次长沙世界之窗，当时觉得那些模拟建筑都像玩具，没感觉出什么特别，也许深圳的会更好一些。这回真去深圳看了一次，感觉仍然一样，终于绝望。&lt;/p&gt;
&lt;p&gt;那些建筑确实是人类的艺术精华，但都
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="摄影" scheme="http://cpiz.com/tag/%E6%91%84%E5%BD%B1/"/>
    
      <category term="旅游" scheme="http://cpiz.com/tag/%E6%97%85%E6%B8%B8/"/>
    
  </entry>
  
  <entry>
    <title>LUNAR RUN耐克10公里（下）</title>
    <link href="http://cpiz.com/2011/11/14/LUNAR%20RUN%E8%80%90%E5%85%8B10%E5%85%AC%E9%87%8C%EF%BC%88%E4%B8%8B%EF%BC%89/"/>
    <id>http://cpiz.com/2011/11/14/LUNAR RUN耐克10公里（下）/</id>
    <published>2011-11-13T17:14:00.000Z</published>
    <updated>2018-05-26T03:44:48.565Z</updated>
    
    <content type="html"><![CDATA[<img src="/2011/11/14/LUNAR%20RUN耐克10公里（下）/SpxImage.png"><p>提前一天拿到了运动套件：一件战衣、一张贴有芯片的号码牌、一个简单的背包袋，都橙得耀眼。11月12日，终于在一个好天气到来了。</p><p>原本约好在广州大剧院会合，但我们完全低估了活动的规模。从上公交开始，看到越来越多穿橙色Nike衫的男女女女，到达花城广场后，点点橙光汇成橙色的洪水与湖泊，哪里还分得清脸孔，老婆说她的感觉是被橙色包围了。</p><p>跑步10公里路的线从花城广场出发，通过海心沙，环绕二沙岛一周后再绕花城广场一周到达终点，参赛者1万5千人。Nike为了这个活动投入了巨大的资源，舞台、音响、摄影器材、广场所有的液晶屏幕、各种临时功能建筑，加上各种服务人员、参赛者、游客填满了整个广场，城市的活力张显到了极致，所有人都提前兴奋了起来。</p><p>比赛即将开始，10个队友中还有2个无法联系上，老婆可怜地成为了全队的物管员。我们8个人挪到了起点区，原以为9点就能开跑，哪知还有一堆市领导介绍与致辞，虽然能够理解一家商业公司要举办这么大的活动绝对不能缺少政府支持，但我们还是忍不住在广播介绍每一个领导出场后高喊一声粤骂“丢~”，场面滑稽。</p><p>开跑，经过起点时看到上面的计时已经是10分多钟，对着头顶吊臂下的摄像机一阵挥手，打开手机里的Endomondo开始记录。</p><p>前面一段路简直就是游园会，基本靠走。也许是免费进入海心沙公园的机会难得，有些参赛者就在里面逛了起来，到达1公里里程碑处后，又有不少男女靠上去拍照纪念。第2公里感觉渐渐上来，8人的队伍不得已分开成几拨，我与子高、德军在第一梯队。到第3公里时，德军先行，剩下我和子高继续互相鼓励。</p><p>二沙岛是广州的一块宝地，环境整洁、空气清新，在树荫里奔跑起来浑身舒畅。观察每个跑步者的姿态，欣赏各种队名也很有乐趣，一路上还有组织方安排的DJ、敲非洲鼓的美女乐团、摇铃铛的啦啦队，毫不枯燥。平常跑到5公里是一个槛，这次双腿却依然感觉良好、体能输出正常。</p><p>第7公里后回到花城广场，眼看终点在望不觉加快了脚步，这打破了体能输出的平衡，身体越来越累。之前我一路在鼓励子高，到最后一公里时已经只顾着大口喘气说不出话，剩下子高不停在提示“200米”、“100米”、“50米”、“20米”……跑过终点的那一刻，那感觉——真是糟透了:)，依稀记得头顶计时牌上是1小时零x分。</p><p>每一个到达目标的人都是胜利者，终点后无数人群在为我们喝彩，一列MM与我们一一击掌，工作人员体贴地为每人发放了饮料、香蕉（补钾），还有……金牌！对，金色的奖牌，这辈子从未得过的宝贝！第一次长跑比赛，真的完成了10公里，而且速度与身体状态都超过预期。虽然有很多人比我提早到达，但我已非常满足。</p><p>陆续地队友们渐渐到齐，包括之前没联系上的2人，全队都完成了10公里。大家聚在一起分享欢乐，用各种普通的、文艺的、二逼的Pose拍照留念，中午再一起腐败了一顿。</p><p><img src="http://pic.yupoo.com/cpiz/BvYZNwZ2/medium.jpg" alt="全程路线" title="全程路线"></p><p><img src="http://pic.yupoo.com/cpiz/BvZ6qaUD/medium.jpg" alt="普通青年合影" title="普通青年合影"></p><p><img src="http://pic.yupoo.com/cpiz/BvZ6vQLH/medium.jpg" alt="二逼青年合影" title="二逼青年合影"></p><p><img src="http://pic.yupoo.com/cpiz/BvZfgXvX/medium.jpg" alt="本青年留影" title="本青年留影"></p><p><img src="http://pic.yupoo.com/cpiz/BvYZ6p6D/medium.jpg" alt="战衣" title="战衣"></p><p><img src="http://pic.yupoo.com/cpiz/Bw3mfecQ/medium.jpg" alt="奖牌" title="奖牌"></p><p><img src="http://pic.yupoo.com/cpiz/Bw7YXapk/medium.jpg" alt="证书" title="证书"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;img src=&quot;/2011/11/14/LUNAR%20RUN耐克10公里（下）/SpxImage.png&quot;&gt;
&lt;p&gt;提前一天拿到了运动套件：一件战衣、一张贴有芯片的号码牌、一个简单的背包袋，都橙得耀眼。11月12日，终于在一个好天气到来了。&lt;/p&gt;
&lt;p&gt;原本约好在广州大剧
      
    
    </summary>
    
      <category term="生活" scheme="http://cpiz.com/category/%E7%94%9F%E6%B4%BB/"/>
    
    
      <category term="摄影" scheme="http://cpiz.com/tag/%E6%91%84%E5%BD%B1/"/>
    
      <category term="跑步" scheme="http://cpiz.com/tag/%E8%B7%91%E6%AD%A5/"/>
    
      <category term="运动" scheme="http://cpiz.com/tag/%E8%BF%90%E5%8A%A8/"/>
    
  </entry>
  
</feed>
