如何用浏览器调试js代码,不如先看看如何爬取百度翻译(多图警告)

tech2024-11-08  18

爬取百度翻译

爬取网站四部曲分析langdetectv2transapi?from=zh&to=en 分析重点请求出现的问题解决问题js代码调试 代码实现 注意

爬取网站四部曲

分析

当我们进入百度翻译的官网时

先打开控制台 因为我们还没使用输入任何东西,所以这二个可能请求可能对我们没有多大帮助,不过读者可自行看看,这里主要是为了查看当我们输入后会有什么变化

当我们输入内容后,可以发现页面没有跳转但是url发送了变化,请求多了三个,这里可以说明在翻译过程中,实现的是ajax,因为ajax可以实现页面局部刷新而不是整个页面刷新 接下来我们看看新出现的请求头的信息

langdetect

这里有我们输入的内容,那我们可以当做重点看待,那我们看其response的结果是什么,是不是我们想要的结果 ???,貌似没有我们想要的结果,但是返回了一个"lan":“zh”,个人翻译为语言:中文,那我们可以假设一下这个请求可能是来判断我们输入的语言是什么

v2transapi?from=zh&to=en

也有我们输入的内容那可以将其列为我们需要考虑的列表中,那我们进行查看其response的结果是否有我们需要的结果 为什么我这里会选择看Preview,那是因为Response的格式有点看不下去,但是发现Preview中结果和Response的结果一样,所以这里我们就先借鉴一下了,从上面可以看出这个请求明显就是我们所需要的,有问题也有答案,所以这里我们完全可以侧重于这个请求

分析重点请求出现的问题

首先我们先看看我们请求体有哪些给后台 我们从上图可以看到 Get

from (需要转换的语言)to (将要转成的语言) Postfrom (需要转换的语言)to (将要转成的语言)query (用户输入的内容)transtype(翻译方式)simple_means_flag(不知道)sign(不清楚)token(字面上的意思应该是命令牌,肯定和cookie有关联)domain(文本方式)

这里有二个不知道是什么可以我们可以多测试几个来判断有没有固定的字段 这里我们可以看到除了sign发生了变化,其他基本上没有发生变化,所以sign则是我们需要解决的问题

解决问题

首页我们知道整个翻译过程是ajax实现的,所以我们可以进行调试js代码来判断sign是如何生成的

js代码调试

然后正常的输入我们要翻译的内容 很多人可能会出现和我上面这个情况一样,js代码基本上全部在一起,很难看不好分析 nice!!!,然后 边看左边也要注意右边的值的变化,搞好就有我们需要的东西出现 很明显这里的h变量有我们需要的东西,那说明现在这个代码区间可能有我们想要的结果,查看一下代码的上下文 这里我们可以看到sign是又y(n)生成的而且n是我们输入的内容,接下来我们可以去看看y(n)这个函数 停在y(n)这个函数面前,不一会我们就可以看到调用他的是e,点击并跳转 通过分析出,这个函数主要是通过r进行加密并输出,但是还会用上面的n(r,o)和变量i这个函数,所以把加密函数导出来可以得到如下:

var i = "320305.131321201" function n(r, o) { for (var t = 0; t < o.length - 2; t += 3) { var a = o.charAt(t + 2); a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a), a = "+" === o.charAt(t + 1) ? r >>> a : r << a, r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a } return r } function e(r) { var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g); if (null === o) { var t = r.length; t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10)) } else { for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++) "" !== e[C] && f.push.apply(f, a(e[C].split(""))), C !== h - 1 && f.push(o[C]); var g = f.length; g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join("")) } var u = void 0, l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107); u = null !== i ? i : (i = window[l] || "") || ""; for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) { var A = r.charCodeAt(v); 128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)), S[c++] = A >> 18 | 240, S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224, S[c++] = A >> 6 & 63 | 128), S[c++] = 63 & A | 128) } for (var p = m, F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++) p += S[b], p = n(p, F); return p = n(p, D), p ^= s, 0 > p && (p = (2147483647 & p) + 2147483648), p %= 1e6, p.toString() + "." + (p ^ m) }

得到加密函数,我们只要用python中第三方库即可调用js中的函数

pip install Pyexecjs

这个库的基本使用如下

#加载js文件 with open("baidujs.js","r") as fp: jsData=fp.read() #execjs.compile(jsDate).call(要调用的函数名,传参) sign=execjs.compile(jsData).call("e",self.keyword)

代码实现

import requests import re import execjs import ast class Baidu_Translate(): """ 1.获取当前用户要转化的语言即lan 2.获取身份标识:token和cookie 我们可以通过正则表达式获取token,获取网站的cookie有二种,这里我们可以用其中一种即创建一个session,因为session会自动保存cookie 3.通过python利用第三方库调用js中的函数,从而获取sign 4.通过正则获取语言列表 """ def __init__(self,keyword): #要翻译的内容 self.keyword=keyword #首页链接 home_page_url="https://fanyi.baidu.com/" #设置请求头 self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36', "x-requested-with":"XMLHttpRequest", "origin": "https://fanyi.baidu.com", "referer": "https://fanyi.baidu.com/?aldtype=16047" } #获取cookie self.session=requests.session() self.lan = self.getlan() #获取首页 result=self.session.get(home_page_url).text self.session.headers=self.headers #获取token self.token=re.findall(r"token: '(.*?)'",result)[0] #获取Sign with open("baidujs.js","r") as fp: jsData=fp.read() self.sign=execjs.compile(jsData).call("e",self.keyword) #获取语言列表 self.langList_string = re.findall(r"langList: (.*?)account:", result,re.S)[0] self.langlist=ast.literal_eval(self.langList_string.replace('\n', '').replace(' ', '')[:-1]) #获取lan(当前要转化的语言) def getlan(self): try: lan_url="https://fanyi.baidu.com/langdetect" response_dict =self.session.post(lan_url,data={'query':self.keyword}).json() if not response_dict.get('error'): lan=response_dict["lan"] return lan except Exception as e: print(e) #获取结果 def translate(self): data={ 'from': self.lan, 'to': 'en' if self.lan != 'en' else 'zh', 'query': self.keyword, 'transtype': 'realtime', 'simple_means_flag': 3, 'sign': self.sign, 'token': self.token } try: #百度翻译的链接 url="https://fanyi.baidu.com/v2transapi" result=self.session.post(url,data=data).json() if not result.get("error"): ret = result['trans_result']['data'][0]['dst'] if self.lan != 'en': print(self.langlist[self.lan]+":"+self.keyword+"\t"+self.langlist["en"]+":"+ret) else: print(self.langlist[self.lan] + ":" + self.keyword + "\t" + self.langlist["zh"] + ":" + ret) except Exception as e: print(e) if __name__ == '__main__': trans=Baidu_Translate("こんにちは") trans.translate()

注意

这里必须先获取要转换的语言,在进行翻译,

最新回复(0)