爬蟲必備:Python 執行 JS 程式碼 —— PyExecJS、PyV8、Js2Py

戴德滿發表於2019-03-18

在使用爬蟲中,經常會遇到網頁請求資料是經過 JS 處理的,特別是模擬登入時可能有加密請求。而目前絕大部分前端 JS 程式碼都是經過混淆的,可讀性極低,想理解程式碼邏輯需要花費大量時間。這時不要著急使用 Selenium 暴力解決,畢竟 Selenium 嚴重拖慢爬蟲效率,我們可以嘗試使用一些第三方庫,來直接執行前端 JS 程式碼得到處理過後的結果。

PyExecJS

這個庫主要是將 JS 程式碼執行在本地的 JS 環境中,優點是我們有多種 JS 環境的選擇,官方推薦了 PyV8、Node.js、PhantomJS、Nashorn 四種,當然缺點是必須安裝一種環境導致不是很輕量,而且呼叫時有一個啟動環境過程,還是有明顯緩慢的。

安裝方式

先解決 JS 環境,這裡推薦安裝 Node.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,需要在這裡下載對應系統的二進位制檔案:github.com/emmetio/pyv… 然後解壓後將 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 scope
var = Scope( JS_BUILTINS )
set_global_object(var)

# Code follows:
var.registers(['x'])
var.put('x', Js(1.0))
複製程式碼

實戰技巧

當選擇完合適的庫後,如果你還不明白在瀏覽器裡進行 Debug 的方法,那需要去搜尋關鍵詞先學習一下。 接下來就是定位目標網頁需要呼叫的 JS 函式,這裡實在無法詳述,因為每個網站的寫法都大不相同。 不過只要你通過 Debug ,檢視資料從請求開始,每一步都經過了哪些 JS 函式,又輸出成什麼樣的資料,就可以順藤摸瓜找到一些可疑的函式,然後將這些方法逐一複製出來,通過上面的庫傳入引數執行,看是否和目標網頁處理後的資料一致,就可以找到目標函式。


最後,關注我的微信公眾號:面向人生程式設計

爬蟲必備:Python 執行 JS 程式碼 —— PyExecJS、PyV8、Js2Py
無論什麼樣的程式設計思想,都不該只存留在程式碼之中,更應伴隨於整個人生旅途,這個公眾號不只聊技術,還會聊產品/網際網路/經濟學等廣泛話題,所以也歡迎非程式設計師關注。

相關文章