上次爬取网易云音乐,折腾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)),代码如下:

headers={"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):
url="https://www.zhihu.com/"
r = requests.get(url,headers=headers,allow_redirects=False) #禁止重定向时,cookies里面有xsrf参数
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实现代码如下:

def get_signature(grantType,clientId,source,timestamp):
h = hmac.new("d1b964811afb40118a12068ff74a12f4","",hashlib.sha1)
h.update(grantType+clientId+source+str(timestamp))
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模块来获取图片点击的坐标值(注意提交结果为实际点击坐标的一半)。

验证码:

验证码结果返回:

验证码处理的代码如下:

def get_captcha(lang,headers):
if lang=="cn":
api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=cn"
else:
api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=en" ret = requests.get(api,headers=headers)
cookies = ret.cookies
show_captcha = re.search("true",ret.text)
captcha=""
if show_captcha:
img_res = requests.put(api,headers=headers,cookies=cookies) #得带上第一步的cookie,否则返回,{u'code': , u'name': u'ERR_CAPSION_TICKET_NOT_FOUND'}
img_json = json.loads(img_res.text)
img_data = img_json["img_base64"].replace("\n","")
with open("captcha.jpg","wb") as i:
i.write(base64.b64decode(img_data))
img = Image.open("captcha.jpg")
if lang=="cn":
plt.imshow(img)
print("点击图片中所有倒立的汉字,在命令行中按回车键提交")
points = plt.ginput() #阻塞点击七次后返回(或者中途点击回车键返回),返回包含坐标组的列表,格式:[(44.661290322580641, 49.951612903225794)]
captcha = json.dumps({
"img_size":[,],
"input_points":[[i[]/,i[]/] for i in points] #获取的坐标得除2
}) else:
img_thread = threading.Thread(target=img.show)
img_thread.setDaemon(True)
img_thread.start()
captcha = raw_input("请输入图片里的验证码:") #python 2.7
r = requests.post(api,headers=headers,data={"input_text":captcha},cookies=cookies) #先提交验证码结果
print(r.text)
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加密方法:

function s(e) {
return (s = "function" == typeof Symbol && "symbol" == typeof Symbol.t ? function(e) {
return typeof e
}
: function(e) {
return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
}
)(e)
}
function i() {}
function h(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e,
this.A = & e
}
function A(e) {
this.i = ( & e) >> ,
this.A = & e
}
function n(e) {
this.n = ( & e) >> ,
this.e = ( & e) >> ,
this.a = ( & e) >> ,
this.s = & e
}
function e(e) {
this.i = e >> & ,
this.h = & e
}
function a() {}
function c(e) {
this.n = ( & e) >> ,
this.e = ( & e) >> ,
this.a = ( & e) >> ,
this.s = & e
}
function o(e) {
this.A = ( & e) >> ,
this.s = & e
}
function r(e) {
this.i = e >> & ,
this.h = e >> & ,
this.s = & e
}
function k(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e,
this.A = & e
}
function B(e) {
this.s = ( & e) >> ,
this.n = ( & e) >> ,
this.e = ( & e) >>
}
function f(e) {
this.i = ( & e) >> ,
this.A = & e
}
function u(e) {
this.A = & e
}
function C(e) {
this.i = ( & e) >>
}
function b(e) {
this.A = & e
}
function g(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e
}
function G() {
this.c = [, , , ],
this.o = ,
this.r = [],
this.k = [],
this.B = [],
this.f = [],
this.u = [],
this.C = !,
this.b = [],
this.g = [],
this.G = !,
this.Q = null,
this.R = null,
this.w = [],
this.x = ,
this.D = {
: i,
: h,
: A,
: n,
: e,
: a,
: c,
: o,
: r,
: k,
: B,
: f,
: u,
: C,
: b,
: g
}
}
Object.defineProperty(exports, "__esModule", {
value: !
});
var t = "1.1"
, __g = {};
i.prototype.M = function(e) {
e.G = !
}
,
h.prototype.M = function(e) {
switch (this.s) {
case :
e.c[this.i] = this.h;
break;
case :
e.c[this.i] = e.k[this.A]
}
}
,
A.prototype.M = function(e) {
e.k[this.A] = e.c[this.i]
}
,
n.prototype.M = function(e) {
switch (this.s) {
case :
e.c[this.n] = e.c[this.e] + e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] - e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] * e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] / e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] % e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] == e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] >= e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] || e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] && e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] !== e.c[this.a];
break;
case :
e.c[this.n] = s(e.c[this.e]);
break;
case :
e.c[this.n] = e.c[this.e]in e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] > e.c[this.a];
break;
case :
e.c[this.n] = -e.c[this.e];
break;
case :
e.c[this.n] = e.c[this.e] < e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] & e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] ^ e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] << e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] >>> e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] | e.c[this.a]
}
}
,
e.prototype.M = function(e) {
e.r.push(e.o),
e.B.push(e.k),
e.o = e.c[this.i],
e.k = [];
for (var t = ; t < this.h; t++)
e.k.unshift(e.f.pop());
e.u.push(e.f),
e.f = []
}
,
a.prototype.M = function(e) {
e.o = e.r.pop(),
e.k = e.B.pop(),
e.f = e.u.pop()
}
,
c.prototype.M = function(e) {
switch (this.s) {
case :
e.C = e.c[this.n] >= e.c[this.e];
break;
case :
e.C = e.c[this.n] <= e.c[this.e];
break;
case :
e.C = e.c[this.n] > e.c[this.e];
break;
case :
e.C = e.c[this.n] < e.c[this.e];
break;
case :
e.C = e.c[this.n] == e.c[this.e];
break;
case :
e.C = e.c[this.n] != e.c[this.e];
break;
case :
e.C = e.c[this.n];
break;
case :
e.C = !e.c[this.n]
}
}
,
o.prototype.M = function(e) {
switch (this.s) {
case :
e.o = this.A;
break;
case :
e.C && (e.o = this.A);
break;
case :
e.C || (e.o = this.A);
break;
case :
e.o = this.A,
e.Q = null
}
e.C = !
}
,
r.prototype.M = function(e) {
switch (this.s) {
case :
for (var t = [], n = ; n < this.h; n++)
t.unshift(e.f.pop());
e.c[] = e.c[this.i](t[], t[]);
break;
case :
for (var r = e.f.pop(), o = [], i = ; i < this.h; i++)
o.unshift(e.f.pop());
e.c[] = e.c[this.i][r](o[], o[]);
break;
case :
for (var a = [], c = ; c < this.h; c++)
a.unshift(e.f.pop());
e.c[] = new e.c[this.i](a[],a[])
}
}
,
k.prototype.M = function(e) {
switch (this.s) {
case :
e.f.push(e.c[this.i]);
break;
case :
e.f.push(this.h);
break;
case :
e.f.push(e.k[this.A]);
break;
case :
e.f.push(e.g[this.A])
}
}
,
B.prototype.M = function(t) {
switch (this.s) {
case :
var s = t.f.pop();
t.c[this.n] = t.c[this.e][s];
break;
case :
var i = t.f.pop()
, h = t.f.pop();
t.c[this.e][i] = h;
break;
case :
var A = t.f.pop();
if(A === 'window') {
A = {
encodeURIComponent: function (url) {
return encodeURIComponent(url)
}
}
} else if (A === 'navigator') {
A = {
'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +
'(KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}
}
t.c[this.n] = eval(A)
}
}
,
f.prototype.M = function(e) {
e.c[this.i] = e.g[this.A]
}
,
u.prototype.M = function(e) {
e.Q = this.A
}
,
C.prototype.M = function(e) {
throw e.c[this.i]
}
,
b.prototype.M = function(e) {
var t = this
, n = [];
e.k.forEach(function(e) {
n.push(e)
});
var r = function(r) {
var o = new G;
return o.k = n,
o.k[] = r,
o.J(e.b, t.A, e.g, e.w),
o.c[]
};
r.toString = function() {
return "() { [native code] }"
}
,
e.c[] = r
}
,
g.prototype.M = function(e) {
switch (this.s) {
case :
for (var t = {}, n = ; n < this.h; n++) {
var r = e.f.pop();
t[e.f.pop()] = r
}
e.c[this.i] = t;
break;
case :
for (var o = [], i = ; i < this.h; i++)
o.unshift(e.f.pop());
e.c[this.i] = o
}
}
,
G.prototype.v = function(e) {
for (var t = Buffer.from(e, 'base64').toString('binary'), n = [], r = ; r < t.length - ; r += )
n.push(t.charCodeAt(r) << | t.charCodeAt(r + ));
this.b = n
}
,
G.prototype.y = function(e) {
for (var t = Buffer.from(e, 'base64').toString('binary'), n = , r = [], o = ; o < t.length; o++) {
var i = ^ t.charCodeAt(o) ^ n;
r.push(String.fromCharCode(i)),
n = i
}
return r.join("")
}
,
G.prototype.F = function(e) {
var t = this;
this.g = e.map(function(e) {
return "string" == typeof e ? t.y(e) : e
})
}
,
G.prototype.J = function(e, t, n) {
for (t = t || ,
n = n || [],
this.o = t,
"string" == typeof e ? (this.F(n),
this.v(e)) : (this.b = e,
this.g = n),
this.G = !,
this.x = Date.now(); this.G; ) {
var r = this.b[this.o++];
if ("number" != typeof r)
break;
var o = Date.now();
if ( < o - this.x)
return;
this.x = o;
try {
this.M(r)
} catch (e) {
if (this.R = e,
!this.Q)
throw "execption at " + this.o + ": " + e;
this.o = this.Q
}
}
}
,
G.prototype.M = function(e) {
var t = ( & e) >> ;
new this.D[t](e).M(this)
}
,
(new G).J("4AeTAJwAqACcAaQAAAAYAJAAnAKoAJwDgAWTACwAnAKoACACGAESOTRHkQAkAbAEIAMYAJwFoAASAzREJAQYBBIBNEVkBnCiGAC0BjRAJAAYBBICNEVkBnDGGAC0BzRAJACwCJAAnAmoAJwKoACcC4ABnAyMBRAAMwZgBnESsA0aADRAkQAkABgCnA6gABoCnA+hQDRHGAKcEKAAMQdgBnFasBEaADRAkQAkABgCnBKgABoCnBOhQDRHZAZxkrAUGgA0QJEAJAAYApwVoABgBnG6sBYaADRAkQAkABgCnBegAGAGceKwGBoANECRACQAnAmoAJwZoABgBnIOsBoaADRAkQAkABgCnBugABoCnByhQDRHZAZyRrAdGgA0QJEAJAAQACAFsB4gBhgAnAWgABIBNEEkBxgHEgA0RmQGdJoQCBoFFAE5gCgFFAQ5hDSCJAgYB5AAGACcH4AFGAEaCDRSEP8xDzMQIAkQCBoFFAE5gCgFFAQ5hDSCkQAkCBgBGgg0UhD/MQ+QACAIGAkaBxQBOYGSABoAnB+EBRoIN1AUCDmRNJMkCRAIGgUUATmAKAUUBDmENIKRACQIGAEaCDRSEP8xD5AAIAgYCRoHFAI5gZIAGgCcH4QFGgg3UBQQOZE0kyQJGAMaCRQ/OY+SABoGnCCEBTTAJAMYAxoJFAY5khI/Nk+RABoGnCCEBTTAJAMYAxoJFAw5khI/Nk+RABoGnCCEBTTAJAMYAxoJFBI5khI/Nk+RABoGnCCEBTTAJAMYBxIDNEEkB3JsHgNQAA==", , ["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"]);
var Q = function(e) {
return __g._encrypt(e)
};

encrypt.js

#准备表单数据
timestamp = int(*time.time())
data_dict = {
"captcha": "",
"client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
"grant_type": "password",
"lang": "en",
"password": "你的密码",
"ref_source": "homepage",
"signature": "",
"source": "com.zhihu.web",
"timestamp": timestamp,
"username": "你的用户名",
"utm_source": "",
}
#将表单数据加密
with open("encrypt.js",'r') as f:
#os.environ["EXECJS_RUNTIME"] = "Node"
# os.environ["NODE_PATH"] = r"D:\nodejs\node_modules"
#print execjs.get().name
js = execjs.compile(f.read().decode("utf-8")) #传入unicode字符
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

  最后完整代码如下:

#coding:utf-

#登陆并爬取知乎

import requests
import time
import hmac
import hashlib
from urllib import urlencode
import execjs #安装PyExecJS模块
import os
import json
import re
import base64
from PIL import Image
import matplotlib.pyplot as plt
import threading def get_signature(grantType,clientId,source,timestamp):
h = hmac.new("d1b964811afb40118a12068ff74a12f4","",hashlib.sha1)
h.update(grantType+clientId+source+str(timestamp))
return h.hexdigest() def get_captcha(lang,headers):
if lang=="cn":
api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=cn"
else:
api = "https://www.zhihu.com/api/v3/oauth/captcha?lang=en" ret = requests.get(api,headers=headers)
cookies = ret.cookies
show_captcha = re.search("true",ret.text)
captcha=""
if show_captcha:
img_res = requests.put(api,headers=headers,cookies=cookies) #得带上第一步的cookie,否则返回,{u'code': , u'name': u'ERR_CAPSION_TICKET_NOT_FOUND'}
img_json = json.loads(img_res.text)
img_data = img_json["img_base64"].replace("\n","")
with open("captcha.jpg","wb") as i:
i.write(base64.b64decode(img_data))
img = Image.open("captcha.jpg")
if lang=="cn":
plt.imshow(img)
print("点击图片中所有倒立的汉字,在命令行中按回车键提交")
points = plt.ginput() #阻塞点击七次后返回(或者中途点击回车键返回),返回包含坐标组的列表,格式:[(44.661290322580641, 49.951612903225794)]
captcha = json.dumps({
"img_size":[,],
"input_points":[[i[]/,i[]/] for i in points] #获取的坐标得除2
}) else:
img_thread = threading.Thread(target=img.show)
img_thread.setDaemon(True)
img_thread.start()
captcha = raw_input("请输入图片里的验证码:") #python 2.7
r = requests.post(api,headers=headers,data={"input_text":captcha},cookies=cookies) #先提交验证码结果
print(r.text)
return captcha,cookies
def get_xsrf(headers):
url="https://www.zhihu.com/"
r = requests.get(url,headers=headers,allow_redirects=False) #禁止重定向时,cookies里面有xsrf参数
xsrf = r.cookies["_xsrf"] def login(lang):
headers={"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",} #准备表单数据
timestamp = int(*time.time())
data_dict = {
"captcha": "",
"client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
"grant_type": "password",
"lang": "en",
"password": "xxxxx",
"ref_source": "homepage",
"signature": "",
"source": "com.zhihu.web",
"timestamp": timestamp,
"username": "xxxxxxxx",
"utm_source": "",
}
data_dict["signature"] = get_signature(data_dict["grant_type"],data_dict["client_id"],data_dict["source"],timestamp)
data_dict["captcha"],cookies = get_captcha(lang,headers) #将表单数据加密
with open("encrypt.js",'r') as f:
#os.environ["EXECJS_RUNTIME"] = "Node"
# os.environ["NODE_PATH"] = r"D:\nodejs\node_modules"
#print execjs.get().name
js = execjs.compile(f.read().decode("utf-8")) #传入unicode字符
data = js.call(u'Q',urlencode(data_dict)) #data_dict为表单数据
print(data) #准备请求头
xsrf = get_xsrf(headers)
header={
"content-type":"application/x-www-form-urlencoded",
#"Referer":"https://www.zhihu.com/signin",
'x-zse-83': '3_1.1',
"x-xsrftoken":xsrf,
}
headers.update(header)
sign_url = "https://www.zhihu.com/api/v3/oauth/sign_in"
response = requests.post(url=sign_url,headers=headers,data=data,cookies=cookies) #cookies["capsion_ticket"]不能少
print(response.status_code)
print(response.text) if __name__=="__main__":
login("cn") #也可以为en

知乎登陆

function s(e) {
return (s = "function" == typeof Symbol && "symbol" == typeof Symbol.t ? function(e) {
return typeof e
}
: function(e) {
return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
}
)(e)
}
function i() {}
function h(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e,
this.A = & e
}
function A(e) {
this.i = ( & e) >> ,
this.A = & e
}
function n(e) {
this.n = ( & e) >> ,
this.e = ( & e) >> ,
this.a = ( & e) >> ,
this.s = & e
}
function e(e) {
this.i = e >> & ,
this.h = & e
}
function a() {}
function c(e) {
this.n = ( & e) >> ,
this.e = ( & e) >> ,
this.a = ( & e) >> ,
this.s = & e
}
function o(e) {
this.A = ( & e) >> ,
this.s = & e
}
function r(e) {
this.i = e >> & ,
this.h = e >> & ,
this.s = & e
}
function k(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e,
this.A = & e
}
function B(e) {
this.s = ( & e) >> ,
this.n = ( & e) >> ,
this.e = ( & e) >>
}
function f(e) {
this.i = ( & e) >> ,
this.A = & e
}
function u(e) {
this.A = & e
}
function C(e) {
this.i = ( & e) >>
}
function b(e) {
this.A = & e
}
function g(e) {
this.s = ( & e) >> ,
this.i = ( & e) >> ,
this.h = & e
}
function G() {
this.c = [, , , ],
this.o = ,
this.r = [],
this.k = [],
this.B = [],
this.f = [],
this.u = [],
this.C = !,
this.b = [],
this.g = [],
this.G = !,
this.Q = null,
this.R = null,
this.w = [],
this.x = ,
this.D = {
: i,
: h,
: A,
: n,
: e,
: a,
: c,
: o,
: r,
: k,
: B,
: f,
: u,
: C,
: b,
: g
}
}
Object.defineProperty(exports, "__esModule", {
value: !
});
var t = "1.1"
, __g = {};
i.prototype.M = function(e) {
e.G = !
}
,
h.prototype.M = function(e) {
switch (this.s) {
case :
e.c[this.i] = this.h;
break;
case :
e.c[this.i] = e.k[this.A]
}
}
,
A.prototype.M = function(e) {
e.k[this.A] = e.c[this.i]
}
,
n.prototype.M = function(e) {
switch (this.s) {
case :
e.c[this.n] = e.c[this.e] + e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] - e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] * e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] / e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] % e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] == e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] >= e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] || e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] && e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] !== e.c[this.a];
break;
case :
e.c[this.n] = s(e.c[this.e]);
break;
case :
e.c[this.n] = e.c[this.e]in e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] > e.c[this.a];
break;
case :
e.c[this.n] = -e.c[this.e];
break;
case :
e.c[this.n] = e.c[this.e] < e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] & e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] ^ e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] << e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] >>> e.c[this.a];
break;
case :
e.c[this.n] = e.c[this.e] | e.c[this.a]
}
}
,
e.prototype.M = function(e) {
e.r.push(e.o),
e.B.push(e.k),
e.o = e.c[this.i],
e.k = [];
for (var t = ; t < this.h; t++)
e.k.unshift(e.f.pop());
e.u.push(e.f),
e.f = []
}
,
a.prototype.M = function(e) {
e.o = e.r.pop(),
e.k = e.B.pop(),
e.f = e.u.pop()
}
,
c.prototype.M = function(e) {
switch (this.s) {
case :
e.C = e.c[this.n] >= e.c[this.e];
break;
case :
e.C = e.c[this.n] <= e.c[this.e];
break;
case :
e.C = e.c[this.n] > e.c[this.e];
break;
case :
e.C = e.c[this.n] < e.c[this.e];
break;
case :
e.C = e.c[this.n] == e.c[this.e];
break;
case :
e.C = e.c[this.n] != e.c[this.e];
break;
case :
e.C = e.c[this.n];
break;
case :
e.C = !e.c[this.n]
}
}
,
o.prototype.M = function(e) {
switch (this.s) {
case :
e.o = this.A;
break;
case :
e.C && (e.o = this.A);
break;
case :
e.C || (e.o = this.A);
break;
case :
e.o = this.A,
e.Q = null
}
e.C = !
}
,
r.prototype.M = function(e) {
switch (this.s) {
case :
for (var t = [], n = ; n < this.h; n++)
t.unshift(e.f.pop());
e.c[] = e.c[this.i](t[], t[]);
break;
case :
for (var r = e.f.pop(), o = [], i = ; i < this.h; i++)
o.unshift(e.f.pop());
e.c[] = e.c[this.i][r](o[], o[]);
break;
case :
for (var a = [], c = ; c < this.h; c++)
a.unshift(e.f.pop());
e.c[] = new e.c[this.i](a[],a[])
}
}
,
k.prototype.M = function(e) {
switch (this.s) {
case :
e.f.push(e.c[this.i]);
break;
case :
e.f.push(this.h);
break;
case :
e.f.push(e.k[this.A]);
break;
case :
e.f.push(e.g[this.A])
}
}
,
B.prototype.M = function(t) {
switch (this.s) {
case :
var s = t.f.pop();
t.c[this.n] = t.c[this.e][s];
break;
case :
var i = t.f.pop()
, h = t.f.pop();
t.c[this.e][i] = h;
break;
case :
var A = t.f.pop();
if(A === 'window') {
A = {
encodeURIComponent: function (url) {
return encodeURIComponent(url)
}
}
} else if (A === 'navigator') {
A = {
'userAgent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +
'(KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
}
}
t.c[this.n] = eval(A)
}
}
,
f.prototype.M = function(e) {
e.c[this.i] = e.g[this.A]
}
,
u.prototype.M = function(e) {
e.Q = this.A
}
,
C.prototype.M = function(e) {
throw e.c[this.i]
}
,
b.prototype.M = function(e) {
var t = this
, n = [];
e.k.forEach(function(e) {
n.push(e)
});
var r = function(r) {
var o = new G;
return o.k = n,
o.k[] = r,
o.J(e.b, t.A, e.g, e.w),
o.c[]
};
r.toString = function() {
return "() { [native code] }"
}
,
e.c[] = r
}
,
g.prototype.M = function(e) {
switch (this.s) {
case :
for (var t = {}, n = ; n < this.h; n++) {
var r = e.f.pop();
t[e.f.pop()] = r
}
e.c[this.i] = t;
break;
case :
for (var o = [], i = ; i < this.h; i++)
o.unshift(e.f.pop());
e.c[this.i] = o
}
}
,
G.prototype.v = function(e) {
for (var t = Buffer.from(e, 'base64').toString('binary'), n = [], r = ; r < t.length - ; r += )
n.push(t.charCodeAt(r) << | t.charCodeAt(r + ));
this.b = n
}
,
G.prototype.y = function(e) {
for (var t = Buffer.from(e, 'base64').toString('binary'), n = , r = [], o = ; o < t.length; o++) {
var i = ^ t.charCodeAt(o) ^ n;
r.push(String.fromCharCode(i)),
n = i
}
return r.join("")
}
,
G.prototype.F = function(e) {
var t = this;
this.g = e.map(function(e) {
return "string" == typeof e ? t.y(e) : e
})
}
,
G.prototype.J = function(e, t, n) {
for (t = t || ,
n = n || [],
this.o = t,
"string" == typeof e ? (this.F(n),
this.v(e)) : (this.b = e,
this.g = n),
this.G = !,
this.x = Date.now(); this.G; ) {
var r = this.b[this.o++];
if ("number" != typeof r)
break;
var o = Date.now();
if ( < o - this.x)
return;
this.x = o;
try {
this.M(r)
} catch (e) {
if (this.R = e,
!this.Q)
throw "execption at " + this.o + ": " + e;
this.o = this.Q
}
}
}
,
G.prototype.M = function(e) {
var t = ( & e) >> ;
new this.D[t](e).M(this)
}
,
(new G).J("4AeTAJwAqACcAaQAAAAYAJAAnAKoAJwDgAWTACwAnAKoACACGAESOTRHkQAkAbAEIAMYAJwFoAASAzREJAQYBBIBNEVkBnCiGAC0BjRAJAAYBBICNEVkBnDGGAC0BzRAJACwCJAAnAmoAJwKoACcC4ABnAyMBRAAMwZgBnESsA0aADRAkQAkABgCnA6gABoCnA+hQDRHGAKcEKAAMQdgBnFasBEaADRAkQAkABgCnBKgABoCnBOhQDRHZAZxkrAUGgA0QJEAJAAYApwVoABgBnG6sBYaADRAkQAkABgCnBegAGAGceKwGBoANECRACQAnAmoAJwZoABgBnIOsBoaADRAkQAkABgCnBugABoCnByhQDRHZAZyRrAdGgA0QJEAJAAQACAFsB4gBhgAnAWgABIBNEEkBxgHEgA0RmQGdJoQCBoFFAE5gCgFFAQ5hDSCJAgYB5AAGACcH4AFGAEaCDRSEP8xDzMQIAkQCBoFFAE5gCgFFAQ5hDSCkQAkCBgBGgg0UhD/MQ+QACAIGAkaBxQBOYGSABoAnB+EBRoIN1AUCDmRNJMkCRAIGgUUATmAKAUUBDmENIKRACQIGAEaCDRSEP8xD5AAIAgYCRoHFAI5gZIAGgCcH4QFGgg3UBQQOZE0kyQJGAMaCRQ/OY+SABoGnCCEBTTAJAMYAxoJFAY5khI/Nk+RABoGnCCEBTTAJAMYAxoJFAw5khI/Nk+RABoGnCCEBTTAJAMYAxoJFBI5khI/Nk+RABoGnCCEBTTAJAMYBxIDNEEkB3JsHgNQAA==", , ["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"]);
var Q = function(e) {
return __g._encrypt(e)
};

encrypt.js

参考: https://zhuanlan.zhihu.com/p/57375111

   https://zhuanlan.zhihu.com/p/34073256

(八)爬虫之js调试(登陆知乎)的更多相关文章

  1. Python 爬虫模拟登陆知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

  2. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

  3. [转]九个Console命令,让js调试更简单

    转自:九个Console命令,让js调试更简单 一.显示信息的命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!DOCTYPE html> <html ...

  4. 【转】天啦噜!原来Chrome自带的开发者工具还能这么用!(提升JS调试能力的10个技巧)

    天啦噜!原来Chrome自带的开发者工具还能这么用! (提升JS调试能力的10个技巧)   Chrome自带开发者工具.它的功能十分丰富,包括元素.网络.安全等等.今天我们主要介绍JavaScript ...

  5. 分享几个日常调试方法让js调试更简单

    下面分享几个日常调试代码的时候在Console命令行显示你的操作,让你的js调试更简单. console显示信息的命令 在浏览器按f12在console上显示你的文本. <!DOCTYPE ht ...

  6. python爬虫scrapy框架——人工识别登录知乎倒立文字验证码和数字英文验证码(2)

    操作环境:python3 在上一文中python爬虫scrapy框架--人工识别知乎登录知乎倒立文字验证码和数字英文验证码(1)我们已经介绍了用Requests库来登录知乎,本文如果看不懂可以先看之前 ...

  7. Js调试中不得不知的Console

    在js调试中,大部分的前端人员都是采用console.log()方法来打印出调试的数据,但是很多人都不知道console这个对象有很多很实在的方法,本文就来介绍一下这些方法的使用. 一.console ...

  8. 【F12】Console命令,让js调试更简单

    Console命令,让js调试更简单 一.显示信息的命令 console.log("normal"); // 用于输出普通信息 console.info("informa ...

  9. Python爬虫—破解JS加密的Cookie

    前言 在GitHub上维护了一个代理池的项目,代理来源是抓取一些免费的代理发布网站.上午有个小哥告诉我说有个代理抓取接口不能用了,返回状态521.抱着帮人解决问题的心态去跑了一遍代码.发现果真是这样. ...

随机推荐

  1. iOS - 解决警告“ld: Warning: Directory Not Found for Option”

    有时候我们可能从项目中删除了某个目录.文件以后,编译出现警告信息: ld: warning: directory not found for option“XXXXXX” 具体类似下图: 很奇怪,为什 ...

  2. Flutter-现有iOS工程引入Flutter

    前言 Flutter 是一个很有潜力的框架,但是目前使用Flutter的APP并不算很多,相关资料并不丰富,介绍现有工程引入Flutter的相关文章也比较少.项目从零开始,引入Flutter操作比较简 ...

  3. bootstrap下拉框保持打开

    $(".dropdown-menu li").on("click", function (e) { e.stopPropagation(); }); 停止传播事 ...

  4. MUI底部导航栏切换效果

    首先是html代码: <nav class="mui-bar mui-bar-tab"> <a href="view/templates/home/ho ...

  5. kbmMW 5.10.01试用报告

    1.FileClient.SameFile 调用这个方法,当本地文件不存在时,会一直等待.跟踪代码,发现: function TkbmMWCustomFileClient.SameFileEx(Loc ...

  6. flex布局实战

    1.实现盒子的水平垂直居中 .parent{ width:200px; height:200px; display:flex; align-items: center; justify-content ...

  7. 【leetcode】637. Average of Levels in Binary Tree

    原题 Given a non-empty binary tree, return the average value of the nodes on each level in the form of ...

  8. RT-Thread--内核基础

    内核介绍 内核处于硬件层之上,内核部分包括内核库.实时内核实现. 实时内核的实现包括:对象管理.线程管理及调度器.线程间通信管理.时钟管理及内存管理等等,内核最小的资源占用情况是 3KB ROM,1. ...

  9. springboot中,使用redisTemplate操作redis

    知识点: springboot中整合redis springboot中redisTemplate的使用 redis存数据时,key出现乱码问题 一:springboot中整合redis (1)pom. ...

  10. go语言defer关键字背后的实现,语法,用法

    原文: https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.4.html ------------------------------ ...