如何使用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读写二进制文件的方法
May 09 Python
使用python将图片按标签分入不同文件夹的方法
Dec 08 Python
Django ManyToManyField 跨越中间表查询的方法
Dec 18 Python
正确理解Python中if __name__ == '__main__'
Jan 24 Python
python 实现selenium断言和验证的方法
Feb 13 Python
python下载微信公众号相关文章
Feb 26 Python
python实现接口并发测试脚本
Jun 25 Python
python中hasattr()、getattr()、setattr()函数的使用
Aug 16 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
Nov 19 Python
python3 assert 断言的使用详解 (区别于python2)
Nov 27 Python
用什么库写 Python 命令行程序(示例代码详解)
Feb 20 Python
Elasticsearch py客户端库安装及使用方法解析
Sep 14 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
php操作JSON格式数据的实现代码
2011/12/24 PHP
关于初学PHP时的知识积累总结
2013/06/07 PHP
Yii入门教程之目录结构、入口文件及路由设置
2014/11/25 PHP
php图像处理类实例
2015/07/28 PHP
php获取网站根目录物理路径的几种方法(推荐)
2017/03/04 PHP
PHP中的empty、isset、isnull的区别与使用实例
2019/03/22 PHP
JS实现仿google、百度搜索框输入信息智能提示的实现方法
2015/04/20 Javascript
DIV+CSS+jQ实现省市联动可扩展
2016/06/22 Javascript
详解jQuery中ajax.load()方法
2017/01/25 Javascript
layui弹出层效果实现代码
2017/05/19 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
2018/01/26 Javascript
vue组件之间数据传递的方法实例分析
2019/02/12 Javascript
VUE中V-IF条件判断改变元素的样式操作
2020/08/09 Javascript
详解Vue的异步更新实现原理
2020/12/22 Vue.js
[01:00:06]加油DOTA_EP01_网络版
2014/08/09 DOTA
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
python定时检查启动某个exe程序适合检测exe是否挂了
2013/01/21 Python
剖析Django中模版标签的解析与参数传递
2015/07/21 Python
python 实现求解字符串集的最长公共前缀方法
2018/07/20 Python
Python面向对象之继承和组合用法实例分析
2018/08/27 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
2019/02/21 Python
详解Python中pandas的安装操作说明(傻瓜版)
2019/04/08 Python
Python判断三段线能否构成三角形的代码
2020/04/12 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
2020/07/01 Python
Python中logger日志模块详解
2020/08/04 Python
python 多线程爬取壁纸网站的示例
2021/02/20 Python
受希腊女神灵感的晚礼服、鸡尾酒礼服和婚纱:THEIA
2018/04/15 全球购物
Under Armour安德玛荷兰官网:美国高端运动科技品牌
2019/07/10 全球购物
游戏商店:Eneba
2020/04/25 全球购物
什么是索引指示器
2012/08/20 面试题
创建无烟单位实施方案
2014/03/29 职场文书
爱心捐助倡议书
2014/05/19 职场文书
2014年党员自我评议总结
2014/09/23 职场文书
教师辞职书范文
2015/02/26 职场文书
预备党员表决心的话
2015/09/22 职场文书
了解Redis常见应用场景
2021/06/23 Redis