新浪微博爬取之模擬登錄(附完整代碼)
目標(biāo)地址
隨便輸入一個(gè)用戶名和密碼(畢竟還不想真的登錄進(jìn)去)。
看到請(qǐng)求中的prelogin
登錄的url為https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)
而另一個(gè)login中的內(nèi)容是
_:里的一串?dāng)?shù)字是一樣的,英國是時(shí)間戳
上面的client里面有個(gè)ssologin.js,應(yīng)該是和login登錄有關(guān)的json
在elements里面查找
打開這個(gè)網(wǎng)址
在之前的query string parameters里面可以找到一個(gè)參數(shù)su,在這個(gè)里面看看su被賦值成了什么
搜索su =
request.su = sinaSSOEncoder.base64.encode(urlencode(username));
意味就是把我們的用戶名url編碼后再進(jìn)行base64編碼即可,此處獲得用戶名的加密方法
python實(shí)現(xiàn)的話就是
def encode_username(usr):
return base64.b64encode(usr.encode('utf-8'))
su發(fā)送的字符為MTIz
Python 實(shí)現(xiàn)相同的效果,驗(yàn)證沒錯(cuò)
后面一段是password的加密
if (me.service) { request.service = me.service } if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey) { request.servertime = me.servertime; request.nonce = me.nonce; request.pwencode = "rsa2"; request.rsakv = me.rsakv; var RSAKey = new sinaSSOEncoder.RSAKey(); RSAKey.setPublic(me.rsaPubkey, "10001"); password = RSAKey.encrypt([me.servertime, me.nonce].join("\t") + "\n" + password) } else { if ((me.loginType & wsse) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.hex_sha1) { request.servertime = me.servertime; request.nonce = me.nonce; request.pwencode = "wsse"; password = sinaSSOEncoder.hex_sha1("" + sinaSSOEncoder.hex_sha1(sinaSSOEncoder.hex_sha1(password)) + me.servertime + me.nonce) } } request.sp = password;
這段看上去就很讓人頭大了,寫了微博密碼的加密過程,有rsa和wsse兩個(gè)加密分支
有大佬驗(yàn)證過了基本上都是走rsa分支的,另一個(gè)分支不用管(我應(yīng)該直說我不會(huì)哈哈哈哈哈)
那么我門仿造他的rsa
import rsa
import binascii
def get_password(message, n):
"""RSA加密用戶密碼"""
pub_key = rsa.PublicKey(int(n, 16), int('10001', 16))
crypto = rsa.encrypt(message.encode('utf8'), pub_key)
return binascii.b2a_hex(crypto)
也是把"10001"加進(jìn)PublicKey,然后進(jìn)行encrypt,然后看下結(jié)果
(當(dāng)然了直接用json里面的對(duì)象進(jìn)行加密也可以咯)
publickey = rsa.PublicKey(int(pubkey, 16), int('10001', 16))
message = str(servertime) + '\t' + str(nonce) + '\n' + str(password)
sp = rsa.encrypt(message.encode(), publickey)
res = binascii.b2a_hex(self.sp)
需要好多username以及password之外的信息,所以還是先請(qǐng)求一波,獲取信息。
Form data里面可以看到好多東西,加密方式也是咱們的rsa2,從剛才的加密方式可以看出需要里面的servertime,nonce,pubkey
url = ' = self.username,tstamp = time.time() * 1000)
try:
res = self.session.get(url).text
print(res)
進(jìn)行一波訪問可以看到獲得的內(nèi)容
用正則表達(dá)式取出{}里面的內(nèi)容
res = re.findall("{.*}",res)[0]###
用json加載,變成字典
self.res = json.loads(res)
這樣就獲得了我們需要的一些參數(shù)。其他的固定的東西直接填上就好。
我的密碼也是亂填的123
發(fā)出的消息是
sp:
e3863eb0dbbf44990b95df6a4c3ff3f57f1e8185cf35d6c39c9f4c2b9bfc18ffe13545619d6520c1834b337b4f88292ff70b9a853ca6b3d2d1f0a24e74e1c85cc17c26e01ba85d9b49426542d156f0afe0e2cf01c0b4d5c3f7ba0fbb3f05ad613c97e7eac860888db17e34718d738243e6091a274e3ca445274f642bccbd2664
但是算出來結(jié)果不一樣啊????
emmm不一樣是正常的畢竟加密不是簡單直接把密碼這個(gè)常量加密的。
嘗試一下模擬登錄
emmm忘了改成自己微博的賬號(hào)密碼了,不過這說明程序可以正常運(yùn)作
emmm這就有點(diǎn)尷尬了,不過也說明正常發(fā)送了正確的用戶名和密碼,并被確認(rèn)
這次讓他訪問一次后等待10秒,再次用session訪問,我趁機(jī)允許登錄,但是還是顯示登錄失敗了(不知道有沒有大佬來指教一番)
于是一怒之下我放了大招:換大號(hào)微博登錄!一次成功,有點(diǎn)開心hhhhh
登錄成功了以后用session再進(jìn)行訪問爬取或者保存下cookie然后利用cookie爬取登錄后可見的內(nèi)容就闊以了。
不過微博的爬蟲雖然不封ip但是會(huì)封賬號(hào),要是比較狠的爬的話還是買一堆小號(hào)比較好。。。
畢竟我大號(hào)微博陪我這么久我可不舍得丟
完整代碼
import base64
import requests
import rsa
import binascii
import re
import json
import time
import random
'''用rsa對(duì)明文密碼進(jìn)行加密,加密規(guī)則通過閱讀js代碼得知'''
class WeiBoLogIn():
def __init__(self,username,password):
self.username = username
self.password = password
self.encode_su()
self.session = requests.session()#建立一個(gè)連續(xù)訪問
self.loginurl = 'https://login.sina.com.cn/signup/signin.php'
self.session.get(self.loginurl)#目標(biāo)登錄地址
#加密su
def encode_su(self):
self.su = base64.b64encode(self.username.encode('utf-8'))
def pre_log(self):
#訪問一波拿到各種東西
url = 'https://login.sina.com.cn/sso/prelogin.php?entry=sso&callback=sinaSSOController.preloginCallBack&su={uname}&rsakt=mod&client=ssologin.js(v1.4.15)&_={tstamp}'.format(uname = self.username,tstamp = time.time() * 1000)
try:
res = self.session.get(url).text
res = re.findall("{.*}",res)[0]###
self.res = json.loads(res)
#print(self.res)
self.nonce = self.res["nonce"]
self.pubkey = self.res["pubkey"]
self.rsakv = self.res["rsakv"]
self.servertime = self.res["servertime"]
#self.nonce =
except:
print('failed')
def get_sp(self):
publickey = rsa.PublicKey(int(self.pubkey,16),int('10001',16))
keycode = str(self.servertime) + '\t' + str(self.nonce) + '\n' + str(self.password)
self.sp = rsa.encrypt(keycode.encode(), publickey)
self.spcode = binascii.b2a_hex(self.sp)
print(self.spcode)
def login(self):
self.pre_log()
self.get_sp()
data = {
'entry': 'sso',
'gateway': '1',
'from': 'null',
'savestate': '30',
'useticket': '0',
'pagerefer': 'https://login.sina.com.cn/sso/login.php?client=ssologin.js',
'vsnf': '1',
'su': self.su,
'service': 'sso',
'servertime': self.servertime,
'nonce': self.nonce,
'pwencode': 'rsa2',
'rsakv': self.rsakv,
'sp': self.spcode,
'sr': '1500*1000',#分辨率吧應(yīng)該是,r是resolution
'encoding': 'UTF-8',
'cdult': '3',
'domain': 'sina.com.cn',
'prelt': random.randint(1,100),
'returntype': 'TEXT'
}
url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js'
j_content = self.session.post(url,data=data).json()
print(j_content)
# time.sleep(10)
# j_content = self.session.post(url,data=data).json()
# print(j_content)
weibo = WeiBoLogIn('****不給看***','*****真的不給看哦***')
#weibo.pre_log()
weibo.login()