如何使用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 相关文章推荐
PHP webshell检查工具 python实现代码
Sep 15 Python
Python中time模块与datetime模块在使用中的不同之处
Nov 24 Python
利用python爬取软考试题之ip自动代理
Mar 28 Python
Python 内置函数进制转换的用法(十进制转二进制、八进制、十六进制)
Apr 30 Python
对python Tkinter Text的用法详解
Oct 11 Python
如何在django里上传csv文件并进行入库处理的方法
Jan 02 Python
Python 实现日志同时输出到屏幕和文件
Feb 19 Python
解决Jupyter Notebook使用parser.parse_args出现错误问题
Apr 20 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
Jun 09 Python
一文详述 Python 中的 property 语法
Sep 01 Python
Python爬虫之自动爬取某车之家各车销售数据
Jun 02 Python
Python实现Hash算法
Mar 18 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
PHPMailer邮件类利用smtp.163.com发送邮件方法
2008/09/11 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
2017/01/17 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
2017/02/08 PHP
ThinkPHP5.1框架数据库链接和增删改查操作示例
2019/08/03 PHP
jQuery 工具函数学习资料
2010/04/29 Javascript
javascript倒计时功能实现代码
2012/06/07 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
2015/04/12 Javascript
JavaScript知识点总结之如何提高性能
2016/01/15 Javascript
AngularJS通过ng-route实现基本的路由功能实例详解
2016/12/13 Javascript
5种JavaScript脚本加载的方式
2017/01/16 Javascript
jQuery实现导航回弹效果
2017/02/27 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
微信运维交互机器人的示例代码
2018/11/12 Javascript
微信小程序基于picker实现级联菜单
2019/02/15 Javascript
js form表单input框限制20个字符,10个汉字代码实例
2019/04/12 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
vue中实现Monaco Editor自定义提示功能
2019/07/05 Javascript
使用Node.js在深度学习中做图片预处理的方法
2019/09/18 Javascript
vue简单练习 桌面时钟的实现代码实例
2019/09/19 Javascript
javascript绘制简单钟表效果
2020/04/07 Javascript
使用JavaScript通过前端发送电子邮件
2020/05/22 Javascript
利用React高阶组件实现一个面包屑导航的示例
2020/08/23 Javascript
[02:26]2016国际邀请赛8月3日开战 中国军团出征西雅图
2016/08/02 DOTA
Python3基础之条件与循环控制实例解析
2014/08/13 Python
Python pass详细介绍及实例代码
2016/11/24 Python
django认证系统实现自定义权限管理的方法
2018/07/16 Python
Python pyinotify模块实现对文档的实时监控功能方法
2018/10/13 Python
Tesserocr库的正确安装方式
2018/10/19 Python
python自动化UI工具发送QQ消息的实例
2019/08/27 Python
zooplus意大利:在线宠物商店
2019/08/07 全球购物
澳大利亚一站式数码相机商店:CameraPro
2020/03/09 全球购物
请解释接口的显式实现有什么意义
2012/05/26 面试题
short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
2014/09/26 面试题
会计电算化应届生自荐信
2014/02/25 职场文书
高一语文教学反思
2016/02/16 职场文书
Win11 Beta 预览版 22621.575 和 22622.575更新补丁KB5016694发布(附更新内容大全)
2022/08/14 数码科技