我的女神 發表於 2020-2-20 01:22:00

js反爬:请开启JavaScript并刷新该页

<p>中国人民银行网站中的这个栏目为例:http://www.pbc.gov.cn/zhengcehuobisi/125207/125217/125925/17105/index1.html</p>
<p>如果直接用request.get(url),就会得到下图的JavaScript并刷新该页,跟着一堆乱七八糟代码。</p>
<p><img src="https://img2018.cnblogs.com/i-beta/987653/202002/987653-20200219190100804-2073746438.png" alt="" width="507" height="165"></p>
<p>简单来说,就是html文件中包含cookie设置和动态跳转网址的js代码,访问这个网页时js会设置cookie然后重定向到另一个网页,所以只是get这个url是不行的。</p>
<p>同理,如果清除cookie,在浏览器中f12,然后按f1禁用js</p>
<p><img src="https://img2018.cnblogs.com/i-beta/987653/202002/987653-20200219191316087-778851836.png" alt="" width="184" height="79"></p>
<p>&nbsp;</p>
<p>&nbsp;刷新页面,就会出现下图乱码,其实就是之前跑代码得到的 “请开启JavaScript并刷新该页” 提示。</p>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/i-beta/987653/202002/987653-20200219191235209-2118985113.png" alt="" width="516" height="98"></p>
<p>因此,要爬取这个网站的关键问题有两个,一个是用js重定向,一个是保存cookie。</p>
<p>先看看返回的网页的js代码。</p>
<p><img src="https://img2018.cnblogs.com/i-beta/987653/202002/987653-20200219191820875-617258171.png" alt="" width="543" height="296"></p>
<p>&nbsp;</p>
<p>这就很乱了,随便用个js代码格式化网站,比如&nbsp;https://www.bm8.com.cn/jsConfusion/</p>
<p>这样就可以比较清晰的看到js代码。</p>
<p>一顿分析之后,实现抓取的过程如下:</p>
<p>先get之前能得到的带有js的html。</p>
<p>将其中的js代码正则提取出来。</p>
<p>将里面的atob替换为window["atob"],增加window对象,函数getURL()返回window["location"],即跳转的链接尾缀。</p>
<p>将这个修改后js代码执行,得到尾缀,与原URL链接,得到重定向的URL。</p>
<p>还有就是cookie问题,直接用requests的session处理就好。</p>
<div class="cnblogs_code">
<pre><span style="font-size: 14px"><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> getPage(URL):
    sess </span>=<span style="color: rgba(0, 0, 0, 1)"> requests.session()
    jsPage </span>=<span style="color: rgba(0, 0, 0, 1)"> sess.get(URL).text
    js </span>= re.findall(r<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">&lt;script type="text/javascript"&gt;([\w\W]*)&lt;/script&gt;</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, jsPage)
    js </span>= re.sub(r<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">atob\(</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">window["atob"](</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, js)
    js2 </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">function getURL(){ var window = {};</span><span style="color: rgba(128, 0, 0, 1)">'</span> + js + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">return window["location"];}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
    ctx </span>=<span style="color: rgba(0, 0, 0, 1)"> execjs.compile(js2)
    tail </span>= ctx.call(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">getURL</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
    URL2 </span>=<span style="color: rgba(0, 0, 0, 1)"> urljoin(URL, tail)
    page </span>=<span style="color: rgba(0, 0, 0, 1)"> sess.get(URL2)
    page.encoding </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UTF-8</span><span style="color: rgba(128, 0, 0, 1)">'</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span> page</span></pre>
</div>
<p>最后,在连续抓取页面时有时会报错,加了一两秒延迟就好了。还是会偶尔报错,用异常抛出让它重试即可。</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/sumuyi/p/12334154.html
頁: [1]
查看完整版本: js反爬:请开启JavaScript并刷新该页