在使用爬虫中,经常会遇到网页请求数据是经过 JS 处理的,特别是模拟登录时可能有加密请求。而目前绝大部分前端 JS 代码都是经过混淆的,可读性极低,想理解代码逻辑需要花费大量时间。这时不要着急使用 Selenium 暴力解决,毕竟 Selenium 严重拖慢爬虫效率,我们可以尝试使用一些第三方库,来直接执行前端 JS 代码得到处理过后的结果。
PyExecJS
这个库主要是将 JS 代码运行在本地的 JS 环境中,优点是我们有多种 JS 环境的选择,官方推荐了 PyV8、Node.js、PhantomJS、Nashorn 四种,当然缺点是必须安装一种环境导致不是很轻量,而且调用时有一个启动环境过程,还是有明显缓慢的。
安装方式
先解决 JS 环境,这里推荐安装 ,安装方便,执行效率也高。
然后pip install PyExecJS
就可以了。 使用例子
>>> import execjs>>> execjs.get().name # 查看调用的环境'Node.js (V8)'>>> ctx = execjs.compile(""" # 执行 JS 语句... function add(x, y) {... return x + y;... }... """)>>> ctx.call("add", 1, 2)3>>> with open('./test.js') as f: # 执行 JS 文件... ctx = execjs.compile(f.read())... ctx.call('add', 1, 2)
PyV8
这是 Google 官方将 Chrome V8 引擎用 Python 封装的库,和 PyExecJS
相比,这个库很轻量,不需要额外装 JS 环境,因为 V8 本身就是环境,同时也因为不需要启动外部环境,执行速度很快。
安装方式
Python3 安装不要使用pip,因为官方只支持 Python2,需要在这里下载对应系统的二进制文件:
然后解压后将 PyV8.py 与 _PyV8.so (如so不是这个名字需要改成这样) 两文件复制到 Python 的 site-packages 目录下,如/usr/local/lib/python3.6/site-packages
。 使用例子
>>> import PyV8 # 注意大小写>>> with PyV8.JSContext() as ctx:... ctx.eval("""... function add(x, y) {... return x + y;... }... """)... ctx.locals.add(1, 2)
Js2Py
最后这个库,作用是将 JS 代码直接转译成 Python 代码,这种方式可以摆脱调用 JS 环境的瓶颈,但遗憾的是如果用于很长的混淆 JS 代码,转译过来的大概率会报错… 所以只建议先尝试一下,如果报错及时更换上面的库。
安装方式
pip install js2py
使用例子
>>> import js2py>>> add = js2py.eval_js("""... function add(x, y) {... return x + y;... }... """)>>> add # 可以看到大括号里已被转译'function add(x, y) { [python code] }'>>> add(1, 2)3>>> # 使用下边这个方法可以输出转译后的代码>>> # 可以保存到文件里,下次不需要再次转译>>> print(js2py.translate_js('var x = 1'))from js2py.pyjs import *# setting scopevar = Scope( JS_BUILTINS )set_global_object(var)# Code follows:var.registers(['x'])var.put('x', Js(1.0))
实战技巧
当选择完合适的库后,如果你还不明白在浏览器里进行 Debug 的方法,那需要去搜索关键词先学习一下。
接下来就是定位目标网页需要调用的 JS 函数,这里实在无法详述,因为每个网站的写法都大不相同。 不过只要你通过 Debug ,查看数据从请求开始,每一步都经过了哪些 JS 函数,又输出成什么样的数据,就可以顺藤摸瓜找到一些可疑的函数,然后将这些方法逐一复制出来,通过上面的库传入参数执行,看是否和目标网页处理后的数据一致,就可以找到目标函数。最后,关注我的微信公众号:面向人生编程
无论什么样的编程思想,都不该只存留在代码之中,更应伴随于整个人生旅途,这个公众号不只聊技术,还会聊产品/互联网/经济学等广泛话题,所以也欢迎非程序员关注。