关灯

图文详解Python模拟登录新浪微博流程

[复制链接]
zylsnn 发表于 2019-5-11 15:00:55 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 
假如您念用Python模仿登岸新浪微专,起首必定要来百度一些相干的常识,理解列位先辈们曾经做得一些事情。那里经由过程搜刮能够明白,新浪微专正在登录时,对用户名、暗码停止了减稀处置,也明白了减稀算法(b64encode、rsa等等)。那里先有个大致印象,我会一步步交给各人怎样本人来发明新浪微专的减稀算法,究竟结果授人以鱼没有如授人以渔嘛!

那里用到的东西是Charles,是Mac下的一个抓包东西。Windows下对应的是Fiddler。假如您没有会用,大概没有熟习,倡议先装置一个,本人入手熟习一下硬件的用法。

好了,筹办事情完成了,空话未几道,开端干货!

(1)开启Charles后,翻开新浪微专的登录页里,并输进用户名、暗码、考证码后登录一遍,这时候候会正在Charles留下全部登录的流程,后边渐渐阐发。

图文详解Python模仿登录新浪微专流程-1.jpg

(2)阐发的第一步,要明白用户名怎样减稀。正在Charles中搜刮“username”。为何那么搜?您假如是做网站的,估量90%的能够城市把用户名变量定名为username吧!搜刮后看到只要文件loginLayers.js中包罗username,该文件的定名也阐明跟文件相干,按照经历该当能判定出那个文件很主要。

图文详解Python模仿登录新浪微专流程-2.jpg

(3)将那个文件的内乱容复造出去,放到一个文本文件中,搜刮username,会找到下边图示中的那么几止代码,从而得知用户名的减稀方法。用户名减稀办法很简朴,encode以后松跟一个base64便可。详细用Python怎样写,本人看代码。

图文详解Python模仿登录新浪微专流程-3.jpg

(4)用户名减稀完了,该当要减稀暗码了。持续正在那个文件中搜刮password,获得:

图文详解Python模仿登录新浪微专流程-4.jpg

那里能够揣测出this.login中的参数b该当便是password。检察login函数,能够获得:

图文详解Python模仿登录新浪微专流程-5.jpg

那里挪用了loginByXMLHttpRequest函数,并传进参数b,即password。以是我们持续搜刮loginByXMLHttpRequest,获得:

图文详解Python模仿登录新浪微专流程-6.jpg

那里挪用了makeXMLRequestQuery函数,并传进参数b,即password。以是我们持续搜刮makeXMLRequestQuery,获得:

图文详解Python模仿登录新浪微专流程-7.jpg

那里挪用了makeRequest函数,并传进参数b,即password。以是我们持续搜刮makeRequest,获得:

图文详解Python模仿登录新浪微专流程-8.jpg

那里就能够明晰的看到暗码减稀流程。详细Python怎样完成,仍是本人看代码。可是那里有个成绩,暗码减稀的时分,会有几个参数需求传进,好比nonce、servertime、rsakv等等,那是甚么鬼呢?持续往下看。

(5)正在Charles中搜刮servertime,会获得一个prelogin的恳求,该恳求返回servertime、nonce、pubkey等参数。那里返回的是一个json串。

图文详解Python模仿登录新浪微专流程-9.jpg

检察该恳求的request,能够看到他需求减稀后的用户名su。按照那里的参数,就能够对暗码停止减稀了。那里略微追念总结下全部流程:

    按照用户名username获得减稀后的用户名su

    按照su获得一个json串,里边包罗减稀暗码用到的各类参数,servertime、nonce等

    按照json串战暗码获得减稀后的暗码,然后就能够登岸了。

(6)正在Charles中能够找到一个login.php恳求,按照经历也能够大致判定那便是登录恳求,究竟证实也的确云云。按照该恳求的request,本人构建postdata,并收收恳求便可。

图文详解Python模仿登录新浪微专流程-10.jpg

那里需求阐明下考证码成绩。有些账号登录需求考证码,有些没有需求,那战账号设置有闭,带有登录庇护的便需求输进考证码。那里也能够按照上边获得的json串中的showpin参数得知(详细睹上边的图)。假如需求考证码,则只需求找到考证码的地点,获得图片:

图文详解Python模仿登录新浪微专流程-11.jpg

将那个图片保留到当地停止野生挨码,大概接进挨码仄台,皆能够获得考证码内乱容。正在我的代码中,我本来启拆了云挨码仄台的接心,间接挪用便可,但为了便利各人测试,我改成野生挨码的情势,详细睹代码:

(7)机关postdata,收收恳求,即使是恳求胜利了,实在借出登录胜利。由于新浪微专另有一步跳转。是否是很费事?别焦急,成功即刻便正在长远了。我们认真检察Charles后,会发明正在上个恳求以后,有下边一个恳求wbsso.login,那便是谁人跳转,以下图。

图文详解Python模仿登录新浪微专流程-12.jpg

该跳转恳求的恳求怎样构建,各人看代码便可,那里便未几道了。代码以下:

图文详解Python模仿登录新浪微专流程-13.jpg

代码中借查抄登录能否胜利,那里也不外多形貌。到那为行,新浪微专便算是登录胜利了。

那里另有一个成绩出有道到,便是Cookie成绩。本文中不断出有提到Cookie,是由于Python中的Cookiejar会帮我们主动处置一切的cookie成绩。您只需求正在模仿登岸之前,起首声明一个cookiejar战opener便可,详细那两个工具的用法,各人自止百度。代码以下:

图文详解Python模仿登录新浪微专流程-14.jpg

模仿登岸微专实的很费事,也的确需求必然的经历,各人多多操练,纯熟把握了那个,信赖您们正在模仿登岸其他网站的时分,也能触类旁通的来破解登录流程。有甚么成绩,能够正在批评中指出,偶然间我会帮各人解问的。

总的代码以下:

# _*_ coding: utf-8 _*_

import re

import rsa

import ssl

import time

import json

import base64

import logging

import binascii

import urllib.parse

# 参考PSpider项目

import spider

ssl._create_default_https_context = ssl._create_unverified_context

class WeiBoLogin(object):

"""

class of WeiBoLogin, to login weibo.com

"""

def __init__(self):

"""

constructor

"""

self.user_name = None # 登任命户名

self.pass_word = None # 登录暗码

self.user_uniqueid = None # 用户独一ID

self.user_nick = None # 用户昵称

self.cookie_jar, self.opener = None, None

return

def login(self, user_name, pass_word, proxies=None):

"""

login weibo.com, return True or False

"""

# 变量赋值初初化

self.user_name = user_name

self.pass_word = pass_word

self.user_uniqueid = None

self.user_nick = None

# 构建cookie_jar战opener,那里没有利用代办署理,同时包管全部流程中没有需求体贴cookie成绩

self.cookie_jar, self.opener = spider.make_cookiejar_opener(is_cookie=True, proxies=proxies)

self.opener.addheaders = spider.make_headers(

user_agent="pc",

host="weibo.com",

referer="http://weibo.com/",

accept="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",

accept_encoding="gzip, deflate",

accept_language="zh-CN,zh;q=0.8"

).items()

# (1) 翻开weibo.com/login.php,先恳求一些须要的cookie疑息

self.opener.open("http://weibo.com/login.php")

# (2) 按照用户名获得减稀后的用户名

s_user_name = self.get_username()

# (3) 操纵减稀后的用户名,获得其他一些数据:json格局

json_data = self.get_json_data(su_value=s_user_name)

if not json_data:

return False

# (4) 按照第三步获得的json数据,获得减稀后的暗码

s_pass_word = self.get_password(json_data["servertime"], json_data["nonce"], json_data["pubkey"])

# (5) 机关登录顶用到的postdata

post_dict = {

"entry": "weibo",

"gateway": "1",

"from": "",

"savestate": "7",

"userticket": "1",

"vsnf": "1",

"service": "miniblog",

"encoding": "UTF-8",

"pwencode": "rsa2",

"sr": "1280*800",

"prelt": "529",

"url": "http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack",

"rsakv": json_data["rsakv"],

"servertime": json_data["servertime"],

"nonce": json_data["nonce"],

"su": s_user_name,

"sp": s_pass_word,

"returntype": "TEXT",

}

# (6) 判定能否需求输进考证码,假如需求,获得考证码并停止挨码操纵

if json_data.get("showpin", None) == 1:

url = "http://login.sina.com.cn/cgi/pin.php?r=%d&s=0&p=%s" % (int(time.time()), json_data["pcid"])

with open("captcha.jpeg", "wb") as file_out:

file_out.write(self.opener.open(url).read())

code = input("请输进考证码:")

# cid, code = self.yundama.get_captcha(self.opener.open(url).read(), "captcha.jpeg", "image/jpeg", codetype="1005")

# if not code:

# return False

post_dict["pcid"] = json_data["pcid"]

post_dict["door"] = code

# (7) 按照机关的postdata,登录微专

login_url_1 = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)&_=%d" % int(time.time())

json_data_1 = json.loads(spider.get_html_content(self.opener.open(login_url_1, data=spider.make_post_data(post_dict))))

if json_data_1["retcode"] == "0":

# 登录后有一个跳转, 机关跳转链接的postdata

post_dict = {

"callback": "sinaSSOController.callbackLoginStatus",

"ticket": json_data_1["ticket"],

"ssosavestate": int(time.time()),

"client": "ssologin.js(v1.4.18)",

"_": int(time.time()*1000),

}

login_url_2 = "https://passport.weibo.com/wbsso/login?" + urllib.parse.urlencode(post_dict)

html_data = spider.get_html_content(self.opener.open(login_url_2), charset="gbk")

json_data_2 = json.loads(re.search("<span class='MathJax_Preview'><img src='http://python.jobbole.com/wp-content/plugins/latex/cache/tex_d91626e87dc0c68a5173e9a7eb5dad84.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="(?P<result>.*)" /></span><script type='math/tex'>(?P<result>.*)</script>", html_data).group("result"))

# 查抄登录能否胜利,并获得用户独一ID,用户昵称等

if json_data_2["result"] is True:

self.user_uniqueid = json_data_2["userinfo"]["uniqueid"]

self.user_nick = json_data_2["userinfo"]["displayname"]

logging.warning("WeiBoLogin succeed: %s", json_data_2)

else:

logging.warning("WeiBoLogin failed: %s", json_data_2)

else:

logging.warning("WeiBoLogin failed: %s", json_data_1)

return True if self.user_uniqueid and self.user_nick else False

def get_username(self):

"""

get username, encrypt file: http://tjs.sjs.sinajs.cn/t5/register/js/page/remote/loginLayer.js

"""

username_quote = urllib.parse.quote_plus(self.user_name)

username_base64 = base64.b64encode(username_quote.encode("utf-8"))

return username_base64.decode("utf-8")

def get_json_data(self, su_value):

"""

get the value of "servertime", "nonce", "pubkey", "rsakv" and "showpin", etc

"""

post_data = urllib.parse.urlencode({

"entry": "weibo",

"callback": "sinaSSOController.preloginCallBack",

"rsakt": "mod",

"checkpin": "1",

"client": "ssologin.js(v1.4.18)",

"su": su_value,

"_": int(time.time()*1000),

})

try:

response = self.opener.open('http://login.sina.com.cn/sso/prelogin.php?'+post_data)

data = spider.get_html_content(response, charset="utf-8")

json_data = json.loads(re.search("<span class='MathJax_Preview'><img src='http://python.jobbole.com/wp-content/plugins/latex/cache/tex_2113437cb5d6c60798b4b1eaf9e54223.gif' style='vertical-align: middle; border: none; padding-bottom:2px;' class='tex' alt="(?P<data>.*)" /></span><script type='math/tex'>(?P<data>.*)</script>", data).group("data"))

except Exception as excep:

json_data = {}

logging.error("WeiBoLogin get_json_data error: %s", excep)

logging.debug("WeiBoLogin get_json_data: %s", json_data)

return json_data

def get_password(self, servertime, nonce, pubkey):

"""

get legal password, encrypt file: http://tjs.sjs.sinajs.cn/t5/register/js/page/remote/loginLayer.js

"""

string = (str(servertime) + '\t' + str(nonce) + '\n' + str(self.pass_word)).encode("utf-8")

public_key = rsa.PublicKey(int(pubkey, 16), int("10001", 16))

password = rsa.encrypt(string, public_key)

password = binascii.b2a_hex(password)

return password.decode()

if __name__ == '__main__':

logging.basicConfig(level=logging.DEBUG, format="%(asctime)s\t%(levelname)s\t%(message)s")

# 测试登录,输进微专的用户名战暗码

weibo = WeiBoLogin()

weibo.login("username", "password")

本文做者:笑虎

您的每次批评及转收是我为您供给最出色的内乱容的动力,帮转起去,感谢。

假如您出有存眷本 头条号 请先存眷。

同时存眷微疑公家账号:Mobile_Internet (也能够第一工夫理解到最新的开辟头条资讯。)

立刻参加QQ群:326254067 (法式员取源代码 (群2))
回复

使用道具 举报

 

精彩评论8

正序浏览
tiantian987 发表于 2019-5-11 15:13:59 | 显示全部楼层
 
不错 很细致!
回复 支持 反对

使用道具 举报

 
feitain321 发表于 2019-5-11 15:23:28 | 显示全部楼层
 
不错
回复 支持 反对

使用道具 举报

 
fiOcEswi 发表于 2019-5-11 15:36:01 | 显示全部楼层
 
不错,我用的是另一个登录接口,没这么复杂,不过条条大路通罗马,学习了,收藏下
回复 支持 反对

使用道具 举报

 
﹏澈 发表于 2019-5-14 13:11:50 | 显示全部楼层
 
我也来顶一下..
回复 支持 反对

使用道具 举报

 
Zany 发表于 2019-5-14 13:16:43 来自手机 | 显示全部楼层
 
确实不错,顶先
回复 支持 反对

使用道具 举报

 
●﹎甜美、纯洁 发表于 2019-5-14 13:24:14 来自手机 | 显示全部楼层
 
垃圾内容,路过为证。
回复 支持 反对

使用道具 举报

 
咖啡吧1 发表于 2019-5-14 13:27:45 来自手机 | 显示全部楼层
 
前排,哇咔咔
回复 支持 反对

使用道具 举报

 
天空°天然蓝i 发表于 2019-5-14 13:30:13 来自手机 | 显示全部楼层
 
介是神马?!!
回复 支持 反对

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

排行榜
作者专栏

关注我们:微信公众号

官方微信

APP下载

全国客服QQ:

3388506817

Email:3388506817#qq.com

【版权声明】本站大部分内容由网友自发贡献,本站不拥有所有权,不承担相关法律责任,如有侵权请告知,本站将立刻删除涉嫌侵权内容。

Copyright   ©2015-2016  乐云媒自媒体之家Powered by©Discuz!技术支持:乐送网络     ( 津ICP备17006261号 )