破解有道翻譯反爬蟲機制(現在不能用了)


破解有道翻譯反爬蟲機制

web端的有道翻譯,在之前是直接可以爬的。也就是說只要獲取到了他的接口,你就可以肆無忌憚的使用他的接口進行翻譯而不需要支付任何費用。那么自從有道翻譯推出他的API服務的時候,就對這個接口做一個反爬蟲機制(如果大家都能免費使用到他的翻譯接口,那他的API服務怎么賺錢)。這個反爬蟲機制在爬蟲領域算是一個非常經典的技術手段。那么他的反爬蟲機制原理是什么?如何破解?接下來帶大家一探究竟。

一、正常爬取一個網站的步驟

如果你要爬取他的翻譯接口,這個流程還是不能少的。首先我們打開有道翻譯的鏈接:http://fanyi.youdao.com/。然后在頁面中右鍵->檢查->Network項。這時候就來到了網絡監聽窗口,以后你在這個頁面中發送的所有網絡請求,都會在Network這個地方顯示出來。接着我們在翻譯的窗口輸入我們需要翻譯的文字,比如輸入hello。然后點擊自動翻譯按鈕,那么接下來在下面就可以看到瀏覽器給有道發送的請求,這里截個圖看看:

在上圖,我們可以看到發送了很多的網絡請求,這里我們點擊第一個網絡POST請求進行查看:

可以看到與一個Request URL,這個url是請求鏈接地址

查看服務器的回復包Response

並且,現在我們再回到Headers的地方,然后滾動到最下面,可以看到有一個Form Data的地方,這個下面展示了許多的數據,這些數據就是你在點擊翻譯的時候瀏覽器給服務器發送的數據:

 

當然現在的Header 里的From Data數據內容不止這些,還多了tv等字段

對其中幾個比較重要的數據進行解釋:

  • i:需要進行翻譯的字符串,這個地方我們輸入的是hello。
  • salt:加密用到的鹽。這個是我們破解有道反爬蟲機制的關鍵點。
  • sign:簽名字符串。也是破解反爬蟲機制的關鍵點
  • 其他的數據類型暫時就不怎么重要了,都是固定寫法,我們后面寫代碼的時候直接鞋子就可以了。到現在為止,我們就可以寫一個簡單的爬蟲,去調用有道翻譯的接口了。這里我們使用的網絡請求庫是Python3自帶的urllib,相關代碼如下:
 1 # 導入需要的庫
 2 import urllib.request  3 import urllib.parse  4 import json  5  
 6 # 等待用戶輸入需要翻譯的單詞
 7 content = input('請輸入需要翻譯的單詞:')  8  
 9 # 有道翻譯的url鏈接
10 url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=null'
11  
12 # 發送給有道服務器的數據
13 data = {} 14  
15 # 需要翻譯的文字
16 data['i'] = content 17 # 下面這些都先按照我們之前抓包獲取到的數據
18 data['from'] = 'AUTO'
19 data['to'] = 'AUTO'
20 data['smartresult'] = 'dict'
21 data['client'] = 'fanyideskweb'
22 data['salt'] = '1500349255670'
23 data['sign'] = '997742c66698b25b43a3a5030e1c2ff2'
24 data['doctype'] = 'json'
25 data['version'] = '2.1'
26 data['keyfrom'] = 'fanyi.web'
27 data['action'] = 'FY_BY_CLICKBUTTON'
28 data['typoResult'] = 'true'
29  
30 # 對數據進行編碼處理
31 data = urllib.parse.urlencode(data).encode('utf-8') 32  
33 # 創建一個Request對象,把url和data傳進去,並且需要注意的使用的是POST請求
34 request = urllib.request.Request(url=self.url, data=data, method='POST') 35 # 打開這個請求
36 response = urllib.request.urlopen(request) 37 # 讀取返回來的數據
38 result_str = response.read().decode('utf-8') 39 # 把返回來的json字符串解析成字典
40 result_dict = json.loads(result_str) 41  
42 # 獲取翻譯結果
43 print('翻譯的結果是:%s' % result_dict)

只是為了顯示作用----學習基本爬蟲流程。

我們運行這個文件后,當我們輸入的是hello的時候,我們可以得到哈羅的這個正確的翻譯結果。而當我們輸入其他需要翻譯的字符串的時候,比如輸入i love you,那么就會得到一個錯誤代碼{"errorCode":50}。這就奇怪了,有道詞典不可能只能翻譯一個英文單詞吧(開始變的貪得無厭 --)。而這個,就是有道詞典的反爬蟲機制。接下來我們就來破解有道詞典的反爬蟲機制。

二、破解反爬蟲機制:

我們可以多次的進行翻譯,並且每次翻譯后都去查看翻譯的時候發送的這個網絡請求,比較每次翻譯時候發送的Form Data的值。我們注意到,Form Data在每次發送網絡請求的時候,只有i和salt以及sign這三個是不同的,其他的數據都是一樣的,這里我用hello和world兩個單詞翻譯時候Form Data的數據進行比較:

圖中的Form Data也證實了我剛剛所說的,就是除了i、salt以及sign是不一樣的。其余都是一樣的。而i不一樣是很正常的。因為i代表的是要翻譯的字符串,這個不同是很正常。而salt和sign這兩個東西不一樣,是怎么產生的呢?這里我們可以分析一下,這兩個值在每次請求的時候都不一樣,只有兩種情況:第一是每次翻譯的時候,瀏覽器會從有道服務器獲取一下這兩個值(返回包里面是否有GET到??)。這樣可以達到每次翻譯的時候值不同的需求。第二是在本地,用JS代碼按照一定的規則生成的。那么我們首先來看第一個情況,我們可以看到在每次發送翻譯請求的時候,並沒有一個請求是專門用來獲取這兩個值的:

第一種情況涼涼...不慌,我們還有法二   hh

所以就可以排除第一種情況。就只剩下一種可能,那就是在本地自己生成的,如果是在本地自己生成的,那么規則是什么呢?這里我們點擊網頁,查看網頁源代碼,查找所有的JS文件,我們找到那個fanyi.js:(現在的有道代碼會用各種混淆的詞匯來掩飾這個js源代碼,還不是為了不讓你爬數據,不過認真找還是能找到的)

然后點擊這個文件,跳轉到這個源文件中,然后全選所有的代碼,復制下來,再打開站長工具:http://tool.chinaz.com/Tools/jsformat.aspx。把代碼復制進去后,點擊格式化:

將數據拷貝到notepad++ 或 sublime,打開,然后搜索salt,可以找到相關的代碼:

這里我們就可以發現所有的值的生成原理了。這里來做個簡介:

d:代表的是需要翻譯的字符串。
f:當前時間的時間戳加上0-10的隨機字符串。
u:一個常量——fanyideskweb。
c:一個常量——rY0D^0'nM0}g5Mm1z%1G4。
salt:就是f變量,時間戳。
sign:使用的是u + d + f + c的md5的值。
知道salt和sign的生成原理后,我們就可以寫Python代碼,來對接他的接口了,以下是相關代碼:

 1 import urllib.request  2  
 3 import urllib.parse  4 import json  5 import time  6 import random  7 import hashlib  8  
 9 content = input('請輸入需要翻譯的句子:') 10  
11 url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/'
12  
13 data = {} 14  
15 u = 'fanyideskweb'
16 d = content 17 f = str(int(time.time()*1000) + random.randint(1,10)) 18 c = 'rY0D^0\'nM0}g5Mm1z%1G4'
19  
20 sign = hashlib.md5((u + d + f + c).encode('utf-8')).hexdigest() 21  
22 data['i'] = content 23 data['from'] = 'AUTO'
24 data['to'] = 'AUTO'
25 data['smartresult'] = 'dict'
26 data['client'] = 'fanyideskweb'
27 data['salt'] = f 28 data['sign'] = sign 29 data['doctype'] = 'json'
30 data['version'] = '2.1'
31 data['keyfrom'] = 'fanyi.web'
32 data['action'] = 'FY_BY_CLICKBUTTON'
33 data['typoResult'] = 'true'
34  
35 data = urllib.parse.urlencode(data).encode('utf-8') 36 request = urllib.request.Request(url=url,data=data,method='POST') 37 response = urllib.request.urlopen(request)
38print(response.read().decode('utf-8'))

現在的js代碼

 

還在學習破解中...希望有大佬破解出來可以分享分享

寫在最后:

像以上這種,通過用JS在本地生成隨機字符串的反爬蟲機制,在爬蟲的時候是經常會遇到的一個問題。主要學習的是一種思路。以后再碰到這種問題的時候知道該如何解決。這樣本篇文章的目的也就達到了。

另外說明一下現在的有道就連爬取一個單純單詞用這個方法都不行了 ,有道使用了更為復雜的反爬蟲機制,等待學習中...

最后附上大佬的博客地址:https://blog.csdn.net/nunchakushuang/article/details/75294947


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM