吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5812|回复: 9
收起左侧

[Python 转载] 新浪微博模拟登录 支持手动处理验证码

[复制链接]
天空宫阙 发表于 2020-2-13 22:02
本帖最后由 天空宫阙 于 2020-2-13 22:05 编辑

介绍
对于爬取少量的微博信息自己手动登录再copy一下cookie是最简单的方式
而对于大规模的爬取,需要大量账号的登录,手动登录费时费力,模拟登录就有它的重要意义
一般的做法是大量账号的模拟登录并保存cookie形成cookie池,提供爬虫使用


代码参考https://github.com/CharlesPikachu/DecryptLogin/blob/master/DecryptLogin/platforms/weibo.py
通过新浪通行证的登录来登录微博https://login.sina.com.cn/signup/signin.php

登录过程
1.预登录,向prelogin_url(https://login.sina.com.cn/sso/prelogin.php)发起get请求得到rsa加密的参数
    该请求的核心参数
    su  为用户名的base64加密
    _   时间戳 python模拟 str(int(time.time()*1000))
    其他entry,rsakt,client为不变参数

2.登录,向ssologin_url(https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19))发起post请求登录
    改请求核心参数
    su 为用户名的base64加密
    servertime 预登录返回
    nonce 预登录返回
    rsakv 预登录返回
    sp servertime + '\t' +nonce +'\n'+ password 这一串字符(如图)的rsa加密
        rsa加密的modules是与请求返回的pubkey,exponent是"10001"(二进制),用PKCS1_v1_5方式填充
        rsa的加密可以用 python的RSA库模拟 也可用pycryptodome库模拟,选择PKCS1_v1_5即可

加密的信息.png

3.请求login_url(https://passport.weibo.com/wbsso/login)
    需要携带的核心参数ticket, ssosavestate,均为post请求的返回值

完整代码
[Python] 纯文本查看 复制代码
""" 
参考https://github.com/CharlesPikachu/DecryptLogin/blob/master/DecryptLogin/platforms/weibo.py
"""
import requests
import base64
import time
import random
# rsa用的是PKCS1_v1_5填充
import rsa
import re
import json
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import PKCS1_v1_5
from binascii import b2a_hex
from PIL import Image
import warnings
# 过滤警告信息
warnings.filterwarnings('ignore')

class weibo:
    def __init__(self):
        self.session = requests.Session()
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
        }
        self.prelogin_url = 'https://login.sina.com.cn/sso/prelogin.php'
        self.ssologin_url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)'
        self.pin_url = 'https://login.sina.com.cn/cgi/pin.php'
        self.login_url = 'https://passport.weibo.com/wbsso/login?'
        self.home_url = 'https://weibo.com/u/%s/home'

    def get_prelogin_info(self,username,password):
        """ 请求prelogin_url得到RSA加密的参数 """
        su = base64.b64encode(username.encode())
        su = str(su,'utf-8')
        params = {
            'entry': 'account',
            # 'callback': 'sinaSSOController.preloginCallBack',
            'su': su,
            'rsakt': 'mod',
            'client': 'ssologin.js(v1.4.15)',
            '_': str(int(time.time()*1000))
        }
        # verify=False 不加也可以返回数据
        res = self.session.get(self.prelogin_url, params=params, verify=False)
        return res.json()

    def get_pin(self):
        """ 保存验证码图片 """
        r = int(random.random()*100000000)
        params = {
                        'r': str(r),
                        's': '0',
                }
        response = self.session.get(self.pin_url,params=params)
        if response.status_code ==200:
            with open('pin_img.png','wb') as f:
                f.write(response.content)
                f.close()
                print('had saved Captcha.')
            # Image好像会调用默认的图片查看器打开图片
            I = Image.open('pin_img.png')
            I.show()
            Captcha_value = input('enter the Captcha value:')
            return Captcha_value

    def post_login_data(self,username,password,Captcha_value=None): 
        """ post请求登录 """  
        p = self.get_prelogin_info(username,password)
        
        # 用不同的库实现RSA加密 都可行
        """ RSA库实现 """
        # publickey = rsa.PublicKey(int(p['pubkey'], 16), int('10001', 16))
        # sp = rsa.encrypt((str(p['servertime'])+'\t'+p['nonce']+'\n'+password).encode(), publickey)
        
        """ 用pycryptodome库实现 """
        rsa_public_key = RSA.construct((int(p['pubkey'],16),int('10001',16)))
        cipher_rsa = PKCS1_v1_5.new(rsa_public_key)
        sp2 = cipher_rsa.encrypt((str(p['servertime'])+'\t'+p['nonce']+'\n'+password).encode())
        # 返回的二进制数据的十六进制表示
        sp = b2a_hex(sp2)
        data_post = {
            'entry': 'account',
            'gateway': '1',
            'from': '',
            'savestate': '30',
            'useticket': '0',
            'pagerefer': '',
            'vsnf': '1',
            'su': base64.b64encode(username.encode()),
            'service': 'account',
            'servertime': str(int(p['servertime'])+random.randint(1, 20)),
            'nonce':p['nonce'],
            'pwencode': 'rsa2',
            'rsakv': p['rsakv'],
            'sp': sp,
            'sr': '1366*768',
            'encoding': 'UTF-8',
            'cdult': '3',
            'domain': 'sina.com.cn',
            'prelt': '95',
            'returntype': 'TEXT',
        }
        if Captcha_value:
            data_post['door'] = Captcha_value
        res = self.session.post(self.ssologin_url, data=data_post,allow_redirects=False, verify=False)
        if res.status_code==200:
            return res.json()
    
    def check_at_login_url(self,res,username):
        ticket, ssosavestate = re.findall(r'ticket=(.*?)&ssosavestate=(.*?)"', res)[0]
        # 请求login_url
        params = {
                    'ticket': ticket,
                    'ssosavestate': str(ssosavestate),
                    'callback': 'sinaSSOController.doCrossDomainCallBack',
                    'scriptId': 'ssoscript0',
                    'client': 'ssologin.js(v1.4.19)',
                    '_': str(int(time.time() * 1000))
                }
        params = '&'.join(['%s=%s' % (key, value) for key, value in params.items()])
        res = self.session.get(self.login_url+params, verify=False)
        uid = re.findall(r'"uniqueid":"(.*?)"', res.text)[0]
        res = self.session.get(self.home_url % uid, verify=False)
        if '我的首页' in res.text:
            print('[INFO]: Account -> %s, login successfully...' % username)
            infos_return = {'username': username}
            return infos_return, self.session

    
    def login(self,username,password):
        res = self.post_login_data(username,password)
        while True:
            if res['retcode']=='0':
                infos_return,login_session = self.check_at_login_url(json.dumps(res),username)
                if login_session:
                    return login_session
                break
            elif res['retcode']=='101':
                # 用户名或密码不正确
                print(res['reason'])
                break
            elif res['retcode']=='4049':
                # 需要验证码
                print(res['reason'])
                res = self.post_login_data(username,password,self.get_pin())
            elif res['retcode']=='2070':
                # 验证码错误
                print(res['reason'])
                res = self.post_login_data(username,password,self.get_pin())
            else:
                print(res)
                break
        


if __name__ == "__main__":
    t = weibo()
    # t.login('用户名','密码')
    login_session = t.login('','')
    # print(login_session.cookies)
    

py文件下载


https://www.lanzouj.com/i9bq9yj

效果示例


示例.png


有验证码的情况
这个例子中是手动输入的
其他方法是接入打码平台,或者cnn(卷积神经网络)训练模型识别(这是人工智能中计算机视觉的内容,还不会)

如果觉得还可以免费评分鼓励一下!

免费评分

参与人数 5吾爱币 +3 热心值 +5 收起 理由
清晨呀 + 1 我很赞同!
zhooou + 1 + 1 谢谢@Thanks!
wangxp + 1 + 1 谢谢@Thanks!
Zeaf + 1 用心讨论,共获提升!
huayugongju + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Zeaf 发表于 2020-2-13 23:30
学习了,感谢!
 楼主| 天空宫阙 发表于 2020-2-14 13:18
新征程 发表于 2020-4-27 11:26
感谢楼主分享,先收藏,具体情况使用再评价
fuxian 发表于 2020-5-22 15:23
你好,请问现在怎么得出微博等级信息
清晨呀 发表于 2020-7-31 17:20
本帖最后由 清晨呀 于 2020-8-6 17:18 编辑

感谢大佬分享,代码很实用
doanthan 发表于 2020-12-31 16:18
楼主有心了,可惜的是通过新浪通行证跳转的方法基本都被河蟹了,都需要扫码或者私信短信验证,今年被封了大批接口。我艰难找到一个能跳验证的,不知道能用多久。
MOEYU_VANILLA 发表于 2020-12-31 21:14
感谢分享
a3851458 发表于 2021-4-18 18:16
大佬现在有可以直接登入APP的吗微博 不要手机验证码的 有吗
头像被屏蔽
zhaochon 发表于 2021-5-23 17:04
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 16:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表