前言
当你想去破解一个网站的JS加密时,你还是需要考虑,你的JS功底足够好吗?其次是这件事情的价值值不值得去花费大量的时间去破解JS加密?思考好这些问题再决定是否要使用破解JS加密的方式去爬虫,毕竟是破解,这是既花费时间,还看一定运气的事情。三思而后行
JS破解有道词典小案例
查找网站中的JS加密文件是哪一个,查看页面源代码就可以找到了。主要还是破解过程,下面直接上代码:
import requests
import time
import random
import hashlib # 使用md5加密
# 请求头
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0',
'Referer': 'https://fanyi.youdao.com/?keyfrom=dict2.index',
'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; OUTFOX_SEARCH_USER_ID=1523284257@60.12.58.56; JSESSIONID=abcDb6kMwIOwfgCZDgJOx; OUTFOX_SEARCH_USER_ID_NCOO=2124804081.0772424; ___rl__test__cookies=1624086557348'
}
# 请求的翻译服务器网址
url = "https://fanyi.youdao.com/translate_o?smartresult=dict,rule"
"""
--------------------------------------------------JS加密分析----------------------------------------------------
目标参数
i: n, 翻译的单词
from: C,
to: S,
smartresult: "dict",
client: E,
salt: r.salt, str(时间戳) + 0~10的一个随机数
sign: r.sign, md5加密("fanyideskweb" + 翻译的单词 + salt + "Tbh5E8=q6U3EXe+&L[4c@")
lts: r.ts, str(时间戳)
bv: r.bv, md5加密(浏览器的版本号)
doctype: "json",
version: "2.1",
keyfrom: "fanyi.web",
action: e || "FY_BY_DEFAULT"
其中的加密函数
var r = function(e) {
var t = n.md5(navigator.appVersion), navigator.appVersion:浏览器的版本号,是固定的,可以在浏览器的控制台查看
r = "" + (new Date).getTime(), 这就是一个字符串类型的毫秒级时间戳
i = r + parseInt(10 * Math.random(), 10);
return {
ts: r,
bv: t,
salt: i,
sign: n.md5("fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@")
}
};
"""
if __name__ == "__main__":
# 输入需要翻译的字符串
text = input("输入需要翻译的字符串: ")
# ---------------进行参数加密----------------
# 浏览器的版本号
browser_id = "5.0 (X11)"
# 时间戳
lts = str(int(time.time() * 1000))
salt = lts + str(random.randint(0, 10))
sign_str = "fanyideskweb" + text + salt + "Tbh5E8=q6U3EXe+&L[4c@"
# 进行md5加密,得到加密的值
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest()
bv = hashlib.md5(browser_id.encode('utf-8')).hexdigest()
# 翻译的一个表单数据
form = {
"i": text,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": salt,
"sign": sign,
"lts": lts,
"bv": bv,
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME"
}
response = requests.post(url, headers=headers, data=form).json()
print(response['translateResult'][0][0]["tgt"])
如上代码,应该比较简单,注释都有写清楚,下面是运行结果:
运行一:
输入需要翻译的字符串: hello world
你好世界
运行二:
输入需要翻译的字符串: Practice makes perfect
熟能生巧
图形验证码登录V2EX网站案例
登录许多网站的时候,我们都需要填写一个验证码,这其实也是反爬虫手段中的一环。如何解决这一个问题,第一个思路,训练一个机器学习的模型,模型训练的足够好之后,我们就可以用这个模型来识别我们的验证码,从而完成登录。但是,很显然,这样的开销太大了,毕竟我们只是想完成一个登录,另一种办法就是使用第三方的“打码平台”进行识别。这里列举一个第三方的打码平台:斐斐打码。
这里由于V2EX这个网站需要魔法上网才可以进入,这里就不给具体的代码了,只简单记录一下思路。
- 请求头:这里需要两个参数,一个user-agent,一个referer
- 请求表单:在浏览器中找到登录的POST请求中的表单数据,可以发现我们的输入,但是它的关键字是一串没有规律的字符。但查看网页源代码后,可以在源代码中对应的标签内看到这一串key值。
- 步骤:第一步要爬取网页源代码,获取key值;第二步:使用第三方打码平台识别验证码(下载验证码图片时需要带请求头cookie);第三步:发送登录的POST请求。
字体反爬
字体反爬:网页开发者自己创造一种字体,因为在字体中每个文字都有其代号,那么以后的网页不会直接显示这个文字的最终效果,而是显示它的代号。因此即使获取到了网页中的文本内容,也只是获取到了代号,而不是文字本身。
因为创建字体费时费力,如果创建的字体过多,也会影响网页的一个加载速度。一般为了反爬虫,仅会针对0~9以及少数汉字进行单独创建,其它的还是使用用户系统中自带的字体。
- 字体反爬虫的解决办法:
- 一般为了考虑网页的渲染性能,通常开发者会把字体编码成base64的方式,因此我们可以在网页中找到@font-face属性,然后获取里面的base64代码,再用Python解码后保存到本地
- 如果没有使用base64,那么另一种方式是直接把字体文件放到服务器上,然后前端通过@font-face中的url函数进行加载。
- 处理字体反爬中,要分析字体形状和真实字符之间的映射关系,很多时候,网站中对字体的编码方式是不断变化的,因此每次我们需要找到当时请求时编码与字体形状的对应关系,再通过对应关系来映射到真正的字符。更难的字体反爬中,可能每次的字体形状也会是不一样的,可能在坐标上会有轻微的调整,爬取这样的网站时就需要我们对字体中的一些坐标进行判断,如果变化在一定的范围内,那么就可以判定为同一个字符。
这一部分我暂时不知道我是否会有这样的需求,暂时不放例子,具体可以看一下实习僧这个网站。