如何使用Python的Requests包实现模拟登陆


Posted in Python onApril 27, 2018

前段时间喜欢用python去抓一些页面玩,但都基本上都是用get请求一些页面,再通过正则去过滤。

今天试了一下,模拟登陆个人网站。发现也比较简单。读懂本文需要对http协议和http会话有一定的理解。

注明:因为模拟登陆的是我的个人网站,所以以下代码对个人网站和账号密码做了处理。

网站分析

爬虫的必备第一步,分析目标网站。这里使用谷歌浏览器的开发者者工具分析。

通过登陆抓取,看到这样一个请求。

上方部分为请求头,下面部分为请求是传的参数。由图片可以看出,页面通过表单提交了三个参数。分别为_csrf,usermane,password。

其中csrf是为了预防跨域脚本伪造。原理很简单,就是每一次请求,服务器生成一串加密字符串。放在隐藏的input表单中。再一次请求的时候,把这个字符串一起传过去,为了验证是否为同一个用户的请求。

如何使用Python的Requests包实现模拟登陆

因此,我们的代码逻辑就有了。首先请求一次登录页面。然后分析页面,拿到csrf字符串。最后把这个字符串和账号密码一起传给服务器用来登录。

第一份代码

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import requests
import re

# 头部信息
headers = {
 'Host':"localhost",
 'Accept-Language':"zh-CN,zh;q=0.8",
 'Accept-Encoding':"gzip, deflate",
 'Content-Type':"application/x-www-form-urlencoded",
 'Connection':"keep-alive",
 'Referer':"http://localhost/login",
 'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
}

# 登陆方法
def login(url,csrf):
 data = {
 "_csrf" : csrf,
 "username": "xiedj",
 "password": "***"
 }

 response = requests.post(url, data=data, headers=headers)
 return response.content


# 第一次访问获取csrf值
def get_login_web(url):
 page = requests.get('http://localhost/login')
 reg = r'<meta name="csrf-token" content="(.+)">'
 csrf = re.findall(reg,page.content)[0]
 login_page = login(url,csrf)
 print login_page


if __name__ == "__main__":
 url = "http://localhost/login/checklogin"
 get_login_web(url)

代码看起来好像没有什么问题。然而执行的时候出错了。核查了一下,错误的原因是,csrf验证失败!

再多次确认获取的csrf和请求登录的csrf字符串没问题了之后,我想到了一个问题。
如果,大家还不知道错误原因的话,这里可以暂停思考一个问题。“服务器如何知道,第一次请求获取csrf和第二次post登录请求是同一个用户?”

到这,应该都清楚了,如果要登录成功,需要解决如何让服务相信两次请求是同一个用户。这里需要用到http会话(不清楚的可以自行百度,这里简单介绍)。

http协议是一个种无状态的协议。为了使这种无状态变得有状态,因此引进了会话。简单的讲,通过session去记录这个状态。当一个用户第一次请求web服务的时候,服务器会生成一个session,用于保存这个用户的信息。同时,在返回给用户端时,把这个sessionID保存在cookies里。当用户再一次请求的时候,浏览器会把这个cookies带上。因此在服务器端就能知道多次请求是否为同一个用户。

因此我们的代码,需要在第一次请求的时候拿到这个sessionID。第二次请求的时候把这个sessionID一起传过去。而requests厉害的地方就是,一句简单requests.Session(),就能使用这个会话对象。

第二份代码

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import requests
import re

# 头部信息
headers = {
 'Host':"localhost",
 'Accept-Language':"zh-CN,zh;q=0.8",
 'Accept-Encoding':"gzip, deflate",
 'Content-Type':"application/x-www-form-urlencoded",
 'Connection':"keep-alive",
 'Referer':"http://localhost/login",
 'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
}

# 登陆方法
def login(url,csrf,r_session):
 data = {
 "_csrf" : csrf,
 "username": "xiedj",
 "password": "***"
 }

 response = r_session.post(url, data=data, headers=headers)
 return response.content


# 第一次访问获取csrf值
def get_login_web(url):
 r_session = requests.Session()
 page = r_session.get('http://localhost/login')
 reg = r'<meta name="csrf-token" content="(.+)">'
 csrf = re.findall(reg,page.content)[0]


 login_page = login(url,csrf,r_session)
 print login_page


if __name__ == "__main__":
 url = "http://localhost/login/checklogin"
 get_login_web(url)

成功获取登陆后的页面

如何使用Python的Requests包实现模拟登陆

由代码可以知道,requests.Session()启动会话对象后,第二次请求会自动把上一次的sessionID一起传过去。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python常用内置模块之xml模块(详解)
May 23 Python
Python实用技巧之利用元组代替字典并为元组元素命名
Jul 11 Python
python实现ID3决策树算法
Aug 29 Python
Python面向对象程序设计OOP深入分析【构造函数,组合类,工具类等】
Jan 05 Python
python笔记之mean()函数实现求取均值的功能代码
Jul 05 Python
Python使用random模块生成随机数操作实例详解
Sep 17 Python
python中图像通道分离与合并实例
Jan 17 Python
适合Python初学者的一些编程技巧
Feb 12 Python
你需要学会的8个Python列表技巧
Jun 24 Python
python和C++共享内存传输图像的示例
Oct 27 Python
Python scrapy爬取起点中文网小说榜单
Jun 13 Python
python实现对doc、txt、xls等文档的读写操作
Apr 02 Python
Python可变参数*args和**kwargs用法实例小结
Apr 27 #Python
python实现对文件中图片生成带标签的txt文件方法
Apr 27 #Python
python模拟表单提交登录图书馆
Apr 27 #Python
Python 读取指定文件夹下的所有图像方法
Apr 27 #Python
python sys,os,time模块的使用(包括时间格式的各种转换)
Apr 27 #Python
python读取文件名称生成list的方法
Apr 27 #Python
python实现图书馆研习室自动预约功能
Apr 27 #Python
You might like
WIN98下Apache1.3.14+PHP4.0.4的安装
2006/10/09 PHP
MySQL GBK→UTF-8编码转换
2007/05/24 PHP
php实现搜索一维数组元素并删除二维数组对应元素的方法
2015/07/06 PHP
php、java、android、ios通用的3des方法(推荐)
2016/09/09 PHP
PHP 接入微信扫码支付总结(总结篇)
2016/11/03 PHP
自制PHP框架之设计模式
2017/05/07 PHP
基于laravel Request的所有方法详解
2019/09/29 PHP
JS 拼图游戏 面向对象,注释完整。
2009/06/18 Javascript
jQuery生成asp.net服务器控件的代码
2010/02/04 Javascript
jquery 删除cookie失效的解决方法
2013/11/12 Javascript
jquery获得keycode的示例代码
2013/12/30 Javascript
jQuery中replaceWith()方法用法实例
2014/12/25 Javascript
easyui Draggable组件实现拖动效果
2015/08/19 Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
2016/02/17 Javascript
AngularJS动态生成div的ID源码解析
2016/08/29 Javascript
js Canvas实现圆形时钟教程
2016/09/19 Javascript
AngularJS动态绑定HTML的方法分析
2016/11/07 Javascript
Jquery属性的获取/设置及样式添加/删除操作技巧分析
2019/12/23 jQuery
OpenLayers实现图层切换控件
2020/09/25 Javascript
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
Python遍历目录中的所有文件的方法
2016/07/08 Python
利用python微信库itchat实现微信自动回复功能
2017/05/18 Python
Python Dataframe 指定多列去重、求差集的方法
2018/07/10 Python
详解django中url路由配置及渲染方式
2019/02/25 Python
pyqt5中QThread在使用时出现重复emit的实例
2019/06/21 Python
Python Pandas 箱线图的实现
2019/07/23 Python
Tensorflow 使用pb文件保存(恢复)模型计算图和参数实例详解
2020/02/11 Python
HTML5网页录音和上传到服务器支持PC、Android,支持IOS微信功能
2019/04/26 HTML / CSS
HTML5 canvas 基本语法
2009/08/26 HTML / CSS
美体小铺波兰官方网站:The Body Shop波兰
2019/09/03 全球购物
介绍一下Linux中的链接
2016/05/28 面试题
综合素质评价个性发展自我评价
2015/03/06 职场文书
2015年工程部工作总结
2015/04/30 职场文书
Spring Boot 整合 Apache Dubbo的示例代码
2021/07/04 Java/Android
springboot入门 之profile设置方式
2022/04/04 Java/Android
Go gRPC进阶教程gRPC转换HTTP
2022/06/16 Golang