抓包工具、PyExeJs模块
在处理一些网站的时候,会遇到一些屏蔽F12,以及只要按出浏览器的开发者工具,就会关闭甚至死机的现象
在遇到这类网站的时候,可以使用抓包工具,把页面上屏蔽开发者工具的代码给干掉
一. Fiddler和Charles
这两款工具是非常优秀的抓包工具。它们可以监听到计算机上所有的http网络请求。利用这种特性,可以获取到页面加载过程中的所有内容
1.1 fiddler简单配置(HTTPS)
接下来,打开www.vmgirls.com,尝试抓包看看,发现https的请求默认是不可用的,需要配置一下证书。
1.2 fiddler简单使用
清理一下信息,然后重新刷新浏览器, 就看到被响应的html内容了
vmgirl之所以不可以打开开发者工具,是因为在其html中,导入了一个disable-devtools.js。
需要想办法把这个东西给干掉,只要干掉了它,就又可以打开F12的开发者工具了
那么如何干掉它呢? 这就需要了解一下fiddler和charles的工作原理了.
fiddler和charles本质,其实就是一个安装在这台计算机上的一个代理,就像这样:
本质上和代理没啥区别,但是, 由于fiddler是自己本地的软件,那么可以在fiddler里对请求过来的内容,进行截取和替换
做这样一个事情,把vmgirls的页面源代码捕获,单独写入一个html文件,然后把其中的disable-devtools.js部分注释掉.
现在这个页面源代码在本地了,就可以进行替换了....
接下来. 重新刷新页面(ctrl+shift+r) , 发现右键有效果了.
1.3 charles安装和使用
charles官网: https://www.charlesproxy.com/download/
charles激活: https://www.zzzmode.com/mytools/charles/
注意:
在windows环境下,如果出现证书不可用的情况,需要手工去windows的证书管理器中,
把Charles的证书拖拽到可信任证书那一栏,然后重启浏览器和charles就可以用了
如果证书默认就可用. 就不要胡乱拖拽
window证书管理器: win+r: 输入certlm.msc
Mac
如果想要实现请求拦截,怎么办?
二. PyExecJS模块
pyexecjs是一个可以运行js代码的一个第三方模块,其使用是非常容易上手的
但是它的运行是要依赖能运行js的第三方环境的,这里选择用node作为运行js的位置.
2.1 安装Nodejs
一路下一步,修改安转位置,最后控制台输入:node -v
npm -v
即可
2.2 安装pyexecjs
pip install pyexecjs
测试一下:
import execjsprint(execjs.get().name) # Node.js (V8)
2.3 简单使用
import execjsprint(execjs.get().name)# execjs.eval 可以直接运行js代码并得到结果
js = """"鲁班_王昭君_猴子_亚瑟_蔡文姬".split("_")
"""
res = execjs.eval(js)
print(res)# execjs.compile() 与 call()
# execjs.compile():事先加载好一段js代码
jj = execjs.compile("""function an(a, b){return a + b }
""")# call():运行代码中的xxx函数. 后续的参数是xxx的参数
ret = jj.call("an", 10, 20)
print(ret)
windows中如果出现编码错误. 在引入execjs之前. 插入以下代码即可.
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')import execjs
完事儿,execjs就这几个功能就够咱使用
2.4 实战案例(调试工具)
接下来,来破解真正的百度翻译
通过抓包可以发现:之前抓取的百度翻译,其实是个伪翻译
真正的一句话的翻译,其实它的url应该是:https://fanyi.baidu.com/v2transapi?from=en&to=zh
接下来就是分析这一坨
y = {from: d.fromLang, // 从xxxxto: d.toLang, // 翻译成xxxxquery: e, // 被翻译的内容transtype: r, // 固定的翻译类型simple_means_flag: 3, // 常量sign: L(e), // ????token: window.common.token, // token. 这个在页面源代码里能找到domain: R.getCurDomain() // 固定值.
};
现在有3个值,无法直接确定。一个是L(e)。 一个是token。另一个是R.getCurDomain()
先看 token
由于在进行翻译的时候,页面是没有刷新的,所以这个token一般在进行翻译的时候,是不会改变的
再看 domain
在页面中设置一个断点,并重新发送请求
点进去返回的是个M. 找M
OK, M是常量,"common"
最后看 L(e)
首先e是被翻译的内容,所以这里是把"要翻译的内容"传递给了L.。但是这个L在哪里,不好找。很简单,设置一个断点,就可以
程序停在这里了,接下来就是这三个按钮,从左到右:
第一个: 释放掉当前debug,程序继续向后运行,直到结束或下一个断点
第二个: 运行下一步,相当于一行代码。
咱们这里,是在一个{}中间进行的断点。而整个{}; 被认为是一行代码,所以下面的 token等会被过掉
第三个: 运行到当前行内部。
咱们这里,就是运行到L(e)里面,看看L(e)里面是干什么的
这里就是那个L(e)了,但这东西属实看不明白,也不容易看明白。里面是一个签名算法,十分难搞
仔细观察下,发现该函数内部只调用了n() a()函数。其他函数都是js内置的东西。OK 向上简单寻找就发现了,这里是一个大闭包
也就是说整个签名的计算,就这些功能。没有调用外界的其他功能。那就好办了。可以直接把这个闭包内的三个函数搞出来,变成我们的js文件
尝试着签个名试试看:
import requests
import execjsf = open("bbd.js", mode="r", encoding='utf-8')
js = execjs.compile(f.read())# execjs._exceptions.ProgramError: ReferenceError: window is not defined.
ret = js.call('e', 'love')
print(ret)
报错了,说这里面没有window
确实,由于我们的js是在node里面运行的,node是没有window对象的. 怎么办?
整合起来这里要用到window['gtk'],这玩意哪里找? 老实说,真不好找。在前面找token的时候,偶然间,发现了这样一段代码:
OK了 . 搞定... 只要把js里面的window['gtk'],修改成这个就好了
至此, 所有参数到位. 写代码就好了.
代码:
import requests
import execjsf = open("baidu加密.js", mode="r", encoding='utf-8')
js = execjs.compile(f.read())url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh"
content = input("请输入一段英文:")
data = {"from": "en","to": "zh","query": content,"transtype": "realtime","simple_means_flag": "3","sign": js.call("e", content),"token": "c63d27ea65fdf259bf4d56b792e47b17","domain": "common",
}
headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8","Referer": "https://fanyi.baidu.com/","Cookie": "REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BIDUPSID=7214BF57BA799CC46A76979BF673523E; PSTM=1623064780; __yjs_duid=1_7946e25e70873bbe5515a663714cef991623067825398; BAIDUID=C434B9AC411BEFD0688E2DD206C8429A:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; MCITY=-131%3A; BDUSS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; BDUSS_BFESS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; H_PS_PSSID=34438_34440_34380_34496_33848_34450_34092_34107_26350_34425_22160; delPer=0; PSINO=2; BA_HECTOR=a08k202181a52h208d1gj6e0m0q; BAIDUID_BFESS=DDAD1DC127ED72714BFB37825559ACDB:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1628330239,1628390196,1629451250,1630747372; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1630747372; ab_sr=1.0.1_ODBhYjIwYzRhMjk4NDNhZDYwYjRmZWZjM2QwY2E3MGNlMDRjYTI1ZjViODM2MDgxODk5NzJjNDFkZTAxYzc0OTVkYmNhYjZiMWMzZDFmNWFkN2QxMzAwMzZlZjhjYmE3ODkxZGRkNDJkNTY2N2M0NTQxODU5YmU4YTA1NGZjYTJkMDUzN2ZkMGVkMzlmOTU1M2ZlZTRhYWY4ZDQ5YTZmNTJjYmExYzk1ZTdiY2I5MTA4YjcyZDE3MWE1MTE5YjBj","User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
}resp = requests.post(url, data=data, headers=headers)
print(resp.json())