如何使用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批量修改文件后缀的方法
Jan 26 Python
python简单程序读取串口信息的方法
Mar 13 Python
Pandas标记删除重复记录的方法
Apr 08 Python
Python快速查找list中相同部分的方法
Jun 27 Python
Python装饰器简单用法实例小结
Dec 03 Python
python处理两种分隔符的数据集方法
Dec 12 Python
pandas实现DataFrame显示最大行列,不省略显示实例
Dec 26 Python
Centos7下源码安装Python3 及shell 脚本自动安装Python3的教程
Mar 07 Python
Python flask路由间传递变量实例详解
Jun 03 Python
Python切片列表字符串如何实现切换
Aug 06 Python
Python如何使用input函数获取输入
Aug 06 Python
python3 删除所有自定义变量的操作
Apr 08 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
PHP5.0正式发布 不完全兼容PHP4 新增多项功能
2006/10/09 PHP
PHP 高级课程笔记 面向对象
2009/06/21 PHP
php批量添加数据与批量更新数据的实现方法
2014/12/16 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
php each 返回数组中当前的键值对并将数组指针向前移动一步实例
2016/11/22 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
thinkphp5.1 文件引入路径问题及注意事项
2018/06/13 PHP
JavaScript高级程序设计(第3版)学习笔记10 再访js对象
2012/10/11 Javascript
jQuery调取jSon数据并展示的方法
2015/01/29 Javascript
JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
2015/12/02 Javascript
jQuery事件绑定on()与弹窗实现代码
2016/04/28 Javascript
老生常谈遮罩层 滚动条的问题
2016/04/29 Javascript
JS 调用微信扫一扫功能
2016/12/22 Javascript
原生js实现回复评论功能
2017/01/18 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
关于Javascript中document.cookie的使用
2017/03/08 Javascript
使用jQuery动态设置单选框的选中效果
2018/12/06 jQuery
如何自动化部署项目?折腾服务器之旅~
2019/04/16 Javascript
vue中监听路由参数的变化及方法
2019/12/06 Javascript
[52:09]2014 DOTA2华西杯精英邀请赛 5 25 NewBee VS DK第二场
2014/05/26 DOTA
[42:22]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第一局
2016/02/27 DOTA
[01:02:18]VGJ.S vs infamous Supermajor 败者组 BO3 第一场 6.4
2018/06/05 DOTA
Python和php通信乱码问题解决方法
2014/04/15 Python
python实现红包裂变算法
2016/02/16 Python
python的继承知识点总结
2018/12/10 Python
pycharm 实现显示project 选项卡的方法
2019/01/17 Python
基于python代码批量处理图片resize
2020/06/04 Python
python根据字典的键来删除元素的方法
2020/08/16 Python
详解Python 中的 defaultdict 数据类型
2021/02/22 Python
Staples美国官方网站:办公用品一站式采购
2016/07/28 全球购物
销售会计工作职责
2013/12/02 职场文书
生产部厂长职位说明书
2014/03/03 职场文书
人事专员岗位职责范本
2014/03/04 职场文书
2015年世界急救日宣传活动方案
2015/05/06 职场文书
2016大学军训通讯稿
2015/11/25 职场文书
调研报告的主要写法
2019/04/18 职场文书