前情提要
爬过百度翻译的朋友们应该都知道:
百度翻译的 sign 参数破解需要一些逆向能力,已经有很多大神讲了,我就不重复了。破解 sign 后还可能遇到另一个问题:同一个 token 和 cookie 可翻译的次数有限,次数过多时会触发百度的反爬机制。 大规模调用的时候需要更多的 token 和 cookie 。
私信小编01即可获取大量Python学习资料
那么需求来了:我们需要一个 token 和 cookie 池。
发送请求的时候,User-Agent、cookie、token三个值缺一不可。
cookie中最重要的两个值是:BAIDUID、yjs_js_security_passport。
yjs_js_security_passport 的构造机制比较复杂,是由很多函数经过加密处理过的,逆向能力较弱的小伙伴只能缴枪投降。
换个思路,既然 User-Agent 不变,我们可以试试用 selenium 看能不能直接读取到 token 和 cookie。
开启浏览器
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
import requests
import re
#以下三行为无头模式运行,无头模式不开启浏览器,也就是在程序里面运行的
# chrome_options = Options()
# chrome_options.add_argument("--headless")
# browser = webdriver.Chrome(executable_path=(r'C:Program Files (x86)GoogleChromeApplicationchromedriver.exe'), options=chrome_options)
#以下一行为有头模式运行,开启浏览器,在程序外面运行的。
#executable_path请放自己的chromedriver.exe路径
browser = webdriver.Chrome(executable_path=(r'C:Program Files (x86)GoogleChromeApplicationchromedriver.exe'))
url = "https://fanyi.baidu.com"
browser.get(url)
获取token
我们发现token值可以在源代码中直接获取。
因为在<script>标签中,所以我们用正则表达式提取:
#获取token
token = re.findall(r"token: '(.*?)'", browser.page_source)[0]
print('token = ', token)
获取cookie
可以用 browser.get_cookies() 方法获取cookie
#获取cookie
cookie_items = browser.get_cookies()
print(cookie_items)
cookie_items 数据类型如下:cookie名存储在 ‘name’ 中,cookie值存储在 ‘value’ 中。
[
{'domain': '.fanyi.baidu.com', 'expiry': 1625133859, 'httpOnly': False, 'name': 'Hm_lvt_64ecd82404c51e03dc91cb9e8c025574', 'path': '/', 'secure': False, 'value': '1593597860'},
{'domain': '.baidu.com', 'expiry': 1593770659, 'httpOnly': False, 'name': '__yjsv5_shitong', 'path': '/', 'secure': False, 'value': '1.0_7_3a72b0201970664024201a227cd1a3ef5b6f_300_1593597859671_42.120.72.105_b3aeb0f3'},
{'domain': 'fanyi.baidu.com', 'expiry': 1679997859, 'httpOnly': False, 'name': 'SOUND_PREFER_SWITCH', 'path': '/', 'secure': False, 'value': '1'},
{'domain': 'fanyi.baidu.com', 'expiry': 1679997859, 'httpOnly': False, 'name': 'REALTIME_TRANS_SWITCH', 'path': '/', 'secure': False, 'value': '1'},
{'domain': 'fanyi.baidu.com', 'expiry': 1679997859, 'httpOnly': False, 'name': 'SOUND_SPD_SWITCH', 'path': '/', 'secure': False, 'value': '1'},
{'domain': 'fanyi.baidu.com', 'expiry': 1679997859, 'httpOnly': False, 'name': 'HISTORY_SWITCH', 'path': '/', 'secure': False, 'value': '1'},
{'domain': '.fanyi.baidu.com', 'httpOnly': False, 'name': 'Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574', 'path': '/', 'secure': False, 'value': '1593597860'},
{'domain': 'fanyi.baidu.com', 'expiry': 1679997859, 'httpOnly': False, 'name': 'FANYI_WORD_SWITCH', 'path': '/', 'secure': False, 'value': '1'},
{'domain': '.baidu.com', 'expiry': 1625133858, 'httpOnly': False, 'name': 'BAIDUID', 'path': '/', 'secure': False, 'value': 'FAE67AC784551906C5007293413E0DF5:FG=1'}
]
我们把完整的cookie字段拼接一下:
#组装cookie字符串
cookie_str = ""
for item_cookie in cookie_items:
item_str = item_cookie["name"]+"="+item_cookie["value"]+"; "
cookie_str += item_str
print('cookie = ', cookie_str)
cookie = Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1593597860; __yjsv5_shitong=1.0_7_3a72b0201970664024201a227cd1a3ef5b6f_300_1593597859671_42.120.72.105_b3aeb0f3; SOUND_PREFER_SWITCH=1; REALTIME_TRANS_SWITCH=1; SOUND_SPD_SWITCH=1; HISTORY_SWITCH=1; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1593597860; FANYI_WORD_SWITCH=1; BAIDUID=FAE67AC784551906C5007293413E0DF5:FG=1;
模拟用户行为
按照上面的代码,我们获得了 token 和 cookie。但是 cookie 中并不含 yjs_js_security_passport,这是为什么呢?
我们猜测是只打开了网页,并没有 ‘翻译’ 的动作,才没有生成 yjs_js_security_passport。
接下来我们模拟一下用户的真实动作。
#在输入框输入‘test’,然后点击‘翻译’按键
browser.find_element_by_xpath("//*[@id='baidu_translate_input']").send_keys("test")
time.sleep(1)
browser.find_element_by_xpath("//*[@id='translate-button']").click()
time.sleep(1)
果不其然,我们得到了 yjs_js_security_passport。
token = 9b8bb341109338ba7e875bd9a9dd88ba
cookie = yjs_js_security_passport=aa994f15dc218dba1a732d1185d8f6f93ecc10b9_1593599172_js; HISTORY_SWITCH=1; FANYI_WORD_SWITCH=1; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1593599169; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1593599169; __yjsv5_shitong=1.0_7_e812f76cb8c9ac4d0b646ada6f3f9f38548f_300_1593599170022_42.120.72.105_4272f097; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; REALTIME_TRANS_SWITCH=1; BAIDUID=9FC8D8494F2ABEC8540D36AA87919AA1:FG=1;
然后我兴高采烈的拿着token、cookie、User-Agent、sign去模拟请求百度翻译了。
但是!返回错误:error:998。
冷静分析
error:997 是 sign 参数计算错误。
error:998 是 token、cookie、User-Agent、sign 不对应错误。
cookie 是直接获取的;User-Agent 一直不变,sign 计算值没有错。
那只能是 token 没有获取正确。
回退到模拟用户行为那一步,我发现点击 ‘翻译’ 按钮后,网页并没有出现正常的翻译结果!
selenium 点击翻译后,右侧依旧是空白。
我猜这应该是百度翻译对 selenium 的识别。(百度真棒)
但是在这个情况下,我手动点击了一下 ‘翻译’ 按钮,发现整个页面刷新了一下!刷新了一下!刷新了一下!(重要的事情说三遍)然后再输入 ‘test’ 就可以正常显示结果了!
骚操作来了
我们可以在一开始加载完页面的时候就刷新一次!
我们可以在一开始加载完页面的时候就刷新一次!
我们可以在一开始加载完页面的时候就刷新一次!
不就能正常访问页面了么?! selenium 刷新页面是用 refresh() 方法,代码如下:
#模仿人类行为欺骗浏览器
browser.refresh()
time.sleep(1)
browser.find_element_by_xpath("//*[@id='baidu_translate_input']").send_keys("test")
time.sleep(1)
browser.find_element_by_xpath("//*[@id='translate-button']").click()
time.sleep(1)
激动人心的时刻到了,我们得到了真实的 token !鼓掌 ~ ~
token = d4097247f1dbb4b6cb402997af0d83b4
cookie = yjs_js_security_passport=bd599955dc8342fd96fbdb7646fb388194da2b82_1593600965_js; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1593600963; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1593600961; __yjsv5_shitong=1.0_7_71d0d2e0248f50163b158f1be6eef5fb59e7_300_1593600962749_42.120.72.105_264a785b; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; REALTIME_TRANS_SWITCH=1; BAIDUID=EBBC5244ED06FB5222636C1A75C13D7C:FG=1;
并且每次运行得到的 token 和 cookie 都不一样。
nice,接下来就可以建立一个自己的 token 和 cookie 池了。
愿大家前程似锦,加油!