使用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+树莓派+YOLO打造一款人工智能照相机
Jan 02 Python
利用Python半自动化生成Nessus报告的方法
Mar 19 Python
如何使用django的MTV开发模式返回一个网页
Jul 22 Python
基于python实现的百度新歌榜、热歌榜下载器(附代码)
Aug 05 Python
Python (Win)readline和tab补全的安装方法
Aug 27 Python
Python常用编译器原理及特点解析
Mar 23 Python
opencv 图像腐蚀和图像膨胀的实现
Jul 07 Python
Python爬取豆瓣数据实现过程解析
Oct 27 Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
Oct 29 Python
python中remove函数的踩坑记录
Jan 04 Python
Python3中对json格式数据的分析处理
Jan 28 Python
python基于tkinter制作下班倒计时工具
Apr 28 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仿博客园 个人博客(1) 数据库与界面设计
2013/07/05 PHP
thinkphp模板输出技巧汇总
2014/11/24 PHP
jquery last-child 列表最后一项的样式
2010/01/22 Javascript
js原生态函数中使用jQuery中的 $(this)无效的解决方法
2011/05/25 Javascript
JavaScript 基础篇之运算符、语句(二)
2012/04/07 Javascript
网页打开自动最大化的js代码
2012/08/22 Javascript
jquery中的常用事件bind、hover、toggle等示例介绍
2014/07/21 Javascript
Node.js实现JS文件合并小工具
2016/02/02 Javascript
js 动态添加元素(div、li、img等)及设置属性的方法
2016/07/19 Javascript
详解如何实现一个简单的Node.js脚手架
2017/12/04 Javascript
vue.js 嵌套循环、if判断、动态删除的实例
2018/03/07 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
2018/06/28 Javascript
js实现动态增加文件域表单功能
2018/10/22 Javascript
vue鼠标悬停事件实例详解
2019/04/01 Javascript
[02:55]2018DOTA2国际邀请赛勇士令状不朽珍藏Ⅲ饰品一览
2018/08/01 DOTA
[01:14:41]DOTA2-DPC中国联赛定级赛 iG vs Magma BO3第一场 1月8日
2021/03/11 DOTA
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
Python内置模块ConfigParser实现配置读写功能的方法
2018/02/12 Python
使用Eclipse如何开发python脚本
2018/04/11 Python
Python实现的凯撒密码算法示例
2018/04/12 Python
Python 最大概率法进行汉语切分的方法
2018/12/14 Python
Python高级特性之闭包与装饰器实例详解
2019/11/19 Python
python中property和setter装饰器用法
2019/12/19 Python
python中count函数简单用法
2020/01/05 Python
使用 Python 处理3万多条数据只要几秒钟
2020/01/19 Python
python GUI库图形界面开发之PyQt5动态(可拖动控件大小)布局控件QSplitter详细使用方法与实例
2020/03/06 Python
深入了解Python 方法之类方法 &amp; 静态方法
2020/08/17 Python
以太网Ethernet IEEE802.3
2013/08/05 面试题
函授毕业自我鉴定
2014/02/04 职场文书
《桂林山水》教学反思
2014/02/08 职场文书
2014年团员学习十八大思想汇报
2014/09/13 职场文书
处级干部考察材料
2014/12/24 职场文书
寻找成龙观后感
2015/06/12 职场文书
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书
详解CSS伪元素的妙用单标签之美
2021/05/25 HTML / CSS
Mysql关于数据库是否应该使用外键约束详解说明
2021/10/24 MySQL