HTTP基本原理
URI和URL
这里我们先了解一下 URI 和 URL,URI 的全称为 Uniform Resource Identifier,即统一资源标志符,URL 的全称为 Universal Resource Locator,即统一资源定位符。
举例来说,https://github.com/favicon.ico,它是一个 URL,也是一个 URI。即有这样的一个图标资源,我们用 URL/URI 来唯一指定了它的访问方式,这其中包括了访问协议 https、访问路径(即根目录)和资源名称 favicon.ico。通过这样一个链接,我们便可以从互联网上找到这个资源,这就是 URL/URI。
URL 是 URI 的子集,也就是说每个 URL 都是 URI,但不是每个 URI 都是 URL。那么,怎样的 URI 不是 URL 呢?URI 还包括一个子类叫作 URN,它的全称为 Universal Resource Name,即统一资源名称。URN 只命名资源而不指定如何定位资源,比如 urn:isbn:0451450523 指定了一本书的 ISBN,可以唯一标识这本书,但是没有指定到哪里定位这本书,这就是 URN。

但是在目前的互联网,URN 的使用非常少,所以几乎所有的 URI 都是 URL,所以一般的网页链接我们可以称之为 URL,也可以称之为 URI,我个人习惯称之为 URL。
超文本
接下来,我们再了解一个概念 —— 超文本,其英文名称叫作 hypertext,我们在浏览器里看到的网页就是超文本解析而成的,其网页源代码是一系列 HTML 代码,里面包含了一系列标签,比如 img 显示图片,p 指定显示段落等。浏览器解析这些标签后,便形成了我们平常看到的网页,而网页的源代码 HTML 就可以称作超文本。
例如,我们在 Chrome 浏览器里面打开任意一个页面,右击任一地方并选择 “检查” 项(或者直接按快捷键 F12),即可打开浏览器的开发者工具,这时在 Elements 选项卡即可看到当前网页的源代码,这些源代码都是超文本。
HTTP 和 HTTPS
在淘宝的首页 https://www.taobao.com/中,URL 的开头会有 http 或 https,这个就是访问资源需要的协议类型,有时我们还会看到 ftp、sftp、smb 开头的 URL,那么这里的 ftp、sftp、smb 都是指的协议类型。在爬虫中,我们抓取的页面通常就是 http 或 https 协议的,我们在这里首先来了解一下这两个协议的含义。
HTTP 的全称是 Hyper Text Transfer Protocol,中文名叫做超文本传输协议,HTTP 协议是用于从网络传输超文本数据到本地浏览器的传送协议,它能保证传送高效而准确地传送超文本文档。HTTP 由万维网协会(World Wide Web Consortium)和 Internet 工作小组 IETF(Internet Engineering Task Force)共同合作制定的规范,目前广泛使用的是 HTTP 1.1 版本。
HTTPS 的全称是 Hyper Text Transfer Protocol over Secure Socket Layer,是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,简称为 HTTPS。
HTTPS 的安全基础是 SSL,因此通过它传输的内容都是经过 SSL 加密的,它的主要作用可以分为两种:
- 建立一个信息安全通道,来保证数据传输的安全。
- 确认网站的真实性,凡是使用了 https 的网站,都可以通过点击浏览器地址栏的锁头标志来查看网站认证之后的真实信息,也可以通过 CA 机构颁发的安全签章来查询。
而某些网站虽然使用了 HTTPS 协议还是会被浏览器提示不安全
HTTP 请求过程
我们在浏览器中输入一个 URL,回车之后便会在浏览器中观察到页面内容。实际上,这个过程是浏览器向网站所在的服务器发送了一个请求,网站服务器接收到这个请求后进行处理和解析,然后返回对应的响应,接着传回给浏览器。响应里包含了页面的源代码等内容,浏览器再对其进行解析,便将网页呈现了出来。

此处客户端即代表我们自己的 PC 或手机浏览器,服务器即要访问的网站所在的服务器
打开 Chrome 浏览器,右击并选择 “检查” 项,即可打开浏览器的开发者工具。这里访问百度 http://www.baidu.com/,输入该URL 后回车,观察这个过程中发生了怎样的网络请求。可以看到,在 Network 页面下方出现了一个个的条目,其中一个条目就代表一次发送请求和接收响应的过程

我们先观察第一个网络请求,即 <www.baidu.com,其中各列的含义如下。>
- 第一列 Name:请求的名称,一般会将 URL 的最后一部分内容当作名称。
- 第二列 Status:响应的状态码,这里显示为 200,代表响应是正常的。通过状态码,我们可以判断发送了请求之后是否得到了正常的响应。
- 第三列 Type:请求的文档类型。这里为 document,代表我们这次请求的是一个 HTML 文档,内容就是一些 HTML 代码。
- 第四列 Initiator:请求源。用来标记请求是由哪个对象或进程发起的。
- 第五列 Size:从服务器下载的文件和请求的资源大小。如果是从缓存中取得的资源,则该列会显示 from cache。
- 第六列 Time:发起请求到获取响应所用的总时间。
- 第七列 Waterfall:网络请求的可视化瀑布流。
点击这个条目即可看到其更详细的信息
首先是 General 部分,Request URL 为请求的 URL,Request Method 为请求的方法,Status Code 为响应状态码,Remote Address 为远程服务器的地址和端口,Referrer Policy 为 Referrer 判别策略。 再继续往下,可以看到,有 Response Headers 和 Request Headers,这分别代表响应头和请求头。请求头里带有许多请求信息,例如浏览器标识、Cookies、Host 等信息,这是请求的一部分,服务器会根据请求头内的信息判断请求是否合法,进而作出对应的响应。图中看到的 Response Headers 就是响应的一部分,例如其中包含了服务器的类型、文档类型、日期等信息,浏览器接受到响应后,会解析响应内容,进而呈现网页内容。
请求
请求,由客户端向服务端发出,可以分为 4 部分内容:请求方法(Request Method)、请求的网址(Request URL)、请求头(Request Headers)、请求体(Request Body)。
-
请求方法
常见的请求方法有两种:GET 和 POST。
在浏览器中直接输入 URL 并回车,这便发起了一个 GET 请求,请求的参数会直接包含到 URL 里。例如,在百度中搜索 Python,这就是一个 GET 请求,链接为 https://www.baidu.com/s?wd=Python,其中 URL 中包含了请求的参数信息,这里参数 wd 表示要搜寻的关键字。POST 请求大多在表单提交时发起。比如,对于一个登录表单,输入用户名和密码后,点击 “登录” 按钮,这通常会发起一个 POST 请求,其数据通常以表单的形式传输,而不会体现在 URL 中。
GET 和 POST 请求方法有如下区别。
- GET 请求中的参数包含在 URL 里面,数据可以在 URL 中看到,而 POST 请求的 URL 不会包含这些数据,数据都是通过表单形式传输的,会包含在请求体中。
- GET 请求提交的数据最多只有 1024 字节,而 POST 方式没有限制。
一般来说,登录时,需要提交用户名和密码,其中包含了敏感信息,使用 GET 方式请求的话,密码就会暴露在 URL 里面,造成密码泄露,所以这里最好以 POST 方式发送。上传文件时,由于文件内容比较大,也会选用 POST 方式。
我们平常遇到的绝大部分请求都是 GET 或 POST 请求,另外还有一些请求方法,如 GET、HEAD、POST、PUT、DELETE、OPTIONS、CONNECT、TRACE 等
方法 描述 GET 请求指定的页面信息,并返回实体主体。 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 PUT 从客户端向服务器传送的数据取代指定的文档的内容。 DELETE 请求服务器删除指定的页面。 CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 OPTIONS 允许客户端查看服务器的性能。 TRACE 回显服务器收到的请求,主要用于测试或诊断。 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 -
请求的网址
请求的网址,即统一资源定位符 URL,它可以唯一确定我们想请求的资源。
-
请求头
请求头,用来说明服务器要使用的附加信息,比较重要的信息有 Cookie、Referer、User-Agent 等。下面简要说明一些常用的头信息。
- Accept:请求报头域,用于指定客户端可接受哪些类型的信息。
- Accept-Language:指定客户端可接受的语言类型。
- Accept-Encoding:指定客户端可接受的内容编码。
- Host:用于指定请求资源的主机 IP 和端口号,其内容为请求 URL 的原始服务器或网关的位置。从 HTTP 1.1 版本开始,请求必须包含此内容。
- Cookie:也常用复数形式 Cookies,这是网站为了辨别用户进行会话跟踪而存储在用户本地的数据。它的主要功能是维持当前访问会话。例如,我们输入用户名和密码成功登录某个网站后,服务器会用会话保存登录状态信息,后面我们每次刷新或请求该站点的其他页面时,会发现都是登录状态,这就是 Cookies 的功劳。Cookies 里有信息标识了我们所对应的服务器的会话,每次浏览器在请求该站点的页面时,都会在请求头中加上 Cookies 并将其发送给服务器,服务器通过 Cookies 识别出是我们自己,并且查出当前状态是登录状态,所以返回结果就是登录之后才能看到的网页内容。
- Referer:此内容用来标识这个请求是从哪个页面发过来的,服务器可以拿到这一信息并做相应的处理,如做来源统计、防盗链处理等。
- User-Agent:简称 UA,它是一个特殊的字符串头,可以使服务器识别客户使用的操作系统及版本、浏览器及版本等信息。在做爬虫时加上此信息,可以伪装为浏览器;如果不加,很可能会被识别出为爬虫。
- Content-Type:也叫互联网媒体类型(Internet Media Type)或者 MIME 类型,在 HTTP 协议消息头中,它用来表示具体请求中的媒体类型信息。例如,text/html 代表 HTML 格式,image/gif 代表 GIF 图片,application/json 代表 JSON 类型,更多对应关系可以查看此对照表:http://tool.oschina.net/commons。
因此,请求头是请求的重要组成部分,在写爬虫时,大部分情况下都需要设定请求头。
-
请求体
请求体一般承载的内容是 POST 请求中的表单数据,而对于 GET 请求,请求体则为空
登录之前,我们填写了用户名和密码信息,提交时这些内容就会以表单数据的形式提交给服务器,此时需要注意 Request Headers 中指定 Content-Type 为 application/x-www-form-urlencoded。只有设置 Content-Type 为 application/x-www-form-urlencoded,才会以表单数据的形式提交。另外,我们也可以将 Content-Type 设置为 application/json 来提交 JSON 数据,或者设置为 multipart/form-data 来上传文件。
Content-Type 提交数据的方式 application/x-www-form-urlencoded 表单数据 multipart/form-data 表单文件上传 application/json 序列化 JSON 数据 text/xml XML 数据 在爬虫中,如果要构造 POST 请求,需要使用正确的 Content-Type,并了解各种请求库的各个参数设置时使用的是哪种 Content-Type,不然可能会导致 POST 提交后无法正常响应。
响应
响应,由服务端返回给客户端,可以分为三部分:响应状态码(Response Status Code)、响应头(Response Headers)和响应体(Response Body)。
-
响应状态码
响应状态码表示服务器的响应状态,如 200 代表服务器正常响应,404 代表页面未找到,500 代表服务器内部发生错误。在爬虫中,我们可以根据状态码来判断服务器响应状态,如状态码为 200,则证明成功返回数据,再进行进一步的处理,否则直接忽略。
常见错误代码
| 状态码 | 说 明 | 详 情 |
|---|---|---|
| 100 | 继续 | 请求者应当继续提出请求。服务器已收到请求的一部分,正在等待其余部分 |
| 101 | 切换协议 | 请求者已要求服务器切换协议,服务器已确认并准备切换 |
| 200 | 成功 | 服务器已成功处理了请求 |
| 201 | 已创建 | 请求成功并且服务器创建了新的资源 |
| 202 | 已接受 | 服务器已接受请求,但尚未处理 |
| 203 | 非授权信息 | 服务器已成功处理了请求,但返回的信息可能来自另一个源 |
| 204 | 无内容 | 服务器成功处理了请求,但没有返回任何内容 |
| 205 | 重置内容 | 服务器成功处理了请求,内容被重置 |
| 206 | 部分内容 | 服务器成功处理了部分请求 |
| 300 | 多种选择 | 针对请求,服务器可执行多种操作 |
| 301 | 永久移动 | 请求的网页已永久移动到新位置,即永久重定向 |
| 302 | 临时移动 | 请求的网页暂时跳转到其他页面,即暂时重定向 |
| 303 | 查看其他位置 | 如果原来的请求是 POST,重定向目标文档应该通过 GET 提取 |
| 304 | 未修改 | 此次请求返回的网页未修改,继续使用上次的资源 |
| 305 | 使用代理 | 请求者应该使用代理访问该网页 |
| 307 | 临时重定向 | 请求的资源临时从其他位置响应 |
| 400 | 错误请求 | 服务器无法解析该请求 |
| 401 | 未授权 | 请求没有进行身份验证或验证未通过 |
| 403 | 禁止访问 | 服务器拒绝此请求 |
| 404 | 未找到 | 服务器找不到请求的网页 |
| 405 | 方法禁用 | 服务器禁用了请求中指定的方法 |
| 406 | 不接受 | 无法使用请求的内容响应请求的网页 |
| 407 | 需要代理授权 | 请求者需要使用代理授权 |
| 408 | 请求超时 | 服务器请求超时 |
| 409 | 冲突 | 服务器在完成请求时发生冲突 |
| 410 | 已删除 | 请求的资源已永久删除 |
| 411 | 需要有效长度 | 服务器不接受不含有效内容长度标头字段的请求 |
| 412 | 未满足前提条件 | 服务器未满足请求者在请求中设置的其中一个前提条件 |
| 413 | 请求实体过大 | 请求实体过大,超出服务器的处理能力 |
| 414 | 请求 URI 过长 | 请求网址过长,服务器无法处理 |
| 415 | 不支持类型 | 请求格式不被请求页面支持 |
| 416 | 请求范围不符 | 页面无法提供请求的范围 |
| 417 | 未满足期望值 | 服务器未满足期望请求标头字段的要求 |
| 500 | 服务器内部错误 | 服务器遇到错误,无法完成请求 |
| 501 | 未实现 | 服务器不具备完成请求的功能 |
| 502 | 错误网关 | 服务器作为网关或代理,从上游服务器收到无效响应 |
| 503 | 服务不可用 | 服务器目前无法使用 |
| 504 | 网关超时 | 服务器作为网关或代理,但是没有及时从上游服务器收到请求 |
| 505 | HTTP 版本不支持 | 服务器不支持请求中所用的 HTTP 协议版本 |
-
响应头
响应头包含了服务器对请求的应答信息,如 Content-Type、Server、Set-Cookie 等。下面简要说明一些常用的头信息。
- Date:标识响应产生的时间。
- Last-Modified:指定资源的最后修改时间。
- Content-Encoding:指定响应内容的编码。
- Server:包含服务器的信息,比如名称、版本号等。
- Content-Type:文档类型,指定返回的数据类型是什么,如 text/html 代表返回 HTML 文档,application/x-javascript 则代表返回 JavaScript 文件,image/jpeg 则代表返回图片。
- Set-Cookie:设置 Cookies。响应头中的 Set-Cookie 告诉浏览器需要将此内容放在 Cookies 中,下次请求携带 Cookies 请求。
- Expires:指定响应的过期时间,可以使代理服务器或浏览器将加载的内容更新到缓存中。如果再次访问时,就可以直接从缓存中加载,降低服务器负载,缩短加载时间。
-
响应体
最重要的当属响应体的内容了。响应的正文数据都在响应体中,比如请求网页时,它的响应体就是网页的 HTML 代码;请求一张图片时,它的响应体就是图片的二进制数据。我们做爬虫请求网页后,要解析的内容就是响应体
在浏览器开发者工具中点击 Preview,就可以看到网页的源代码,也就是响应体的内容,它是解析的目标。 在做爬虫时,我们主要通过响应体得到网页的源代码、JSON 数据等,然后从中做相应内容的提取。
Web网页基础
网页的组成
网页可以分为三大部分 —— HTML、CSS 和 JavaScript。如果把网页比作一个人的话,HTML 相当于骨架,JavaScript 相当于肌肉,CSS 相当于皮肤,三者结合起来才能形成一个完善的网页。
-
HTML
HTML 是用来描述网页的一种语言,其全称叫作 Hyper Text Markup Language,即超文本标记语言。网页包括文字、按钮、图片和视频等各种复杂的元素,其基础架构就是 HTML。不同类型的元素通过不同类型的标签来表示,如图片用 img 标签表示,视频用 video 标签表示,段落用 p 标签表示,它们之间的布局又常通过布局标签 div 嵌套组合而成,各种标签通过不同的排列和嵌套才形成了网页的框架。
在 Chrome 浏览器中打开百度,右击并选择 “检查” 项(或按 F12 键),打开开发者模式,这时在 Elements 选项卡中即可看到网页的源代码
这就是 HTML,整个网页就是由各种标签嵌套组合而成的。这些标签定义的节点元素相互嵌套和组合形成了复杂的层次关系,就形成了网页的架构。
-
CSS
HTML 定义了网页的结构,但是只有 HTML 页面的布局并不美观,可能只是简单的节点元素的排列,为了让网页看起来更好看一些,这里借助了 CSS。
CSS,全称叫作 Cascading Style Sheets,即层叠样式表。“层叠” 是指当在 HTML 中引用了数个样式文件,并且样式发生冲突时,浏览器能依据层叠顺序处理。“样式” 指网页中文字大小、颜色、元素间距、排列等格式。
CSS 是目前唯一的网页页面排版样式标准,有了它的帮助,页面才会变得更为美观。
#head_wrapper.s-ps-islite .s-p-top {position: absolute;bottom: 40px;width: 100%;height: 181px;}就是一个 CSS 样式。大括号前面是一个 CSS 选择器。此选择器的意思是首先选中 id 为 head_wrapper 且 class 为 s-ps-islite 的节点,然后再选中其内部的 class 为 s-p-top 的节点。大括号内部写的就是一条条样式规则,例如 position 指定了这个元素的布局方式为绝对布局,bottom 指定元素的下边距为 40 像素,width 指定了宽度为 100% 占满父元素,height 则指定了元素的高度。也就是说,我们将位置、宽度、高度等样式配置统一写成这样的形式,然后用大括号括起来,接着在开头再加上 CSS 选择器,这就代表这个样式对 CSS 选择器选中的元素生效,元素就会根据此样式来展示了。 在网页中,一般会统一定义整个网页的样式规则,并写入 CSS 文件中(其后缀为 c ss)。在 HTML 中,只需要用 link 标签即可引入写好的 CSS 文件,这样整个页面就会变得美观、优雅。
-
JavaScript
JavaScript,简称 JS,是一种脚本语言。HTML 和 CSS 配合使用,提供给用户的只是一种静态信息,缺乏交互性。我们在网页里可能会看到一些交互和动画效果,如下载进度条、提示框、轮播图等,这通常就是 JavaScript 的功劳。它的出现使得用户与信息之间不只是一种浏览与显示的关系,而是实现了一种实时、动态、交互的页面功能。
JavaScript 通常也是以单独的文件形式加载的,后缀为 js,在 HTML 中通过 script 标签即可引入,例如:
<script src="jquery-2.1.0.js"></script>综上所述,HTML 定义了网页的内容和结构,CSS 描述了网页的布局,JavaScript 定义了网页的行为。
网页的结构
我们首先用例子来感受一下 HTML 的基本结构。新建一个文本文件,名称可以自取,后缀为 html,内容如下:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>这就是一个最简单的 HTML 实例。开头用 DOCTYPE 定义了文档类型,其次最外层是 html 标签,最后还有对应的结束标签来表示闭合,其内部是 head 标签和 body 标签,分别代表网页头和网页体,它们也需要结束标签。head 标 签内定义了一些页面的配置和引用,如:
<meta charset="UTF-8">
它指定了网页的编码为 UTF-8。
title 标签则定义了网页的标题,会显示在网页的选项卡中,不会显示在正文中。body 标签内则是在网页正文中显示的内容。div 标签定义了网页中的区块,它的 id 是 container,这是一个非常常用的属性,且 id 的内容在网页中是唯一的,我们可以通过它来获取这个区块。然后在此区块内又有一个 div 标签,它的 class 为 wrapper,这也是一个非常常用的属性,经常与 CSS 配合使用来设定样式。然后此区块内部又有一个 h2 标签,这代表一个二级标题。另外,还有一个 p 标签,这代表一个段落。在这两者中直接写入相应的内容即可在网页中呈现出来,它们也有各自的 class 属性。
将代码保存后,在浏览器中打开该文件,可以看到如图所示的内容。

可以看到,在选项卡上显示了 This is a Demo 字样,这是我们在 head 中的 title 里定义的文字。而网页正文是 body 标签内部定义的各个元素生成的,可以看到这里显示了二级标题和段落。 这个实例便是网页的一般结构。一个网页的标准形式是 html 标签内嵌套 head 和 body 标签,head 内定义网页的配置和引用,body 内定义网页的正文。
节点树及节点间的关系
在 HTML 中,所有标签定义的内容都是节点,它们构成了一个 HTML DOM 树。
我们先看下什么是 DOM。DOM 是 W3C(万维网联盟)的标准,其英文全称 Document Object Model,即文档对象模型。它定义了访问 HTML 和 XML 文档的标准:
W3C 文档对象模型(DOM)是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。
W3C DOM 标准被分为 3 个不同的部分:
- 核心 DOM - 针对任何结构化文档的标准模型
- XML DOM - 针对 XML 文档的标准模型
- HTML DOM - 针对 HTML 文档的标准模型
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
- 整个文档是一个文档节点
- 每个 HTML 元素是元素节点
- HTML 元素内的文本是文本节点
- 每个 HTML 属性是属性节点
- 注释是注释节点
HTML DOM 将 HTML 文档视作树结构,这种结构被称为节点树

通过 HTML DOM,树中的所有节点均可通过 JavaScript 访问,所有 HTML 节点元素均可被修改,也可以被创建或删除。
节点树中的节点彼此拥有层级关系。我们常用父(parent)、子(child)和兄弟(sibling)等术语描述这些关系。父节点拥有子节点,同级的子节点被称为兄弟节点。
在节点树中,顶端节点称为根(root)。除了根节点之外,每个节点都有父节点,同时可拥有任意数量的子节点或兄弟节点。
选择器
我们知道网页由一个个节点组成,CSS 选择器会根据不同的节点设置不同的样式规则,那么怎样来定位节点呢?
在 CSS 中,我们使用 CSS 选择器来定位节点。例如,上例中 div 节点的 id 为 container,那么就可以表示为 #container,其中 # 开头代表选择 id,其后紧跟 id 的名称。另外,如果我们想选择 class 为 wrapper 的节点,便可以使用.wrapper,这里以点(.)开头代表选择 class,其后紧跟 class 的名称。另外,还有一种选择方式,那就是根据标签名筛选,例如想选择二级标题,直接用 h2 即可。这是最常用的 3 种表示,分别是根据 id、class、标签名筛选,请牢记它们的写法。
另外,CSS 选择器还支持嵌套选择,各个选择器之间加上空格分隔开便可以代表嵌套关系,如 #container .wrapper p 则代表先选择 id 为 container 的节点,然后选中其内部的 class 为 wrapper 的节点,然后再进一步选中其内部的 p 节点。另外,如果不加空格,则代表并列关系,如 div#container .wrapper p.text 代表先选择 id 为 container 的 div 节点,然后选中其内部的 class 为 wrapper 的节点,再进一步选中其内部的 class 为 text 的 p 节点。这就是 CSS 选择器,其筛选功能还是非常强大的。
另外,CSS 选择器还有一些其他语法规则
CSS语法
| 选 择 器 | 例 子 | 例子描述 |
|---|---|---|
| .class | .intro | 选择 class=“intro” 的所有节点 |
| #id | #firstname | 选择 id=“firstname” 的所有节点 |
| * | * | 选择所有节点 |
| element | p | 选择所有 p 节点 |
| element,element | div,p | 选择所有 div 节点和所有 p 节点 |
| element element | div p | 选择 div 节点内部的所有 p 节点 |
| element>element | div>p | 选择父节点为 div 节点的所有 p 节点 |
| element+element | div+p | 选择紧接在 div 节点之后的所有 p 节点 |
| [attribute] | [target] | 选择带有 target 属性的所有节点 |
| [attribute=value] | [target=blank] | 选择 target=“blank” 的所有节点 |
| [attribute~=value] | [title~=flower] | 选择 title 属性包含单词 flower 的所有节点 |
| a | 选择所有未被访问的链接 | |
| a | 选择所有已被访问的链接 | |
| a | 选择活动链接 | |
| a | 选择鼠标指针位于其上的链接 | |
| input | 选择获得焦点的 input 节点 | |
| p | 选择每个 p 节点的首字母 | |
| p | 选择每个 p 节点的首行 | |
| p | 选择属于父节点的第一个子节点的所有 p 节点 | |
| p | 在每个 p 节点的内容之前插入内容 | |
| p | 在每个 p 节点的内容之后插入内容 | |
| p | 选择带有以 it 开头的 lang 属性值的所有 p 节点 | |
| element1~element2 | p~ul | 选择前面有 p 节点的所有 ul 节点 |
| [attribute^=value] | a[src^=“https”] | 选择其 src 属性值以 https 开头的所有 a 节点 |
| [attribute$=value] | a[src$=“.pdf”] | 选择其 src 属性以.pdf 结尾的所有 a 节点 |
| [attribute*=value] | a[src*=“abc”] | 选择其 src 属性中包含 abc 子串的所有 a 节点 |
| p | 选择属于其父节点的首个 p 节点的所有 p 节点 | |
| p | 选择属于其父节点的最后 p 节点的所有 p 节点 | |
| p | 选择属于其父节点唯一的 p 节点的所有 p 节点 | |
| p | 选择属于其父节点的唯一子节点的所有 p 节点 | |
| p | 选择属于其父节点的第二个子节点的所有 p 节点 | |
| p | 同上,从最后一个子节点开始计数 | |
| p | 选择属于其父节点第二个 p 节点的所有 p 节点 | |
| p | 同上,但是从最后一个子节点开始计数 | |
| p | 选择属于其父节点最后一个子节点的所有 p 节点 | |
| 选择文档的根节点 | ||
| p | 选择没有子节点的所有 p 节点(包括文本节点) | |
| #news | 选择当前活动的 #news 节点 | |
| input | 选择每个启用的 input 节点 | |
| input | 选择每个禁用的 input 节点 | |
| input | 选择每个被选中的 input 节点 | |
| 选择非 p 节点的所有节点 | ||
| ::selection | ::selection | 选择被用户选取的节点部分 |
爬虫基本原理
我们可以把互联网比作一张大网,而爬虫(即网络爬虫)便是在网上爬行的蜘蛛。把网的节点比作一个个网页,爬虫爬到这就相当于访问了该页面,获取了其信息。可以把节点间的连线比作网页与网页之间的链接关系,这样蜘蛛通过一个节点后,可以顺着节点连线继续爬行到达下一个节点,即通过一个网页继续获取后续的网页,这样整个网的节点便可以被蜘蛛全部爬行到,网站的数据就可以被抓取下来了。
爬虫概述
简单来说,爬虫就是获取网页并提取和保存信息的自动化程序,下面概要介绍一下。
-
获取网页
爬虫首先要做的工作就是获取网页,这里就是获取网页的源代码。源代码里包含了网页的部分有用信息,所以只要把源代码获取下来,就可以从中提取想要的信息了。
前面讲了请求和响应的概念,向网站的服务器发送一个请求,返回的响应体便是网页源代码。所以,最关键的部分就是构造一个请求并发送给服务器,然后接收到响应并将其解析出来。
Python 提供了许多库来帮助我们实现这个操作,如 urllib、requests 等。我们可以用这些库来帮助我们实现 HTTP 请求操作,请求和响应都可以用类库提供的数据结构来表示,得到响应之后只需要解析数据结构中的 Body 部分即可,即得到网页的源代码,这样我们可以用程序来实现获取网页的过程了。
-
提取信息
获取网页源代码后,接下来就是分析网页源代码,从中提取我们想要的数据。首先,最通用的方法便是采用正则表达式提取,这是一个万能的方法,但是在构造正则表达式时比较复杂且容易出错。
另外,由于网页的结构有一定的规则,所以还有一些根据网页节点属性、CSS 选择器或 XPath 来提取网页信息的库,如 Beautiful Soup、pyquery、lxml 等。使用这些库,我们可以高效快速地从中提取网页信息,如节点的属性、文本值等。
提取信息是爬虫非常重要的部分,它可以使杂乱的数据变得条理清晰,以便我们后续处理和分析数据。
-
保存数据
提取信息后,我们一般会将提取到的数据保存到某处以便后续使用。这里保存形式有多种多样,如可以简单保存为 TXT 文本或 JSON 文本,也可以保存到数据库,如 MySQL 和 MongoDB 等,也可保存至远程服务器,如借助 SFTP 进行操作等。
-
自动化程序
说到自动化程序,意思是说爬虫可以代替人来完成这些操作。首先,我们手工当然可以提取这些信息,但是当量特别大或者想快速获取大量数据的话,肯定还是要借助程序。爬虫就是代替我们来完成这份爬取工作的自动化程序,它可以在抓取过程中进行各种异常处理、错误重试等操作,确保爬取持续高效地运行。
能抓怎样的数据
在网页中我们能看到各种各样的信息,最常见的便是常规网页,它们对应着 HTML 代码,而最常抓取的便是 HTML 源代码。
另外,可能有些网页返回的不是 HTML 代码,而是一个 JSON 字符串(其中 API 接口大多采用这样的形式),这种格式的数据方便传输和解析,它们同样可以抓取,而且数据提取更加方便。
此外,我们还可以看到各种二进制数据,如图片、视频和音频等。利用爬虫,我们可以将这些二进制数据抓取下来,然后保存成对应的文件名。
另外,还可以看到各种扩展名的文件,如 CSS、JavaScript 和配置文件等,这些其实也是最普通的文件,只要在浏览器里面可以访问到,就可以将其抓取下来。
上述内容其实都对应各自的 URL,是基于 HTTP 或 HTTPS 协议的,只要是这种数据,爬虫都可以抓取。
JavaScript 渲染页面
有时候,我们在用 urllib 或 requests 抓取网页时,得到的源代码实际和浏览器中看到的不一样。
这是一个非常常见的问题。现在网页越来越多地采用 Ajax、前端模块化工具来构建,整个网页可能都是由 JavaScript 渲染出来的,也就是说原始的 HTML 代码就是一个空壳,例如:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> </div> </body> <script src="app.js"></script></html>body 节点里面只有一个 id 为 container 的节点,但是需要注意在 body 节点后引入了 app.js,它便负责整个网站的渲染。
在浏览器中打开这个页面时,首先会加载这个 HTML 内容,接着浏览器会发现其中引入了一个 app.js 文件,然后便会接着去请求这个文件,获取到该文件后,便会执行其中的 JavaScript 代码,而 JavaScript 则会改变 HTML 中的节点,向其添加内容,最后得到完整的页面。
但是在用 urllib 或 requests 等库请求当前页面时,我们得到的只是这个 HTML 代码,它不会帮助我们去继续加载这个 JavaScript 文件,这样也就看不到浏览器中的内容了。
这也解释了为什么有时我们得到的源代码和浏览器中看到的不一样。
因此,使用基本 HTTP 请求库得到的源代码可能跟浏览器中的页面源代码不太一样。对于这样的情况,我们可以分析其后台 Ajax 接口,也可使用 Selenium、Splash 这样的库来实现模拟 JavaScript 渲染。
会话和Cookies
在浏览网站的过程中,我们经常会遇到需要登录的情况,有些页面只有登录之后才可以访问,而且登录之后可以连续访问很多次网站,但是有时候过一段时间就需要重新登录。还有一些网站,在打开浏览器时就自动登录了,而且很长时间都不会失效,这种情况涉及会话(Session)和 Cookies 的相关知识。
静态网页和动态网页
在开始之前,我们需要先了解一下静态网页和动态网页的概念。这里还是前面的示例代码,内容如下
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>这是最基本的 HTML 代码,我们将其保存为一个 .html 文件,然后把它放在某台具有固定公网 IP 的主机上,主机上装上 Apache 或 Nginx 等服务器,这样这台主机就可以作为服务器了,其他人便可以通过访问服务器看到这个页面,这就搭建了一个最简单的网站
这种网页的内容是 HTML 代码编写的,文字、图片等内容均通过写好的 HTML 代码来指定,这种页面叫作静态网页。它加载速度快,编写简单,但是存在很大的缺陷,如可维护性差,不能根据 URL 灵活多变地显示内容等。例如,我们想要给这个网页的 URL 传入一个 name 参数,让其在网页中显示出来,是无法做到的。
因此,动态网页应运而生,它可以动态解析 URL 中参数的变化,关联数据库并动态呈现不同的页面内容,非常灵活多变。我们现在遇到的大多数网站都是动态网站,它们不再是一个简单的 HTML,而是可能由 JSP、PHP、Python 等语言编写的,其功能比静态网页强大和丰富太多了。
此外,动态网站还可以实现用户登录和注册的功能。再回到开头提到的问题,很多页面是需要登录之后才可以查看的。按照一般的逻辑来说,输入用户名和密码登录之后,肯定是拿到了一种类似凭证的东西,有了它,我们才能保持登录状态,才能访问登录之后才能看到的页面。
无状态 HTTP
在了解会话和 Cookies 之前,我们还需要了解 HTTP 的一个特点,叫作无状态。
HTTP 的无状态是指 HTTP 协议对事务处理是没有记忆能力的,也就是说服务器不知道客户端是什么状态。当我们向服务器发送请求后,服务器解析此请求,然后返回对应的响应,服务器负责完成这个过程,而且这个过程是完全独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。这意味着如果后续需要处理前面的信息,则必须重传,这导致需要额外传递一些前面的重复请求,才能获取后续响应,然而这种效果显然不是我们想要的。为了保持前后状态,我们肯定不能将前面的请求全部重传一次,这太浪费资源了,对于这种需要用户登录的页面来说,更是棘手。
这时两个用于保持 HTTP 连接状态的技术就出现了,它们分别是会话和 Cookies。会话在服务端,也就是网站的服务器,用来保存用户的会话信息;Cookies 在客户端,也可以理解为浏览器端,有了 Cookies,浏览器在下次访问网页时会自动附带上它发送给服务器,服务器通过识别 Cookies 并鉴定出是哪个用户,然后再判断用户是否是登录状态,然后返回对应的响应。
我们可以理解为 Cookies 里面保存了登录的凭证,有了它,只需要在下次请求携带 Cookies 发送请求而不必重新输入用户名、密码等信息重新登录了。
因此在爬虫中,有时候处理需要登录才能访问的页面时,我们一般会直接将登录成功后获取的 Cookies 放在请求头里面直接请求,而不必重新模拟登录。
-
会话
会话,其本来的含义是指有始有终的一系列动作 / 消息。比如,打电话时,从拿起电话拨号到挂断电话这中间的一系列过程可以称为一个会话。
而在 Web 中,会话对象用来存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在会话对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个会话对象。当会话过期或被放弃后,服务器将终止该会话。
2. Cookies
Cookies 指某些网站为了辨别用户身份、进行会话跟踪而存储在用户本地终端上的数据。
-
会话维持
当客户端第一次请求服务器时,服务器会返回一个响应头中带有 Set-Cookie 字段的响应给客户端,用来标记是哪一个用户,客户端浏览器会把 Cookies 保存起来。当浏览器下一次再请求该网站时,浏览器会把此 Cookies 放到请求头一起提交给服务器,Cookies 携带了会话 ID 信息,服务器检查该 Cookies 即可找到对应的会话是什么,然后再判断会话来以此来辨认用户状态。
在成功登录某个网站时,服务器会告诉客户端设置哪些 Cookies 信息,在后续访问页面时客户端会把 Cookies 发送给服务器,服务器再找到对应的会话加以判断。如果会话中的某些设置登录状态的变量是有效的,那就证明用户处于登录状态,此时返回登录之后才可以查看的网页内容,浏览器再进行解析便可以看到了。
反之,如果传给服务器的 Cookies 是无效的,或者会话已经过期了,我们将不能继续访问页面,此时可能会收到错误的响应或者跳转到登录页面重新登录。
所以,Cookies 和会话需要配合,一个处于客户端,一个处于服务端,二者共同协作,就实现了登录会话控制。
-
属性结构
接下来,我们来看看 Cookies 都有哪些内容。这里以知乎为例,在浏览器开发者工具中打开 Application 选项卡,然后在左侧会有一个 Storage 部分,最后一项即为 Cookies,将其点开,这些就是 Cookies。

可以看到,这里有很多条目,其中每个条目可以称为 Cookie。它有如下几个属性。
- Name,即该 Cookie 的名称。Cookie 一旦创建,名称便不可更改
- Value,即该 Cookie 的值。如果值为 Unicode 字符,需要为字符编码。如果值为二进制数据,则需要使用 BASE64 编码。
- Max Age,即该 Cookie 失效的时间,单位秒,也常和 Expires 一起使用,通过它可以计算出其有效时间。Max Age 如果为正数,则该 Cookie 在 Max Age 秒之后失效。如果为负数,则关闭浏览器时 Cookie 即失效,浏览器也不会以任何形式保存该 Cookie。
- Path,即该 Cookie 的使用路径。如果设置为 /path/,则只有路径为 /path/ 的页面可以访问该 Cookie。如果设置为 /,则本域名下的所有页面都可以访问该 Cookie。
- Domain,即可以访问该 Cookie 的域名。例如如果设置为 .zhihu.com,则所有以 zhihu.com,结尾的域名都可以访问该 Cookie。
- Size 字段,即此 Cookie 的大小。
- Http 字段,即 Cookie 的 httponly 属性。若此属性为 true,则只有在 HTTP Headers 中会带有此 Cookie 的信息,而不能通过 document.cookie 来访问此 Cookie。
- Secure,即该 Cookie 是否仅被使用安全协议传输。安全协议。安全协议有 HTTPS,SSL 等,在网络上传输数据之前先将数据加密。默认为 false。
-
会话 Cookie 和持久 Cookie
从表面意思来说,会话 Cookie 就是把 Cookie 放在浏览器内存里,浏览器在关闭之后该 Cookie 即失效;持久 Cookie 则会保存到客户端的硬盘中,下次还可以继续使用,用于长久保持用户登录状态。
其实严格来说,没有会话 Cookie 和持久 Cookie 之 分,只是由 Cookie 的 Max Age 或 Expires 字段决定了过期的时间。
因此,一些持久化登录的网站其实就是把 Cookie 的有效时间和会话有效期设置得比较长,下次我们再访问页面时仍然携带之前的 Cookie,就可以直接保持登录状态。
常见误区
在谈论会话机制的时候,常常听到这样一种误解 ——“只要关闭浏览器,会话就消失了”。可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对会话来说,也是一样,除非程序通知服务器删除一个会话,否则服务器会一直保留。比如,程序一般都是在我们做注销操作时才去删除会话。
但是当我们关闭浏览器时,浏览器不会主动在关闭之前通知服务器它将要关闭,所以服务器根本不会有机会知道浏览器已经关闭。之所以会有这种错觉,是因为大部分会话机制都使用会话 Cookie 来保存会话 ID 信息,而关闭浏览器后 Cookies 就消失了,再次连接服务器时,也就无法找到原来的会话了。如果服务器设置的 Cookies 保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 Cookies 发送给服务器,则再次打开浏览器,仍然能够找到原来的会话 ID,依旧还是可以保持登录状态的。
而且恰恰是由于关闭浏览器不会导致会话被删除,这就需要服务器为会话设置一个失效时间,当距离客户端上一次使用会话的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把会话删除以节省存储空间。
代理基本原理
我们在做爬虫的过程中经常会遇到这样的情况,最初爬虫正常运行,正常抓取数据,一切看起来都是那么美好,然而一杯茶的功夫可能就会出现错误,比如 403 Forbidden,这时候打开网页一看,可能会看到 “您的 IP 访问频率太高” 这样的提示。出现这种现象的原因是网站采取了一些反爬虫措施。比如,服务器会检测某个 IP 在单位时间内的请求次数,如果超过了这个阈值,就会直接拒绝服务,返回一些错误信息,这种情况可以称为封 IP。
既然服务器检测的是某个 IP 单位时间的请求次数,那么借助某种方式来伪装我们的 IP,让服务器识别不出是由我们本机发起的请求,不就可以成功防止封 IP 了吗?
一种有效的方式就是使用代理。
基本原理
代理实际上指的就是代理服务器,英文叫作 proxy server,它的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站。
在我们正常请求一个网站时,是发送了请求给 Web 服务器,Web 服务器把响应传回给我们。如果设置了代理服务器,实际上就是在本机和服务器之间搭建了一个桥,此时本机不是直接向 Web 服务器发起请求,而是向代理服务器发出请求,请求会发送给代理服务器,然后由代理服务器再发送给 Web 服务器,接着由代理服务器再把 Web 服务器返回的响应转发给本机。
这样我们同样可以正常访问网页,但这个过程中 Web 服务器识别出的真实 IP 就不再是我们本机的 IP 了,就成功实现了 IP 伪装,这就是代理的基本原理。
代理的作用
那么,代理有什么作用呢?我们可以简单列举如下。
突破自身 IP 访问限制,访问一些平时不能访问的站点。
访问一些单位或团体内部资源,如使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类 FTP 下载上传,以及各类资料查询共享等服务。
提高访问速度,通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
隐藏真实 IP,上网者也可以通过这种方法隐藏自己的 IP,免受攻击,对于爬虫来说,我们用代理就是为了隐藏自身 IP,防止自身的 IP 被封锁。
爬虫代理
对于爬虫来说,由于爬虫爬取速度过快,在爬取过程中可能遇到同一个 IP 访问过于频繁的问题,此时网站就会让我们输入验证码登录或者直接封锁 IP,这样会给爬取带来极大的不便。
使用代理隐藏真实的 IP,让服务器误以为是代理服务器在请求自己。这样在爬取过程中通过不断更换代理,就不会被封锁,可以达到很好的爬取效果。
代理分类
代理分类时,既可以根据协议区分,也可以根据其匿名程度区分,下面分别总结如下:
-
根据协议区分
根据代理的协议,代理可以分为如下类别:
- FTP 代理服务器,主要用于访问 FTP 服务器,一般有上传、下载以及缓存功能,端口一般为 21、2121 等。
- HTTP 代理服务器,主要用于访问网页,一般有内容过滤和缓存功能,端口一般为 80、8080、3128 等。
- SSL/TLS 代理,主要用于访问加密网站,一般有 SSL 或 TLS 加密功能(最高支持 128 位加密强度),端口一般为 443。
- RTSP 代理,主要用于 Realplayer 访问 Real 流媒体服务器,一般有缓存功能,端口一般为 554。
- Telnet 代理,主要用于 telnet 远程控制(黑客入侵计算机时常用于隐藏身份),端口一般为 23。
- POP3/SMTP 代理,主要用于 POP3/SMTP 方式收发邮件,一般有缓存功能,端口一般为 110/25。
- SOCKS 代理,只是单纯传递数据包,不关心具体协议和用法,所以速度快很多,一般有缓存功能,端口一般为 1080。SOCKS 代理协议又分为 SOCKS4 和 SOCKS5,SOCKS4 协议只支持 TCP,而 SOCKS5 协议支持 TCP 和 UDP,还支持各种身份验证机制、服务器端域名解析等。简单来说,SOCK4 能做到的 SOCKS5 都可以做到,但 SOCKS5 能做到的 SOCK4 不一定能做到。
-
根据匿名程度区分
根据代理的匿名程度,代理可以分为如下类别。
- 高度匿名代理,高度匿名代理会将数据包原封不动的转发,在服务端看来就好像真的是一个普通客户端在访问,而记录的 IP 是代理服务器的 IP。
- 普通匿名代理,普通匿名代理会在数据包上做一些改动,服务端上有可能发现这是个代理服务器,也有一定几率追查到客户端的真实 IP。代理服务器通常会加入的 HTTP 头有 HTTP_VIA 和 HTTP_X_FORWARDED_FOR。
- 透明代理,透明代理不但改动了数据包,还会告诉服务器客户端的真实 IP。这种代理除了能用缓存技术提高浏览速度,能用内容过滤提高安全性之外,并无其他显著作用,最常见的例子是内网中的硬件防火墙。
- 间谍代理,间谍代理指组织或个人创建的,用于记录用户传输的数据,然后进行研究、监控等目的代理服务器。
常见代理设置
- 使用网上的免费代理,最好使用高匿代理,使用前抓取下来筛选一下可用代理,也可以进一步维护一个代理池。
- 使用付费代理服务,互联网上存在许多代理商,可以付费使用,质量比免费代理好很多。
- ADSL 拨号,拨一次号换一次 IP,稳定性高,也是一种比较有效的解决方案。
HTTP Basic Principles
URI and URL
Here we first understand URI and URL. URI stands for Uniform Resource Identifier, and URL stands for Uniform Resource Locator.
For example, [https://github.com/favicon.ico] is a URL, and it is also a URI. This icon resource can be uniquely identified by a URL/URI, which includes the access protocol https, the path (root directory), and the resource name favicon.ico. Through such a link, we can locate this resource on the Internet, which is exactly what a URL/URI is used for.
URL is a subset of URI, meaning every URL is a URI, but not every URI is a URL. Then, what URI is not a URL? URI also includes a subclass called URN, whose full name is Uniform Resource Name. URN only names a resource and does not specify how to locate it, for example urn:isbn:0451450523 specifies a book’s ISBN, which can uniquely identify the book but does not specify where to locate it; that is URN.

But on the current Internet, URN usage is quite rare, so almost all URIs are URLs, thus general web links can be referred to as URL, or URI; I personally prefer to call them URL.
Hypertext
Next, let’s understand another concept — hypertext, whose English name is hypertext. The web pages we see in the browser are formed by hypertext parsing; their page source code is a sequence of HTML code containing various tags, such as img to display images, p to designate paragraphs, etc. After the browser parses these tags, it forms the web page we normally see, and the page source HTML can be called hypertext.
For example, in Chrome, right-click anywhere on any page and choose “Inspect” (or press F12) to open the browser’s developer tools. In the Elements tab you can see the current page’s source code; this code is hypertext.
HTTP and HTTPS
On Taobao’s homepage [https://www.taobao.com/], the URL at the beginning begins with http or https, which is the protocol required to access the resource. Sometimes you may also see URLs starting with ftp, sftp, smb; these are also protocol types. In crawlers, the pages we fetch are usually HTTP or HTTPS, so here we first understand these two protocols.
HTTP stands for Hyper Text Transfer Protocol; the Chinese name is Hypertext Transfer Protocol. The HTTP protocol is used to transfer hypertext data from the network to the local browser; it ensures efficient and accurate transmission of hypertext documents. HTTP is a standard developed through collaborative effort by the World Wide Web Consortium (W3C) and the Internet Engineering Task Force (IETF); the widely used version today is HTTP 1.1.
HTTPS stands for Hyper Text Transfer Protocol over Secure Socket Layer; it is a secure HTTP channel, simply the secure version of HTTP, i.e., HTTP with SSL layer, abbreviated as HTTPS.
The security basis of HTTPS is SSL, so content transmitted through it is encrypted with SSL. Its main purposes can be divided into two:
- Establish a secure communication channel to ensure data transmission security.
- Verify the authenticity of the website; any site using HTTPS can have its authentication information viewed by clicking the lock icon in the browser’s address bar, or can be verified via the security signature issued by a CA authority.
Some sites, even though using HTTPS, may still be flagged as not secure by browsers.
HTTP Request Process
When we enter a URL in the browser and press Enter, we see the page content in the browser. In fact, this process is the browser sending a request to the server hosting the site; the server processes and parses the request, then returns a corresponding response, which is sent back to the browser. The response contains the page’s source code and other content; the browser parses it and renders the page.

Here the client represents our own PC or mobile browser, and the server is the website’s hosting server.
Open Chrome, right-click and choose “Inspect” to open the browser’s developer tools. Here, visit a site like Baidu [http://www.baidu.com/], enter that URL and press Enter, and observe how the network requests occur. You can see in the Network panel a series of entries, each entry representing a request/response cycle.
General
Click this entry to see more detailed information.
First is the General section: Request URL is the URL of the request, Request Method is the method, Status Code is the response status, Remote Address is the address and port of the remote server, and Referrer Policy is the referrer-detection policy. Continuing down, you can see Response Headers and Request Headers, which represent the response headers and request headers respectively. The request headers carry lots of information such as browser identification, cookies, Host, etc. This is part of the request; the server uses the information in the headers to decide whether the request is valid and respond accordingly. The Response Headers shown in the figure are part of the response, such as the server type, document type, date, etc. After the browser receives the response, it parses the content and renders the page.
Request
A request, issued by the client to the server, can be divided into four parts: Request Method, Request URL, Request Headers, and Request Body.
- Request Method
There are two common methods: GET and POST.
When you enter a URL in the browser and press Enter, this initiates a GET request; the request parameters are included directly in the URL. For example, searching Python on Baidu results in a GET request; the link is https://www.baidu.com/s?wd=Python, where the parameter wd indicates the search keyword. POST requests are usually initiated when submitting a form. For example, in a login form, after entering username and password and clicking the “Login” button, this typically triggers a POST request, and its data is usually transmitted as form data, not visible in the URL.
Differences between GET and POST:
- In GET requests, parameters are included in the URL and can be seen in the URL, while in POST requests the URL does not contain these data; the data are transmitted via the form and included in the request body.
- GET requests have a maximum data size of about 1024 bytes, while POST has no such limit.
Generally, when logging in, you submit a username and password, which contain sensitive information; using GET would expose the password in the URL, leading to leakage, so it is better to send via POST. When uploading files, due to potentially large content, POST is used as well.
Most requests you encounter are GET or POST, but there are other methods as well, such as GET, HEAD, POST, PUT, DELETE, OPTIONS, CONNECT, TRACE, etc.
| Method | Description |
|---|---|
| GET | Requests the specified page information and returns the entity body. |
| HEAD | Similar to GET, but the response does not contain the body; used to obtain headers. |
| POST | Submits data to be processed to a specified resource (e.g., submitting a form or uploading a file). Data is included in the request body. POST may create new resources and/or modify existing ones. |
| PUT | Replaces the content of a specified document with the data sent by the client. |
| DELETE | Requests the server to delete the specified page. |
| CONNECT | Reserved for proxies that can tunnel the connection. |
| OPTIONS | Allows the client to view the server’s capabilities. |
| TRACE | Echoes back the request received by the server, mainly for testing or diagnostics. |
| PATCH | A supplement to PUT, used for partial updates to a known resource. |
- Request URL
The request URL, i.e., the Uniform Resource Locator (URL), uniquely identifies the resource we want to request.
- Request Headers
Request headers specify additional information for the server to use. Important headers include Cookie, Referer, User-Agent, etc. Here are brief explanations of some common headers.
- Accept: Request header field used to specify which types of information the client can accept.
- Accept-Language: Specifies the languages the client can accept.
- Accept-Encoding: Specifies the content encodings the client can accept.
- Host: Specifies the host IP and port of the requested resource; its value is the location of the original server or gateway for the request URL. Since HTTP/1.1, this header must be included.
- Cookie: Also commonly Cookies; data stored on the client to differentiate users and maintain sessions. Its main function is to maintain the current session. For example, after logging in to a site, the server stores login state in the session; on subsequent requests, Cookies keep you logged in.
- Referer: Identifies which page the request came from; the server can use this for analytics, anti-hotlinking, etc.
- User-Agent: A short string header that helps the server identify the client’s operating system and version, browser and version, etc. Adding this in crawlers can pretend to be a browser; without it, you might be flagged as a crawler.
- Content-Type: Also known as Internet Media Type or MIME type. In HTTP headers, it indicates the media type of the request body. For example, text/html denotes HTML, image/gif denotes GIF images, application/json denotes JSON data, and more can be found in this reference table: http://tool.oschina.net/commons.
Thus, request headers are an important part of the request, and when writing crawlers, you usually need to set request headers.
- Request Body
The request body generally carries the data in POST requests; for GET requests, the body is empty.
Before logging in, we fill in a username and password, and when submitting these are sent to the server as form data. In this case, pay attention to the Content-Type specified in the Request Headers as application/x-www-form-urlencoded. Only when Content-Type is set to application/x-www-form-urlencoded will the data be submitted as form data. You can also set Content-Type to application/json to submit JSON data, or to multipart/form-data to upload files.
| Content-Type | Data submission method |
|---|---|
| application/x-www-form-urlencoded | Form data |
| multipart/form-data | Form file uploads |
| application/json | Serialized JSON data |
| text/xml | XML data |
In a crawler, to construct a POST request, you need to use the correct Content-Type and understand which Content-Type different request libraries use for various parameters; otherwise, POST submissions may not receive a proper response.
Response
A response is returned by the server to the client and can be divided into three parts: Response Status Code, Response Headers, and Response Body.
- Response Status Code
The response status code indicates the server’s response status. For example, 200 means normal response, 404 means not found, 500 means internal server error. In crawlers, you can determine whether the server responded normally by the status code; if the status is 200, you have data, and you can proceed; otherwise, you can ignore.
Common Error Codes
| Status Code | Description | Details |
|---|---|---|
| 100 | Continue | The requester should continue with the request. The server has received part of the request and is waiting for the rest. |
| 101 | Switching Protocols | The requester has asked the server to switch protocols, the server has agreed and is ready to switch. |
| 200 | OK | The server has successfully processed the request. |
| 201 | Created | The request has succeeded and the server has created a new resource. |
| 202 | Accepted | The server has accepted the request but has not yet processed it. |
| 203 | Non-Authoritative Information | The server has successfully processed the request, but the returned information may come from another source. |
| 204 | No Content | The server successfully processed the request, but there is no content to return. |
| 205 | Reset Content | The server successfully processed the request, and the content has been reset. |
| 206 | Partial Content | The server has successfully processed part of the request. |
| 300 | Multiple Choices | The server can provide multiple options for the request. |
| 301 | Moved Permanently | The requested page has permanently moved to a new location; permanent redirect. |
| 302 | Found | The requested page temporarily moves to another page; temporary redirect. |
| 303 | See Other | If the original request was POST, the redirected document should be retrieved with GET. |
| 304 | Not Modified | The requested page has not been modified; continue using the previous resource. |
| 305 | Use Proxy | The requester should use a proxy to access the page. |
| 307 | Temporary Redirect | The requested resource is temporarily located at another place. |
| 400 | Bad Request | The server cannot parse the request. |
| 401 | Unauthorized | The request lacks valid authentication credentials. |
| 403 | Forbidden | The server refuses to fulfill the request. |
| 404 | Not Found | The server cannot find the requested page. |
| 405 | Method Not Allowed | The method specified in the request is not allowed. |
| 406 | Not Acceptable | The server cannot respond with the requested content. |
| 407 | Proxy Authentication Required | The client must authenticate itself to the proxy. |
| 408 | Request Timeout | The server timed out waiting for the request. |
| 409 | Conflict | The request could not be completed due to a conflict with the current state of the resource. |
| 410 | Gone | The resource requested is no longer available. |
| 411 | Length Required | The server refuses to accept the request without a defined Content-Length. |
| 412 | Precondition Failed | The server does not meet one of the preconditions specified in the request headers. |
| 413 | Payload Too Large | The request entity is larger than the server is able to process. |
| 414 | URI Too Long | The URI requested is longer than the server is able to process. |
| 415 | Unsupported Media Type | The request format is not supported by the target resource. |
| 416 | Range Not Satisfiable | The server cannot provide the requested range. |
| 417 | Expectation Failed | The server cannot meet the requirements of the Expect request-header field. |
| 500 | Internal Server Error | The server encountered an error and could not complete the request. |
| 501 | Not Implemented | The server does not support the functionality required to fulfill the request. |
| 502 | Bad Gateway | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
| 503 | Service Unavailable | The server is currently unable to handle the request. |
| 504 | Gateway Timeout | The server, acting as a gateway or proxy, did not receive a timely response from the upstream server. |
| 505 | HTTP Version Not Supported | The server does not support the HTTP protocol version used in the request. |
- Response Headers
Response headers contain the server’s reply information, such as Content-Type, Server, Set-Cookie, etc. Here are brief explanations of some common headers.
- Date: The time the response was generated.
- Last-Modified: The last modification time of the resource.
- Content-Encoding: The encoding of the response content.
- Server: Information about the server, such as its name and version.
- Content-Type: The document type, indicating the type of data returned, such as text/html for HTML documents, application/x-javascript for JavaScript files, image/jpeg for images.
- Set-Cookie: Sets cookies. The Set-Cookie header tells the browser to store this in Cookies; on subsequent requests, Cookies are sent.
- Expires: Specifies the expiration time of the response; proxies or browsers can update the cached content. If you visit again, content can be loaded directly from the cache, reducing server load and loading time.
- Response Body
Most importantly is the content of the response body. The body contains the main data of the response; for example, when requesting a web page, the response body is the page’s HTML code; when requesting an image, the response body is the image’s binary data. When crawling a page, the content you parse comes from the response body.
In the browser’s developer tools, click Preview to see the page’s source code, which is the content of the response body; this is the target to parse.
When crawling, we mainly obtain the page’s source code, JSON data, etc., from the response body, and then extract the corresponding content.
Web Page Basics
Composition of Web Pages
A webpage can be divided into three parts — HTML, CSS, and JavaScript. If you compare a webpage to a person, HTML is the skeleton, JavaScript is the muscles, and CSS is the skin; only when combined do they form a complete webpage.
- HTML
HTML is a language used to describe webpages, full name Hyper Text Markup Language. Web pages include text, buttons, images, and videos, and the basic structure is HTML. Different types of elements are represented by different tags, such as img for images, video for videos, p for paragraphs; their layout is often achieved by nesting div elements. The tags are arranged and nested to form the page’s framework.
In Chrome, open Baidu, right-click and choose “Inspect” (or press F12) to open the developer mode. In the Elements tab you can view the page’s source code.
This is HTML; the entire page is built from nested tags. The nodes defined by these tags nest and combine to form a complex hierarchical structure, which constitutes the page’s architecture.
- CSS
HTML defines the page structure, but plain HTML layout alone isn’t very attractive. CSS is used to style the page.
CSS stands for Cascading Style Sheets. “Cascading” means that when multiple styles are applied to HTML and conflicts occur, the browser resolves them according to the cascade order. “Styles” refer to text size, color, spacing, layout, etc.
CSS is currently the only standard for web page styling. With CSS, pages look more attractive.
#head_wrapper.s-ps-islite .s-p-top { position: absolute; bottom: 40px; width: 100%; height: 181px;}That is a CSS rule. The part before the braces is a CSS selector. This selector means: first select the node with id head_wrapper and class s-ps-islite, then select the internal node with class s-p-top. Inside the braces are individual style rules, such as position indicating absolute layout, bottom indicating a bottom margin of 40 pixels, width 100% to fill the parent, and height for the element’s height. In other words, we write placement, width, height, and other styles in this form, bracketed, and the initial CSS selector that targets the selected elements makes the style take effect, and the elements render accordingly.
In web pages, style rules are usually defined globally and written into CSS files (with a .css suffix). In HTML, you can include the prepared CSS file with a link tag, and the whole page becomes more visually appealing.
- JavaScript
JavaScript, or JS, is a scripting language. HTML and CSS together provide static information to users, but lack interactivity. You may see interactive effects on a page, such as download progress bars, prompts, or carousels, and this is usually thanks to JavaScript. It enables real-time, dynamic, interactive page functionality.
JavaScript is typically loaded as a separate file, with a .js suffix, and included in HTML via a script tag, for example:
<script src="jquery-2.1.0.js"></script>In summary, HTML defines the content and structure of a webpage, CSS describes the layout, and JavaScript defines the page’s behavior.
Web Page Structure
Let’s start with an example to feel the basic structure of HTML. Create a text file with any name, with a .html extension, containing the following:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>This is the simplest HTML example. The document type is defined with DOCTYPE at the top; the outermost tag is html, and there are closing tags to mark the end. Inside are head and body tags, which represent the page header and page body, and both require closing tags. The head tag defines some page configurations and references, for example:
<meta charset="UTF-8">
This specifies the page’s encoding as UTF-8.
The title tag defines the page title, which will be displayed on the browser tab but not in the body. The body tag contains the actual content displayed on the page. The div tag defines a block in the page; its id is container, a very commonly used attribute, and the id’s value is unique in the page; we can access this block via it. Inside this block there is another div tag with class wrapper, which is another common attribute often used with CSS to set styles. Inside this block there is an h2 tag representing a second-level heading, and a p tag representing a paragraph. The corresponding content can be written directly inside these elements, and they also have their own class attributes.
Save the code, open the file in a browser, and you will see content like in the figure.

As you can see, the tab shows the text This is a Demo, which is defined in the head’s title. The page body is generated by the elements defined in the body, and you can see the secondary heading and the paragraph.
This example is the general structure of a webpage. A standard webpage is html with nested head and body; the head defines the page’s configuration and references, and the body defines the main content.
Node Tree and Relationships Between Nodes
In HTML, all content defined by tags is a node, forming an HTML DOM tree.
First, let’s understand what DOM is. The DOM is a standard by the W3C (World Wide Web Consortium). Its English full name is Document Object Model. It defines a standard for accessing HTML and XML documents:
The W3C Document Object Model (DOM) is a platform- and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of documents.
The W3C DOM standard is divided into three parts:
- Core DOM — the standard model for any structured document
- XML DOM — the standard model for XML documents
- HTML DOM — the standard model for HTML documents
According to the W3C HTML DOM standard, all content in an HTML document is nodes:
- The whole document is a document node
- Each HTML element is an element node
- The text inside HTML elements is a text node
- Each HTML attribute is an attribute node
- Comments are comment nodes
HTML DOM treats an HTML document as a tree structure, called a node tree.

Through the HTML DOM, all nodes in the tree can be accessed via JavaScript; all HTML node elements can be modified, created, or deleted.
Nodes in the tree have hierarchical relationships. We commonly use terms such as parent, child, and sibling to describe these relationships. A parent node has child nodes, and siblings are nodes at the same level.
At the top of the node tree is the root. Besides the root, every node has a parent and can have any number of child or sibling nodes.
Selectors
We know a webpage is made of individual nodes, and CSS selectors apply different style rules to different nodes. So how do we locate nodes?
In CSS, we use CSS selectors to locate nodes. For example, in the above example, the div node has id container, which can be expressed as #container; the # at the start represents an id selector, followed by the id name. If we want to select a node with class wrapper, we can use .wrapper; here the dot at the start denotes a class selector, followed by the class name. There’s also a way to select by tag name, e.g., to select second-level headings, simply use h2. These are the three most common selectors: by id, by class, and by tag name; remember their syntax.
Additionally, CSS selectors support nested selection: place spaces between selectors to indicate nesting, such as #container .wrapper p, which means first select the node with id container, then select its internal node with class wrapper, and finally select the p node inside it. If you omit spaces, it denotes a sibling relationship, e.g., div#container .wrapper p.text means first select the div with id container, then the internal node with class wrapper, then the p node with class text inside that. This is CSS selectors; their filtering capability remains very powerful.
In addition, CSS selectors have some other syntactic rules.
CSS Syntax
| Selector | Example | Description |
|---|---|---|
| .class | .intro | Select all nodes with class=“intro” |
| #id | #firstname | Select all nodes with id=“firstname” |
| * | * | Select all nodes |
| element | p | Select all p nodes |
| element,element | div,p | Select all div nodes and all p nodes |
| element element | div p | Select all p nodes inside div nodes |
| element>element | div>p | Select all p nodes whose parent is a div |
| element+element | div+p | Select all p nodes immediately following a div |
| [attribute] | [target] | Select all nodes with the target attribute |
| [attribute=value] | [target=blank] | Select all nodes with target=“blank” |
| [attribute~=value] | [title~=flower] | Select all nodes whose title attribute contains the word “flower” |
| a | Select all unvisited links | |
| a | Select all visited links | |
| a | Select active links | |
| a | Select links under the mouse cursor | |
| input | Select focused input nodes | |
| p | Select the first letter of every p | |
| p | Select the first line of every p | |
| p | Select all p that are the first child of their parent | |
| p | Insert content before each p’s content | |
| p | Insert content after each p’s content | |
| p | Select all p elements with lang attributes starting with “it” | |
| element1~element2 | p~ul | Select all ul elements preceded by a p |
| [attribute^=value] | a[src^=“https”] | Select all a elements whose src starts with “https” |
| [attribute$=value] | a[src$=“.pdf”] | Select all a elements whose src ends with “.pdf” |
| [attribute*=value] | a[src*=“abc”] | Select all a elements whose src contains the substring “abc” |
| p | Select all p elements that are the first of their type among siblings | |
| p | Select all p elements that are the last of their type among siblings | |
| p | Select all p elements that are the only one of their type among siblings | |
| p | Select all p elements that are the only child of their parent | |
| p | Select all p elements that are the nth child of their parent | |
| p | As above, counting from the last child | |
| p | Select all p elements that are the second p of their parent | |
| p | Same as above, counting from the last child | |
| p | Select all p elements that are the last child of their parent | |
| Select the root element of the document | ||
| p | Select all p elements with no children (including text) | |
| #news | Select the currently active target in the document | |
| input | Select all enabled input elements | |
| input | Select all disabled input elements | |
| input | Select all checked input elements | |
| Select all elements that do not match the selector | ||
| ::selection | ::selection | Select the portion of the document that has been highlighted by the user |
Crawling Basics
We can think of the Internet as a giant web, and crawlers (web crawlers) as spiders crawling the net. Treat each node as a webpage; the crawler visits a page to obtain its information. The connections between nodes can be thought of as links between pages; after visiting one node, the spider can follow the links to reach the next node and fetch subsequent pages. In this way, all the web’s nodes can be crawled, and a site’s data can be scraped.
Crawling Overview
In simple terms, a crawler is an automated program that fetches web pages and extracts and stores information. Here is a brief overview.
-
Fetch Web Pages
The crawler’s first task is to fetch the page, i.e., to obtain the page’s source code. The source code contains useful information, so once fetched, you can extract the desired data.
Previously we discussed the concepts of requests and responses: you send a request to the site’s server, and the response body is the page’s source code. Therefore, the key part is to construct a request and send it to the server, then receive and parse the response.
Python provides many libraries to help us implement this operation, such as urllib, requests, etc. We can use these libraries to implement HTTP requests; requests and responses are represented using data structures provided by the libraries. After obtaining the response, you only need to parse the Body part of the data structure to get the page’s source code, enabling you to automate the page-getting process.
-
Extract Information
After obtaining the page’s source code, the next step is to analyze the source code to extract the data we want. First, the most universal method is to use regular expressions; this is a universal approach, but constructing regular expressions can be complex and error-prone.
Additionally, because web page structures follow certain rules, there are libraries that extract web information based on node attributes, CSS selectors, or XPath, such as Beautiful Soup, pyquery, lxml, etc. Using these libraries, we can efficiently extract information from the page, such as node attributes and text values.
Extracting information is a very important part of crawling; it helps organize scattered data for subsequent handling and analysis.
-
Save Data
After extracting information, we typically save the data somewhere for later use. There are many formats, such as saving as TXT or JSON, or saving to databases like MySQL and MongoDB, or saving to remote servers via methods like SFTP.
-
Automation
When we mention automation, it means crawlers can perform these tasks on our behalf. Of course, we can manually extract the information, but when the scale is large or we want to obtain a lot of data quickly, automation is preferable. A crawler is an automated program that carries out the crawling, can handle various exceptions and retry on errors, and ensures the crawling runs continuously and efficiently.
What Data Can Be Retrieved
Web pages contain various kinds of information. The most common are standard web pages, which correspond to HTML code; the most commonly fetched data is the HTML source code.
Also, some pages return not HTML but a JSON string (many APIs use this form); this data format is convenient for transmission and parsing. It can be crawled as well, and data extraction can be easier.
Additionally, you may see various binary data, such as images, videos, and audio. With crawlers, you can fetch these binary data and save them with appropriate filenames.
You can also encounter files with various extensions, such as CSS, JavaScript, and configuration files; these are also common files that can be crawled as long as they are accessible in the browser.
All of the above correspond to their respective URLs, based on HTTP or HTTPS; as long as it is this type of data, crawlers can fetch it.
JavaScript Rendering Pages
Sometimes, when we use urllib or requests to fetch a page, the source code we obtain may differ from what is seen in the browser.
This is a very common problem. Today’s websites increasingly use Ajax and frontend modular tools, and the entire page may be rendered by JavaScript, meaning the original HTML code is just an empty shell, for example:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> </div> </body> <script src="app.js"></script></html>The body only contains a node with id container, but note that app.js is included after the body, and it is responsible for rendering the entire site.
When opening this page in a browser, the HTML content loads first, then the browser detects app.js, fetches it, and runs the JavaScript code, which modifies the HTML nodes by adding content, ultimately resulting in a complete page.
However, when requesting this page with urllib or requests, you only get the HTML code; it won’t load the JavaScript file, so you won’t see the browser-rendered content.
This explains why sometimes the source code you fetch differs from what you see in the browser.
Therefore, the HTML source obtained via basic HTTP request libraries may differ from the page as rendered by the browser. In such cases, you can analyze the backend Ajax interfaces or use libraries like Selenium or Splash to simulate JavaScript rendering.
Sessions and Cookies
While browsing pages, you often encounter the need to log in; some pages are only accessible after login, and after logging in you can access many pages in a row, but sometimes you need to re-login after a certain time. Some sites also automatically log you in when you open the browser, and the login may remain valid for a long time. This involves sessions and cookies.
Static vs Dynamic Web Pages
Before we begin, let’s understand static vs dynamic web pages. Here is the example from earlier:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>This is the most basic HTML code; save it as an .html file on a host with a fixed public IP, install a server like Apache or Nginx, so that others can access the page through the server—this is a simple website.
This kind of webpage is written in HTML; text, images, and other content are specified by HTML code. This type of page is static: it loads quickly, and is easy to write, but has significant drawbacks, such as poor maintainability and the inability to flexibly display content based on the URL. For example, if we want to pass a name parameter in the URL to display on the page, this is not feasible.
Therefore, dynamic pages emerged. They can parse changes in URL parameters, connect to a database, and dynamically render different content, offering great flexibility. Most sites we encounter today are dynamic; they are not just simple HTML, but may be written in languages like JSP, PHP, Python, etc., and are far more powerful and feature-rich than static pages.
Furthermore, dynamic sites can implement user login and registration. Recalling the initial question, many pages require login to view. In general, after entering a username and password to log in, you obtain something like a credential, and with it you can maintain a login state to access pages that require login.
Stateless HTTP
To understand sessions and cookies, we first need to understand a feature of HTTP called statelessness.
HTTP’s statelessness means the HTTP protocol does not retain memory of transactions; the server does not know the client’s state. When we send a request to the server, the server processes it and returns a response, and this process is completely independent; the server does not remember prior state changes. This means that if later you need to process earlier information, you must resend those requests, leading to repeated requests and extra overhead, which is wasteful—especially for pages requiring user login.
Two techniques to maintain HTTP connection state emerged: sessions (on the server) and cookies (on the client). With cookies, the browser automatically includes them in subsequent requests to the server; the server identifies the user via cookies, determines if the user is logged in, and returns the appropriate response.
We can understand that cookies store login credentials; with them, on subsequent requests you only need to send cookies, without re-entering username and password.
Thus in crawling, when you need to access pages that require login, you can directly reuse the cookies obtained after a successful login in the request headers, without re-simulating login.
-
Sessions
A session originally means a finite sequence of actions/messages. For example, a phone call—from picking up the phone to hanging up—constitutes a session.
In the Web, a session object stores the attributes and configuration information needed for a specific user session. This way, when a user navigates between web pages of an application, the variables stored in the session object persist for the entire user session. When a user requests a Web page from the application and there is no session yet, the web server will automatically create a session object. When the session expires or is abandoned, the server will terminate the session.
-
Cookies
Cookies refer to data stored on the user’s local device by websites to distinguish users and track sessions.
-
Session persistence
When the client first requests the server, the server returns a response with a Set-Cookie header to identify the user. The browser stores the Cookies. On subsequent requests to the site, the browser includes these Cookies in the request header; the server uses the Cookies to locate the corresponding session and determine the user’s status.
When you successfully log in to a site, the server tells the client which Cookies to set; on subsequent visits, the client sends the Cookies to the server, which then finds the corresponding session and verifies. If the variables in the session that indicate login status are valid, the user is considered logged in, and the server returns content that’s visible only after login; the browser can render it.
Conversely, if the Cookies sent to the server are invalid or the session has expired, you will not be able to continue accessing the page, and you may receive an error response or be redirected to the login page.
Therefore, Cookies and sessions must work together—the client side and the server side cooperate to implement login session control.
-
Attributes of Cookies
Now, let’s look at what Cookies contain. Taking Zhihu as an example, open the Application tab in the browser’s developer tools, then on the left there is a Storage section; the last item is Cookies. Open it, and these are Cookies.

You can see that there are many entries; each entry can be called a Cookie. It has the following attributes:
- Name, the name of the cookie. Once created, the name cannot be changed.
- Value, the value of the cookie. If the value contains Unicode characters, you need to encode them. If the value is binary data, you need to use BASE64 encoding.
- Max Age, the expiration time of the cookie in seconds; it is often used with Expires to calculate its validity. If Max-Age is positive, the cookie expires after Max-Age seconds. If negative, the cookie expires when the browser is closed, and the browser will not save this cookie in any form.
- Path, the path for which the cookie is valid. If set to /path/, the cookie is accessible only on pages with that path. If set to /, the cookie is accessible across all pages of the domain.
- Domain, the domain that can access the cookie. For example, if set to .zhihu.com, all domains ending with zhihu.com can access this cookie.
- Size, the size of the cookie.
- Http (HttpOnly), the cookie’s HttpOnly attribute. If true, the cookie is only included in HTTP requests and cannot be accessed via document.cookie.
- Secure, whether this cookie should only be transmitted over secure protocols (HTTPS, SSL, etc.). Defaults to false.
-
Session Cookies and Persistent Cookies
In simple terms, session cookies keep cookies in the browser’s memory; when the browser is closed, these cookies disappear. Persistent cookies are saved to the client’s hard drive and can be used next time to maintain login state.
In fact, strictly speaking, there is no hard division between session cookies and persistent cookies; it is determined by the cookie’s Max-Age or Expires field.
Therefore, some sites that require persistent login set the cookie’s expiration longer, so that visiting again carries the previous cookie and you remain logged in.
Common Misconceptions
When discussing session mechanisms, there is a common misconception—“as long as you close the browser, the session disappears.” Think of a membership card: unless the user actively cancels it with the store, the store won’t delete the user’s data. The same applies to sessions; unless the program tells the server to delete a session, the server keeps it.
But when you close the browser, the browser doesn’t actively inform the server that it will close, so the server has no opportunity to know. The illusion arises because most session mechanisms store the session ID in a session cookie, and after closing the browser the cookies disappear; upon reconnecting, you cannot locate the original session, so login state seems lost.
Moreover, since closing the browser does not delete the session, the server should set an expiration for the session; when the time since the last activity exceeds this expiration, the server can consider the client inactive and delete the session to save storage space.
Proxy Basics
During crawling, you may encounter a scenario where the crawler runs smoothly at first, fetches data normally, and then, within a short time, you see errors like 403 Forbidden. Opening the page, you may see a message such as “Your IP address is making requests too frequently.” This is due to anti-crawling measures. For example, a server may monitor the number of requests from a single IP in a given time; if it exceeds a threshold, it may deny service and return an error. This is IP blocking.
If the server is monitoring the number of requests from an IP per unit time, using a method to disguise your IP so the server cannot identify your machine could help prevent IP blocking.
One effective method is to use a proxy.
Basic Principle
A proxy, or proxy server, is a server that acts on behalf of network users to fetch information. In simple terms, it is an intermediary for network data.
When we normally request a website, we send the request to the Web server, and the server returns the response. If a proxy server is set, you effectively build a bridge between your machine and the server. Your machine does not directly request the Web server; instead, you send the request to the proxy server, which forwards the request to the Web server, and then forwards the Web server’s response back to your machine.
In this way, we can browse the web normally, but the real IP seen by the Web server is no longer your machine’s IP, achieving IP masking. This is the basic principle of a proxy.
Uses of Proxies
So, what are proxies used for? Here are some common uses.
- Break through IP-based access restrictions to reach sites that are normally inaccessible.
- Access internal resources of organizations or institutions, e.g., using free proxies within an educational network to access FTP downloads/uploads and other resources.
- Improve access speed: proxies often have large disk caches; when information passes through, it is cached; subsequent requests for the same information can be served from the cache, speeding up access.
- Hide real IP: users can hide their IP, protecting against attacks. For crawlers, using proxies hides the crawler’s own IP to prevent blocking.
Crawler Proxies
For crawlers, due to high fetch speeds, the same IP might be used too frequently, and sites may require CAPTCHA or block the IP, which is inconvenient.
Using proxies hides the real IP, making the server think the request comes from a proxy. By continuously changing proxies during crawling, you avoid blocking and can achieve better crawling performance.
Proxy Classification
Proxies can be categorized by protocol or by anonymity level. Here is a summary:
- By Protocol
- FTP proxy servers, mainly used to access FTP servers; typically support uploading, downloading, and caching; ports usually 21, 2121, etc.
- HTTP proxies, mainly used to access web pages; typically support content filtering and caching; ports 80, 8080, 3128, etc.
- SSL/TLS proxies, mainly used to access encrypted sites; generally provide SSL or TLS encryption (up to 128-bit); port 443.
- RTSP proxies, mainly for RealPlayer to access Real streaming servers; usually have caching; port 554.
- Telnet proxies, primarily for Telnet remote control (often used to hide identity in hacking); port 23.
- POP3/SMTP proxies, used for POP3/SMTP email; typically with caching; ports 110/25.
- SOCKS proxies, simply forward data packets without regard to protocol, so they are much faster; often include caching; port 1080. SOCKS has SOCKS4 and SOCKS5; SOCKS4 supports only TCP, while SOCKS5 supports TCP and UDP, and also supports various authentication mechanisms and server-side DNS resolution. In short, anything SOCKS4 can do, SOCKS5 can do as well; but SOCKS5 cannot necessarily do everything SOCKS4 can.
- By Anonymity Level
- Highly anonymous proxies (elite proxies) forward data without modification, appearing to the server as a standard client, with the proxy’s IP being recorded.
- Ordinary anonymous proxies modify the data in some way; the server may detect that it’s a proxy and there’s a chance of tracing back to the client’s real IP. Proxies often add HTTP_VIA and HTTP_X_FORWARDED_FOR headers.
- Transparent proxies not only modify the data but also reveal the client’s real IP to the server. These proxies offer little more than caching for speed and content-filtering for security; the most common example is a hardware firewall in internal networks.
- Spy proxies refer to proxies created to record the data transmitted by users, for research, monitoring, etc.
Common Proxy Settings
- Using free proxies from the Internet is best combined with high anonymity; fetch and filter usable proxies beforehand, or maintain a proxy pool.
- Use paid proxy services; there are many proxy providers online, and paid proxies typically offer higher quality than free proxies.
- ADSL dial-up: connect each time to obtain a new IP; high stability and a fairly effective solution.
HTTPの基本原理
URIとURL
ここでは URI と URL をまず理解します。URI の正式名称は Uniform Resource Identifier(統一資源識別子)、URL の正式名称は Universal Resource Locator(統一資源定位子)です。
例えば、[https://github.com/favicon.ico、それ自体が] URLでもあり URI でもあります。つまりこのようなアイコン資源があり、私たちは URL/URI を用いてそのアクセス方法を一意に指定します。これには https のアクセスプロトコル、アクセスパス(根ディレクトリ)およびリソース名 favicon.ico が含まれます。こうしたリンクを通じて、私たちはインターネット上からこの資源を見つけることができます。これが URL/URI です。
URL は URI のサブセットです。つまりすべての URL は URI ですが、すべての URI が URL であるとは限りません。では、どのような URI が URL でないのでしょうか。URI には URN(Uniform Resource Name、統一資源名)というサブクラスも含まれます。URN は資源を命名するだけで、資源の定位方法を指定しません。例えば urn:isbn:0451450523 は本の ISBN を指定し、その本を一意に識別しますが、どこでその本を位置づけるかは指定されていません。これが URN です。

しかし現在のインターネットでは URN の使用は非常に少なく、ほぼすべての URI は URL です。したがって一般的なウェブリンクは URL と呼ぶことも URI と呼ぶこともできます。私は個人的には URL と呼ぶ習慣です。
超テキスト
続いて、概念の一つである超テキストを理解します。その英語名は hypertext。ブラウザで見えるウェブページは超テキストとして解析されたもので、ウェブページのソースコードは一連の HTML コードであり、そこには img タグ(画像)、p タグ(段落表示)などのタグが含まれます。ブラウザがこれらのタグを解析した後、私たちが普段見るウェブページが形成され、ウェブページのソース HTML は超テキストと呼べます。
例えば、Chrome ブラウザで任意のページを開き、任意の場所を右クリックして「検証」項目を選択(もしくは F12 キーを直接押す)と、ブラウザの開発者ツールを開くことができます。ここで Elements タブには現在のウェブページのソースコードが表示され、これらはすべて超テキストです。
HTTPとHTTPS
淘宝のトップページには https://www.taobao.com/中、URL の先頭に http または https がつくことがあります。これは資源へアクセスするためのプロトコルの種類で、時には ftp、sftp、smb で始まる URL も見られます。ここでの ftp、sftp、smb はすべてプロトコルの種類を指します。スクレイピングでは、取得するページは通常 http または https のプロトコルを用いるので、ここでこの二つのプロトコルの意味を説明します。
HTTP の正式名称は Hyper Text Transfer Protocol(超テキスト転送プロトコル)で、ウェブ上の超テキストデータをローカルのブラウザへ転送するための伝送プロトコルです。高速かつ正確に超文書を伝送できることを保証します。HTTP は World Wide Web Consortium(W3C)と Internet Engineering Task Force(IETF)によって共同で制定された規格で、現在広く使われているのは HTTP/1.1 版です。
HTTPS の正式名称は Hyper Text Transfer Protocol over Secure Socket Layer で、安全性を目的とした HTTP のチャンネルです。要するに HTTP のセキュア版で、HTTP に SSL レイヤーを追加したものを HTTPS と呼びます。
HTTPS のセキュリティの基礎は SSL です。従って HTTPS を通じて伝送される内容はすべて SSL で暗号化されます。主な役割は二つです。
- 情報セキュアなチャネルを構築し、データ転送の安全を保証する。
- サイトの信頼性を確認する。HTTPS を使用するサイトは、ブラウザのアドレスバーの錠マークをクリックしてウェブサイトの認証情報を確認でき、CA 機関が発行したセキュリティ署名を参照して調べることもできます。
ただし、HTTPS を使用しているサイトでもブラウザに「安全でない」と表示されることがあります。
HTTPリクエストの過程
ブラウザに URL を入力してエンターを押すと、ブラウザ上でページの内容を観察できます。実際にはこの過程は、ブラウザがサイトのサーバへリクエストを送信し、サーバがそのリクエストを処理してレスポンスを返し、それをブラウザが受け取り、レスポンスにはページのソースコードなどが含まれ、それをブラウザが解析してウェブページを表示します。

このときクライアントは私たち自身の PC やスマホのブラウザを指し、サーバはアクセスしようとするウェブサイトが置かれているサーバです。
Chrome ブラウザを開き、右クリックして「検証」を選択するとブラウザの開発者ツールを開くことができます。ここで百度にアクセスして http://www.baidu.com/ を開き、URL を入力してエンターを押すと、ネットワークのリクエストがどう発生したかを観察できます。Network ページの下部にはエントリが現れ、そのうちのひとつがリクエストの送信とレスポンスの受信の過程を表します。

まず最初のネットワークリクエストを観察します。すなわち http://www.baidu.com/ です。各列の意味は以下のとおりです。
- Name:リクエストの名称。通常は URL の最後の部分を名称として用います。
- Status:レスポンスのステータスコード。ここは 200 と表示され、レスポンスが正常であることを意味します。ステータスコードでリクエスト後に正しいレスポンスを得られたかを判断します。
- Type:リクエストされた文書のタイプ。ここでは document で、今回のリクエストは HTML 文書で、内容は HTML コードです。
- Initiator:リクエストの発火元。どのオブジェクトやプロセスがリクエストを発したかを示します。
- Size:サーバからダウンロードしたファイルとリクエスト資源のサイズ。キャッシュから取得した場合は from cache と表示されます。
- Time:リクエストの開始からレスポンスを得るまでの総時間。
- Waterfall:ネットワークリクエストの可視化された瀑布状表示。
このエントリをクリックすると、より詳細な情報が表示されます。
まず General 部分、Request URL はリクエストの URL、Request Method はリクエストの方法、Status Code はレスポンスの状態コード、Remote Address はリモートサーバのアドレスとポート、Referrer Policy は Referrer の判定ポリシーです。さらに下に進むと、Response Headers と Request Headers があり、これはそれぞれレスポンスヘッダーとリクエストヘッダーを表します。リクエストヘッダーには多くのリクエスト情報が含まれ、例としてブラウザの識別子、Cookies、Host などの情報があります。これはリクエストの一部で、サーバはリクエストヘッダー内の情報に基づいてリクエストが正当かどうかを判断し、それに応じたレスポンスを返します。図に見える Response Headers はレスポンスの一部で、サーバの種類、文書タイプ、日付などの情報を含み、ブラウザはレスポンスを受け取るとレスポンス内容を解析し、ウェブページを表示します。
リクエスト
リクエストは、クライアントからサーバへ送信され、4 つの部分に分かれます:リクエストメソッド(Request Method)、リクエストURL(Request URL)、リクエストヘッダー(Request Headers)、リクエストボディ(Request Body)。
-
リクエストメソッド
よく使われるリクエストメソッドは 2 つ、GET と POST です。
ブラウザで URL を直接入力してエンターを押すと、GET リクエストが発行され、リクエストのパラメータは URL に直接含まれます。例えば、百度で Python を検索する場合、リンクは https://www.baidu.com/s?wd=Python となり、URL に検索キーワード wd の情報が含まれます。POST リクエストは多くがフォームの送信時に発行されます。例えば、ログインフォームでユーザー名とパスワードを入力して「ログイン」ボタンをクリックすると、通常は POST リクエストが発行され、そのデータはフォームの形式で送信され、URL には現れません。
GET と POST の違いは以下のとおりです。
- GET のパラメータは URL に含まれ、URL からデータが見えます。一方、POST の場合は URL にデータは含まれず、データはフォーム形式で送信され、リクエストボディに含まれます。
- GET で送信できるデータ量は最大で 1024 バイトですが、POST には制限がありません。
一般的に、ログイン時にはユーザー名とパスワードを送信します。機密情報を含むためGET でのリクエストはURL にパスワードが露出してしまい、パスワードの漏洩を招くため、POST で送信するのが望ましいです。ファイルのアップロード時にはファイル内容が大きいため、POST を選択します。
私たちが日常的に遭遇するほとんどのリクエストは GET または POST です。ほかにも GET、HEAD、POST、PUT、DELETE、OPTIONS、CONNECT、TRACE などのリクエストメソッドがあります。
メソッド 説明 GET 指定されたページ情報を要求し、エンティティ本文を返します。 HEAD GET に似ていますが、レスポンスには具体的な内容が含まれず、ヘッダを得るのに用います。 POST 指定リソースへデータを提出して処理を要求します(例:フォーム送信やファイルのアップロード)。データはリクエストボディに含まれます。POST は新しいリソースの作成や既存リソースの変更を引き起こすことがあります。 PUT クライアントからサーバへ送信したデータで指定の文書の内容を置換します。 DELETE 指定されたページをサーバが削除するよう要求します。 CONNECT HTTP/1.1 で、接続をパイプライン化できるプロキシサーバのために予約されています。 OPTIONS クライアントがサーバの機能を確認します。 TRACE サーバが受信したリクエストをエコーします。主にテスト・診断用です。 PATCH PUT の補足で、既知のリソースの部分更新を行います。 -
リクエストURL
リクエストURL、すなわち統一リソース定位子 URL は、リクエストしたい資源を一意に特定します。
-
リクエストヘッダー
リクエストヘッダーは、サーバに対して追加情報を伝えるためのものです。特に重要な情報として Cookie、Referer、User-Agent などがあります。以下によく使われるヘッダーを簡単に説明します。
- Accept:リクエストヘッダ領域で、クライアントが受け入れる情報のタイプを指定します。
- Accept-Language:クライアントが受け入れる言語の種類を指定します。
- Accept-Encoding:クライアントが受け入れる内容のエンコードを指定します。
- Host:リクエスト資源のホスト IP とポート番号を指定します。その内容はリクエストURLの原本サーバーもしくはゲートウェイの位置です。HTTP/1.1 以降、リクエストには必須です。
- Cookie:Cookies の複数形として使われることもあり、サイトがユーザーを識別してセッションを追跡するために端末に保存するデータです。主な機能は現在のアクセスセッションを維持することです。例えば、あるサイトにログイン後、サーバはセッションでログイン状態を保存します。以降、ページを更新したり別ページを要求してもログイン状態が維持され、表示されるページはログイン後の内容になります。Cookies には、サーバのセッションを識別する情報が含まれており、ブラウザがそのサイトのページをリクエストするたびに Cookies をリクエストヘッダーに追加してサーバに送信します。サーバは Cookies で自分自身を識別し、現在の状態がログイン状態であることを確認し、ログイン後のみ閲覧できるページを返します。
- Referer:このリクエストがどのページから送信されたかを識別する情報で、サーバはこれを取得して対応します。例えば参照元の統計や防盗リンク対策など。
- User-Agent:略称 UA。サーバがクライアントのOSとバージョン、ブラウザとバージョンなどを認識します。スクレイピング時にこれを設定するとブラウザを偽装できます。設定しないとクローラーと識別される可能性があります。
- Content-Type:インターネットメディアタイプ(MIME type)とも呼ばれ、HTTP ヘッダ内でリクエスト内のメディアタイプ情報を表します。例えば text/html は HTML、image/gif は GIF、application/json は JSON など。対応表はこの対照表を参照してください:[http://tool.oschina.net/commons。]
したがって、リクエストヘッダーはリクエストの重要な構成要素です。クローリングを行う際には大半の場合、リクエストヘッダーを設定する必要があります。
-
リクエストボディ
リクエストボディには一般に POST リクエストのフォームデータが含まれ、GET リクエストの場合は空になります。
ログイン前にユーザー名とパスワードを入力して送信すると、これらはフォームデータとしてサーバへ送信されます。このとき、Request Headers の Content-Type を application/x-www-form-urlencoded に設定しておく必要があります。Content-Type を application/x-www-form-urlencoded に設定すると、フォームデータとして送信されます。あるいは Content-Type を application/json に設定して JSON データを送信したり、multipart/form-data に設定してファイルをアップロードすることもできます。
Content-Type 提出データの方式 application/x-www-form-urlencoded フォームデータ multipart/form-data フォームファイルのアップロード application/json JSON データのシリアライズ text/xml XML データ クローラーで POST リクエストを作成する場合、正しい Content-Type を使用し、各種ライブラリのパラメータ設定でどの Content-Type が使用されているかを理解する必要があります。そうでないと POST 提出後に正しく応答されない可能性があります。
レスポンス
レスポンスはサーバからクライアントへ返され、3つの部分に分かれます。レスポンスステータスコード(Response Status Code)、レスポンスヘッダー(Response Headers)、レスポンスボディ(Response Body)。
-
レスポンスステータスコード
レスポンスステータスコードはサーバの応答状態を表します。例として 200 はサーバが正常に応答、404 はページが見つからない、500 はサーバ内部エラーを意味します。スクレイピングではステータスコードに基づいてサーバの応答状態を判断します。例えば 200 ならデータの取得に成功したとみなし、次の処理へ進みます。そうでなければ無視します。
よくあるエラーコード
| ステータスコード | 説明 | 詳細 |
|---|---|---|
| 100 | 続行 | クライアントはリクエストを継続して送るべき。サーバはリクエストの一部を受信し、残りを待機。 |
| 101 | プロトコルの切替 | クライアントがサーバにプロトコル切替を要求し、サーバがそれを確認して切替準備完了。 |
| 200 | 成功 | サーバがリクエストを正常に処理しました。 |
| 201 | 作成済み | リクエストは成功し、サーバが新しいリソースを作成。 |
| 202 | 受理 | サーバはリクエストを受理したが、まだ処理中。 |
| 203 | 非認証情報 | サーバはリクエストを処理したが、返される情報は別のソースから。 |
| 204 | 内容なし | サーバはリクエストを処理したが、返す内容はなし。 |
| 205 | 内容をリセット | サーバはリクエストを処理し、内容をリセット。 |
| 206 | 部分的内容 | サーバはリクエストの一部を処理。 |
| 300 | 複数の選択肢 | 要求に対してサーバは複数の操作を実行可能。 |
| 301 | 永久移動 | 要求されたページは新しい場所へ永久に移動。 |
| 302 | 一時移動 | ページは一時的に別ページへ転送。 |
| 303 | 他の場所を参照 | 元のリクエストが POST の場合、リダイレクト先は GET で取得されるべき。 |
| 304 | 未変更 | 今回のリクエストで返されたページは変更されず、前回の資源を使用。 |
| 305 | プロキシ使用 | クライアントはこのページへプロキシを使用してアクセスするべき。 |
| 307 | 一時リダイレクト | 資源は一時的に別の場所から応答。 |
| 400 | 不正なリクエスト | サーバはこのリクエストを解析できません。 |
| 401 | 未認証 | リクエストは認証されていない、または認証に失敗。 |
| 403 | アクセス禁止 | サーバがこのリクエストを拒否。 |
| 404 | 見つからない | サーバが要求されたページを見つけられません。 |
| 405 | メソッド禁止 | サーバがリクエスト中の指定メソッドを許可していません。 |
| 406 | 受理不能 | 要求内容でページを応答できません。 |
| 407 | プロキシ認証が必要 | クライアントはプロキシ認証を使用する必要があります。 |
| 408 | リクエストタイムアウト | サーバのリクエスト処理がタイムアウト。 |
| 409 | 競合 | サーバはリクエストの完了時に競合を検出。 |
| 410 | すでに削除 | 要求された资源は永久に削除。 |
| 411 | 有効長が必要 | 有効な Content-Length ヘッダを欠くリクエストは受け付けません。 |
| 412 | 前提条件失敗 | サーバはリクエストの前提条件の一部を満たしていません。 |
| 413 | リクエストエンティティが大きすぎる | リクエストのエンティティが大きすぎて処理不能。 |
| 414 | リクエスト URI が長すぎる | リクエストURLが長すぎて処理不能。 |
| 415 | サポートされていないメディアタイプ | リクエスト形式が閲覧ページでサポートされていません。 |
| 416 | リクエスト範囲不適合 | 要求範囲を提供できません。 |
| 417 | 期待値失敗 | サーバが期待するリクエストヘッダを満たしていません。 |
| 500 | サーバ内部エラー | サーバがエラーに遭遇し、リクエストを完了できません。 |
| 501 | 実装されていない | サーバはリクエストを完了する機能を持ちません。 |
| 502 | バッドゲートウェイ | 上流サーバから無効な応答を受け、ゲートウェイとして動作します。 |
| 503 | サービス利用不可 | サーバは現在利用できません。 |
| 504 | ゲートウェイタイムアウト | 上流サーバからの応答を timely に受け取れませんでした。 |
| 505 | HTTP バージョン不支援 | サーバはリクエストで使用された HTTP バージョンをサポートしていません。 |
-
レスポンスヘッダー
レスポンスヘッダーには、サーバがリクエストに対して返す情報が含まれます。例えば Content-Type、Server、Set-Cookie など。よく使われるヘッダーを簡単に説明します。
- Date:レスポンスが生成された時刻。
- Last-Modified:資源の最終更新時刻。
- Content-Encoding:レスポンス内容のエンコード。
- Server:サーバの情報(名称、バージョンなど)。
- Content-Type:文書タイプ。返されるデータの種類を指定。例: text/html は HTML、application/x-javascript は JavaScript、image/jpeg は画像。
- Set-Cookie:Cookies の設定。レスポンスヘッダーの Set-Cookie はブラウザにこの内容を Cookies に格納させ、次回のリクエストで Cookies を送信させます。
- Expires:レスポンスの有効期限。キャッシュの更新に利用され、再訪問時にキャッシュから読み込みサーバ負荷を軽減します。
-
レスポンスボディ
最も重要なのはレスポンスボディの内容です。レスポンス本文はレスポンスボディに含まれ、例えばウェブページを要求した場合のレスポンスボディはページの HTML コード、画像を要求した場合は画像のバイナリデータなどです。スクレイピングでウェブページを要求した後、解析すべき内容はレスポンスボディです。
ブラウザの開発者ツールの Preview をクリックするとページのソースコード、すなわちレスポンスボディの内容を見られ、解析対象となります。スクレイピングでは、レスポンスボディからウェブページのソースコードや JSON データなどを取得し、そこから目的の内容を抽出します。
ウェブページの基礎
ウェブページの構成
ウェブページは大きく 3 つの部分に分けられます。HTML、CSS、JavaScript。ウェブページを人に例えるなら、HTML は骨格、JavaScript は筋肉、CSS は皮膚です。3つが組み合わさって初めて、完成されたウェブページになります。
-
HTML
HTML はウェブページを記述する言語で、その正式名称は Hyper Text Markup Language(超テキストマークアップ言語)です。ウェブページには文章、ボタン、画像、動画などの複雑な要素が含まれ、基本構造は HTML。異なるタイプの要素は、画像は img、動画は video、段落は p などのタグで表現されます。これらは div などのレイアウトタグでネスト・組み合わせることで、ウェブページの枠組みを形成します。
Chrome で百度を開き、右クリックして「検証」を選択(または F12)して開発者モードを開くと、Elements タブでウェブページのソースコードが表示されます。
これが HTML です。ウェブページ全体はさまざまなタグのネストで構成され、これらのタグが定義するノードは互いにネスト・組み合わせて複雑な階層関係を作り、ウェブページの構造を形成します。
-
CSS
HTML はウェブページの構造を定義しますが、単に HTML のレイアウトだけでは美しくありません。CSS を用いてスタイルを整えます。
CSS の正式名称は Cascading Style Sheets(カスケーディング・スタイル・シート)です。「層叠」は、HTML に複数のスタイルシートを参照し、スタイルが衝突した場合にブラウザが層叠順序に従って処理できることを指します。「スタイル」はウェブページの文字サイズ、色、要素間の間隔、配置などのフォーマットを指します。
CSS は現在、ウェブページのレイアウト・スタイリングの標準となる唯一の規格です。
#head_wrapper.s-ps-islite .s-p-top {position: absolute;bottom: 40px;width: 100%;height: 181px;}これは CSS のスタイルです。中括弧の前には CSS セレクターが来ます。セレクターの意味は、まず id が head_wrapper かつ class が s-ps-islite のノードを選択し、その内部の class が s-p-top のノードをさらに選択します。中括弧内には一つずつのスタイル規則が書かれており、例えば position はこの要素のレイアウトを絶対配置に、bottom は要素の下端の余白を 40 ピクセル、width は幅を 100%、parent 要素を満たすように指定します。つまり、位置・幅・高などのスタイル設定をこのような形で一括して書き、先頭に CSS セレクターを付けることで、CSS セレクターで選択した要素にこのスタイルが適用され、要素はこのスタイルに従って表示されます。 ウェブページでは、通常はウェブ全体のスタイル規則を統一して CSS ファイル(拡張子は .css)に書き込みます。HTML では link タグを用いて作成済みの CSS ファイルを読み込むだけで、ページ全体が美しく洗練されたものになります。
-
JavaScript
JavaScript(略称 JS)はスクリプト言語です。HTML と CSS を組み合わせて使うことで、ユーザーに提供される情報は静的なものになり、インタラクションが欠如します。ウェブページにはダウンロードの進捗バー、ダイアログ、カルーセルなどのインタラクションやアニメーションが見られますが、これは通常 JavaScript の貢献です。JavaScript の登場により、ユーザーと情報の関係は単なる閲覧・表示の関係ではなく、リアルタイムで動的・インタラクティブなページ機能を実現しました。
JavaScript は通常、js 拡張子の単独ファイルとして読み込まれ、HTML の中で script タグを通じて導入します。
<script src="jquery-2.1.0.js"></script>総括すると、HTML はウェブページの内容と構造を、CSS はページのレイアウトを、JavaScript はページの動作を定義します。
ウェブページの構造
まず例を使って HTML の基本構造を体感します。名前は任意で、拡張子は.html のテキストファイルを作成し、次の内容とします。
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>これは最も基本的な HTML の例です。先頭の DOCTYPE は文書型を定義し、最も外側は html タグ、最後に対応する終了タグで閉じられ、内部には head タグと body タグがあり、それぞれウェブページのヘッダーと本文を表します。head タグ内にはページの設定や参照が定義されます。
<meta charset="UTF-8"> はウェブページのエンコーディングを UTF-8 に指定します。
title タグはウェブページのタイトルを定義し、タブに表示されますが本文には表示されません。body 内にはウェブページの本文として表示される要素が含まれ、div タグはページ内の区分を表します。その id は container で、これはウェブページ内で一意です。さらにこの区分の中には div タグがあり、class は wrapper です。これも CSS と組み合わせてスタイルを設定する際に頻繁に使われる属性です。次に内部には h2 タグがあり、これは見出しの二級分を表します。さらに p タグは段落を表します。これらの内容をそのまま書くと、ウェブページに表示されます。それぞれに class 属性も付いています。
コードを保存してブラウザで開くと、図のような内容が表示されます。

タブには This is a Demo の文字が表示され、これは head の title で定義した文字列です。ウェブページ本文は body タグ内の各要素によって生成され、ここでは二級見出しと段落が表示されます。この例はウェブページの一般的な構造です。ウェブページの標準形は html タグが内包する head と body で、head 内にウェブページの設定・参照を、body 内に本文を定義します。
ノードツリーとノード間の関係
HTML では、すべてのタグが定義する内容はノードで、これらは HTML DOM ツリーを構成します。
まず DOM とは何かを見てみましょう。DOM は W3C の標準で、英文正式名称は Document Object Model、すなわち「文書オブジェクトモデル」です。これにより、HTML および XML 文書へのアクセス標準を定義します。
W3C の文書オブジェクトモデル(DOM)は、プラットフォームや言語に依存しないインターフェースで、プログラムやスクリプトが文書の内容、構造、スタイルを動的にアクセス・更新できることを可能にします。
W3C DOM の標準は 3 つの部分に分かれています。
- Core DOM - どのような構造化文書にも対応する標準モデル
- XML DOM - XML 文書の標準モデル
- HTML DOM - HTML 文書の標準モデル
W3C の HTML DOM 標準によれば、HTML 文書のすべての内容はノードです:
- 文書全体は文書ノード
- 各 HTML 要素は要素ノード
- HTML 要素内のテキストはテキストノード
- 各 HTML 属性は属性ノード
- コメントはコメントノード
HTML DOM は HTML 文書を木構造として扱います。これがノードツリーと呼ばれる所以です。

HTML DOM を通じて、ツリー内のすべてのノードは JavaScript からアクセスでき、すべての HTML ノード要素は変更・作成・削除が可能です。
ノードツリーのノードは階層関係を持ちます。私たちは parent、child、sibling などの用語を使ってこれらの関係を説明します。親ノードは子ノードを持ち、同レベルの子ノードは兄弟ノードと呼ばれます。
ツリーの最上位ノードはルート(root)と呼ばれます。根ノード以外の各ノードは親ノードを持ち、任意の数の子ノードまたは兄弟ノードを持つことができます。
セレクター
ウェブページはノードの集合であり、CSS セレクターはノードごとに異なるスタイル規則を設定します。ではノードをどうやって特定するのでしょうか?
CSS ではセレクターを用いてノードを特定します。例えば、上の例の div ノードの id が container なら、#container と表現します。# で始まるのは id を選択することを意味します。その後には id の名前が続きます。また、class が wrapper のノードを選択したい場合は .wrapper を使用します。ここでは先頭のドット . は class を選択することを示します。さらに、タグ名で選択する方法もあり、例えば二級見出しを選択したい場合は h2 をそのまま使います。これが最もよく使われる 3 種の表現方法で、id、class、タグ名で選択します。覚えておいてください。
また、CSS セレクターはネストして選択することも支持します。各セレクターの間にスペースを入れるとネスト関係を表します。例えば #container .wrapper p は、まず id が container のノードを選択し、その内部の class が wrapper のノードを選択し、さらにその内部の p ノードを選択します。逆に、スペースを入れなければ並列関係を表します。 div#container .wrapper p.text は、まず id が container の div ノードを選択し、その内部の class が wrapper のノードを選択し、さらに内部の class が text の p ノードを選択します。これが CSS セレクターです。その機能は非常に強力です。
さらに、CSS セレクターには他にもさまざまな文法規則があります。
CSS文法
| セレクター | 例 子 | 説明 |
|---|---|---|
| .class | .intro | class=“intro” のすべてのノードを選択 |
| #id | #firstname | id=“firstname” のすべてのノードを選択 |
| * | * | すべてのノード |
| element | p | すべての p ノード |
| element,element | div,p | すべての div ノードとすべての p ノード |
| element element | div p | div ノード内部のすべての p ノード |
| element>element | div>p | 親ノードが div のすべての p ノード |
| element+element | div+p | div ノードの直後にあるすべての p ノード |
| [attribute] | [target] | target 属性を持つすべてのノード |
| [attribute=value] | [target=blank] | target=“blank” のすべてのノード |
| [attribute~=value] | [title~=flower] | title 属性に flower という単語を含むすべてのノード |
| a | 未訪問のリンクを選択 | |
| a | 訪問済みのリンクを選択 | |
| a | アクティブなリンク | |
| a | 自マウスカーソルが上にあるリンクを選択 | |
| input | フォーカスを得ている input ノードを選択 | |
| p | 各 p ノードの先頭文字を選択 | |
| p | 各 p ノードの先頭行を選択 | |
| p | 親ノードの最初の子ノードを持つすべての p ノード | |
| p | 各 p ノードの内容の前に内容を挿入 | |
| p | 各 p ノードの内容の後に内容を挿入 | |
| p | lang 属性値が it で始まるすべての p ノードを選択 | |
| element1~element2 | p~ul | 前に p ノードを持つすべての ul ノードを選択 |
| [attribute^=value] | a[src^=“https”] | src 属性値が https で始まるすべての a ノードを選択 |
| [attribute$=value] | a[src$=“.pdf”] | src 属性値が .pdf で終わるすべての a ノードを選択 |
| [attribute*=value] | a[src*=“abc”] | src 属性値に abc を含むすべての a ノードを選択 |
| p | 親ノードの最初の p ノードを全て選択 | |
| p | 親ノードの最後の p ノードを全て選択 | |
| p | 親ノードの中で唯一の p ノードを全て選択 | |
| p | 親ノードの唯一の子ノードである p ノードを全て選択 | |
| p | 親ノードの第2子ノードに属するすべての p ノード | |
| p | 同様、最後の子ノードから数えます | |
| p | 親ノードの2番目の p ノードに属するすべての p ノード | |
| p | 同様、最後の子ノードから数えます | |
| p | 親ノードの最後の子ノードであるすべての p ノード | |
| ドキュメントの根ノード | ||
| p | 子ノードを持たないすべての p ノード(テキストノードを含む) | |
| #news | 現在アクティブな #news ノード | |
| input | 有効化されているすべての input ノード | |
| input | 無効化されているすべての input ノード | |
| input | チェックされているすべての input ノード | |
| p ノード以外のすべてのノード | ||
| ::selection | ::selection | ユーザーが選択したノードの一部 |
クローラーの基本原理
私たちはインターネットを大きな網と見なすことができます。クローラー(ネットワーク・クローラー)はその網を這い回るクモのようなものです。網のノードを個々のウェブページと見なし、クローラーがそのページに到達すると、それを訪問して情報を取得します。ノード間のリンクをウェブページ同士の結びつきとみなし、あるノードを経由して次のノードへと進み、別のページを取得していくことができるようにします。こうして網全体のノードをクローラーがすべて巡回することで、サイトのデータを取得できるようになります。
クローラーの概要
要約すると、クローラーはウェブページを取得し、情報を抽出・保存する自動化プログラムです。以下に概要を説明します。
-
ウェブページの取得
クローラーが最初に行うべき作業はウェブページを取得することです。ここではウェブページのソースコードを取得します。ソースコードにはウェブページの有用な情報が含まれており、それを取得すれば、欲しい情報を抽出できます。
先に説明したように、リクエストとレスポンスの概念を用いて、サイトのサーバへリクエストを送信し、レスポンスボディとしてウェブページのソースコードを取得します。したがって、最も重要な部分はリクエストを構築してサーバへ送信し、レスポンスを受け取り、それを解析することです。
Python にはこの操作を実現する多くのライブラリがあり、urllib、requests などが代表例です。これらのライブラリを用いて HTTP リクエストを実行します。リクエストとレスポンスはライブラリが提供するデータ構造で表現でき、レスポンスを得た後は Body 部分を解析するだけで、ウェブページのソースコードを取得できます。こうして私たちはプログラムを用いてウェブページの取得プロセスを実現します。
-
情報の抽出
ウェブページのソースコードを取得したら、次はそれを分析して欲しいデータを抽出します。まず、最も一般的な方法は正規表現を用いることですが、正規表現の作成は複雑でミスが起きやすい万能な方法です。
さらに、ウェブページの構造には一定の規則があるため、ウェブページのノード属性、CSS セレクター、または XPath に基づいて情報を抽出するライブラリも存在します。たとえば Beautiful Soup、pyquery、lxml など。これらのライブラリを使うと、ノードの属性やテキスト値など、ウェブページ情報を効率よく抽出できます。
情報の抽出はクローラーにとって非常に重要な部分で、雑然としたデータを整理して後の処理・分析を容易にします。
-
データの保存
抽出した情報を、後で利用するためにどこかへ保存します。保存形式は TXT や JSON などのテキスト形式、データベース(MySQL、MongoDB など)へ保存、さらには遠隔サーバへ保存することも可能です(SFTP などを利用)。
-
自動化プログラム
自動化プログラムとは、クローラーが人間に代わってこれらの作業を実行できるという意味です。手作業で情報を抽出することも可能ですが、規模が大きい場合や大量のデータを素早く取得したい場合にはプログラムの助けが必要です。クローラーはこの収集作業を自動化するプログラムで、収集中にさまざまな例外処理や再試行を行い、収集を継続的かつ高効率で動作させます。
どのようなデータを取得できるか
ウェブページにはさまざまな情報が表示されます。最も一般的なのは通常のウェブページで、HTML コードに対応します。最も頻繁に取得されるのは HTML のソースコードです。
また、場合によってはウェブページが HTML コードを返さず、JSON 文字列を返すことがあります(API の多くがこの形式を採用します)。この形式のデータは転送と解析が容易で、取得可能です。
さらに、画像・動画・音声などのさまざまなバイナリデータも見ることができます。クローラーを用いてこれらのバイナリデータを取得し、対応するファイル名で保存します。
また、CSS、JavaScript、設定ファイルなど拡張子の異なるファイルも見られます。これらも最も一般的なファイルで、ブラウザでアクセスできれば取得できます。
これらはすべて各自の URL に対応しており、HTTP または HTTPS プロトコルに基づくデータです。こうしたデータはクローラーで取得可能です。
JavaScript でページをレンダリングする
場合によっては、urllib や requests を使ってウェブページを取得する際、得られるソースコードがブラウザで見えるものと実際には異なることがあります。
これは非常に一般的な問題です。現在のウェブページは Ajax やフロントエンドのモジュール化ツールを用いて構築されることが増え、ページ全体が JavaScript でレンダリングされる場合があり、元の HTML コードは空の shell のようなものです。例えば:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> </div> </body> <script src="app.js"></script></html>body の中には id が container のノードだけがあります。しかし body の後に app.js が読み込まれており、それがサイト全体のレンダリングを担当します。
このページをブラウザで開くと、最初にこの HTML が読み込まれ、次に app.js が読み込まれ、それに含まれる JavaScript が実行され、HTML のノードを変更して内容を追加し、最終的に完全なページを得られます。
しかし、urllib や requests などの基本的な HTTP リクエストライブラリを使って現在のページを取得すると、得られるのはこの HTML コードだけで、JavaScript ファイルの読み込みを継続する手助けにはなりません。そのため、ブラウザで見える内容を得ることはできません。
このことは、取得したソースコードがブラウザのページソースと異なる理由の一つです。
したがって、基本的な HTTP リクエストライブラリを使って得られるソースコードは、ブラウザのページソースと必ずしも同じではありません。このような場合、バックエンドの Ajax API を分析するか、Selenium、Splash のようなライブラリを用いて JavaScript のレンダリングを模倣することができます。
セッションとCookies
ウェブを閲覧しているとき、しばしばログインが必要な場面に遭遇します。いくつかのページはログイン後にのみ閲覧可能で、ログイン後はサイトを連続して何度も閲覧できます。しかし、しばらくすると再度ログインが必要になることがあります。また、ブラウザを開いた時点で自動的にログインしており、長時間有効な場合もあります。これらはセッション(Session)と Cookies の知識に関わります。
静的ウェブページと動的ウェブページ
まず、静的ウェブページと動的ウェブページの概念を理解しておく必要があります。以下は前の例のコードです。
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>This is a Demo</title> </head> <body> <div id="container"> <div class="wrapper"> <h2 class="title">Hello World</h2> <p class="text">Hello, this is a paragraph.</p> </div> </div> </body></html>これは最も基本的な HTML コードです。これを .html ファイルとして保存し、固定のグローバル IP を持つホストに置き、Apache や Nginx などのサーバをインストールします。こうしてこのホストがサーバとして機能し、他の人がそのサーバへアクセスしてこのページを閲覧できるようになります。これが最も簡単なウェブサイトの構築です。
この種のウェブページの内容は HTML コードで作成され、文字・画像などの内容は HTML コードで指定します。このようなページは静的ウェブページと呼ばれます。読み込み速度が速く、作成が簡単ですが、保守性が低く、URL によって動的にコンテンツを表示することができないなどの欠点があります。例えば、このページの URL に name パラメータを渡して、ページ内に表示させることはできません。
したがって、動的ウェブページが生まれました。URL のパラメータの変化を動的に解析し、データベースと連携して、異なるページ内容を動的に表示することができます。現在出会うほとんどのサイトは動的サイトで、単純な HTML だけではなく、JSP、PHP、Python などの言語で作成される機能があり、静的ウェブページよりもはるかに強力で豊富です。
さらに、動的ウェブサイトはユーザーのログインと登録機能を実現します。冒頭で挙げた問題に戻ると、多くのページはログイン後でなければ表示できません。通常は、ユーザー名とパスワードを入力してログインすると、何らかの証憑のようなものを入手し、それを用いてログイン状態を維持し、ログイン後に閲覧可能なページへアクセスします。
無状態 HTTP
セッションと Cookies を理解する前に、HTTP の特徴の一つ「無状態」について理解しておく必要があります。
HTTP の無状態とは、HTTP プロトコルが取引処理に記憶能力を持たないことを指します。つまりサーバはクライアントの状態を知らず、リクエストを送信してレスポンスを受け取り、それを完結させます。この過程は完全に独立しており、前後の状態の変化を記録しません。したがって前の情報を処理するためには、再送信が必要となり、前の重複リクエストを送信して後続のレスポンスを取得することになり、これは我々が望む挙動ではありません。前後の状態を維持するためには、前のリクエストをすべて再送信するのは資源の無駄です。ログインが必要なページでは特に困難です。
この時、HTTP 接続状態を維持する技術として、セッションと Cookies の二つが現れます。セッションはサーバ側、すなわちウェブサイトのサーバで、ユーザーのセッション状態を保持するための属性・設定情報を保存します。クライアントがウェブページ間を移動しても、セッション内の変数は失われません。セッションが存在しない場合、Web サーバは自動的にセッションオブジェクトを作成します。セッションが期限切れになるか放棄されると、サーバはそのセッションを終了します。
2. Cookies
Cookies は、いくつかのサイトがユーザーの身元を識別し、セッションを追跡するためにユーザーの端末に保存するデータです。
- 会話維持 クライアントが初めてサーバにリクエストしたとき、サーバは Set-Cookie を含むレスポンスを返し、どのユーザーかを識別します。ブラウザは Cookies を保存します。次回のリクエスト時にはこの Cookies をリクエストヘッダとともにサーバへ送信します。Cookies にはセッション ID が含まれており、サーバはその Cookies から対応するセッションを特定し、ログイン状態を維持します。ログイン後のページを閲覧するには、サーバはセッション内の状態を確認します。ログイン状態であれば、ログイン後に閲覧可能なページを返します。 逆に、Cookies が無効であったり、セッションが期限切れの場合は、ページへアクセスできなくなる可能性があり、エラーが返されるか、ログインページへリダイレクトされることがあります。
したがって Cookies とセッションは連携して動作します。クライアント側とサーバ側の協調によって、ログインセッションのコントロールが実現します。
-
属性構造
Cookies にはさまざまな属性が含まれます。以降は知乎を例に、ブラウザの開発者ツールの Application タブを開き、左の Storage 部分の Cookies を展開して確認します。

ここには多くのエントリがあり、各エントリを Cookies と呼ぶことができます。主な属性は次のとおりです。
- Name:Cookie の名称。作成後は変更不可。
- Value:Cookie の値。Unicode 文字の場合は文字エンコード、二進データの場合は BASE64 エンコードを使用。
- Max Age:この Cookie の有効期限を秒単位で指定します。Expires と併用され、有効期間を算出します。Max Age が正の値ならこの秒数後に失効します。負の値なら、ブラウザを閉じたときに失効します。
- Path:この Cookie の使用パス。/path/ と設定するとパスが /path/ のページだけがこの Cookie を使用できます。/ に設定すると同一ドメイン下のすべてのページでこの Cookies にアクセスできます。
- Domain:この Cookies にアクセスできるドメイン。例として .zhihu.com を設定すると、.zhihu.com で終わるすべてのドメインからこの Cookie にアクセスできます。
- Size:この Cookie のサイズ。
- Http(HttpOnly):この Cookie の HttpOnly 属性。true の場合、HTTP ヘッダの情報でのみこの Cookie を参照でき、document.cookie からはアクセスできません。
- Secure:この Cookies が安全なプロトコル(HTTPS、SSL など)でのみ送信されるべきかどうか。デフォルトは false。
-
セッション Cookies と永続 Cookies
外観上、セッション Cookies はブラウザのメモリ内に保存され、ブラウザを閉じると失効します。永続 Cookies はクライアントのハードディスクに保存され、次回も使用可能で、長期間のログイン状態を保持します。
実際には、セッション Cookies と永続 Cookies の区別は Max Age または Expires フィールドによって決まります。
したがって、永続的なログインを提供するサイトは、Cookie の有効期限とセッションの有効期間を長く設定することで、次回の閲覧時にも以前の Cookies を持っていけば、ログイン状態を維持できます。
よくある誤解
セッション機構について語る際、よくある誤解として「ブラウザを閉じるとセッションが消える」というものがあります。会員カードの例を考えると、顧客が店舗に解約を申し出ない限り顧客データを削除しません。セッションも同様で、サーバがセッションを削除するよう通知しない限り、サーバはセッションを保持します。例えば、アプリでログアウト操作を行う場合にのみセッションを削除します。
ただし、ブラウザを閉じるとサーバへ通知されず、サーバがセッションを削除する機会がないため、この誤解が生じます。多くのセッション機構はセッションIDを Cookies に保存します。ブラウザを閉じると Cookies が消えてしまい、再接続時に元のセッションを見つけられなくなるのです。もしサーバが Cookies をディスクに保存するよう設定していたり、ブラウザが送信する HTTP リクエストヘッダを変更して元の Cookies を送信できる場合、ブラウザを再起動しても元のセッション ID を見つけてログイン状態を維持できます。
さらに、ブラウザを閉じてもセッションが削除されないことが原因で、サーバは会話を維持します。これを考慮して、サーバはセッションに有効期限を設定します。クライアントが最後にセッションを使用してから一定時間が過ぎると、サーバはクライアントが活動を停止したとみなし、セッションを削除してストレージ空間を節約します。
プロキシの基本原理
クローラーを実行していると、最初は正常にデータを取得できているにもかかわらず、ある時点で 403 Forbidden などのエラーが発生することがあります。サイトを開くと「あなたの IP のアクセス頻度が高すぎます」といった表示が出ることがあります。これはサイトが対策を施しているためで、サーバは一定時間内に特定の IP からのリクエスト数を検出し、閾値を超えるとサービスを拒否します。これを IP ブロックと呼びます。
サーバが検出するのは特定の IP の一定時間内のリクエスト回数です。したがって、何らかの方法で IP を偽装し、サーバが自機からのリクエストと判断できなくすれば、IP ブロックを回避できるのではないでしょうか。
一つの有効な方法はプロキシの使用です。
基本原理
プロキシとは、プロキシサーバのことで、英語名は proxy server です。その機能はネットワークユーザーが情報を取得するための中継点になることです。
通常ウェブサイトへアクセスすると、サーバへリクエストを送信します。プロキシサーバを介すると、実際には自分のマシンとサーバの間にブリッジを作ったような状況になり、クライアントは直接 Web サーバへリクエストを送るのではなく、プロキシサーバへリクエストを送ります。リクエストはまずプロキシサーバへ送られ、プロキシサーバが Web サーバへ再送信し、Web サーバからのレスポンスを再びクライアントへ転送します。
このようにして私たちは通常通りウェブページへアクセスできますが、この過程でサーバが認識する実 IP はもはや自分の IP ではなく、プロキシサーバの IP になります。これにより IP の偽装が実現され、プロキシの基本原理が成立します。
プロキシの作用
プロキシには次のような作用があります。
- 自身の IP アクセス制限を突破して、通常アクセスできないサイトへアクセスする。
- 教育ネット内の地址帯など、内部リソースにアクセスするためのプロキシを利用して FTP のダウンロード・アップロード、資料検索・共有などのサービスを利用する。
- キャッシュ技術を用いて処理の高速化。プロキシサーバは大容量のディスクキャッシュを設定して、外部情報を取得すると同時にキャッシュへ保存します。別の利用者が同じ情報へアクセスした場合、キャッシュから情報を取り出して提供することでアクセス速度を向上させます。
- 実 IP を隠す。回避策として用い、クローラーの IP がブロックされるのを防ぎます。
クローラー用プロキシ
クローラーでは、データ取得速度が速すぎると同じ IP からのアクセス頻度が高く見られ、サイト側が CAPTCHA を要求したり IP をブロックしたりします。これを回避するために、プロキシを使って実 IP を隠し、プロキシを頻繁に変更することでブロックを回避できます。
プロキシの分類
プロキシは、プロトコル別と匿名性の度合い別に分類できます。以下にそれぞれをまとめます。
-
プロトコル別
- FTP プロキシサーバ:FTP サーバへアクセスする用途が主で、アップロード・ダウンロード・キャッシュ機能を持ち、ポートは通常 21、2121 など。
- HTTP プロキシサーバ:ウェブページへのアクセスが主で、コンテンツフィルタリングとキャッシュ機能を持ち、ポートは通常 80、8080、3128 など。
- SSL/TLS プロキシ:暗号化サイトへのアクセス用。SSL または TLS 暗号化機能を持ち(最大 128 ビットの暗号強度をサポート)、ポートは通常 443。
- RTSP プロキシ:RealPlayer による Real メディアサーバへのアクセス、キャッシュ機能を持つことが多く、ポートは通常 554。
- Telnet プロキシ:Telnet によるリモート制御用で、ポートは通常 23。
- POP3/SMTP プロキシ:POP3/SMTP によるメール送受信、キャッシュ機能を持ち、ポートは通常 110/25。
- SOCKS プロキシ:データパケットを単純に転送するだけで、プロトコルや用途を特に気にしません。SOCKS は SOCKS4 と SOCKS5 に分かれ、SOCKS4 は TCP のみをサポート、SOCKS5 は TCP と UDP をサポートし、認証機構やサーバ側のドメイン名解決などもサポートします。要するに、SOCKS4 でできることは SOCKS5 でもほぼ可能ですが、SOCKS5 が可能なことが SOCKS4 では必ずしも可能とは限りません。
-
匿名性レベル別
- 高度匿名プロキシはデータパケットをそのまま転送します。サーバから見ると通常のクライアントのアクセスに見え、記録される IP はプロキシサーバの IP となります。
- 通常匿名プロキシはデータパケットにいくつかの変更を加え、サーバ側でこれはプロキシだと気づく可能性があり、クライアントの実 IP を追跡されることがあります。HTTP_VIA および HTTP_X_FORWARDED_FOR などのヘッダを追加することが多いです。
- 透明プロキシはデータパケットを改変するだけでなく、クライアントの実 IP をサーバに伝えます。キャッシュによる速度向上やコンテンツフィルタリングによるセキュリティ向上以外には顕著な利点は少なく、最も一般的な例は内部ネットワークのハードウェアファイアウォールです。
- 间諜プロキシは、組織や個人が作成した、ユーザーの伝送データを記録することを目的としたプロキシサーバです。
よくあるプロキシ設定
- ネット上の無料プロキシを使用する場合は、できるだけ高匿名性のものを使用します。使用前に取得して有効なプロキシをフィルタリングするか、プロキシプールを構築します。
- 有料プロキシサービスを利用します。インターネット上には多くのプロキシ業者があり、料金を支払って利用でき、品質は無料プロキシより高いです。
- ADSL ダイヤルアップ。1回の接続ごとに IP が変更され、安定性が高く、比較的効果的な解決策の一つです。
部分信息可能已经过时









