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是我自己的一個驗證碼識别庫。