Python爬蟲入門教程 61-100 寫個爬蟲碰到反爬了,動手破壞它!

夢想橡皮擦發表於2019-04-22

python3爬蟲遇到了反爬

當你興沖沖的開啟一個網頁,發現裡面的資源好棒,能批量下載就好了,然後感謝寫個爬蟲down一下,結果,一頓操作之後,發現網站竟然有反爬措施,尷尬了。

接下來的幾篇文章,我們研究一下各種反爬蟲套路,當然網際網路沒有100%的反爬措施,只要你能使用瀏覽器訪問的網頁,都是可以爬取到了,所有的人不能杜絕爬蟲,只能在一定程度上增加你爬取的成本,說白了,就是讓你的技術爬不到~

爬蟲和反爬蟲一直都是這個領域程式設計師對抗的基礎,從最簡單的UA限制,到略微複雜一些的IP限制,使用者限制,技術都是不斷髮展的,但是,不怕賊偷,就怕賊惦記,只要你的網站內容有價值,放心,一堆爬蟲coder盯著呢?

emmmm....

搞定javascript加密

js加密最簡單的是採用md5進行的,我們通過http://fanyi.youdao.com/來演示本篇部落格內容

在這裡插入圖片描述
接下來你要注意的是這個請求是由哪個Js檔案發起的
在這裡插入圖片描述
檔案獲取到為 fanyi.min.js,繼續追蹤,滑鼠在這個檔名上面停留一下就可以獲取到基本資訊,我們點選跟請求相關的那個方法對應的檔案連結,跳轉到方法內部
在這裡插入圖片描述

這個地方有個操作細節,你需要學會,點選檔案之後,跳轉到的JS檔案是壓縮之後的,進行一下格式化操作

在這裡插入圖片描述
拿到原始碼

    t.translate = function(e, t) {
        _ = f("#language").val();
        var n = x.val()
          , r = g.generateSaltSign(n)
          , i = n.length;
        if (F(),
        T.text(i),
        i > 5e3) {
            var a = n;
            n = a.substr(0, 5e3),
            r = g.generateSaltSign(n);
            var s = a.substr(5e3);
            s = (s = s.trim()).substr(0, 3),
            f("#inputTargetError").text("有道翻譯字數限制為5000字,“" + s + "”及其後面沒有被翻譯!").show(),
            T.addClass("fonts__overed")
        } else
            T.removeClass("fonts__overed"),
            f("#inputTargetError").hide();
        d.isWeb(n) ? o() : l({
            i: n,
            from: C,
            to: S,
            smartresult: "dict",
            client: k,
            salt: r.salt,
            sign: r.sign,
            ts: r.ts,
            bv: r.bv,
            doctype: "json",
            version: "2.1",
            keyfrom: "fanyi.web",
            action: e || "FY_BY_DEFAULT",
            typoResult: !1
        }, t)
    }
複製程式碼

引數分析

  • i 表示 帶翻譯的詞語
  • from 設定為 AUTO
  • to 設定為 AUTO
  • smartresult 預設值 dict
  • client 翻譯的客戶端:預設應該為 fanyideskweb
  • salt 第一個變數 需要查閱生成規則
  • sign 第二個變數 需要查閱生成規則
  • ts
  • bv
  • 其餘的引數保持預設即可

重點引數

  • salt
  • sign
  • ts
  • bv

程式碼的複查當中找到引數來源

 var r = function(e) {
        var t = n.md5(navigator.appVersion)
          , r = "" + (new Date).getTime()
          , i = r + parseInt(10 * Math.random(), 10);
        return {
            ts: r,
            bv: t,
            salt: i,
            sign: n.md5("fanyideskweb" + e + i + "1L5ja}w$puC.v_Kz3@yYn")
        }
複製程式碼

OK,我們已經獲取到引數的內容了

  • ts = r 表示當前的時間戳
  • salt 用r去加上一個隨機數
  • sign 為 一個特殊的md5,中間重點注意 e 其實就是你要翻譯的詞語
  • navigator.appVersion 這個比較容易,在開發者工具中執行一下就可以得到了

5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36

程式碼嘗試

準備好這麼多材料之後,剩下的就是編碼了,我們開始吧,這個地方依據的是JS的原始碼,然後轉換成Python即可,沒有特別難的地方

引數的生成

def generate_salt_sign(translate):
    # var t = n.md5(navigator.appVersion)
    app_version = "5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
    bv = hashlib.md5(app_version.encode(encoding='UTF-8')).hexdigest()
    # r = "" + (new Date).getTime()
    ts = str(int(round(time.time(),3)*1000))
    # i = r + parseInt(10 * Math.random(), 10);
    salt = ts + str(random.randint(1,10))

    # sign: n.md5("fanyideskweb" + e + i + "1L5ja}w$puC.v_Kz3@yYn")
    sign = hashlib.md5(("fanyideskweb"+translate+salt+"1L5ja}w$puC.v_Kz3@yYn").encode(encoding='utf-8')).hexdigest()

    return salt,sign,ts,bv
複製程式碼

引數的拼接與header的準備

def params():
    data = {}
    translate = 'morning'
    client = 'fanyideskweb'
    data['i'] = translate
    data['from'] = 'AUTO'
    data['to'] = 'AUTO'
    data['smartresult'] = 'dict'
    data['client'] = client

    data['salt'],data['sign'],data['ts'],data['bv'] = generate_salt_sign(translate)
    data['doctype'] = 'json'
    data['version'] = '2.1'
    data['keyfrom'] = 'fanyi.web'
    data['action'] = 'FY_BY_REALTIME'
    data['typoResult'] = 'false'

    return data
複製程式碼

發起請求

def tran():
    data = params()
    headers = {}
    headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
    headers["Referer"] = "http://fanyi.youdao.com/"
    headers["Cookie"] = "OUTFOX_SEARCH_USER_ID=-1868577286@222.222.147.75;"

    with requests.post("http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule",headers=headers,data=data) as res:
        print(res.text)

if __name__ == '__main__':
    tran()
複製程式碼

結果展示

{"translateResult":[[{"tgt":"早....","src":"morning"}]],"errorCode":0,"type":"en2zh-CHS","smartResult":{"entries":["","n. 早晨;黎明;初期\r\n"],"type":1}}
複製程式碼

得到資料之後就表示我們的目標完成了~

本篇部落格的反爬內容搞定~

關注微信公眾賬號,回覆0401獲取原始碼

在這裡插入圖片描述

相關文章