程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

Python网络爬虫原理解构,原来如此简单!

hfteth 2025-03-29 17:47:42 技术文章 9 ℃

第2章 网络爬虫基础

网络爬虫实现的思想是模拟用户使用浏览器向网站发送请求,网站响应请求后,将HTML文档发送过来,爬虫再对网页做信息提取和存储。因此,了解浏览器与网站服务器之间的通信方式和交互过程,理解HTML页面的组织和结构,掌握页面信息的提取和存储技术,能进一步加深对网络爬虫原理的理解。

2.1 HTTP基本原理

下面来看一下用户从浏览器输入某个网址到获取网站内容的整个过程。该过程主要分为4个步骤,如图2-1所示。

图2-1 访问网站的过程

(1)在浏览器中输入URL地址(如百度地址>https://www.baidu.com),然后回车。

(2)在浏览器中向网站服务器发送请求访问的命令。

(3)网站服务器响应请求后,向浏览器发送HTML文档(也可以是图片、视频和JSON数据等其他资源)。

(4)浏览器解析、渲染HTML文档后,将页面展示给用户。

下面详细讲解这些步骤中的关键知识,这将有助于我们更深入地了解爬虫的基本原理。

2.1.1 URL介绍

我们把在浏览器的地址栏里输入的网址叫做URL(Uniform Resource Locator,统一资源定位符)。URL用于确定分散在互联网中各种资源的位置和访问方式。例如摄图网中故宫博物馆的图片地址为
http://seopic.699pic.com/photo/50088/2824.jpg_wh1200.jpg。它包含了以下几种信息:

·访问协议:http,用于确定数据传输的方式。

·服务器名称:seopic.699pic.com,图片所在的网站服务器地址。

·访问路径:photo/50088,图片目录。

·资源名:2824.jpg_wh1200.jpg,图片名称。

2.1.2 HTTP和HTTPS协议

首先来看一下访问协议。为了保证浏览器能够正确解析并显示网站服务器传送的资源,需要制定一套双方都遵守的协议,最常见的有HTTP和HTTPS协议。当然还有其他功能的协议,如FTP(文件传输协议)、TELNET(远程登录服务)、FILE(本地文件传输协议)等。在爬虫中,通常是通过HTTP或HTTPS协议获取到页面的。

下面就来了解一下这两个协议。

HTTP(HyperText Transfer Protocol,超文本传输协议)是用于从网络中传输超文本到本地浏览器的传输协议,是互联网中应用最广泛的一种网络协议。它能保证高效而准确地传送超文本文档,我们平常看到的HTML文档就是超文本文档。

HTTP协议以明文方式发送内容,不提供任何方式的数据加密。像银行卡号、密码等对安全性要求高的信息传输,就不能使用HTTP,而要使用HTTPS协议。

HTTPS(HyperText Transfer Protocol over Secure Socket Layer,安全套接字层超文本传输协议)是以安全为目标的HTTP通道,简单地讲,就是HTTP的安全版。HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并对浏览器和服务器之间的通信加密。

目前,越来越多的网站都开始采用安全级别更高的HTTPS协议了。

2.1.3 HTTP请求(Request)

当用户通过浏览器访问某个网站时,浏览器会向网站服务器发送访问请求,这个请求就叫做HTTP请求。请求包含的内容主要有:

·请求方法(Request Method);

·请求网址(Request URL);

·请求头(Request Headers);

·请求体(Request Body)。

为了更直观地说明这个过程,我们使用Chrome浏览器自带的“开发者工具”来查看浏览器发送的请求信息。下面以访问百度(https://www.baidu.com)为例来讲解。

(1)打开Chrome浏览器,按F12键,显示“开发者工具”栏。

(2)在地址栏中输入百度网址https://www.baidu.com,然后回车。

(3)此时“开发者工具”栏抓取到了许多浏览器请求及服务器响应信息。按如图2-2所示的顺序选中各个选项,在第4步的Headers选项卡中,就能查看到请求信息了。

图2-2 查看请求内容

下面来看一下浏览器向百度的网站服务器发送了哪些请求信息。

1.请求方法(Request Method)

HTTP协议定义了许多与服务器交互的方法,最常用的有GET和POST方法。

如果浏览器向服务器发送一个GET请求,则请求的参数信息会直接包含在URL中。例如在百度搜索栏中输入scrapy,单击“百度一下”按钮,就形成了一个GET请求。搜索结果页面的URL变为https://www.baidu.com/s?wd=scrapy,URL中问号(?)后面的wd=scrapy就是请求的参数,表示要搜寻的关键字。

POST请求主要用于表单的提交。表单中输入的卡号、密码等隐私信息通过POST请求方式提交后,数据不会暴露在URL中,而是保存于请求体中,避免了信息的泄露。

2.请求网址(Request URL)

另外,还有一个选项Remote Address:180.97.33.107:443,这是百度服务器的IP地址。也可以使用IP地址来访问百度。

3.请求头(Request Headers)

请求头的内容在Headers选项卡中的Request Headers目录下,如图2-3所示。请求头中包含了许多有关客户端环境和请求正文的信息,比较重要的信息有Cookie和User-Agent等。

图2-3 Chrome中的请求头

下面简单介绍常用的请求头信息。

·Accept:浏览器端可以接受的媒体类型。text/html代表浏览器可以接受服务器发送的文档类型为text/html,也就是我们常说的HTML文档。

·Accept-Encoding:浏览器接受的编码方式。

·Accept-Language:浏览器所接受的语言种类。

·Connection:表示是否需要持久连接。keep-alive表示浏览器与网站服务器保持连接;close表示一个请求结束后,浏览器和网站服务器就会断开,下次请求时需重新连接。

·Cookie:有时也用复数形式Cookies,指网站为了辨别用户身份、进行会话跟踪而储存在用户本地的数据(通常经过加密),由网站服务器创建。例如当我们登录后,访问该网站的其他页面时,发现都是处于登录状态,这是Cookie在发挥作用。因为浏览器每次在请求该站点的页面时,都会在请求头中加上保存有用户名和密码等信息的Cookie并将其发送给服务器,服务器识别出该用户后,就将页面发送给浏览器。在爬虫中,有时需要爬取登录后才能访问的页面,通过对Cookie进行设置,就可以成功访问登录后的页面了。

·Host:指定被请求资源的Internet主机和端口号,通常从URL中提取。

·User-Agent:告诉网站服务器,客户端使用的操作系统、浏览器的名称和版本、CPU版本,以及浏览器渲染引擎、浏览器语言等。在爬虫中,设置此项可以将爬虫伪装成浏览器。

4.请求体(Request Body)

请求体中保存的内容一般是POST请求发送的表单数据。对于GET请求,请求体为空。

2.1.4 HTTP响应(Response)

当网站服务器接收到浏览器的请求后,会发送响应消息给浏览器,这个响应就叫做HTTP响应。一个完整的响应消息主要包含:

·响应状态码(Response Status Code);

·响应头(Response Headers);

·响应体(Response Body)。

1.响应状态码(Response Status Code)

响应状态码表示服务器对请求的响应结果。例如,200代表服务器响应成功,403代表禁止访问,404代表页面未找到,408代表请求超时。浏览器会根据状态码做出相应的处理。在爬虫中,可以根据状态码来判断服务器的状态,如果状态码为200,则继续处理数据,否则直接忽略。表2-1中列举了常见的状态码。

表2-1 常见状态码及说明

2.响应头(Response Headers)

响应头中包含了服务器对请求的应答信息。在Chrome浏览器的“开发者工具”中,响应头的内容在Headers选项卡中的Response Headers目录中,如图2-4所示。

图2-4 Chrome中的响应头信息

下面简单介绍一下常用的响应头信息。

·Date:服务器响应时间。

·Content-Type:返回数据的文档类型,如text/html代表返回HTML文档;application/x-javascript代表返回JavaScript文件;image/jpeg代表返回图片。

·Content-Encoding:服务器支持的返回内容压缩编码类型。

·Server:服务器软件的名称。

·Set-Cookie:设置HTTP Cookie。

·Expires:响应过期的日期和时间。

3.响应体(Response Body)

响应体中存放服务器发送给浏览器的正文数据。在Chrome浏览器的“开发者工具”中,与Headers选项卡平行的Response选项卡中存储的就是响应体数据。比如请求访问百度首页时,它的响应体就是百度首页的HTML代码,如图2-5所示。

图2-5 服务器返回的百度首页的响应体

当访问摄图网中故宫博物馆的图片(
http://seopic.699pic.com/photo/50088/2824.jpg_wh1200.jpg)时,它的响应体就是一张图片的二进制数据。Response选项卡中无法显示图片数据,在左边的Preview选项卡中可以预览,如图2-6所示。

图2-6 服务器返回的图片预览

在爬虫中,我们从响应体中获取HTML代码、JSON数据和网络图片等,然后从中提取相应的内容。

2.2 网页基础

当从网站服务器获取了HTML文档后,就需要从文档中提取有价值、有意义的数据了。如何从看似纷繁复杂、杂乱无章的HTML文档中提取想要的数据呢?这就必须要了解HTML的基本组成和结构了。可以将HTML看成一个树形结构,沿着树根往下遍历,就能找到任何想要位置的数据了。

2.2.1 HTML文档

HTML(HyperText Markup Language,超文本标记语言)用于创建网页。HTML使用标签来表示不同的内容,如使用表示图片,使用

表示表格,使用
对页面进行布局等,各种标签互相嵌套,就形成了复杂的网页。

还记得在Chrome浏览器的“开发者工具”中,如何查看百度的HTML代码吗?没错,服务器将它放在了响应体中,见图2-5所示。

2.2.2 网页的结构

下面来看一个简单的电影排行的HTML例子。代码可以在记事本中编写,保存后将后缀改为html(movies.html),也可以在PyCharm中新建一个HTML文档。下面是实现的HTML代码:




  
      
      电影排行
  
  
      

电影排行榜单

1.肖申克的救赎

2.霸王别姬


使用浏览器打开movies.html,网页效果如图2-7所示。

下面来分析一下这个HTML代码。

·第一行代码中用DOCTYPE定义了文档类型。

·使用尖括号定义标签,如、、、

·标签一般是成对出现的,如是起始标签,是终止标签。

·最外层的是HTML标签,表示HTML代码的范围。内部包含head和body标签,分别表示网页头和网页体。

·head标签内定义了网页的属性和引用。例如,指明了网页的编码方式为UTF-8;电影排行定义了网页的标题。

·body标签内是浏览器显示的正文内容,也是爬虫获取数据的来源。

·div标签类似于一个容器,它将内部所有的内容看成一个整体,主要用于页面的布局。

图2-7 电影排行页面

·h1标签代表一级标题;p标签代表段落,会自动换行。

·标签内可以定义自己的属性。例如,

的属性id值为content。这是一个非常有用的属性,因为整个网页中,id的值是唯一的,可以通过它快速定位到这个标签。在
中,属性class的值为m_list,这也是一个非常有用的属性,通过它可以定位到所有相同样式的标签。

2.2.3 节点树及节点之间的关系

如何获取穿插在HTML文档中的文本信息呢?可以把HTML文档看作一棵树,准确地讲,叫做HTML DOM树。什么是DOM呢?DOM(Document Object Model,文档对象模型)是W3C(万维网联盟)的标准,它定义了访问HTML和XML文档的标准。不同的浏览器有不同的呈现网页的内部数据结构。但DOM树是跨平台且不依赖语言的,可以支持几乎所有的浏览器。

根据W3C的HTML DOM标准,HTML文档中的所有内容都是节点,所以HTML DOM树也叫做节点树。

·整个文档是一个文档节点。

·每个HTML元素是元素节点。

·HTML元素内的文本是文本节点。

·每个HTML属性是属性节点。

·注释是注释节点。

注意:这里所说的元素和标签是不一样的。标签是指被尖括号括起来的对象,元素是指从起始标签到终止标签所包含的所有内容的对象,如

电影排行榜单

就是一个元素,其中

是一个标签。

将电影排行的HTML文档转化为HTML DOM树,如图2-8所示,图中的方框就是一个个节点。

图2-8 HTML DOM树结构

通过这棵HTML DOM树,就可以遍历任意节点了。例如要获取网页的标题“电影排行”,可以沿着图2-8中树的左侧,从根节点依次查找:html→head→title→文本“电影排行”。

树中的节点之间具有层级关系,常用父(parent)、子(child)和兄弟(sibling)等术语描述这些关系。父节点拥有子节点,同级的子节点被称为兄弟节点。在节点树中,顶端节点称为根(root)。如图2-9所示为部分节点之间的关系。

图2-9  节点之间的关系

2.3 使用XPath提取网页信息

即使我们了解了HTML的树结构,要设法解析这棵树以获取文本内容,也将是一个十分艰巨的任务。好消息是,已经有人替我们实现了这些功能,通过一种被称为XPath的语言,就可以轻松地定位并提取元素、属性和文本。Scrapy爬虫框架中,也引入了XPath语言来定位和提取数据。

2.3.1 XPath介绍

XPath(XML Path Language,XML路径语言),是一门在XML文档中查找信息的语言。HTML与XML结构类似,也可以在HTML中查找信息。

2.3.2 XPath常用路径表达式

XPath使用路径表达式来选取HTML文档中的节点或者节点集。这些路径表达式和我们在常规的计算机文件系统中看到的表达式非常相似。

例如,在Windows系统中,要指明桌面上的文件hello.py的路径,通常可以写成C:\Users\tao\Desktop\hello.py,从C盘开始,使用反斜杠(\)逐级向下查找,直到找到最终的目标。如表2-2中列举了常用的XPath路径表达式。

表2-2 XPath常用路径表达式

有计算机基础的读者对诸如:斜杠(/)、点(.)、两点(..)的用法一定不会陌生。即使不熟悉也没关系,因为XPath的语法实在太简单了。下面通过一些实例来加深对XPath用法的理解。

还是以电影排行的HTML文档为例,使用XPath提取页面信息。HTML代码和显示页面,如图2-10所示。

图2-10 电影排行代码和显示页面

1.安装lxml库

使用XPath之前,要先安装Python的lxml库。lxml库是一个HTML/XML的解析器。安装方法非常简单,在命令行中输入以下命令即可。


>pip install lxml

2.导入lxml库

提取数据之前,要先导入lxml库的etree模块,再使用etree读取movies.html文件,生成一个节点树的对象,代码如下:


#导入lxml库的etree模块
from lxml import etree
#解析movies.html文件,返回一个节点树的对象
html_selector = etree.parse("movies.html",etree.HTMLParser())

节点树的对象生成后,就可以使用XPath抽取数据了。

3.获取html元素

使用斜杠(/)从根节点开始获取html元素。


#获取根节点html的元素
root = html_selector.xpath("/html")
print(root)

运行结果如下:


[]

可以看出,返回的root是一个列表,列表中存储了一个Element(元素)类型的对象,对象中节点的名称为html。

4.获取title元素

可以使用斜杠(/)从根节点开始逐层查找元素的子节点。


#斜杠(/)获取节点title
title = html_selector.xpath("/html/head/title")
print(title)

运行结果如下:


[]

需要注意的是,斜杠(/)在起始位置时,代表的是从根节点开始查找,其他位置代表查找子节点。

5.获取title的文本

可以使用text()获取节点title中的文本。


#text()获取节点title的文本
title_name = html_selector.xpath("/html/head/title/text()")
print(title_name)

运行结果如下:


['电影排行']

6.获取所有电影名称

电影名称所在的p节点相对根节点很远,如果从根节点逐层往下查找,XPath的表达式就会很长,如/html/body/div/div/p/text()。使用双斜杠(//)可以不考虑位置,获取页面中所有符合规则的子孙节点。


movie_name = html_selector.xpath("//p/text()")
print(movie_name)

运行结果如下:


['1.肖申克的救赎', '2.霸王别姬']

代码使用了双斜杠(//)抽取出页面中所有节点p的文本。注意抽取出来的所有数据,均是保存于列表中的。

当然,双斜杠(//)也可以放在路径表达式的中间,代码如下:


name = html_selector.xpath("/html//div[@id='content']/h1/text()")

运行结果如下:


['1.肖申克的救赎', '2.霸王别姬']

7.获取网页的编码格式

有时要获取的信息保存在属性中。例如,页面的编码格式就是在meta标签的charset属性中。可以使用“@属性名”的方式获取属性值。


#使用@获取属性的值
meta = html_selector.xpath("//meta/@charset")
print(meta)

运行结果如下:


['UTF-8']

在爬虫中,经常使用@href获取超链接。

8.获取div的id属性值

通过斜杠(/)或双斜杠(//)可以查找子节点或子孙节点。那么如何通过子节点,查找父节点呢?可以用两点(..)来实现。


attr = html_selector.xpath("//h1/../@id")
print(attr)

运行结果如下:


['content']

h1的后面是两点(..),即定位到h1的父节点

,再使用@id获取属性id的值。

2.3.3 XPath带谓语的路径表达式

有时需要查找某个特定的节点或者包含某个指定值的节点,如获取属性id为content的div元素,或者获取第一个p节点的文本等,如果使用XPath路径表达式,实现起来就比较困难,这时就需要用到谓语了。谓语被嵌在方括号([ ])中,用于查找特定节点或指定值的节点。如表2-3中列举了一些常用的带谓语的路径表达式(还是以电影排行的HTML文档为例)。

表2-3 常用的带谓语的路径表达式

XPath的功能非常强大,内置函数也很丰富,熟练使用,能大大提高HTML信息的提取效率。在Scrapy爬虫中,也是主要使用XPath定位和提取数据。更多XPath的用法,可以参考w3cschool(
http://www.w3school.com.cn/xpath/index.asp)。

2.4 本章小结

本章首先介绍了浏览器访问网站服务器的过程;接着讲解了HTML网页的组成和结构;最后实现了使用XPath提取网页信息。这正是网络爬虫运行的核心步骤,即模拟浏览器发送请求,服务器返回网页,然后解析网页信息。通过本章的学习,为网络爬虫的开发打下了坚实的理论基础。

Tags:

最近发表
标签列表