初学Python3小白一枚,若有错误请不吝赐教
整个过程 从填写数据到跳转到主页一共经历了七个步骤:
1.在登陆前,输入账号结束,失去输入框焦点,浏览器会发送两个请求,分别请求了登陆前加密密码所需的servertime、nonce、pubkey(图中对应3)
2.第二个ajax请求的是关于验证码的(图中对应4、5)
3.这个是点击登录按钮后,将加密后的数据post到服务器(图中对应6)
4.服务器会返回一系列数据,(对应图中的8),它包含了重定向的地址
5.多次页面加载后,会接收到来自服务器的json数据包(对应图中的19)在这
个数据包中包含了每个微博用户特定的uniqueid
6.这是一个携带有相关用户信息的script脚本(对应图中的22)
7.经过一系列的跳转后,最终跳转到个人主页面
遇到的最严重的坑,就是验证码的啦
验证码的请求分析,着实耗费了大半天 。这是验证码请求的服务器地址:
https://login.sina.com.cn/cgi/pin.php?r=18674039&s=0&p=yf-c92f2edb50c21d4bcbfdc3fccfdb94c4c23f
其中分析后发现:
固定服务器url:https://login.sina.com.cn/cgi/pin.php?
携带的参数:r = 18674039,p = yf-c92f2edb50c21d4bcbfdc3fccfdb94c4c23f,s = 0
其中s和p是固定值,r是一串不固定变化的数字,在分析的过程中,我试图寻找关于r的规律,最后实在没办法,我打算在Fiddler中测试一下,看看不加参数r是否能获得,结果是可喜可贺的,确实获得了。
事实上,在保证cookie一致的情况下,去请求验证码,也就是说和你本次的登录保持在一个cookie中,可以主动的抓取验证码。
# 获取验证码
def get_verificationcode():
print("开始请求获取验证码...")
url = "https://login.sina.com.cn/cgi/pin.php?s=0&p=yf-9f5e31626347e127bc21874aa9d6f4d745ca"
request.urlretrieve(url=url, filename="./img/code.jpg")
print("验证码获取成功!")
return input("请输入验证码:")
在应对验证码问题上,我这里采用的是半人工半自动的,将每次获得的验证码存到当前目录下的img文件中,人工查看和输入验证码。
经分析在第二步发送登录的post请求之前,浏览器会实现发一个请求,请求的响应信息如下:
里边携带的servertime、pubkey、nonce、rsakv等关键信息在后边加密密码和包装post请求数据非常关键。关于如何得到这个分析以及整个爬虫的结构也,参考了这篇博文:https://www.cnblogs.com/houkai/p/3488468.html.
以下是加密模块encrypt.py的代码
import base64
import binascii
import rsa
# 对用户名加密
def encryUsername(username):
print("开始加密用户名...")
text = (base64.b64encode(username.encode(encoding="utf-8")))
text = text.decode()
return str(text).replace("=", "")
# 对密码加密
def encryPassword(password,servertime,nonce,pubkey):
print("开始加密密码...")
rsaPublickey = int(pubkey, 16)
key = rsa.PublicKey(rsaPublickey, 65537) # 创建公钥
message = str(servertime) + '\t' + str(nonce) + '\n' + str(password) # 拼接明文js加密文件中得到
message = bytes(message, encoding="utf-8")
passwd = rsa.encrypt(message, key) # 加密
passwd = binascii.b2a_hex(passwd) # 将加密信息转换为16进制。
return passwd
在Chrome的开发者模式下,可以抓取相关参数信息
# 组织post数据
def get_postData(su,password,servertime,nonce,pubkey,rsakv):
print("开始组织post数据...")
# 密码加密
sp = encrypt.encryPassword(password, servertime, nonce, pubkey)
# 验证码请求
door = get_verificationcode()
# 构造post请求参数
data = {
"door": door,
"entry": "weibo",
"gateway": 1,
"from": "",
"savestate": 7,
"su": su,
"sp": sp,
"servertime": servertime,
"service": "miniblog",
"nonce": nonce,
"rsakv": rsakv,
"encoding": "UTF-8",
"domain": "sina.com.cn",
"returntype": "META",
"vsnf": 1,
"useticket": 1,
"pwencode": "rsa2",
"prelt": 372,
"qrcode_flag": "false",
"url": "https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack"
}
data = parse.urlencode(data).encode("utf-8")
return data
这个过程参考了:https://www.cnblogs.com/woaixuexi9999/p/9404745.html
在模块login.py中定义了一个类Login,其中的登录方法代码:
def login(self):
# 第一步 获得时间戳、公钥、nonce等数据
req = request.Request(url=self.__preloginUrl,headers=self.headers1,method="get")
response = request.urlopen(req)
text = response.read()
servertime, nonce, pubkey, rsakv = dealdata.get_prelogin(text=text)
# 第二步 向服务器发送post请求 登录信息
postdata = dealdata.get_postData(self.__su,self.__password,servertime,nonce,pubkey,rsakv)
req = request.Request(url=self.__loginUrl, headers=self.__postheaders, data=postdata,method="post")
response = request.urlopen(req)
text = response.read()
# 第三步 解析登录响应数据 获取中间链接
replaceUrl = dealdata.get_replaceUrl(text=text)
# 分析登录结果
result,retcode,reason = dealdata.get_reason(replaceUrl)
if result==False:
print("登录失败!")
print("原因",reason)
return
else:
print("登录成功!")
print("正在向个人主页跳转...")
# 第四步 加载中间链接 提取ticket
response = request.urlopen(replaceUrl)
text = response.read()
ticket = dealdata.get_ticket(text=text)
# 第五步 利用ticket组合关键部分构造网址 获得携带uniqueid的json数据
uniqueidUrl = ticket + "&callback=sinaSSOController.doCrossDomainCallBack&scriptId=ssoscript0&client=ssologin.js(v1.4.19)&_=1564805281285"
response = request.urlopen(uniqueidUrl)
text = response.read()
uniqueid = dealdata.get_uniqueid(text)
# 第六步 跳转到主页
print("进入个人主页...")
homeUrl = "https://weibo.com/u/" + uniqueid + "/home"
request.urlretrieve(homeUrl, "./html/home.html")
处理数据的dealdata.py模块
工程文件列表
code.jpg是验证码
home.html是加载的主页
初学Python,深感Python的强大。人生苦短,我用Python。
此程序仅供尝试使用,不可商用。
转载请注明出处:https://blog.csdn.net/Blz624613442/article/details/98368815