上次爬取网易云音乐,折腾js调试了好久,难受。。。。今天继续练练手,研究下知乎登陆,让痛苦更猛烈些。
1.简单分析
很容易就发现登陆的url=“https://www.zhihu.com/api/v3/oauth/sign\_in”,post方法提交,需要的请求头和表单数据如下两图,请求头中有一个特殊的x-xsrftoken,表单数据为加密后的一长串字符窜,因此需要构造这两个值即可。


2. 获取 x-xsrftoken值
首先是这个特殊的x-xsrftoken,发现通过访问url="https://www.zhihu.com/",返回的cookies里面能拿到(会自动重定向,需要禁止重定向拿到requests.get(url,headers=headers,allow\_redirects=False)),代码如下:
1headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",}def get_xsrf(headers): 2 url="https://www.zhihu.com/" 3 r = requests.get(url,headers=headers,allow_redirects=False) #禁止重定向时,cookies里面有xsrf参数 4 xsrf = r.cookies["_xsrf"]
3. 构造表单数据
然后就是表单数据的构造和加密了, 根据前辈们的提示,提交url为url=“https://www.zhihu.com/api/v3/oauth/sign\_in”,一般表单会和末尾部分/oauth/sign\_in有关系,于是在js文件里面搜索sign\_in时,发现了下面的API,通过添加断点,点击登录,然后执行到断点处时,看到了如下的表单数据。变换不同账号试了下,发现只有captcha,signature,timestamp三个值在改变,其他参数不变。很明显,captcha为验证码,timestamp为时间戳(注意是13位),signature也像一个加密值,接下来就是寻找这几个值构造表单了。
表单数据:

3.1 构造signature
对于signature,在js文件中搜索signature,发现了下面的signature关键字,同样打断点,发现signature是采用hmac对四个数据加密后的结果;加密方 法为sha1,salt值如下,然后加密的参数依次是e=“password”, u="c3cef7c66a1843f8b3a9e6a1e3160e20"(就是clientId), source="com.zhihu.web", n为13为 时间戳。用python实现代码如下:
1def get_signature(grantType,clientId,source,timestamp): 2 h = hmac.new("d1b964811afb40118a12068ff74a12f4","",hashlib.sha1) 3 h.update(grantType+clientId+source+str(timestamp)) 4 return h.hexdigest()

3**.2 构造captcha**
然后是处理验证码captcha参数,发现有三种情况:
1. 不需要验证码,captcha=""
2. 请求验证码的url为"https://www.zhihu.com/api/v3/oauth/captcha?lang=cn",返回为汉字图片,需要点击图片中倒立的汉字,captcha为坐标值
3.请求验证码的url为"https://www.zhihu.com/api/v3/oauth/captcha?lang=en",返回英文字母图片,输入图片中英文字符即可,captcha为英文字符
验证码的请求和处理流程如下:
首先向上述两个验证码请求url中任一个发送get请求,如果返回{show_captcha:False},不需要验证码,captcha="",直接返回即可;如果返回{show_captcha:True},则需要验证码,继续向该url发送put请求(需要第一步的cookie),服务器会返回base64编码的验证码图片,利用base64解码写入文件即为验证码图片。打开图片,根据要求输入验证码或点击图片即为captcha的值,这里需要先携带cookie和验证码值,向服务器发送post请求,返回success才表示验证成功。比较特殊的是中文验证码处理,验证码的值为几组坐标值,如下第二张图片所示,可以利用matplotlib.pyplot模块来获取图片点击的坐标值(注意提交结果为实际点击坐标的一半)。
验证码:

验证码结果返回:

验证码处理的代码如下:

1def get_captcha(lang,headers): 2 if lang=="cn": 3 api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=cn" 4 else: 5 api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=en" 6 7 ret = requests.get(api,headers=headers) 8 cookies = ret.cookies 9 show_captcha = re.search("true",ret.text) 10 captcha="" 11 if show_captcha: 12 img_res = requests.put(api,headers=headers,cookies=cookies) #得带上第一步的cookie,否则返回,{u'code': 120002, u'name': u'ERR_CAPSION_TICKET_NOT_FOUND'} 13 img_json = json.loads(img_res.text) 14 img_data = img_json["img_base64"].replace("\n","") 15 with open("captcha.jpg","wb") as i: 16 i.write(base64.b64decode(img_data)) 17 img = Image.open("captcha.jpg") 18 if lang=="cn": 19 plt.imshow(img) 20 print("点击图片中所有倒立的汉字,在命令行中按回车键提交") 21 points = plt.ginput(7) #阻塞点击七次后返回(或者中途点击回车键返回),返回包含坐标组的列表,格式:[(44.661290322580641, 49.951612903225794)] 22 captcha = json.dumps({ 23 "img_size":[200,44], 24 "input_points":[[i[0]/2,i[1]/2] for i in points] #获取的坐标得除2 25 }) 26 27 else: 28 img_thread = threading.Thread(target=img.show) 29 img_thread.setDaemon(True) 30 img_thread.start() 31 captcha = raw_input("请输入图片里的验证码:") #python 2.7 32 r = requests.post(api,headers=headers,data={"input_text":captcha},cookies=cookies) #先提交验证码结果 33 print(r.text) 34 return captcha,cookies
验证码处理
4. 加密表单数据
拿到上述表单需要的值后,剩下的就是对表单数据进行加密了,搜索了下encrypt,找到了如下的js代码,通过打断点,看到了下图中e的值,和表单中的参数一模一样,可以确定为加密方法,简单研究了下js代码,实在看不懂。。。。谷歌了下大佬们的解决方案(见文末参考),发现需要将加密方法(28853行大括号截止处,对应function)拷贝出来,利用execjs模块在python中执行js代码即可。需要注意的是,拷贝出来的加密方法是在浏览器中运行的,需要去掉window,document等对象处理成node.js环境下运行的js代码,然后安装node.js,将execjs模块的运行环境设置为node.js即可以运行了。下面为处理后的encrypt代码和python加密方法:

1function s(e) { 2 return (s = "function" == typeof Symbol && "symbol" == typeof Symbol.t ? function(e) { 3 return typeof e 4 } 5 : function(e) { 6 return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e 7 } 8 )(e) 9} 10function i() {} 11function h(e) { 12 this.s = (2048 & e) >> 11, 13 this.i = (1536 & e) >> 9, 14 this.h = 511 & e, 15 this.A = 511 & e 16} 17function A(e) { 18 this.i = (3072 & e) >> 10, 19 this.A = 1023 & e 20} 21function n(e) { 22 this.n = (3072 & e) >> 10, 23 this.e = (768 & e) >> 8, 24 this.a = (192 & e) >> 6, 25 this.s = 63 & e 26} 27function e(e) { 28 this.i = e >> 10 & 3, 29 this.h = 1023 & e 30} 31function a() {} 32function c(e) { 33 this.n = (3072 & e) >> 10, 34 this.e = (768 & e) >> 8, 35 this.a = (192 & e) >> 6, 36 this.s = 63 & e 37} 38function o(e) { 39 this.A = (4095 & e) >> 2, 40 this.s = 3 & e 41} 42function r(e) { 43 this.i = e >> 10 & 3, 44 this.h = e >> 2 & 255, 45 this.s = 3 & e 46} 47function k(e) { 48 this.s = (4095 & e) >> 10, 49 this.i = (1023 & e) >> 8, 50 this.h = 1023 & e, 51 this.A = 63 & e 52} 53function B(e) { 54 this.s = (4095 & e) >> 10, 55 this.n = (1023 & e) >> 8, 56 this.e = (255 & e) >> 6 57} 58function f(e) { 59 this.i = (3072 & e) >> 10, 60 this.A = 1023 & e 61} 62function u(e) { 63 this.A = 4095 & e 64} 65function C(e) { 66 this.i = (3072 & e) >> 10 67} 68function b(e) { 69 this.A = 4095 & e 70} 71function g(e) { 72 this.s = (3840 & e) >> 8, 73 this.i = (192 & e) >> 6, 74 this.h = 63 & e 75} 76function G() { 77 this.c = [0, 0, 0, 0], 78 this.o = 0, 79 this.r = [], 80 this.k = [], 81 this.B = [], 82 this.f = [], 83 this.u = [], 84 this.C = !1, 85 this.b = [], 86 this.g = [], 87 this.G = !1, 88 this.Q = null, 89 this.R = null, 90 this.w = [], 91 this.x = 0, 92 this.D = { 93 0: i, 94 1: h, 95 2: A, 96 3: n, 97 4: e, 98 5: a, 99 6: c, 100 7: o, 101 8: r, 102 9: k, 103 10: B, 104 11: f, 105 12: u, 106 13: C, 107 14: b, 108 15: g 109 } 110} 111Object.defineProperty(exports, "__esModule", { 112 value: !0 113}); 114var t = "1.1" 115 , __g = {}; 116i.prototype.M = function(e) { 117 e.G = !1 118} 119, 120h.prototype.M = function(e) { 121 switch (this.s) { 122 case 0: 123 e.c[this.i] = this.h; 124 break; 125 case 1: 126 e.c[this.i] = e.k[this.A] 127 } 128} 129, 130A.prototype.M = function(e) { 131 e.k[this.A] = e.c[this.i] 132} 133, 134n.prototype.M = function(e) { 135 switch (this.s) { 136 case 0: 137 e.c[this.n] = e.c[this.e] + e.c[this.a]; 138 break; 139 case 1: 140 e.c[this.n] = e.c[this.e] - e.c[this.a]; 141 break; 142 case 2: 143 e.c[this.n] = e.c[this.e] * e.c[this.a]; 144 break; 145 case 3: 146 e.c[this.n] = e.c[this.e] / e.c[this.a]; 147 break; 148 case 4: 149 e.c[this.n] = e.c[this.e] % e.c[this.a]; 150 break; 151 case 5: 152 e.c[this.n] = e.c[this.e] == e.c[this.a]; 153 break; 154 case 6: 155 e.c[this.n] = e.c[this.e] >= e.c[this.a]; 156 break; 157 case 7: 158 e.c[this.n] = e.c[this.e] || e.c[this.a]; 159 break; 160 case 8: 161 e.c[this.n] = e.c[this.e] && e.c[this.a]; 162 break; 163 case 9: 164 e.c[this.n] = e.c[this.e] !== e.c[this.a]; 165 break; 166 case 10: 167 e.c[this.n] = s(e.c[this.e]); 168 break; 169 case 11: 170 e.c[this.n] = e.c[this.e]in e.c[this.a]; 171 break; 172 case 12: 173 e.c[this.n] = e.c[this.e] > e.c[this.a]; 174 break; 175 case 13: 176 e.c[this.n] = -e.c[this.e]; 177 break; 178 case 14: 179 e.c[this.n] = e.c[this.e] < e.c[this.a]; 180 break; 181 case 15: 182 e.c[this.n] = e.c[this.e] & e.c[this.a]; 183 break; 184 case 16: 185 e.c[this.n] = e.c[this.e] ^ e.c[this.a]; 186 break; 187 case 17: 188 e.c[this.n] = e.c[this.e] << e.c[this.a]; 189 break; 190 case 18: 191 e.c[this.n] = e.c[this.e] >>> e.c[this.a]; 192 break; 193 case 19: 194 e.c[this.n] = e.c[this.e] | e.c[this.a] 195 } 196} 197, 198e.prototype.M = function(e) { 199 e.r.push(e.o), 200 e.B.push(e.k), 201 e.o = e.c[this.i], 202 e.k = []; 203 for (var t = 0; t < this.h; t++) 204 e.k.unshift(e.f.pop()); 205 e.u.push(e.f), 206 e.f = [] 207} 208, 209a.prototype.M = function(e) { 210 e.o = e.r.pop(), 211 e.k = e.B.pop(), 212 e.f = e.u.pop() 213} 214, 215c.prototype.M = function(e) { 216 switch (this.s) { 217 case 0: 218 e.C = e.c[this.n] >= e.c[this.e]; 219 break; 220 case 1: 221 e.C = e.c[this.n] <= e.c[this.e]; 222 break; 223 case 2: 224 e.C = e.c[this.n] > e.c[this.e]; 225 break; 226 case 3: 227 e.C = e.c[this.n] < e.c[this.e]; 228 break; 229 case 4: 230 e.C = e.c[this.n] == e.c[this.e]; 231 break; 232 case 5: 233 e.C = e.c[this.n] != e.c[this.e]; 234 break; 235 case 6: 236 e.C = e.c[this.n]; 237 break; 238 case 7: 239 e.C = !e.c[this.n] 240 } 241} 242, 243o.prototype.M = function(e) { 244 switch (this.s) { 245 case 0: 246 e.o = this.A; 247 break; 248 case 1: 249 e.C && (e.o = this.A); 250 break; 251 case 2: 252 e.C || (e.o = this.A); 253 break; 254 case 3: 255 e.o = this.A, 256 e.Q = null 257 } 258 e.C = !1 259} 260, 261r.prototype.M = function(e) { 262 switch (this.s) { 263 case 0: 264 for (var t = [], n = 0; n < this.h; n++) 265 t.unshift(e.f.pop()); 266 e.c[3] = e.c[this.i](t[0], t[1]); 267 break; 268 case 1: 269 for (var r = e.f.pop(), o = [], i = 0; i < this.h; i++) 270 o.unshift(e.f.pop()); 271 e.c[3] = e.c[this.i][r](o[0], o[1]); 272 break; 273 case 2: 274 for (var a = [], c = 0; c < this.h; c++) 275 a.unshift(e.f.pop()); 276 e.c[3] = new e.c[this.i](a[0],a[1]) 277 } 278} 279, 280k.prototype.M = function(e) { 281 switch (this.s) { 282 case 0: 283 e.f.push(e.c[this.i]); 284 break; 285 case 1: 286 e.f.push(this.h); 287 break; 288 case 2: 289 e.f.push(e.k[this.A]); 290 break; 291 case 3: 292 e.f.push(e.g[this.A]) 293 } 294} 295, 296B.prototype.M = function(t) { 297 switch (this.s) { 298 case 0: 299 var s = t.f.pop(); 300 t.c[this.n] = t.c[this.e][s]; 301 break; 302 case 1: 303 var i = t.f.pop() 304 , h = t.f.pop(); 305 t.c[this.e][i] = h; 306 break; 307 case 2: 308 var A = t.f.pop(); 309 if(A === 'window') { 310 A = { 311 encodeURIComponent: function (url) { 312 return encodeURIComponent(url) 313 } 314 } 315 } else if (A === 'navigator') { 316 A = { 317 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' + 318 '(KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' 319 } 320 } 321 t.c[this.n] = eval(A) 322 } 323} 324, 325f.prototype.M = function(e) { 326 e.c[this.i] = e.g[this.A] 327} 328, 329u.prototype.M = function(e) { 330 e.Q = this.A 331} 332, 333C.prototype.M = function(e) { 334 throw e.c[this.i] 335} 336, 337b.prototype.M = function(e) { 338 var t = this 339 , n = [0]; 340 e.k.forEach(function(e) { 341 n.push(e) 342 }); 343 var r = function(r) { 344 var o = new G; 345 return o.k = n, 346 o.k[0] = r, 347 o.J(e.b, t.A, e.g, e.w), 348 o.c[3] 349 }; 350 r.toString = function() { 351 return "() { [native code] }" 352 } 353 , 354 e.c[3] = r 355} 356, 357g.prototype.M = function(e) { 358 switch (this.s) { 359 case 0: 360 for (var t = {}, n = 0; n < this.h; n++) { 361 var r = e.f.pop(); 362 t[e.f.pop()] = r 363 } 364 e.c[this.i] = t; 365 break; 366 case 1: 367 for (var o = [], i = 0; i < this.h; i++) 368 o.unshift(e.f.pop()); 369 e.c[this.i] = o 370 } 371} 372, 373G.prototype.v = function(e) { 374 for (var t = Buffer.from(e, 'base64').toString('binary'), n = [], r = 0; r < t.length - 1; r += 2) 375 n.push(t.charCodeAt(r) << 8 | t.charCodeAt(r + 1)); 376 this.b = n 377} 378, 379G.prototype.y = function(e) { 380 for (var t = Buffer.from(e, 'base64').toString('binary'), n = 66, r = [], o = 0; o < t.length; o++) { 381 var i = 24 ^ t.charCodeAt(o) ^ n; 382 r.push(String.fromCharCode(i)), 383 n = i 384 } 385 return r.join("") 386} 387, 388G.prototype.F = function(e) { 389 var t = this; 390 this.g = e.map(function(e) { 391 return "string" == typeof e ? t.y(e) : e 392 }) 393} 394, 395G.prototype.J = function(e, t, n) { 396 for (t = t || 0, 397 n = n || [], 398 this.o = t, 399 "string" == typeof e ? (this.F(n), 400 this.v(e)) : (this.b = e, 401 this.g = n), 402 this.G = !0, 403 this.x = Date.now(); this.G; ) { 404 var r = this.b[this.o++]; 405 if ("number" != typeof r) 406 break; 407 var o = Date.now(); 408 if (500 < o - this.x) 409 return; 410 this.x = o; 411 try { 412 this.M(r) 413 } catch (e) { 414 if (this.R = e, 415 !this.Q) 416 throw "execption at " + this.o + ": " + e; 417 this.o = this.Q 418 } 419 } 420} 421, 422G.prototype.M = function(e) { 423 var t = (61440 & e) >> 12; 424 new this.D[t](e).M(this) 425} 426, 427(new G).J("4AeTAJwAqACcAaQAAAAYAJAAnAKoAJwDgAWTACwAnAKoACACGAESOTRHkQAkAbAEIAMYAJwFoAASAzREJAQYBBIBNEVkBnCiGAC0BjRAJAAYBBICNEVkBnDGGAC0BzRAJACwCJAAnAmoAJwKoACcC4ABnAyMBRAAMwZgBnESsA0aADRAkQAkABgCnA6gABoCnA+hQDRHGAKcEKAAMQdgBnFasBEaADRAkQAkABgCnBKgABoCnBOhQDRHZAZxkrAUGgA0QJEAJAAYApwVoABgBnG6sBYaADRAkQAkABgCnBegAGAGceKwGBoANECRACQAnAmoAJwZoABgBnIOsBoaADRAkQAkABgCnBugABoCnByhQDRHZAZyRrAdGgA0QJEAJAAQACAFsB4gBhgAnAWgABIBNEEkBxgHEgA0RmQGdJoQCBoFFAE5gCgFFAQ5hDSCJAgYB5AAGACcH4AFGAEaCDRSEP8xDzMQIAkQCBoFFAE5gCgFFAQ5hDSCkQAkCBgBGgg0UhD/MQ+QACAIGAkaBxQBOYGSABoAnB+EBRoIN1AUCDmRNJMkCRAIGgUUATmAKAUUBDmENIKRACQIGAEaCDRSEP8xD5AAIAgYCRoHFAI5gZIAGgCcH4QFGgg3UBQQOZE0kyQJGAMaCRQ/OY+SABoGnCCEBTTAJAMYAxoJFAY5khI/Nk+RABoGnCCEBTTAJAMYAxoJFAw5khI/Nk+RABoGnCCEBTTAJAMYAxoJFBI5khI/Nk+RABoGnCCEBTTAJAMYBxIDNEEkB3JsHgNQAA==", 0, ["BRgg", "BSITFQkTERw=", "LQYfEhMA", "PxMVFBMZKB8DEjQaBQcZExMC", "", "NhETEQsE", "Whg=", "Wg==", "MhUcHRARDhg=", "NBcPBxYeDQMF", "Lx4ODys+GhMC", "LgM7OwAKDyk6Cg4=", "Mx8SGQUvMQ==", "SA==", "ORoVGCQgERcCAxo=", "BTcAERcCAxo=", "BRg3ABEXAgMaFAo=", "SQ==", "OA8LGBsP", "GC8LGBsP", "Tg==", "PxAcBQ==", "Tw==", "KRsJDgE=", "TA==", "LQofHg4DBwsP", "TQ==", "PhMaNCwZAxoUDQUeGQ==", "PhMaNCwZAxoUDQUeGTU0GQIeBRsYEQ8=", "Qg==", "BWpUGxkfGRsZFxkbGR8ZGxkHGRsZHxkbGRcZG1MbGR8ZGxkXGRFpGxkfGRsZFxkbGR8ZGxkHGRsZHxkbGRcZGw==", "ORMRCyk0Exk8LQ==", "ORMRCyst"]); 428var Q = function(e) { 429 return __g._encrypt(e) 430};
encrypt.js

1#准备表单数据 2 timestamp = int(1000*time.time()) 3 data_dict = { 4 "captcha": "", 5 "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20", 6 "grant_type": "password", 7 "lang": "en", 8 "password": "你的密码", 9 "ref_source": "homepage", 10 "signature": "", 11 "source": "com.zhihu.web", 12 "timestamp": timestamp, 13 "username": "你的用户名", 14 "utm_source": "", 15 } 16#将表单数据加密 17 with open("encrypt.js",'r') as f: 18 #os.environ["EXECJS_RUNTIME"] = "Node" 19 # os.environ["NODE_PATH"] = r"D:\nodejs\node_modules" 20 #print execjs.get().name 21 js = execjs.compile(f.read().decode("utf-8")) #传入unicode字符 22 data = js.call(u'Q',urlencode(data_dict)) #data_dict为表单数据
表单加密

5. 加密数据提交
拿到所有数据后,可以提交post请求了,需要注意的有三个地方:
1.表单中参数的大小写和拼写要注意了 (我开始将client_id写成了clientId,报错找不到client_id参数)
2. 请求头headers必须需要"content-type":",'x-zse-83',"x-xsrftoken"三个参数
3. 需要带上cookie,最主要的是cookie中的cookies["capsion_ticket"]不能少,可以利用获取验证码时返回的cookie
最后完整代码如下:

1#coding:utf-8 2 3#登陆并爬取知乎 4 5import requests 6import time 7import hmac 8import hashlib 9from urllib import urlencode 10import execjs #安装PyExecJS模块 11import os 12import json 13import re 14import base64 15from PIL import Image 16import matplotlib.pyplot as plt 17import threading 18 19 20 21def get_signature(grantType,clientId,source,timestamp): 22 h = hmac.new("d1b964811afb40118a12068ff74a12f4","",hashlib.sha1) 23 h.update(grantType+clientId+source+str(timestamp)) 24 return h.hexdigest() 25 26def get_captcha(lang,headers): 27 if lang=="cn": 28 api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=cn" 29 else: 30 api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=en" 31 32 ret = requests.get(api,headers=headers) 33 cookies = ret.cookies 34 show_captcha = re.search("true",ret.text) 35 captcha="" 36 if show_captcha: 37 img_res = requests.put(api,headers=headers,cookies=cookies) #得带上第一步的cookie,否则返回,{u'code': 120002, u'name': u'ERR_CAPSION_TICKET_NOT_FOUND'} 38 img_json = json.loads(img_res.text) 39 img_data = img_json["img_base64"].replace("\n","") 40 with open("captcha.jpg","wb") as i: 41 i.write(base64.b64decode(img_data)) 42 img = Image.open("captcha.jpg") 43 if lang=="cn": 44 plt.imshow(img) 45 print("点击图片中所有倒立的汉字,在命令行中按回车键提交") 46 points = plt.ginput(7) #阻塞点击七次后返回(或者中途点击回车键返回),返回包含坐标组的列表,格式:[(44.661290322580641, 49.951612903225794)] 47 captcha = json.dumps({ 48 "img_size":[200,44], 49 "input_points":[[i[0]/2,i[1]/2] for i in points] #获取的坐标得除2 50 }) 51 52 else: 53 img_thread = threading.Thread(target=img.show) 54 img_thread.setDaemon(True) 55 img_thread.start() 56 captcha = raw_input("请输入图片里的验证码:") #python 2.7 57 r = requests.post(api,headers=headers,data={"input_text":captcha},cookies=cookies) #先提交验证码结果 58 print(r.text) 59 return captcha,cookies 60def get_xsrf(headers): 61 url="https://www.zhihu.com/" 62 r = requests.get(url,headers=headers,allow_redirects=False) #禁止重定向时,cookies里面有xsrf参数 63 xsrf = r.cookies["_xsrf"] 64 65def login(lang): 66 headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",} 67 68 #准备表单数据 69 timestamp = int(1000*time.time()) 70 data_dict = { 71 "captcha": "", 72 "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20", 73 "grant_type": "password", 74 "lang": "en", 75 "password": "xxxxx", 76 "ref_source": "homepage", 77 "signature": "", 78 "source": "com.zhihu.web", 79 "timestamp": timestamp, 80 "username": "xxxxxxxx", 81 "utm_source": "", 82 } 83 data_dict["signature"] = get_signature(data_dict["grant_type"],data_dict["client_id"],data_dict["source"],timestamp) 84 data_dict["captcha"],cookies = get_captcha(lang,headers) 85 86 #将表单数据加密 87 with open("encrypt.js",'r') as f: 88 #os.environ["EXECJS_RUNTIME"] = "Node" 89 # os.environ["NODE_PATH"] = r"D:\nodejs\node_modules" 90 #print execjs.get().name 91 js = execjs.compile(f.read().decode("utf-8")) #传入unicode字符 92 data = js.call(u'Q',urlencode(data_dict)) #data_dict为表单数据 93 print(data) 94 95 #准备请求头 96 xsrf = get_xsrf(headers) 97 header={ 98 "content-type":"application/x-www-form-urlencoded", 99 #"Referer":"https://www.zhihu.com/signin", 100 'x-zse-83': '3_1.1', 101 "x-xsrftoken":xsrf, 102 } 103 headers.update(header) 104 sign_url = "https://www.zhihu.com/api/v3/oauth/sign_in" 105 response = requests.post(url=sign_url,headers=headers,data=data,cookies=cookies) #cookies["capsion_ticket"]不能少 106 print(response.status_code) 107 print(response.text) 108 109if __name__=="__main__": 110 login("cn") #也可以为en
知乎登陆

1function s(e) { 2 return (s = "function" == typeof Symbol && "symbol" == typeof Symbol.t ? function(e) { 3 return typeof e 4 } 5 : function(e) { 6 return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e 7 } 8 )(e) 9} 10function i() {} 11function h(e) { 12 this.s = (2048 & e) >> 11, 13 this.i = (1536 & e) >> 9, 14 this.h = 511 & e, 15 this.A = 511 & e 16} 17function A(e) { 18 this.i = (3072 & e) >> 10, 19 this.A = 1023 & e 20} 21function n(e) { 22 this.n = (3072 & e) >> 10, 23 this.e = (768 & e) >> 8, 24 this.a = (192 & e) >> 6, 25 this.s = 63 & e 26} 27function e(e) { 28 this.i = e >> 10 & 3, 29 this.h = 1023 & e 30} 31function a() {} 32function c(e) { 33 this.n = (3072 & e) >> 10, 34 this.e = (768 & e) >> 8, 35 this.a = (192 & e) >> 6, 36 this.s = 63 & e 37} 38function o(e) { 39 this.A = (4095 & e) >> 2, 40 this.s = 3 & e 41} 42function r(e) { 43 this.i = e >> 10 & 3, 44 this.h = e >> 2 & 255, 45 this.s = 3 & e 46} 47function k(e) { 48 this.s = (4095 & e) >> 10, 49 this.i = (1023 & e) >> 8, 50 this.h = 1023 & e, 51 this.A = 63 & e 52} 53function B(e) { 54 this.s = (4095 & e) >> 10, 55 this.n = (1023 & e) >> 8, 56 this.e = (255 & e) >> 6 57} 58function f(e) { 59 this.i = (3072 & e) >> 10, 60 this.A = 1023 & e 61} 62function u(e) { 63 this.A = 4095 & e 64} 65function C(e) { 66 this.i = (3072 & e) >> 10 67} 68function b(e) { 69 this.A = 4095 & e 70} 71function g(e) { 72 this.s = (3840 & e) >> 8, 73 this.i = (192 & e) >> 6, 74 this.h = 63 & e 75} 76function G() { 77 this.c = [0, 0, 0, 0], 78 this.o = 0, 79 this.r = [], 80 this.k = [], 81 this.B = [], 82 this.f = [], 83 this.u = [], 84 this.C = !1, 85 this.b = [], 86 this.g = [], 87 this.G = !1, 88 this.Q = null, 89 this.R = null, 90 this.w = [], 91 this.x = 0, 92 this.D = { 93 0: i, 94 1: h, 95 2: A, 96 3: n, 97 4: e, 98 5: a, 99 6: c, 100 7: o, 101 8: r, 102 9: k, 103 10: B, 104 11: f, 105 12: u, 106 13: C, 107 14: b, 108 15: g 109 } 110} 111Object.defineProperty(exports, "__esModule", { 112 value: !0 113}); 114var t = "1.1" 115 , __g = {}; 116i.prototype.M = function(e) { 117 e.G = !1 118} 119, 120h.prototype.M = function(e) { 121 switch (this.s) { 122 case 0: 123 e.c[this.i] = this.h; 124 break; 125 case 1: 126 e.c[this.i] = e.k[this.A] 127 } 128} 129, 130A.prototype.M = function(e) { 131 e.k[this.A] = e.c[this.i] 132} 133, 134n.prototype.M = function(e) { 135 switch (this.s) { 136 case 0: 137 e.c[this.n] = e.c[this.e] + e.c[this.a]; 138 break; 139 case 1: 140 e.c[this.n] = e.c[this.e] - e.c[this.a]; 141 break; 142 case 2: 143 e.c[this.n] = e.c[this.e] * e.c[this.a]; 144 break; 145 case 3: 146 e.c[this.n] = e.c[this.e] / e.c[this.a]; 147 break; 148 case 4: 149 e.c[this.n] = e.c[this.e] % e.c[this.a]; 150 break; 151 case 5: 152 e.c[this.n] = e.c[this.e] == e.c[this.a]; 153 break; 154 case 6: 155 e.c[this.n] = e.c[this.e] >= e.c[this.a]; 156 break; 157 case 7: 158 e.c[this.n] = e.c[this.e] || e.c[this.a]; 159 break; 160 case 8: 161 e.c[this.n] = e.c[this.e] && e.c[this.a]; 162 break; 163 case 9: 164 e.c[this.n] = e.c[this.e] !== e.c[this.a]; 165 break; 166 case 10: 167 e.c[this.n] = s(e.c[this.e]); 168 break; 169 case 11: 170 e.c[this.n] = e.c[this.e]in e.c[this.a]; 171 break; 172 case 12: 173 e.c[this.n] = e.c[this.e] > e.c[this.a]; 174 break; 175 case 13: 176 e.c[this.n] = -e.c[this.e]; 177 break; 178 case 14: 179 e.c[this.n] = e.c[this.e] < e.c[this.a]; 180 break; 181 case 15: 182 e.c[this.n] = e.c[this.e] & e.c[this.a]; 183 break; 184 case 16: 185 e.c[this.n] = e.c[this.e] ^ e.c[this.a]; 186 break; 187 case 17: 188 e.c[this.n] = e.c[this.e] << e.c[this.a]; 189 break; 190 case 18: 191 e.c[this.n] = e.c[this.e] >>> e.c[this.a]; 192 break; 193 case 19: 194 e.c[this.n] = e.c[this.e] | e.c[this.a] 195 } 196} 197, 198e.prototype.M = function(e) { 199 e.r.push(e.o), 200 e.B.push(e.k), 201 e.o = e.c[this.i], 202 e.k = []; 203 for (var t = 0; t < this.h; t++) 204 e.k.unshift(e.f.pop()); 205 e.u.push(e.f), 206 e.f = [] 207} 208, 209a.prototype.M = function(e) { 210 e.o = e.r.pop(), 211 e.k = e.B.pop(), 212 e.f = e.u.pop() 213} 214, 215c.prototype.M = function(e) { 216 switch (this.s) { 217 case 0: 218 e.C = e.c[this.n] >= e.c[this.e]; 219 break; 220 case 1: 221 e.C = e.c[this.n] <= e.c[this.e]; 222 break; 223 case 2: 224 e.C = e.c[this.n] > e.c[this.e]; 225 break; 226 case 3: 227 e.C = e.c[this.n] < e.c[this.e]; 228 break; 229 case 4: 230 e.C = e.c[this.n] == e.c[this.e]; 231 break; 232 case 5: 233 e.C = e.c[this.n] != e.c[this.e]; 234 break; 235 case 6: 236 e.C = e.c[this.n]; 237 break; 238 case 7: 239 e.C = !e.c[this.n] 240 } 241} 242, 243o.prototype.M = function(e) { 244 switch (this.s) { 245 case 0: 246 e.o = this.A; 247 break; 248 case 1: 249 e.C && (e.o = this.A); 250 break; 251 case 2: 252 e.C || (e.o = this.A); 253 break; 254 case 3: 255 e.o = this.A, 256 e.Q = null 257 } 258 e.C = !1 259} 260, 261r.prototype.M = function(e) { 262 switch (this.s) { 263 case 0: 264 for (var t = [], n = 0; n < this.h; n++) 265 t.unshift(e.f.pop()); 266 e.c[3] = e.c[this.i](t[0], t[1]); 267 break; 268 case 1: 269 for (var r = e.f.pop(), o = [], i = 0; i < this.h; i++) 270 o.unshift(e.f.pop()); 271 e.c[3] = e.c[this.i][r](o[0], o[1]); 272 break; 273 case 2: 274 for (var a = [], c = 0; c < this.h; c++) 275 a.unshift(e.f.pop()); 276 e.c[3] = new e.c[this.i](a[0],a[1]) 277 } 278} 279, 280k.prototype.M = function(e) { 281 switch (this.s) { 282 case 0: 283 e.f.push(e.c[this.i]); 284 break; 285 case 1: 286 e.f.push(this.h); 287 break; 288 case 2: 289 e.f.push(e.k[this.A]); 290 break; 291 case 3: 292 e.f.push(e.g[this.A]) 293 } 294} 295, 296B.prototype.M = function(t) { 297 switch (this.s) { 298 case 0: 299 var s = t.f.pop(); 300 t.c[this.n] = t.c[this.e][s]; 301 break; 302 case 1: 303 var i = t.f.pop() 304 , h = t.f.pop(); 305 t.c[this.e][i] = h; 306 break; 307 case 2: 308 var A = t.f.pop(); 309 if(A === 'window') { 310 A = { 311 encodeURIComponent: function (url) { 312 return encodeURIComponent(url) 313 } 314 } 315 } else if (A === 'navigator') { 316 A = { 317 'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' + 318 '(KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' 319 } 320 } 321 t.c[this.n] = eval(A) 322 } 323} 324, 325f.prototype.M = function(e) { 326 e.c[this.i] = e.g[this.A] 327} 328, 329u.prototype.M = function(e) { 330 e.Q = this.A 331} 332, 333C.prototype.M = function(e) { 334 throw e.c[this.i] 335} 336, 337b.prototype.M = function(e) { 338 var t = this 339 , n = [0]; 340 e.k.forEach(function(e) { 341 n.push(e) 342 }); 343 var r = function(r) { 344 var o = new G; 345 return o.k = n, 346 o.k[0] = r, 347 o.J(e.b, t.A, e.g, e.w), 348 o.c[3] 349 }; 350 r.toString = function() { 351 return "() { [native code] }" 352 } 353 , 354 e.c[3] = r 355} 356, 357g.prototype.M = function(e) { 358 switch (this.s) { 359 case 0: 360 for (var t = {}, n = 0; n < this.h; n++) { 361 var r = e.f.pop(); 362 t[e.f.pop()] = r 363 } 364 e.c[this.i] = t; 365 break; 366 case 1: 367 for (var o = [], i = 0; i < this.h; i++) 368 o.unshift(e.f.pop()); 369 e.c[this.i] = o 370 } 371} 372, 373G.prototype.v = function(e) { 374 for (var t = Buffer.from(e, 'base64').toString('binary'), n = [], r = 0; r < t.length - 1; r += 2) 375 n.push(t.charCodeAt(r) << 8 | t.charCodeAt(r + 1)); 376 this.b = n 377} 378, 379G.prototype.y = function(e) { 380 for (var t = Buffer.from(e, 'base64').toString('binary'), n = 66, r = [], o = 0; o < t.length; o++) { 381 var i = 24 ^ t.charCodeAt(o) ^ n; 382 r.push(String.fromCharCode(i)), 383 n = i 384 } 385 return r.join("") 386} 387, 388G.prototype.F = function(e) { 389 var t = this; 390 this.g = e.map(function(e) { 391 return "string" == typeof e ? t.y(e) : e 392 }) 393} 394, 395G.prototype.J = function(e, t, n) { 396 for (t = t || 0, 397 n = n || [], 398 this.o = t, 399 "string" == typeof e ? (this.F(n), 400 this.v(e)) : (this.b = e, 401 this.g = n), 402 this.G = !0, 403 this.x = Date.now(); this.G; ) { 404 var r = this.b[this.o++]; 405 if ("number" != typeof r) 406 break; 407 var o = Date.now(); 408 if (500 < o - this.x) 409 return; 410 this.x = o; 411 try { 412 this.M(r) 413 } catch (e) { 414 if (this.R = e, 415 !this.Q) 416 throw "execption at " + this.o + ": " + e; 417 this.o = this.Q 418 } 419 } 420} 421, 422G.prototype.M = function(e) { 423 var t = (61440 & e) >> 12; 424 new this.D[t](e).M(this) 425} 426, 427(new G).J("4AeTAJwAqACcAaQAAAAYAJAAnAKoAJwDgAWTACwAnAKoACACGAESOTRHkQAkAbAEIAMYAJwFoAASAzREJAQYBBIBNEVkBnCiGAC0BjRAJAAYBBICNEVkBnDGGAC0BzRAJACwCJAAnAmoAJwKoACcC4ABnAyMBRAAMwZgBnESsA0aADRAkQAkABgCnA6gABoCnA+hQDRHGAKcEKAAMQdgBnFasBEaADRAkQAkABgCnBKgABoCnBOhQDRHZAZxkrAUGgA0QJEAJAAYApwVoABgBnG6sBYaADRAkQAkABgCnBegAGAGceKwGBoANECRACQAnAmoAJwZoABgBnIOsBoaADRAkQAkABgCnBugABoCnByhQDRHZAZyRrAdGgA0QJEAJAAQACAFsB4gBhgAnAWgABIBNEEkBxgHEgA0RmQGdJoQCBoFFAE5gCgFFAQ5hDSCJAgYB5AAGACcH4AFGAEaCDRSEP8xDzMQIAkQCBoFFAE5gCgFFAQ5hDSCkQAkCBgBGgg0UhD/MQ+QACAIGAkaBxQBOYGSABoAnB+EBRoIN1AUCDmRNJMkCRAIGgUUATmAKAUUBDmENIKRACQIGAEaCDRSEP8xD5AAIAgYCRoHFAI5gZIAGgCcH4QFGgg3UBQQOZE0kyQJGAMaCRQ/OY+SABoGnCCEBTTAJAMYAxoJFAY5khI/Nk+RABoGnCCEBTTAJAMYAxoJFAw5khI/Nk+RABoGnCCEBTTAJAMYAxoJFBI5khI/Nk+RABoGnCCEBTTAJAMYBxIDNEEkB3JsHgNQAA==", 0, ["BRgg", "BSITFQkTERw=", "LQYfEhMA", "PxMVFBMZKB8DEjQaBQcZExMC", "", "NhETEQsE", "Whg=", "Wg==", "MhUcHRARDhg=", "NBcPBxYeDQMF", "Lx4ODys+GhMC", "LgM7OwAKDyk6Cg4=", "Mx8SGQUvMQ==", "SA==", "ORoVGCQgERcCAxo=", "BTcAERcCAxo=", "BRg3ABEXAgMaFAo=", "SQ==", "OA8LGBsP", "GC8LGBsP", "Tg==", "PxAcBQ==", "Tw==", "KRsJDgE=", "TA==", "LQofHg4DBwsP", "TQ==", "PhMaNCwZAxoUDQUeGQ==", "PhMaNCwZAxoUDQUeGTU0GQIeBRsYEQ8=", "Qg==", "BWpUGxkfGRsZFxkbGR8ZGxkHGRsZHxkbGRcZG1MbGR8ZGxkXGRFpGxkfGRsZFxkbGR8ZGxkHGRsZHxkbGRcZGw==", "ORMRCyk0Exk8LQ==", "ORMRCyst"]); 428var Q = function(e) { 429 return __g._encrypt(e) 430};
encrypt.js