上一节,我们讲了如何配置Charles代理,这一节我们通过模拟微博登录这个例子来看看如何使用Charles分析网站加载流程,顺便把微博模拟登录的Python代码也给实现了。

1. 用Charles记录整个登录过程

首先,我们运行Charles并开始记录。然后打开Chrome浏览器,选择使用Charles代理,打开微博首页 ,出现登录页面(如果之前登录过微博,要先退出登录)。输入用户名和密码进行登录,登录成功后就可以停止Charles的记录。这样我们就用Charles完整记录下了微博的登录过程。见图:

我们把整个登录过程写出一个Python类,它的定义为:

class WeiboLogin:

user_agent = (

'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.11 (KHTML, like Gecko) '

'Chrome/20.0.1132.57 Safari/536.11'

)

def __init__(self, username, password, cookies_tosave='weibo.cookies'):

self.weibo_user = username

self.weibo_password = password

self.cookies_tosave = cookies_tosave

self.session = requests.session()

self.session.headers['User-Agent'] = self.user_agent

接下来我们分析登录过程,并逐一实现这个类的各个方法。

2. 分析登录过程

把Charles的主窗口切换到“Sequence”标签页,

我们可以按加载时间顺序观察Charles记录的微博登录过程,我们发现第一个可疑的请求的Host是:

login.sina.com.cn

点击该条记录,下方出现该条请求的完整内容,它的路径是:

GET /sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.19)&_=1542456042531 HTTP/1.1

这个GET请求的参数_=1542456042531看起来是个时间戳,这个在ssologin.js(看后面是如何找到的)定义为preloginTimeStart,可以用int(time.time()*1000)得到。

从prelogin.php这个名字看,它是一个预登陆,即在你输入用户名和密码前,它先从服务器拿点东西过来:

用Python实现这个prelogin:

def prelogin(self):

preloginTimeStart = int(time.time()*1000)

url = ('https://login.sina.com.cn/sso/prelogin.php?'

'entry=weibo&callback=sinaSSOController.preloginCallBack&'

'su=&rsakt=mod&client=ssologin.js(v1.4.19)&'

'_=%s') % preloginTimeStart

resp = self.session.get(url)

pre_login_str = re.match(r'[^{]+({.+?})', resp.text).group(1)

pre_login = json.loads(pre_login_str)

pre_login['preloginTimeStart'] = preloginTimeStart

print ('pre_login 1:', pre_login)

return pre_login

这些预先拿过来的东西有什么用呢?目前为止还不知道,继续往下看。

补充:关于认证码

昨天最初写这篇教程的时候,没有碰到验证码。今天就碰到验证码跳出来了,真是大快人心,可以把这部分补充上了。

对比昨天的prelogin的URL参数不能发现,今天的多了两个参数:

su=xxxxx 就是加密的那个(实为base64编码)用户名

checkpin=1 告诉服务器要检查验证码(我去,自己写爬虫绝对不会这么干)

带着这两个参数请求服务器,返回来的也会多了showpin的值:

既然要显示pin(验证码),就要下载验证码,它的地址是:

https://login.sina.com.cn/cgi/pin.php?r=2855501&s=0&p=aliyun-a34a347956ab8e98d6eb1a99dfddd83bc708

这个是怎么来的呢?直接按Ctrl+F 打开“Text to Find”窗口搜索“pin.php”:

这个Find窗口很有用,它让我们可以在记录的所有请求和响应里面查找特定文本,并且它还支持正则表达式、大小写敏感、只找全词。只找全词,对查找su这样的短词很有帮助,可以过滤大量包含它的词,比如super。

这里要特别说明一下,为什么只选在”Response Body”里面查找。

因为我们是要找上面的URL是如何生成的,我们认为它是在某个js文件的某段代码实现的,所以它一定是在 Response Body 里面的,这样也可以过滤掉很多无关信息。

通过上面的过滤,直接就定位了相关代码,双击进去,再稍微一搜,就发现对应的代码了:

var pincodeUrl = "https://login.sina.com.cn/cgi/pin.php";

...

return pincodeUrl + "?r=" + Math.floor(Math.random() * 100000000) + "&s=" + size + (pcid.length > 0 ? "&p=" + pcid : "")

有了这个js,用Python来实现就易如反掌了,小猿们可以自己试试看。

有了验证码的URL,我们就用self.session下载它并保存为文件,在POST 所有login数据前,通过pin = input('>>please input pin:')来获取,加入到POST数据里面一起POST发送即可。

第二条可疑的请求的Host跟第一条一样,路径是:

POST /sso/login.php?client=ssologin.js(v1.4.19) HTTP/1.1

这是一条POST,我来看看它POST的数据,选择这条记录,点击“Contents”标签,再点击“Form”标签,可以看到它POST的数据:

这时候我们可以把这写POST的参数和prelogin得到的联系起来了。

参数:su

这个看上去是“加密”的username,即用户名。那它是怎么加密的呢?浏览器运行的是JavaScript,所以我们猜测是通过JS加密的,那么是哪段JS呢?看上面login.php路径里给了参数client=ssologin.js(v1.4.19),那我们就去ssologin.js里面找找,选择加载这个js文件的请求,“Contents”标签下面就会显示JS代码,按Ctrl+F查找username:

果然在这里,其实就是用base64编码了一下,算不上加密,于是我们就有了获得su的方法:

def encrypt_user(self, username):

user = urllib.parse.quote(username)

su = base64.b64encode(user.encode())

return su

**参数:sp**

跟su同样的思路,还是在ssologin.js里面查找password,我们发现了加密password的算法:

于是有了获得sp的方法:

def encrypt_passwd(self, passwd, pubkey, servertime, nonce):

key = rsa.PublicKey(int(pubkey, 16), int('10001', 16))

message = str(servertime) + '\t' + str(nonce) + '\n' + str(passwd)

passwd = rsa.encrypt(message.encode('utf-8'), key)

return binascii.b2a_hex(passwd)

参数:prelt

既然ssologin.js就是管登录的,那我们还是在这里找prelt,Ctrl+F 查找到

request.prelt = preloginTime;

原理prelt就是preloginTime的简称,那我们再搜索preloginTime:

preloginTime = (new Date()).getTime() - preloginTimeStart - (parseInt(result.exectime, 10) || 0)

这里的preloginTimeStart就是请求prelogin.php时的时间戳,result.exectime就是prelogin请求返回结果里面的exectime。

哈哈哈,又找到了prelt的算法,其实这个prelt就是从请求开始到现在的时间差,似乎也没那么重要,随机一个就可以,不过还是用Python实现一下:

def get_prelt(self, pre_login):

prelt = int(time.time() * 1000) - pre_login['preloginTimeStart'] - pre_login['exectime']

return prelt

目前,我们已经获得了登录的重要参数,接下来再看看登录请求的流程,在“Sequence”的 “Filter” 输入login,我们可以看到过滤后的请求,其中前三个就是登录的先后顺序:

其详细流程就是:

prelogin从服务器获得一些参数

把加密的用户名密码等参数POST给https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)

第2步返回的是html代码,html代码里面重定向到另外的url (所以我们代码里面也要实现这个重定向)

第3步返回的还是html代码,里面通过JS先实现几个跨域设置,最后重定向到另外一个url(我们也要实现这部分操作)

第4步返回的HTTP头里面重定向到另外的URL,request会跟随这个重定向,不用我们实现。

用Python实现html代码里面的JS重定向的方法就是,用正则表达式提取出JS代码里面的重定向URL,然后用requests做GET请求。

完整的登录流程的代码就是:

def login(self):

# step-1. prelogin

pre_login = self.prelogin()

su = self.encrypt_user(self.weibo_user)

sp = self.encrypt_passwd(

self.weibo_password,

pre_login['pubkey'],

pre_login['servertime'],

pre_login['nonce']

)

prelt = self.get_prelt(pre_login)

data = {

'entry': 'weibo',

'gateway': 1,

'from': '',

'savestate': 7,

'qrcode_flag': 'false',

'userticket': 1,

'pagerefer': '',

'vsnf': 1,

'su': su,

'service': 'miniblog',

'servertime': pre_login['servertime'],

'nonce': pre_login['nonce'],

'vsnf': 1,

'pwencode': 'rsa2',

'sp': sp,

'rsakv' : pre_login['rsakv'],

'encoding': 'UTF-8',

'prelt': prelt,

'sr': "1280*800",

'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.'

'sinaSSOController.feedBackUrlCallBack',

'returntype': 'META'

}

# step-2 login POST

login_url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)'

resp = self.session.post(login_url, data=data)

print(resp.headers)

print(resp.content)

print('Step-2 response:', resp.text)

# step-3 follow redirect

redirect_url = re.findall(r'location\.replace\("(.*?)"', resp.text)[0]

print('Step-3 to redirect:', redirect_url)

resp = self.session.get(redirect_url)

print('Step-3 response:', resp.text)

# step-4 process step-3's response

arrURL = re.findall(r'"arrURL":(.*?)\}', resp.text)[0]

arrURL = json.loads(arrURL)

print('CrossDomainUrl:', arrURL)

for url in arrURL:

print('set CrossDomainUrl:', url)

resp_cross = self.session.get(url)

print(resp_cross.text)

redirect_url = re.findall(r'location\.replace\(\'(.*?)\'', resp.text)[0]

print('Step-4 redirect_url:', redirect_url)

resp = self.session.get(redirect_url)

print(resp.text)

with open(self.cookies_tosave, 'wb') as f:

pickle.dump(self.session.cookies, f)

return True

代码中打印了很多信息,方便我们过程整个登录过程。

要测试我们的实现就很简单了:

if __name__ == '__main__':

weibo_user = 'your-weibo-username'

weibo_password = 'your-weibo-password'

wb = WeiboLogin(weibo_user, weibo_password)

wb.login()

修改为你的微博账户和密码就可以测试起来啦。

练习题

本文我们提到了验证码的解决方法,但并没有把相关代码加入到self.login()这个函数中,小猿们可以根据文中讲到的方法自己添加实验一下,看看是否能成功。

我的公众号:猿人学 Python 上会分享更多心得体会,敬请关注。

***版权申明:若没有特殊说明,文章皆是猿人学 yuanrenxue.com 原创,没有猿人学授权,请勿以任何形式转载。***

python爬虫登录微博_为爬虫获取登录cookies: 使用Charles和requests模拟微博登录相关推荐

  1. 基于python的网络爬虫开题报告_网络爬虫开题报告.docx

    网络爬虫开题报告 网络爬虫开题报告 篇一:毕设开题报告 及开题报告分析 开题报告如何写 注意点 1.一.对指导教师下达的课题任务的学习与理解 这部分主要是阐述做本课题的重要意义 2.二.阅读文献资料进 ...

  2. python爬虫ip限制_简单爬虫,突破IP访问限制和复杂验证码,小总结

    简单爬虫,突破复杂验证码和IP访问限制 好吧,看题目就知道我是要写一个爬虫,这个爬虫的目标网站有一些反爬取意识,所以就有了本文了. 我先说说场景吧: 由于工作需要,平时有一大堆数据需要在网上查询,并归 ...

  3. python discuz论坛帖子_[Scrapy爬虫实战]Discuz论坛版块内全部帖子获取

    先插入封面(老惯例了) 高清无码PDF见: 链接:https://pan.baidu.com/s/1qD0IBElUFTFv0F34QV6vIA 提取码:0e6n 项目源码见: 链接:https:// ...

  4. python 随机请求头_为了爬虫换个头,我用python实现三种随机请求头方式!

    相信大家在爬虫中都设置过请求头 user-agent 这个参数吧? 在请求的时候,加入这个参数,就可以一定程度的伪装成浏览器,就不会被服务器直接识别为spider.demo.code ,据我了解的,我 ...

  5. python网页爬虫菜鸟教程_【爬虫】菜鸟教程,支持翻页,存储

    1.项目简介 豆瓣相信很多人都爬过,我也把我的方法拿出来交流学习,我也是菜鸟过来的,不会省略代码,此教程纯属娱乐,大神勿喷. 2.工具 requests re pygal mysql Anacond2 ...

  6. python爬取同花顺_网络爬虫页面解析的疑问?同花顺-问财

    http://stock.10jqka.com.cn/company.shtml 搜了下汽车 25条信息 直接用爬虫爬这个网址,http://www.iwencai.com/stockpick/sea ...

  7. python如何爬虫股票数据_简单爬虫:东方财富网股票数据爬取(python_017)

    需求:将东方财富网行情中心的股票数据爬取下来,包括上证指数.深圳指数.上证A股.深圳A股.新股.中小板.创业板 等 一.目标站点分析 东方财富网的行情中心页面包含了所有股票信息.在左侧的菜单栏中包含了 ...

  8. python爬去新浪微博_荐爬虫实战 新浪微博爬取 详细分析

    目标 #2020.5.22 #author:pmy #目标:爬取最爱的绵羊的微博,包含时间,文本内容,点赞数,评论数与转发数 #在更换博主时主要在于修改headers中的referer和参数中的con ...

  9. java可以用数组存爬虫数据么_网络爬虫文件存取(TXT,JSON,CSV)特点与用法

    TXT文本存储 1.基本实例 首先,我们采用selenium的方法爬取新闻联播文字稿的首页,这是因为这个网页比较简单,本文重点在文件存取上. from selenium import webdrive ...

最新文章

  1. redis 一主二从
  2. java 自适应响应式 网站 源码 SSM 生成 静态化 手机 平板 PC
  3. 簡單安裝軟件 GNU Linux
  4. 不懂编程的产品经理如何不被程序员吊打?
  5. apache.camel_Apache Camel 2.9发布–十大变化
  6. 京东商品知识图谱,约10万商品品牌,约65万品牌销售关系
  7. neo4j︱图数据库基本概念、操作罗列与整理(一)
  8. windows 10 主题美化
  9. 兄弟打印机打印时显示服务器内部错误,打印机出现内部错误无法打印什么原因...
  10. sequel pro 格式化sql
  11. linux下python网络编程框架-twisted安装手记,linux下Python网络编程框架-Twisted安装
  12. HTML5页面结构标签
  13. matlab能做财务报表吗,基于Matlab 的零售企业财务报表分析.pdf
  14. 算数-02-史丰收算法
  15. 2020年度最值得关注论文TOP10
  16. 小程序 加快安卓手机向蓝牙设备发送大数据
  17. 关闭Tomcat报错The web application [ROOT] appears to have started a thread named [Abandoned connectio
  18. Python学习手册之数据类型
  19. 虚幻引擎图文笔记:使用MixamoConverter对Mixamo动画重定向成UESkeleton匹配动画
  20. 阿里云备案成功的域名可以用腾讯云的服务器吗?

热门文章

  1. 腾讯云代理商:腾讯云数据库成功落地国信证券 承载日均亿级交易额
  2. c++屏蔽Win10系统快捷键
  3. 极佳mysql修复数据库修复_极佳SQL数据库修复工具下载
  4. 强连通分量/点双连通分量/边双联通分量 总结
  5. DPABISurf使用教材
  6. 苹果体验店:鲜为人知的乔布斯的秘密
  7. 腾讯云iis8.5新建网站无法访问_如何建立自己的网站(零基础小白教程一)
  8. 使用LABVIEW发送邮件
  9. 杂谈:火星救援和未来城市
  10. 稳定币迎来“去中心化”转变,HAY为BNB Chain带来了什么