前两天看了一篇大佬模拟登录淘宝的blog感觉收获颇多,刚好这两天比较闲,研究了下微博的登录方式

进入正题:

琢磨了两天找到了两种方式

  1. 构造登录时提交的加密参数,比较复杂,但是切换成不常用的ip也不会出验证码,这里详细讲这种方式
  2. 用selenium加载,切ip会出图形验证码,可以通过调用第三方API的方式破解,这里只写了不出验证码的情况供参考

第一种方式:

1.向’https://login.sina.com.cn/sso/prelogin.php’发送预登录的get请求
2.向’https://login.sina.com.cn/sso/login.php’发送正式登录的post请求
3.向’https://passport.weibo.com/wbsso/login?ticket=*****&ssosavestate=*****’发送get请求(****根据上一个请求响应而定,后面会说)
三步完成后进入登录状态,可以访问个人主页和做其他事情了~

  • 会用到RSA加密,不了解原理的可以看一下b站李永乐老师的视频,应该相当形象

这里是思路,可以直接跳过看代码

  1. chrome在未登录状态下打开微博,应该是这样的页面,先打开开发者模式,填写右边的用户名、密码,戳登录,页面跳转后,可以看到提交了几个POST请求(Preserve log记得勾选,否则一跳就看不到了)。最后一个明显是与登录相关,访问它不带参数的Request Url,可以到达一个比较纯净的登录接口: ‘https://login.sina.com.cn/signup/signin.php?entry=sso’

    2.同样打开开发者模式,用浏览器登录,提交的POST请求有两个,第一个是验证邮箱是否有效的,可以不用管;第二个就是我们的登录请求。提交的form data里有一堆参数。再重新登录一次,可以发现大部分是固定的,但是有几个参数值得注意,su, nonce, servertime, pubkey, rsakv, sp,构造出这几个参数,应该就可以顺利登录。

    3.检索后,发现su参数是向’https://login.sina.com.cn/sso/prelogin.php’请求时带上去的,用charles或者fiddler等抓包软件可以看到这个请求返回了一个json文件,有nonce, servertime, pubkey, rsakv的值,与POST请求提交的一致,可以肯定在正式登录之前先请求了这个url

    4.剩下su、sp没有解决,监听一下登陆页面的鼠标点击事件,发现一段关键代码,su参数就是由用户名经过url编码再base64转码后得来的。再往后走,sp参数也找到了,是登录密码经过rsa登录后得到的,sp详细的构造过程见代码注释


    5.所有参数都就绪了,但是发送正式登录请求返回的是一个json文件,CrossDomainUrlList里的正好是我们发送登录请求后要跳转的链接列表(在代码测试的时候会知道只有带ticket参数那个必须进行跳转

**这里是代码:**

from time import time
import requests
import base64
from urllib import parse
import re
import json
import rsa
import binascii
from lxml import etree
import os# 建立一个会话对象,使cookie可以跨请求保留
SESSION = requests.session()# cookies保留再本地的路径
COOKIES_FILE_PATH = 'weibo_login_cookies.json'class WeiboLogin:def __init__(self, username, password):"""需传入两个参数:param username:用户名:param password: 密码"""# 预登录urlself.pre_login_url = 'https://login.sina.com.cn/sso/prelogin.php'# 正式登录urlself.login_url = 'https://login.sina.com.cn/sso/login.php'# 个人主页urlself.mysina_url = 'http://my.sina.com.cn/'# 微博用户名self.username = username# 微博密码self.password = passworddef per_login(self):"""预登录,此步骤仅验证用户名:return:正式登录时要用上的5个参数值,su,nonce,servertime,pubkey,rsakv"""# su参数是用户名经过url编码和base64转码后的字符串su = base64.b64encode(parse.quote(username).encode('utf-8')).decode('utf-8')per_login_params = {'entry': "account",'callback': "sinaSSOController.preloginCallBack",'su': su,'rsakt': "mod",'client': "ssologin.js(v1.4.15)",'_': int(time()*1000),}try:response = SESSION.get(self.pre_login_url, params=per_login_params)# 响应异常时,抛出异常信息response.raise_for_status()except Exception as error:print('预登录失败,原因:')raise error# 返回值是非标注格式的json字符串response_json = re.search(r'\((.*?)\)', response.text).group(1)response_dict = json.loads(response_json)# 提取出需要的其他4个参数nonce = response_dict['nonce']servertime = response_dict['servertime']pubkey = response_dict['pubkey']rsakv = response_dict['rsakv']if nonce:print('预登录成功, nonce参数为: %s' % nonce)return su, nonce, servertime, pubkey, rsakvdef encrypt_password(self, pubkey, servertime, nonce):"""构造sp参数,sp参数是经过rsa加密的密码:params pubkey, servertime, nonce: 预登录取得:return: sp参数"""# 接收方(微博服务器)提供的pubkey,转16进制rsa_publickey = int(pubkey, 16)# 加载公钥,传入参数n和参数e(关于参数的解释可参考这篇大佬文章 https://blog.csdn.net/chengqiuming/article/details/70139817)key = rsa.PublicKey(rsa_publickey, int('10001', 16))# 加载明文mmessage = str(servertime) + '\t' + nonce + '\n' + password# 加密成密文c,有c = m^e mod n(解密的时候是还原m, m = c^d mod n, 其中d为私钥)encrypt_message = rsa.encrypt(message.encode('utf-8'), key)# 16进制密文sp = binascii.b2a_hex(encrypt_message).decode('utf-8')return spdef login(self):"""构造form data发送post请求,正式登录:return: 登录成功的cookies"""# 加载本地cookies文件,加载成功则跳过登录,直接访问个人主页if self.load_cookies():return True# cookies过期,正常进行登录login_params = {'client': "ssologin.js(v1.4.15)",'_': int(time() * 1000),}# 预登录,返回5个参数su, nonce, servertime, pubkey, rsakv = self.per_login()# sp参数sp = self.encrypt_password(pubkey, servertime, nonce)# 构造表单login_form_data = {'entry': "account",'gateway': "1",'from': "null",'savestate': "30",'useticket': "0",'vsnf': "1",'su': su,'service': "account",'servertime': servertime,'nonce': nonce,'pwencode': "rsa2",'rsakv': rsakv,'sp': sp,'sr': "1280*720",'encoding': "UTF-8",'cdult': "3",'domain': "sina.com.cn",'prelt': "170",'returntype': "TEXT",}login_url = 'https://login.sina.com.cn/sso/login.php'try:# 登录请求返回一个json文件,里面有三个url,验证第一个url必须跳转,否则无法成功访问个人主页response = SESSION.post(login_url, params=login_params, data=login_form_data)response.raise_for_status()except Exception as error:print('登陆失败,原因:')raise error# 做一次必要的跳转,跳转的目的是补全cookies信息cross_url = re.search(r'"(https:.*?)"', response.text).group(1)cross_url = re.sub(r'\\', '', re.sub(r'\\', '', cross_url))if cross_url:print('登录成功,正在跳转%s' % cross_url)# 发送get请求,使session自动更新cookiesSESSION.get(cross_url)# 访问个人主页,成功则保存cookies至本地if self.verify_login_status():self.serialize_cookies()def verify_login_status(self):"""访问个人主页,验证登录状态"""try:response = SESSION.get(self.mysina_url)response.raise_for_status()except Exception as error:print('获取个人主页失败,原因: ')raise error# 不明原因返回了部分乱码,所以取content再decodehtml = etree.HTML(response.content.decode('utf-8'))nickname = html.xpath('//div[@class="me_w"]//p[@class="me_name"]/text()')[0]if nickname:print('已处于登录状态!当前处于[%s]的个人主页' % nickname)return Trueelse:raise RuntimeError('获取微博昵称失败!response: %s' % response.content.decode('utf-8'))def load_cookies(self):"""检查本地cookies是否可用"""# 判断cookies文件是否存在if not os.path.exists(COOKIES_FILE_PATH):return False# 加载本地cookiesSESSION.cookies = self.deserialize_cookies()# 判断cookies是否过期try:self.verify_login_status()except Exception as error:os.remove(COOKIES_FILE_PATH)print('本地cookies文件过期,正在删除...')return Falseprint('加载新浪微博登录cookies成功!')return Truedef serialize_cookies(self):"""保存cookies至本地"""cookies_dict = requests.utils.dict_from_cookiejar(SESSION.cookies)with open(COOKIES_FILE_PATH, 'w+', encoding='utf-8') as file:json.dump(cookies_dict, file)print('保存cookies文件成功!文件名: %s' % COOKIES_FILE_PATH)def deserialize_cookies(self):"""读取本地cookies"""with open(COOKIES_FILE_PATH, 'r+', encoding='utf-8') as file:cookies_dict = json.load(file)cookies = requests.utils.cookiejar_from_dict(cookies_dict)return cookiesif __name__ == '__main__':# 这里输入用户名username = '*************'# 这里输入登录密码password = '*************'wb_login = WeiboLogin(username, password)wb_login.login()

程序会在根目录下创建登录成功的cookies文件
如果本地cookies未创建&已过期,运行结果如下:

如果本地cookies未过期,运行结果如下:


第二种方式:

selenium常规操作,
1.定位用户名、密码输入框,定位登录按钮
2.输入相应数据,点击登录按钮
3.登录成功(如果在非常用ip登录会弹出图形验证码,代码会报错,用第三方API识别验证码可破)


**这里是代码:**

from selenium import webdriver# chrome driver所在路径
driver_path = r'C:\Users\12517\PycharmProjects\chromedriver.exe'
username = '*************'
password = '*************'options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
# 如果切换为非常用ip,页面会自动刷新出图形验证码(常用ip直接登陆即可成功)
driver = webdriver.Chrome(executable_path=driver_path, options=options)
driver.get('https://login.sina.com.cn/signup/signin.php')
username_tag = driver.find_element_by_xpath('//input[@id="username"]')
password_tag = driver.find_element_by_xpath('//input[@id="password"]')
login_btn = driver.find_element_by_xpath('//input[@class="W_btn_a btn_34px"]')
username_tag.send_keys(username)
password_tag.send_keys(password)
login_btn.click()

python爬虫:模拟登录新浪微博并实现cookies保存,详细讲一下rsa相关推荐

  1. 【Python技能树共建】Python爬虫模拟登录

    Python 爬虫模拟登录 Python 爬虫模拟登录是使用脚本实现自动登录,部分站点需要逆向加密逻辑,更多的站点会采用验证码进行鉴权验证. 本文为大家带来最简单的登录,其核心用到的是 request ...

  2. python爬虫 模拟登录人人网过程解析

    这篇文章主要介绍了python爬虫 模拟登录人人网过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 equests 提供了一个叫做sessio ...

  3. python登录教务系统_强智科技教务系统python爬虫模拟登录分析(湖南)

    强智科技教务系统python爬虫模拟登录分析(湖南) 本文章仅用作于学习 前提:最近期末到来,想第一时间看到新出成绩的,于是就有了爬取学校教务系统自己的成绩并通过Qmsg酱推送到自己QQ上的想法,目前 ...

  4. python–爬虫–模拟登录全面介绍和简例–以抓取雅卓app为例

    转载请注明出处:python–爬虫–模拟登录全面介绍和简例–以抓取雅卓app为例 我们在前面的文章中已经学习了如果使用python进行数据抓取. 但我们常常会遇到一种场景,就是想要获取的页面内容或者接 ...

  5. python爬虫登陆教程_(python模拟登陆教程)python爬虫模拟登录是什么意思

    python爬虫模拟登录是什么意思 网站需要登录后才能所需要的信息,此时可以设计爬虫进拟登录,原理是利用浏cookie. 一.浏览器访问服务器的过程: (1)浏览器(客户端)向Web服务器发出一个HT ...

  6. python爬虫登录有验证码_大神教你用Python爬虫模拟登录带验证码网站

    爬取网站时经常会遇到需要登录的问题,这是就需要用到模拟登录的相关方法.python提供了强大的url库,想做到这个并不难.这里以登录学校教务系统为例,做一个简单的例子. 首先得明白cookie的作用, ...

  7. 枯燥的寒假生活(一) python爬虫模拟登录whu老教务系统获取期末考试成绩(已失效 , 老教务系统增加了新的反爬, 老教务系统已停用)

    python模拟登录老教务系统(2021.6.24更新) 一.写在前面 之前用爬虫爬取的都是静态网页html中的内容,但是大多数时候需要动态处理网页爬取数据.因为学校出成绩太慢了,每次都自己打开浏览器 ...

  8. python爬虫模拟登录古诗文网站

    爬取目标网站https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx?type=s 工具: ...

  9. python爬虫模拟登录人人网

    模拟登录:爬取基于某些用户的用户信息. 需求1:对人人网进行模拟登录. 点击登录按钮之后会发起一个post请求 post请求中会携带登录之前录入的相关的登录信息(用户名,密码,验证码-) 验证码:每次 ...

  10. Python爬虫模拟登录京东获取个人信息

    http://www.xgezhang.com/python_crawler_jingdong.html 先上我的代码.参考了上面链接的文章 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

最新文章

  1. 微信小程序-页面跳转传值
  2. vscode怎么弄php,vscode如何设置语言
  3. 把C#.NET程序移植到DB2上的经验浅谈(C#连接DB2可以用IBM.Data.DB2.dll)
  4. “APP杀手”?微信小程序瞬间原形毕露
  5. AOJ0028 Mode Value【出现次数最多+map+vector+水题】
  6. 西瓜书-感知机与BP算法
  7. 构建自己的Conficker
  8. Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands
  9. 【Java编程】写一个将华氏温度转换成摄氏温度的程序,转换的公式是:°F = (9/5)*°C + 32 其中C表示摄氏温度,F表示华氏温度。
  10. arccos用计算机,arccos(arccos在线计算器)
  11. Could not find a declaration file for module ‘xxx‘. ‘xxx‘ implicitly has an ‘any‘ type.
  12. java 北京时区_世界时区和Java时区详解
  13. word 的使用 —— 分页符与分节符
  14. 6,美国2012年总统候选人政治献金数据分析
  15. html完整语句,html语句
  16. 宏基因组分析教程-Analysis of Metagenomic Data
  17. 卡方检验(Chi-square test/Chi-Square Goodness-of-Fit Test)
  18. iOS手机端日志打印显示工具
  19. java虚拟机系列:java虚拟机内存模型
  20. arduino编码器计数_基于Arduino开发环境的光电编码器检测仪设计方案 - 全文

热门文章

  1. 中国全国地面站点数据(1981-2010)、月平均气象、月平均降水、月平均相对湿度、月最大降水、月最高温度最低温度、月最高温平均值最低温平均值、高低温站点基础数据,气候数据
  2. 关于手机游戏市场的调研方案(终结版)
  3. 7-8 愿天下有情人都是失散多年的兄妹 (25分)
  4. Python学习笔记---sep用法
  5. 【DSGN 解读】用于三维目标检测的深度立体几何网络
  6. mybatis系列-03-入门程序
  7. 各位想不想知道,360的保镖,在保护什么?
  8. 数据库设计阶段 各阶段的任务
  9. 【Unity3D日常开发】Unity3D中实现向Web服务器上传图片以及下载图片功能
  10. Unity3d 5 官方教程:UI