一、获得接口 url

  1. 打开百度翻译:百度翻译
  2. 右键检查 或者 F12 打开控制台、点击网络这一项:
  3. 输入文字:哈哈,点击图中的过滤按钮,选择全部

    可以看到,v2transapi?from=zh&to=jp 请求的预览中就是我们需要的响应数据:
  4. 同时看到 headers 中有我们的 Cookie 字段:

二、查看POST表单格式

因为是POST请求,点击载荷看到我们的表单格式:

三、python 访问百度翻译 v2transapi 接口初试

将之前获得的 cookie、token 填入:

import json
import urllib.request
import urllib.parse# 第一步中咱们知道接口是这个 url
url = 'https://fanyi.baidu.com/v2transapi?from=zh&to=jp'
# headers 必须带 Cookie,百度翻译的反扒手段之一
headers = {'Cookie': 你的 cookie
}
# 要翻译的单词
query = '哈哈'
# 表单数据,将第二步中的kv全部复制过来
data = {'from': 'zh','to': 'jp','query': query,'simple_means_flag': '3','sign': ‘404035.182642’,'token': 你的 token,'domain': 'common'
}
# 封装 request 对象
data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url=url, data=data, headers=headers)
# 调用 urlopen,获得返回值
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# 用 json 可以解码返回值中的 Unicode 字符
print(json.loads(content))

运行结果:

看起来成功了!换个单词翻译试试:将 query 改为 啦啦啦 再运行:

居然是未知错误,观察我们的表单数据发现有个特殊字段:'sign': ‘404035.182642’,所以我们需要知道这个 sign 字段是如何生成的

四、探究原因

重新查看我们控制台中的接口:

启动器中可以看到所有的调用栈,点击第一个不是 jquery 的 js:@ translate.js:181

可以发现该方法正是我们的 $.ajax 方法,我们得知 data 的变量名为 paramData,在该文件内摁 ctrl+f 搜索这个变量:

发现 sign 是调用了 pGrab( qeury ) 方法:这个 qeury 正是我们的待翻译文字。我们 ctrl+f 搜索 pGrab 发现是导入别的 js 文件中的方法:

全局搜索该文件:点击控制台左边这三个点 - 打开文件,或者 ctrl+p。


翻到文件末尾看到导出的方法是 tl,所以实质 sign = tl( query ),右键该文件点击另存为,将 pGrab.js 文件放入我们的项目路径。

五、python 访问百度翻译 v2transapi 接口再试

现在的思路就是需要在 python 中调用该 js 中的 tl( query ) 方法生成我们的 sign,此时我们需要导入 execjs 模块(需要 nodejs 环境:本人版本 v14.0.0)

  1. 安装

    pip install PyExecJS
    
  2. 导入:

    import execjs
    
  3. 使用:

    query = '哈哈'
    with open('pGrab.js', mode='r', encoding='utf-8') as f:sign = execjs.compile(f.read()).call("tl", query)
    print(sign)
    
  4. 运行

    提示 window 未定义,在 pGrab.js 中搜索发现只有一处使用了该变量:

    现在的目标就变成了如何知道这个 window “长什么样”

  5. 此时我们可以利用浏览器的调试功能,直接定位到这行代码查看 window 变量!
    在图示这行打上断点:

    然后在翻译框随便输入,js 会暂停在断点这行。鼠标指上 window 变量,在里面寻找 key = gtk

    因为我们通过搜索 pGrab.js 知道只用了 window 中的这一个 kv,所以我们在项目中的 pGrap.js 文件首行添加

    window = { 'gtk': '320305.131321201' }
    
  6. 重新运行我们第3步的代码:

    对比我们之前的 query = '哈哈' 对应的 sign 值是同一个值:

    问题全部解决了,上代码最终版!

六、代码最终版

import json
import urllib.request
import urllib.parse
import execjs# 第一步中咱们知道接口是这个 url
url = 'https://fanyi.baidu.com/v2transapi?from=zh&to=jp'
# headers 必须带 Cookie,百度翻译的反扒手段之一
headers = {'Cookie': 你的 cookie
}
# 要翻译的单词
query = '哈哈'
# 生成 sign
with open('pGrab.js', mode='r', encoding='utf-8') as f:sign = execjs.compile(f.read()).call("tl", query)
print(sign)
# 表单数据,将第二步中的kv全部复制过来
data = {'from': 'zh','to': 'jp','query': query,'simple_means_flag': '3','sign': sign,'token': 你的 token,'domain': 'common'
}
# 封装 request 对象
data = urllib.parse.urlencode(data).encode('utf-8')
request = urllib.request.Request(url=url, data=data, headers=headers)
# 调用 urlopen,获得返回值
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# 用 json 可以解码返回值中的 Unicode 字符
print(json.loads(content))

运行结果:

pGrab.js

window = {'gtk': '320305.131321201'};function rl(num, rule) {for (let i = 0; i < rule.length - 2; i += 3) {let d = rule.charAt(i + 2);d = 'a' <= d ? d.charCodeAt(0) - 87 : Number(d);d = '+' === rule.charAt(i + 1) ? num >>> d : num << d;num = '+' === rule.charAt(i) ? num + d & 4294967295 : num ^ d;}return num;
}let gtk = null;function tl(query) {// 非 BMP 的 unicode 在 js 会以高低位保存在,导致 string.length 返回是 2,与后端不一致// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAtlet noBMPChar = query.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);if (noBMPChar === null) {let qLen = query.length;if (qLen > 30) {query = `${query.substr(0, 10)}${query.substr(Math.floor(qLen / 2) - 5, 10)}${query.substr(-10, 10)}`;}} else {let bmpPart = query.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/);let i = 0;let len = bmpPart.length;let qArray = [];for (; i < len; i++) {if (bmpPart[i] !== '') {qArray.push(...bmpPart[i].split(''));}if (i !== len - 1) {qArray.push(noBMPChar[i]);}}let qLen = qArray.length;// query 截取if (qLen > 30) {// query = `${query.substr(0, 10)}${query.substr(Math.floor(qLen / 2) - 5, 10)}${query.substr(-10, 10)}`;query = qArray.slice(0, 10).join('')+ qArray.slice(Math.floor(qLen / 2) - 5, Math.floor(qLen / 2) + 5).join('')+ qArray.slice(-10).join('');}}let tk;// key - gtklet key = `${String.fromCharCode(103)}${String.fromCharCode(116)}${String.fromCharCode(107)}`;if (gtk !== null) {tk = gtk;} else {tk = (gtk = window[key] || '') || '';}let tkArr = tk.split('.');let tk0 = Number(tkArr[0]) || 0;let tk1 = Number(tkArr[1]) || 0;let e = [];for (let f = 0, g = 0; g < query.length; g++) {let ucode = query.charCodeAt(g);// 将 unicode 对应 utf8 各字节存入 array eif (ucode < 128) {// utf 编码为变字节,参考 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html// 单字节 操作e[f++] = ucode;} else {if (ucode < 2048) {// 双字节 操作e[f++] = ucode >> 6 | 192;} else {// charCodeAt 总是返回一个小于 65,536 的值。// 这是因为高位编码单元(higher code point)使用一对(低位编码(lower valued))代理伪字符("surrogate" pseudo-characters)来表示,从而构成一个真正的字符。// 因此,为了查看或复制(reproduce)65536 及以上编码字符的完整字符,需要在获取 charCodeAt(i) 的值的同时获取 charCodeAt(i+1) 的值// 貌似是因为一个 char 两个字节(16位),支持 unicode \u0000 - \uffffif (55296 === (ucode & 64512)&& g + 1 < query.length&& 56320 === (query.charCodeAt(g + 1) & 64512)) {// 四字节 操作ucode = 65536 + ((ucode & 1023) << 10) + (query.charCodeAt(++g) & 1023);e[f++] = ucode >> 18 | 240;e[f++] = ucode >> 12 & 63 | 128;} else {// 三字节 操作e[f++] = ucode >> 12 | 224;}e[f++] = ucode >> 6 & 63 | 128;}// 末字节e[f++] = ucode & 63 | 128;}}let rlt = tk0;// let rule1 = '+-a^+6';let rule1 = `${String.fromCharCode(43)}${String.fromCharCode(45)}${String.fromCharCode(97)}`+ `${String.fromCharCode(94)}${String.fromCharCode(43)}${String.fromCharCode(54)}`;// let rule2 = '+-3^+b+-f'let rule2 = `${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)}`;for (let i = 0; i < e.length; i++) {rlt += e[i];// +-a^+6rlt = rl(rlt, rule1);}rlt = rl(rlt, rule2);rlt ^= tk1;rlt < 0 && (rlt = (rlt & 2147483647) + 2147483648);rlt %= 1E6;return `${rlt.toString()}.${rlt ^ tk0}`;
}

七、补充

scrapy 访问百度翻译 v2transapi 接口

settings.py 中注释掉:

# ROBOTSTXT_OBEY = True

新建 spider:

import scrapy
import execjsclass BaiduFanyiSpider(scrapy.Spider):name = 'baidu_fanyi'allowed_domains = ['fanyi.baidu.com']# 必须注释# start_urls = ['https://fanyi.baidu.com/v2transapi']# 必须改名def parse_second(self, response):print(response.json())passdef start_requests(self):url = 'https://fanyi.baidu.com/v2transapi?from=zh&to=jp'query = '哈哈'with open('pGrab.js', mode='r', encoding='utf-8') as f:sign = execjs.compile(f.read()).call("tl", query)# print(sign)headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',}cookies = {将 cookies 按分号拆开,等号改写成 kv 形式,例如:'BIDUPSID': xxx,...}data = {'from': 'zh','to': 'jp','query': query,'simple_means_flag': '3','sign': sign,'token': 你的token,'domain': 'common'}yield scrapy.FormRequest(url=url, headers=headers, formdata=data, cookies=cookies, callback=self.parse_second)

运行结果:

完结撒花

用 python 调用百度翻译 v2transapi 接口相关推荐

  1. 【2019-07-23】]python3 把日语翻译为中文 调用百度翻译API接口及API申请使用教程

    点击申请百度翻译API,得到一个你自己的API账户. 点击查看申请教程,感谢教程原作者. API官网提供了一个python2的使用接口的demo还有详细的解释文档 想用python3完成,代码几乎照搬 ...

  2. python调用百度翻译-Python 调用百度翻译API

    由于实习公司这边做的是日文app,有时要看看用户反馈,对于我这种五十音图都没记住的人,表示百度翻译确实还可以.但不想每次都复制粘贴啊,google被墙也是挺蛋疼的事,所以用python结合baidu ...

  3. python百度翻译api申请网页版_python3调用百度翻译api接口实现全过程

    现在很都平台的翻译api接口都开始收费了,比如谷歌.微软.yandex等等,注册非常麻烦,而且要钱,目前就百度还剩下一个最基础的翻译api不需要钱,今天我要和大家分享的是怎样使用python3调用百度 ...

  4. python调用百度翻译、谷歌翻译

    谷歌翻译不提供接口,想要使用谷歌的翻译结果,需要借用爬虫技术,将待翻译的文本传入,抓取页面,解析出翻译结果,经测试,这种方法的翻译效果较差,不建议使用. 百度翻译提供接口,可在百度翻译注册开发者后获取 ...

  5. 使用Python调用baidu翻译的接口,实现转换android stuido 中的values/strings.xml 解放生产力,自动翻译生成文件

    调用baidu翻译的接口,实现转换android stuido 中的values/strings.xml 解放生产力,自动翻译生成文件 因为使用的是合法免费的接口,每秒只能请求一次,测试结果翻译330 ...

  6. python调用百度翻译-python3调用百度翻译API实时翻译的实例代码

    python3调用百度翻译API实现实时翻译 今天需要做一个翻译的工具,找到之前写过的有道翻译,已经不能用了,最后看到百度翻译还不错,不过官方版本是Python2,我需要Python3,就自己写了一个 ...

  7. 前端js调用百度翻译api接口

    目录 1.到百度翻译开放平台注册自己的账号 2.编辑html代码,设计一个简易的页面 3.远程调用百度翻译api 4.完整代码 5.测试 到百度翻译开放平台注册自己的账号 (1)进入网页:开放平台官网 ...

  8. Python 调用百度翻译接口实现翻译

    小编分别写过有道,百度的翻译Demo,个人感觉有这么几个区别: 代码量:百度更简洁,有道太冗余: 是否收费:有道翻译免费,百度翻译超过一定量是要收费的,所以要验证key: 规范性:相比有道翻译,百度翻 ...

  9. python调用百度翻译api+离线语种检测

    百度翻译api调用(具体参考的哪篇博文找不到了,好几篇太像了,原作者留意到可以告知我改转载附上链接): import urllib, hashlib import random import requ ...

最新文章

  1. (2)Spark下载与入门
  2. js下拉 selenium_selenium 常见面试题以及答案(Java版)
  3. ABAP里几种整型数据类型的范围和转换
  4. 为什么私有GIT服务器上无法查看上传的代码?
  5. 花旗银行文章解释DeFi的好处
  6. CVPR(IEEE Conference on Computer Vision and Pattern Recognition)
  7. 蓝桥杯 ADV-189 算法提高 连接乘积
  8. 张广慧:云计算对游戏开发者的价值
  9. java私聊_【转帖】实现了视频私聊功能
  10. DirectFB简介以及移植[一]【转】
  11. 台达伺服电机编码器改功率刷功率软件
  12. oppok3如何刷机_OPPO K3(6GB/64GB/全网通)手机密码忘记怎么刷机?
  13. 基于IM实现直播礼物效果
  14. python海龟画笔速度_【判断题】Python海龟绘图中,设置画笔绘制速度的函数是speed()。...
  15. 微信营销与博客营销的区别
  16. 练习HTML——简单的网页设计
  17. 电力行业三次谐波计算
  18. 2022年,我不允许任何人还没有免费图床系统
  19. python libusb_python, libusb, pyusb
  20. 设计模式(一)——六大原则

热门文章

  1. TypeError: (intermediate value) is not iterable
  2. MySQL Connector/J 8.0
  3. 推荐的10本python豆瓣高分书单,小白到大佬!
  4. Jquery 根据 字符串首字符(string)生成Base64头像
  5. 不删档魔法正版服务器,全新3D魔幻ARPG《魔法天堂》不删档内测今日开启!
  6. Java取得:月初,月末
  7. RevitBIM数据库V6.0版插件--企业专属
  8. warning: enumeration value ‘FEA_INT‘ not handled in switch
  9. Excel搭建RFM模型
  10. django 进阶-- 模型