<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[Redanula's Blog]]></title>
  
  <link href="/atom.xml" rel="self"/>
  <link href="http://yoursite.com/"/>
  <updated>2018-10-17T04:51:55.198Z</updated>
  <id>http://yoursite.com/</id>
  
  <author>
    <name><![CDATA[Redanula]]></name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title><![CDATA[CocoaPods自建库]]></title>
    <link href="http://yoursite.com/2018/10/11/2018-10-11/"/>
    <id>http://yoursite.com/2018/10/11/2018-10-11/</id>
    <published>2018-10-11T12:30:41.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"></content>
    <summary type="html">
    
    </summary>
    
      <category term="CocoaPods" scheme="http://yoursite.com/tags/CocoaPods/"/>
    
      <category term="iOS" scheme="http://yoursite.com/tags/iOS/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS白板同步绘制方案调研]]></title>
    <link href="http://yoursite.com/2018/09/24/2018-09-24/"/>
    <id>http://yoursite.com/2018/09/24/2018-09-24/</id>
    <published>2018-09-24T07:30:59.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<h3 id="Apple_Pencil绘制原理">Apple Pencil绘制原理</h3><p><img src="/images/15377762585144.png" alt=""></p>
<ul>
<li>Apple Pencil 可以额外采集到 altitude（高度角）、azimuth（方位角）、force（压感值）</li>
<li>关于force压感值（3D Touch）：force乘以一个压感系数sensitivity(自定义)，计算一个两点之前的线宽linewidth(force * sensitivity)，来实现压力不同线宽不同功能</li>
<li>关于altitude角度：一般用来绘画阴影部分，如角度小于30°的时候，可以模拟素描阴影的绘制</li>
<li>关于合并：Apple Pencil的捕获频率为240Hz,UIKit一般捕获触摸的频率为60Hz，这意味着Apple Pencil可以捕捉到更多的点，UIKit会把Apple Pencil捕获的多余的点合并到最后一个触摸点的UITouch对象里。</li>
<li>关于预估：iOS9以后UITouch可以实时返回预估的笔迹</li>
</ul>
<p><strong>以上的场景，使用force、altitude的计算、或处理合并的所有点均会增加绘制过程中的点阵数据包的大小，同时绘制的系数也需要调优减少可能造成的锯齿，如果是互动白板传输数据的场景（如腾讯在线课堂、网易白板等），都没有使用压感和角度的功能。如果是本地高精度的绘画应用，均是可以实现的。具体是否需要可以根据后续需求来定。后续会针对这一块（使用force、altitude、合并、预估笔迹）做预研和压力测试是否可行，增大笔迹包流量下的性能、消息丢失统计、体验、延时等的性价比综合对比分析</strong></p>
<p>详情见：<a href="https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_input_from_apple_pencil?language=objc" target="_blank" rel="noopener">Handling Input from Apple Pencil</a></p>
<h3 id="iOS端白板绘制实现方案">iOS端白板绘制实现方案</h3><p>调研了目前网上白板的实现方式，基于不考虑压感值和角度的采集的情况下，都是基于UIResponder实现的，考虑优先实现一个画板的基础功能（撤销、恢复、橡皮等），实现方案有以下几种：</p>
<h4 id="1-UIBezierPath➕drawRect实现">1.UIBezierPath➕drawRect实现</h4><p>优点：实现简单<br>缺点：实现撤销、恢复等功能需要重绘调用drawRect，在累计笔迹大量的情况下，频繁刷新drawRect会导致内存过大</p>
<h4 id="2-Quartz2D➕drawRect实现">2.Quartz2D➕drawRect实现</h4><p>优点：UIBezierPath其实是Quartz2D的封装，实现简单<br>缺点：因为重写了drawRect的方法，和方案一同样有笔迹过多的情况下内存过大的问题</p>
<h4 id="3-UIBezierPath➕CAShapeLayer实现">3.UIBezierPath➕CAShapeLayer实现</h4><p>优点：撤销、恢复等功能实现简单，内存小<br>缺点：橡皮实现较为复杂，需要注意优化计算量</p>
<h4 id="4-OpenGLES实现">4.OpenGLES实现</h4><p>优点：实现自由度最高，性能理论可以调到最优<br>缺点：开发复杂，学习成本高，所有功能（橡皮、撤销、恢复、矩形等）需要采坑实现及调优</p>
<p>参考了大部分源码,一个高性能的白板基本采用方案三 UIBezierPath➕CAShapeLayer 实现</p>
<h3 id="画板绘制流程">画板绘制流程</h3><h4 id="采集">采集</h4><p>每一个笔迹在开始、结束、移动的过程中有起始点B、终点E及移动点阵M1,M2,…,MN存在，iPad端绘制的同时会采集这些点阵通过NATS传输供学生端绘制，采集的通用格式为：</p>
<pre><code>{
    <span class="string">"n"</span>:<span class="number">1</span>, <span class="comment">// 序号 no</span>
    <span class="string">"c"</span>:<span class="number">1</span>, <span class="comment">// 笔画颜色 color</span>
    <span class="string">"l"</span>:<span class="number">1</span>, <span class="comment">// 笔画宽度 line</span>
    <span class="string">"s"</span>:<span class="number">0</span>, <span class="comment">// 分片数量 sub number</span>
    <span class="string">"o"</span>:<span class="number">0</span>, <span class="comment">// 分片序号 sub order</span>
    <span class="string">"e"</span>:<span class="number">0</span>, <span class="comment">// 画线类型0默认 1直线 2椭圆 3矩形 4橡皮擦等</span>
    <span class="string">"a"</span>:<span class="number">0</span>, <span class="comment">// 操作类型action: 1 正常绘图 2 撤销 3 恢复 4 清空等</span>
    <span class="string">"t"</span>:<span class="number">10000</span>, <span class="comment">// 时间戳 timestamp</span>
    <span class="string">"w"</span>:<span class="number">1024</span>, <span class="comment">// 画板高度</span>
    <span class="string">"h"</span>:<span class="number">768</span>, <span class="comment">// 画板宽度</span>
    <span class="string">"d"</span>:[{<span class="string">"x"</span>:<span class="number">10.5</span>,<span class="string">"y"</span>:<span class="number">10.5</span>},{<span class="string">"x"</span>:<span class="number">20.5</span>,<span class="string">"y"</span>:<span class="number">20.5</span>}]  <span class="comment">// x,y为坐标</span>
}
</code></pre><p>其中，d的数组实际就是</p>
<pre><code>[B,M1,M2,...,MN,E]
</code></pre><p>针对每个笔迹，归类为以下绘制方式，值为e（0默认 1直线 2椭圆 3矩形 4橡皮擦）：<br>默认笔画（曲线）：对相邻的点做贝塞尔曲线（BezierPath），BezierPath分多个阶段，高阶的曲线更圆滑</p>
<h4 id="贝塞尔曲线说明">贝塞尔曲线说明</h4><p><a href="https://zh.wikipedia.org/zh-cn/貝茲曲線" target="_blank" rel="noopener">贝塞尔曲线</a><br><a href="https://developer.apple.com/documentation/uikit/uibezierpath?language=objc：" target="_blank" rel="noopener">Apple UIBezierPath</a></p>
<p><img src="/images/15397483774667.gif" alt=""></p>
<h4 id="曲线的优化计算">曲线的优化计算</h4><p>1.移动到起始点 N1<br>2.当累计点到N2,N3,N4的时候，计算N2和N4的中点N3, 覆盖原来的N3点；<br>3.以N1为起始点对N3画一条二阶贝塞尔曲线，控制点为N2和N4<br>4.将N3做为起始点N1，N4作为第一个累计点N2，回到第一步</p>
<p>详细参考：<a href="https://code.tutsplus.com/tutorials/smooth-freehand-drawing-on-ios--mobile-13164" target="_blank" rel="noopener">Smooth Freehand Drawing</a></p>
<p>直线：取第一个点B和最后一个点E,画一条直线<br>矩形：取第一个点B和最后一个点E,范围内画一个矩形，需要注意起始点和终点的向量方向<br>椭圆：取第一个点B和最后一个点E,范围内画一个椭圆，需要注意起始点和终点的向量方向<br>点：当B和E的坐标相等时，就画一个点</p>
<p>动作，值a（1 正常绘图 2 撤销 3 恢复 4 清空等）：<br>撤销：pop撤销栈最后一个临时图片并push恢复栈，渲染<br>恢复：pop恢复栈最后一个临时图片并push撤销栈，渲染<br>清空：清空所有栈及当前画板</p>
<h4 id="点阵分片及重组">点阵分片及重组</h4><p>笔迹传输是按照每个笔迹采集的，如果一个笔迹的点阵数量过大，可以分片处理，NATS消息体里面会表示s和o表示分片的数量及序号，接收端需要收到全部分片后进行点阵d的数组重组及绘制。</p>
<h4 id="时间戳">时间戳</h4><p>需要和视频流里面的时间戳消息做对比，小于视频流时间戳的时候才显示笔迹。</p>
]]></content>
    <summary type="html">
    <![CDATA[<h3 id="Apple_Pencil绘制原理">Apple Pencil绘制原理</h3><p><img src="/images/15377762585144.png" alt=""></p>
<ul>
<li>Apple Pencil 可以额外采集到 altitude（高]]>
    </summary>
    
      <category term="白板" scheme="http://yoursite.com/tags/%E7%99%BD%E6%9D%BF/"/>
    
      <category term="Apple Pencil" scheme="http://yoursite.com/tags/Apple-Pencil/"/>
    
      <category term="UIBezierPath" scheme="http://yoursite.com/tags/UIBezierPath/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Travis CI 持续部署Hexo博客到GitHub Page和VPS服务器]]></title>
    <link href="http://yoursite.com/2018/08/28/travis_ci_auto_deploy_hexo_to_vps/"/>
    <id>http://yoursite.com/2018/08/28/travis_ci_auto_deploy_hexo_to_vps/</id>
    <published>2018-08-28T04:00:00.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<h3 id="写在前面">写在前面</h3><blockquote>
<p>N久之前在GitHub Page上部署了Hexo，本地生成文章的时候需要<code>hexo g&amp;&amp;hexo d</code>等步骤才能上传到GitHub，最近又把博客折腾到了VPS上，手动deploy到VPS的同时又不能更新GitHub上，因此搜索了一下解决方案，发现可以实现git flow push到source后，使用Travis CI 持续集成自动deploy到GitHub Page，同时推送到VPS服务器。</p>
</blockquote>
<h3 id="构建流程">构建流程</h3><h4 id="基本准备：">基本准备：</h4><ul>
<li>GitHub Source 即博客源码仓库，以下称为Source</li>
<li>GitHub Page 静态页仓库</li>
<li>配置好Nginx，git等环境的VPS</li>
</ul>
<h4 id="构建流程如下：">构建流程如下：</h4><ol>
<li>新增或修改了文章，push到GitHub的source</li>
<li>Travis CI 发现source改变后自动执行配置好的脚本，生成静态页面</li>
<li>Travis 推送静态页面文件到VPS服务器</li>
<li>Travis push静态页面到GitHub</li>
</ol>
<h3 id="GitHub_和_Travis_设置">GitHub 和 Travis 设置</h3><p>因为之前已经建好Blog的仓库和GitHub Page的仓库了，这些网上都很多教程，并不复杂，就直接记录如何让Source的仓库和Travis关联的步骤：</p>
<ol>
<li><p>进入GitHub的Setting页面</p>
<p> <img src="/images/15354229059347.jpg" alt=""></p>
</li>
<li><p>选择Developer settings<br> <img src="/images/15354230831184.jpg" alt=""></p>
</li>
<li><p>选择Personal access tokens，生成Travis需要的access token<br> <img src="/images/15354231182717.jpg" alt=""></p>
</li>
<li><p>填写一个token的描述，如hexoblog，选择repo，然后Generate token即可</p>
<p> <img src="/images/15354232588232.jpg" alt=""></p>
</li>
<li><p>这里要复制下生成的token（只允许看见一次），在Travis那边可以使用<br>  <img src="/images/15354239349022.jpg" alt=""></p>
</li>
<li><p>打开 <a href="https://travis-ci.org" target="_blank" rel="noopener">Travis</a> 网站(<a href="https://travis-ci.org" target="_blank" rel="noopener">https://travis-ci.org</a>) ,org后缀的才是对GitHub Public仓库免费的，com的针对是付费的私有仓库的。使用GitHub账号登录。</p>
<p> <img src="/images/15354244967581.jpg" alt=""><br></p>
</li>
<li>网上很多教程说需要打开<code>Build only if .travis.yml is present</code>选项（.travis.yml存在才生成），但最新的设置好像没有这个选项了，这里也不会有影响，然后需要Add一个Token, 新增一个HEXO_TOKEN，ValuE那里填写刚刚GitHub复制的access token即可。<br>iv和key是后面VPS那边自动生成的，这里可以先忽略。配置完以后就需要到博客仓库<code>.travis.yml</code>文件了。<br><img src="/images/15354245505828.jpg" alt=""></li>
</ol>
<h3 id="本地配置">本地配置</h3><ol>
<li><p>在本地Blog根目录下新建.travis.yml文件，配置如下：<br> 其中<code>github.com/redanula/redanula.github.com.git</code>为GitHub Page的仓库，<code>HEXO_TOKEN</code>为Travis刚刚Travis配置的token的标识。</p>
<pre><code>language: node_js
node_js: stable
cache:
  apt: true
  directories:
  -<span class="ruby"> node_modules
</span>before_install:
-<span class="ruby"> export <span class="constant">TZ</span>=<span class="string">'Asia/Shanghai'</span>
</span>install:
-<span class="ruby"> npm install
</span>script:
-<span class="ruby"> hexo clean
</span>-<span class="ruby"> hexo g &amp;&amp; gulp
</span>after_script:
-<span class="ruby"> git clone <span class="symbol">https:</span>/<span class="regexp">/${GH_REF} .deploy_git
</span></span>-<span class="ruby"><span class="regexp"> cd .deploy_git
</span></span>-<span class="ruby"><span class="regexp"> git checkout master
</span></span>-<span class="ruby"><span class="regexp"> cd ../</span>
</span>-<span class="ruby"> mv .deploy_git/.git/ ./public/
</span>-<span class="ruby"> cd ./public
</span>-<span class="ruby"> git config user.name <span class="string">"redanula"</span>
</span>-<span class="ruby"> git config user.email <span class="string">"yanglangjing@hotmail.com"</span>
</span>-<span class="ruby"> git add .
</span>-<span class="ruby"> git commit -m <span class="string">"Travis CI Auto Builder at `date +"</span>%<span class="constant">Y</span>-%m-%d %<span class="constant">H</span><span class="symbol">:%M<span class="string">"`"</span></span>
</span>-<span class="ruby"> git push --force --quiet <span class="string">"https://${HEXO_TOKEN}@${GH_REF}"</span> <span class="symbol">master:</span>master
</span>branches:
  only:
  -<span class="ruby"> master
</span>env:
  global:
  -<span class="ruby"> <span class="constant">GH_REF</span><span class="symbol">:</span> github.com/redanula/redanula.github.com.git
</span>notifications:
  email:
  -<span class="ruby"> yanglangjing<span class="variable">@hotmail</span>.com
</span>  on_success: change
  on_failure: always
</code></pre></li>
<li><p>提交<code>.travis.yml</code>文件到GitHub，这时候GitHub Page就会自动生成了。可以打开<a href="https://travis-ci.org" target="_blank" rel="noopener">Travis</a>查看对应的Current构建过程。首次提交的之后，发现生成的 <a href="https://redanula.github.io" target="_blank" rel="noopener">redanula.github.io</a> 是空白的，找了下原因是因为使用的next主题没有在Source仓库的hexo theme的目录，add &amp; push对应的主题到Source仓库之后就成功了。接下来就是服务器的工作了。<br> <img src="/images/15354264456856.jpg" alt=""></p>
</li>
</ol>
<h3 id="VPS服务器配置">VPS服务器配置</h3><ol>
<li><p>ssh登录VPS服务器，安装Travis服务<br>先安装ruby 如果提示如下：<br>current directory: /var/lib/gems/2.3.0/gems/ffi-1.9.25/ext/ffi_c<br>/usr/bin/ruby2.3 -r ./siteconf20180821-29696-1onq3fa.rb extconf.rb<br>mkmf.rb can’t find header files for ruby at /usr/lib/ruby/include/ruby.h<br>需要安装对应的ruby包:</p>
<pre><code><span class="preprocessor"># 如果是在centos等系统下面，执行命令：</span>
yum install ruby-devel 

<span class="preprocessor"># 如果是在Ubuntu等系统下面，执行命令:</span>
apt-<span class="keyword">get</span> install ruby-dev  

<span class="preprocessor"># 安装travis命令行工具，gem指令需要先安装ruby</span>
gem install travis
</code></pre></li>
<li><p>新增一个Git账号</p>
<pre><code><span class="keyword">adduser </span>git
</code></pre></li>
<li><p>赋予git用户sudo权限</p>
<pre><code><span class="keyword">chmod</span> 740 /etc/sudoers
<span class="keyword">vim</span> /etc/sudoers

<span class="comment"># User privilege specification 在root行后面增加</span>
<span class="keyword">git</span>    <span class="literal">ALL</span>=(<span class="literal">ALL</span>:<span class="literal">ALL</span>) <span class="literal">ALL</span>

<span class="comment"># 保存退出后，修改回文件权限</span>
<span class="keyword">chmod</span> 440 /etc/sudoers
</code></pre></li>
<li><p>配置SSH</p>
<pre><code><span class="comment"># 切换到git用户下</span>
su git

<span class="comment"># 生成ssh密钥对 注意密码要为空，Travis自动过程中才不会被输入密码步骤卡住，生成后目录 /home/git/.ssh/id_rsa</span>
ssh-keygen -t rsa

<span class="comment"># 设置.ssh目录为700</span>
chmod <span class="number">700</span> ~<span class="regexp">/.ssh/</span>

<span class="comment"># 设置.ssh目录下的文件为600</span>
chmod <span class="number">600</span> ~<span class="regexp">/.ssh/</span>*

<span class="comment"># 切换到.ssh/目录</span>
cd .ssh/

<span class="comment"># 将公钥内容添加到authorized_keys</span>
cat id_rsa.pub <span class="prompt">&gt;&gt; </span>authorized_keys
</code></pre></li>
<li><p>Travis配置</p>
<pre><code><span class="comment"># 在home目录下拉取Source仓库</span>
cd /home
git clone 你的仓库.git 

<span class="comment"># cd到仓库根目录</span>
<span class="comment"># 登录github帐号</span>
travis login <span class="comment">--auto</span>

<span class="comment"># 生成加密公钥文件id_rsa.enc并自动增加解密行到.travis.yml文件；-r 指向GitHub的Source仓库</span>
travis <span class="built_in">encrypt</span>-<span class="built_in">file</span> ~/.ssh/id_rsa <span class="comment">--add -r redanula/blog-hexo-source</span>
</code></pre><p> 修改.travis.yml，在before_install钩子后面添加权限处理:</p>
<pre><code>before_install:

- chmod 600 ~/.ssh/id_rsa
- echo -e <span class="string">"Host 【配置名】\n\tStrictHostKeyChecking no\n"</span> &gt;&gt; ~/.ssh/config
</code></pre><p> 修改.travis.yml，在after_success钩子后面添加推送行为：</p>
<pre><code>#/var/www/blog为博客目录
after_script:   

- rsync -rv --delete -e 'ssh -o stricthostkeychecking=no -p 对应ssh端口' public/ git@对应的IP或域名:/var/www/blog
</code></pre><p> 这里注意<code>~/.ssh/id_rsa</code>路径需要去掉travis命令自动添加的转义 \ 这里的key和iv文件就是上文图中Travis后台自动出现的两个值</p>
<pre><code>openssl aes-<span class="number">256</span>-cbc -K <span class="variable">$encrypted</span>_598a070685f0_key -iv <span class="variable">$encrypted</span>_598a070685f0_iv -<span class="keyword">in</span> id_rsa.enc -out ~/.ssh/id_rsa -d
</code></pre><p> 推送.travis.yml文件到Source（也可以vps先推送上去本地拉下来做上述几步的修改）</p>
<pre><code>git <span class="keyword">add</span> ./
git commit -m <span class="string">"Travis CI"</span>
git <span class="keyword">push</span>
</code></pre><p> 接下来就可以随意只管提交文章，Travis会自动持续集成到GitHub Page 和 服务器了：）。</p>
<pre><code>Done. Your build exited <span class="keyword">with</span> <span class="number">0.</span>
</code></pre></li>
</ol>
<h3 id="参考文章">参考文章</h3><p><a href="https://skychang.github.io/2017/01/01/Hexo-Use_Travis_CI_Auto_Deploy_Blog/" target="_blank" rel="noopener">Hexo - 使用 Travis CI 自動佈署 Blog</a><br><a href="https://segmentfault.com/a/1190000009054888" target="_blank" rel="noopener">使用 Travis 自动部署 Hexo 到 Github 与 自己的服务器</a><br><a href="https://blog.csdn.net/qq_23079443/article/details/79015225" target="_blank" rel="noopener">用TravisCI持续集成自动部署Hexo博客的个人实践</a><br><a href="https://www.noonme.com/post/2016/03/travisci-hexo-deploy/" target="_blank" rel="noopener">使用travis-ci自动部署hexo博客</a><br><a href="https://www.peteruhnak.com/blog/2016/06/06/deploying-pharo-builds-from-travis-over-ssh/" target="_blank" rel="noopener">Deploying Pharo builds from Travis over ssh</a><br><a href="https://juejin.im/post/5a9e1a5751882555712bd8e1" target="_blank" rel="noopener">Travis-CI自动化测试并部署至自己的CentOS服务器</a><br><a href="https://www.jianshu.com/p/b926ecf1c6f6" target="_blank" rel="noopener">Hexo搭建个人博客并使用Git部署到VPS</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<h3 id="写在前面">写在前面</h3><blockquote>
<p>N久之前在GitHub Page上部署了Hexo，本地生成文章的时候需要<code>hexo g&amp;&amp;hexo d</code>等步骤才能上传到GitHub，最近又把博客折腾到了VPS上，]]>
    </summary>
    
      <category term="Travis CI" scheme="http://yoursite.com/tags/Travis-CI/"/>
    
      <category term="Hexo" scheme="http://yoursite.com/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS腾讯云人脸识别]]></title>
    <link href="http://yoursite.com/2018/08/08/tencentcloudservice/"/>
    <id>http://yoursite.com/2018/08/08/tencentcloudservice/</id>
    <published>2018-08-08T14:12:15.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<h3 id="前言">前言</h3><p>工作需要做了一个简易的、通过API第三方人脸识别、人脸对比分析的App Demo，对比了一下各家提供的服务、SDK，最后选择了腾讯云的智能图像服务。<br>调用API的流程为：</p>
<pre><code><span class="number">1.</span>鉴权签名 
<span class="number">2.</span>调用人脸识别、人脸对比等API。
</code></pre><p>这里主要在iOS上模拟生成鉴权签名识别的流程，实际生产环境应该是服务器生成鉴权签名，APP调用接口识别。</p>
<h3 id="鉴权签名">鉴权签名</h3><p>云端开通服务后的Key：</p>
<pre><code><span class="hexcolor">#def</span>ine kAPPID @<span class="string">"your APPID"</span>
<span class="hexcolor">#def</span>ine kSecretId @<span class="string">"your SecretId"</span>
<span class="hexcolor">#def</span>ine kSecretKey @<span class="string">"your SecretKey"</span>
</code></pre><p>拼接签名串：</p>
<pre><code>- (<span class="built_in">NSString</span> *)getSign{

    <span class="built_in">NSDate</span>* date = [<span class="built_in">NSDate</span> dateWithTimeIntervalSinceNow:<span class="number">0</span>];<span class="comment">//获取当前时间0秒后的时间</span>
    <span class="built_in">NSDate</span>* edate = [<span class="built_in">NSDate</span> dateWithTimeIntervalSinceNow:<span class="number">60</span>*<span class="number">60</span>*<span class="number">24</span>*<span class="number">30</span>];<span class="comment">//一个月</span>
    <span class="built_in">NSTimeInterval</span> time=[date timeIntervalSince1970];<span class="comment">// *1000 是精确到毫秒，不乘就是精确到秒</span>
    <span class="built_in">NSTimeInterval</span> etime=[edate timeIntervalSince1970];<span class="comment">// *1000 是精确到毫秒，不乘就是精确到秒</span>
    <span class="built_in">NSString</span> *timeString = [<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"%.0f"</span>, time];
    <span class="built_in">NSString</span> *etimeString = [<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"%.0f"</span>, etime];
    <span class="keyword">int</span> ranInt = arc4random() %<span class="number">100000</span>;
    <span class="built_in">NSString</span> *ranString = [<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"%d"</span>, ranInt];
    <span class="built_in">NSString</span> *abketr = [<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"a=%@&amp;b=%@&amp;k=%@&amp;e=%@&amp;t=%@&amp;r=%@"</span>,
                        kAPPID,
                        <span class="string">@"tencentyun"</span>,
                        kSecretId,
                        etimeString,
                        timeString,
                        ranString
                        ];
    <span class="built_in">NSString</span> *signString = [<span class="keyword">self</span> HmacSha1:kSecretKey data:abketr];

    <span class="keyword">return</span> signString;
}
</code></pre><p>HMAC-SHA1 算法加密，注意最后需要拼接签名串到NSMutableData末尾：</p>
<pre><code><span class="comment">//HmacSHA1加密；</span>
- (<span class="built_in">NSString</span> *)HmacSha1:(<span class="built_in">NSString</span> *)key data:(<span class="built_in">NSString</span> *)data
{
    <span class="keyword">const</span> <span class="keyword">char</span> *cKey  = [key cStringUsingEncoding:<span class="built_in">NSASCIIStringEncoding</span>];
    <span class="keyword">const</span> <span class="keyword">char</span> *cData = [data cStringUsingEncoding:<span class="built_in">NSASCIIStringEncoding</span>];

    <span class="keyword">unsigned</span> <span class="keyword">char</span> cHMAC[CC_SHA1_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    <span class="built_in">NSData</span> *HMAC = [[<span class="built_in">NSData</span> alloc] initWithBytes:cHMAC length:<span class="keyword">sizeof</span>(cHMAC)];
    <span class="built_in">NSData</span> *dData = [[<span class="built_in">NSData</span> alloc] initWithBytes:cData length:strlen(cData)];

    <span class="built_in">NSMutableData</span> *mData = [[<span class="built_in">NSMutableData</span> alloc] init];

    [mData appendData:HMAC];
    [mData appendData:dData];

    <span class="built_in">NSString</span> *hash = [mData base64EncodedStringWithOptions:<span class="number">0</span>];<span class="comment">//将加密结果进行一次BASE64编码。</span>
    <span class="keyword">return</span> hash;
}
</code></pre><p>如果是SHA256，可以：</p>
<pre><code>unsigned <span class="value">char</span> cHMAC<span class="attr_selector">[CC_SHA256_DIGEST_LENGTH]</span>;
<span class="function">CCHmac</span>(kCCHmacAlgSHA256, cKey, <span class="function">strlen</span>(cKey), cData, <span class="function">strlen</span>(cData), cHMAC);
</code></pre><h3 id="人脸检测">人脸检测</h3><p>通过生成的签名添加到请求头authorization里面，请求如下：</p>
<pre><code>NSString *apiString = [NSString <span class="string">stringWithFormat:</span>@<span class="string">"%@%@"</span>,@<span class="string">"https://recognition.image.myqcloud.com"</span>,@<span class="string">"/face/detect"</span>];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager <span class="string">setRequestSerializer:</span>[AFHTTPRequestSerializer serializer]];
[manager.requestSerializer <span class="string">setValue:</span>@<span class="string">"recognition.image.myqcloud.com"</span> <span class="string">forHTTPHeaderField:</span>@<span class="string">"host"</span>];
[manager.requestSerializer <span class="string">setValue:</span>[self getSign] <span class="string">forHTTPHeaderField:</span>@<span class="string">"authorization"</span>];
[manager <span class="string">POST:</span>apiString <span class="string">parameters:</span>params <span class="string">constructingBodyWithBlock:</span>^(id&lt;AFMultipartFormData&gt;  _Nonnull formData) {
    [formData <span class="string">appendPartWithFileData:</span>imageData <span class="string">name:</span>@<span class="string">"image"</span> <span class="string">fileName:</span>@<span class="string">"image.jpg"</span> <span class="string">mimeType:</span>@<span class="string">"image/jpg"</span>];
} <span class="string">progress:</span>nil <span class="string">success:</span>^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    block(responseObject);
} <span class="string">failure:</span>^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    block(nil);
}];
</code></pre><p>其他接口可以查看：<br><a href="https://cloud.tencent.com/document/product/867/17719" target="_blank" rel="noopener">1.腾讯云鉴权签名</a><br><a href="https://cloud.tencent.com/document/product/867/17588" target="_blank" rel="noopener">2.人脸识别接口文档</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<h3 id="前言">前言</h3><p>工作需要做了一个简易的、通过API第三方人脸识别、人脸对比分析的App Demo，对比了一下各家提供的服务、SDK，最后选择了腾讯云的智能图像服务。<br>调用API的流程为：</p>
<pre><code><span class="n]]>
    </summary>
    
      <category term="腾讯云" scheme="http://yoursite.com/tags/%E8%85%BE%E8%AE%AF%E4%BA%91/"/>
    
      <category term="Objective-C SHA1" scheme="http://yoursite.com/tags/Objective-C-SHA1/"/>
    
      <category term="人脸识别" scheme="http://yoursite.com/tags/%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB/"/>
    
      <category term="鉴权" scheme="http://yoursite.com/tags/%E9%89%B4%E6%9D%83/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[.Net Core 添加 HTTP Headers]]></title>
    <link href="http://yoursite.com/2018/08/01/http-headers/"/>
    <id>http://yoursite.com/2018/08/01/http-headers/</id>
    <published>2018-08-01T12:43:12.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<h3 id="前言">前言</h3><p>基于安全的需求，要在API（基于.Net Core）交互的过程中除了特有的鉴权外，还添加额外的Header。</p>
<h3 id="Strict-Transport-Security">Strict-Transport-Security</h3><h4 id="1-概述">1.概述</h4><p><u>HTTP Strict Transport Security is an excellent feature to support on your site and strengthens your implementation of TLS by getting the User Agent to enforce the use of HTTPS. Recommended value strict-transport-security: max-age=31536000; includeSubDomains.</u></p>
<p>HTTP Strict Transport Security（HTTP严格安全传输） 通常简称为HSTS，要求浏览器只能通过HTTPS访问当前资源，而不是HTTP。浏览器会自动把所有尝试使用HTTP的请求自动替换为HTTPS请求，在一定范围内（如钓鱼网站等）防止中间人攻击。</p>
<h4 id="2-示例">2.示例</h4><pre><code><span class="attribute">Strict-Transport-Security</span>: <span class="string">max-age=31536000</span>

<span class="scss"><span class="comment">//includeSubDomains适用于该网站的所有子域名</span>
<span class="value">Strict</span>-Transport-Security<span class="value">: max-age=<span class="number">31536000</span>;</span> includeSubDomains

<span class="comment">//Google维护 首次浏览器加载后可以预加载到缓存，需要向Google申请</span>
<span class="value">Strict</span>-Transport-Security<span class="value">: max-age=<span class="number">31536000</span>;</span> preload</span>
</code></pre><h3 id="Public-Key-Pins">Public-Key-Pins</h3><h4 id="1-概述-1">1.概述</h4><p><u>HTTP Public Key Pinning protects your site from MiTM attacks using rogue X.509 certificates. By whitelisting only the identities that the browser should trust, your users are protected in the event a certificate authority is compromised.</u></p>
<p>HTTP公钥固定（又称HTTP公钥钉扎，英语：HTTP Public Key Pinning，缩写HPKP）是HTTPS网站防止攻击者利用数字证书认证机构（CA）错误签发的证书进行中间人攻击的一种安全机制，用于预防CA遭受入侵或其他会造成CA签发未授权证书的情况。</p>
<h4 id="2-示例-1">2.示例</h4><pre><code>/*
<span class="code">    pin-sha256 即证书指纹，允许出现多次（实际上最少应该指定两个）；</span>
<span class="code">    max-age 和 includeSubdomains (可选) 与HSTS一致；</span>
<span class="code">    report-uri(可选) 用来指定验证失败时的上报地址，格式和含义跟 CSP（Content Security Policy）中的同名字段一致；</span>
*/

Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [<span class="link_label">; includeSubdomains</span>][<span class="link_reference">; report-uri="reportURI"</span>]
</code></pre><h3 id="X-Frame-Options">X-Frame-Options</h3><h4 id="1-概述-2">1.概述</h4><p><u>X-Frame-Options tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking. Recommended value x-frame-options: SAMEORIGIN.</u></p>
<p>X-Frame-Options是用来给浏览器指示允许一个页面可否在 frame,iframe 或者 object 标签中展现的标记。避免了点击劫持 (clickjacking) 的攻击。</p>
<h4 id="2-示例-2">2.示例</h4><p>在IIS中配置如下：</p>
<pre><code><span class="tag">&lt;<span class="title">system.webServer</span>&gt;</span>
  ...

  <span class="tag">&lt;<span class="title">httpProtocol</span>&gt;</span>
    <span class="tag">&lt;<span class="title">customHeaders</span>&gt;</span>
      <span class="tag">&lt;<span class="title">add</span> <span class="attribute">name</span>=<span class="value">"X-Frame-Options"</span> <span class="attribute">value</span>=<span class="value">"SAMEORIGIN"</span> /&gt;</span>
    <span class="tag">&lt;/<span class="title">customHeaders</span>&gt;</span>
  <span class="tag">&lt;/<span class="title">httpProtocol</span>&gt;</span>

  ...
<span class="tag">&lt;/<span class="title">system.webServer</span>&gt;</span>
</code></pre><h3 id="X-Content-Type-Options">X-Content-Type-Options</h3><h4 id="1-概述-3">1.概述</h4><p><u>X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. The only valid value for this header is X-Content-Type-Options: nosniff</u></p>
<p>通常浏览器会根据Content-Type字段来区分类型，X-Content-Type-Options用来禁用浏览器的 MIME 类型嗅探。</p>
<h4 id="2-示例-3">2.示例</h4><pre><code><span class="attribute">X-Content-Type-Options</span>: <span class="string">nosniff</span>
</code></pre><h3 id="Referrer-Policy">Referrer-Policy</h3><h4 id="1-概述-4">1.概述</h4><p><u>Referrer Policy is a new header that allows a site to control how much information the browser includes with navigations away from a document and should be set by all sites.</u></p>
<p>HTTP来源地址（referer，或HTTP referer）是HTTP表头的一个字段，用来表示从哪儿链接到目前的网页，采用的格式是URL。换句话说，借着HTTP来源地址，目前的网页可以检查访客从哪里而来，这也常被用来对付伪造的跨网站请求。<a href="https://zh.wikipedia.org/wiki/HTTP參照位址" target="_blank" rel="noopener">Referrer维基百科</a></p>
<h4 id="2-示例-4">2.示例</h4><pre><code><span class="attribute">Referrer-Policy</span>: <span class="string">no-referrer</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">no-referrer-when-downgrade</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">origin</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">origin-when-cross-origin</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">same-origin</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">strict-origin</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">strict-origin-when-cross-origin</span>
<span class="attribute">Referrer-Policy</span>: <span class="string">unsafe-url</span>
</code></pre><p>同源、跨域等策略详细参考：<a href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy" target="_blank" rel="noopener">同源策略</a></p>
<h3 id="Content-Security-Policy">Content-Security-Policy</h3><h4 id="1-概述-5">1.概述</h4><p><u>Content Security Policy is an effective measure to protect your site from XSS attacks. By whitelisting sources of approved content, you can prevent the browser from loading malicious assets.</u></p>
<p>Content Security Policy，网页安全政策，缩写 CSP。CSP可以添加来源白名单，防止XSS攻击，更进一步可以通过<code>report-uri</code>记录异常行为。</p>
<h4 id="2-示例-5">2.示例</h4><pre><code>Content-Security-<span class="string">Policy:</span> <span class="keyword">default</span>-src <span class="string">'self'</span>; ...; report-uri /my_amazing_csp_report_parser;
</code></pre><h3 id="X-XSS-Protection">X-XSS-Protection</h3><h4 id="1-概述-6">1.概述</h4><p><u>X-XSS-Protection sets the configuration for the cross-site scripting filter built into most browsers. Recommended value “X-XSS-Protection: 1; mode=block”.</u></p>
<p>X-XSS-Protection 是浏览器默认开启的，防止XSS的保护机制。可以为不支持 CSP 的旧版浏览器的用户提供保护。</p>
<h4 id="2-示例-6">2.示例</h4><pre><code><span class="comment">//关闭</span>
X-XSS-Protection: <span class="number">0</span>
<span class="comment">//默认开始，清除页面</span>
X-XSS-Protection: <span class="number">1</span>
<span class="comment">//开启，不加载</span>
X-XSS-Protection: <span class="number">1</span>; mode=block
<span class="comment">//CSP 通过`report-uri`记录异常行为</span>
X-XSS-Protection: <span class="number">1</span>; report=&lt;reporting-uri&gt;
</code></pre><h3 id="-Net_Core的_Header_添加">.Net Core的 Header 添加</h3><p>了解以上Header后，对应就要添加.Net Core的Header了，详细参考：<a href="https://andrewlock.net/adding-default-security-headers-in-asp-net-core/" target="_blank" rel="noopener">How to add default security headers in ASP.NET Core using custom middleware</a><br>构建对应的SecurityHeadersMiddleware，然后在<code>Startup.cs</code>的<code>Configure</code>添加：</p>
<pre><code>app.<span class="type">UseSecurityHeadersMiddleware</span>(<span class="keyword">new</span> <span class="type">SecurityHeadersBuilder</span><span class="literal">()</span>.<span class="type">AddDefaultSecurePolicy</span><span class="literal">()</span>);
</code></pre><p>也可以参考：<a href="https://damienbod.com/2018/02/08/adding-http-headers-to-improve-security-in-an-asp-net-mvc-core-application/" target="_blank" rel="noopener">ADDING HTTP HEADERS TO IMPROVE SECURITY IN AN ASP.NET MVC CORE APPLICATION</a>，在 NuGet Package 里添加 <code>NWebsec.AspNetCore.Middleware</code><br>然后在<code>Startup.cs</code>的<code>Configure</code>添加：</p>
<pre><code>app.UseHsts<span class="params">(hsts =&gt; hsts.MaxAge<span class="params">(<span class="number">365</span>)</span>.IncludeSubdomains<span class="params">()</span>)</span>;
app.UseXContentTypeOptions<span class="params">()</span>;
app.UseReferrerPolicy<span class="params">(opts =&gt; opts.NoReferrer<span class="params">()</span>)</span>;
app.UseXXssProtection<span class="params">(options =&gt; options.EnabledWithBlockMode<span class="params">()</span>)</span>;
app.UseXfo<span class="params">(options =&gt; options.Deny<span class="params">()</span>)</span>;
app.UseCsp<span class="params">(opts =&gt; opts
    .BlockAllMixedContent<span class="params">()</span>
    .StyleSources<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
    .StyleSources<span class="params">(s =&gt; s.UnsafeInline<span class="params">()</span>)</span>
    .FontSources<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
    .FormActions<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
    .FrameAncestors<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
    .ImageSources<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
    .ScriptSources<span class="params">(s =&gt; s.Self<span class="params">()</span>)</span>
)</span>;
</code></pre><p>上述文章还推荐了一个在线扫描Header的网站：<a href="https://securityheaders.com/" target="_blank" rel="noopener">https://securityheaders.com/</a> 可以试试网站的安全评分。</p>
<p>按上述添加完后的响应的Header，Done：<br>    <img src="/images/2018080101.png" alt="2018080101"></p>
<h3 id="参考">参考</h3><p><a href="https://developer.mozilla.org/zh-CN/docs/Security/HTTP_Strict_Transport_Security" target="_blank" rel="noopener">HTTP Strict Transport Security</a><br><a href="https://imququ.com/post/http-public-key-pinning.html" target="_blank" rel="noopener">HTTP Public Key Pinning 介绍</a><br><a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/X-Frame-Options" target="_blank" rel="noopener">X-Frame-Options 响应头</a><br><a href="https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/gg622941(v=vs.85" target="_blank" rel="noopener">Reducing MIME type security risks</a>)<br><a href="http://www.ruanyifeng.com/blog/2016/09/csp.html" target="_blank" rel="noopener">Content Security Policy 入门教程</a><br><a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/X-Frame-Options" target="_blank" rel="noopener">X-Frame-Options 响应头</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<h3 id="前言">前言</h3><p>基于安全的需求，要在API（基于.Net Core）交互的过程中除了特有的鉴权外，还添加额外的Header。</p>
<h3 id="Strict-Transport-Security">Strict-Transport-Securit]]>
    </summary>
    
      <category term="Http Header" scheme="http://yoursite.com/tags/Http-Header/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[swagger生成xml文件上传到azure云主机]]></title>
    <link href="http://yoursite.com/2017/12/20/aspdotnetcoreswagger/"/>
    <id>http://yoursite.com/2017/12/20/aspdotnetcoreswagger/</id>
    <published>2017-12-20T07:25:04.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>swagger xml文件默认不上传到azure云主机，如需要上传需要修改 <strong>csproj</strong> 文件（Asp.Net Core环境）。添加如下配置：</p>
<pre><code><span class="tag">&lt;<span class="title">PropertyGroup</span>&gt;</span>
  <span class="tag">&lt;<span class="title">GenerateDocumentationFile</span>&gt;</span>true<span class="tag">&lt;/<span class="title">GenerateDocumentationFile</span>&gt;</span>
<span class="tag">&lt;/<span class="title">PropertyGroup</span>&gt;</span>

<span class="tag">&lt;<span class="title">Target</span> <span class="attribute">Name</span>=<span class="value">"IncludeDocFile"</span> <span class="attribute">BeforeTargets</span>=<span class="value">"PrepareForPublish"</span>&gt;</span>
  <span class="tag">&lt;<span class="title">ItemGroup</span> <span class="attribute">Condition</span>=<span class="value">" '$(DocumentationFile)' != '' "</span>&gt;</span>
    <span class="tag">&lt;<span class="title">_DocumentationFile</span> <span class="attribute">Include</span>=<span class="value">"$(DocumentationFile)"</span> /&gt;</span>
    <span class="tag">&lt;<span class="title">ContentWithTargetPath</span> <span class="attribute">Include</span>=<span class="value">"@(_DocumentationFile-&gt;'%(FullPath)')"</span>
                           <span class="attribute">RelativePath</span>=<span class="value">"%(_DocumentationFile.Identity)"</span>
                           <span class="attribute">TargetPath</span>=<span class="value">"%(_DocumentationFile.Filename)%(_DocumentationFile.Extension)"</span>
                           <span class="attribute">CopyToPublishDirectory</span>=<span class="value">"PreserveNewest"</span> /&gt;</span>
  <span class="tag">&lt;/<span class="title">ItemGroup</span>&gt;</span>
<span class="tag">&lt;/<span class="title">Target</span>&gt;</span>
</code></pre><p><a href="https://github.com/dotnet/sdk/issues/795" target="_blank" rel="noopener">issue: dotnet/sdk/issues/795</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>swagger xml文件默认不上传到azure云主机，如需要上传需要修改 <strong>csproj</strong> 文件（Asp.Net Core环境）。添加如下配置：</p>
<pre><code><span class="tag">&lt;<span class]]>
    </summary>
    
      <category term="Asp.Net Core" scheme="http://yoursite.com/tags/Asp-Net-Core/"/>
    
      <category term="Swagger" scheme="http://yoursite.com/tags/Swagger/"/>
    
      <category term="azure云" scheme="http://yoursite.com/tags/azure%E4%BA%91/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[SQL--数据导入]]></title>
    <link href="http://yoursite.com/2017/08/01/SQL-%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%85%A5/"/>
    <id>http://yoursite.com/2017/08/01/SQL-数据导入/</id>
    <published>2017-08-01T06:34:56.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>之前写API及处理后台数据的时候写了一些脚本，记录一下。</p>
<p>快捷数据表操作的存储过程脚本。eg: exec ‘Z_InitData’,’目标表T1’,’源表T2’</p>
<pre><code><span class="operator"><span class="keyword">Create</span> <span class="keyword">PROCEDURE</span> Z_InitData
    @tbname <span class="keyword">nvarchar</span>(<span class="number">100</span>),
    @fromtbname <span class="keyword">nvarchar</span>(<span class="number">100</span>)
<span class="keyword">AS</span>
<span class="keyword">BEGIN</span>
    <span class="comment">-- SET NOCOUNT ON added to prevent extra result sets from</span>
    <span class="comment">-- interfering with SELECT statements.</span>
    <span class="keyword">SET</span> NOCOUNT <span class="keyword">ON</span>;</span>
    <span class="operator"><span class="keyword">declare</span> @<span class="keyword">sql</span> <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)
    <span class="keyword">declare</span> @<span class="keyword">col</span> <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)
    <span class="keyword">set</span> @<span class="keyword">sql</span> = <span class="string">'select @col = stuff((select '',''+name from syscolumns where id=object_id( '''</span>+ @tbname +<span class="string">''') order by name for xml path('''')),1,1,'''')'</span>  
    exec sp_executesql @<span class="keyword">sql</span>,<span class="keyword">N</span><span class="string">'@col nvarchar(max) output'</span>,@<span class="keyword">col</span> <span class="keyword">output</span>
    <span class="keyword">set</span> @<span class="keyword">sql</span> = <span class="string">' truncate table '</span>+ @tbname +<span class="string">';'</span>
    <span class="keyword">set</span> @<span class="keyword">sql</span> = @<span class="keyword">sql</span> + <span class="string">' set IDENTITY_INSERT '</span>+ @tbname +<span class="string">' on ;'</span>
    <span class="keyword">set</span> @<span class="keyword">sql</span> = @<span class="keyword">sql</span> + <span class="string">' insert into '</span>+ @tbname + <span class="string">'('</span>+ @<span class="keyword">col</span> +<span class="string">') select '</span>+@<span class="keyword">col</span>+ <span class="string">' from '</span> + @fromtbname
    <span class="keyword">set</span> @<span class="keyword">sql</span> = @<span class="keyword">sql</span> + <span class="string">'; set IDENTITY_INSERT '</span>+ @tbname +<span class="string">' off;'</span>
    print(@<span class="keyword">sql</span>)
    exec(@<span class="keyword">sql</span>)
<span class="keyword">END</span></span>
</code></pre><hr>
<p>打印表字段，方便insert。eg: exec ‘Z_Print’,’目标表T1’</p>
<pre><code><span class="operator"><span class="keyword">ALTER</span> <span class="keyword">PROCEDURE</span> Z_Print
    @tbname <span class="keyword">nvarchar</span>(<span class="number">100</span>) =<span class="string">'TTT'</span>
<span class="keyword">AS</span>
<span class="keyword">BEGIN</span>
    <span class="comment">-- SET NOCOUNT ON added to prevent extra result sets from</span>
    <span class="comment">-- interfering with SELECT statements.</span>
    <span class="keyword">SET</span> NOCOUNT <span class="keyword">ON</span>;</span>
    <span class="operator"><span class="keyword">declare</span> @<span class="keyword">sql</span> <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)
    <span class="keyword">declare</span> @<span class="keyword">col</span> <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)
    <span class="keyword">set</span> @<span class="keyword">sql</span> = <span class="string">'select @col = stuff((select '',''+name from syscolumns where id=object_id( '''</span>+ @tbname +<span class="string">''') order by name for xml path('''')),1,1,'''')'</span>  
    exec sp_executesql @<span class="keyword">sql</span>,<span class="keyword">N</span><span class="string">'@col nvarchar(max) output'</span>,@<span class="keyword">col</span> <span class="keyword">output</span>
    <span class="keyword">set</span> @<span class="keyword">sql</span> = <span class="string">' insert into '</span>+ @tbname + <span class="string">'('</span>+ @<span class="keyword">col</span> +<span class="string">') '</span>
    print(@<span class="keyword">sql</span>)
<span class="keyword">END</span></span>
</code></pre>]]></content>
    <summary type="html">
    <![CDATA[<p>之前写API及处理后台数据的时候写了一些脚本，记录一下。</p>
<p>快捷数据表操作的存储过程脚本。eg: exec ‘Z_InitData’,’目标表T1’,’源表T2’</p>
<pre><code><span class="operator"><span class]]>
    </summary>
    
      <category term="SQL" scheme="http://yoursite.com/tags/SQL/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS本地时间与同步]]></title>
    <link href="http://yoursite.com/2017/07/31/iOS-Article-001/"/>
    <id>http://yoursite.com/2017/07/31/iOS-Article-001/</id>
    <published>2017-07-31T13:52:35.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<h3 id="概念">概念</h3><p>GMT（Greenwich Mean Time）格林尼治时间<br>UTC（Coordinated Universal Time ）原子钟标准时间<br>Unix time（以UTC 1970年1月1号 00：00：00为基准时间）</p>
<hr>
<h3 id="sysctl_API">sysctl API</h3><p>iOS系统上次设备重启时间（iOS9后不能使用）</p>
<pre><code><span class="preprocessor">#<span class="keyword">include</span> <span class="string">&lt;sys/sysctl.h&gt;</span></span>

- (<span class="keyword">long</span>)bootTime
{
    <span class="preprocessor">#<span class="keyword">define</span> MIB_SIZE <span class="number">2</span></span>
    <span class="keyword">int</span> mib[MIB_SIZE];
    <span class="keyword">size_t</span> size;
    <span class="keyword">struct</span> timeval  boottime;

    mib[<span class="number">0</span>] = CTL_KERN;
    mib[<span class="number">1</span>] = KERN_BOOTTIME;
    size = <span class="keyword">sizeof</span>(boottime);
    <span class="keyword">if</span> (sysctl(mib, MIB_SIZE, &amp;boottime, &amp;size, <span class="literal">NULL</span>, <span class="number">0</span>) != -<span class="number">1</span>)
    {
        <span class="keyword">return</span> boottime.tv_sec;
    }
    <span class="keyword">return</span> <span class="number">0</span>;
}
</code></pre><h3 id="时间校准">时间校准</h3><p>1、记录上一次请求的时候获取服务器时间serverTime，与本地时间lastLocalTime</p>
<p>2、需要计算的时候取出curLocalTime（即NSDate），计算与lastLocalTime的偏移量T</p>
<p>3、serverTime+T 就是当前的服务器时间</p>
<h5 id="另外，计算运行时长，计算自上一次重启后的运行时间">另外，计算运行时长，计算自上一次重启后的运行时间</h5><pre><code><span class="comment">//get system uptime since last boot</span>
- (NSTimeInterval)uptime
{
    <span class="keyword">struct</span> timeval boottime;
    <span class="keyword">int</span> mib[<span class="number">2</span>] = {CTL_KERN, KERN_BOOTTIME};
    <span class="keyword">size_t</span> size = <span class="keyword">sizeof</span>(boottime);

    <span class="keyword">struct</span> timeval now;
    <span class="keyword">struct</span> timezone tz;
    gettimeofday(&amp;now, &amp;tz);

    <span class="keyword">double</span> uptime = -<span class="number">1</span>;

    <span class="keyword">if</span> (sysctl(mib, <span class="number">2</span>, &amp;boottime, &amp;size, <span class="literal">NULL</span>, <span class="number">0</span>) != -<span class="number">1</span> &amp;&amp; boottime.tv_sec != <span class="number">0</span>)
    {
        uptime = now.tv_sec - boottime.tv_sec;
        uptime += (<span class="keyword">double</span>)(now.tv_usec - boottime.tv_usec) / <span class="number">1000000.0</span>;
    }
    <span class="keyword">return</span> uptime;
}
</code></pre><p>详细参考 <a href="http://mrpeak.cn/blog/ios-time/" target="_blank" rel="noopener">http://mrpeak.cn/blog/ios-time/</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<h3 id="概念">概念</h3><p>GMT（Greenwich Mean Time）格林尼治时间<br>UTC（Coordinated Universal Time ）原子钟标准时间<br>Unix time（以UTC 1970年1月1号 00：00：00为基准时间）</]]>
    </summary>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS Tips--NSDictionary和NSArray 快捷计算函数]]></title>
    <link href="http://yoursite.com/2017/07/30/iOS-Tips-NSDictionary-NSArray-%E5%BF%AB%E6%8D%B7%E8%AE%A1%E7%AE%97%E5%87%BD%E6%95%B0/"/>
    <id>http://yoursite.com/2017/07/30/iOS-Tips-NSDictionary-NSArray-快捷计算函数/</id>
    <published>2017-07-30T15:15:46.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>NSArray 有快捷的汇总公式，只要用 @函数.键路径 即可：</p>
<pre><code><span class="title">NSArray</span> *array = [NSArray arrayWithObjects:@<span class="string">"1.0"</span>,@<span class="string">"2.0"</span>,nil];
<span class="title">CGFloat</span> sum = [[array valueForKeyPath:@<span class="string">"<span class="variable">@sum</span>.floatValue"</span>] floatValue];
<span class="title">CGFloat</span> avg = [[array valueForKeyPath:@<span class="string">"<span class="variable">@avg</span>.floatValue"</span>] floatValue];
<span class="title">CGFloat</span> max =[[array valueForKeyPath:@<span class="string">"<span class="variable">@max</span>.floatValue"</span>] floatValue];
<span class="title">CGFloat</span> min =[[array valueForKeyPath:@<span class="string">"<span class="variable">@min</span>.floatValue"</span>] floatValue];
</code></pre><p>如果汇总值是在NSDictionary里面，同样可以取值进行汇总：</p>
<pre><code><span class="name">NSArray</span> *<span class="atom">dic</span> = [{@<span class="string">"KeyName1"</span>:@<span class="string">"1.0"</span>,@<span class="string">"KeyName2"</span>:@<span class="string">"abc"</span>},{@<span class="string">"KeyName1"</span>:@<span class="string">"2.0"</span>,@<span class="string">"KeyName2"</span>:@<span class="string">"bcd"</span>}]; 
<span class="name">CGFloat</span> <span class="atom">sum</span> = [[[<span class="atom">dic</span> <span class="atom">valueForKeyPath</span>:@<span class="string">"KeyName1"</span>] <span class="atom">valueForKeyPath</span>:@<span class="string">"@sum.floatValue"</span>] <span class="atom">floatValue</span>];
<span class="name">CGFloat</span> <span class="atom">max</span> = [[[<span class="atom">dic</span> <span class="atom">valueForKeyPath</span>:@<span class="string">"KeyName1"</span>] <span class="atom">valueForKeyPath</span>:@<span class="string">"@max.floatValue"</span>] <span class="atom">floatValue</span>];
</code></pre><p>以上快捷汇总实际是KVC的用法，更多KVC的用法参考<br>1.<a href="http://www.jianshu.com/p/b7dda8d49dc4" target="_blank" rel="noopener">http://www.jianshu.com/p/b7dda8d49dc4</a><br>2.<a href="https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/KeyValueCoding.html" target="_blank" rel="noopener">https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/KeyValueCoding.html</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>NSArray 有快捷的汇总公式，只要用 @函数.键路径 即可：</p>
<pre><code><span class="title">NSArray</span> *array = [NSArray arrayWithObjects:@<span class="strin]]>
    </summary>
    
      <category term="iOS" scheme="http://yoursite.com/tags/iOS/"/>
    
      <category term="KVC" scheme="http://yoursite.com/tags/KVC/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Python链家爬虫]]></title>
    <link href="http://yoursite.com/2017/03/21/Python%E9%93%BE%E5%AE%B6%E7%88%AC%E8%99%AB/"/>
    <id>http://yoursite.com/2017/03/21/Python链家爬虫/</id>
    <published>2017-03-21T02:23:17.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>业余时间做了个链家的爬虫，爬取数据写入sqlite，方便浏览和对比。<br>具体参考了冰蓝大牛的博客<a href="http://lanbing510.info/2016/03/15/Lianjia-Spider.html?utm_source=tuicool&amp;utm_medium=referral" target="_blank" rel="noopener">http://lanbing510.info/2016/03/15/Lianjia-Spider.html?utm_source=tuicool&amp;utm_medium=referral</a>, 根据链家最新的web样式做了修改（2017-03）爬在售的二手房的数据。</p>
<p>链家对短时间内同一个IP的流量有监控，所以如果用多线程去爬，太快可能会被要求输入验证码。试了以下用代理ip池去爬，因为可用的免费代理ip不多也不稳定，就放弃了。后面想数据爬的也不多，就加个延时模拟人为慢慢爬了，另外还有个问题可能是单位时间内Request太快可能解析不到数据，就把延时放在BeautifulSoup解析后面，并加了如果没有数据则重复5次请求的验证过程，才成功抓全数据：</p>
<pre><code><span class="tag">time</span>.<span class="function"><span class="title">sleep</span><span class="params">(np.random.rand()</span></span>*<span class="number">3</span>+<span class="number">3</span>)
</code></pre><p>这里贴出关键的匹配代码，代码好粗糙，仅供发参考：）</p>
<pre><code><span class="function"><span class="keyword">def</span> <span class="title">onsell_spider</span><span class="params">(mydb,url_page=<span class="string">u"http://gz.lianjia.com/ershoufang/pg1rs越秀/"</span>,area=<span class="string">u"越秀"</span>)</span>:</span>
    <span class="comment"># time.sleep(np.random.rand()*1)</span>
    <span class="keyword">print</span> url_page
    counts = <span class="number">0</span>
    trytime = <span class="number">0</span>
    <span class="keyword">while</span> counts==<span class="number">0</span> &amp; trytime&lt;=<span class="number">5</span>:
        <span class="keyword">try</span>:
            req = urllib2.Request(url_page,headers=hds[random.randint(<span class="number">0</span>,len(hds)-<span class="number">1</span>)])
            source_code = urllib2.urlopen(req,timeout=<span class="number">10</span>).read()
            plain_text=unicode(source_code)<span class="comment">#,errors='ignore')   </span>
            soup = BeautifulSoup(plain_text, <span class="string">"lxml"</span>)
        <span class="keyword">except</span> (urllib2.HTTPError, urllib2.URLError), e:
            <span class="keyword">print</span> e
            exception_write(<span class="string">'onsell_spider'</span>,url_page)
            <span class="keyword">return</span>
        <span class="keyword">except</span> Exception,e:
            <span class="keyword">print</span> e
            exception_write(<span class="string">'onsell_spider'</span>,url_page)
            <span class="keyword">return</span>
        time.sleep(np.random.rand()*<span class="number">3</span>+<span class="number">3</span>)
        cj_list=soup.findAll(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'info clear'</span>})

        <span class="keyword">print</span> len(cj_list)
        counts = len(cj_list)
        trytime = trytime + <span class="number">1</span>
        <span class="keyword">for</span> cj <span class="keyword">in</span> cj_list:
            info_dict={}
            href=cj.find(<span class="string">'a'</span>)
            <span class="keyword">if</span> <span class="keyword">not</span> href:
                <span class="keyword">continue</span>
            info_dict.update({<span class="string">u'链接'</span>:href.attrs[<span class="string">'href'</span>]})
            name=cj.find(<span class="string">'a'</span>).text
            info_dict.update({<span class="string">u'标题'</span>:name})

     <span class="comment">#href TEXT primary key UNIQUE, name TEXT, community TEXT, style TEXT, area TEXT, orientation TEXT,decoration TEXT,haslift TEXT,floor TEXT, year TEXT, bplace TEXT,splace TEXT, unit_price TEXT, total_price TEXT, subway TEXT, other TEXT</span>

            content=unicode(cj.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'houseInfo'</span>}).renderContents().strip())
            info=re.match(<span class="string">r"&lt;span .*&gt;&lt;/span&gt;&lt;a .*&gt;(.*)&lt;/a&gt;(.*)"</span>, content)

            <span class="comment"># print info</span>
            <span class="keyword">if</span> info:
                info=info.groups()
                info_dict.update({<span class="string">u'小区'</span>:info[<span class="number">0</span>]})

                str = info[<span class="number">1</span>].strip().split(<span class="string">'|'</span>)
                <span class="comment"># print str[1]</span>

                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'户型'</span>:str[<span class="number">1</span>].strip()})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'户型'</span>:<span class="string">''</span>})
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'面积'</span>:str[<span class="number">2</span>].strip()})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'面积'</span>:<span class="string">''</span>})
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'朝向'</span>:str[<span class="number">3</span>].strip()})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'朝向'</span>:<span class="string">''</span>})
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'装修'</span>:str[<span class="number">4</span>].strip()})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'装修'</span>:<span class="string">''</span>})
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'有无电梯'</span>:str[<span class="number">5</span>].strip()})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'有无电梯'</span>:<span class="string">''</span>})

            content=unicode(cj.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'positionInfo'</span>}).renderContents().strip())
            info=re.match(<span class="string">r"&lt;span .*&gt;&lt;/span&gt;(.*)\)(.*)&lt;a .*&gt;(.*)&lt;/a&gt;"</span>, content)
            <span class="keyword">if</span> info:
                info=info.groups()
                <span class="comment"># print info</span>
                info_dict.update({<span class="string">u'楼层'</span>:info[<span class="number">0</span>]})
                info_dict.update({<span class="string">u'建造时间'</span>:info[<span class="number">1</span>]})
                info_dict.update({<span class="string">u'大区域'</span>:area})
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'小区域'</span>:info[<span class="number">2</span>]})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'小区域'</span>:info[<span class="number">2</span>]})


            content=cj.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'unitPrice'</span>}).find(<span class="string">'span'</span>).text
            <span class="keyword">if</span> content:
                info_dict.update({<span class="string">u'单价'</span>:content})
            content=cj.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'totalPrice'</span>}).find(<span class="string">'span'</span>).text
            <span class="keyword">if</span> content:
                info_dict.update({<span class="string">u'总价'</span>:content})

            content=cj.find(<span class="string">'span'</span>,{<span class="string">'class'</span>:<span class="string">'subway'</span>})
            <span class="comment"># print content</span>
            <span class="keyword">if</span> content:
                <span class="keyword">try</span>:
                    info_dict.update({<span class="string">u'地铁'</span>:content.text})
                <span class="keyword">except</span> Exception,e:
                    info_dict.update({<span class="string">u'地铁'</span>:<span class="string">''</span>})

            content=cj.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'followInfo'</span>}).text
            <span class="keyword">if</span>  content:
                info_dict.update({<span class="string">u'其他'</span>:content})

            command=sql_onsell_insert_command(info_dict)
            mydb.execute(command,<span class="number">1</span>)


<span class="function"><span class="keyword">def</span> <span class="title">do_onsell_spider</span><span class="params">(mydb,area=<span class="string">u"越秀"</span>)</span>:</span>

    url=<span class="string">u"http://gz.lianjia.com/ershoufang/pg%drs%s/"</span> % (<span class="number">1</span>,area)

    <span class="keyword">try</span>:
        req = urllib2.Request(url,headers=hds[random.randint(<span class="number">0</span>,len(hds)-<span class="number">1</span>)])
        source_code = urllib2.urlopen(req,timeout=<span class="number">10</span>).read()
        plain_text=unicode(source_code)<span class="comment">#,errors='ignore')   </span>
        soup = BeautifulSoup(plain_text, <span class="string">"lxml"</span>)
    <span class="keyword">except</span> (urllib2.HTTPError, urllib2.URLError), e:
        <span class="keyword">print</span> e
        exception_write(<span class="string">'do_onsell_spider'</span>,area)
        <span class="keyword">return</span>
    <span class="keyword">except</span> Exception,e:
        <span class="keyword">print</span> e
        exception_write(<span class="string">'do_onsell_spider'</span>,area)
        <span class="keyword">return</span>

    time.sleep(np.random.rand()*<span class="number">1</span>+<span class="number">1</span>)
    content=soup.find(<span class="string">'div'</span>,{<span class="string">'class'</span>:<span class="string">'page-box house-lst-page-box'</span>})
    <span class="comment"># print soup</span>

    <span class="keyword">if</span> content:
        d=<span class="string">"d="</span>+content.get(<span class="string">'page-data'</span>)
        exec(d)
        total_pages=d[<span class="string">'totalPage'</span>]

    <span class="keyword">print</span> total_pages

    <span class="keyword">for</span> i <span class="keyword">in</span> range(total_pages):
        time.sleep(np.random.rand()*<span class="number">1</span>)
        url_page=<span class="string">u"http://gz.lianjia.com/ershoufang/pg%drs%s/"</span> % (i+<span class="number">1</span>,area)
        onsell_spider(mydb,url_page,area)
</code></pre><p>对BeautifulSoup的方法还不太熟悉，用的都是简单粗暴的方法，后续再去细看了。</p>
<p>爬下来的数据：<br>    <img src="/images/imgdata.png" alt=""></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>业余时间做了个链家的爬虫，爬取数据写入sqlite，方便浏览和对比。<br>具体参考了冰蓝大牛的博客<a href="http://lanbing510.info/2016/03/15/Lianjia-Spider.html?utm_source=tuicool&amp;u]]>
    </summary>
    
      <category term="Python" scheme="http://yoursite.com/tags/Python/"/>
    
      <category term="Python爬虫" scheme="http://yoursite.com/tags/Python%E7%88%AC%E8%99%AB/"/>
    
      <category term="链家" scheme="http://yoursite.com/tags/%E9%93%BE%E5%AE%B6/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Python高德爬虫]]></title>
    <link href="http://yoursite.com/2017/03/13/Python%E9%AB%98%E5%BE%B7%E7%88%AC%E8%99%AB/"/>
    <id>http://yoursite.com/2017/03/13/Python高德爬虫/</id>
    <published>2017-03-13T06:29:59.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>前段时间因公司需求，需要爬取高德地图的数据，就学习了下Python，并做了个简易的爬虫GUI。</p>
<p>因为高德有api，所以爬数据灰常简单。<br>整个流程：输入城市编码-》根据api爬取数据-》导出到Excel<br>使用的库：BeautifulSoup PyQt5 openpyxl urllib2 requests等</p>
<p>具体思路：</p>
<h3 id="高德申请api的key，配置好需要爬取的参数：">高德申请api的key，配置好需要爬取的参数：</h3><p>参数城市、POI分类、查询关键词等,如果不hardcode的部分可以从界面传入</p>
<pre><code>url = <span class="string">r'http://restapi.amap.com/v3/place/text?&amp;citylimit=true&amp;&amp;output=xml&amp;offset=25&amp;page=1&amp;key=[your key]&amp;extensions=base'</span>
wherestr = <span class="string">r'&amp;city=440106&amp;types=050301&amp;keywords=肯德基'</span>
</code></pre><h3 id="关键抓取代码：">关键抓取代码：</h3><pre><code><span class="function"><span class="keyword">def</span> <span class="title">store_spider</span><span class="params">(self, citystr, storetype, wherestr)</span>:</span>
    page_num=<span class="number">1</span>;
    store_list=[]
    try_times=<span class="number">0</span>

    url = <span class="string">r'http://restapi.amap.com/v3/place/text?&amp;citylimit=true&amp;&amp;output=xml&amp;offset=25&amp;page=1&amp;key=[your key]&amp;extensions=base'</span>
    url = url + wherestr
    total_record = <span class="number">1</span>

    <span class="keyword">while</span>(total_record&gt;<span class="number">0</span>):
        url=url.replace(<span class="string">'page='</span>+str(page_num-<span class="number">1</span>),<span class="string">'page='</span>+str(page_num))

        <span class="comment"># time.sleep(np.random.rand()*1)</span>

        <span class="keyword">try</span>:
            req = urllib2.Request(url, headers=hds[page_num%len(hds)])
            source_code = urllib2.urlopen(req).read()
            plain_text=str(source_code)   
        <span class="keyword">except</span> (urllib2.HTTPError, urllib2.URLError), e:
            <span class="keyword">print</span> e
            try_times+=<span class="number">1</span>;
            <span class="keyword">print</span> try_times
            <span class="keyword">if</span> try_times&gt;<span class="number">10</span>:
                date = QDateTime.currentDateTime(); 
                self.bigEditor.setPlainText(<span class="string">"网络连接异常，抓取【"</span>+ citystr + <span class="string">"】"</span>+ storetype +<span class="string">"结束。"</span> + date.toString(<span class="string">" 时间:yyyy/MM/dd HH:mm:ss"</span>) + <span class="string">"\n"</span> + self.bigEditor.toPlainText())
                <span class="keyword">break</span>
            <span class="keyword">else</span>:
                <span class="keyword">continue</span>

        soup = BeautifulSoup(plain_text, <span class="string">"lxml"</span>)
        list_soup = soup.find(<span class="string">'pois'</span>, {<span class="string">'type'</span>: <span class="string">'list'</span>})

        <span class="comment"># try_times+=1;</span>
        <span class="keyword">if</span> list_soup==<span class="keyword">None</span> <span class="keyword">and</span> try_times&lt;<span class="number">10</span>:
            <span class="keyword">continue</span>
        <span class="keyword">elif</span> list_soup==<span class="keyword">None</span> <span class="keyword">or</span> len(list_soup)&lt;=<span class="number">1</span>:
            <span class="keyword">break</span> 

        total_record_str = soup.find(<span class="string">'count'</span>).string.strip()
        total_record = string.atoi(str(total_record_str))

        <span class="keyword">if</span> total_record == <span class="number">0</span> : <span class="keyword">break</span>

        <span class="keyword">for</span> storeinfo <span class="keyword">in</span> list_soup.findAll(<span class="string">'poi'</span>):
            name  = storeinfo.find(<span class="string">'name'</span>).string.strip()
            location  = storeinfo.find(<span class="string">'location'</span>).string.strip()
            location_list = location.split(<span class="string">','</span>)

            <span class="keyword">try</span>:
                location_logtitudes = location_list[<span class="number">0</span>]
            <span class="keyword">except</span>:
                location_logtitudes = <span class="string">'未知'</span>

            <span class="keyword">try</span>:
                location_autitudes = location_list[<span class="number">1</span>]
            <span class="keyword">except</span>:
                location_autitudes = <span class="string">'未知'</span>

            <span class="keyword">try</span>:
                tel  = storeinfo.find(<span class="string">'tel'</span>).string.strip()
            <span class="keyword">except</span>:
                tel  = <span class="string">''</span>

            <span class="keyword">try</span>:
                adname  = storeinfo.find(<span class="string">'adname'</span>).string.strip()
            <span class="keyword">except</span>:
                adname  = <span class="string">''</span>

            <span class="keyword">try</span>:
                address  = storeinfo.find(<span class="string">'address'</span>).string.strip()
            <span class="keyword">except</span>:
                address  = <span class="string">''</span>

            typecode  = storeinfo.find(<span class="string">'typecode'</span>).string.strip()
            pname  = storeinfo.find(<span class="string">'pname'</span>).string.strip()
            cityname  = storeinfo.find(<span class="string">'cityname'</span>).string.strip()
            amaptype  = storeinfo.find(<span class="string">'type'</span>).string.strip()
            amapid  = storeinfo.find(<span class="string">'id'</span>).string.strip()
            store_list.append([name,pname,cityname,adname,address,location_logtitudes,location_autitudes,tel,storetype,amapid,typecode,amaptype])
        try_times=<span class="number">0</span> 

            <span class="comment"># print 'Page %d' % page_num</span>

        <span class="comment">#输出到GUI</span>
        date = QDateTime.currentDateTime(); 
        self.bigEditor.setPlainText(date.toString(<span class="string">"正在抓取【"</span>+ citystr + <span class="string">"】"</span>+ storetype +<span class="string">",页码: "</span> + str(page_num) + <span class="string">"  时间:yyyy/MM/dd HH:mm:ss"</span>) + <span class="string">"\n"</span> + self.bigEditor.toPlainText())
        app.processEvents()
        page_num+=<span class="number">1</span>
    <span class="keyword">return</span> store_list
</code></pre><h3 id="导出到excel：">导出到excel：</h3><pre><code><span class="comment">#保存到excel</span>
<span class="function"><span class="keyword">def</span> <span class="title">save_storelists_excel</span><span class="params">(self, storelists, citystr)</span>:</span>

    wb=Workbook()
    ws=[]

    <span class="comment"># for i in range(len(typelist)):</span>
    ws.append(wb.create_sheet(title=citystr.decode())) 
    <span class="comment"># for i in range(len(typelist)): </span>
    ws[<span class="number">0</span>].append([<span class="string">'序号'</span>,<span class="string">'商店名称'</span>,<span class="string">'省份'</span>,<span class="string">'城市'</span>,<span class="string">'区/县'</span>,<span class="string">'商店地址'</span>,<span class="string">'经度'</span>,<span class="string">'纬度'</span>,<span class="string">'联系电话'</span>,<span class="string">'商店类型'</span>,<span class="string">'高德ID'</span>,<span class="string">'高德类型ID'</span>,<span class="string">'高德类型'</span>])
    count=<span class="number">1</span>
    <span class="keyword">for</span> storelist <span class="keyword">in</span> storelists:
        <span class="keyword">for</span> st <span class="keyword">in</span> storelist:
            ws[<span class="number">0</span>].append([count,st[<span class="number">0</span>],st[<span class="number">1</span>],st[<span class="number">2</span>],st[<span class="number">3</span>],st[<span class="number">4</span>],st[<span class="number">5</span>],st[<span class="number">6</span>],st[<span class="number">7</span>],st[<span class="number">8</span>],st[<span class="number">9</span>],st[<span class="number">10</span>],st[<span class="number">11</span>]])
            count+=<span class="number">1</span>
    <span class="comment"># 保存excel       </span>
    save_path= <span class="string">'storelist'</span>
    save_path+=(<span class="string">'-'</span>+citystr.decode())
    save_path+=<span class="string">'.xlsx'</span>
    wb.remove_sheet(wb[<span class="string">'Sheet'</span>]); 
    <span class="comment"># save_path = os.path.join(os.path.abspath(os.curdir), save_path)</span>

    <span class="keyword">if</span> getattr(sys, <span class="string">'frozen'</span>, <span class="keyword">False</span>):
        application_path = os.path.dirname(sys.executable)
    <span class="keyword">elif</span> __file__:
        application_path = os.path.dirname(__file__)

    save_path = os.path.join(application_path, save_path)

    wb.save(save_path)

    date = QDateTime.currentDateTime(); 
    self.bigEditor.setPlainText(<span class="string">"导出到目录文件:【"</span> + save_path + date.toString(<span class="string">"】 时间:yyyy/MM/dd HH:mm:ss"</span>) + <span class="string">"\n"</span> + self.bigEditor.toPlainText())
    app.processEvents()
</code></pre><p>另外UI使用的是PyQt5，PyQt的UI从运行到打包一堆坑要踩，不过很多问题都可以搜到解决方案。UI部分做了个输入框，输入城市以后可以从本地sqlite查询对应该城市区域的全部编码，然后赋值到wherestr上，开始爬取数据并输出到QTextEdit。</p>
<p>总的来说，高德地图API对爬虫很友好，企业认证的调用次数上限都很高，只是貌似每次调用最多就只能返回1000条数据，如果说POI分类多，最好分别进行遍历抓取。这个爬虫都是用到很基础的库，后续有时间继续研究~</p>
<p>效果截图：<br>    <img src="/images/imgui.png" alt=""></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>前段时间因公司需求，需要爬取高德地图的数据，就学习了下Python，并做了个简易的爬虫GUI。</p>
<p>因为高德有api，所以爬数据灰常简单。<br>整个流程：输入城市编码-》根据api爬取数据-》导出到Excel<br>使用的库：BeautifulSoup PyQt]]>
    </summary>
    
      <category term="Python" scheme="http://yoursite.com/tags/Python/"/>
    
      <category term="Python爬虫" scheme="http://yoursite.com/tags/Python%E7%88%AC%E8%99%AB/"/>
    
      <category term="高德地图API" scheme="http://yoursite.com/tags/%E9%AB%98%E5%BE%B7%E5%9C%B0%E5%9B%BEAPI/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS VPN开发]]></title>
    <link href="http://yoursite.com/2017/03/01/iOS%20VPN%E5%BC%80%E5%8F%91/"/>
    <id>http://yoursite.com/2017/03/01/iOS VPN开发/</id>
    <published>2017-03-01T03:27:43.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>#####参考链接：<br>1.iOS 9 Network Extension VPN API编程指南<a href="http://www.helusi.com/ios9-network-extension-vpn-api/" target="_blank" rel="noopener">http://www.helusi.com/ios9-network-extension-vpn-api/</a><br>2.分享开发 iOS 和 Mac 全新 VPN 的艰难历程<a href="https://www.v2ex.com/t/264480" target="_blank" rel="noopener">https://www.v2ex.com/t/264480</a><br>3.Potatso原理解析<a href="https://www.kidneyband.com/?p=174" target="_blank" rel="noopener">https://www.kidneyband.com/?p=174</a></p>
<p>#####苹果开发者文档：<br>NEPacketTunnelProvider<a href="https://developer.apple.com/reference/networkextension/nepackettunnelprovider?language=objc" target="_blank" rel="noopener">https://developer.apple.com/reference/networkextension/nepackettunnelprovider?language=objc</a><br>SimpleTunnel<a href="https://developer.apple.com/library/prerelease/content/samplecode/SimpleTunnel/Introduction/Intro.html" target="_blank" rel="noopener">https://developer.apple.com/library/prerelease/content/samplecode/SimpleTunnel/Introduction/Intro.html</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>#####参考链接：<br>1.iOS 9 Network Extension VPN API编程指南<a href="http://www.helusi.com/ios9-network-extension-vpn-api/" target="_blank" rel="n]]>
    </summary>
    
      <category term="iOS VPN" scheme="http://yoursite.com/tags/iOS-VPN/"/>
    
      <category term="Network Extension" scheme="http://yoursite.com/tags/Network-Extension/"/>
    
      <category term="NEPacketTunnelProvider" scheme="http://yoursite.com/tags/NEPacketTunnelProvider/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[UITableView-and-UIActivityIndicatorView 同页面的设置]]></title>
    <link href="http://yoursite.com/2015/11/26/UITableView-and-UIActivityIndicatorView/"/>
    <id>http://yoursite.com/2015/11/26/UITableView-and-UIActivityIndicatorView/</id>
    <published>2015-11-25T16:01:59.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<hr>
<p>storyboard 中 UIActivityIndicatorView 要放在tabelview下方<br>tableview y设置为0 重设约束才能保证tableview的顶部不会空白。</p>
]]></content>
    <summary type="html">
    <![CDATA[<hr>
<p>storyboard 中 UIActivityIndicatorView 要放在tabelview下方<br>tableview y设置为0 重设约束才能保证tableview的顶部不会空白。</p>
]]>
    </summary>
    
      <category term="UITableView" scheme="http://yoursite.com/tags/UITableView/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[NSDictionary NSMutableDictionary]]></title>
    <link href="http://yoursite.com/2015/08/18/NSDictionary-NSMutableDictionary/"/>
    <id>http://yoursite.com/2015/08/18/NSDictionary-NSMutableDictionary/</id>
    <published>2015-08-18T13:35:24.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>转自：<a href="http://seven-sally.lofter.com/post/19d861_5404fa" target="_blank" rel="noopener">http://seven-sally.lofter.com/post/19d861_5404fa</a></p>
<h2 id="不可变词典NSDictionary">不可变词典NSDictionary</h2><h3 id="字典初始化">字典初始化</h3><pre><code><span class="built_in">NSNumber</span> *numObj = [<span class="built_in">NSNumber</span> numberWithInt:<span class="number">100</span>];
</code></pre><h3 id="以一个元素初始化">以一个元素初始化</h3><pre><code>NSDictionary *dic = [NSDictionary <span class="string">dictionaryWithObject:</span>numObj <span class="string">forKey:</span>@<span class="string">"key"</span>];
</code></pre><h3 id="初始化两个元素">初始化两个元素</h3><pre><code><span class="built_in">NSDictionary</span> *dic = [<span class="built_in">NSDictionary</span> dictionaryWithObjectsAndKeys:numObj, <span class="string">@"valueKey"</span>, numObj2, <span class="string">@"value2"</span>,<span class="literal">nil</span>];
</code></pre><h3 id="初始化新字典，新字典包含otherDic">初始化新字典，新字典包含otherDic</h3><pre><code><span class="built_in">NSDictionary</span> *dic = [<span class="built_in">NSDictionary</span> dictionaryWithDictionary:otherDic];
</code></pre><h3 id="以文件内容初始化字典">以文件内容初始化字典</h3><pre><code><span class="built_in">NSDictionary</span> *dic = [<span class="built_in">NSDictionary</span> dictionaryWithContentsOfFile:path];
</code></pre><h3 id="常用方法">常用方法</h3><h3 id="获取字典数量">获取字典数量</h3><pre><code>NSInteger <span class="command">count</span> = [dic <span class="command">count</span>];
</code></pre><h3 id="通过key获取对应的value对象">通过key获取对应的value对象</h3><pre><code>NSObject <span class="keyword">*</span>valueObj = [dic objectForKey:<span class="comment">@"key"];</span>
</code></pre><h3 id="将字典的key转成枚举对象，用于遍历">将字典的key转成枚举对象，用于遍历</h3><pre><code>NSEnumerator *enumerator = [dic keyEnumerator]<span class="comment">;</span>
</code></pre><h3 id="获取所有键的集合">获取所有键的集合</h3><pre><code>NSArray *keys = [dic allKeys]<span class="comment">;</span>
</code></pre><h3 id="获取所有值的集合">获取所有值的集合</h3><pre><code>NSArray *values = [dic allValues]<span class="comment">;</span>
</code></pre><p><br></p>
<h2 id="可变数组NSMutableDictionary">可变数组NSMutableDictionary</h2><h3 id="初始化一个空的可变字典">初始化一个空的可变字典</h3><pre><code><span class="built_in">NSMutableDictionary</span> *dic2 = [<span class="built_in">NSMutableDictionary</span> dictionaryWithObjectsAndKeys:<span class="string">@"v1"</span>,<span class="string">@"key1"</span>,<span class="string">@"v2"</span>,<span class="string">@"key2"</span>,<span class="literal">nil</span>];

<span class="built_in">NSDictionary</span> *dic3 = [<span class="built_in">NSDictionary</span> dictionaryWithObject:<span class="string">@"v3"</span> forKey:<span class="string">@"key3"</span>];
</code></pre><h3 id="向字典2对象中添加整个字典对象3">向字典2对象中添加整个字典对象3</h3><pre><code><span class="title">[dic2 addEntriesFromDictionary:dic3]</span><span class="comment">;</span>
</code></pre><h3 id="向字典2对象中最佳一个新的key3和value3">向字典2对象中最佳一个新的key3和value3</h3><pre><code>[dic2 <span class="built_in">set</span>Value:@<span class="string">"value3"</span> <span class="keyword">for</span>Key:@<span class="string">"key3"</span>];
</code></pre><h3 id="初始化一个空的可变字典-1">初始化一个空的可变字典</h3><pre><code><span class="built_in">NSMutableDictionary</span> *dic1 = [<span class="built_in">NSMutableDictionary</span> dictionary];
</code></pre><h3 id="将空字典1对象内容设置与字典2对象相同">将空字典1对象内容设置与字典2对象相同</h3><pre><code><span class="title">[dic1 setDictionary:dic2]</span><span class="comment">;</span>
</code></pre><h3 id="将字典中key1对应的值删除">将字典中key1对应的值删除</h3><pre><code>[dic1 removeObjectForKey<span class="string">@"key1"</span>];

<span class="built_in">NSArray</span> *array = [<span class="built_in">NSArray</span> arrayWithObjects:<span class="string">@"key1"</span>, <span class="literal">nil</span>];
</code></pre><h3 id="根据指定的数组（key）移除字典1的内容">根据指定的数组（key）移除字典1的内容</h3><p>[dic2 removeObjectsForKeys:array];</p>
<h3 id="移除字典所有对象">移除字典所有对象</h3><pre><code><span class="title">[dic1 removeAllObjects]</span><span class="comment">;</span>
</code></pre><h3 id="遍历字典">遍历字典</h3><h3 id="快速枚举">快速枚举</h3><pre><code><span class="keyword">for</span> (<span class="keyword">id</span> key <span class="keyword">in</span> dic){

    <span class="keyword">id</span> obj = [dic objectForKey:key];

    <span class="built_in">NSLog</span>(<span class="string">@"%@"</span>, obj);

}
</code></pre><h3 id="一般枚举">一般枚举</h3><pre><code>NSArray *<span class="built_in">keys</span> = [dic allKeys];

inr length = [<span class="built_in">keys</span> <span class="built_in">count</span>];

for (<span class="typename">int</span> i = <span class="number">0</span>; i &lt; length；i++){

    id <span class="built_in">key</span> = [<span class="built_in">keys</span> objectAtIndex:i];

    id obj = [dic objectForKey:<span class="built_in">key</span>];

    NSLog(@<span class="string">"%@"</span>, obj);

}
</code></pre><h3 id="通过枚举类型枚举">通过枚举类型枚举</h3><pre><code><span class="built_in">NSEnumerator</span> *enumerator = [dic keyEnumerator];

<span class="keyword">id</span> key = [enumerator nextObject];

<span class="keyword">while</span> (key) {

    <span class="keyword">id</span> obj = [dic objectForKey:key];

    <span class="built_in">NSLog</span>(<span class="string">@"%@"</span>, obj);

    key = [enumerator nextObject];
}
</code></pre>]]></content>
    <summary type="html">
    <![CDATA[<p>转自：<a href="http://seven-sally.lofter.com/post/19d861_5404fa" target="_blank" rel="noopener">http://seven-sally.lofter.com/post/19d861_54]]>
    </summary>
    
      <category term="NSDictionary" scheme="http://yoursite.com/tags/NSDictionary/"/>
    
      <category term="NSMutableDictionary" scheme="http://yoursite.com/tags/NSMutableDictionary/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[markdown语法备忘]]></title>
    <link href="http://yoursite.com/2015/08/17/markdown-mark/"/>
    <id>http://yoursite.com/2015/08/17/markdown-mark/</id>
    <published>2015-08-16T16:01:59.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>参考<a href="http://ibruce.info/2013/11/26/markdown/" title="不如的博客" target="_blank" rel="noopener">markdown简明语法</a></p>
<hr>
<ol>
<li>强调用*或_</li>
<li>多级标题用n个#号</li>
<li>大标题、小标题用3个或以上===、—</li>
<li>引用&lt;、&lt;&lt;</li>
<li>行内代码&lt;!–0–&gt;</li>
<li>段落代码每行前加1个tab</li>
<li>无序列表用+或-号</li>
<li>文字链接用[text](url,””)；超链接用<url>;图片链接用![text](url,””)</url></li>
</ol>
<h1 id="Markdown_语法和_MWeb_写作使用说明">Markdown 语法和 MWeb 写作使用说明</h1><h2 id="Markdown_的设计哲学">Markdown 的设计哲学</h2><blockquote>
<p>Markdown 的目標是實現「易讀易寫」。<br>不過最需要強調的便是它的可讀性。一份使用 Markdown 格式撰寫的文件應該可以直接以純文字發佈，並且看起來不會像是由許多標籤或是格式指令所構成。<br>Markdown 的語法有個主要的目的：用來作為一種網路內容的<em>寫作</em>用語言。</p>
</blockquote>
<a id="more"></a>
<h2 id="本文约定">本文约定</h2><p>如果有写 <code>效果如下：</code>， 在 MWeb 编辑状态下只有用 <code>CMD + 4</code> 或 <code>CMD + R</code> 预览才可以看效果。</p>
<h2 id="标题">标题</h2><p>Markdown 语法：</p>
<figure class="highlight clean"><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"># 第一级标题 `&lt;h1&gt;` </span><br><span class="line">## 第二级标题 `&lt;h2&gt;` </span><br><span class="line">###### 第六级标题 `&lt;h6&gt;`</span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<h1 id="第一级标题_&lt;h1&gt;">第一级标题 <code>&lt;h1&gt;</code></h1><h2 id="第二级标题_&lt;h2&gt;">第二级标题 <code>&lt;h2&gt;</code></h2><h6 id="第六级标题_&lt;h6&gt;">第六级标题 <code>&lt;h6&gt;</code></h6><h2 id="强调">强调</h2><p>Markdown 语法：</p>
<figure class="highlight autohotkey"><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">*这些文字会生成`&lt;em&gt;`*</span><br><span class="line">_这些文字会生成`&lt;u&gt;`_</span><br><span class="line"></span><br><span class="line">**这些文字会生成`&lt;strong&gt;`**</span><br><span class="line">__这些文字会生成`&lt;strong&gt;`__</span><br></pre></td></tr></table></figure>
<p>在 MWeb 中的快捷键为： <code>CMD + U</code>、<code>CMD + I</code>、<code>CMD + B</code><br>效果如下：</p>
<p><em>这些文字会生成<code>&lt;em&gt;</code></em><br><em>这些文字会生成<code>&lt;u&gt;</code></em></p>
<p><strong>这些文字会生成<code>&lt;strong&gt;</code></strong><br><strong>这些文字会生成<code>&lt;strong&gt;</code></strong></p>
<h2 id="换行">换行</h2><p>四个及以上空格加回车。<br>如果不想打这么多空格，只要回车就为换行，请勾选：<code>Preferences</code> - <code>Themes</code> - <code>Translate newlines to &lt;br&gt; tags</code></p>
<h2 id="列表">列表</h2><h3 id="无序列表">无序列表</h3><p>Markdown 语法：</p>
<figure class="highlight autohotkey"><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></pre></td><td class="code"><pre><span class="line">* 项目一 无序列表 `* + 空格键`</span><br><span class="line">* 项目二</span><br><span class="line">	* 项目二的子项目一 无序列表 `TAB + * + 空格键`</span><br><span class="line">	* 项目二的子项目二</span><br></pre></td></tr></table></figure>
<p>在 MWeb 中的快捷键为： <code>Option + U</code><br>效果如下：</p>
<ul>
<li>项目一 无序列表 <code>* + 空格键</code></li>
<li>项目二<ul>
<li>项目二的子项目一 无序列表 <code>TAB + * + 空格键</code></li>
<li>项目二的子项目二</li>
</ul>
</li>
</ul>
<h3 id="有序列表">有序列表</h3><p>Markdown 语法：</p>
<figure class="highlight lsl"><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 class="number">1.</span> 项目一 有序列表 `数字 + . + 空格键`</span><br><span class="line"><span class="number">2.</span> 项目二 </span><br><span class="line"><span class="number">3.</span> 项目三</span><br><span class="line">	<span class="number">1.</span> 项目三的子项目一 有序列表 `TAB + 数字 + . + 空格键`</span><br><span class="line">	<span class="number">2.</span> 项目三的子项目二</span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<ol>
<li>项目一 有序列表 <code>数字 + . + 空格键</code></li>
<li>项目二 </li>
<li>项目三<ol>
<li>项目三的子项目一 有序列表 <code>TAB + 数字 + . + 空格键</code></li>
<li>项目三的子项目二</li>
</ol>
</li>
</ol>
<h3 id="任务列表（Task_lists）">任务列表（Task lists）</h3><p>Markdown 语法：</p>
<figure class="highlight haml"><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">-<span class="ruby"> [ ] 任务一 未做任务 <span class="string">`- + 空格 + [ ]`</span></span></span><br><span class="line"><span class="ruby">- [x] 任务二 已做任务 <span class="string">`- + 空格 + [x]`</span></span></span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<ul>
<li>[ ] 任务一 未做任务 <code>- + 空格 + [ ]</code></li>
<li>[x] 任务二 已做任务 <code>- + 空格 + [x]</code></li>
</ul>
<h2 id="图片">图片</h2><p>Markdown 语法：</p>
<figure class="highlight markdown"><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">![<span class="string">GitHub set up</span>](<span class="link">http://zh.mweb.im/asset/img/set-up-git.gif</span>)</span><br><span class="line">格式: ![<span class="string">Alt Text</span>](<span class="link">url</span>)</span><br></pre></td></tr></table></figure>
<p><code>Control + Shift + I</code> 可插入Markdown语法。<br>如果是 MWeb 的文档库中的文档，还可以用拖放图片、<code>CMD + V</code> 粘贴、<code>CMD + Option + I</code> 导入这三种方式来增加图片。<br>效果如下：</p>
<p><img src="http://zh.mweb.im/asset/img/set-up-git.gif" alt="GitHub set up"></p>
<p>MWeb 引入的特别的语法来设置图片宽度，方法是在图片描述后加 <code>-w + 图片宽度</code> 即可，比如说要设置上面的图片的宽度为 140，语法如下：</p>
<p><img src="http://zh.mweb.im/asset/img/set-up-git.gif" alt="GitHub set up-w140"></p>
<h2 id="链接">链接</h2><p>Markdown 语法：</p>
<figure class="highlight markdown"><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">email <span class="xml"><span class="tag">&lt;<span class="name">example@example.com</span>&gt;</span></span></span><br><span class="line">[<span class="string">GitHub</span>](<span class="link">http://github.com</span>)</span><br><span class="line">自动生成连接  <span class="xml"><span class="tag">&lt;<span class="name">http:</span>//<span class="attr">www.github.com</span>/&gt;</span></span></span><br></pre></td></tr></table></figure>
<p><code>Control + Shift + L</code> 可插入Markdown语法。<br>如果是 MWeb 的文档库中的文档，拖放或<code>CMD + Option + I</code> 导入非图片时，会生成连接。<br>效果如下：</p>
<p>Email 连接： <a href="&#x6d;&#97;&#x69;&#108;&#x74;&#111;&#58;&#101;&#120;&#97;&#x6d;&#112;&#108;&#x65;&#64;&#x65;&#x78;&#x61;&#109;&#112;&#108;&#101;&#46;&#99;&#x6f;&#x6d;">&#101;&#120;&#97;&#x6d;&#112;&#108;&#x65;&#64;&#x65;&#x78;&#x61;&#109;&#112;&#108;&#101;&#46;&#99;&#x6f;&#x6d;</a><br><a href="http://github.com" target="_blank" rel="noopener">连接标题Github网站</a><br>自动生成连接像： <a href="http://www.github.com/" target="_blank" rel="noopener">http://www.github.com/</a> 这样</p>
<h2 id="区块引用">区块引用</h2><p>Markdown 语法：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">某某说:</span><br><span class="line"><span class="meta">&gt;</span><span class="bash"> 第一行引用</span></span><br><span class="line"><span class="meta">&gt;</span><span class="bash"> 第二行费用文字</span></span><br></pre></td></tr></table></figure>
<p><code>CMD + Shift + B</code> 可插入Markdown语法。<br>效果如下：</p>
<p>某某说:</p>
<blockquote>
<p>第一行引用<br>第二行费用文字</p>
</blockquote>
<h2 id="行内代码">行内代码</h2><p>Markdown 语法：</p>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">像这样即可：`&lt;addr&gt;` `<span class="keyword">code</span>`</span><br></pre></td></tr></table></figure>
<p><code>CMD + K</code> 可插入Markdown语法。<br>效果如下：</p>
<p>像这样即可：<code>&lt;addr&gt;</code> <code>code</code></p>
<h2 id="多行或者一段代码">多行或者一段代码</h2><p>Markdown 语法：</p>
<pre><code><span class="comment"><figure class="highlight js"><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="function"><span class="keyword">function</span> <span class="title">fancyAlert</span>(<span class="params">arg</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(arg) &#123;</span><br><span class="line">    $.facebox(&#123;<span class="attr">div</span>:<span class="string">'#foo'</span>&#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></span>
</code></pre><p><code>CMD + Shift + K</code> 可插入Markdown语法。<br>效果如下：</p>
<figure class="highlight js"><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="function"><span class="keyword">function</span> <span class="title">fancyAlert</span>(<span class="params">arg</span>) </span>&#123;</span><br><span class="line">	<span class="keyword">if</span>(arg) &#123;</span><br><span class="line">		$.facebox(&#123;<span class="attr">div</span>:<span class="string">'#foo'</span>&#125;)</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="顺序图或流程图">顺序图或流程图</h2><p>Markdown 语法：</p>
<pre><code><span class="comment"><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></pre></td><td class="code"><pre><span class="line">张三-&gt;李四: 嘿，小四儿, 写博客了没?</span><br><span class="line">Note right of 李四: 李四愣了一下，说：</span><br><span class="line">李四--&gt;张三: 忙得吐血，哪有时间写。</span><br></pre></td></tr></table></figure></span>

<span class="comment"><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">st=&gt;start: 开始</span><br><span class="line">e=&gt;end: 结束</span><br><span class="line">op=&gt;operation: 我的操作</span><br><span class="line">cond=&gt;condition: 确认？</span><br><span class="line"></span><br><span class="line">st-&gt;op-&gt;cond</span><br><span class="line">cond(yes)-&gt;e</span><br><span class="line">cond(no)-&gt;op</span><br></pre></td></tr></table></figure></span>
</code></pre><p>效果如下（ <code>Preferences</code> - <code>Themes</code> - <code>Enable sequence &amp; flow chart</code> 才会看到效果 ）：</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></pre></td><td class="code"><pre><span class="line">张三-&gt;李四: 嘿，小四儿, 写博客了没?</span><br><span class="line">Note right of 李四: 李四愣了一下，说：</span><br><span class="line">李四--&gt;张三: 忙得吐血，哪有时间写。</span><br></pre></td></tr></table></figure>
<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">st=&gt;start: 开始</span><br><span class="line">e=&gt;end: 结束</span><br><span class="line">op=&gt;operation: 我的操作</span><br><span class="line">cond=&gt;condition: 确认？</span><br><span class="line"></span><br><span class="line">st-&gt;op-&gt;cond</span><br><span class="line">cond(yes)-&gt;e</span><br><span class="line">cond(no)-&gt;op</span><br></pre></td></tr></table></figure>
<p>更多请参考：<a href="http://bramp.github.io/js-sequence-diagrams/" target="_blank" rel="noopener">http://bramp.github.io/js-sequence-diagrams/</a>, <a href="http://adrai.github.io/flowchart.js/" target="_blank" rel="noopener">http://adrai.github.io/flowchart.js/</a></p>
<h2 id="表格">表格</h2><p>Markdown 语法：</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></pre></td><td class="code"><pre><span class="line">第一格表头 | 第二格表头</span><br><span class="line">--------- | -------------</span><br><span class="line">内容单元格 第一列第一格 | 内容单元格第二列第一格</span><br><span class="line">内容单元格 第一列第二格 多加文字 | 内容单元格第二列第二格</span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<table>
<thead>
<tr>
<th>第一格表头</th>
<th>第二格表头</th>
</tr>
</thead>
<tbody>
<tr>
<td>内容单元格 第一列第一格</td>
<td>内容单元格第二列第一格</td>
</tr>
<tr>
<td>内容单元格 第一列第二格 多加文字</td>
<td>内容单元格第二列第二格</td>
</tr>
</tbody>
</table>
<h2 id="删除线">删除线</h2><p>Markdown 语法：</p>
<pre><code>加删除线像这样用： ~~删除这些~~
</code></pre><p>效果如下：</p>
<p>加删除线像这样用： <del>删除这些</del></p>
<h2 id="分隔线">分隔线</h2><p>以下三种方式都可以生成分隔线：</p>
<pre><code><span class="keyword">*</span><span class="keyword">*</span><span class="keyword">*</span>

<span class="keyword">*</span><span class="keyword">*</span><span class="keyword">*</span><span class="keyword">*</span><span class="keyword">*</span>

- - -
</code></pre><p>效果如下：</p>
<hr>
<hr>
<hr>
<h2 id="MathJax">MathJax</h2><p>Markdown 语法：</p>
<figure class="highlight taggerscript"><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">块级公式：</span><br><span class="line">$$	x = <span class="symbol">\d</span>frac&#123;-b <span class="symbol">\p</span>m <span class="symbol">\s</span>qrt&#123;b^2 - 4ac&#125;&#125;&#123;2a&#125; $$</span><br><span class="line"></span><br><span class="line"><span class="symbol">\\</span>[ <span class="symbol">\f</span>rac&#123;1&#125;&#123;<span class="symbol">\B</span>igl(<span class="symbol">\s</span>qrt&#123;<span class="symbol">\p</span>hi <span class="symbol">\s</span>qrt&#123;5&#125;&#125;-<span class="symbol">\p</span>hi<span class="symbol">\B</span>igr) e^&#123;<span class="symbol">\f</span>rac25 <span class="symbol">\p</span>i&#125;&#125; =</span><br><span class="line">1+<span class="symbol">\f</span>rac&#123;e^&#123;-2<span class="symbol">\p</span>i&#125;&#125; &#123;1+<span class="symbol">\f</span>rac&#123;e^&#123;-4<span class="symbol">\p</span>i&#125;&#125; &#123;1+<span class="symbol">\f</span>rac&#123;e^&#123;-6<span class="symbol">\p</span>i&#125;&#125;</span><br><span class="line">&#123;1+<span class="symbol">\f</span>rac&#123;e^&#123;-8<span class="symbol">\p</span>i&#125;&#125; &#123;1+<span class="symbol">\l</span>dots&#125; &#125; &#125; &#125; <span class="symbol">\\</span>]</span><br><span class="line"></span><br><span class="line">行内公式： $<span class="symbol">\G</span>amma(n) = (n-1)!<span class="symbol">\q</span>uad<span class="symbol">\f</span>orall n<span class="symbol">\i</span>n<span class="symbol">\m</span>athbb N$</span><br></pre></td></tr></table></figure>
<p>效果如下（<code>Preferences</code> - <code>Themes</code> - <code>Enable MathJax</code> 才会看到效果）：</p>
<p>块级公式：<br>$$    x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$</p>
<p>\[ \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} =<br>1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}}<br>{1+\frac{e^{-8\pi}} {1+\ldots} } } } \]</p>
<p>行内公式： $\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N$</p>
<h2 id="脚注（Footnote）">脚注（Footnote）</h2><p>Markdown 语法：</p>
<figure class="highlight accesslog"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是一个脚注：<span class="string">[^sample_footnote]</span></span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<p>这是一个脚注：<a href="这里是脚注信息">^sample_footnote</a></p>
<h2 id="注释和阅读更多">注释和阅读更多</h2><!-- comment -->
<!-- more -->
<p>Actions-&gt;Insert Read More Comment <em>或者</em> <code>Command + .</code><br><strong>注</strong> 阅读更多的功能只用在生成网站或博客时，插入时注意要后空一行。</p>
<h2 id="TOC">TOC</h2><p>Markdown 语法：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[TOC]</span><br></pre></td></tr></table></figure>
<p>效果如下：</p>
<p>[TOC]</p>
]]></content>
    <summary type="html">
    <![CDATA[<p>参考<a href="http://ibruce.info/2013/11/26/markdown/" title="不如的博客" target="_blank" rel="noopener">markdown简明语法</a></p>
<hr>
<ol>
<li>强调用*或_</li>
<li>多级标题用n个#号</li>
<li>大标题、小标题用3个或以上===、—</li>
<li>引用&lt;、&lt;&lt;</li>
<li>行内代码&lt;!–0–&gt;</li>
<li>段落代码每行前加1个tab</li>
<li>无序列表用+或-号</li>
<li>文字链接用[text](url,””)；超链接用<url>;图片链接用![text](url,””)</url></li>
</ol>
<h1 id="Markdown_语法和_MWeb_写作使用说明">Markdown 语法和 MWeb 写作使用说明</h1><h2 id="Markdown_的设计哲学">Markdown 的设计哲学</h2><blockquote>
<p>Markdown 的目標是實現「易讀易寫」。<br>不過最需要強調的便是它的可讀性。一份使用 Markdown 格式撰寫的文件應該可以直接以純文字發佈，並且看起來不會像是由許多標籤或是格式指令所構成。<br>Markdown 的語法有個主要的目的：用來作為一種網路內容的<em>寫作</em>用語言。</p>
</blockquote>]]>
    
    </summary>
    
      <category term="markdown" scheme="http://yoursite.com/tags/markdown/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[hexo搭建博客done]]></title>
    <link href="http://yoursite.com/2015/08/13/postname/"/>
    <id>http://yoursite.com/2015/08/13/postname/</id>
    <published>2015-08-12T16:08:31.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"></content>
    <summary type="html">
    
    </summary>
    
  </entry>
  
  <entry>
    <title><![CDATA[Hello World]]></title>
    <link href="http://yoursite.com/2015/08/12/hello-world/"/>
    <id>http://yoursite.com/2015/08/12/hello-world/</id>
    <published>2015-08-11T16:01:59.000Z</published>
    <updated>2018-10-17T04:51:55.198Z</updated>
    <content type="html"><![CDATA[<p>Welcome to <a href="http://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="http://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="http://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p>
<h2 id="Quick_Start">Quick Start</h2><h3 id="Create_a_new_post">Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p>
<h3 id="Run_server">Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p>
<h3 id="Generate_static_files">Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p>
<h3 id="Deploy_to_remote_sites">Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure>
<p>More info: <a href="http://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p>
]]></content>
    <summary type="html">
    <![CDATA[<p>Welcome to <a href="http://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="http://hexo.io]]>
    </summary>
    
  </entry>
  
</feed>
