python爬蟲(chóng) -- 有道翻譯小工具

最近的項(xiàng)目中需要自動(dòng)翻譯一些英文的文章祥国,所以就在簡(jiǎn)書(shū)上找了找有沒(méi)有有道翻譯的小爬蟲(chóng)导狡,結(jié)果就找到了一篇文章 破解有道翻譯反爬蟲(chóng)機(jī)制扰法。

可能是有道那邊有調(diào)整的原因,結(jié)果文章中有些小問(wèn)題决左,在此做一下更正。

瀏覽器打開(kāi) http://fanyi.youdao.com/走贪,右鍵 -> 檢查 -> Network項(xiàng)佛猛。在翻譯框中輸入 beautiful后,我們會(huì)發(fā)現(xiàn)請(qǐng)求來(lái)了坠狡。

我們已經(jīng)確定了很多信息:

  • URL:http://fanyi.youdao.com/translate_osmartresult=dict&smartresult=rule

  • 請(qǐng)求方法為 POST继找。

  • 請(qǐng)求參數(shù)

我們?cè)僭嚵诵┢渌岛蟀l(fā)現(xiàn),果真變化的只有那幾個(gè)參數(shù):

  • i : 我們要翻譯的詞或者句子

  • salt : 加密用到的鹽

  • sign : 簽名字符串

然后跟著作者的思路逃沿,來(lái)到了哪個(gè)迷迷茫茫的JS文件中婴渡,終于找到:

嗯,沒(méi)有問(wèn)題感挥,和作者說(shuō)的沒(méi)有差錯(cuò)缩搅。

只是秘鑰變了 ebSeFb%=XZ%T[KZ)c(sy!。但是比較好奇触幼,有道是如何更換秘鑰的硼瓣,策略又是什么?

先用作者文章中的代碼,更換秘鑰堂鲤,直接跑起來(lái)亿傅,BUT,BUT瘟栖,BUT沒(méi)有跑通:

{'errorCode': 50}

靜下心來(lái)葵擎,好好想想“胗矗可能是沒(méi)有加 header酬滤,有道應(yīng)該會(huì)有防爬蟲(chóng)的簡(jiǎn)單機(jī)制。再試:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36",
    "Accept":"application/json, text/javascript, */*; q=0.01",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
    "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
    "Cookie":"_ntes_nnid=c686062b6d8c9e3f11e2a8413b5bb9a8,1517022642199; OUTFOX_SEARCH_USER_ID_NCOO=1367486017.479911; OUTFOX_SEARCH_USER_ID=722357816@10.168.11.24; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcCzqE6R9jTv5rTtoWgw; fanyi-ad-id=40789; fanyi-ad-closed=1; ___rl__test__cookies=1519344925194",
    "Referer":"http//fanyi.youdao.com/",
    "X-Requested-With": "XMLHttpRequest"
}

執(zhí)行還是報(bào)錯(cuò):

 Desktop python3 aa.py
請(qǐng)輸入需要翻譯的單詞:hello
Traceback (most recent call last):
  File "aa.py", line 94, in <module>
    print(YouDaoFanYi().translate(content))
  File "aa.py", line 77, in translate
    dictResult = json.loads(result)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 349, in loads
    s = s.decode(detect_encoding(s), 'surrogatepass')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

什么情況寓涨,把響應(yīng)body打印出來(lái)盯串,更是驚奇:

b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xabV*)J\xcc+\xceI,I\rJ-.\xcd)Q\xb2\x8a\x8e\xaeV*I\x072\x94\x9e\xec]\xf0t\xe9^%\x1d\xa5\xe2\xa2d 7#5''_\xa966VG)\xb5\xa8(\xbf\xc89?%U\xc9\xca@G\xa9\xa4\xb2\x00\xc8PJ\xcd3\xaa\xca\xd0u\xf6\x08\x06\xe9\xc8M,*\x81\x99X\r\x94*)\xcaL-\x06\x1a\xae\x04\x94\xcc\xd3Sx\xb1p\xc5\xf3%\xbb^N_\xf7\xb4a\xe6\xfb==\n\xcf\x9a\xbb\x9e.m\x7f\xd61\xed\xe9\x94%/\xb6n\x7f\xb6y\xc5\xb3\x96\xfeg\xd3\xb7=\x9f\xd5\xf2|\xca\x8a\x17\xeb\xd7\xc6\x14\xc5\xe4\x01\xb5f\xe6\x95\xe8)<\x9d\xd6\xf4~\xcf\xec\xa7\x93;\x9e\xef\x9d\x0e\x15\x07\x1a\xa9\xe1\x01r\x9f\xe6\x93]\xbb\x9eN\xe8\x05\xcak<\xdb<U\xf3\xe9\xfc\xe6g[f\x83\x15\x01\x9d\rq\xa8am-\x00\x9f\x1b\xb6\x04\xf7\x00\x00\x00"

繼續(xù)檢查,繼續(xù)找原因戒良,突然我看到了一個(gè)令我覺(jué)悟的信息:

嗯体捏,這個(gè)應(yīng)該是問(wèn)題的關(guān)鍵。python3urllib應(yīng)該沒(méi)有實(shí)現(xiàn)這個(gè)機(jī)制糯崎。

def readData(resp):
    info = resp.info()
    encoding = info.get('Content-Encoding')
    transferEncoding = info.get('Transfer-Encoding:')
    if transferEncoding != 'chunked' and encoding != 'gzip':
        return resp.read()
    str = ""
    while True:
        chunk = resp.read(4096)
        if not chunk: break
        decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
        data = decomp.decompress(chunk)
        str = str + data.decode("utf-8")
    return str

嗯几缭,應(yīng)該沒(méi)問(wèn)題了,再試一下:

Desktop python3 aa.py
請(qǐng)輸入需要翻譯的單詞:beautiful
['美麗的']

完成沃呢,沒(méi)有問(wèn)題了年栓。

最后給出完整的代碼:

# -*- coding: utf-8 -*-


import urllib.request
import urllib.parse
import json
import zlib

import time
import random
import hashlib


class YouDaoFanYi:

    def __init__(self):
        self.url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36",
            "Accept":"application/json, text/javascript, */*; q=0.01",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
            "Cookie":"_ntes_nnid=c686062b6d8c9e3f11e2a8413b5bb9a8,1517022642199; OUTFOX_SEARCH_USER_ID_NCOO=1367486017.479911; OUTFOX_SEARCH_USER_ID=722357816@10.168.11.24; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcCzqE6R9jTv5rTtoWgw; fanyi-ad-id=40789; fanyi-ad-closed=1; ___rl__test__cookies=1519344925194",
            "Referer":"http//fanyi.youdao.com/",
            "X-Requested-With": "XMLHttpRequest"
        }

        self.data = {
            "from":"AUTO",
            "to": "AUTO",
            "smartresult": "dict",
            "client": "fanyideskweb",
            "doctype": "json",
            "version": "2.1",
            "keyfrom": "fanyi.web",
            "action": "FY_BY_REALTIME",
            "typoResult": "false"
        }

        self.client = 'fanyideskweb'
        self.secretKey = 'ebSeFb%=XZ%T[KZ)c(sy!'

    @staticmethod
    def readData(resp):
        info = resp.info()
        encoding = info.get('Content-Encoding')
        transferEncoding = info.get('Transfer-Encoding:')
        if transferEncoding != 'chunked' and encoding != 'gzip':
            return resp.read()
        str = ""
        while True:
            chunk = resp.read(4096)
            if not chunk: break
            decomp = zlib.decompressobj(16 + zlib.MAX_WBITS)
            data = decomp.decompress(chunk)
            str = str + data.decode("utf-8")
        return str

    def translate(self, content):
        data = dict(self.data)
        salt = str(int(time.time() * 1000) + random.randint(1, 10))
        sign = hashlib.md5((self.client + content + salt + self.secretKey).encode('utf-8')).hexdigest()

        data["client"] = self.client
        data["salt"] = salt
        data["sign"] = sign
        data["i"]=content

        data = urllib.parse.urlencode(data).encode('utf-8')
        request = urllib.request.Request(url=self.url, data=data, headers=self.headers, method='POST')
        response = urllib.request.urlopen(request)
        #result=response.read()
        #print(result)
        result = YouDaoFanYi.readData(response)
        response.close()
        dictResult = json.loads(result)

        paragraphs=[]
        for paragraph in dictResult["translateResult"]:
            line=""
            for a in paragraph:
                line = line + a["tgt"]

            if(len(line) != 0):
                paragraphs.append(line)

        return paragraphs


#有道翻譯中,是支持翻譯多段落文章的樟插,所以調(diào)用translate之后韵洋,會(huì)返回一個(gè)數(shù)組,數(shù)組里的元素就是翻譯過(guò)后的段落黄锤。輸入幾個(gè)段落搪缨,輸出就有幾個(gè)段落。

content = input('請(qǐng)輸入需要翻譯的單詞:').replace("\\n", "\n")

print(YouDaoFanYi().translate(content))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸵熟,一起剝皮案震驚了整個(gè)濱河市副编,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌流强,老刑警劉巖痹届,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異打月,居然都是意外死亡队腐,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)奏篙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)柴淘,“玉大人迫淹,你說(shuō)我怎么就攤上這事∥希” “怎么了敛熬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)第股。 經(jīng)常有香客問(wèn)我应民,道長(zhǎng),這世上最難降的妖魔是什么夕吻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任诲锹,我火速辦了婚禮,結(jié)果婚禮上梭冠,老公的妹妹穿的比我還像新娘辕狰。我一直安慰自己,他們只是感情好控漠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著悬钳,像睡著了一般盐捷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上默勾,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天碉渡,我揣著相機(jī)與錄音,去河邊找鬼母剥。 笑死滞诺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的环疼。 我是一名探鬼主播习霹,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼炫隶!你這毒婦竟也來(lái)了淋叶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伪阶,失蹤者是張志新(化名)和其女友劉穎煞檩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體栅贴,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斟湃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了檐薯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凝赛。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哄酝,到底是詐尸還是另有隱情友存,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布陶衅,位于F島的核電站屡立,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏搀军。R本人自食惡果不足惜膨俐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罩句。 院中可真熱鬧焚刺,春花似錦、人聲如沸门烂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)屯远。三九已至蔓姚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慨丐,已是汗流浹背坡脐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留房揭,地道東北人备闲。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捅暴,于是被迫代替她去往敵國(guó)和親恬砂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 破解有道翻譯反爬蟲(chóng)機(jī)制 web端的有道翻譯伶唯,在之前是直接可以爬的觉既。也就是說(shuō)只要獲取到了他的接口,你就可以肆無(wú)忌憚的...
    編程小蟬閱讀 6,112評(píng)論 10 28
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,071評(píng)論 25 707
  • 網(wǎng)絡(luò)爬蟲(chóng)乳幸,是一個(gè)自動(dòng)提取網(wǎng)頁(yè)的程序瞪讼,它為搜索引擎從萬(wàn)維網(wǎng)上下載網(wǎng)頁(yè),是搜索引擎的重要組成粹断。但是當(dāng)網(wǎng)絡(luò)爬蟲(chóng)被濫用后符欠,...
    謙面客閱讀 2,065評(píng)論 1 4
  • 從小我就有個(gè)超能力 想讓什么事情發(fā)生 就逆向想象 比如 外面陰天 用力想著下雨 接下來(lái)就會(huì)是大晴天, 辦了錯(cuò)事 想...
    懷青閱讀 203評(píng)論 0 1
  • 這里是溫柔的瓶埋,堅(jiān)硬和粗糙的圍墻里希柿,我就躲在那诊沪,安心的看著眼前的星星。 第一曾撤,不被情緒沖昏了頭腦端姚,像一個(gè)無(wú)頭...
    眼白閱讀 288評(píng)論 0 0