整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript编程 Cookie

ookie 用于存储 web 页面的用户信息。


什么是 Cookie?

Cookie 是一些数据, 存储于你电脑上的文本文件中。

当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。

Cookie 的作用就是用于解决 "如何记录客户端的用户信息":

  • 当用户访问 web 页面时,他的名字可以记录在 cookie 中。

  • 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。

Cookie 以名/值对形式存储,如下所示:

username=John Doe

当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。


使用 JavaScript 创建Cookie

JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie。

JavaScript 中,创建 cookie 如下所示:

document.cookie="username=John Doe";

您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT";

您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/";


使用 JavaScript 读取 Cookie

在 JavaScript 中, 可以使用以下代码来读取 cookie:

var x = document.cookie;


使用 JavaScript 修改 Cookie

在 JavaScript 中,修改 cookie 类似于创建 cookie,如下所示:

document.cookie="username=John Smith; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/";

旧的 cookie 将被覆盖。


使用 JavaScript 删除 Cookie

删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

注意,当您删除时不必指定 cookie 的值。


Cookie 字符串

document.cookie 属性看起来像一个普通的文本字符串,其实它不是。

即使您在 document.cookie 中写入一个完整的 cookie 字符串, 当您重新读取该 cookie 信息时,cookie 信息是以名/值对的形式展示的。

如果您设置了新的 cookie,旧的 cookie 不会被覆盖。 新 cookie 将添加到 document.cookie 中,所以如果您重新读取document.cookie,您将获得如下所示的数据:

cookie1=value; cookie2=value;

显示所有 Cookie 创建 Cookie 1 创建 Cookie 2 删除 Cookie 1 删除 Cookie 2

如果您需要查找一个指定 cookie 值,您必须创建一个JavaScript 函数在 cookie 字符串中查找 cookie 值。


JavaScript Cookie 实例

在以下实例中,我们将创建 cookie 来存储访问者名称。

首先,访问者访问 web 页面, 他将被要求填写自己的名字。该名字会存储在 cookie 中。

访问者下一次访问页面时,他会看到一个欢迎的消息。

在这个实例中我们会创建 3 个 JavaScript 函数:

  1. 设置 cookie 值的函数

  2. 获取 cookie 值的函数

  3. 检测 cookie 值的函数


设置 cookie 值的函数

首先,我们创建一个函数用于存储访问者的名字:

function setCookie(cname,cvalue,exdays){

函数解析:

以上的函数参数中,cookie 的名称为 cname,cookie 的值为 cvalue,并设置了 cookie 的过期时间 expires。

该函数设置了 cookie 名、cookie 值、cookie过期时间。


获取 cookie 值的函数

然后,我们创建一个函数用户返回指定 cookie 的值:

function getCookie(cname){

函数解析:

cookie 名的参数为 cname。

创建一个文本变量用于检索指定 cookie :cname + "="。

使用分号来分割 document.cookie 字符串,并将分割后的字符串数组赋值给 ca (ca = document.cookie.split(';'))。

循环 ca 数组 (i=0;i<ca.length;i++),然后读取数组中的每个值,并去除前后空格 (c=ca[i].trim())。

如果找到 cookie(c.indexOf(name) == 0),返回 cookie 的值 (c.substring(name.length,c.length)。

如果没有找到 cookie, 返回 ""。


检测 cookie 值的函数

最后,我们可以创建一个检测 cookie 是否创建的函数。

如果设置了 cookie,将显示一个问候信息。

如果没有设置 cookie,将会显示一个弹窗用于询问访问者的名字,并调用 setCookie 函数将访问者的名字存储 365 天:

function checkCookie(){

完整实例

实例

functionsetCookie(cname,cvalue,exdays){vard = newDate(); d.setTime(d.getTime()+(exdays*24*60*60*1000)); varexpires = "expires="+d.toGMTString(); document.cookie = cname + "=" + cvalue + "; " + expires;}functiongetCookie(cname){varname = cname + "="; varca = document.cookie.split(';'); for(vari=0; i<ca.length; i++){varc = ca[i].trim(); if(c.indexOf(name)==0)returnc.substring(name.length,c.length); }return"";}functioncheckCookie(){varuser=getCookie("username"); if(user!=""){alert("Welcome again " + user); }else{user = prompt("Please enter your name:",""); if(user!="" && user!=null){setCookie("username",user,365); }}}

以下实例在页面载入时执行 checkCookie() 函数。

document.cookie 将以字符串的方式返回所有的 cookie,类型格式: cookie1=value; cookie2=value; cookie3=value;

一节,我们使用Charles记录微博的登录过程,并从中解析出了微博的登录细节,还用Python模拟实现了整个过程。只要微博登录不改变,我们的代码就一直可用,这也算是一劳永逸的事情了,而且程序运行中不需要人工参与,高度自动化。记得之前微博还是有验证码的,这次重新实现的这个过程中没有发现验证码的蛛丝马迹。

完全用Python实现模拟登录的过程其实是很累的,考验的是耐力、观察力、联想能力等等。虽然累,但一旦完成后面就省心了,也算是值得一试。

然而世事无常,并非所有登录都像微博那样无验证码(也许有,只是没有跳出来),更多的是像12306,知乎,哔哩哔哩那样上了变态的验证码的。有时候为了自动识别验证码耗费的精力之大难以想象,所以我们写爬虫时,要综合考量投入产出比,人工输入验证码可能是更快捷便利的方法。

今天,我们就介绍一款专门从浏览器缓存的cookies获取cookies的工具,一个Python的模块:browsercookie。

它是一个很有用的爬虫工具,通过加载你浏览器的cookies到一个cookiejar对象里面,让你轻松下载需要登录的网页内容。

browsercookie 的安装

它的源代码在bitbucket上: browsercookie

可以从源码安装,或者直接pip安装

pip install browsercookie

需要注意的是,在Windows系统下,内置的sqlite模块在加载FireFox数据库时会抛出错误。需要更新sqlite的版本:

pip install pysqlite

browsercookie 的使用


我们拿百度的首页来做实验,如果没有登录cookies,打开的首页右上角菜单栏显示登录而不显示用户名,如果有登录cookies,首页则显示用户名而不显示登录,通过在得到的html中搜索“登录”来验证这两者的不同准备工作就是,要先打开浏览器(比如Chrome, 或Firefox)登录一下百度,然后就可以关掉浏览器了,当然开着也无所谓。

首先,我们看看未登录状态下得到的标题:

In [1]: import requests
In [2]: url = 'https://baidu.com/'
In [3]: r1 = requests.get(url)
In [4]: r1.content.decode('utf-8').find('登录')
Out[4]: 1580
In [5]: r1.content.decode('utf8').find('user-name')
Out[5]: -1

由上面的实验我们看出来,没有cookies请求得到登录的信息,‘user-name’是显示登录名时的css的class,通过查找user-name再次确认没有登录。

然后,在看看从浏览器获得cookies后得到的标题:

In [11]: cjff = browsercookie.firefox()
In [12]: header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'}
In [13]: r2 = requests.get(url, cookies=cjff, headers=header)
In [14]: r2.content.decode('utf8').find('登录')
Out[14]: -1
In [15]: r2.content.decode('utf8').find('user-name')
Out[15]: 5038

通过上面的代码,我们验证了从browsercookie获取cookies并成功登录的百度。

细心的小猿们可能已经发现了,我用的cookies是从Firefox那里得来的

<code>cjff = browsercookie.firefox()</code>。

原因是,我先实验从Chrome那里获取cookies,得到的cookies里面确实也包含百度,但是就是不能登录,于是改用Firefox就轻松登录了。


browsercookie 的缺憾

前面我们也提到了从Chrome获得的cookies不能登录百度的问题,后来我又实验了几个不同的网站,有的可以也有不可以的,再次证明了这个模块的不完美。

不过,这个库用起来很简单,几行代码就可以验证它对我们要登录的网站是否起作用,所以,写爬虫遇到登录的问题不妨先拿它验证一下,万一行呢,不就省了很多精力。

还有一类问题,就是你得到了cookies,访问任何该网站的URL,它都先返回一段登录验证的html,里面通过JS重定向到不同的网址,你需要进一步解析这段JS代码才能访问到你真正想访问的目标网址,这样的操作就比较累人,这样的网站对爬虫很不友好。别猜了,我说的就是微博。

 <html>
 <head>
 <title>新浪通行证</title>
 <meta http-equiv="refresh" content="0; url='https://login.sina.com.cn/crossdomain2.php?action=login&entry=miniblog&r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogin%3Fssosavestate%3D1574046135%26url%3Dhttps%253A%252F%252Fweibo.com%252Fkaifulee%26display%3D0%26ticket%3DST-MTM3MTQ1MzA0MA%3D%3D-1542510135-gz-E235393C87F25EE4E30B221C2B5F7F37-1%26retcode%3D0&login_time=1542509978&sign=d531a8b4eed9c403'"/>
 <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
 </head>
 <body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#551a8b" alink="#ff0000">
 <script type="text/javascript" language="javascript">
 location.replace("https://login.sina.com.cn/crossdomain2.php?action=login&entry=miniblog&r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogin%3Fssosavestate%3D1574046135%26url%3Dhttps%253A%252F%252Fweibo.com%252Fkaifulee%26display%3D0%26ticket%3DST-MTM3MTQ1MzA0MA%3D%3D-1542510135-gz-E235393C87F25EE4E30B221C2B5F7F37-1%26retcode%3D0&login_time=1542509978&sign=d531a8b4eed9c403");
 </script>
 </body>
 </html>

这种异步加载的网页越来越多,尤其是前端框架ReactJS, VueJS等框架的出现让前后端分离,由浏览器运行JavaScript来渲染前端。这个时候,就需要我们的爬虫支持JavaScript的运行,此时此刻,requests等单纯的HTTP协议库已经无能为力了,我们需要更强大的工具

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
 <title> New Document </title>
 <meta name="Generator" content="EditPlus">
 <meta name="Author" content="">
 <meta name="Keywords" content="">
 <meta name="Description" content="">
 </head>
<body>
 <input type="text" id="a"/> 
 <input type="button" value="保存cookie" onclick="test()"/> 
 <input type="button" value="获取cookie" onclick="alert(getCookie('userName'))"/> 
 </body>
<script language=javascript> 

window.onload=function(){
 document.getElementById("a").value=getCookie('userName');
}
function test()
{
	var a = document.getElementById('a').value;
 SetCookie('userName',a)
}
 //获得coolie 的值
function cookie(name){ 
 var cookieArray=document.cookie.split("; "); //得到分割的cookie名值对 
 var cookie=new Object(); 
 for (var i=0;i<cookieArray.length;i++){ 
 var arr=cookieArray[i].split("="); //将名和值分开 
 if(arr[0]==name)return unescape(arr[1]); //如果是指定的cookie,则返回它的值 
 } 
 return ""; 
} 

function delCookie(name)//删除cookie
{
 document.cookie = name+"=;expires="+(new Date(0)).toGMTString();
}

function getCookie(objName){//获取指定名称的cookie的值
 var arrStr = document.cookie.split("; ");
 for(var i = 0;i < arrStr.length;i ++){
 var temp = arrStr[i].split("=");
 if(temp[0] == objName) return unescape(temp[1]);
 } 
}

function addCookie(objName,objValue,objHours){ //添加cookie
 var str = objName + "=" + escape(objValue);
 if(objHours > 0){ //为时不设定过期时间,浏览器关闭时cookie自动消失
 var date = new Date();
 var ms = objHours*3600*1000;
 date.setTime(date.getTime() + ms);
 str += "; expires=" + date.toGMTString();
 }
 document.cookie = str;
}

function SetCookie(name,value)//两个参数,一个是cookie的名子,一个是值
{
 var Days = 30; //此 cookie 将被保存 30 天
 var exp = new Date(); //new Date("December 31, 9998");
 exp.setTime(exp.getTime() + Days*24*60*60*1000);
 document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}

function getCookie(name)//取cookies函数 
{
 var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
 if(arr != null) return unescape(arr[2]); return null;
}

function delCookie(name)//删除cookie
{
 var exp = new Date();
 exp.setTime(exp.getTime() - 1);
 var cval=getCookie(name);
 if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}
</script>
</html>