ファンファン爬虫類最初の戦い - Baiduの翻訳のAjaxを克服します


タグ:パイソン、リクエスト、JSON、pyexecjs

1.準備クローラ - 取付モジュール

pip install requests
pip install PyExecJs

PyExecJsパイソンは、JSの使用を実行するコードモジュールです。

2.情報要求を探します

2.1取得

そのURLを見つける見つけるためにオープンBaiduの翻訳ウェブサイトは次のとおりです。https://fanyi.baidu.com/?aldtype=16047#auto/zh
開発者向けツールで見つけることができる必要があり、これは要求を取得するURLであることを確認するために難しいことではありません?aldtype=16047文書、次のように示します:

?aldtype = 16047

すべての要求は、関連する情報はここで取得することができます取得します。

2.2ポスト

そして、確かに私たちは本当にオンラインURL、翻訳サイトを探している、リアルタイム翻訳はポストによって要求されるものを得ることはありませ。だから、我々はファイルのポストを要求してきた開発者ツールを見ておく必要があります。
偶然という名の男を発見したverify?token=ものを何ファイルには、POSTリクエストですが、ステータスコードは、Status Codeリクエストエラー(403)ではない、(302)をリダイレクトすることです。その代わりに、私たちは、探している。
遭遇したような問題は、一般的に、行き、その後、翻訳の内容を提出することパケットキャプチャ(開発ツール)でのツールとはという男を見たv2transapi。ファイルは、我々が探しているものである
ので、ここで我々は、我々が望むものを得ることができますpost本物を探して、情報をpost:リクエストURLですhttps://fanyi.baiduを。 COM / v2transapi
しかし、ペンシルバニア州ペンシルバニア州ペンシルバニア...、解析によって得られた情報を含む、コードの後に終了errorされる。問題が記載されています。

以来、開発ツール、怒りが嫌いctrl+shift+fキー、検索入力ボックスを入力しv2transapi、その後、憎しみをEnterキーを押し、ダブルクリックした結果を、。いくつかの手がかりを見つけるように見えた
パッケージ隠さ混乱jsのコード、めまいビットではなく、インサイドnot'reコンテンツを探している最終的に知っているが、これは唯一の手がかりである、または外観に付着する。
案の定、お馴染みとなじみのないコンテンツを見ました$.ajax({type:"POST",url:"/v2transapi",cache:!1,data:p})
分析(PSによると:あなたがダウン段階の分析によって、ステップをしたくない場合は、データPの含有量に相当する)は、ラインブレークポイントで再生することができ、私たちの次の手掛かりです。
今では、変数pを使用することができ、そしてpは確かに見つけることが、その後、インターネットが難しくないはずが割り当てられていますPを見つけました:p={from:g.fromLang,to:g.toLang,query:a,transtype:n,simple_means_flag:3,sign:m(a),token:window.common.token};
。いくつかのデジャヴがああ分析によると、これは私たちのpであるform data以下に示すように、パラメータは、同じです。

フォームデータ

私たちはほとんどがそれを気にする必要は何ですか?当然そう多くのデータ、signそれはそれを暗号化するためにM機能を使用してのように見える、と前の分析ステップで、それは変数のデータであることを見つけるかもしれないので、他のパラメータであります同じことが。キャプチャツールから直接取得することができます
ので、我々はさらなる分析を行かなければならないsign
$.ajax({type:"POST",url:"/v2transapi",cache:!1,data:p})状態のデバッグにブレークポイントをプレーした後、入力ボックスを翻訳、単に翻訳するコンテンツを入力して、この時間。
関数は、M上でマウスを移動し、mはちょうど見出さ発見以下に示すように、コンテンツをポップすることが見出されています。

電子機能に関連付けられている説明のm個の点は、我々は.jsファイルを維持するために、電子関連の機能の内容を下にコピーし、コードのJS execjsを実行するために使用することができます。

コード3.

3.1 JSファイル

var i = "320305.131321201"

function a(r){if(Array.isArray(r)){for(var o=0,t=Array(r.length);o<r.length;o++)t[o]=r[o];
return t}return Array.from(r)}

function n(r,o){for(var t=0;t<o.length-2;t+=3){var a=o.charAt(t+2);a=a>="a"?a.charCodeAt(0)-87:Number(a),a="+"===o.charAt(t+1)?r>>>a:r<<a,r="+"===o.charAt(t)?r+a&4294967295:r^a
}return r}

function e(r) {
        var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
        if (null === o) {
            var t = r.length;
            t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr( - 10, 10))
        } else {
            for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)"" !== e[C] && f.push.apply(f, a(e[C].split(""))),
            C !== h - 1 && f.push(o[C]);
            var g = f.length;
            g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice( - 10).join(""))
        }
        var u = void 0,
        l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);
        u = null !== i ? i: (i = window[l] || "") || "";
        for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {
            var A = r.charCodeAt(v);
            128 > A ? S[c++] = A: (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)), S[c++] = A >> 18 | 240, S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224, S[c++] = A >> 6 & 63 | 128), S[c++] = 63 & A | 128)
        }
        for (var p = m,
        F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++) p += S[b],
        p = n(p, F);
        return p = n(p, D),
        p ^= s,
        0 > p && (p = (2147483647 & p) + 2147483648),
        p %= 1e6,
        p.toString() + "." + (p ^ m)
    }

3.2 PYファイル

import json
import re

import execjs
import js2py
import requests


class baidu_translate():
    def __init__(self):
        self.GET_URL = 'https://fanyi.baidu.com/?aldtype=16047#zh/en/'
        self.POST_URL = 'https://fanyi.baidu.com/v2transapi'

        self.GET_HEADERS = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0', 'Accept': '*/*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Host': 'fanyi.baidu.com', 'Origin': 'https://fanyi.baidu.com', 'Referer': 'https://fanyi.baidu.com/', 'X-Requested-With': 'XMLHttpRequest',
            # 'cookie': '',
        }
        self.POST_HEADERS = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0',
            'Accept': '*/*',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Connection': 'keep-alive',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Host': 'fanyi.baidu.com',
            'Origin': 'https://fanyi.baidu.com',
            'Referer': 'https://fanyi.baidu.com/?aldtype=16047',
            'X-Requested-With': 'XMLHttpRequest',
        }

        self._session = requests.session()
        self._data = {
            'from': 'zh',
            'to': 'en',
            'transtype': 'realtime',
            'simple_means_flag': '3',
            # 'query': '',  # 要翻译的词或句, 变项
            # 'sign': '',  # Ajax(js) 加密, 变项
            # 'token': '',  # 不变项
        }
        # 可以直接拿浏览器上的 token, 因为 token 是不变的
        self._get_token()

    def _get_token(self):
        response = self._session.get(self.GET_URL, headers=self.GET_HEADERS)
        html = response.text
        li = re.search(r"<script>\s*window\[\'common\'\] = ([\s\S]*?)</script>", html)
        token = re.search(r"token: \'([a-zA-Z0-9]+)\',", li.group(1))
        self._data['token'] = token.group(1)

    def _get_sign(self):
        # 将 使用 js 加密的函数 copy 到 baidu_translate.js 文件中
        # 然后使用 execjs 执行
        with open('baidu_translate.js') as fp:
            sign = execjs.compile(fp.read()).call('e', self._query)
            self._data['sign'] = sign

    def translate(self, query):
        self._query = query
        self._get_sign()
        self._data['query'] = self._query
        print(self._data)
        response = self._session.post(self.POST_URL, data=self._data, headers=self.POST_HEADERS)
        content = response.content.decode()
        dict_data = json.loads(content)
        # print(dict_data)
        ret = dict_data['trans_result']['data'][0]['dst']
        print(ret)


if __name__ == "__main__":
    trans = baidu_translate()
    trans.translate('百度翻译, 我在爬你')

おすすめ

転載: www.cnblogs.com/trent-fzq/p/11210900.html
おすすめ