import requests
import time
import json
import rsa
import binascii
import base64
import random
import re
from dll_call import DLLCALL
class WeiBoLogin:
def __init__(self,username,password):
self.username = username
self.password = password
self.session = requests.session()
self.showpin = 0
self.cookie_file = "Cookie.json"
self.cookie=""
self.nonce,self.pubkey,self.rsakv,self.pcid= "","","","",
self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
self.OCRDLL = DLLCALL("F:\hqm\wb1\login\dll_lib\OCR.dll")
self.ip_list=[]
self.proxy_ip= get_chroce_ip()
self.set_cookie=''
self.myuid=''
def save_cookie(self):
lens = len(self.cookie)
if lens==0:
self.login(self)
with open(self.cookie_file, 'w') as f:
json.dump(self.cookie, f)
def load_cookie(self):
'''
导出cookie
:return: Cookie
'''
with open(self.cookie_file,'r') as f:
cookie = requests.utils.cookiejar_from_dict(json.load(f))
return cookie
def pre_login(self,usr):
'''
预登陆
:return:
'''
su = base64.b64encode(usr.encode('utf-8')).decode()
url = 'https://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su={}&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.19)&_={}'.format(su,int(time.time() * 1000))
res= requests.get(url,headers = self.headers)
# print(res.text)
p = re.compile('preloginCallBack\((.+)\)')
pp=p.search(res.text).group(1)
js = json.loads(pp)
self.nonce,self.pubkey,self.rsakv,self.pcid= js["nonce"],js["pubkey"],js["rsakv"],js["pcid"]
self.showpin=js["showpin"]
def sso_login(self,sp,su):
'''
发送加密后的用户名和密码
:param sp: 加密后的密码
:param su: 加密后的用户名
:return:
'''
proxy = self.proxy_ip
showpin = self.showpin
def get_cha(pcid):
cha_url = "http://login.sina.com.cn/cgi/pin.php?r=" + str(
int(random.random() * 100000000)) + "&s=0&p=" + pcid
cha_page = requests.get(cha_url,headers=self.headers)
with open("cha.jpg", 'wb') as f:
f.write(cha_page.content)
f.close()
if showpin == 1:
img = cha_page.content
retCode = self.OCRDLL.OCR_E(img, len(img))
retCode = self.OCRDLL.getMsg()
#code = input('请输入验证码')
return retCode
return
data ={
'encoding':'utf-8',
'entry': 'weibo',
'from': '',
'gateway': '1',
'nonce': self.nonce,
'pagerefer': 'https://login.sina.com.cn/crossdomain2.php?action=logout&r=https%3A%2F%2Fweibo.com%2Flogout.php%3Fbackurl%3D%252F',
'prelt': '22',
'pwencode': 'rsa2',
'qrcode_flag': 'false',
'returntype': 'META',
'rsakv': self.rsakv,
'savestate': '7',
'servertime': int(time.time()),
'service': 'miniblog',
'sp': sp,
'sr': '1920*1080',
'su': su,
'url': 'https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
'useticket': '1',
'vsnf': '1'}
url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)&_={}'.format(int(time.time() * 1000))
if self.showpin == 0:
resp=self.session.post(url, headers=self.headers,data=data)
code = get_cha(self.pcid)
data['pcid'] =self.pcid
data['door'] = code
resp=self.session.post(url, headers=self.headers,data=data)
def login(self):
'''
模拟登陆
:return:
'''
#用户名使用base64加密
def encode_username(usr):
return base64.b64encode(usr.encode('utf-8'))[:-1]
#密码使用rsa加密
def encode_password(code_str):
pub_key = rsa.PublicKey(int(self.pubkey,16),65537)
crypto = rsa.encrypt(code_str.encode('utf-8'),pub_key)
return binascii.b2a_hex(crypto)#转成16进制
#获取nonce,pubkey,rsakv
self.pre_login(self.username)
#加密用户名
su = encode_username(self.username)
#加密密码
text = str(int(time.time())) + "\t" +str(self.nonce) + "\n" + str(self.password)
sp = encode_password(text)
#发送参数,保存cookie
self.sso_login(sp,su)
cookie_dt = requests.utils.dict_from_cookiejar(self.session.cookies)
self.cookie=cookie_dt
self.save_cookie()
self.session.close()
def run(username,password):
wb = WeiBoLogin(username,password)
wb.login()
1, 在提交POST请求之前, 需要GET 获取两个参数。
地址是:http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)
得到的数据中有 “servertime” 和 “nonce” 的值, 是随机的,其他值貌似没什么用。
2, 通过httpfox 观察POST 的数据, 参数较复杂,其中 “su" 是加密后的username, “sp"是加密后的password。“servertime” 和 ”nonce” 是上一步得到的。其他参数是不变的。
username 经过了BASE64 计算: username = base64.encodestring( urllib.quote(username) )[:-1];
password 经过了三次SHA1 加密, 且其中加入了 servertime 和 nonce 的值来干扰。
即: 两次SHA1加密后, 将结果加上 servertime 和 nonce 的值, 再SHA1 算一次。
3. showpin是判断是否需要验证码,showpin=0则不需要验证码,showpin=1则需要验证码。dll_lib是我自己的一个验证码识别库。