主頁 > 後端開發 > 【Python3爬蟲】模擬實作小牛在線登錄程序

【Python3爬蟲】模擬實作小牛在線登錄程序

2020-09-22 21:50:32 後端開發

一、站點分析

  小牛在線的登錄入口地址為:https://www.xiaoniu88.com/user/login,

  用戶登錄時除了需要輸入用戶名和密碼,還要輸一個驗證碼,我們可以先任意輸入一個用戶名、密碼以及驗證碼,打開開發者工具,點擊登錄并登錄失敗,在開發者工具中切換到 Network 頁面,找到如下請求:

https://www.xiaoniu88.com/user/login?1593312412749

  很明顯這個問號后面跟的是一個十三位的時間戳,然后往下拉查看這個 POST 請求的引數內容:

  其中有五個引數 username 是輸入的用戶名,password 是密碼加密后的結果,code 是輸入的驗證碼,ooh.token.name 和 ooh.token.value 所表示的含義尚且不知,實作模擬登錄小牛在線,必須要知道如何得到除了用戶名以外的四個引數,若要問如何得到這幾個引數,請往下看,

 

二、引數破解

1.兩個token

  在開發者工具中 Ctrl + F 全域搜索“token”,然后在登錄頁面中可以搜到如下內容,其中就包含了請求引數中的 ooh.token.name 和 ooh.token.value 的值:

   可以看到是兩個隱藏的 input 標簽,其 value 就是登錄時所需要的 token 值,

2.密碼password

  先全域搜索“password”,找到一個 JS 檔案,地址為:

https://image.xiaoniu88.com/static/WebXn/dist/user/login/js/init-1d71e7dd19.js

  打開后搜索“password”,首先是通過使用 JQuery 中的 #id 選擇器將 id 為“password”的元素賦值給變數 x,如下圖:

  

  之后要獲取密碼輸入框中的內容就要使用 x.val() 方法,因而可以搜索 x.val(),并找到如下代碼部分:

  

   其中 RSAUtils.pwdEncode(x.val()) 就是獲取密碼內容并進行加密的,然后還將加密后的結果寫入到了密碼框內,之后用 v.serialize() 對引數進行格式化并復制給變數 t,再使用 Ajax 發送 POST 請求,請求的 url 就是登錄頁面的 url + “?” + 時間戳,data 引數的值就是 t 的值,通過斷點除錯可以看到 t 的值就是請求中所攜帶引數的值,截圖如下:

   我們現在已經知道密碼加密的方法就是 RSAUtils.pwdEncode(),搜索“pwdEncode”可以找到如下代碼部分:

  

   將加密代碼背景關系部分都復制下來,并作了一點更改,一是增加 var window = this 用于定義 window,二是定義 encrypt 方法用于呼叫加密函式,完整的 JS 代碼如下:

var window = this;
!function (e) {
    function t(i) {
        var e = u
            , t = e.biDivideByRadixPower(i, this.k - 1)
            , s = e.biMultiply(t, this.mu)
            , n = e.biDivideByRadixPower(s, this.k + 1)
            , o = e.biModuloByRadixPower(i, this.k + 1)
            , r = e.biMultiply(n, this.modulus)
            , a = e.biModuloByRadixPower(r, this.k + 1)
            , l = e.biSubtract(o, a);
        l.isNeg && (l = e.biAdd(l, this.bkplus1));
        for (var d = e.biCompare(l, this.modulus) >= 0; d;)
            l = e.biSubtract(l, this.modulus),
                d = e.biCompare(l, this.modulus) >= 0;
        return l
    }

    function s(i, e) {
        var t = u.biMultiply(i, e);
        return this.modulo(t)
    }

    function n(i, e) {
        var t = new b;
        t.digits[0] = 1;
        for (var s = i, n = e; ;) {
            if (0 != (1 & n.digits[0]) && (t = this.multiplyMod(t, s)),
                n = u.biShiftRight(n, 1),
            0 == n.digits[0] && 0 == u.biHighIndex(n))
                break;
            s = this.multiplyMod(s, s)
        }
        return t
    }

    function o(i) {
        for (var e = "", t = 0; t < i; t++)
            e += Math.floor(10 * Math.random());
        return e
    }

    var r, a, l, d, u = e.RSAUtils || {}, c = 16, h = c, f = 65536, m = f >>> 1, p = f * f, g = f - 1,
        b = e.BigInt = function (i) {
            "boolean" == typeof i && 1 == i ? this.digits = null : this.digits = a.slice(0),
                this.isNeg = !1
        }
    ;
    u.setMaxDigits = function (i) {
        r = i,
            a = new Array(r);
        for (var e = 0; e < a.length; e++)
            a[e] = 0;
        l = new b,
            d = new b,
            d.digits[0] = 1
    }
        ,
        u.setMaxDigits(20);
    var v = 15;
    u.biFromNumber = function (i) {
        var e = new b;
        e.isNeg = i < 0,
            i = Math.abs(i);
        for (var t = 0; i > 0;)
            e.digits[t++] = i & g,
                i = Math.floor(i / f);
        return e
    }
    ;
    var w = u.biFromNumber(1e15);
    u.biFromDecimal = function (i) {
        for (var e, t = "-" == i.charAt(0), s = t ? 1 : 0; s < i.length && "0" == i.charAt(s);)
            ++s;
        if (s == i.length)
            e = new b;
        else {
            var n = i.length - s
                , o = n % v;
            for (0 == o && (o = v),
                     e = u.biFromNumber(Number(i.substr(s, o))),
                     s += o; s < i.length;)
                e = u.biAdd(u.biMultiply(e, w), u.biFromNumber(Number(i.substr(s, v)))),
                    s += v;
            e.isNeg = t
        }
        return e
    }
        ,
        u.biCopy = function (i) {
            var e = new b((!0));
            return e.digits = i.digits.slice(0),
                e.isNeg = i.isNeg,
                e
        }
        ,
        u.reverseStr = function (i) {
            for (var e = "", t = i.length - 1; t > -1; --t)
                e += i.charAt(t);
            return e
        }
    ;
    var x = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
    u.biToString = function (i, e) {
        var t = new b;
        t.digits[0] = e;
        for (var s = u.biDivideModulo(i, t), n = x[s[1].digits[0]]; 1 == u.biCompare(s[0], l);)
            s = u.biDivideModulo(s[0], t),
                digit = s[1].digits[0],
                n += x[s[1].digits[0]];
        return (i.isNeg ? "-" : "") + u.reverseStr(n)
    }
        ,
        u.biToDecimal = function (i) {
            var e = new b;
            e.digits[0] = 10;
            for (var t = u.biDivideModulo(i, e), s = String(t[1].digits[0]); 1 == u.biCompare(t[0], l);)
                t = u.biDivideModulo(t[0], e),
                    s += String(t[1].digits[0]);
            return (i.isNeg ? "-" : "") + u.reverseStr(s)
        }
    ;
    var y = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
    u.digitToHex = function (e) {
        var t = 15
            , s = "";
        for (i = 0; i < 4; ++i)
            s += y[e & t],
                e >>>= 4;
        return u.reverseStr(s)
    }
        ,
        u.biToHex = function (i) {
            for (var e = "", t = (u.biHighIndex(i),
                u.biHighIndex(i)); t > -1; --t)
                e += u.digitToHex(i.digits[t]);
            return e
        }
        ,
        u.charToHex = function (i) {
            var e, t = 48, s = t + 9, n = 97, o = n + 25, r = 65, a = 90;
            return e = i >= t && i <= s ? i - t : i >= r && i <= a ? 10 + i - r : i >= n && i <= o ? 10 + i - n : 0
        }
        ,
        u.hexToDigit = function (i) {
            for (var e = 0, t = Math.min(i.length, 4), s = 0; s < t; ++s)
                e <<= 4,
                    e |= u.charToHex(i.charCodeAt(s));
            return e
        }
        ,
        u.biFromHex = function (i) {
            for (var e = new b, t = i.length, s = t, n = 0; s > 0; s -= 4,
                ++n)
                e.digits[n] = u.hexToDigit(i.substr(Math.max(s - 4, 0), Math.min(s, 4)));
            return e
        }
        ,
        u.biFromString = function (i, e) {
            var t = "-" == i.charAt(0)
                , s = t ? 1 : 0
                , n = new b
                , o = new b;
            o.digits[0] = 1;
            for (var r = i.length - 1; r >= s; r--) {
                var a = i.charCodeAt(r)
                    , l = u.charToHex(a)
                    , d = u.biMultiplyDigit(o, l);
                n = u.biAdd(n, d),
                    o = u.biMultiplyDigit(o, e)
            }
            return n.isNeg = t,
                n
        }
        ,
        u.biDump = function (i) {
            return (i.isNeg ? "-" : "") + i.digits.join(" ")
        }
        ,
        u.biAdd = function (i, e) {
            var t;
            if (i.isNeg != e.isNeg)
                e.isNeg = !e.isNeg,
                    t = u.biSubtract(i, e),
                    e.isNeg = !e.isNeg;
            else {
                t = new b;
                for (var s, n = 0, o = 0; o < i.digits.length; ++o)
                    s = i.digits[o] + e.digits[o] + n,
                        t.digits[o] = s % f,
                        n = Number(s >= f);
                t.isNeg = i.isNeg
            }
            return t
        }
        ,
        u.biSubtract = function (i, e) {
            var t;
            if (i.isNeg != e.isNeg)
                e.isNeg = !e.isNeg,
                    t = u.biAdd(i, e),
                    e.isNeg = !e.isNeg;
            else {
                t = new b;
                var s, n;
                n = 0;
                for (var o = 0; o < i.digits.length; ++o)
                    s = i.digits[o] - e.digits[o] + n,
                        t.digits[o] = s % f,
                    t.digits[o] < 0 && (t.digits[o] += f),
                        n = 0 - Number(s < 0);
                if (n == -1) {
                    n = 0;
                    for (var o = 0; o < i.digits.length; ++o)
                        s = 0 - t.digits[o] + n,
                            t.digits[o] = s % f,
                        t.digits[o] < 0 && (t.digits[o] += f),
                            n = 0 - Number(s < 0);
                    t.isNeg = !i.isNeg
                } else
                    t.isNeg = i.isNeg
            }
            return t
        }
        ,
        u.biHighIndex = function (i) {
            for (var e = i.digits.length - 1; e > 0 && 0 == i.digits[e];)
                --e;
            return e
        }
        ,
        u.biNumBits = function (i) {
            var e, t = u.biHighIndex(i), s = i.digits[t], n = (t + 1) * h;
            for (e = n; e > n - h && 0 == (32768 & s); --e)
                s <<= 1;
            return e
        }
        ,
        u.biMultiply = function (i, e) {
            for (var t, s, n, o = new b, r = u.biHighIndex(i), a = u.biHighIndex(e), l = 0; l <= a; ++l) {
                for (t = 0,
                         n = l,
                         j = 0; j <= r; ++j,
                         ++n)
                    s = o.digits[n] + i.digits[j] * e.digits[l] + t,
                        o.digits[n] = s & g,
                        t = s >>> c;
                o.digits[l + r + 1] = t
            }
            return o.isNeg = i.isNeg != e.isNeg,
                o
        }
        ,
        u.biMultiplyDigit = function (i, e) {
            var t, s, n;
            result = new b,
                t = u.biHighIndex(i),
                s = 0;
            for (var o = 0; o <= t; ++o)
                n = result.digits[o] + i.digits[o] * e + s,
                    result.digits[o] = n & g,
                    s = n >>> c;
            return result.digits[1 + t] = s,
                result
        }
        ,
        u.arrayCopy = function (i, e, t, s, n) {
            for (var o = Math.min(e + n, i.length), r = e, a = s; r < o; ++r,
                ++a)
                t[a] = i[r]
        }
    ;
    var C = [0, 32768, 49152, 57344, 61440, 63488, 64512, 65024, 65280, 65408, 65472, 65504, 65520, 65528, 65532, 65534, 65535];
    u.biShiftLeft = function (i, e) {
        var t = Math.floor(e / h)
            , s = new b;
        u.arrayCopy(i.digits, 0, s.digits, t, s.digits.length - t);
        for (var n = e % h, o = h - n, r = s.digits.length - 1, a = r - 1; r > 0; --r,
            --a)
            s.digits[r] = s.digits[r] << n & g | (s.digits[a] & C[n]) >>> o;
        return s.digits[0] = s.digits[r] << n & g,
            s.isNeg = i.isNeg,
            s
    }
    ;
    var S = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535];
    u.biShiftRight = function (i, e) {
        var t = Math.floor(e / h)
            , s = new b;
        u.arrayCopy(i.digits, t, s.digits, 0, i.digits.length - t);
        for (var n = e % h, o = h - n, r = 0, a = r + 1; r < s.digits.length - 1; ++r,
            ++a)
            s.digits[r] = s.digits[r] >>> n | (s.digits[a] & S[n]) << o;
        return s.digits[s.digits.length - 1] >>>= n,
            s.isNeg = i.isNeg,
            s
    }
        ,
        u.biMultiplyByRadixPower = function (i, e) {
            var t = new b;
            return u.arrayCopy(i.digits, 0, t.digits, e, t.digits.length - e),
                t
        }
        ,
        u.biDivideByRadixPower = function (i, e) {
            var t = new b;
            return u.arrayCopy(i.digits, e, t.digits, 0, t.digits.length - e),
                t
        }
        ,
        u.biModuloByRadixPower = function (i, e) {
            var t = new b;
            return u.arrayCopy(i.digits, 0, t.digits, 0, e),
                t
        }
        ,
        u.biCompare = function (i, e) {
            if (i.isNeg != e.isNeg)
                return 1 - 2 * Number(i.isNeg);
            for (var t = i.digits.length - 1; t >= 0; --t)
                if (i.digits[t] != e.digits[t])
                    return i.isNeg ? 1 - 2 * Number(i.digits[t] > e.digits[t]) : 1 - 2 * Number(i.digits[t] < e.digits[t]);
            return 0
        }
        ,
        u.biDivideModulo = function (i, e) {
            var t, s, n = u.biNumBits(i), o = u.biNumBits(e), r = e.isNeg;
            if (n < o)
                return i.isNeg ? (t = u.biCopy(d),
                    t.isNeg = !e.isNeg,
                    i.isNeg = !1,
                    e.isNeg = !1,
                    s = biSubtract(e, i),
                    i.isNeg = !0,
                    e.isNeg = r) : (t = new b,
                    s = u.biCopy(i)),
                    [t, s];
            t = new b,
                s = i;
            for (var a = Math.ceil(o / h) - 1, l = 0; e.digits[a] < m;)
                e = u.biShiftLeft(e, 1),
                    ++l,
                    ++o,
                    a = Math.ceil(o / h) - 1;
            s = u.biShiftLeft(s, l),
                n += l;
            for (var c = Math.ceil(n / h) - 1, v = u.biMultiplyByRadixPower(e, c - a); u.biCompare(s, v) != -1;)
                ++t.digits[c - a],
                    s = u.biSubtract(s, v);
            for (var w = c; w > a; --w) {
                var x = w >= s.digits.length ? 0 : s.digits[w]
                    , y = w - 1 >= s.digits.length ? 0 : s.digits[w - 1]
                    , C = w - 2 >= s.digits.length ? 0 : s.digits[w - 2]
                    , S = a >= e.digits.length ? 0 : e.digits[a]
                    , $ = a - 1 >= e.digits.length ? 0 : e.digits[a - 1];
                x == S ? t.digits[w - a - 1] = g : t.digits[w - a - 1] = Math.floor((x * f + y) / S);
                for (var I = t.digits[w - a - 1] * (S * f + $), k = x * p + (y * f + C); I > k;)
                    --t.digits[w - a - 1],
                        I = t.digits[w - a - 1] * (S * f | $),
                        k = x * f * f + (y * f + C);
                v = u.biMultiplyByRadixPower(e, w - a - 1),
                    s = u.biSubtract(s, u.biMultiplyDigit(v, t.digits[w - a - 1])),
                s.isNeg && (s = u.biAdd(s, v),
                    --t.digits[w - a - 1])
            }
            return s = u.biShiftRight(s, l),
                t.isNeg = i.isNeg != r,
            i.isNeg && (t = r ? u.biAdd(t, d) : u.biSubtract(t, d),
                e = u.biShiftRight(e, l),
                s = u.biSubtract(e, s)),
            0 == s.digits[0] && 0 == u.biHighIndex(s) && (s.isNeg = !1),
                [t, s]
        }
        ,
        u.biDivide = function (i, e) {
            return u.biDivideModulo(i, e)[0]
        }
        ,
        u.biModulo = function (i, e) {
            return u.biDivideModulo(i, e)[1]
        }
        ,
        u.biMultiplyMod = function (i, e, t) {
            return u.biModulo(u.biMultiply(i, e), t)
        }
        ,
        u.biPow = function (i, e) {
            for (var t = d, s = i; ;) {
                if (0 != (1 & e) && (t = u.biMultiply(t, s)),
                    e >>= 1,
                0 == e)
                    break;
                s = u.biMultiply(s, s)
            }
            return t
        }
        ,
        u.biPowMod = function (i, e, t) {
            for (var s = d, n = i, o = e; ;) {
                if (0 != (1 & o.digits[0]) && (s = u.biMultiplyMod(s, n, t)),
                    o = u.biShiftRight(o, 1),
                0 == o.digits[0] && 0 == u.biHighIndex(o))
                    break;
                n = u.biMultiplyMod(n, n, t)
            }
            return s
        }
        ,
        e.BarrettMu = function (i) {
            this.modulus = u.biCopy(i),
                this.k = u.biHighIndex(this.modulus) + 1;
            var e = new b;
            e.digits[2 * this.k] = 1,
                this.mu = u.biDivide(e, this.modulus),
                this.bkplus1 = new b,
                this.bkplus1.digits[this.k + 1] = 1,
                this.modulo = t,
                this.multiplyMod = s,
                this.powMod = n
        }
    ;
    var $ = function (i, t, s, n) {
        var o = u;
        this.e = o.biFromHex(i),
            this.d = o.biFromHex(t),
            this.m = o.biFromHex(s),
            this.chunkSize = 2 * o.biHighIndex(this.m),
            this.radix = 16,
            this.barrett = new e.BarrettMu(this.m),
            this.rndLen = n
    };
    u.getKeyPair = function (i, e, t, s) {
        return new $(i, e, t, s)
    }
        ,
    "undefined" == typeof e.twoDigit && (e.twoDigit = function (i) {
            return (i < 10 ? "0" : "") + String(i)
        }
    );
    var I = "00d3e5839928d17df7ad0ae809c772cd07615cc6531e49aaa2331ba80d1308d25a67f055d2e5c2e90871e779e6ac8629de1d9203333e3b3aabdb1c90dea66c23db6d6941ec89bb99a1f8e44e0a4207341a58f5e43e49f9b69bff1f3115dda47a27e67c6d4b81895a39065ca1ae278d0dfca752aac9c8ac9d0b25cdea70e17e39db"
        , k = "010001"
        , _ = "7";
    u.pwdEncode = function (i) {
        var e = u.getKeyPair(k, "", I, _);
        return u.encryptedString(e, i)
    }
        ,
        u.encryptedString = function (i, e) {
            for (var t = o(i.rndLen) + e, s = [], n = t.length, r = 0; r < n;)
                s[r] = t.charCodeAt(r),
                    r++;
            for (; s.length % i.chunkSize != 0;)
                s[r++] = 0;
            var a, l, d, c = s.length, h = "";
            for (r = 0; r < c; r += i.chunkSize) {
                for (d = new b,
                         a = 0,
                         l = r; l < r + i.chunkSize; ++a)
                    d.digits[a] = s[l++],
                        d.digits[a] += s[l++] << 8;
                var f = i.barrett.powMod(d, i.e)
                    , m = 16 == i.radix ? u.biToHex(f) : u.biToString(f, i.radix);
                h += m + " "
            }
            return h.substring(0, h.length - 1)
        }
        ,
        u.decryptedString = function (i, e) {
            var t, s, n, o = e.split(" "), r = "";
            for (t = 0; t < o.length; ++t) {
                var a;
                for (a = 16 == i.radix ? u.biFromHex(o[t]) : u.biFromString(o[t], i.radix),
                         n = i.barrett.powMod(a, i.d),
                         s = 0; s <= u.biHighIndex(n); ++s)
                    r += String.fromCharCode(255 & n.digits[s], n.digits[s] >> 8)
            }
            return 0 == r.charCodeAt(r.length - 1) && (r = r.substring(0, r.length - 1)),
                r
        }
        ,
        u.setMaxDigits(130),
        e.RSAUtils = u
}(window);


function encrypt(pwd) {
    return RSAUtils.pwdEncode(pwd);
}

3.驗證碼code

  我們可以發現引數中 code 的值就是驗證碼的內容,通過查看元素可以得到其驗證碼圖片的地址為:https://www.xiaoniu88.com/user/captcha,

  既然有了驗證碼圖片的地址,我們就能夠請求并將圖片下載下來,就能夠得到登錄所需的驗證碼來了,下面就是請求驗證碼圖片的地址并將圖片下載到本地的代碼:

 1 def get_captcha():
 2     url = "https://www.xiaoniu88.com/user/captcha"
 3     headers = {
 4         "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;"
 5                   "q=0.8,application/signed-exchange;v=b3;q=0.9",
 6         "Accept-Encoding": "gzip, deflate, br",
 7         "Accept-Language": "zh-CN,zh;q=0.9","Cache-Control": "max-age=0","Connection": "keep-alive",
 8         "Cookie": "_ga=GA1.2.1575428040.1593311456; _gid=GA1.2.390668910.1593311456; Hm_lvt_7226b8c4"
 9                   "8cd07619c7a9ebd471d9d589=1593311456; SESSIONID=486a67f0-85e9-4c92-8bbf-35f5fe7438f9; sr=33127"
10                   "1.43.11.3.101.54.204.169.0.33.20.15.07; Hm_lpvt_7226b8c48cd07619c7a9ebd471d9d589=1593329691",
11         "Host": "www.xiaoniu88.com",
12         "Referer": "https://www.xiaoniu88.com/user/login",
13         "Sec-Fetch-Dest": "document",
14         "Sec-Fetch-Mode": "navigate",
15         "Sec-Fetch-Site": "none",
16         "Sec-Fetch-User": "?1",
17         "Upgrade-Insecure-Requests": "1",
18         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
19                       "Chrome/83.0.4103.116 Safari/537.36"
20     }
21     res = requests.get(url, headers=headers, stream=True)
22     if res.status_code == 200:
23         with open("captcha.jpg", "wb") as f:
24             f.write(res.content)
25     else:
26         print("狀態碼:{},請求驗證碼出錯,終止程式!".format(res.status_code))
27         exit()

  圖片下載下來之后,如果是人工識別驗證碼再輸入內容,一是使用起來并不方便,二是會出現驗證碼過期的情況,所以推薦使用打碼平臺進行識別,最后將回傳的結果加入到請求引數中,

 

三、模擬登錄

1.獲取 token

  由前面分析可知兩個 token 的值就是兩個隱藏的 input 標簽的 value,因而我們只需要使用 lxml 進行決議就能得到了,獲取 token 的代碼如下:

 1 def get_token(self):
 2     """
 3     獲取token
 4     :return:
 5     """
 6     res = requests.get(self.url, headers=self.headers)
 7     if res.status_code == 200:
 8         et = etree.HTML(res.text)
 9         token_name = et.xpath('//*[@id="ooh.token.name"]/@value')[0]
10         token_value = https://www.cnblogs.com/TM0831/p/et.xpath('//*[@id="ooh.token.value"]/@value')[0]
11         return token_name, token_value
12     print("狀態碼:{},請求頁面出錯,終止程式!".format(res.status_code))
13     exit()

2.加密password

  使用 JS 進行加密的代碼已經有了,現在只需要使用 execjs 模塊進行呼叫即可,使用方法如下:

with open("encrypt.js", "r", encoding="utf-8") as f:
    ctx = execjs.compile(f.read())
password = ctx.call("encrypt", password)

3.識別驗證碼

  驗證碼的識別可以通過打碼平臺來完成,例如超級鷹,使用 Python 進行呼叫的示例代碼如下:

 1 import requests
 2 from hashlib import md5
 3 
 4 
 5 class CJYClient(object):
 6     def __init__(self, username, password, soft_id):
 7         self.username = username
 8         self.password = md5(password.encode('utf8')).hexdigest()
 9         self.soft_id = soft_id
10         self.base_params = {
11             'user': self.username,
12             'pass2': self.password,
13             'softid': self.soft_id,
14         }
15         self.headers = {
16             'Connection': 'Keep-Alive',
17             'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
18         }
19 
20     def PostPic(self, im, codetype):
21         """
22         im: 圖片位元組
23         codetype: 題目型別 參考 http://www.chaojiying.com/price.html
24         """
25         params = {
26             'codetype': codetype,
27         }
28         params.update(self.base_params)
29         files = {'userfile': ('ccc.jpg', im)}
30         r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=https://www.cnblogs.com/TM0831/p/params, files=files,
31                           headers=self.headers)
32         return r.json()
33 
34     def ReportError(self, im_id):
35         """
36         im_id:報錯題目的圖片ID
37         """
38         params = {
39             'id': im_id,
40         }
41         params.update(self.base_params)
42         r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=https://www.cnblogs.com/TM0831/p/params, headers=self.headers)
43         return r.json()
44 
45 
46 def use_cjy(filename):
47     username = ""  # 用戶名
48     password = ""  # 密碼
49     app_id = ""  # 軟體ID
50     cjy = CJYClient(username, password, app_id)  # 用戶中心>>軟體ID
51     im = open(filename, 'rb').read()  # 本地圖片檔案路徑
52     return cjy.PostPic(im, 1006)  # 1006->驗證碼型別

  其中用戶名、密碼和軟體 ID 都需要自行填寫,使用時只需要將本地驗證碼圖片檔案的路徑傳入到 use_cjy() 方法中即可,就會回傳識別的結果,

4.模擬登錄

  模擬登錄的主函式如下,登錄請求所回傳的結果是 JSON 格式,其中 resultCode 欄位的值為0表示登錄成功,為其他值則表示登錄失敗,具體失敗原因可以在網頁原始碼中進行查看,這里不做處理:

 1 def login(self):
 2     """
 3     登錄方法
 4     :return:
 5     """
 6     url = self.url + "?" + str(int(time.time()) * 1000)
 7     token = self.get_token()
 8     self.get_captcha()
 9     captcha = use_cjy("captcha.jpg")
10     if captcha["err_no"]:
11         print("驗證碼識別出錯,終止程式!")
12         exit()
13     data =https://www.cnblogs.com/TM0831/p/ {
14         "ooh.token.name": token[0],
15         "ooh.token.value": token[1],
16         "username": self.username,
17         "password": self.encrypt(),
18         "code": captcha["pic_str"]
19     }
20     res = requests.post(url, headers=self.headers, data=https://www.cnblogs.com/TM0831/p/data)
21     try:
22         if res.json()["resultCode"] == 0:
23             print("登錄成功!")
24         else:
25             print("登錄失敗!")
26     except Exception as e:
27         print(e)

 

完整代碼已上傳到 GitHub!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/107517.html

標籤:Python

上一篇:Python應用基礎-根據指定檔案生成XML

下一篇:Python資料分析幫你清晰的了解整理員工們的作業效率和整體滿意度

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more