第3章Web应用架构与协议

Web服务器存储了Web页面,按照一定的方式响应客户端的请求。理解Web服务器的工作原理,对于掌握和设计网络爬虫具有重要意义。本章简述Web服务器的应用架构,重点对网站页面文件的组织与内容生成、HTTP、状态保持技术以及Robots协议进行详细介绍。


3.1常用的Web服务器软件
3.1.1流行的Web服务器软件

常见的Web服务器软件有Apache、IIS(Internet Information Server)、Nginx、Lighttpd、Zeus、Resin、Tomcat等。


Apache是使用范围很广的Web服务器软件,是Apache软件基金会的一个开放源代码的跨平台网页服务器。它可以运行在几乎所有主流的计算机平台上。Apache的特点是简单、速度快、性能稳定。它支持基于IP或域名的虚拟主机,支持代理服务器,支持安全套接字层(Secure Socket Layer,SSL)等。目前,互联网网站主要使用它作为静态资源服务器,也可以作为代理服务器转发请求,同时结合Tomcat等Servlet容器处理JSP等动态网页。Apache Web服务器软件网站页面如图31所示。





图31Apache Web服务器软件网站页面




Nginx是一个高性能的HTTP和反向代理服务器,国内使用Nginx作为Web服务器的网站也越来越多,其中包括新浪博客、网易新闻、搜狐博客等门户网站频道,在3万以上访问次数的高并发环境下,Nginx的处理能力相当于Apache的10倍。
Nginx Web服务器软件网站页面如图32所示。






图32Nginx Web服务器软件网站页面




IIS(Internet信息服务)是微软公司主推的Web服务器,IIS与Windows Server完全集成在一起,因此用户能够利用Windows Server和新技术文件系统
(New Technology File System,NTFS)
内置的安全特性建立强大、灵活且安全的Internet和Intranet站点。IIS Web服务器软件网站页面如图33所示。





图33IIS Web服务器软件网站页面




Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发。因为Tomcat技术先进、性能稳定,而且免费,所以深受Java爱好者的喜爱,并得到了部分软件开发商的认可,是目前比较流行的Web应用服务器。Tomcat Web服务器软件网站页面如图34所示。




图34Tomcat Web服务器软件网站页面



3.1.2在Python中配置Web服务器

Python 3提供了小型Web服务器软件的功能,可以很方便地进行Web页面的开发和测试。以Windows操作系统为例,具体过程如下。

(1) 通过执行cmd命令进入Windows控制台。

(2) 切换到Web服务器的虚拟根目录,也就是存放网页的根目录位置。

(3) 执行如下命令。



python -m http.server 端口号






以下是一个例子,假设虚拟根目录是E:\xxx,则进入控制台后执行以下命令。



C:\>e:

E:\>cd xxx

E:\xxx>python -m http.server 8080






那么,启动成功后控制台显示如下。



Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...






之后,可以在浏览器中输入http://localhost:8080/浏览E:\xxx中的页面和文件,在浏览的过程中控制台默认
输出每个点击访问记录,样例如下。



127.0.0.1 - - [05/Nov/2019 15:43:32] "GET / HTTP/1.1" 200 -

127.0.0.1 - - [05/Nov/2019 15:43:36] "GET /1.html HTTP/1.1" 200 -

127.0.0.1 - - [05/Nov/2019 15:43:46] "GET /20.html HTTP/1.1" 200 -

127.0.0.1 - - [05/Nov/2019 15:44:03] "GET /4.html HTTP/1.1" 200 -

127.0.0.1 - - [05/Nov/2019 15:44:12] "GET /ch.txt HTTP/1.1" 200 -








3.2Web服务器的应用架构

基于Web的互联网应用都离不开Web服务器,在门户网站、网络论坛、电子商务网站等典型应用中,核心部件都是Web服务器。Web服务器为互联网用户提供页面信息访问服务,基本的访问方式包括浏览信息、发布信息等形式。

3.2.1典型应用架构


从应用架构的角度看,Web服务器与客户端构成一种Client/Server的技术体系。在实际应用中需要考虑网站内容的可管理性、网站的并发能力、容错能力以及网站的可维护性等许多问题。针对这些问题有不同的解决方案,由此产生不同的应用架构。4种典型的应用架构描述如下。


1.  Client/Server

最简单的Web应用架构是单纯的Client/Server架构,它也是其他架构的基础,如图35所示。其中,客户端可以是各种浏览器,也可以是爬虫程序。

在这种架构中,一方面,Web服务器作为存储器,各种HTML文件可以直接存储在Web服务器的硬盘上,根据用户的请求情况再


图35Client/Server架构


访问这些文件; 另一方面,Web服务器也是一个执行机构,能够处理用户的请求。在网络爬虫技术中,这种应用架构适用于静态网页的处理,每个静态网页对应硬盘上的一个文件。

2.  Client/Server/Database


在很多Web应用中,并不能简单地从Web服务器的硬盘上读取HTML文件内容推送给用户,而是需要读取后台数据库或访问其他服务器。相应地,在Web应用架构中就必须增加数据库服务器,如图36所示。




图36Client/Server/Database架构




在这种架构中,Web服务器上的HTML文件中通常存在一些动态脚本,这些脚本在用户请求时由Web服务器执行。在执行过程中访问数据库,获取数据访问结果,Web服务器再将执行结果编码成HTML,推送给客户端。在网络爬虫技术中,这种架构支持了动态网页的实现。也就是说,网页中的主体内容是来自数据库或其他服务器,而不是直接存在Web服务器的HTML文件中。因此,动态网页的采集会消耗更多的服务器资源,
包括Web服务器内存、网络带宽以及数据库服务器的连接,
爬虫采集策略优化时要考虑这些因素。


3.  Web服务器集群

互联网Web服务器提供了开放式服务,可能会有大量用户并发访问的情况出现。在这种情况下,为了保证用户访问的体验度和容错性,Web服务器通常需要进行高可用和负载均衡设计。


负载均衡就是根据某种任务均衡策略把客户端请求分发到集群中的每台服务器上,让整个服务器群均衡地处理网站请求。因此,集群是这种应用架构的典型特征和核心之一,通常用多台Web服务器构成一个松耦合系统,这些服务器之间通过网络通信实现相互协作,共同承载所有客户端的请求压力。如图37所示的应用架构就是这种集群架构,整个集群对外来看是一台Web服务器。




图37Web服务器集群



在这种架构中,网络爬虫每次连接到网站的IP地址可能并不是固定的,因此如果网络爬虫进行了DNS缓存优化设计,就应当考虑到Web服务器集群的这种具体情况。

4. 虚拟主机


虚拟主机是另一种常见的Web应用架构,它是指在一台服务器上配置多个网站,使得每个网站看起来具有独立的物理计算机。虚拟主机的实现方法有以下3种。


(1) 基于IP地址的方法。在服务器上绑定多个IP,配置Web服务器,把网站绑定在不同的IP上。当客户端或爬虫访问不同的IP地址时就得到不同网站的响应。



(2) 基于端口的方法。不同网站共享一个IP地址,但是通过不同的端口实现对不同网站的访问。这时
客户端访问的URL的形式为http://hostname:port/,需要指定端口。


(3) 基于主机名的方法。设置DNS将多个域名解析到同一个IP地址上,IP地址对应的服务器上配置Web服务端,添加多个网站,为每个网站设定一个主机名。因为HTTP访问请求头里包含有主机名(即host属性)信息,所以当Web服务器收到访问请求时就可以根据不同的主机名访问不同的网站。


3.2.2Web页面的类型


从Web网页的组成结构来看,一个标准的网页一般包含4部分,即内容、结构、表现效果和行为。内容是网页中直接传达给阅读者的信息,包括文本、数据、图片、音/视频等; 结构是指Web页面的布局,对内容进行分类使之更具有逻辑性,符合用户的浏览习惯; 表现效果是指对已经结构化的内容进行视觉感官上的渲染,如字体、颜色等; 行为是指网页内容的生成方式。


根据Web页面组成结构中的信息内容的生成方式,可以将Web页面分为静态页面、动态页面、伪静态页面三大类。静态
页面随着互联网的出现而出现,虽然目前有大量的交互式动态页面能很好地提升用户体验,但是由于静态页面除了Web服务外,不需要其他服务的支持,对服务器的资源消耗少,所以这种类型的页面在现阶段仍然被广泛使用。动态页面一般需要数据库等其他计算、存储服务的支持,因此需要消耗更多的服务端资源。Web服务器在响应爬虫命令请求时,不管是静态页面还是动态页面,服务器返回给爬虫的信息一般都是封装成为HTML格式。因此,对于页面解析器,在处理Web服务器响应信息时,只要处理HTML格式的内容即可。


静态页面以HTML文件的形式存在于Web服务器的硬盘上,其内容和最终显示效果是事先设计好的,在环境配置相同的终端上的显示效果是一致的,并且这些内容、表现效果等由且仅由HTML、JavaScript、CSS等语言控制。因此,静态页面的内容、结构和表现效果是固定的,其行为也比较简单,即在制作网页时直接保存到硬盘文件。

从实际应用的角度来看,目前互联网上大部分都是动态页面。动态页面是相对静态页面而言的,具有明显的交互性,能根据用户的要求和选择动态改变。动态页面的主要特征如下。


(1) 页面内容是可变的,不同人、不同时间访问页面时,显示的内容可能不同。

(2) 页面结构也是允许变化的,但为了提升用户浏览的体验,结构一般不会频繁改变。

(3) 在表现效果上,页面中不同部分的效果会随着内容的变化而变化。

(4) 页面行为是区别于静态页面最主要的特征,动态页面并不是直接把内容存储到文件中,而是要进一步执行内容生成步骤,通常的方式有访问数据库等。


除了静态页面和动态页面外,还有一类页面称为伪静态页面,这种页面的出现是为了增强搜索引擎爬虫的友好界面。伪静态页面是以静态页面展现出来,但实际上是用动态脚本来处理的。为了达到这个目的,伪静态页面技术通常采用404错误处理机制
或rewrite技术实现将静态的URL页面请求转换成内部的动态访问,再将结果以同样的URL返回给用户。


伪静态页面的URL本质上可以理解成不带“=”的参数,是将参数转换为URL的子目录或文件名的一部分。例如,某论坛中同一个帖子的伪静态页面地址及其对应的动态页面地址分别如下。



http://****.com/htm_data/7/1985527.html

http://****.com/read.php?fid=7&tid=1985527






其中,伪静态页面地址的htm_data后面的7以及1985527分别与动态页面地址的fid=7和tid=1985527对应。又如,股吧论坛一个帖子对应的URL是https://guba.eastmoney.com/news/300059/948261749.html,其后缀名为html,该URL实际上是一个伪静态页面,因为页面中的帖子及其对应的回帖内容必定是动态生成的。当服务器收到伪静态页面的URL地址请求后提取出URL中相应的部分,如本例中的300059和948261749,并作为动态参数构造动态请求,在执行完成后将结果返回给客户端。


3.2.3页面文件的组织方式

大量的Web页面文件在Web服务器中的组织管理方式对于提升页面的可维护性是非常重要的。下面以Tomcat为例说明服务器的页面文件管理方式。


如图38所示,在D盘的Tomcat安装目录下有子目录webapps,该子目录是Tomcat规定的虚拟根目录。在该子目录下有aaa和bbb两个子目录,而aaa下还有一个子目录images。其中,aaa下有两个文件a1.html和a2.html; bbb下有一个文件b1.html; images子目录下有3个文件,分别为p1.gif、p2.gif、p3.gif。


假设按照Tomcat的默认端口8080,那么在浏览器中访问a1.html的URL为



http://127.0.0.1:8080/aaa/a1.html






其相应的结果如图39所示,页面中的图片在a1.html中是通过<img src="images/p1.gif">来获得。这里的images/p1.gif就表示在当前目录中访问images子目录下的p1.gif,而由于访问的是a1.html文件,当前目录就是aaa。




图38Tomcat的目录结构






图39a1.html的访问方式及效果





下面的HTML代码则展示了a1.html页面中超链接的3种写法。

(1) 采用相对链接,访问a2.html。



<p><img SRC="images/p1.gif"> <a href="a2.html"> a2</a></p>






(2) 采用相对链接,访问b1.html,..表示上级目录,此处即为虚拟根目录。



<p><img SRC="images/p2.gif"> <a href="..\bbb\b1.html"> b1</a></p>






(3) 采用http开始的完整URL绝对链接,访问b1.html。



<p><img SRC="images/p3.gif"> <a href="http://127.0.0.1:8080\bbb\b1.html"> b1</a></p>






从这个例子可以看出,对于爬虫,在获取a1.html页面之后要寻找其中的href超链接。对于绝对链接,只需要把
href=后面的字符串提取出来即可; 而对于相对链接,没有完整的http,单纯从这个href所指定的链接无法知道其真正的结果,需要进行超链接的转换。


为了简化相对路径的转换,在HTML中提供了<base>标签,用来指定页面中所有超链接的基准路径。例如,如果在a1.html中增加如下<base>标签: 



<base href="http://127.0.0.1:8080/aaa/" />






那么就意味着该文件中的所有超链接都以根目录下的aaa子目录为当前目录。因此,作为爬虫程序,也应当检查HTML文档中是否存在<base>标签。
如果不存在,则需要自行解析href的指向,并转换为绝对链接。





3.3Robots协议
3.3.1Robots协议的来历


普通的Web网站提供了开放式的空间,用户只要通过浏览器即可直接访问,大部分新闻网站、机构主页都属于这种形式。另一种Web网站页面则提供有限的开放式空间,需要经过身份识别后进一步访问更多页面信息,最常用的方法是要求用户输入用户名和口令信息,验证通过后访问Web页面。典型的这种Web网站页面是在线购物、社交媒体等网站中的个人相关信息页面。


对于搜索引擎爬虫,可以畅通无阻地采集第一种Web页面,也可以在适当配置后以动态页面的方式访问第二种
Web页面。因此,不管哪种类型的Web页面,最终都可以被搜索引擎收录而永久存储,并提供给用户任意搜索。这个结果在一定程度上增加了网站被其他人了解的可能性,为网站带来一定的流量增加。但是,某些页面可能是临时性的,或者不希望永久地存储于搜索引擎中。


为了给Web网站提供灵活的控制方式决定页面是否能够被爬虫采集,1994年搜索行业正式发布了一份行业规范,即Robots协议。Robots协议又称为爬虫协议、机器人协议等,其全称是Robots Exclusion Protocol,即“网络爬虫排除协议”。这一协
议几乎被所有搜索引擎采纳,包括Google、Bing、百度、搜狗等。随着互联网大数据时代的到来,目前互联网上除了搜索引擎的爬虫外还存在大量的非搜索引擎爬虫,该协议也就成为各类爬虫行为的行业规范。


3.3.2Robots协议的规范与实现


网站通过Robots协议告诉爬虫哪些页面可以抓取,哪些页面不能抓取。Robots协议指定了某种标识的爬虫能够抓取的目录或不能抓取的目录,也就是访问许可策略。这些访问许可的定义写在一个名为robots.txt的文件中,该文件需要放在网站的虚拟根目录中。它可以公开访问,即在浏览器中打开网站后,在网站首页的地址后面添加/robots.txt,如果网站设置了访问许可,按
Enter键就可以看到网站的Robots协议,即robots.txt文件的内容。

robots.txt文件的具体约定如下。


(1) 文件中包含一个或多个记录,每个记录由一个或多个空白行隔开。每个记录由多行组成,每行的形式为



<field>:<optionalspace><value><optionalspace>






记录指出了每个字段及其对应的值。字段名有UserAgent、Disallow、Allow,每个记录就是由这些关键词来规定爬虫的访问许可。


在一个记录中可以有多个UserAgent、多个Disallow或Allow。


(2) UserAgent的使用方式是UserAgent [agent_name],其中agent_name有两种典型形式,即*和具体的爬虫标识。例如
: 



User-Agent:* 表示所定义的访问许可适用于所有爬虫

User-Agent: Baiduspider表示所定义的访问许可适用于标识为Baiduspider的爬虫






一些常见的爬虫标识有Baiduspider、Baiduspiderimage、Baiduspidernews、Googlebot、YoudaoBot、Sogou web spider、Sosospider、EasouSpider等,从名字本身可以看出爬虫是属于哪个公司的。这些标识是爬虫自己确定的,并对外公开,
如百度的爬虫可以在http://baidu.com/search/spider.htm查到。


(3)  
Disallow和Allow的使用方法相同,只是决定了不同的访问许可。这种访问许可是针对目录、文件或页面而言的,即允许或不允许访问。Robots协议的默认规则是一个目录如果没有显式声明为Disallow,它是允许访问的。


下面以Disallow为例进行说明。

Disallow的典型写法如下。



Disallow:/

Disallow:/homepage/

Disallow:/login.php







Disallow指定的字段值可以是一个全路径,也可以是部分路径,任何以该字段值开始的URL都会被认为是不允许访问的,
如Disallow:/help就蕴含着不允许访问/help.html和/help/index.html等,而Disallow:/help/不会限制对
/help.html的访问,但是对/help/index.html限制访问。


接下来看一些典型的例子。

1) https://www.taobao.com/robots.txt


摘录两条记录,分别表示该网站对Bingbot和360Spider的访问许可。可以看出,对于前者,除了8条许可访问外,其他都是不允许抓取的; 而对于360Spider,只有3条许可访问。



User-Agent: Bingbot

Allow:/article

Allow:/oshtml

Allow:/product

Allow:/spu

Allow:/dianpu

Allow:/oversea

Allow:/list

Allow:/ershou

Disallow:/



User-Agent: 360Spider








Allow:/article

Allow:/oshtml

Allow:/ershou

Disallow:/






2) https://www.baidu.com/robots.txt

摘录最后3条记录,前两条分别表示该网站对yisouspider和EasouSpider的访问许可。可以看出,除了8条不允许访问外,其他没有写的目录都是允许抓取的。最后一条记录表示除了前面定义的爬虫外,其他爬虫不允许访问整个网站
(Disallow:/)。



User-Agent: yisouspider

Disallow:/baidu

Disallow:/s?

Disallow:/shifen/

Disallow:/homepage/

Disallow:/cpro

Disallow:/ulink?

Disallow:/link?

Disallow:/home/news/data/



User-Agent: EasouSpider

Disallow:/baidu

Disallow:/s?

Disallow:/shifen/

Disallow:/homepage/

Disallow:/cpro

Disallow:/ulink?

Disallow:/link?

Disallow:/home/news/data/



User-Agent:*

Disallow:/






3) http://www.xinhuanet.com/robots.txt


新华网的robots.txt文件非常简单,可以看出,它允许所有爬虫抓取该网站的所有页面。实际上,这种做法等同于网站根目录下没有robots.txt文件。



# robots.txt for http://www.xinhuanet.com/



User-Agent:*

Allow:/






由此可见,Robots协议通过Allow与Disallow的搭配使用,对爬虫的抓取实行限制或放行。如果网站大部分是不允许爬虫抓取的,则可以像淘宝一样,定义允许访问的模式,其他的则不允许。反之,如果大部分是允许抓取的,则可以参考百度的做法,显式定义不允许访问的模式。结合自己网站的结构,选择合适的编写方法能够简化robots.txt文件。例如,
某个网站的根目录下有a1~a10子目录,只允许爬虫抓取a10子目录,按照前面的叙述,写成
以下左边的形式就比右边的形式要简洁得多。





User-Agent:*

Allow:/a10/

Disallow:/a
User-Agent:*

Disallow:/a1/

Disallow:/a2/

Disallow:/a3/

Disallow:/a4/

Disallow:/a5/

Disallow:/a6/

Disallow:/a7/

Disallow:/a8/

Disallow:/a9/





上述基本功能及书写方式得到了大部分搜索引擎爬虫的支持,除此以外,还有一些拓展功能。虽然它们的普及性还不是很广,但随着行业规范意识的增强,在编写爬虫程序时了解这些拓展功能,对于设计更加友好的爬虫是非常有益的。这些拓展功能主要有通配符的使用、抓取延时、访问时段、抓取频率和Robots版本号。


(1) 通配符的使用。
Robots中的许可记录允许使用通配符表示Disallow或Allow的范围。这些通配符包括*、$,需要注意的是问号(?)并不作为一个通配符。通配符*代表0个或多个任意字符(包括0个)。$表示行结束符,用来表示至此结束,后面不跟其他任何字符。


通配符举例说明如下。



Disallow:/pop/*.html






上述语句
表示不允许爬虫访问/pop/目录下任何扩展名为.html的文件。



Disallow:/private*/






上述语句表示不允许访问以private开头的所有子目录。



Disallow:/*.asp$






上述语句表示不允许访问以.asp结尾的文件,这就排除了以.aspx结尾的文件。


(2) 抓取延时。
规定爬虫程序两次访问网站的最小时间延时(以秒为单位),实际上就是规定了爬虫页面抓取的最高请求频率。使用方法如下。




Crawl-delay: 10






表示两次访问网站的最小时间延时为10s。


(3) 访问时段。
某些网站可能存在业务高峰期,为了使服务器将更多资源分配给它的用户,不希望爬虫抓取数据。这时可以在许可记录中增加一行: 




Visit-time: 0100-0500






表示允许爬虫在凌晨1:00到5:00访问网站,其他时间段不允许访问。

(4) 抓取频率。
这是用来限定URL读取频率的一个选项,使用方法如下。



Request-rate: 40/1m 0100 - 0759






表示在1:00到07:59之间,以不超过每分钟40次的频率进行访问。

(5) Robots版本号。
用来指定Robots协议的版本号,也就是编写robots.txt文件时遵守的Robots协议版本。虽然版本号只是一个选项,但是如果增加这个字段,就会让爬虫程序在解析robots.txt文件时更加方便。例如:



Robot-version: Version 2.0






指出了所使用的版本为2.0。

目前,上述拓展功能在各网站中的使用还不流行,一个例子是知乎的robots
.txt文件(https://www.zhihu.com/robots.txt),其针对EasouSpider的约定就包含了Requestrate、Crawldelay,也使用了通配符。简书(https://www.jianshu.com/robots.txt)也有类似的使用。



User-agent: EasouSpider

Request-rate: 1/2 # load 1 page per 2 seconds

Crawl-delay: 10

Disallow: /login

Disallow: /logout

Disallow: /resetpassword

Disallow: /terms

Disallow: /search

Disallow: /notifications

Disallow: /settings

Disallow: /inbox

Disallow: /admin_inbox

Disallow: /*?guide*





3.4HTTP






超文本传输协议(HTTP)是互联网上
广泛使用的一种网络协议,所有WWW文件都必须遵守这个标准。HTTP是基于TCP/IP
的应用层协议,采用请求/响应模型。通过使用Web浏览器、网络爬虫或其他工具,客户端向服务器的指定端口(默认端口为80)发送一个HTTP请求,服务器根据接收到的请求向客户端发送响应信息。

3.4.1HTTP版本的技术特性



自1991年
HTTP的第一个版本HTTP 0.9正式提出以来,HTTP
已经经历了3个版本的演化,目前大部分
网页使用HTTP 1.1作为主要的网络通信协议。


1.  HTTP 0.9

HTTP 0.9是第一个版本的HTTP,发布于1991年。HTTP 0.9只允许客户端发送GET这一种请求,不支持请求头,因此客户端无法向服务器端传递太多消息。


HTTP 0.9规定服务器只能响应HTML格式的字符串,即纯文本,不能响应其他的格式,该协议只用于用户传输HTML文档。服务器响应后,TCP网络连接就会关闭。如果请求的网页不存在,服务器也不会返回任何错误码。

2.  HTTP 1.0


1996年,HTTP的第二个版本HTTP 1.0发布。HTTP 1.0是以HTTP 0.9为基础发展起来的,并且在HTTP 0.9
的基础上增加了许多新内容。


(1) HTTP 1.0增加了请求方法。HTTP 1.0支持GET、POST、HEAD等请求方法,每种方法规定的客户端与服务器之间通信的类型不同。



(2) HTTP 1.0扩大了可处理的数据类型,引入了MIME(Multipurpose Internet Mail Extensions)机制,除了纯文本外,还可以传输图片、音频、视频等多媒体数据。


(3) HTTP 1.0在处理TCP网络连接时与HTTP 0.9相似,但在请求头中加入了Connection: keepalive,要求服务器在请求响应后不要关闭TCP连接,实现TCP连接复用,可以避免Web页面资源请求时重新建立TCP连接的性能降低。

3.  HTTP 1.1


HTTP 1.1是目前使用最广泛的HTTP版本,于1997年发布。HTTP 1.1与之前的版本相比,主要改进集中在提高性能、安全性以及数据类型处理等方面。



(1) HTTP 1.1与HTTP 1.0最大的区别在于默认采用持久连接。客户端不需要在请求头中特别声明(Connection:keepalive),但具体实现是否声明依赖于浏览器和Web服务器。请求响应结束后TCP连接默认不关闭,降低了建立TCP连接所需的资源和时间消耗。


(2) HTTP 1.1支持管道(Pipelining)方式,可以同时发送多个请求。在发送请求的过程中,客户端不需要等待服务器对前一个请求的响应就可以直接发送下一个请求。管道方式提高了请求的传输速度,提高了HTTP的效率。但是,服务器在响应时必须按照接收到请求的顺序发送响应,以保证客户端收到正确的信息。


(3) HTTP 1.1添加了Host(请求头)字段。随着虚拟主机这种应用架构技术的发展,在一台物理服务器上可以存在多个虚拟主机,这些虚拟主机共享一个IP地址。HTTP 1.1在请求头中加入Host字段,指出要访问服务器上的哪个网站。


4.  HTTP 2

HTTP 2于2015年发布,在实现与HTTP 1.1完全语义兼容的基础上,
实现了性能大幅提升,但尚未真正应用。


(1) HTTP 2允许客户端与服务器同时通过同一个连接发送多重请求/响应消息,实现多路复用。HTTP 2加入了二进制分帧层,HTTP消息被分解为独立的帧,帧可以交错发送,然后再根据流标识符在接收端重新拼装,使得HTTP 2可以在一个TCP连接内
同时发送请求和响应。


(2) HTTP 2压缩大量重复的首部信息,提升通信效率。HTTP每次通信都会携带首部,当一个客户端想从一个服务器请求许多资源时,可能会出现大量重复的请求头信息。特别是在HTTP 1.1中,请求头信息以纯文本的形式发送,大量重复的请求头信息重复传输对网络运输资源的消耗很大。


3.4.2HTTP报文


HTTP报文中存在着多行内容,一般由ASCII码串组成,各字段的长度是不确定的。HTTP报文可分为两种,即请求报文和响应报文。由于目前大部分网站使用HTTP 1.1或HTTP 1.0版本,所以这里
主要介绍这两种报文。

(1) Request Message(请求报文): 客户端→服务器端,由客户端向服务器端发出请求,用于向网站请求不同的资源,包括HTML文档、图片等。

(2) Response Message(响应报文): 
服务器端→客户端,
服务器响应客户端的请求时发送的回应报文,可以是HTML文档的内容,也可以是图片的二进制数据等。


HTTP 1.1的请求报文和响应报文在形式上与HTTP 1.0相同,只是HTTP 1.1中添加了一些头部扩充HTTP 1.0的功能。因此,本节关于请求报文和响应报文的叙述既适用于HTTP 1.0,也适用于HTTP 1.1。


1. 请求报文

HTTP规定请求报文由起始行、头部(headers)以及实体(entitybody)构成,报文格式如下。




<method> <request-URL> <version>

<headers>



<entity-body>






第一行是报文的起始行,也称为请求行,由请求方法<method>、请求URL<requestURL>、协议版本<version>构成。HTTP 1.0和HTTP 1.1支持GET、POST、HEAD请求方法,每种方法规定了客户端与服务器之间通信的类型。


接下来是头部<headers>,也称为请求头,包含了客户端处理请求时所需要的信息。根据实际需要,请求头可以是多行的形式。服务器据此获取客户端关于请求的若干配置参数,如语言种类信息、

客户端信息、优先级等内容。头部本质来说是包含若干属性的列表,格式为“属性名:属性值”。如
AcceptLanguage: zhCN,将zhCN值赋给AcceptLanguage属性,表示客户端可接收的语言为简体中文。


请求头之后是换行符,表示请求头的结束。


请求头结束标志之后是请求报文的实体<entitybody>,也称为请求体,是传输的内容构成。请求体通过param1=value1&param2=value2的键值对形式将要传递的请求参数(通常是一个页面表单中的组件值)编码成一个格式化串。


下面是一个向服务器传递name和password参数的请求体实例。



name=Jack&password=1234






值得注意的是,在使用GET和HEAD方法请求网页时没有请求体。其请求参数表现在请求行,附加在URL后面,使用
问号(?)来表示URL的结尾和请求参数的开始
,不同参数之间用“&”连接
。例如,下面的命令行表示客户端使用HTTP 1.0请求网页example.html,请求方法为GET。



GET /example.html? name=Jack&password=1234 HTTP/1.0

User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64)

Accept: text/html







这种方式可传递的参数长度受限
,并且一些类似银行卡号、密码的敏感内容也不宜出现在URL中,解决这些问题的方法就是使用POST
。HEAD与GET方法的区别在于,服务器端接收到HEAD请求信息只返回响应头,不会返回响应体; 而使用POST方法请求时,客户端发送给服务器
的参数允许更多,其请求数据都封装在请求体中。

2. 响应报文


与请求报文类似,HTTP响应报文由起始行、头部(headers)以及实体(entitybody)构成。HTTP 1.0和HTTP 1.1规定的响应报文格式如下。



<version><status><reason-phrase>

<headers>



<entity-body>






响应报文
与请求报文的区别在于第一行,响应报文的起始行也称为响应行,由协议版本、状态码、原因短语构成。状态码为表示网页服务器HTTP响应状态的3位数字,客户端或爬虫可从状态码中得到服务器响应状态,后续将对状态码进行详细介绍。原因短语为状态码提供了文本形式的解释。例如,下面的命令为服务器响应行,以“200 OK”结束,表明响应操作成功。




HTTP 1.0 200 OK






报文的响应行之后是响应头,包含服务器响应的各种信息,其结构与请求头一致,都是“属性名:属性值”的格式。


报文的<entitybody>部分是响应体,响应体是HTTP要传输的内容。根据响应信息的不同,响应体可以是多种类型的数据,如图片、视频、CSS、JS、HTML页面或应用程序等。如果客户端请求的是HTML页面,则响应体为HTML代码。客户端依据响应头中ContentType的属性值对响应体进行解析,如果属性值与响应体不对应,客户端可能无法正常解析。


以下是一个响应报文的例子,表示向客户端成功响应了text/plain类型的文本。



HTTP/1.0 200 OK

Content-Type: text/plain



<html>

<body>example</body>

</html>






3.4.3HTTP头部


在HTTP的请求报文和响应报文中都有头部信息块,其中的每个记录具有“属性名:属性值”的形式。
例如,请求http://www.fudan.edu.cn/2016/index.html页面,从浏览器的开发者模式下
观察到的
请求头和响应头信息块分别如图310和图311所示
。除了第一行的请求行和响应行外,其他都是头部信息。





图310请求头信息块






图311响应头信息块


从图310中可以看出,一些属性在爬虫程序设计中是非常重要的,如UserAgent、Accept、AcceptLanguage、Cookie、ContentType
,可以直接在程序中填写相应的属性名和属性值设置爬虫的行为和特征。


属性名可以归纳为三大类,即请求头和响应头都可以使用的属性,以及请求头和响应头分别独有的属性。完整的头部属性名可以在
Wikipedia网站的List_of_HTTP_header_fields页面中查阅(https://en.wikipedia.org/wiki/List_of_HTTP_header_fields),一些常用的属性名说明如下。


1)  Accept


Accept请求头表示可接受的响应内容。与Accept首部类似的还有AcceptCharset、AcceptEncoding、AcceptLanguage等,分别表示客户端可接受的字符集、可接受的编码方式和可接受的语言。


值得注意的是,HTTP 1.1为这些首部引入了品质因子q,用来表示不同版本的可用性。
例如,在图310请求头中,Accept属性值中出现了两个品质因子q,服务器会优先选取品质因子值高的对应资源版本作为响应。


2)  Host


HTTP 1.1添加Host首部表示服务器的域名以及服务器所监听的端口号(如果所请求的端口为所请求服务的标准端口,则端口号可以省略)。例如,图310请求头中的Host: www.fudan.edu.cn字段表示客户端请求访问域名为
www.fudan.edu.cn的服务器的80端口。HTTP 1.0认为每台服务器都绑定一个唯一的IP地址,但目前多个虚拟站点可以共享同一个IP地址。在加入Host首部后,其属性值可以明确指出要访问IP地址上的哪个站点。应当指出的是,请求头中必须包含Host首部,否则服务器会返回一个错误。

3)  Range


HTTP 1.1在请求头中添加Range首部表示客户端向服务器请求资源的某个部分。例如
,Range: bytes=0499表示客户端请求资源的前500字节。Range首部的使用避免了服务器向客户端发送其不需要的资源
。从Web服务器下载文件时,所使用的断点续传功能就依赖于这个首部的使用。


4)  UserAgent


UserAgent首部表示客户端的身份标识字符串。通过该字符串使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等信息。对于浏览器,该字符串的标准格式为



浏览器标识 (操作系统标识; 加密等级标识; 浏览器语言) 渲染引擎标识 版本信息






一个例子如下。



User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36






对于爬虫程序,该属性的值是可以随便设置的,并不一定要遵守浏览器和格式,但是这种方式增加了服务器识别爬虫的风险。


5)  ContentRange


与请求头的Range属性相对应,HTTP 1.1在响应头中添加ContentRange首部表示服务器已响应客户端请求的部分资源。例如,ContentRange: bytes 0499/1024表示已经响应了实体的前500字节,斜杠后面的数字表示实体的大小。


6)  ContentType


ContentType首部表示响应体的MIME类型,即响应体是用何种方式编码的。常见的媒体编码格式类型有text/html(HTML格式)、text/plain(纯文本格式)、image/jpeg(JPG图片格式); 以application开头的媒体格式类型有application/json(JSON数据格式)、application/pdf(PDF格式)、application/msword(Word文档格式)。

7)  Cookie


Cookie是请求报文中可用的属性,也是客户端最重要的请求头属性。Cookie存储了客户端的一些重要信息,如身份标识、所在地区等,通常是一个文本文件。在向服务器发送URL请求时可以将文件内容读出,附加在HTTP的请求头中,能免去用户输入信息的麻烦。



8)  SetCookie


SetCookie是响应报文中可用的属性,服务器可以在响应报文中使用该属性将一些信息推送给客户端。客户端收到信息后,通常的做法是生成Cookie文件,将这些内容保存起来。例如,以下代码表示服务器发送UserID、Version信息给客户端,希望客户端将它们保存到Cookie文件中。



Set-Cookie: UserID=Wang12; Version=1






9)  Connection


Connection是请求报文和响应报文中都可用的属性,通过该属性可以允许客户端和服务器指定与请求/响应连接有关的选项,相应的属性值有keepalive、Upgrade。


从前面关于HTTP版本技术特性演变的介绍可以看出,keepalive是一个很重要的属性。然而,
并不是设置了keepalive就意味着可以建立永久连接。在默认情况下,Web服务端设置了keepalive的超时时间,当连接超过指定的时间时,服务端就会主动关闭连接。此外,为了缩短HTTP响应时间,避免Web服务拥塞,并发连接数
(即同时处于keepalive的连接的数目)也不宜太大。

10)  ContentLength

ContentLength首部表示响应体的长度,其属性值用八进制字节表示。

11)  ContentLanguage

ContentLanguage首部表示响应内容所使用的语言。

12)  Server

Server首部表示服务器名称。

13)  Warning


HTTP 1.1在响应头中添加Warning首部以更好地描述错误和警告信息,这些信息通常比原因短语更详细。


14)  Referer


HTTP Referer是header的一部分,当浏览器向Web服务器发送请求时一般会带上Referer属性值,告诉服务器该请求是从哪个页面链接过来的。例如,B页面上有一个链接到A页面,当用户从该链接访问A页面时,发送给A页面所在的Web服务器的请求头中的Referer值就是B。

3.4.4HTTP状态码


HTTP状态码(HTTP Status Code)是用来表示Web服务器HTTP响应状态的3位数字代码。通过HTTP状态码可以得知服务器的响应状态,以便更好地处理通信过程中遇到的问题。对于爬虫程序,可以通过这个状态码确定页面抓取结果。HTTP状态码由RFC 2616规范定义,并得到RFC 2518、RFC 2817、RFC 2295、RFC 2774、RFC 4918等规范扩展。状态码
有5种类别,即信息、成功、重定向、请求错误和服务器错误。


状态码由3位数字构成,如200表示请求成功。数字中的第一位代表了状态码所属的响应类别,共有五大类状态码,分别以
数字1~5开头,如表31所示。


表31状态码的类别



状态码类别分 类 描 述


1××信息状态码表示服务器已经收到请求,需要继续处理。在HTTP 1.0中没有定义1××状态码,因此除非在某些试验条件下,服务器不要向客户端发送1××响应
2××成功状态码表示请求被成功接收并处理
3××重定向状态码表示需要采取进一步操作才能完成请求。这类状态码用来重定向,对于GET或HEAD请求,服务器响应时会自动将客户端转到新位置
4××客户端错误状态码表示客户端的请求可能出错,服务器无法处理请求
5××服务器错误状态码表示服务器在处理请求的过程中内部发生了错误



服务器返回的状态码后常跟有原因短语(如200 OK),原因短语为状态码提供了文本形式的解释。


状态码的个数很多,被RFC 2616、RFC 2518、RFC 2817等规范定义的状态码有60多个,但实际常见的状态码仅有10个,通常用在爬虫程序中。


1) 成功状态码

200(OK)是最常见的状态码,表示服务器成功处理了请求,同时请求所希望的响应头或实体随着响应返回。


202(Accepted)表示服务器已接受请求,但尚未处理。


2) 重定向状态码

301(Moved Permanently)表示请求的资源已经永久地移动到新位置,即被分配了新的URL。客户端以后的新请求都应使用新的URL。

304(Not Modified)表示客户端发送了一个带条件的GET请求且该请求已被允许,而文档的内容并没有改变。在返回的响应报文中不含实体的主体部分。

3) 客户端错误状态码

400(Bad Request)表示请求报文存在语法错误或参数错误,服务器无法理解。

401(Unauthorized)表示当前请求要求客户端进行身份认证或是身份认证失败。对于需要登录的网页,服务器可能返回此响应。

403(Forbidden)表示服务器已经理解请求,但是拒绝执行。拒绝执行可能是客户端无访问权限等原因,但服务器无须给出拒绝执行的理由。

404(Not Found)表示请求失败,在服务器上无法找到请求的资源。


4) 服务器错误状态码

500(Internal Server Error)表示服务器执行请求时发生错误,无法完成请求。当服务器端的源代码出现错误时会返回这个状态码。

503(Server Unavailable)表示服务器超负载或正停机维护,无法处理请求。这个状态通常是临时的,将在一段时间后恢复。


3.4.5HTTPS


超文本传输安全协议(Hypertext Transfer Protocol Secure,HTTPS)是一种通过计算机网络进行安全通信的传输协议,简单来说,HTTPS是HTTP的安全版本。HTTP报文使用明文发送,传输的信息很容易被监听和篡改; HTTPS是使用SSL/TLS加密的HTTP,可以保护传输数据的隐私和完整性,同时实现服务器的身份验证。


SSL(安全套接层)是介于HTTP与TCP之间的安全协议,SSL在传输层同时使用对称加密以及非对称加密对网络连接进行加密。其中,对称加密算法的加密与解密使用同一个密钥; 非对称加密算法的加密与解密使用不同的两个密钥,即公开密钥
(Public Key,简称公钥)和私有密钥(Private Key,简称私钥)。非对称加密与对称加密相比安全性更高,但是加密与解密花费的时间长、速度慢。因此,在准备建立连接时,SSL使用服务器的证书(公钥)将对称密钥非对称加密,保证对称密钥的安全; 在连接建立后,SSL对数据量较大的传输内容使用对称加密,提高加密效率。


传输层安全协议(Transport Layer Security Protocol,TLS)是SSL 3.0的后续版本,与SSL的内容大致相同,因此很多文章将TLS与SSL并列称呼,即SSL/TLS。


HTTPS相当于在HTTP的基础上使用SSL/TLS对传输的数据进行加密,因此HTTPS与HTTP交互最大的区别在于,使用HTTPS传输数据之前需要客户端与服务器进行一次SSL握手,在握手过程中将确立双方加密传输数据的密码信息。如图312所示,下面主要介绍SSL握手中的单向认证过程,即客户端校验服务器的证书合法性。




图312HTTPS交互过程




(1) 客户端的浏览器发送客户端SSL协议的版本号、加密算法的种类、产生的随机数以及其他在SSL协议中需要用到的信息。


(2) 服务器向客户端返回SSL协议的版本号、加密算法的种类、随机数以及其他相关信息,同时服务器还将向客户端发送自己的证书。证书用于身份验证,其中包含用于非对称加密的公共密钥。


(3) 客户端用服务器传过来的证书进行服务器信息校验。服务器信息校验的内容包括证书链是否可靠、证书是否过期、证书域名是否与当前的访问域名匹配等。如果服务器信息校验没有通过,则结束本次通信; 否则继续进行步骤(4)。


(4) 客户端随机生成一个用于后续通信的对称密钥,然后使用服务器在步骤(2)发来的公共密钥对其加密,之后将加密的对称密钥发送给服务器。



(5) 服务器使用私有密钥解密客户端发来的信息,得到用于后续通信的对称密钥。


(6) 客户端向服务器发送信息,信息中指明协商后续通信要使用的对称密钥完成,后面的通信都要使用
步骤(5)得出的对称密钥进行加密,同时通知服务器握手过程结束。


(7) 服务器也向客户端发送协商后续通信要使用的对称密钥完成,握手过程结束。


之后SSL握手结束,客户端和服务器开始使用相同的对称密钥对要传输的数据进行加密,同时进行通信完整性的检验。


3.5状态保持技术


当使用浏览器访问Web服务器上的页面时,浏览器首先会建立与Web服务器的HTTP连接,之后浏览器在这个连接上发送URL,接收服务器返回的信息,并显示在浏览器上。如果进行连接复用或持久化,后续的URL请求和响应信息接收都可以在这个连接上进行,这些请求是相互独立的。


如果前后两次URL请求之间需要共享某些数据,如在第一个页面进行了用户登录,第二个页面的访问就需要以该用户身份进行。更简单地讲,一个客户端访问服务器时,可能会在这个Web服务器上的多个页面之间不断刷新、反复连接同一个页面或向一个页面提交信息。在这种情况下,不同页面之间或同一个页面的不同次访问之间需要保持某种状态,实现这种需求的技术就是状态保持技术。


由于HTTP本身是无状态的,客户端向服务器发送一个
请求,然后服务器返回一个响应,不同URL之间的状态无法共享,即状态无法保持。在一个通信系统中要实现状态保持,只能从客户端和服务器两个角度来设计,
相应地,这两种状态保持技术就是Cookie和Session。


3.5.1Cookie


Cookie是由服务器生成,并在客户端进行保存和读取的一种信息,Cookie通常以文件形式保存在
客户端。查看Cookie的方法
因浏览器的不同而不同,图313、图314所示分别为在Chrome和
Edge浏览器中查看Cookie的方法。






图313在Chrome浏览器中查看Cookie的方法






图314在Edge浏览器中查看Cookie的方法



每个Cookie记录中包含了名字、值、过期时间、路径和域,具体解释如表32所示。



表32Cookie记录内容解释


一个Cookie记录对应行的解释取 值 样 例


nameCookie变量名uid
valueCookie变量值abcxyz001
domain+pathCookie变量所属的域、路径,即作用范围mail.fudan.edu.cn/
option可选标志1600
a过期时间(FILETIME格式)的高位整数1638219776
b过期时间(FILETIME格式)的低位整数36669619
c创建时间(FILETIME格式)的高位整数1256217104
d创建时间(FILETIME格式)的低位整数30651615
*Cookie记录分隔符



变量名(name)和变量值(value)并没有特殊的命名规定,也没有写法上的限制。由于Cookie是在服务
器生成,最终由浏览器
进行解析,所以这些名称和值一般与页面的某些变量有关。


域(domain)是指Cookie变量所属的域,也就是该Cookie的有效域范围。路径(path)是接在域后面的URL路径,最简单的路径是/,也可以是/image等形式。路径与域合在一起就构成了Cookie的作用范围,表示Cookie变量在该范围内的网页都有效,不管用户访问该目录中的哪个网页,浏览器都会将该Cookie信息附在网页头部中,并发送给服务器。


如果设置了过期时间,浏览器会把Cookie保存到硬盘上,当关闭后再次打开浏览器时,这些Cookie仍然有效直到超过设定的过期时间。如果没有设置过期时间,则表示这个Cookie的生命期为浏览器会话期,只要关闭浏览器窗口,Cookie就消失了。这种生命期为浏览器会话期的Cookie称为会话Cookie。会话Cookie一般不存储在硬盘上,而是保存在内存里。




图315某Web登录页面



这里举一个例子,
如图315所示,
在一个提供页面登录的Web页面(http://mail.fudan.edu.cn/)中
勾选“记住用户名”选项,希望浏览器记住用户名,之后随便输入一个用户名,如abcxyz001,
单击“登录”按钮,再重新加载该页面,就会发现浏览器自动填充了用户名。


这时查看mail.fudan.edu.cn的Cookie文件就会发现,文件中的一个记录如图316所示,可以看出
name和value分别为uid、abcxyz001。uid实际上就是图315中用户名输入框的名字。



在了解了Cookie的内容之后,需要了解Cookie的创建和使用方法。Cookie中记录的内容是在服务器生成的,然后通过HTTP headers从服务器发送到浏览器上。




图316Cookie文件中的

一个记录


浏览器在处理用户输入的URL时,根据其中的域名寻找是否有相应的Cookie,如果有,则进一步检查其中的作用范围。当作用范围大于或等于URL指向的位置时,浏览器会将该Cookie中的内容读出,附在请求资源的HTTP请求头上并发送给服务器。


具体的创建和使用方式与Web服务的框架和支持的语言有一定关系,但基本原理是一样的。
以上面的登录处理为例,这是一个JSP页面,假如为Login.jsp,单击“登录”按钮之后,将输入的用户名、密码提交给action="results.jsp"进行处理。那么
在results.jsp中,下面的脚本将用户输入的用户名作为Cookie的值(value),其对应的名
称(name)为username。最后通过
响应让浏览器生成一个Cookie。




String username = request.getParameter("username");

Cookie cookie1 = new Cookie("username",username); //创建Cookie

cookie1.setMaxAge(3600); //设置过期时间,以秒为单位

cookie1.setPath("/"); //设置路径

response.addCookie(cookie1);//发送到浏览器执行创建动作






当再次访问这个JSP页面时,
浏览器自动读取Cookie内容并附加在请求头中,这样
服务器
就可以通过下面的代码
获得浏览器发送的Cookie内容,并从中读取出用户名。这段代码可以嵌入自动输入用户名的页面中。




Cookie cookies[]=request.getCookies(); 

Cookie sCookie=cookies[1]; 

String username=sCookie.getValue();






接着就可以按照下面的方式将username变量赋值给输入框,然后发送给浏览器,这样在浏览器上就能看到填充的用户名了。



<input type="text" name="username" value =<%=username%> size="44">










3.5.2Session



仅使用Cookie保持状态存在一定的问题,主要表现在以下几方面。


(1) Cookie虽然可以灵活地增加name和value,但每个域名的Cookie数量、Cookie文件大小是受限的,具体数值取决于不同浏览器。例如,Firefox将每个域名的Cookie限制为最多50个,每个文件最大4KB。因此,在一些需要在客户端和Web服务器之间进行较多数据交换的应用中,使用Cookie就不合适。


(2) Cookie存在一定的安全风险,Cookie信息可以很容易被截获,如果是明文,则可能造成信息泄露。但不管是明文还是密文,都可以直接被用来伪造HTTP请求,即Cookie欺骗,冒充受害人的身份登录网站。
参考文献[8]展示了一个实际的Cookie被窃取的案例。


Session是另一种常见的在客户端与服务器之间保持状态的机制,在一定程度上解决或缓解了上述问题,准确理解其技术原理有利于设计更好的动态爬虫。


Session可以看作Web服务器上的一个内存块,能够将原本保存在Cookie中的用户信息存储在该内存块中,而客户端和服务器之间依靠一个全局唯一标识Session_id访问Session中的用户数据,这样只需要在Cookie中保存Session_id就可以实现不同页面之间的数据共享。可见,在Session机制下,除了Session_id外,其他用户信息并不保存到Cookie文件中,这解决了上述两个问题。


虽然Session_id也可能会像Cookie内容一样被截获,但通常Session_id是加密存储的。对于安全性保障更有效的机制是它的动态性,即Session是在调用HttpServletRequest.getSession(true)这样的语句时才被创建,而在符合下面3个条件之一时终止。


(1) 程序调用HttpSession.invalidate()。

(2) 服务器关闭或服务停止。

(3) Session超时,即在一定的连续时间内服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间。这个最大时长一般是30min,在服务器上可配置。


因此,只要Session在内存中的存活时间不是太长,当攻击者截获某个Session_id时,其对应的内存Session可能已经销毁了,
也就无法获得用户数据。


根据以上描述,可以得出Session、Cookie、服务器和客户端(浏览器、爬虫)之间的关系,如图317所示。





图317Session、Cookie、服务器和客户端的关系



除了提升安全性外,Session由于保留了客户端请求的内存块,因此当该请求的处理需要连接数据库等额外操作时,使用Session会大大提升请求效率。在12.3节的例子中展示了这种优势。


思考题

1. Web服务器及应用架构与网络爬虫之间是什么关系?


2. 使用Tomcat等Web服务器软件制作页面,并在浏览器中浏览。


3. 浏览器需要遵守Robots协议吗? Robots协议中主要规定了哪些方面的内容?

4. 不同版本的HTTP的主要区别是什么?


5. 使用浏览器的开发者工具查看HTTP请求报文、响应报文、状态码和Cookie。

6. 谈谈Cookie的作用。