Skip to content

Commit e40d995

Browse files
author
Luo
committed
新增 登录模块
1 parent 5a95335 commit e40d995

1 file changed

Lines changed: 227 additions & 0 deletions

File tree

auth.py

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/usr/bin/env python
2+
#-*- coding:utf-8 -*-
3+
4+
# Build-in / Std
5+
import os, sys, time, platform, random
6+
import re, json, cookielib
7+
8+
# requirements
9+
import requests, termcolor
10+
11+
try:
12+
import BeautifulSoup
13+
except:
14+
from bs4 import BeautifulSoup
15+
16+
requests = requests.Session()
17+
requests.cookies = cookielib.LWPCookieJar('cookies')
18+
try:
19+
requests.cookies.load(ignore_discard=True)
20+
except:
21+
pass
22+
23+
class Logging:
24+
flag = True
25+
26+
@staticmethod
27+
def error(msg):
28+
if Logging.flag == True:
29+
print "".join( [ termcolor.colored("ERROR", "red"), ": ", termcolor.colored(msg, "white") ] )
30+
@staticmethod
31+
def warn(msg):
32+
if Logging.flag == True:
33+
print "".join( [ termcolor.colored("WARN", "yellow"), ": ", termcolor.colored(msg, "white") ] )
34+
@staticmethod
35+
def info(msg):
36+
# attrs=['reverse', 'blink']
37+
if Logging.flag == True:
38+
print "".join( [ termcolor.colored("INFO", "magenta"), ": ", termcolor.colored(msg, "white") ] )
39+
@staticmethod
40+
def debug(msg):
41+
if Logging.flag == True:
42+
print "".join( [ termcolor.colored("DEBUG", "magenta"), ": ", termcolor.colored(msg, "white") ] )
43+
@staticmethod
44+
def success(msg):
45+
if Logging.flag == True:
46+
print "".join( [ termcolor.colored("SUCCES", "green"), ": ", termcolor.colored(msg, "white") ] )
47+
48+
# Setting Logging
49+
Logging.flag = True
50+
51+
class LoginPasswordError(Exception):
52+
def __init__(self, message):
53+
if type(message) != type("") or message == "": self.message = u"帐号密码错误"
54+
else: self.message = message
55+
Logging.error(self.message)
56+
57+
class NetworkError(Exception):
58+
def __init__(self, message):
59+
if type(message) != type("") or message == "": self.message = u"网络异常"
60+
else: self.message = message
61+
Logging.error(self.message)
62+
class AccountError(Exception):
63+
def __init__(self, message):
64+
if type(message) != type("") or message == "": self.message = u"帐号类型错误"
65+
else: self.message = message
66+
Logging.error(self.message)
67+
68+
69+
70+
71+
72+
def download_captcha():
73+
url = "http://www.zhihu.com/captcha.gif"
74+
r = requests.get(url, params={"r": random.random()} )
75+
if int(r.status_code) != 200:
76+
raise NetworkError(u"验证码请求失败")
77+
image_name = u"verify." + r.headers['content-type'].split("/")[1]
78+
open( image_name, "wb").write(r.content)
79+
"""
80+
System platform: https://docs.python.org/2/library/platform.html
81+
"""
82+
if platform.system() == "Linux":
83+
os.system("see %s &" % image_name )
84+
elif platform.system() == "Darwin":
85+
os.system("open %s &" % image_name )
86+
elif platform.system() == "SunOS":
87+
os.system("open %s &" % image_name )
88+
elif platform.system() == "FreeBSD":
89+
os.system("open %s &" % image_name )
90+
elif platform.system() == "Unix":
91+
os.system("open %s &" % image_name )
92+
elif platform.system() == "OpenBSD":
93+
os.system("open %s &" % image_name )
94+
elif platform.system() == "NetBSD":
95+
os.system("open %s &" % image_name )
96+
elif platform.system() == "Windows":
97+
os.system("open %s &" % image_name )
98+
else:
99+
Logging.info(u"我们无法探测你的作业系统,请自行打开验证码 %s 文件,并输入验证码。" % os.path.join(os.getcwd(), image_name) )
100+
101+
captcha_code = raw_input( termcolor.colored("请输入验证码: ", "cyan") )
102+
return captcha_code
103+
104+
def search_xsrf():
105+
url = "http://www.zhihu.com/"
106+
r = requests.get(url)
107+
if int(r.status_code) != 200:
108+
raise NetworkError(u"验证码请求失败")
109+
results = re.compile(r"\<input\stype=\"hidden\"\sname=\"_xsrf\"\svalue=\"(\S+)\"", re.DOTALL).findall(r.text)
110+
if len(results) < 1:
111+
Logging.info(u"提取XSRF 代码失败" )
112+
return None
113+
return results[0]
114+
115+
def build_form(account, password):
116+
account_type = "email"
117+
if re.match(r"^\d{11}$", account): account_type = "phone"
118+
elif re.match(r"^\S+\@\S+\.\S+$", account): account_type = "email"
119+
else: raise AccountError(u"帐号类型错误")
120+
121+
form = {account_type: account, "password": password, "remember_me": True }
122+
123+
form['_xsrf'] = search_xsrf()
124+
form['captcha'] = download_captcha()
125+
return form
126+
127+
def upload_form(form):
128+
url = "http://www.zhihu.com/login/email"
129+
headers = {
130+
'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36",
131+
'Host': "www.zhihu.com",
132+
'Origin': "http://www.zhihu.com",
133+
'Pragma': "no-cache",
134+
'Referer': "http://www.zhihu.com/",
135+
'X-Requested-With': "XMLHttpRequest"
136+
}
137+
138+
r = requests.post(url, data=form, headers=headers)
139+
if int(r.status_code) != 200:
140+
raise NetworkError(u"表单上传失败!")
141+
142+
if r.headers['content-type'].lower() == "application/json":
143+
result = r.json()
144+
if result["r"] == 0:
145+
Logging.success(u"登录成功!" )
146+
return {"result": True}
147+
elif result["r"] == 1:
148+
Logging.success(u"登录失败!" )
149+
return {"error": {"code": int(result['errcode']), "message": result['msg'], "data": result['data'] } }
150+
else:
151+
Logging.warn(u"表单上传出现未知错误: \n \t %s )" % ( str(result) ) )
152+
return {"error": {"code": -1, "message": u"unknow error"} }
153+
else:
154+
Logging.warn(u"无法解析服务器的响应内容: \n \t %s " % r.text )
155+
return {"error": {"code": -2, "message": u"parse error"} }
156+
157+
158+
def islogin():
159+
# check session
160+
url = "http://www.zhihu.com/settings/profile"
161+
r = requests.get(url, allow_redirects=False)
162+
status_code = int(r.status_code)
163+
if status_code == 301 or status_code == 302:
164+
# 未登录
165+
return False
166+
elif status_code == 200:
167+
return True
168+
else:
169+
Logging.warn(u"网络故障")
170+
return None
171+
172+
173+
def read_account_from_config_file(config_file="config.ini"):
174+
from ConfigParser import ConfigParser
175+
cf = ConfigParser()
176+
if os.path.exists(config_file) and os.path.isfile(config_file):
177+
Logging.info(u"正在加载配置文件 ...")
178+
cf.read(config_file)
179+
#cookies = cf._sections['cookies']
180+
email = cf.get("info", "email")
181+
password = cf.get("info", "password")
182+
if email == "" or password == "":
183+
Logging.warn(u"帐号信息无效")
184+
return (None, None)
185+
else: return (email, password)
186+
else:
187+
Logging.error(u"配置文件加载失败!")
188+
return (None, None)
189+
190+
191+
192+
193+
def login(account=None, password=None):
194+
if islogin() == True:
195+
Logging.success(u"你已经登录过咯")
196+
197+
if account == None:
198+
(account, password) = read_account_from_config_file()
199+
if account == None:
200+
account = raw_input("请输入登录帐号: ")
201+
password = raw_input("请输入登录密码: ")
202+
203+
204+
form_data = build_form(account, password)
205+
"""
206+
result:
207+
{"result": True}
208+
{"error": {"code": 19855555, "message": "unknow.", "data": "data" } }
209+
{"error": {"code": -1, "message": u"unknow error"} }
210+
"""
211+
result = upload_form(form_data)
212+
if "error" in result:
213+
if result["error"]['code'] == 1991829:
214+
# 验证码错误
215+
Logging.error(u"验证码输入错误,请准备重新输入。" )
216+
return login()
217+
else:
218+
Logging.warn(u"unknow error." )
219+
return False
220+
elif "result" in result and result['result'] == True:
221+
# 登录成功
222+
Logging.success(u"登录成功!" )
223+
requests.cookies.save()
224+
return True
225+
226+
if __name__ == "__main__":
227+
login()

0 commit comments

Comments
 (0)