<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>签到 on Hacper&#39;s Blog</title>
    <link>https://hacperme.com/tags/%E7%AD%BE%E5%88%B0/</link>
    <description>Recent content in 签到 on Hacper&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <lastBuildDate>Sun, 30 Sep 2018 14:17:04 +0800</lastBuildDate>
    <atom:link href="https://hacperme.com/tags/%E7%AD%BE%E5%88%B0/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>用 Python 实现多看阅读签到领书币</title>
      <link>https://hacperme.com/posts/notes/2018-09-30-duokan_python/</link>
      <pubDate>Sun, 30 Sep 2018 14:17:04 +0800</pubDate>
      <guid>https://hacperme.com/posts/notes/2018-09-30-duokan_python/</guid>
      <description>对 Android 多看阅读 APP 进行抓包，可以获取其每天签到领书币的请求接口。 1 2 3 4 5 6 7 POST /checkin/v0/checkin HTTP/1.1 Host: www.duokan.com Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip,deflate Cookie: device_id=***************************;app_id=DkReader.Android;build=562180926;channel=TBVP2Y;user_type=1;device_hash=###################;device_hash_set=null;token=XXXXXXXXXXXXXXXXXXXXXXX; _t=1538224732&amp;amp;_c=10319 请求头 Cookie 中的 token 来自账号登录成功后返回的数据</description>
      <content:encoded><![CDATA[<p><img loading="lazy" src="https://ipfs.busy.org/ipfs/QmZHQJL6NNq3geu6Q7EhBS9wju86xZATqwn6rtNHr8s8mi" alt="image.png"  />
</p>
<p>对 Android 多看阅读 APP 进行抓包，可以获取其每天签到领书币的请求接口。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-http" data-lang="http"><span class="line"><span class="cl"><span class="nf">POST</span> <span class="nn">/checkin/v0/checkin</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
</span></span><span class="line"><span class="cl"><span class="n">Host</span><span class="o">:</span> <span class="l">www.duokan.com</span>
</span></span><span class="line"><span class="cl"><span class="n">Content-Type</span><span class="o">:</span> <span class="l">application/x-www-form-urlencoded</span>
</span></span><span class="line"><span class="cl"><span class="n">Accept-Encoding</span><span class="o">:</span>  <span class="l">gzip,deflate</span>
</span></span><span class="line"><span class="cl"><span class="n">Cookie</span><span class="o">:</span>  <span class="l">device_id=***************************;app_id=DkReader.Android;build=562180926;channel=TBVP2Y;user_type=1;device_hash=###################;device_hash_set=null;token=XXXXXXXXXXXXXXXXXXXXXXX;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">_t=1538224732&amp;_c=10319
</span></span></code></pre></td></tr></table>
</div>
</div><p>请求头 Cookie 中的 token 来自账号登录成功后返回的数据里，请求体中的_t 参数是当前时间（时间戳），_c 是由时间戳和 device_id 计算得来的。</p>
<p>用 Apk Extractor Lite 提取出多看阅读的安装包，再用 MT管理器 打开，反编译后可以得到生成 _t _C 参数的 JAVA 程序：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="nf">genCsrfCode</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">split</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">ReaderEnv</span><span class="p">.</span><span class="na">get</span><span class="p">().</span><span class="na">getDeviceId</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="sc">&#39;&amp;&#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">System</span><span class="p">.</span><span class="na">currentTimeMillis</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">1000</span><span class="p">))).</span><span class="na">split</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="p">;</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">split</span><span class="p">.</span><span class="na">length</span><span class="p">;</span><span class="w"> </span><span class="n">i2</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">generate</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">split</span><span class="o">[</span><span class="n">i2</span><span class="o">]</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="p">{</span><span class="s">&#34;_t&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">String</span><span class="p">.</span><span class="na">valueOf</span><span class="p">(</span><span class="n">r4</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;_c&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">String</span><span class="p">.</span><span class="na">valueOf</span><span class="p">(</span><span class="n">i</span><span class="p">)};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">generate</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">str</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">((</span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">131</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">str</span><span class="p">.</span><span class="na">getBytes</span><span class="p">()</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">65536</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>类似的，可以写成 Python 程序：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;device_id&#39;</span><span class="p">:</span> <span class="s1">&#39;************************&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;app_id&#39;</span><span class="p">:</span> <span class="s1">&#39;DkReader.Android&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;build&#39;</span><span class="p">:</span> <span class="s1">&#39;562180926&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;device_hash&#39;</span><span class="p">:</span> <span class="s1">&#39;######################&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;token&#39;</span><span class="p">:</span> <span class="s1">&#39;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_csrf_params</span><span class="p">(</span><span class="n">device_id</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">t</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">timestamp</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">    <span class="n">string</span> <span class="o">=</span> <span class="n">device_id</span> <span class="o">+</span> <span class="s1">&#39;&amp;&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">string</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="n">c</span> <span class="o">*</span> <span class="mi">131</span> <span class="o">+</span> <span class="n">string</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">encode</span><span class="p">()[</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="mi">65536</span>
</span></span><span class="line"><span class="cl">        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">t</span><span class="p">,</span> <span class="n">c</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>签到：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">duokanqd</span><span class="p">(</span><span class="n">config</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;https://www.duokan.com/checkin/v0/checkin&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">Cookie</span> <span class="o">=</span> <span class="s2">&#34;device_id=</span><span class="si">{device_id}</span><span class="s2">;app_id=</span><span class="si">{app_id}</span><span class="s2">;build=</span><span class="si">{build}</span><span class="s2">;channel=TBVP2Y;user_type=1;device_hash=</span><span class="si">{device_hash}</span><span class="s2">;</span><span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span><span class="s2">device_hash_set=null;token=</span><span class="si">{token}</span><span class="s2">;&#34;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">**</span><span class="n">config</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;Content-Type&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;application/x-www-form-urlencoded&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;User-Agent&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;Dalvik/2.1.0 (Linux; U; Android 8.0.0; PRA-AL00X Build/HONORPRA-AL00X)&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;Accept-Encoding&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;gzip,deflate&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;Cookie&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">Cookie</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">_t</span><span class="p">,</span> <span class="n">_c</span> <span class="o">=</span> <span class="n">get_csrf_params</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;device_id&#39;</span><span class="p">,</span> <span class="s1">&#39;D0063006284a6677&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;_t&#39;</span><span class="p">:</span> <span class="n">_t</span><span class="p">,</span> <span class="s1">&#39;_c&#39;</span><span class="p">:</span> <span class="n">_c</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">rsp</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">rsp</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">duokanqd</span><span class="p">(</span><span class="n">config</span><span class="p">))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span><span class="err">&#39;msg&#39;:</span> <span class="err">&#39;今日已签到&#39;,</span> <span class="err">&#39;result&#39;:</span> <span class="err">500002</span><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>写个定时任务，每天执行一下这个签到程序就可以自动领书币了。<br>
抓包获取的 token 总会到失效的一天，得通过多看的登录接口更新 token，其登录API为：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-http" data-lang="http"><span class="line"><span class="cl"><span class="nf">POST</span> <span class="nn">/dk_id/api/wx/login</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
</span></span><span class="line"><span class="cl"><span class="n">Host</span><span class="o">:</span> <span class="l">www.duokan.com</span>
</span></span><span class="line"><span class="cl"><span class="n">Content-Type</span><span class="o">:</span> <span class="l">application/x-www-form-urlencoded</span>
</span></span><span class="line"><span class="cl"><span class="n">Cookie</span><span class="o">:</span>  <span class="l">device_id=XXXXXXXXXXXXXXXX;device_hash=********************</span>
</span></span><span class="line"><span class="cl"><span class="n">User-Agent</span><span class="o">:</span>  <span class="l">Dalvik/2.1.0 (Linux; U; Android 8.0.0; PRA-AL00X Build/HONORPRA-AL00X)</span>
</span></span><span class="line"><span class="cl"><span class="n">Accept-Encoding</span><span class="o">:</span>  <span class="l">gzip</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">package=com.duokan.reader&amp;code=XXXXXXXXXXXXX&amp;_t=1538236192&amp;_c=60082
</span></span></code></pre></td></tr></table>
</div>
</div><p>这是我用微信账号授权登录的请求，code 这个参数是使用微信授权登录的一个临时令牌，code 是一次性的，用过就失效了。code 这个参数获取不了，想要自动登录多看账号的想法失败。</p>
<p>如果不用微信登录，而直接用小米的账号密码登录，是不是可以成功登录多看呢？得注册个小米账号试试。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
