Home Request
1, no codes
2, a verification code to
The second request
We can see that, when the captcha a first transmission request response when show_captcha is False, this code is not required; if you need Ture login codes,
Further captcha will immediately send a second request, the response can be obtained img_base64, i.e., the encrypted image.
3、
Should be that the data we need
We need to see the data example, the signature is encrypted, so we need to look at is what the hell signature
Js come together can crawl through an encrypted part
Attach Source
const jsdom = require("jsdom"); const { JSDOM } = jsdom; const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`); window = dom.window; document = window.document; XMLHttpRequest = window.XMLHttpRequest; "use strict"; function t(e) { return (t = "function" == typeof Symbol && "symbol" == typeof Symbol.A ? function(e) { return typeof e } : function(e) { return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e } )(e) } Object.defineProperty(exports, "__esModule", { value: !0 }); var A = "2.0" , __g = {}; function s() {} function i(e) { this.t = (2048 & e) >> 11, this.s = (1536 & e) >> 9, this.i = 511 & e, this.h = 511 & e } function h(e) { this.s = (3072 & e) >> 10, this.h = 1023 & e } function a(e) { this.a = (3072 & e) >> 10, this.c = (768 & e) >> 8, this.n = (192 & e) >> 6, this.t = 63 & e } function c(e) { this.s = e >> 10 & 3, this.i = 1023 & e } function n() {} function e(e) { this.a = (3072 & e) >> 10, this.c = (768 & e) >> 8, this.n = (192 & e) >> 6, this.t = 63 & e } function o(e) { this.h = (4095 & e) >> 2, this.t = 3 & e } function r(e) { this.s = e >> 10 & 3, this.i = e >> 2 & 255, this.t = 3 & e } s.prototype.e = function(e) { e.o = !1 } , i.prototype.e = function(e) { switch (this.t) { case 0: e.r[this.s] = this.i; break; case 1: e.r[this.s] = e.k[this.h] } } , h.prototype.e = function(e) { e.k[this.h] = e.r[this.s] } , a.prototype.e = function(e) { switch (this.t) { case 0: e.r[this.a] = e.r[this.c] + e.r[this.n]; break; case 1: e.r[this.a] = e.r[this.c] - e.r[this.n]; break; case 2: e.r[this.a] = e.r[this.c] * e.r[this.n]; break; case 3: e.r[this.a] = e.r[this.c] / e.r[this.n]; break; case 4: e.r[this.a] = e.r[this.c] % e.r[this.n]; break; case 5: e.r[this.a] = e.r[this.c] == e.r[this.n]; break; case 6: e.r[this.a] = e.r[this.c] >= e.r[this.n]; break; case 7: e.r[this.a] = e.r[this.c] || e.r[this.n]; break; case 8: e.r[this.a] = e.r[this.c] && e.r[this.n]; break; case 9: e.r[this.a] = e.r[this.c] !== e.r[this.n]; break; case 10: e.r[this.a] = t(e.r[this.c]); break; case 11: e.r[this.a] = e.r[this.c]in e.r[this.n]; break; case 12: e.r[this.a] = e.r[this.c] > e.r[this.n]; break; case 13: e.r[this.a] = -e.r[this.c]; break; case 14: e.r[this.a] = e.r[this.c] < e.r[this.n]; break; case 15: e.r[this.a] = e.r[this.c] & e.r[this.n]; break; case 16: e.r[this.a] = e.r[this.c] ^ e.r[this.n]; break; case 17: e.r[this.a] = e.r[this.c] << e.r[this.n]; break; case 18: e.r[this.a] = e.r[this.c] >>> e.r[this.n]; break; case 19: e.r[this.a] = e.r[this.c] | e.r[this.n]; break; case 20: e.r[this.a] = !e.r[this.c] } } , c.prototype.e = function(e) { e.Q.push(e.C), e.B.push(e.k), e.C = e.r[this.s], e.k = []; for (var t = 0; t < this.i; t++) e.k.unshift(e.f.pop()); e.g.push(e.f), e.f = [] } , n.prototype.e = function(e) { e.C = e.Q.pop(), e.k = e.B.pop(), e.f = e.g.pop() } , e.prototype.e = function(e) { switch (this.t) { case 0: e.u = e.r[this.a] >= e.r[this.c]; break; case 1: e.u = e.r[this.a] <= e.r[this.c]; break; case 2: e.u = e.r[this.a] > e.r[this.c]; break; case 3: e.u = e.r[this.a] < e.r[this.c]; break; case 4: e.u = e.r[this.a] == e.r[this.c]; break; case 5: e.u = e.r[this.a] != e.r[this.c]; break; case 6: e.u = e.r[this.a]; break; case 7: e.u = !e.r[this.a] } } , o.prototype.e = function(e) { switch (this.t) { case 0: e.C = this.h; break; case 1: e.u && (e.C = this.h); break; case 2: e.u || (e.C = this.h); break; case 3: e.C = this.h, e.w = null } e.u = !1 } , r.prototype.e = function(e) { switch (this.t) { case 0: for (var t = [], n = 0; n < this.i; n++) t.unshift(e.f.pop()); e.r[3] = e.r[this.s](t[0], t[1]); break; case 1: for (var r = e.f.pop(), i = [], o = 0; o < this.i; o++) i.unshift(e.f.pop()); e.r[3] = e.r[this.s][r](i[0], i[1]); break; case 2: for (var a = [], s = 0; s < this.i; s++) a.unshift(e.f.pop()); e.r[3] = new e.r[this.s](a[0],a[1]) } } ; var k = function(e) { for (var t = 66, n = [], r = 0; r < e.length; r++) { var i = 24 ^ e.charCodeAt(r) ^ t; n.push(String.fromCharCode(i)), t = i } return n.join("") }; function Q(e) { this.t = (4095 & e) >> 10, this.s = (1023 & e) >> 8, this.i = 1023 & e, this.h = 63 & e } function C(e) { this.t = (4095 & e) >> 10, this.a = (1023 & e) >> 8, this.c = (255 & e) >> 6 } function B(e) { this.s = (3072 & e) >> 10, this.h = 1023 & e } function f(e) { this.h = 4095 & e } function g(e) { this.s = (3072 & e) >> 10 } function u(e) { this.h = 4095 & e } function w(e) { this.t = (3840 & e) >> 8, this.s = (192 & e) >> 6, this.i = 63 & e } function G() { this.r = [0, 0, 0, 0], this.C = 0, this.Q = [], this.k = [], this.B = [], this.f = [], this.g = [], this.u = !1, this.G = [], this.b = [], this.o = !1, this.w = null, this.U = null, this.F = [], this.R = 0, this.J = { 0: s, 1: i, 2: h, 3: a, 4: c, 5: n, 6: e, 7: o, 8: r, 9: Q, 10: C, 11: B, 12: f, 13: g, 14: u, 15: w } } Q.prototype.e = function(e) { switch (this.t) { case 0: e.f.push(e.r[this.s]); break; case 1: e.f.push(this.i); break; case 2: e.f.push(e.k[this.h]); break; case 3: e.f.push(k(e.b[this.h])) } } , C.prototype.e = function(A) { switch (this.t) { case 0: var t = A.f.pop(); A.r[this.a] = A.r[this.c][t]; break; case 1: var s = A.f.pop() , i = A.f.pop(); A.r[this.c][s] = i; break; case 2: var h = A.f.pop(); A.r[this.a] = eval(h) } } , B.prototype.e = function(e) { e.r[this.s] = k(e.b[this.h]) } , f.prototype.e = function(e) { e.w = this.h } , g.prototype.e = function(e) { throw e.r[this.s] } , u.prototype.e = function(e) { var t = this , n = [0]; e.k.forEach(function(e) { n.push(e) }); var r = function(r) { var i = new G; return i.k = n, i.k[0] = r, i.v(e.G, t.h, e.b, e.F), i.r[3] }; r.toString = function() { return "() { [native code] }" } , e.r[3] = r } , w.prototype.e = function(e) { switch (this.t) { case 0: for (var t = {}, n = 0; n < this.i; n++) { var r = e.f.pop(); t[e.f.pop()] = r } e.r[this.s] = t; break; case 1: for (var i = [], o = 0; o < this.i; o++) i.unshift(e.f.pop()); e.r[this.s] = i } } , G.prototype.D = function(e) { for (var t = window.atob(e), n = t.charCodeAt(0) << 8 | t.charCodeAt(1), r = [], i = 2; i < n + 2; i += 2) r.push(t.charCodeAt(i) << 8 | t.charCodeAt(i + 1)); this.G = r; for (var o = [], a = n + 2; a < t.length; ) { var s = t.charCodeAt(a) << 8 | t.charCodeAt(a + 1) , c = t.slice(a + 2, a + 2 + s); o.push(c), a += s + 2 } this.b = o } , G.prototype.v = function(e, t, n) { for (t = t || 0, n = n || [], this.C = t, "string" == typeof e ? this.D(e) : (this.G = e, this.b = n), this.o = !0, this.R = Date.now(); this.o; ) { var r = this.G[this.C++]; if ("number" != typeof r) break; var i = Date.now(); if (500 < i - this.R) return; this.R = i; try { this.e(r) } catch (e) { this.U = e, this.w && (this.C = this.w) } } } , G.prototype.e = function(e) { var t = (61440 & e) >> 12; new this.J[t](e).e(this) } , "undefined" != typeof window && (new G).v("AxjgB5MAnACoAJwBpAAAABAAIAKcAqgAMAq0AzRJZAZwUpwCqACQACACGAKcBKAAIAOcBagAIAQYAjAUGgKcBqFAuAc5hTSHZAZwqrAIGgA0QJEAJAAYAzAUGgOcCaFANRQ0R2QGcOKwChoANECRACQAsAuQABgDnAmgAJwMgAGcDYwFEAAzBmAGcSqwDhoANECRACQAGAKcD6AAGgKcEKFANEcYApwRoAAxB2AGcXKwEhoANECRACQAGAKcE6AAGgKcFKFANEdkBnGqsBUaADRAkQAkABgCnBagAGAGcdKwFxoANECRACQAGAKcGKAAYAZx+rAZGgA0QJEAJAAYA5waoABgBnIisBsaADRAkQAkABgCnBygABoCnB2hQDRHZAZyWrAeGgA0QJEAJAAYBJwfoAAwFGAGcoawIBoANECRACQAGAOQALAJkAAYBJwfgAlsBnK+sCEaADRAkQAkABgDkACwGpAAGAScH4AJbAZy9rAiGgA0QJEAJACwI5AAGAScH6AAkACcJKgAnCWgAJwmoACcJ4AFnA2MBRAAMw5gBnNasCgaADRAkQAkABgBEio0R5EAJAGwKSAFGACcKqAAEgM0RCQGGAYSATRFZAZzshgAtCs0QCQAGAYSAjRFZAZz1hgAtCw0QCQAEAAgB7AtIAgYAJwqoAASATRBJAkYCRIANEZkBnYqEAgaBxQBOYAoBxQEOYQ0giQKGAmQABgAnC6ABRgBGgo0UhD/MQ8zECALEAgaBxQBOYAoBxQEOYQ0gpEAJAoYARoKNFIQ/zEPkAAgChgLGgkUATmBkgAaAJwuhAUaCjdQFAg5kTSTJAsQCBoHFAE5gCgHFAQ5hDSCkQAkChgBGgo0UhD/MQ+QACAKGAsaCRQCOYGSABoAnC6EBRoKN1AUEDmRNJMkCxgFGgsUPzmPkgAaCJwvhAU0wCQFGAUaCxQGOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQMOZISPzZPkQAaCJwvhAU0wCQFGAUaCxQSOZISPzZPkQAaCJwvhAU0wCQFGAkSAzRBJAlz/B4FUAAAAwUYIAAIBSITFQkTERwABi0GHxITAAAJLwMSGRsXHxMZAAk0Fw8HFh4NAwUABhU1EBceDwAENBcUEAAGNBkTGRcBAAFKAAkvHg4PKz4aEwIAAUsACDIVHB0QEQ4YAAsuAzs7AAoPKToKDgAHMx8SGQUvMQABSAALORoVGCQgERcCAxoACAU3ABEXAgMaAAsFGDcAERcCAxoUCgABSQAGOA8LGBsPAAYYLwsYGw8AAU4ABD8QHAUAAU8ABSkbCQ4BAAFMAAktCh8eDgMHCw8AAU0ADT4TGjQsGQMaFA0FHhkAFz4TGjQsGQMaFA0FHhk1NBkCHgUbGBEPAAFCABg9GgkjIAEmOgUHDQ8eFSU5DggJAwEcAwUAAUMAAUAAAUEADQEtFw0FBwtdWxQTGSAACBwrAxUPBR4ZAAkqGgUDAwMVEQ0ACC4DJD8eAx8RAAQ5GhUYAAFGAAAABjYRExELBAACWhgAAVoAQAg/PTw0NxcQPCQ5C3JZEBs9fkcnDRcUAXZia0Q4EhQgXHojMBY3MWVCNT0uDhMXcGQ7AUFPHigkQUwQFkhaAkEACjkTEQspNBMZPC0ABjkTEQsrLQ=="); var b = function(e) { return __g._encrypt(encodeURIComponent(e)) } exports.ENCRYPT_VERSION = A, exports.default = b
import base64 import hmac import time from ctypes import * from hashlib import sha1 from urllib.parse import urlencode import execjs from requests_html import HTMLSession from http.cookiejar import LWPCookieJar import requests # session = HTMLSession() # requests.session() # session.cookies = LWPCookieJar() # session.cookies.save('1.txt') # session.cookies.load('1.txt') # session.request() # 云打码平台开发者文档调用的接口 YDMApi = windll.LoadLibrary(r'D:\my way\个人代码\spider\知乎\yundamaAPI-x64.dll') appId = 9250 # 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得! appKey = b'11cd5fea5bcddb99b5a2886ae480f7a2' # username = b'yxp_ynx' password = b'yxp_ynx' codetype = 1004 # 分配30个字节存放识别结果 result = c_char_p(b" ") # 识别超时时间 单位:秒 timeout = 60 # 验证码文件路径 filename = b'captcha.png' class Spider(): def __init__(self): self.session = HTMLSession() # 验证码访问请求 self.captacha_api = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=en' self.home_page = 'https://www.zhihu.com/signin?next=%2F' self.sign_in_api = 'https://www.zhihu.com/api/v3/oauth/sign_in' self.header = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36' } self.captcha = '' self.signature = '' # 获取cookies def get_first_cookie(self): self.session.get(url=self.home_page,headers=self.header) def deal_captcha(self): while True: r = self.session.get(url=self.captacha_api, headers=self.header).json() # 能获得show_captcha则为图片验证码登陆 if r.get('show_captcha'): r = self.session.put(self.captacha_api, headers= self.header).json() # 获得加密图片 img_base64 = r.get('img_base64') # 获取图片验证按数据 img_content = base64.b64decode(img_base64) # 图片写入文件 with open ('captcha.png','wb') as f: f.write(img_content) # 调用大码品平台接口,解读验证码 YDMApi.YDM_EasyDecodeByPath(username, password, appId, appKey, filename, codetype, timeout, result) self.captcha = result.value.decode('utf-8') # 拿到验证码,发送post请求 r = self.session.post(url=self.captacha_api, headers=self.header, data={'input_text':self.captcha}).json() if r.get('success'): print('验证码输入成功') break else: print('失败重试') # signature请求数据 def get_signature(self): obj = hmac.new(b'd1b964811afb40118a12068ff74a12f4',digestmod=sha1) obj.update(b'password') obj.update(b'c3cef7c66a1843f8b3a9e6a1e3160e20') obj.update(b'com.zhihu.web') obj.update(str(int(time.time() * 1000)).encode('utf-8')) self.signature = obj.hexdigest() # 登陆发送数据 def sign_in(self): data = { 'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20', 'grant_type': 'password', 'timestamp': int(time.time() * 1000), 'source': 'com.zhihu.web', 'signature': self.signature, 'username': '+8618896530856', 'password': 'a-new-world', 'captcha': self.captcha, 'lang': 'en', 'utm_source': '', 'ref_source': 'other_https://www.zhihu.com/signin?next=%2F', } # 带上js加密算法 with open('知乎加密.js', 'rt',encoding='utf-8') as f: js_code = f.read() js_obj = execjs.compile(js_code, cwd='node_modules') # 必须要转成字典类型 res = js_obj.call('b', urlencode(data)) # cnpm install jsdom 用于js的一个包 # 带上请求头 header = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36', 'x-zse-83': '3_2.0', 'content-type': 'application/x-www-form-urlencoded', } self.session.post(url=self.sign_in_api, headers=header, data=res) r = self.session.get(url=r'https://www.zhihu.com/', headers=self.header) print(r.text) def run(self): self.get_first_cookie() self.deal_captcha() self.get_signature() self.sign_in() if __name__ == '__main__': zhihu = Spider() zhihu.run() ''' 在加密js文件必须加上 const jsdom = require("jsdom"); const { JSDOM } = jsdom; const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`); window = dom.window; document = window.document; XMLHttpRequest = window.XMLHttpRequest; '''