使用PyV8在Python爬虫中执行js代码


Posted in Python onFebruary 16, 2017

前言

可能很多人会觉得这是一个奇葩的需求,爬虫去好好的爬数据不就行了,解析js干嘛?吃饱了撑的?

搜索一下互联网上关于这个问题还真不少,但是大多数童鞋是因为自己的js基础太烂,要么是HTML基础烂,要么ajax基础烂,反正各方面都很烂。基础这么渣不好好去学基础写什么爬虫?

那你肯定要问了“请问我的朋友,你TM怎么也有这个需求?莫非你是个技术渣?”

非也非也,博主作为一个拥有3年多前端经验的攻城尸,怎么会被这个问题给难倒呢,老夫今天遇到的问题很显然没有那么简单。

问题

那么博主到底是遇到什么问题了呢?

博主今天要去爬一个接口,但是调用那个接口需要带上令牌,也就是存储在Cookie中的一个类似token的东西,Cookie的值是一段js生成的,这段js又是通过另外一个接口获取回来的,而获取回来的js代码还是动态的,WTF!!!开发人员你这是 弄撒嘞?

路人甲:我擦嘞,声称经验老道的博主不会分析js的逻辑?

对,我就是不会,特么的js代码都是混淆加密的,眼睛都看瞎了都特么不知道写的都是写啥?

算了,我直接执行拿到结果就好了,管他写的是什么鬼。

思路

理一理思路,现在要做的事情其实很简单

  1. 请求接口A,拿到动态生成的混淆过的js代码
  2. 执行js代码,拿到生成的cookie值
  3. 请求接口B,带上js生成的令牌
  4. 拿到结果,愉快的玩耍...

思路相当的清晰,感觉秒秒钟就可以实现了呢。()

难题

Python里面执行js?有点意思,我干嘛不用nodejs呢?

因为Python是世界上最?诺挠镅园。∶挥兄?唬?/p>

找到了PyV8这个神奇的模块,机器已经有了pip,执行安装一下不就OK了?

pip install pyv8

不要怀疑,博主机器装的是 Kali Linux ,Root 权限,不需要 sudo

接着报错

pip install -U PyV8
Collecting PyV8
 Using cached PyV8-0.5.zip
Building wheels for collected packages: PyV8
 Running setup.py bdist_wheel for PyV8 ... error
 Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-QUm4bX/PyV8/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" bdist_wheel -d /tmp/tmpb0udlepip-wheel- --python-tag cp27:
 running bdist_wheel
 running build
 running build_py
 creating build
 creating build/lib.linux-x86_64-2.7
 copying PyV8.py -> build/lib.linux-x86_64-2.7
 running build_ext
 building '_PyV8' extension
 creating build/temp.linux-x86_64-2.7
 creating build/temp.linux-x86_64-2.7/src
 x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-cFt4xx/python2.7-2.7.12=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DBOOST_PYTHON_STATIC_LIB -Ilib/python/inc -Ilib/boost/inc -Ilib/v8/inc -I/usr/include/python2.7 -c src/Exception.cpp -o build/temp.linux-x86_64-2.7/src/Exception.o
 cc1plus: warning: command line option ‘-Wstrict-prototypes' is valid for C/ObjC but not for C++
 In file included from src/Exception.cpp:1:0:
 src/Exception.h:6:16: fatal error: v8.h: 没有那个文件或目录
 #include <v8.h>
     ^
 compilation terminated.
 error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
 
 ----------------------------------------
 Failed building wheel for PyV8
 Running setup.py clean for PyV8
Failed to build PyV8
Installing collected packages: PyV8
 Running setup.py install for PyV8 ... error
 Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-QUm4bX/PyV8/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-7OAwUa-record/install-record.txt --single-version-externally-managed --compile:
 running install
 running build
 running build_py
 creating build
 creating build/lib.linux-x86_64-2.7
 copying PyV8.py -> build/lib.linux-x86_64-2.7
 running build_ext
 building '_PyV8' extension
 creating build/temp.linux-x86_64-2.7
 creating build/temp.linux-x86_64-2.7/src
 x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-cFt4xx/python2.7-2.7.12=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DBOOST_PYTHON_STATIC_LIB -Ilib/python/inc -Ilib/boost/inc -Ilib/v8/inc -I/usr/include/python2.7 -c src/Exception.cpp -o build/temp.linux-x86_64-2.7/src/Exception.o
 cc1plus: warning: command line option ‘-Wstrict-prototypes' is valid for C/ObjC but not for C++
 In file included from src/Exception.cpp:1:0:
 src/Exception.h:6:16: fatal error: v8.h: 没有那个文件或目录
  #include <v8.h>
     ^
 compilation terminated.
 error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
 
 ----------------------------------------
Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-QUm4bX/PyV8/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-7OAwUa-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-QUm4bX/PyV8/

似乎是因为缺少 v8.h 这个文件导致的,可是又看不懂啥意思。

解决

通过搜索引擎找到了解决方案,原来是因为 PyV8 依赖于Boost ,然而这个问题官方并没有说,所以得先安装下这个包

apt-get update && apt-get install libboost-all-dev

安装完成之后继续安装 PyV8 ,依然是上面同样的问题,看来只能手动来了。

下载 https://github.com/emmetio/pyv8-binaries

解压并选择合适自己系统环境的文件,再次解压 并把解压得到的文件复制到

/usr/lib/python2.7/dist-packages/

里面去,然后测试看是否成功,终端执行

python
import PyV8

如果没有报错,那就成功了,开始愉快的玩耍,下面是我需要解析的js代码

var l = [119, 98, 115, 33, 111, 109, 120, 105, 118, 62, 92, 50, 50, 54, 45, 50, 50, 51, 45, 50, 50, 55, 45, 50, 49, 58, 45, 50, 50, 49, 45, 50, 51, 51, 45, 50, 50, 52, 45, 50, 50, 51, 45, 50, 50, 54, 45, 50, 49, 55, 45, 50, 49, 58, 45, 50, 49, 50, 45, 50, 50, 54, 45, 50, 50, 58, 45, 50, 50, 49, 45, 50, 50, 51, 45, 50, 50, 58, 45, 50, 51, 51, 45, 50, 50, 58, 45, 50, 50, 55, 45, 50, 50, 54, 45, 50, 50, 54, 94, 60, 119, 98, 115, 33, 121, 119, 99, 100, 108, 62, 92, 49, 45, 51, 50, 45, 53, 45, 55, 45, 50, 50, 45, 57, 45, 56, 45, 50, 51, 45, 51, 45, 51, 49, 45, 50, 52, 45, 50, 54, 45, 50, 49, 45, 50, 57, 45, 52, 45, 58, 45, 50, 53, 45, 50, 56, 45, 54, 45, 50, 55, 45, 50, 58, 45, 50, 94, 60, 119, 98, 115, 33, 118, 62, 35, 35, 60, 103, 112, 115, 33, 41, 119, 62, 49, 60, 119, 61, 121, 119, 99, 100, 108, 47, 109, 102, 111, 104, 117, 105, 60, 119, 44, 44, 42, 124, 118, 44, 62, 84, 117, 115, 106, 111, 104, 47, 103, 115, 112, 110, 68, 105, 98, 115, 68, 112, 101, 102, 41, 111, 109, 120, 105, 118, 92, 121, 119, 99, 100, 108, 92, 119, 94, 94, 42, 126, 60, 37, 47, 100, 112, 112, 108, 106, 102, 41, 40, 114, 117, 112, 108, 102, 111, 40, 45, 118, 45, 124, 113, 98, 117, 105, 59, 40, 48, 40, 126, 42, 60];
eval(function(p, a, c, k, e, d) {
 e = function(c) {
 return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
 };
 if (!''.replace(/^/, String)) {
 while (c--) d[e(c)] = k[c] || e(c);
 k = [function(e) {
 return d[e]
 }];
 e = function() {
 return '\\w+'
 };
 c = 1
 };
 while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
 return p
}('6 3=\'\';7(2=0;2<4.5;2++){3+=8.a(4[2]-1)};9(3)', 11, 11, '||i|t|l|length|var|for|String|eval|fromCharCode'.split('|'), 0, {}))

已经经过整理,其实刚开始就只有一行,比较尴尬

姿势

折腾的过程可谓是各种曲折,不过也学到了不少姿势,比如,如何把混淆的js还原成原始代码

使用Firebug插件就能轻松解决这个问题,打开firebug插件,找到脚本选项,选择带 eval 的项,一般解析到最后一行就是原始代码了,我上面的那段 js 还原之后就便成了这个样子

var balwi=[115,116,115,122,112,115,110,106,122,110,122,112,101,119,115,106,113,101,116,116,119,106];var ljpry=[15,21,4,9,12,14,11,0,18,20,8,16,7,2,1,10,17,13,19,6,5,3];var j="";for (k=0;k<ljpry.length;k++){j+=String.fromCharCode(balwi[ljpry[k]])};$.cookie('qtoken',j,{path:'/'});

稍微整理一下得到一个格式清晰的代码

var balwi = [115, 116, 115, 122, 112, 115, 110, 106, 122, 110, 122, 112, 101, 119, 115, 106, 113, 101, 116, 116, 119, 106];
var ljpry = [15, 21, 4, 9, 12, 14, 11, 0, 18, 20, 8, 16, 7, 2, 1, 10, 17, 13, 19, 6, 5, 3];
var j = "";
for (k = 0; k < ljpry.length; k++) {
 j += String.fromCharCode(balwi[ljpry[k]])
};
$.cookie('qtoken', j, {
 path: '/'
});

有了原始代码就很容易得到令牌的生成算法,使用Python生成,这回不用麻烦 PyV8 大神出马了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
Python实现Linux下守护进程的编写方法
Aug 22 Python
轻松实现python搭建微信公众平台
Feb 16 Python
Python基于pillow判断图片完整性的方法
Sep 18 Python
Python通过future处理并发问题
Oct 17 Python
python自动化报告的输出用例详解
May 30 Python
Python中logging.NullHandler 的使用教程
Nov 29 Python
python实现植物大战僵尸游戏实例代码
Jun 10 Python
Django Aggregation聚合使用方法解析
Aug 01 Python
python中seaborn包常用图形使用详解
Nov 25 Python
pandas-resample按时间聚合实例
Dec 27 Python
用pytorch的nn.Module构造简单全链接层实例
Jan 14 Python
python函数的两种嵌套方法使用
Apr 02 Python
Python错误提示:[Errno 24] Too many open files的分析与解决
Feb 16 #Python
Python变量和数据类型详解
Feb 15 #Python
Django学习笔记之Class-Based-View
Feb 15 #Python
关于Python面向对象编程的知识点总结
Feb 14 #Python
Django日志模块logging的配置详解
Feb 14 #Python
深入理解Python对Json的解析
Feb 14 #Python
Python 2与Python 3版本和编码的对比
Feb 14 #Python
You might like
PHP正则表达式之定界符和原子介绍
2012/10/05 PHP
解析PHP的Yii框架中cookie和session功能的相关操作
2016/03/17 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
PHP生成及获取JSON文件的方法
2016/08/23 PHP
js 判断浏览器类型 去全角、半角空格 自动关闭当前窗口
2009/04/10 Javascript
jQuery帮助之CSS尺寸(五)outerHeight、outerWidth
2009/11/14 Javascript
jQuery+css3动画属性制作猎豹浏览器宽屏banner焦点图
2015/03/16 Javascript
JavaScript弹出新窗口后向父窗口输出内容的方法
2015/04/06 Javascript
jQuery判断指定id的对象是否存在的方法
2015/05/22 Javascript
javascript图片滑动效果实现
2021/01/28 Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
2015/11/30 Javascript
jQuery弹出窗口打开链接的实现代码
2016/12/24 Javascript
Vue应用部署到服务器的正确方式
2017/07/15 Javascript
ES6学习教程之Map的常用方法总结
2017/08/03 Javascript
Vue常用的几个指令附完整案例
2018/11/06 Javascript
JavaScript 替换所有匹配内容及正则替换方法
2020/02/12 Javascript
Python守护进程(daemon)代码实例
2015/03/06 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
Python3匿名函数用法示例
2018/07/25 Python
Python使用pandas对数据进行差分运算的方法
2018/12/22 Python
如何在Cloud Studio上执行Python代码?
2019/08/09 Python
python opencv 实现读取、显示、写入图像的方法
2020/06/08 Python
XD健身器材:Kevlar球、Crossfit健身球
2019/03/26 全球购物
LN-CC日本:高端男装和女装的奢侈时尚目的地
2019/09/01 全球购物
18岁生日感言
2014/01/12 职场文书
大学生求职自我评价
2014/01/16 职场文书
应聘医药销售自荐书范文
2014/02/08 职场文书
期终自我鉴定
2014/02/17 职场文书
2014全国两会学习心得体会1000字
2014/03/10 职场文书
2014两会学习心得:时代的发展
2014/03/17 职场文书
学校党的群众路线教育实践活动总结报告
2014/07/03 职场文书
无房证明样本
2015/06/17 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
小程序后台PHP版本部署运行 LNMP+WNMP
2021/04/01 Servers
CSS3鼠标悬浮过渡缩放效果
2021/04/17 HTML / CSS
DjangoRestFramework 使用 simpleJWT 登陆认证完整记录
2021/06/22 Python