作者:matrix
发布时间:2020-02-25
分类:Python
Python中单个地址进行请求我都是使用header的cookie中添加会话信息,简单干脆。但是多个域名跳转请求的时候就出现了问题,多域名的话需要按照域名host作为key来缓存,这岂不是很麻烦?
requests.Session()也很少使用,这次正好试试。requests.Session()可以作为全局变量来保存请求的cookies会话信息。这样在脚本的单次执行中可以很好的关联请求会话信息,避免要求多次登录的情况出现。
环境:python 3.7
Session 单次会话
这里所谓单次会话
其实就是单次运行脚本的一种效果
如果想要下次重新运行脚本依旧使用之前的cookies就必须要持久化处理。
import requests
session = requests.Session()
response1 = session.post('https://passport.baidu.com/v2/?login&tag=hhtjim.com')
response2 = session.get('http://www.baidu.com/?tag=pang)
response1请求会返回Set-Cookie
的响应头,Session会记录Set-Cookie的值然后在response2中携带Cookie
的请求头。这些都是会话处理的效果,也就是requests自动完成。这样如果response1登录成功,则后续请求就可以直接进行,避免手动携带Cookie
Session本地持久化
现在需求是本地保存cookies信息,避免重新执行脚本的时候还要求登录。
本来没找到现成的方法只能自己序列化存储cookies数据,然后载入的时候反序列化就好了。但是后面看到http.cookiejar.MozillaCookieJa
这些函数可以处理目前的问题。
import requests,os
http.cookiejar import MozillaCookieJar
session = requests.Session() #作为全局变量使用
#载入cookies
path = 'cookies.txt' #设置cookies文件保存路径
s = MozillaCookieJar(path)
os.path.isfile(path) and s.load(path, ignore_discard=True, ignore_expires=True)#存在文件则载入
session.cookies = s #使用MozillaCookieJar进行会话管理
response1 = session.post('https://passport.baidu.com/v2/?login&tag=hhtjim.com')
#触发保存会话到本地文件
session.cookies.save(ignore_discard=True, ignore_expires=True)
response2 = session.get('http://www.baidu.com/?tag=pang)
上面操作就可以实现本地持久化存储,如果过期则会自动使用过期的Session请求续签。相对于单次会话其实就多了load和save操作,知道这基本原理也能够自己实现。
⚠️注意:
ignore_discard=True
参数确保有开启,否则使用save方法
不会保存到本地,load()
处也是一致,避免无法读取。
如果想要清空会话使用clear()
方法即可,再save()方法执行文件保存。
Note that the save() method won’t save session cookies anyway, unless you ask otherwise by passing a true ignore_discard argument.
参考:
https://stackoverflow.com/questions/13030095/how-to-save-requests-python-cookies-to-a-file
https://zhuanlan.zhihu.com/p/42950252
作者:matrix
发布时间:2015-05-17
分类:兼容并蓄
我之前不会编写函数,都是用的别人做的。后来慢慢学会就逐步添加想要的功能,但是问题出现了。
我修改的函数(用于curl抓取页面)的相关设置太多,导致函数的形参多的冒泡,使用起来很麻烦
function curl_get($url, $re=0,$ua=0,$ip=1,$post=0,$followLocation=0......){}//像这样
curl_get($url, 0,0,0,$post,0,1,0......)//每次调用的时候很蛋疼
最近难以忍受调用这种形式的函数,遂修改下
function curl_get($url, $array=array('re'=>0,'ua'=>0,'ip'=>1,'post'=>0,followLocation=>0,......)){}
刚开始没发现使用上有问题,但是后来真闯到鬼了,明明默认的形参是ip=1,但是打死都没反应
curl_get($url, $array=array('post'=>0))
后来知道是怎么回事:调用函数时的array('post'=>0)参数覆盖了形参$array=array('re'=>0,'ua'=>0,'ip'=>1...),等于是这样的话除了设置的post数组,其他的数组都没有设置(包括形参)。。。好吧,看下面解决办法
解决方案1
function curl_get($url, $array=array())
{
$defaultOptions = array(
're'=>0,
'ua'=>0,
'ip'=>1,
'post'=>0,
'followLocation'=>0,
//......
);
$array = array_merge($defaultOptions, $array);
//do......
}
解决方案2
function curl_get($url,$str='') {
$str_deaful='re=0&ua=0&ip=1&post=0&followLocation=0...';
parse_str($str_deaful,$arr);
parse_str($str,$arr2);
$array = array_merge($arr,$arr2);
//do......
}
参考:http://segmentfault.com/q/1010000000192291
作者:matrix
发布时间:2014-05-12
分类:零零星星
学校用的是正方教务系统,这玩意做的太恶心了。
用php模拟登录前进行fiddler软件抓包。
每个学校的正方教务系统略有不同,这里仅仅是个样本。
根据抓包结果找到提交所需的post数据
__VIEWSTATE=内容&tbYHM=内容&tbPSW=内容&ddlSF=%D1%A7%C9%FA&imgDL.x=39&imgDL.y=13
说明:第一个内容是登录页面里找到的,第二、三个内容是用户名和密码
判断是否登录成功
成功登录后页面会302跳转到/xsmainfs.aspx?xh=XXX的URL
php代码参考:
<?php
$url = '';//正方教务系统登录地址
$ID = '';
$PA = '';
$cookieid = Get_SessionId($url);//获取登录页面的会话ID
/*
is_login()函数判断是否登录成功
*/
function is_login()
{
global $url,$ID,$PA,$cookieid;
preg_match('#value="([^"]+)"#', curl_get($url), $vi);
$p = '__VIEWSTATE=' . urlencode($vi[1]) . '&tbYHM=' . $ID . '&tbPSW=' . $PA . '&ddlSF=%D1%A7%C9%FA&imgDL.x=39&imgDL.y=13'; //默认学生
$co = curl_get($url, $p, 0, 0, 0, array('Cookie: ASP.NET_SessionId=' . $cookieid));
//curl_get('地址/xsleft.aspx?flag=grxx', array('Cookie: ASP.NET_SessionId=' . $cookieid)); //获取基本信息以前必须访问这个地址
return strpos($co, "/xsmainfs.aspx?xh=" . $ID)? true : false ;
}
function curl_get($url, $add_arry_header = 0)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16'));
if ($add_arry_header)
{
curl_setopt($ch, CURLOPT_HTTPHEADER, $add_arry_header);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$get_url = curl_exec($ch);
curl_close($ch);
return $get_url;
}
function Get_SessionId($u) // 获取aspx的会话ID
{
$a = get_headers($u);
$a = str_replace(array(';', ':'), '&', $a[6]);
parse_str($a, $aa);
return $aa['ASP_NET_SessionId'] ;
}
?>
说明:代码不完全可用,只是参考,记录。
ps:
正方教务系统的登录地址还有default4.aspx的精简登录框,模拟这个的话应该更简单。