Python 网络爬虫与数据采集
- 第1章 序章 网络爬虫基础
- 1 爬虫基本概述
- 1.1 爬虫是什么
- 1.2 爬虫可以做什么
- 1.3 爬虫的分类
- 1.4 爬虫的基本流程
- 1.4.1 浏览网页的流程
- 1.4.2 爬虫的基本流程
- 1.5 爬虫与反爬虫
- 1.5.1 爬虫的攻与防
- 1.5.2 常见的反爬与反反爬
- 1.6 爬虫的合法性与 robots 协议
- 1.6.1 robots 协议
- 1.6.2 查看网页的 robots 协议
- 1.7 Python 爬虫相关库
- 2. Chrome 浏览器开发者工具
- 2.1 Chrome 浏览器开发者工具简述
- 2.1.1 什么是浏览器开发者工具
- 2.1.2 浏览器开发者工具基本使用
- 2.2 浏览器开发者工具面板说明
- 2.2.1 元素 (Elements) 面板
- 2.2.2 网络 (Network) 面板 (1)
- 2.2.3 网络 (Network) 面板 (2)
- 3. HTTP 协议
- 3.1 HTTP 简介
- 3.2 主要特点
- 3.3 URL,URI,URN
- 3.3.1 URI* 统一资源标识符
- 3.3.2 URL* 统一资源定位符
- 3.3.3 URN* 统一资源名称
- 3.3.4 URI,URL,URN 的区别
- 3.4 HTTP 协议与 HTTPS 协议
- 3.4.1 HyperText
- 3.4.2 HTTP 与 HTTPS
- 3.5 HTTP 请求过程
- 3.5.1 General
- 3.5.2 请求方法 (Request Method)
- 3.5.3 状态码 (Status Code)
- 3.5.4 请求头信息 (Request Headers)
- 3.5.5 响应头信息 (Response Headers)
- 3.5.6 响应体 (Response Body)
- 3.6 Cookies 和 session
- 3.6.1 Cookies
- 3.6.2 session
- 3.6.3 Cookies 和 session 区别
第1章 序章 网络爬虫基础
1 爬虫基本概述
1.1 爬虫是什么
网络爬虫(Crawler)又称网络蜘蛛,或者网络机器人(Robots). 它是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。换句话来说,它可以根据网页的链接地址自动获取网页内容。如果把互联网比做一个大蜘蛛网,它里面有许许多多的网页,网络蜘蛛可以获取所有网页的内容。
爬虫是一个模拟人类请求网站行为, 并批量下载网站资源的一种程序或自动化脚本。
1.2 爬虫可以做什么
- 搜索引擎
- 采集金融数据
- 采集商品数据
- 采集竞争对手的客户数据
- 采集行业相关数据,进行数据分析
- 刷流量
1.3 爬虫的分类
- 通用网络爬虫
又称为全网爬虫,其爬取对象由一批 URL 扩充至整个 Web,主要由搜索引擎或大型 Web 服务商使用。 - 聚焦网络爬虫
又称为主题网络爬虫,其特点是只选择性的地爬取与预设的主题相关的页面,相比通用网络爬虫,聚焦网络爬虫仅需要爬取与主题相关的页面,极大地节省硬件及网络资源,能更快的更新保存页面,更好的满足特定人群对特定领域的需求。 - 增量网络爬虫
只对已下载的网页采取增量式更新,或只爬取新产生的及已经发生变化的网页,这种机制能够在某种程度上保证所爬取的网页尽可能的新。 - 深度网络爬虫
Web 页面按照存在的方式可以分为表层页面和深层页面两类。表层页面是只传统搜索引擎可以索引到的页面,以超链接可以达到的静态页面为主。深层页面是指大部分内容无法通过静态链接获取,隐藏在搜索表单之后的,需要用户提交关键词后才能获得的 Web 页面,如一些登陆后可见的网页。
1.4 爬虫的基本流程
1.4.1 浏览网页的流程
图 1.1: 浏览网页的流程
1.4.2 爬虫的基本流程
- 请求网页
通过 HTTP 库向目标站点发起请求,即发送一个 Request,请求可以包含额外的 headers 等
信息,等待服务器响应! - 获得相应内容
如果服务器能正常响应,会得到一个 Response,Response 的内容便是所要获取的页面内容,
类型可能有 HTML,Json 字符串,二进制数据(如图片视频)等类型。 - 解析内容
得到的内容可能是 HTML,可以用正则表达式、网页解析库进行解析。可能是 Json,可以
直接转为 Json 对象解析,可能是二进制数据,可以做保存或者进一步的处理。 - 存储解析的数据
保存形式多样,可以存为文本,也可以保存至数据库,或者保存特定格式的文件
测试案例
代码 0-0: 爬取搜狗首页的页面数据
#导 包
import requests
#step_1 : 指 定 url
url = ’https :// www . sogou . com /’
#step_2 : 发 起 请 求 :
#使 用 get 方 法 发 起 get 请 求 , 该 方 法 会 返 回 一 个 响 应 对 象 。 参 数 url 表 示 请 求 对 应 的 url
response = requests . get ( url = url )
#step_3 : 获 取 响 应 数 据 :
#通 过 调 用 响 应 对 象 的 text 属 性 , 返 回 响 应 对 象 中 存 储 的 字 符 串 形 式 的 响 应 数 据 ( 页 面 源 码
数 据 )
page_text = response . text
#step_4 : 持 久 化 存 储
with open (’sogou . html ’,’w’, encoding =’utf -8’) as fp:
fp . write ( page_text )
print (’ 爬 取 数 据 完 毕 ! ! ! ’)
1.5 爬虫与反爬虫
- 爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量。
- 反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量。
- 误伤:在反爬虫的过程中,错误的将普通用户识别为爬虫。误伤率高的反爬虫策略,效果再好也不能用。
- 拦截:成功地阻止爬虫访问。这里会有拦截率的概念。通常来说,拦截率越高的反爬虫策略,误伤的可能性就越高。因此需要做个权衡。
- 资源:机器成本与人力成本的总和。
1.5.1 爬虫的攻与防
- 攻:
Day 1 小莫想要某站上所有的电影,写了标准的爬虫 (基于 HttpClient 库),不断地遍历某站的电影列表页面,根据 Html 分析电影名字存进自己的数据库。 - 守:
Day 1 这个站点的运维小黎发现某个时间段请求量陡增,分析日志发现都是IP(xxx.xxx.xxx.xxx) 这个用户,并且 user-agent 还是 Python-urllib/3.6 ,基于这两点判断非人类后直接在服务器上封杀。 - 攻:
Day 2 小莫电影只爬了一半,于是也针对性的变换了下策略:1. user-agent 模仿百度(“Baiduspider…”),2IP 每爬半个小时就换一个 IP 代理。 - 守:
Day 2 小黎也发现了对应的变化,于是在服务器上设置了一个频率限制,每分钟超过 120次请求的再屏蔽 IP。同时考虑到百度家的爬虫有可能会被误伤,想想市场部门每月几十万的投放,于是写了个脚本,通过 hostname 检查下这个 ip 是不是真的百度家的,对这些 ip 设置一个白名单。 - 攻:
Day 3 小莫发现了新的限制后,想着我也不急着要这些数据,留给服务器慢慢爬吧,于是修改了代码,随机 1-3 秒爬一次,爬 10 次休息 10 秒,每天只在 8-12,18-20 点爬,隔几天还休息一下。 - 守:
Day 3 小黎看着新的日志头都大了,再设定规则不小心会误伤真实用户,于是准备换了一个思路,当 3 个小时的总请求超过 50 次的时候弹出一个验证码弹框,没有准确正确输入的话就把 IP 记录进黑名单。 - 攻:
Day 4 小莫看到验证码有些傻脸了,不过也不是没有办法,先去学习了图像识别(关键词PIL,tesseract),再对验证码进行了二值化,分词,模式训练之后,总之最后识别了小黎的验证码(关于验证码,验证码的识别,验证码的反识别也是一个恢弘壮丽的斗争史…),之后爬虫又跑了起来。 - 守:
Day 4 小黎是个不折不挠的好同学,看到验证码被攻破后,和开发同学商量了变化下开发模式,数据并不再直接渲染,而是由前端同学异步获取,并且通过 JavaScript 的加密库生成动态的 token,同时加密库再进行混淆(比较重要的步骤的确有网站这样做,参见淘宝和微博的登陆流程)。 - 攻:
Day 5 混淆过的加密库就没有办法了么?当然不是,可以慢慢调试,找到加密原理,不过小莫不准备用这么耗时耗力的方法,他放弃了基于 HttpClient 的爬虫,选择了内置浏览器引擎的爬虫 (关键词:PhantomJS,Selenium),在浏览器引擎运行页面,直接获取了正确的结果,又一次拿到了对方的数据。 - 守:
Day 5 小黎:…
1.5.2 常见的反爬与反反爬
守: 通过 User-Agent 来控制访问:
从用户请求的 Headers 反爬虫是最常见的反爬虫策略。由于正常用户访问网站时是通过浏览器访问的,所以目标网站通常会在收到请求时校验 Headers 中的 User-Agent 字段,如果不是携带正常的 User-Agent 信息的请求便无法通过请求。
笔记 User Agent 中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识 别客户使用的操作系统及版本、CPU
类型、浏览器及版本、浏览器渲染引擎、浏览器语言、 浏览器插件等。
破:应对措施:如果遇到了这类反爬虫机制,可以直接在自己写的爬虫中添加 Headers,将浏览器的 User-Agent 复制到爬虫的 Headers 中
守: 基于行为检测 (限制 IP)
还有一些网站会通过用户的行为来检测网站的访问者是否是爬虫,例如同一 IP 短时间内多次访问同一页面,或者同一账户短时间内多次进行相同操作。大多数网站都是前一种情况,对于这种情况有两种策略:
破:应对措施:
- 可以专门写一个在网上抓取可用代理 ip 的脚本,然后将抓取到的代理 ip 维护到代理池中供爬虫使用,当然,实际上抓取的 ip 不论是免费的还是付费的,通常的使用效果都极为一般,如果需要抓取高价值数据的话也可以考虑购买宽带 adsl 拨号的 VPS,如果 ip 被目标网站被封掉,重新拨号即可。
- 降低请求频率。例如每个一个时间段请求一次或者请求若干次之后 sleep 一段时间。由于网站获取到的 ip 是一个区域网的 ip,该 ip 被区域内的所有人共享,因此这个间隔时间并不需要特别长, 对于第二种情况,可以在每次请求后随机间隔几秒再进行下一次请求。对于有逻辑漏洞的网站,可以通过请求几次,退出登录,重新登录,继续请求来绕过同一账号短时间内不能多次进行相同请求的限制,如果能有多个账户,切换使用,效果更佳。
守: 通过账号权限反爬 (ookie 限制)
部分网站需要登录才能继续操作,这部分网站虽然并不是为了反爬虫才要求登录操作,但确实起到了反爬虫,的作用, 可是网页上有一部分内容如: 新浪微博是需要用户登录才能查看更多内容。限制每个每天下载 300 张.
破:应对措施:
因此可以通过注册账号,访问时带 cookie, 模拟登录的方法进行规避。
守: 验证码限制
这是一个相当古老但却不失有效性的反爬虫策略。更早的时候,这种验证码可以通过 OCR技术进行简单的图像识别破解,但是现在来说,验证码的干扰线,噪点已经多到肉眼都无法轻易识别的地步。所以目前而言,由于 OCR 技术发展不力,验证码技术反而成为了许多网站最有效的手段之一。
破:应对措施:
- 神经网络训练 NLP(图像识别)
- 人工识别
- 打码平台
- 第三方 OCR 库
守: 动态页面的反爬虫 (通过变换网页结构反爬)
一些社交网站常常会更换网页结构,而爬虫大部分情况下都需要通过网页结构来解析需要的数据,所以这种做法也能起到反爬虫的作用。在网页结构变换后,爬虫往往无法在原本的网页位置找到原本需要的内容.
破:应对措施: - 只爬取一次时,在其网站结构调整之前,将需要的数据全部爬取下来;使用脚本对网
站结构进行监测,结构变化时,发出告警并及时停止爬虫。 - 逆向分析,抓包
- selenium 库
1.6 爬虫的合法性与 robots 协议
1.6.1 robots 协议
robots 协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(Robots Exclusion Protocol ),当使用一个爬虫爬取一个网站的数据时,需要遵守网站所有者针对所有爬虫所制定的协议! 简单说就是是一种存放于网站根目录下的 ASCII 编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。
robots . txt 的 样 例
User - agent : *
Disallow : /
Allow : / public /
这实现了对所有搜索爬虫只允许爬取 public 目录的功能,将上述内容保存成 robots.txt 文件,放在网站的根目录下,和网站的入口文件(比如 index.php、index.html 和 index.jsp 等)放在一起。上面的 User-agent 描述了搜索爬虫的名称,这里将其设置为*则代表该协议对任何爬取爬虫有效。比如,我们可以设置:User-agent: Baiduspider 。这就代表我们设置的规则对百度爬虫是有效的。如果有多条 User-agent 记录,则就会有多个爬虫会受到爬取限制,但至少需要指定一条。Disallow 指定了不允许抓取的目录,比如上例子中设置为/则代表不允许抓取所有页面。Allow一般和 Disallow 一起使用,一般不会单独使用,用来排除某些限制。现在我们设置为/public /,则表示所有页面不允许抓取,但可以抓取 public 目录。
禁止所有爬虫访问任何目录的代码如下:
User - agent : *
Disallow : /
允许所有爬虫访问任何目录的代码如下:
User - agent : * Disallow :
禁止所有爬虫访问网站某些目录的代码如下:
User - agent : *
Disallow : / private /
Disallow : / tmp /
只允许某一个爬虫访问的代码如下:
User - agent : WebCrawler
Disallow :
User - agent : *
Disallow : /
1.6.2 查看网页的 robots 协议
❖ 合法的爬虫
- 遵守 Robots 协议
Robots 协议也叫 robots.txt(统一小写)是一种存放于网站根目录下的 ASCII 编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。Robots 协议就是告诉爬虫,哪些信息是可以爬取,哪些信息不能被爬取,严格按照Robots 协议爬取网站相关信息一般不会出现太大问题。 - 不能造成对方服务器瘫痪
但不是说只要遵守 Robots 协议的爬虫就没有问题,还涉及到两个因素,第一不能大规模爬虫导致对方服务器瘫痪,这等于网络攻击。2019 年 05 月 28 日国家网信办发布的《数据安全管理办法(征求意见稿)》中,拟通过行政法规的形式,对爬虫的使用进行限制:网络运营者采取自动化手段访问收集网站数据,不得妨碍网站正常运行;此类行为严重影响网站运行,如自动化访问收集流量超过网站日均流量三分之一,网站要求停止自动化访问收集时,应当停止。 - 不能非法获利
恶意利用爬虫技术抓取数据,攫取不正当竞争的优势,甚至是牟取不法利益的,则可能触犯法律。实践中,非法使用爬虫技术抓取数据而产生的纠纷其实数量并不少,大多是以不正当竞争为由提请诉讼。
举个例子,如果你把大众点评上的所有公开信息都抓取了下来,自己复制了一个一模
一样的网站,并且还通过这个网站获取了大量的利润,这样也是有问题的。
一般情况下,爬虫都是为了企业获利的,因此需要爬虫开发者的道德自持和企业经营 者的良知才是避免触碰法律底线的根本所在。
❖ 违法的爬虫
- 爬虫不能涉及个人隐私!
“一个程序员写了个爬虫程序,整个公司 200 多人被端了。”如果爬虫程序采集到公民的姓名、身份证件号码、通信通讯联系方式、住址、账号密码、财产状况、行踪轨迹等个人信息,并将之用于非法途径的,则肯定构成非法获取公民个人信息的违法行为。也就是说你爬虫爬取信息没有问题,但不能涉及到个人的隐私问题,如果涉及了并且通过非法途径收益了,那肯定是违法行为。
另外,还有下列三种情况,爬虫有可能违法,严重的甚至构成犯罪: - 爬虫程序规避网站经营者设置的反爬虫措施或者破解服务器防抓取措施,非法获取相
关信息,情节严重的,有可能构成“非法获取计算机信息系统数据罪”。 - 爬虫程序干扰被访问的网站或系统正常运营,后果严重的,触犯刑法,构成“破坏计
算机信息系统罪” - 爬虫采集的信息属于公民个人信息的,有可能构成非法获取公民个人信息的违法行为,
情节严重的,有可能构成“侵犯公民个人信息罪”。
1.7 Python 爬虫相关库
❖ 请求库
- urllib3 库
提供很多 Python 标准库里所没有的重要特性:线程安全,连接池,客户端 SSL/TLS验证,文件分部编码上传,协助处理重复请求和 HTTP 重定位,支持压缩编码,支持HTTP 和 SOCKS 代理,100% 测试覆盖率
- urllib 库
Python 内置的 HTTP 请求库,提供一系列用于操作 URL 的功能
- requests 库
基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库selenium Selenium 是一个自动化测试工具,利用它我们可以驱动浏览器执行特定的动作,如点击、下拉等操作,对于一些 JavaScript 渲染页面来说,这种抓取方式非常有效。
ChromeDriver谷歌浏览器的的驱动,只有安装了浏览器驱动,才能使用 selenium 来驱动谷歌浏览器完成相应的操作
❖ 解析库
- 正则表达式
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。正则表达式是繁琐的,但它是强大的
- lxml 的
- C 语言编写高效 HTML/XML 处理库。支持 HTML 和 XML 的解析,也支持 XPath 解析方式,而且解析效率非常高。
- xpath 库
XPath,全称 XML Path Language,即 XML 路径语言,它是一门在 XML 文档中查找信息的语言。XPath 最初设计是用来搜寻 XML 文档的,但是它同样适用于 HTML 文档的搜索。
- BeautifulSoup 库
BeautifulSoup 是 Python 的一个 HTML 或 XML 的解析库,利用它我们可以从网页提取数据。它拥有很强大的 API 和多样的解析方式
❖ 数据库与存储库
- MySQL 数据库与 PyMySQL 库
MySQL一个轻量级的关系型数据库,PyMySQL是在Python3.x版本中用于连接MySQL服务器的一个库。
- MongoDB 数据库与 PyMongo
MongoDB 是由 C++ 语言编写的非关系型数据库,其存储字段可以包含其他文档、数组及文档数组,非常灵活。PyMongo 是在 Python3.x 版本中用于连接 MongoDB 服务器的一个库。
❖ 爬虫框架
- crapy
一个为了爬取网站数据,提取结构性数据而编写的应用框架
2. Chrome 浏览器开发者工具
2.1 Chrome 浏览器开发者工具简述
2.1.1 什么是浏览器开发者工具
其实简单的说,浏览器开发者工具就是给专业的 web 应用和网站开发人员使用的工具,它的作用在于,帮助开发人员对网页进行布局,比如 HTML+CSS,帮助前端工程师更好的调试脚本(JavaScript、jQuery)之类的,还可以使用工具查看网页加载过程,获取网页请求(这个过程也叫做抓包),抓包是非常有意思的过程,而每一个浏览器厂商生产出来的浏览器都会有自己的杀手锏,也就是功能上的差别,那么这个时候你就找一个最适合自己的浏览器使用就可以,接下来就是介绍我常用的三个浏览器。
2.1.2 浏览器开发者工具基本使用
❖ 如何调出开发者工具
按 F12 调出 & 右键检查(或快捷键 Ctrl+Shift+i)调出
图 2.1: 浏览器开发者工具
2.2 浏览器开发者工具面板说明
chrome 开发者工具最常用的四个功能模块:元素(ELements)、控制台(Console)、源代码(Sources),网络(Network)。爬虫这块用的比较多的是元素 (ELements), 网络 (Network).
图 2.2: 浏览器开发者工具
❖ 元素(Elements):用于查看或修改 HTML 元素的属性、CSS 属性、监听事件、断点等。css可以即时修改,即时显示。大大方便了开发者调试页面
❖ 控制台(Console):控制台一般用于执行一次性代码,查看 JavaScript 对象,查看调试日志信息或异常信息。还可以当作 Javascript API 查看用。例如我想查看 console 都有哪些方法和属性,我可以直接在 Console 中输入"console" 并执行
❖ 源代码(Sources):该页面用于查看页面的 HTML 文件源代码、JavaScript 源代码、CSS 源代码,此外最重要的是可以调试 JavaScript 源代码,可以给 JS 代码添加断点等。
❖ 网络(Network):网络页面主要用于查看 header 等与网络连接相关的信息。:网络页面主要用于查看 header 等与网络连接相关的信息。
2.2.1 元素 (Elements) 面板
查看元素的代码:点击左上角的箭头图标(或按快捷键 Ctrl+Shift+C)进入选择元素模式,然后从页面中选择需要查看的元素,然后可以在开发者工具元素(Elements)一栏中定位到该元素源代码的具体位置
图 2.3: 浏览器开发者工具
用于定位元素,复制某类元素路径,这个在使用 BS4 库,selenium 库时,选择定位器会用到!
可以更改浏览器显示方式! 使用手机或者其他设备! 也可以更改当前使用的设备的网络连接速度!
2.2.2 网络 (Network) 面板 (1)
Network 面板可以记录页面上的网络请求的详情信息,从发起网页页面请求 Request 后分析 HTTP 请求后得到的各个请求资源信息(包括状态、资源类型、大小、所用时间、Request 和Response 等),可以根据这个进行网络性能优化。该面板主要包括 5 大块窗格:
图 2.6: 浏览器开发者工具
❖ Controls 控制 Network 的外观和功能。
❖ Filters 控制 Requests Table 具体显示哪些内容。
❖ Overview 显示获取到资源的时间轴信息。
❖ Requests Table 按资源获取的前后顺序显示所有获取到的资源信息,点击资源名可以查看该资源的详细信息。
❖ Summary 显示总的请求数、数据传输量、加载时间信息。
其中用的比较多的是:Controls,Filter,Requests Table
图 2.7: 浏览器开发者工具
使用频率一般,在部分网站上抓取某些请求时使用! 有时需要选择 Disable Cache, 不需要缓存。
图 2.8: 浏览器开发者工具
这个主要用来选择一些请求时用的!常用的俩选项 XHR 和 JS, 其他偶尔用用!
xhr,全称为 XMLHttpRequest,用于与服务器交互数据,是 ajax 功能实现所依赖的对象,jquery 中的 ajax
就是对 xhr 的封装。
图 2.9: 浏览器开发者工具
查看一些请求的名字,状态码,类型,大小和类型! 这个不是重点!重点是这个资源本身的一些属性!
2.2.3 网络 (Network) 面板 (2)
点击任意一个资源我们可以得到如下资源!
图 2.10: 浏览器开发者工具
这个主要用于查看这个请求的内容! 知道数据是否在这块放着!
图 2.11: 浏览器开发者工具
主要用于查看某个资源是如何请求的, 请求头信息,请求体信息,响应体信息等等,下面会具体介绍! 这部分内容相对来说还是很重要的!
图 2.12: 浏览器开发者工具
generel 主要用于查看请求的 url 和请求方式,响应状态码,等信息,常用的就这四个!
图 2.13: 浏览器开发者工具
Request Headers 请求头信息,里面信息很多,常用来做伪装浏览器使用,最常见的伪装方法就是使用 User-Agent! 当然还有一些其他的伪装方法!
3. HTTP 协议
3.1 HTTP 简介
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP 是一个基于 TCP/IP 通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
HTTP 是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于 1990 年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在 WWW中使用的是 HTTP/1.0 的第六版,HTTP/1.1 的规范化工作正在进行之中,而且 HTTP-NG(Next Generation of HTTP) 的建议已经提出。
HTTP 协议工作于客户端-服务端架构为上。浏览器作为 HTTP 客户端通过 URL 向 HTTP 服务端即 WEB 服务器发送所有请求。Web 服务器根据接收到的请求后,向客户端发送响应信息。
图 3.1: http 请求-响应模型
3.2 主要特点
❖ 1、简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
❖ 2、灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
❖ 3. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
❖ 4. 无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
❖ 5. 支持 B/S 及 C/S 模式。
3.3 URL,URI,URN
这三个缩略词是 Tim Berners-Lee 在一篇名为 RFC 3986: Uniform Resource Identifier (URI):Generic Syntax 的文档中定义的互联网标准追踪协议。
引文:统一资源标识符 (URI) 提供了一个简单、可扩展的资源标识方式。URI 规范中的语义和语法来源于万维网全球信息主动引入的概念,万维网从 1990 年起使用这种标识符数据,并被描述为“万维网中的统一资源描述符”。
Tim Berners-Lee , 万维网的发明者,同时也是万维网联盟 (W3C) 的负责人。照片由 Paul Clarke遵循 CC BY-SA 4.0 协议提供。
3.3.1 URI* 统一资源标识符
HTTP 使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的 URI,包含了用于查找某个资源的足够的信息URI (Uniform Resource Identifier) 即统一资源标志符
3.3.2 URL* 统一资源定位符
URL, 全称是 UniformResourceLocator, 中文叫统一资源定位符, 是互联网上用来标识某一处资
源的地址。https://github.com/favicon.ico 既是一个 URL, 也是一个 URI即有这样的一个图标资源用 URL/URI 来唯一指定了它的访问方式这其中包括了访问协议HTTPS、访问路径(即根目录)和资源名称 favicon, ico URL 是 URI 的一个子集,也就是说每个 URL 都是 URI, 但不是每个 URI 都是 URL
从上面的 URL 可以看出,一个完整的 URL 包括以下几部分:
❖ 1. 协议部分:该 URL 的协议部分为“http:”,这代表网页使用的是 HTTP 协议。在 Internet中可以使用多种协议,如 HTTP,FTP 等等本例中使用的是 HTTP 协议。在"HTTP" 后面的“//”为分隔符
❖ 2. 域名部分:该 URL 的域名部分为“www.aspxfans.com”。一个 URL 中,也可以使用 IP 地址作为域名使用
❖ 3. 端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个 URL 必须的部分,如果省略端口部分,将采用默认端口
❖ 4. 虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个 URL 必须的部分。本例中的虚拟目录是“/news/”
❖ 5. 文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个 URL 必须的部分,如果省略该部分,则使用默认的文件名
❖ 6. 锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个 URL 必须的部分
❖ 7. 参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
3.3.3 URN* 统一资源名称
URN (Universa I Resource Name) 即统一资源名称
URN 只命名资源而不指定如何定位资源, 比如:
- urn:isbn:0451450523 (其 ISBN 编号,以确定一本书)
- urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 (一个全局唯一标识符)
- urn:publishing:book (标识文档作为一个图书类型的 XML 命名空间)
- urn: isbn:0451450523 指定了一本书的 ISBN, 可以唯一标识这本书,但是没有指定到哪里定位这本书
3.3.4 URI,URL,URN 的区别
URI,是 uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。 Web 上可用的每种资源如 HTML 文档、图像、视频片段、程序等都是一个来 URI 来定位的 URI 一般由三部组成:
❖ 访问资源的命名机制
❖ 存放资源的主机名
❖ 资源自身的名称,由路径表示,着重强调于资源
URL 是 uniform resource locator,统一资源定位器,它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。URL 是 Internet 上用来描述信息资源的字符串,主要用在各种 WWW 客户程序和服务器程
序上,特别是著名的 Mosaic。采用 URL 可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。
URL 一般由三部组成:
❖ 协议 (或称为服务方式)
❖ 存有该资源的主机 IP 地址 (有时也包括端口号)
❖ 主机资源的具体地址。如目录和文件名等
URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如 mailto:javanet@java.sun.com URI 是以一种抽象的,高层次概念定义统一资源标识,而 URL 和 URN 则是具体的资源标识的方式。URL 和 URN 都是一种 URI。笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。上面的 mailto、news 和 isbn URI 都是 URN 的示例。
在 Java 的 URI 中,一个 URI 实例可以代表绝对的,也可以是相对的,只要它符合 URI 的语法规则。而 URL 类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的。在 Java类库中,URI 类不包含任何访问资源的方法,它唯一的作用就是解析。相反的是,URL 类可以打开一个到达资源的流。
图 3.2: URL、URN 和 URI 的关系图
3.4 HTTP 协议与 HTTPS 协议
3.4.1 HyperText
超文本(英语:Hypertext)是一种可以显示在电脑显示器或电子设备上的文本,现时超文本普遍以电子文档的方式存在,其中的文字包含有可以链接到其他字段或者文档的超链接,允许从当前阅读位置直接切换到超链接所指向的文字。
浏览器里看到的网页就是超文本解析而成的,其网页源代码是一系列 HTML 代码,里面包含了一系列标签比如:
❖ img 显示图片
❖ P 指定显示段落等
浏览器解析这些标签后,便形成了我们平常看到的网页,而网页的源代码 HTML 就可以称作超文本
3.4.2 HTTP 与 HTTPS
https://www.taobao.com/ 中,URL 的开头会有 http 或 https 这个就是访问资源需要的协议类型,有时还会看到 ftp. sftp. smb 开头的 URL ftp 、sftpx smb 都是指的协议类型
❖ 超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。通过 HTTP 或者HTTPS 协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。HTTP 的发展是由蒂姆·伯纳斯-李于 1989 年在欧洲核子研究组织(CERN)所发起。HTTP 的标准制定由万维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(InternetEngineering Task Force,IETF)进行协调,最终发布了一系列的 RFC,其中最著名的是 1999年 6 月公布的 RFC 2616,定义了 HTTP 协议中现今广泛使用的一个版本——HTTP 1.1。2014 年 12 月,互联网工程任务组(IETF)的 Hypertext Transfer Protocol Bis(httpbis)工作小组将HTTP/2 标准提议递交至 IESG 进行讨论,于 2015 年 2 月 17 日被批准。HTTP/2 标准于 2015 年 5 月以 RFC 7540 正式发表,取代 HTTP 1.1 成为 HTTP 的实现标准。
❖ 超文本传输安全协议(英语:HyperText Transfer Protocol Secure,缩写:HTTPS;常称为HTTP over TLS、HTTP over SSL 或 HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。这个协议由网景公司(Netscape)在 1994 年首次提出,随后扩展到互联网上。历史上,HTTPS 连接经常用于万维网上的交易支付和企业信息系统中敏感信息的传输。在2000 年代末至 2010 年代初,HTTPS 开始广泛使用,以确保各类型的网页真实,保护账户和保持用户通信,身份和网络浏览的私密性。另外,还有一种安全超文本传输协议(S-HTTP)的 HTTP 安全传输实现,但是 HTTPS 的广泛应用而成为事实上的 HTTP 安全传输实现,S-HTTP 并没有得到广泛支持。
笔记 HTTP (Hyper Text Transfer Protoco I) 中文名叫作超文本传输协议用于从网络传输超文本数据
到本地浏览器的传送协议,能保证高效而准确地传送超文本文档由万维网协会 (World Wide Web Consortium) 和
Internet 工作小组 IETF (Internet Engineer ing Task Force) 共同合作制定的规范目前
广泛使用的是 HTTP 1.1 版本 HTTPS (Hyper Text Transfer Protocol over Secure
Socket Layer) 是以安全为目标的 HTTP 通道, 简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,简称为
HTTPS 安全基础是 SSL, 因此通过它 传输的内容都是经过 SSL 加密. 主要作用可以分为两种:
建立一个信息安全通道,来保证数据传输的安全 确认网站的真实性,凡是使用了 HTTPS 的网站,都可以通过点击浏览器地址栏的锁头标志
来查看网站 越来越多的网站和 App 都已经向 HTTPS 方向发展
- 苹果公司强制所有 iOS App 在 2017 年 1 月 1 日前全部改为使用 HTTPS 加密,否则 App 就 无法在应用商店上架
- 谷歌从 2017 年 1 月推出的 Chrome 5 6 开始,对未进行 HTTPS 加密的网址链接亮出风险提 示,即在地址栏的显著位置提醒用户“此网页不安全”
- 腾讯微信小程序的官方需求文档要求后台使用 HTTPS 请求进行网络通信,不道足条件的域 名和协议无法请求
HTTPS 已经已经是大势所趋
HTTP 的 URL 是由“http://”起始与默认使用端口 80,而 HTTPS 的 URL 则是由“https://”起始与默认使用端口 443。
HTTP 不是安全的,而且攻击者可以通过监听和中间人攻击等手段,获取网站帐户和敏感信息等。HTTPS 的设计可以防止前述攻击,在正确配置时是安全的。
3.5 HTTP 请求过程
在浏览器中输入一个 URL, 回车之后便可以在浏览器中观察到页面内容这个过程是浏览器向网站所在的服务器发送了一个请求网站服务器接收到这个请求后进行处理和解析,然后返回对应的响应,接着传回给浏览器。
图 3.3: http 请求-响应模型
打开 Chrome 浏览器,右击并选择“检查”项即可打开浏览器的开发者工具
图 3.4: http 请求的过程
❖ Name: 请求的名称, 一般会把 URL 的最后一部分当作名称
❖ Status: 响应的状态码,一般 200 表示响应成功,通过状态码,可以判断发送的请求是否获得正常响应
❖ Type:请求的文档类型,document 表示这次的请求是一个 html
❖ Initiator: 请求源,用于标记请求是由那个对象或者端口发起的
❖ Size: 从服务器,下载的文件和请求内容的大小,如果是从缓存中得到的则该列会显示 from cash,
❖ Time: 发起请求到获取响应的总时间
❖ Waterfall: 网络请求的可视化瀑布流点击一个进去可以查看到详细信息
图 3.5: http 请求的信息
❖ General:HTTP 标头字段列表
❖ Request Headers: 请求头信息
❖ Response Headers: 响应头信息
❖ Query String Parameters:查询字符串参数:其实就是 get 请求中 url 后面要带的参数。也就是说,向对应网址服务器传递这些参数就可以获得请求的内容
3.5.1 General
HTTP 标头字段列表
图 3.6: HTTP 标头字段列表
❖ Request URL: 请求的网址
❖ Request Method: 请求方法
❖ Status Code: 响应状态码
❖ Remote Address:Remote Address 代表的是当前 HTTP 请求的远程地址,即 HTTP 请求的源地址。HTTP 协议在三次握手时使用的就是这个 Remote Address 地址,在发送响应报文时也是使用这个 Remote Address 地址。
❖ Referrer Policy: 当用户在浏览器上点击一个链接时,会产生一个 HTTP 请求,用于获取新的页面内容,而在该请求的报头中,会包含一个 Referrer,用以指定该请求是从哪个页面跳转页来的,常被用于分析用户来源等信息。但是也有成为用户的一个不安全因素,比如有些网站直接将 sessionid 或是 token 放在地址栏里传递的,会原样不动地当作 Referrer 报头的内容传递给第三方网站。所以就有了 Referrer Policy,用于过滤 Referrer 报头内容,目前是一个候选标准,不过已经有部分浏览器支持该标准。具体的可查看这里。
笔记 Remote Address 代表的是当前 HTTP 请求的远程地址,即 HTTP 请求的源地址。HTTP
协议在三次握手时使用的就是这个 Remote Address 地址,在发送响应报文时也是使用这个 RemoteAddress
地址。因此,如果请求者伪造 Remote Address 地址,他将无法收到 HTTP 的响应报文,此时伪造没有任何意义。这也就使得
Remote Address 默认具有防篡改的功能。如果 Http 请求经过代理服务器转发,则这种情况,用户的真实 ip
会丢失,所以才有了“X-Forwarded-For”的方式。当你使用了代理时,web 服务器就不知道你的真实 IP
了,为了避免这个情况,代理服务器通 常会增加一个叫做 x_forwarded_for 的头信息,把连接它的客户端 IP(即你的上网机器
IP)加到这个头信息里,这样就能保证网站的 web 服务器能获取到真实 IP,X-Forwarded-For 是一个扩展头。
HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实
IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239 (Forwarded
HTTP Extension)标准之中。X-Forwarded-For 请求头格式非常简单,就这样:X-Forwarded-For:
client, proxy1, proxy2可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备
IP,然后是每一级代理设备的 IP。如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP
分别为IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:X-Forwarded-For:
IP0, IP1, IP2 总结是:在使用 nginx 等反向代理服务器的时候,是必须使用 X-Forward-For 来获取用户 IP
地址的(此时 Remote Address 是 nginx 的地址),因为此时 XForward-For 中的地址是由 nginx
写入的,而 nginx 是可信任的。不过此时要注意,要禁止 web 对外提供服务。
3.5.2 请求方法 (Request Method)
HTTP/1.1 协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源:
❖ GET
向指定的资源发出“显示”请求。使用 GET 方法应该只用在读取资料,而不应当被用于产生“副作用”的操作中,例如在网络应用程序中。其中一个原因是 GET 可能会被网络爬虫等随意访问。参见安全方法。浏览器直接发出的 GET 只能由一个 url 触发。GET 上要在 url之外带一些参数就只能依靠 url 上附带 querystring。
❖ HEAD
与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
❖ POST
向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。每次提交,表单的数据被浏览器用编码到 HTTP 请求的 body 里。浏览器发出的 POST 请求的 body主要有两种格式,一种是 application/x-www-form-urlencoded 用来传输简单的数据,大概就是"key1=value1&key2=value2" 这样的格式。另外一种是传文件,会采用 multipart/form-data格式。采用后者是因为 application/x-www-form-urlencoded 的编码方式对于文件这种二进制的数据非常低效。
❖ PUT
向指定资源位置上传其最新内容。
❖ DELETE
请求服务器删除 Request-URI 所标识的资源。
❖ TRACE
回显服务器收到的请求,主要用于测试或诊断。
❖ OPTIONS
这个方法可使服务器传回该资源所支持的所有 HTTP 请求方法。用’*’ 来代替资源名称,向Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作。
❖ CONNECT
HTTP/1.1 协议中预留给能够将连接改为隧道方式的代理服务器。通常用于 SSL 加密服务器的链接(经由非加密的 HTTP 代理服务器)。方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码 405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码 501(Not Implemented)。
笔记 常见的请求方法有:GET 和 POST 在浏览器中直接输入 URL 并回车,便发起了一个 GET请求,请求的参数会直接包含到 URL
里例如:在百度中搜索 P yth o n , 这就是一个 GET 请求,链接为
https://www.baidu.com/s?wd=Python URL 中包含了请求的参数信息,这里参数 wd 表示要搜寻的关键字
POST 请求大多在表单提交时发起例如:对于一个登录表单,输入用户名和密码后,点击其数据通常以表单的形式传输,而不会体现在 URL
中“登录”按钮这通常会发起一个 POST 请求 GET 和 POST 请求方法有如下区别 GET 请求中的参数包含在 URL
里面,数据可以在 URL 中看到,而 POST 请求的 URL 不会包含这些数据数据都是通过表单形式传输的,会包含在请求体中GET
请求提交的数据最多只有 1024 字节,而 POST 请求没有限制。
3.5.3 状态码 (Status Code)
所有 HTTP 响应状态代码都分为五个类或类别。状态码的第一位数字定义响应的类别,而最后两位数字没有任何分类或分类作用。该标准定义了五类:
❀ 1xx 信息响应–收到请求,继续进行
❀ 2xx 成功–成功接收,理解并接受了请求
❀ 3xx 重定向–为了完成请求,需要采取进一步的措施
❀ 4xx 客户端错误–请求包含错误的语法或无法满足
❀ 5xx 服务器错误–服务器无法满足看似有效的请求
状态码详细说明
❖ 201-206 都表示服务器成功处理了请求的状态代码,说明网页可以正常访问。
➢ 200(成功)服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。
➢ 201(已创建)请求成功且服务器已创建了新的资源。
➢ 202(已接受)服务器已接受了请求,但尚未对其进行处理。
➢ 203(非授权信息)服务器已成功处理了请求,但返回了可能来自另一来源的信息。
➢ 204(无内容)服务器成功处理了请求,但未返回任何内容。
➢ 205(重置内容)服务器成功处理了请求,但未返回任何内容。与 204 响应不同,此响应要求请求者重置文档视图(例如清除表单内容以输入新内容)。
➢ 206(部分内容)服务器成功处理了部分 GET 请求。
❖ 300-3007 表示的意思是:要完成请求,您需要进一步进行操作。通常,这些状态代码是永远重定向的。
➢ 300(多种选择)服务器根据请求可执行多种操作。服务器可根据请求者来选择一项操作,或提供操作列表供其选择。
➢ 301(永久移动)请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。您应使用此代码通知搜索引擎蜘蛛网页或网站已被永久移动到新位置。
➢ 302(临时移动)服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。会自动将请求者转到不同的位置。但由于搜索引擎会继续抓取原有位置并将其编入索引,因此您不应使用此代码来告诉搜索引擎页面或网站已被移动。
➢ 303(查看其他位置)当请求者应对不同的位置进行单独的 GET 请求以检索响应时,服务器会返回此代码。对于除 HEAD 请求之外的所有请求,服务器会自动转到其他位置。
➢ 304(未修改)自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。如果网页自请求者上次请求后再也没有更改过,您应当将服务器配置为返回此响应。由于服务器可以告诉搜索引擎自从上次抓取后网页没有更改过,因此可节省带宽和开销。
➢ 305(使用代理)请求者只能使用代理访问请求的网页。如果服务器返回此响应,那么,服务器还会指明请求者应当使用的代理。
➢ 307(临时重定向)服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。会自动将请求者转到不同的位置。但由于搜索引擎会继续抓取原有位置并将其编入索引,因此您不应使用此代码来告诉搜索引擎某个页面或网站已被移动。。
❖ 4XXHTTP 状态码表示请求可能出错,会妨碍服务器的处理。
➢ 400(错误请求)服务器不理解请求的语法。
➢ 401(身份验证错误)此页要求授权。您可能不希望将此网页纳入索引。
➢ 403(禁止)服务器拒绝请求。
➢ 404(未找到)服务器找不到请求的网页。例如,对于服务器上不存在的网页经常会返回此代码。
例如:http://www.0631abc.com/20100aaaa,就会进入 404 错误页面
➢ 405(方法禁用)禁用请求中指定的方法。
➢ 406(不接受)无法使用请求的内容特性响应请求的网页。
➢ 407(需要代理授权)此状态码与 401 类似,但指定请求者必须授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理。
➢ 408(请求超时)服务器等候请求时发生超时。
➢ 409(冲突)服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表。
➢ 410(已删除)请求的资源永久删除后,服务器返回此响应。该代码与 404(未找到)代码相似,但在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久删除,您应当使用 301 指定资源的新位置。
➢ 411(需要有效长度)服务器不接受不含有效内容长度标头字段的请求。
➢ 412(未满足前提条件)服务器未满足请求者在请求中设置的其中一个前提条件。
➢ 413(请求实体过大)服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
➢ 414(请求的 URI 过长)请求的 URI(通常为网址)过长,服务器无法处理。
➢ 415(不支持的媒体类型)请求的格式不受请求页面的支持。
➢ 416(请求范围不符合要求)如果页面无法提供请求的范围,则服务器会返回此状态码。
➢ 417(未满足期望值)服务器未满足" 期望" 请求标头字段的要求。
❖ 500 至 505 表示的意思是:服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
➢ 500(服务器内部错误)服务器遇到错误,无法完成请求。
➢ 501(尚未实施)服务器不具备完成请求的功能。例如,当服务器无法识别请求方法时,服务器可能会返回此代码。
➢ 502(错误网关)服务器作为网关或代理,从上游服务器收到了无效的响应。
➢ 503(服务不可用)目前无法使用服务器(由于超载或进行停机维护)。通常,这只是一种暂时的状态。
➢ 504(网关超时)服务器作为网关或代理,未及时从上游服务器接收请求。
➢ 505(HTTP 版本不受支持)服务器不支持请求中所使用的 HTTP 协议版本。
3.5.4 请求头信息 (Request Headers)
请求头信息用来说明服务器要使用的附加信息,比较重要的信息有 Cookie、Referer、User-Agent
Python Code:
GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101
Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT
If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control: max-age=0
请求头由 key/value 对组成,每行为一对,key 和 value 之间通过冒号 (😃 分割。请求头的作用主要用于通知服务端有关于客户端的请求信息
❖ Accept:浏览器可接受的 MIME 类型;
❖ Accept-Charset:浏览器可接受的字符集;
❖ Accept-Encoding:浏览器能够进行解码的数据编码方式,比如 gzip。Servlet 能够向支持 gzip的浏览器返回经 gzip 编码的 HTML 页面。许多情形下这可以减少 5 到 10 倍的下载时间;
❖ Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到;
❖ Authorization:授权信息,通常出现在对服务器发送的 WWW-Authenticate 头的应答中;
❖ Connection:表示是否需要持久连接。如果 Servlet 看到这里的值为“Keep-Alive”,或者看到请求使用的是 HTTP 1.1(HTTP 1.1 默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如 Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet 需要在应答中发送一个 Content-Length 头,最简单的实现方是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;
❖ Content-Length:表示请求消息正文的长度;
❖ Cookie:这是最重要的请求头信息之一;也常用复数形式 Cookies, 这是网站为了辨别用户进行会话跟踪而存储在用户本地的数据它的主要功能是维持当前访问会话。例如,我们输入用户名和密码成功登录某个网站后,服务器会用会话保存登录状态信息,后面我们每次刷新或请求该站点的其他页面时,会发现都是登录状态,这就是 Cookies 的功劳 Cookies 里有信息标识了我们所对应的服务器的会话,每次浏览器在请求该站点的页面时,都会在请求头中加上 Cookies 并将其发送给服务器,服务器通过 Cookies 识别出是我们自己,并且查出当前状态是登录状态,所以返回结果就是登录之后才能看到的网页内容
❖ From:请求发送者的 email 地址,由一些特殊的 Web 客户程序使用,浏览器不会用到它;
❖ Host:初始 URL 中的主机和端口;
❖ If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答;
❖ Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝;
❖ Referer:包含一个 URL,用户从该 URL 代表的页面出发访问当前请求的页面。此内容用来标识这个请求是从哪个页面发过来的,服务器可以拿到这一信息并做相应的处理如做来源统计、防盗链处理等
❖ User-Agent:浏览器类型,如果 Servlet 返回的内容与浏览器类型有关则该值非常有用;简称UA , 它是一个特殊的字符串头,可以使服务器识别客户使用的操作系统及版本、浏览器及版本等信息。在做爬虫时加上此信息,可以伪装为浏览器;如果不加,很可能会被识别出为爬虫
❖ UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的 IE 浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和 CPU 类型。
3.5.5 响应头信息 (Response Headers)
响应报文:当收到 get 或 post 等方法发来的请求后,服务器就要对报文进行响应。
Python Code:
200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jul 2016 16:06:00 GMT
Etag: "c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive: timeout=5, max=997
Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT
Server: Apache
Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600;
Path=/; secure
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
X-Backend-Server: developer2.webapp.scl3.mozilla.com
X-Cache-Info: not cacheable; meta data too large
X-kuma-revision: 1085259
x-frame-options: DENY
❖ Allow:服务器支持哪些请求方法(如 GET、POST 等);
❖ Content-Encoding:文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream 可以很方便地进行 gzip 压缩,但只有 Unix 上的 Netscape 和 Windows 上的 IE 4、IE5 才支持它。因此,Servlet 应该通过查看 Accept-Encoding 头(即 request.getHeader(“AcceptEncoding”))检查浏览器是否支持 gzip,为支持 gzip 的浏览器返回经 gzip 压缩的 HTML 页
面,为其他浏览器返回普通页面;
❖ Content-Length:表示内容长度。只有当浏览器使用持久 HTTP 连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容;
❖ Content-Type:表示后面的文档属于什么 MIME 类型。Servlet 默认为 text/plain,但通常需要显式地指定为text/html。由于经常要设置 Content-Type,因此 HttpServletResponse 提供了一个专用的方法 setContentTyep。可在 web.xml 文件中配置扩展名和 MIME 类型的对应关系;
❖ Date:当前的 GMT 时间。你可以用 setDateHeader 来设置这个头以避免转换时间格式的麻烦;
❖ Expires:指明应该在什么时候认为文档已经过期,从而不再缓存它。
❖ Last-Modified:文档的最后改动时间。客户可以通过 If-Modified-Since 请求头提供一个日期,该请求将被视为一个条件 GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个 304(Not Modified)状态。Last-Modified 也可用 setDateHeader 方法来设置;
❖ Location:表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse 的sendRedirect 方法,该方法同时设置状态代码为 302;
❖ Refresh:表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader(“Refresh”, “5; URL=http://host/path”) 让浏览器读取指定的页面。注意这种功能通常是通过设置 HTML 页面 HEAD 区的 实现,这是因为,自动刷新或重定向对于那些不能使用 CGI或 Servlet 的 HTML 编写者十分重要。但是,对于 Servlet 来说,直接设置 Refresh 头更加方便。注意 Refresh 的意义是“N 秒之后刷新本页面或访问指定页面”,而不是“每隔 N 秒刷新本页面或访问指定页面”。因此,连续刷新要求每次都发送一个 Refresh 头,而发送 204 状态代码则可以阻止浏览器继续刷新,不管是使用 Refresh 头还是 <META HTTP-EQUIV=“Refresh”…>。注意 Refresh 头不属于 HTTP 1.1 正式规范的一部分,而是一个扩展,但 Netscape 和 IE都支持它。
3.5.6 响应体 (Response Body)
最重要的当属响应体的内容,响应的正文数据都在响应体中比如:
请求网页时,它的响应体就是网页的 HTML 代码;请求一张图片时,它的响应体就是图片的二进制数据
3.6 Cookies 和 session
3.6.1 Cookies
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
Cookie 主要用于以下三个方面:
❖ 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
❖ 个性化设置(如用户自定义设置、主题等)
❖ 浏览器行为跟踪(如跟踪分析用户行为等)
Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB 。
3.6.2 session
session 是另一种记录服务器和客户端会话状态的机制 session 是基于 cookie 实现的,session存储在服务器端,sessionId 会被存储到客户端的 cookie 中
session 认证流程:
❖ 用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session
❖ 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名
❖ 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。
3.6.3 Cookies 和 session 区别
Cookies 是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。Cookies 是当你浏览某网站时,由 Web 服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户 ID、密码、浏览过的网页、停留的时间等信息。session:当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个Session 对象。当会话过期或被放弃后,服务器将终止该会话。cookie 机制:采用的是在客户端保持状态的方案,而 session 机制采用的是在服务端保持状态的方案。同时我们看到由于服务器端保持状态的方案在客户端也需要保存一个标识,所以 session 机制可能需要借助 cookie 机制来达到保存标识的目的。Session 是服务器用来跟踪用户的一种手段,每个 Session 都有一个唯一标识:session ID。当服务器创建了 Session 时,给客户端发送的响应报文包含了 Set-cookie 字段,其中有一个名为 sid的键值对,这个键值 Session ID。客户端收到后就把 Cookie 保存浏览器,并且之后发送的请求报表都包含 SessionID。HTTP 就是通过 Session 和 Cookie 这两个发送一起合作来实现跟踪用户状态,Session 用于服务端,Cookie 用于客户端。