第2章 Python爬虫入门
2.1 爬虫的分类
网络爬虫按照系统结构和实现技术,常见的主要有以下几种类型:通用网络爬虫、聚焦网络爬虫、增量式网络爬虫和深层网络爬虫。 实际的网络爬虫系统通常是几种爬虫类型相交叉结合实现的。
下面分别对这几种常见爬虫做概念性的讲解。
2.1.1 通用网络爬虫
通用网络爬虫是指爬取目标资源在全互联网中,爬取目标数据巨大。对爬取性能要求非常高。应用于大型搜索引擎中,有非常高的应用价值。通用网络爬虫主要由初始URL集合、URL队列、页面爬行模块、页面分析模块、页面数据库、链接过滤模块等构成。通用网络爬虫的爬行策略主要有深度优先爬行策略和广度优先爬行策略。
2.1.2 聚焦网络爬虫
聚焦网络爬虫是指将爬取目标定位在与主题相关的页面中,主要应用在对特定信息的爬取中,主要为某一类特定的人群提供服务。聚焦网络爬虫主要由初始URL集合、URL队列、页面爬行模块、页面分析模块、页面数据库、链接过滤模块、内容评价模块、链接评价模块等构成。
聚焦网络爬虫的爬行策略有基于内容评价的爬行策略、基于链接评价的爬行策略、基于增强学习的爬行策略和基于语境图的爬行策略。
2.1.3 增量式网络爬虫
增量式网络爬虫是指对已下载网页采取增量式更新和只爬行新产生的或已经发生变化网页的爬虫,它能够在一定程度上保证所爬行的页面是尽可能新的页面。与周期性爬行和刷新页面的网络爬虫相比,增量式网络爬虫只会在需要时爬行新产生或发生更新的页面,不会重新下载没有发生变化的页面,可有效减少数据下载量,及时更新已爬行的网页,减小时间和空间上的耗费,但是增加了爬行算法的复杂度和实现难度。增量式网络爬虫的体系结构包含爬行模块、排序模块、更新模块、本地页面集、待爬行URL集及本地页面URL集。
增量式网络爬虫有两个目标:
- 保持本地页面集中存储的页面为最新页面
- 提高本地页面集中页面的质量
为实现第一个目标,增量式网络爬虫需要通过重新访问网页来更新本地页面集中的页面内容,常用的方法有以下几种:
- 统一更新法:爬虫以相同的频率访问所有网页,不考虑网页的改变频率
- 个体更新法:爬虫根据个体网页的改变频率来重新访问各页面
- 基于分类的更新法:爬虫根据网页改变频率将其分为更新较快网页子集和更新较慢网页子集两类,然后以不同的频率访问这两类网页。
2.1.4 深层网络爬虫
深层网络爬虫可以爬取互联网中的深层页面。在互联网中页面按存在方式分类,可分为表层页面和深层页面。
- 表层页面:指的是不需要提交表单,使用静态的链接就可以达到静态的页面
- 深层页面:隐藏在表单后面,不能通过静态链接直接获取,是需要提交一定的关键词之后才能获取到的页面
在互联网中,深层页面的数量往往比表层页面的数量要多得多,故而,需要想办法爬取深层页面。爬取深层页面,需要想办法自动填写好对应表单,所以,深层网络爬虫最重要的部分为表单填写部分。
深层网络爬虫主要由URL列表、LVS列表(LVS指的是标签/数值集合,即填充表单的数据源)、爬行控制器、解析器、LVS控制器、表单分析器、表单处理器、响应分析器等构成。
深层网络爬虫表单的填写有两种:
- 第1种:基于领域知识的表单填写,简单地说就是建立一个填写表单的关键词库,在需要填写时,根据语义分析选择对应的关键词进行填写;
- 第2种:基于网页结构分析的表单填写,简单地说,这种填写方式一般在领域知识有限的情况下使用,这种方式会根据网页结构进行分析,并自动地进行表单填写。
2.2爬虫的基本结构和工作流程
网络爬虫是搜索引擎抓取系统的重要组成部分。爬虫的主要目的是将互联网上的网页下载到本地形成一个互联网内容的镜像备份。
一个通用的普通网络爬虫的基本结构如下图所示:
网络爬虫的基本工作流程如下:
- 选取一些种子URL,如某地区的新闻列表1~10页的URL;
- 将这些URL放入待抓取的URL列表中;
- 依次从待抓取的URL列表中取出URL进行解析,得到网页源码,并下载存储到已下载网页源码库中,同时将这个已抓取过的URL放进已抓取的URL列表中;
- 分析已经抓取URL列表中URL对应的网页源码,从中按照一定的需求或规则,提取出新URL放入待抓取的URL列表中,这样依次循环,直到待抓取URL列表中的URL抓取完为止。例如新闻列表中每夜每一条新闻的标题详情URL。
2.3 爬虫策略
在实际的爬虫项目开发过程中,对于待抓取的URL列表的设计是很重要的一部分。例如,待抓取URL列表中的URL以什么样的顺序排列就是一个很重要的问题,因为这涉及到先抓取哪个页面,后抓取哪个页面。而决定这些URL排列顺序的方法,称为抓取策略。下面介绍几种常见的抓取策略。
2.3.1 深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。
2.3.2 宽度优先遍历策略
宽度优先遍历策略的基本思路是,将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会首先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。
例如,以淘宝网首页为起始URL为例,如果采用宽度优先的遍历策略,就会首先把淘宝网首页所有的URL提取出来放到待抓取URL列表中,然后再选择其中的一个URL进入,继续在进入的新页面中提取所有的URL,层层递进,依次循环,直到所有的URL抓取完毕。
2.3.3 大站优先策略
大站优先策略是指以网站为单位来进行主题选择,确定优先性,对于待爬取URL队列中的网页,根据所属网站归类,如果哪个网站等待下载的页面最多,则优先下载这些链接,其本质思想倾向于优先下载大型网站。因为大型网站往往包含更多的页面。鉴于大型网站往往是著名企业的内容,其网页质量一般较高,所以这个思路虽然简单,但是有一定依据。实验表明,这个算法效果也要优先于宽度优先遍历策略。
2.3.4最佳优先搜索策略
最佳优先搜索策略按照一定的网页分析算法,预测候选URL与目标网页的相似度,或与主题的相关性,并选取评价最好的一个或几个URL进行抓取。它只访问经过网页分析算法预测为“有用”的网页。存在的一个问题是,在爬虫抓取路径上的很多相关网页可能被忽略,因为最佳优先策略是一种局部最优搜索算法。因此需要将最佳优先结合具体的应用进行改进,以跳出局部最优点。
2.4 HTTP的基本原理
2.4.1 URI和URL介绍
URI:统一资源标识符,Uniform Resource Identifier
URL:统一资源定位符,Universal Resource Locator
举例来说,“http://www.baidu.com/search/detail?z=0&word=爬虫教程”这个地址是百度搜索的一个链接,它是一个URL,也是一个URI。用URI/URL来唯一指定了它的访问方式,这其中包括了访问协议https、访问主机www.baidu.com和资源路径(“/”后面的内容)。通过这样一个链接,我们便可以从互联网上找到这个资源,这就是URL/URI。这种链接一般为了简便习惯性地称为URL。
因此,笼统地说,每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称(Uniform Resource Name,URN),它命名资源但不指定如何定位资源。
URI是个纯粹的句法结构,用于指定标识Web资源的字符串的各个不同部分。URL是URI的一个特例,它包含了定位Web资源的足够信息。其他URI,如mailto: cay@horstman.com 则不属于定位符,因为根据该标识符无法定位任何资源。
2.4.2 超文本
“超文本”是超级文本的中文缩写,它的英文名称为HyperText,我们经常上网打开浏览器所看到的网页就是超文本解析而成的。其网页源码是一系列的HTML代码,其中包含了各种标签。浏览器解析这些标签之后,便成了我们平常所看到的网页,而网页的源代码就可以称为超文本。
2.4.3 HTTP和HTTPS
在上网过程中,访问的网址(URL)的开头会有http或https,这就是访问资源需要的协议类型,有时还会看到ftp、sftp、smb开头的URL,它们也都是协议类型。在爬虫中,抓取的页面通常是http或https协议的,下面先来了解一下这两个协议的含义。
HTTP(Hyper Text Transfer Protocol,超文本传输协议)是用于从网络传输超文本数据到本地浏览器的传送协议,它能保证高效而准确地传送超文本文档。HTTP是由万维网协会(World Wide Web Consortium)和互联网工程工作小组IETF(Internet Engineering Task Force)共同合作制定的规范,目前使用广泛的是HTTP1.1版本。
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer, 超文本传输安全协议) 是以安全为目标的HTTP通道,简单讲就是HTTP的安全版,即HTTP下加入SSL层。HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。它是一个URI scheme(抽象标识符体系),句法类同htp:体系,用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通信方法。现在它被广泛用于万维网上安全敏感的通信,如交易支付方面。
现在越来越多的网站和App都在使用HTTPS,如我们每天都在使用的即时通信聊天工具微信,以及微信中的微信公众号、微信小程序等。这说明未来肯定以HTTPS为发展的方向。
然而某些网站虽然使用了HTTPS,但还是会被浏览器提示不安全,例如,使用谷歌浏览器Chrome打开12306购票网站http://www.12306.cn,这时浏览器就会提示【您的连接不是私密连接】。这是因为12306的CA证书是由中国铁道部自行签发的,而这个证书是不被CA机构信任的,所以才会出现这样的提示,但是实际上它的数据传输依然是经过SSL加密认证的。如果爬取这样的站点就需要设置忽略证书的选项,否则会提示SSL连接错误。
2.4.4 HTTP的请求过程
通过前面的学习了解了什么是HTTP和HTTPS,下面深入了解一下它们的请求过程。由与HTTP和HTTPS的请求过程都是一样的,因此这里仅以HTTP为例。HTTP的请求过程笼统地来讲,可归纳为以下几个步骤:
客户端浏览器向网站所在的服务器发送一个请求–>网站服务器接收到这个请求后进行解析和处理,返回响应对应的数据给浏览器- ->浏览器中包含网页的源代码等内容,浏览器再对齐进行解析,最终将结果呈现给用户。
使用谷歌浏览器打开淘宝网首页,按F12进入开发者调试模式。以淘宝网为例,输入“http://www.taobao.com”进入淘宝网首页,观察右侧开发者模式中的选项卡,选择【Network】选项卡。界面出现了很多的条目,其实这就是一个请求接受和响应的过程。
通过观察可以发现它有很多列,各列的含义如下:
- Name:代表的是请求的名称,一般情况下,URL的最后一部分内容就是名称。
- Status:响应的状态码,如果显示是200则代表响应正常,通过这个状态码可以判断发送了请求后是否得到了正常的响应,如常见的响应状态码404、500等。
- Type:请求的类型,常见的类型有xhr、document等,如这里有一个名称为www.taobao.com的请求,它的类型为document,表示这次请求的是一个HTML文档,响应的内容就是一些HTML代码。
- Initiator:请求源,用来标记请求是哪个进程或对象发起的。
- Size:表示从服务器下载的文件和请求的资源大小。如果是从缓存中取得的资源,则该列会显示from cache。
- Time:表示从发起请求到响应所耗费的总时间。
- Waterfall:网络请求的可视化瀑布流。
下面来单击www.taobao.com这个名称的请求,可以看到关于请求更详细的信息。
- General部分:Request URL为请求的URL,Request Method为请求的方法,Status Code为响应状态码,Remote Address 为远程服务器的地址和端口,Referrer Policy为Referrer判别策略。
- Response Headers和Request Headers部分:该部分代表响应头和请求头。请求头中有许多信息,如浏览器标识、Cookie、Host等,这是请求的一部分,服务器会根据请求头内部的信息判断请求是否合法,进而做出对应的响应。Response Header就是响应的一部分,例如,其中包含了服务器的类型、文档类型、日期信息等,浏览器接收到响应后,会解析响应内容,进而展现给用户。
概括地说,其实请求主要包含以下部分:请求方法、请求网址、请求头和请求体。而响应包含响应状态码、响应头和响应体。HTTP的请求过程大致就是这样。
2.5 网页基础
2.5.1 网页的组成
一个网页的结构就是使用结构化的方法对网页中用到的信息进行整理和分类,使内容更具有条理性、逻辑性和易读性。如果网页没有自己的结构,那么打开的网页就像一团乱麻,很难在其中找到自己想要的信息。一个好的结构是网页带来好的用户体验的重要的一环。
一个完整的网页大致可以分为三部分:HTML、CSS和JS,这三部分组成了我们平时看到的网页。下面分别介绍这三部分的功能。
1.HTML
HTML(Hyper Text Markup Language.超文本标记语言)是用来描述网页的一种语言。这里需要申明一点,HTML不是一种编程语言,而是一种标记语言。HTML使用标记标签来描述网页,同时HTML文档包含了HTML标签及文本内容,所以HTML文档也称为Web页面。网页包括文字按钮、图片、视频等各种复杂的元素,不同类型的元素通过不同类型的标签来表示,如图片用img标签来表示,段落用p标签来表示,它们之间的布局又常通过布局标签div嵌套组合而成,各种标签通过不同的排列和嵌套才形成了网页的框架。
整个网页就是各种标签前套组合而成的。这些标签定义的节点元素相互嵌套和组合形成了复杂的层次关系,从而形成了网页的架构。
2.CSS
通过前面的介绍了解到HTML定义了网页的结构,但是只有HTML页面的布局并不美观,可能只是简单的节点元素的排列,为了让网页看起来更美观一些,需要借助CSS。Css(Cascading
Style Sheet,层叠样式表)是用来控制网页外观的一门技术。
在网页初期,是没有CSS的。那时的网页仅仅是用HTML标签来制作,CSS的出现就是为了改造HTML标签在浏览器展示的外观,使其更加美观。如果没有CSS,就不会有现在色彩缤纷的网页页面。
例如,以下代码就是一个CSS样式
#test{
width:800px;
height:600px;
background-color:red;
}
大括号前面是一个CSS选择器,此选择器的意思是选中id为test的节点,大括号内部写的就是一条条的样式规则,例如,width 指定了元素的宽,height指定了元素的高,background-color指定了元素的背景颜色。也就是说,将宽、高、背景颜色等样式配置统一写成这样的形式,然后用大括号括起来,接着在开头加上CSS选择器,这就代表这个样式对CSS选择器选中的元素生效,元素就会根据此样式来展示了。
在网页中一般会统一定义整个网页的样式规则,并写入CSS文件中(其后缀名为.css)。在HTML中,只需要用link标签即可引入写好的CSS文件,这样整个网页就会变得美观。
3.JavaScript
JavaScript(简称JS)是一种脚本语言。HTML和CSS配合使用,提供给用户的只是一种静态信息,缺乏交互性。在网页里可能会看到一些交互和动画效果,如下载进度条、提示框、轮播图、表单提交等,这通常就是JavaScript的功劳。它的出现使得用户与信息之间不只是一种浏览器与显示的关系,而实现了一种实时、动态、交互的页面功能。
JavaScript通常也是以单独的文件形式加载的,后缀名为js,在HTML中通过script标签即可引人。例如:
<script src="test.js"></script>
综上所述,HTML定义了网页的内容和结果,CSS描述了网页的布局,JavaScript定义了网页的行为。
2.6 Session和Cookie
在浏览网站过程中,我们经常会遇到需要登录的情况,有些页面需要登录之后才能访问,而且登录之后可以连续访问很多次网站,但是有时过一段时间就需要重新登录。还有一些网站在打开浏览器时就自动登录了,而且很长时间都不会失效。这就主要涉及Session和Cookie的相关知识。
2.6.1 Session和Cookie的基本原理
Session和Cookie是用于保持HTTP连接状态的技术。在网页或APP等应用中基本都会使用到,同时鉴于后面在写爬虫时,也会经常涉及需要携带Cookie应对一般的反爬,下面将会分别对Session和Cookie的基本原理做简要讲解。
1. Session
Session代表服务器与浏览器的一次会话过程,这个过程可以是连续的,也可以是时断时续的。Session是一种服务器端的机制,Session对象用来存储特定用户会话所需的信息。Session由服务端生成,保存在服务器的内存、缓存、硬盘或数据库中。
Session的基本原理如下:
- 当用户访问一个服务器,如果服务器启用Session,服务器就要为该用户创建一个Session,在创建Session时,服务器首先检查这个用户发来的请求里是否包含了一个Session ID,如果包含了一个Session ID,则说明之前该用户已经登录过并为此用户创建过Session,那么服务器就按照这个Session ID把这个Session在服务器的内存查找出来(如果查找不到,就有可能新建一个)。
- 如果客户端请求中不包含Session ID,则为该客户端创建一个Session并生成一个与此Session相关的Session ID。要求这个Session ID是唯一的、不重复的、不容易找到规律的字符串,这个Session ID将在本次响应中返回到客户端保存,而保存这个Session ID的正是Cookie,这样在交互过程中浏览器可以自动地按照规则把这个标识发送给服务器。
2. Cookie
因为HTTP是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结账时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么。为了做到这点,就需要使用到Cookie。服务器可以设置或读取Cookie中包含的信息,借此维护用户与服务器会话中的状态。
Cookie是由服务端生成后发送给客户端(通常是浏览器)的。Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie。
- 内存Cookie:由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。
- 硬盘Cookie:保存在硬盘里,有一个过期时间,除非用户手动清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的。所以,按存在时间,可分为非持久Cookie和持久Cookie。
Cookie的基本原理如下。
- 创建Cookie:当用户第一次浏览某个使用Cookie的网站时,该网站的服务器就进行如下工作。给该用户生成一个唯一的识别码(Cookie ID),创建一个Cookie对象;默认情况下,它是
一个会话级别的Cookie,存储在浏览器的内存中,用户退出浏览器之后被删除。如果网站希望浏览器将该Cookie存储在磁盘上,则需要设置最大时效(maxAge),并给出一个以秒为单位的时间(其中将最大时效设为0则是命令浏览器删除该Cookie);然后将Cookie放入HTTP响应报头,将Cookie插入一个Set-Cookie HTTP 请求报头中。最终发送该HTTP 响应报文。 - 设置存储Cookie:浏览器收到该响应报文之后,根据报文头里的Set-Cookie 特殊的指示,生成相应的Cookie,保存在客户端。该Cookie中记录着用户当前的信息。
- 发送Cookie:当用户再次访问该网站时,浏览器首先检查所有存储的Cookie,如果某个存在该网站的Cookie(即该Cookie所声明的作用范围大于等于将要请求的资源),则把该Cookie
附在请求资源的HTTP请求头上发送给服务器。 - 读取Cookie:服务器接收到用户的HTTP请求报文之后,从报文头获取到该用户的Cookie,从中找到所需要的内容。
2.6.2 Session和Cookie的区别
了解了Session和Cookie的基本原理,下面来了解一下它们之间的区别。Session是存储在服务器端的,Cookie是存储在客户端的,所以Session的安全性要高于Cookie。再者,我们获取的Session 中的信息是通过存放在会话Cookie 中的Session ID获取的,因为Session是存放在服务器中的,所以Session中的东西不断增加会增加服务器的负担,我们会把一些重要的东西放在Session中,不太重要的东西放在客户端Cookie中,Cookie分为两大类,会话Cookie和持久化Cookie,它们的生命周期和浏览器是一致的,浏览器关了会话Cookie 也就消失了,而持久化Cookie会存储在客户端硬盘中。当浏览器关闭时会话Cookie也就消失了,所以Session也就消失了,Session在什么情况下丢失,就是在服务器关闭时,或者是Session过期时(默认30分钟)。
2.6.3 常见误区
在谈论会话机制时,常常会产生这样的误解——“只要关闭浏览器,会话就消失了”。可以想一下银行卡的例子,除非客户主动销卡,否则银行绝对不会轻易销卡删除客户的资料信息。对于会话来说也是一样,除非程序通知服务器删除一个会话,否则服务器会一直保留。例如,程序一般都是在我们做注销的操作时才去删除会话。
当我们关闭浏览器时,浏览器不会主动在关闭之前通知服务器它将会关闭,所以服务器根本就不会知道浏览器已经关闭。之所以会有这种错觉,是因为大部分会话机制都会使用会话Cookie来保存会话ID信息,而关闭浏览器之后Cookie就消失了,再次连接服务器时,也就无法找到原来的会话了。如果服务器设置的Cookie保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的Cookie发送给服务器,再次打开浏览器,仍然能够找到原来的会话ID,依旧还是可以保持登录状态的。
而且恰恰是由于关闭浏览器不会导致会话被删除,这就需要服务器为会话设置一个失效时间,当距离客户端上一次使用会话的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把会话删除以节省存储空间。
Session和Cookie机制详解看这里:Cookie/Session机制详解