百度翻译网页接口破解

定位

打开百度翻译网站, 随便输入单词, 通过观察接口调用及返回, 很容易就能定位到目标接口.

定位百度翻译接口

查看该接口调用参数, from, to, query 三个参数的含义比较明显, 分别是 翻译源语言, 翻译目标语言, 待翻译文本, 破解的关键应该在于 sign, token 两个参数.

翻译接口参数

查看Initator, 可以看到调用集中在 index, public 两个文件. 比较安心的是函数名未作混淆, 直接跳转至 doTrans 函数. 一番调试后发现该函数离接口调用还是有点远的. 既然接口参数名比较长且有含义, 接口调用也被限制在两个文件内, 那就直接 ctrl+f 大法吧.

搜索关键字 token, 很快就能在 index 文件中定位至参数构造处.

接口调用栈
参数构造处

token参数破解

token参数从全局变量 window 中取出, 想用正常方法定位其被设置的位置可谓困难之至, 不过有了 Chrome Devtools Protocol, 想调试全局变量就简单了.

通过运行下面的代码便能获取到一个能调试 window.common 的浏览器, 在 window.common 被赋值时会进入断点.

from selenium import webdriver


# 初始化浏览器
options = webdriver.ChromeOptions()
options.add_experimental_option(
    "excludeSwitches",
    ["enable-automation"]
)
driver = webdriver.Chrome(
    executable_path="your driver path",
    options=options
)

# 更改window.common
token_locator = """
    Object.defineProperty(window, "common", {
        set: (value) => {console.log(value);debugger;}
    })
"""
driver.execute_cdp_cmd(
    "Page.addScriptToEvaluateOnNewDocument",
    {
        "source": token_locator
    }
)

# 让浏览器不因为python进程退出而消失
input("don't go")

打开上述浏览器的控制台, 打开百度翻译网站, 顺利进入断点. 回溯调用栈可以轻松定位出 window.common 被设置的地方, 百度很阴地把它放在了html文件中, 这要是按照常理在一堆js文件中寻找是不可能找到的.

window.common设置处

不过等等, 这里 token 是个空字符串, 明显不对劲. 从断点处继续运行, 发现控制台报错, 获取 window.common 出错, 这是当然的, 因为之前cdp代码中只定义了其 get 方法.

当然, 可以在cdp代码中补全 window.commonget 方法, 并用同样的方法魔改 window.common.token, 定位至其被修改的位置. 不过稍微细心点, 在html文件之后不远处就能发现其中玄机.

cookie检测

从这段贴心的注释可进行合理推测: 第一次进入页面没有cookie, 导致 token 为空字符串, 这时会刷新页面, 有了第一次请求的cookie, 就能够正常获取 token 了.

用一段代码验证下, 发现不带 User-Agent 请求会被拒, 看来百度还是会检测这玩意的.

import httpx


UA= (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
    + "(KHTML, like Gecko) Chrome/90.0.4430.95 Safari/537.36"
)

client = httpx.Client(headers={"User-Agent": UA})
url = "https://fanyi.baidu.com"

with open("first.html", "wb") as f:
    f.write(client.get(url).content)

with open("second.html", "wb") as f:
    f.write(client.get(url).content)
token依赖于cookie

果不其然, 带上cookie的第二次请求就能正常获取到 token 了, 至此 token 参数破解完成.

sign参数破解

从之前找到的接口请求参数构造处可定位至 sign 参数构造处. sign 参数构造比较简单, 只涉及两个函数, 也没有什么技巧, 可以读懂js的逻辑后用python仿写, 也可也复制js代码后用相关python库运行. 后者可能还得配置node, 更为麻烦, 实用性也要打折扣.

sign 参数构造过程中用到了 window.gtk 这一变量, 当然可以通过cdp的方式调试, 但其实之前的html代码中该变量已经出现过了.

sign参数构造

完整代码

待补充…