python爬虫 -- 有道翻译小工具

最近的项目中需要自动翻译一些英文的文章,所以就在简书上找了找有没有有道翻译的小爬虫,结果就找到了一篇文章 破解有道翻译反爬虫机制

可能是有道那边有调整的原因,结果文章中有些小问题,在此做一下更正。

浏览器打开 http://fanyi.youdao.com/,右键 -> 检查 -> Network项。在翻译框中输入 beautiful后,我们会发现请求来了。

我们已经确定了很多信息:

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

  • 请求方法为 POST。

  • 请求参数

我们再试了些其他值后发现,果真变化的只有那几个参数:

  • i : 我们要翻译的词或者句子

  • salt : 加密用到的盐

  • sign : 签名字符串

然后跟着作者的思路,来到了哪个迷迷茫茫的JS文件中,终于找到:

嗯,没有问题,和作者说的没有差错。

只是秘钥变了 ebSeFb%=XZ%T[KZ)c(sy!。但是比较好奇,有道是如何更换秘钥的,策略又是什么?

先用作者文章中的代码,更换秘钥,直接跑起来,BUT,BUT,BUT没有跑通:

{'errorCode': 50}

静下心来,好好想想。可能是没有加 header,有道应该会有防爬虫的简单机制。再试:

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"
}

执行还是报错:

 Desktop python3 aa.py
请输入需要翻译的单词: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

什么情况,把响应body打印出来,更是惊奇:

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"

继续检查,继续找原因,突然我看到了一个令我觉悟的信息:

嗯,这个应该是问题的关键。python3urllib应该没有实现这个机制。

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

嗯,应该没问题了,再试一下:

Desktop python3 aa.py
请输入需要翻译的单词:beautiful
['美丽的']

完成,没有问题了。

最后给出完整的代码:

# -*- 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


#有道翻译中,是支持翻译多段落文章的,所以调用translate之后,会返回一个数组,数组里的元素就是翻译过后的段落。输入几个段落,输出就有几个段落。

content = input('请输入需要翻译的单词:').replace("\\n", "\n")

print(YouDaoFanYi().translate(content))

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 破解有道翻译反爬虫机制 web端的有道翻译,在之前是直接可以爬的。也就是说只要获取到了他的接口,你就可以肆无忌惮的...
    编程小蝉阅读 6,098评论 10 28
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,442评论 25 707
  • 网络爬虫,是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成。但是当网络爬虫被滥用后,...
    谦面客阅读 2,053评论 1 4
  • 从小我就有个超能力 想让什么事情发生 就逆向想象 比如 外面阴天 用力想着下雨 接下来就会是大晴天, 办了错事 想...
    怀青阅读 201评论 0 1
  • 这里是温柔的,坚硬和粗糙的围墙里,我就躲在那,安心的看着眼前的星星。 第一,不被情绪冲昏了头脑,像一个无头...
    眼白阅读 285评论 0 0