小小千想和您聊一聊

当前位置: 首页> 技术分享> 第2章 爬虫基础知识

第2章 爬虫基础知识

  本章学习目标

  l 掌握Cookiejar的使用

  l 掌握W3C标准

  l 掌握网页抓取方法

  网络爬虫可用来爬取网页内容,因此在学习爬虫的同时,需要了解Web前端的相关知识。本章抽取Web前端知识和爬虫抓取数据的相关库进行讲解,大家需熟练掌握这些必备知识,为之后Python爬虫的学习打下基础。

  2.1 Cookie的使用

  2.1.1 Cookie的概念

  Cookie诞生的最初目的是为了存储Web中的状态信息,以便服务器端的使用。当用户访问一个互联网页面时,HTTP无状态协议发挥着关键作用,所谓的无状态协议是指无法维持客户端与服务器端之间的会话状态。

  比如,若仅仅使用HTTP协议登录“扣丁学堂”网站,登录成功后继续访问该网站的其他网页,则该登录状态就会消失,用户需重新登录一次,这样就大大降低了用户体验。如果将该会话信息比如登陆状态等保存下来,这样当访问同一个网站的其他页面时将会方便很多。

  保存客户端与服务器端的会话信息有两种常用方式,第一种是在客户端中通过Cookie记录会话信息,第二种是在服务器端通过Session记录会话信息。需要注意的是,这两种保存方式都会用到Cookie。

  使用Cookie保存会话信息时,会话信息会全部保存在客户端,当访问同一个网站的其他页面时,会从Cookie中读取对应的会话信息,用于判断当前的会话状态,比如判断当前的登陆状态等。

  使用Session保存会话信息时,会话信息会全部保存在服务器端,而服务器端会发送SessionID等信息给客户端,客户端收到后将该信息保存于Cookie中。当访问同一个网站的其他页面时,客户端根据Cookie中的信息从服务器中的Session中检索出会话信息,进而判断会话状态。显然,这种方式也会用到Cookie。

  Cookie的本质是服务器在客户端上存储的小段文本,它会随着每一个请求发送至同一服务器。服务器用HTTP头向客户端发送Cookie,客户端会解析这些Cookie并将它们保存为一个本地文件。

  Cookie的工作方式是:服务器给每个Session分配一个唯一的SessionID,并通过Cookie发送给客户端,当客户端发起新的请求时,将在Cookie头中携带这个SessionID,服务器可据此找到这个客户端对应的Session。如图2.1所示。

  图2.1 Cookie工作流程

  在爬虫工作过程中如果使用Cookie登录成功,那么在爬取该网站其他网页时,就会保持登录状态而继续进行内容的爬取。

  2.1.2 使用Cookiejar处理Cookie

  网站最基本的功能就是用户注册登录,对于用户而言登录后可以拥有更多的功能和操作。例如,ChinaUnix.net(以下简称CU)是一个开源技术社区论坛,用户输入正确的用户名和密码,登录成功后可以管理自己的帖子。

  在Python3中可使用Cookiejar库处理Cookie,操作步骤如下:

  l 导入http.cookiejar模块处理Cookie。

  l 使用http.cookiejar.Cookie()创建CookieJar对象。

  l 使用HTTPCookieProcessor创建cookie处理器,并且当作参数构建opener对象。

  l 创建全局opener对象。

  接下来通过爬取CU网站的两个网页,讲解Cookiejar处理Cookie的使用方法,其CU网站的登录地址为“http://bbs.chinaunix.net/member.php?mod=logging&action=login&

  logsubmit=yes”,页面如图2.2所示。

  图2.2 ChinaUnix登陆界面

  需要注意的是,上面给出的登录地址仅仅是登录界面的地址,并不是提交数据的登录地址。若要获取真实的登陆地址,可通过键盘上F12按键调出网页调试界面进行分析。调出调试界面后,首先需要在登录的输入框中输入对应的用户名以及密码。本书使用的账号为“a877348180”,密码是“a123456”。

  输入对应帐号密码之后,单击【登录】,同时观察调试界面中的网址,点开这些网址可以看到几乎都使用了GET方法,只有一个使用了POST请求方法,点击观察就可以分析出处理POST表单的真实地址,将该网址复制出来“http://bbs.chinaunix.net/member.php?mod

  =logging&action=login&loginsubmit=yes&loginhash=Lw8lJ”,如图2.3所示。

  图2.3 真实POST表单地址

  选择查看源代码,并找到登录框对应的HTML代码,可以看到用户名所对应的表单name:username,密码对应的表单name:password。因此爬虫需要构建的数据格式为:


  {
  "username":"a877348180",
  "password":"a123456"
  }

  实际操作时根据自己注册的帐号名和密码更换即可。

  接下来将通过Cookiejar自动处理Cookie,实现登录CU网站成功后访问其他页面时也是登录状态,验证方式是爬取登录页面和另一个页面,且爬取下来的另一个页面也是登陆状态,具体代码如例2-1所示。

  【例2-1】 Cookiejar自动处理Cookie


  1 import urllib.request
  2 import urllib.parse
  3 import http.cookiejar
  4 login_url = "http://bbs.chinaunix.net/member.php?mod=
  5 logging&action=login&loginsubmit=yes&loginhash=L768Q"
  6 login_data = urllib.parse.urlencode({"username":"a877348180",
  7 "password":"a123456"}).encode('utf-8')
  8 req = urllib.request.Request(login_url, login_data)
  9 req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64;
  10 rv:61.0) Gecko/20100101 Firefox/61.0")
  11 # cookie处理第一步:创建cookiejar对象
  12 cookiejar = http.cookiejar.CookieJar()
  13 # 第二步:以cookie为处理器创建opener对象
  14 opener = urllib.request.build_opener(
  15 urllib.request.HTTPCookieProcessor(cookiejar))
  16 # 第三步:创建全局opener对象
  17 urllib.request.install_opener(opener)
  18 wb_file = overall_opener.open(req)
  19 wb_data = wb_file.read()
  20 fhandle = open("D:/spiderFile/bbs1.html","wb")
  21 fhandle.write(wb_data)
  22 fhandle.close()
  23 wb_url2="http://bbs.chinaunix.net/forum-55-1.html"
  24 wb_data2 = urllib.request.urlopen(wb_url2).read()
  25 fhandle = open("D:/spiderFile/bbs2.html","wb")
  26 fhandle.write(wb_data2)
  27 fhandle.close()

  运行程序后,查看D盘中spiderFile目录下保存的本地文件,第一个文件“bbs1.html”如图2.4所示。

  图2.4 登录后的论坛

  可以看到已经登录成功,接着打开bbs2.html,如图2.5所示。

  图2.5 登录后的论坛

  图2.6为爬虫爬取的CU网站登录后的下一个页面,该页面通过Cookie保存了登录状态,所以可以看到该页面也是登录状态。

  例2-1中的代码按照Cookiejar库处理Cookie的步骤,引入Cookiejar库后,第12行代码首先创建了一个CookieJar对象cookiejar,然后第14行创建一个Cookie处理器,随后以该处理器作为参数通过urllib.request.build_opener()创建一个Opener对象opener,并使用urllib.request.install_opener(opener)将opener安装为全局默认的对象,这样在使用urlopen()方法时,也会使用安装的Opener对象。

  需要注意的是,第9行和第10行代码中使用了“User-Agent”属性,关于该属性的知识介绍放在后面,这里只需要知道如何获取该属性值即可。例2-1中使用的浏览器是Firefox火狐浏览器,打开网页“http://www.baidu.com”并按F12打开网页调试界面,如图2.6所示。

  图2.6 获取User-Agent属性值

  将调试界面切换到“网络”后,点击输入框会出现很多方法,选择一个方法将会在右侧的消息头中看到该属性及对应的值。最后将其放入程序中即可。

  2.2 正则表达式介绍

  2.1.1 正则表达式的概念

  在编写网页文件的程序时,经常会对含有复杂规则的字符串进行查询,而正则表达式就是用一些具有特殊含义的符号组合在一起来描述字符或字符串的规则。比如想要查询一个网页中所有的联系人电话,此时可以编写一个正则表达式来表示所有的电话,然后在网页中提取出所有满足该规则的字符串即可。在Python中,通过内嵌的re模块来实现正则表达式的功能。需要注意的是,Python的正则表达式是被编译成一系列的字节码,然后使用C语言编写的匹配引擎来执行。

  2.1.2 正则表达式详解

  当想要查找网页中所有的“python”字符串时,可以使用正则表达式来匹配,但设置的规则不同,匹配出来的结果也不同。例如使用正则表达式“\w\dpython\w”匹配出来的可能是23python8或者u6python_等,而使用“\bpython\b”匹配出来的则是python。由此可见,需要掌握一些正则表达式的基础知识,才能匹配出想要的结果。本节主要从原子、元字符、模式修正符、贪婪模式与懒惰模式等方面介绍正则表达式的知识。

  1. 原子

  “原子”一词很容易联想到物理学中物质由原子组成的概念,类似的,原子是正则表达式中最基本的组成单位。但很显然,正则表达式中的原子与物理学中的原子不是一个概念。正则表达式中常见的原子有以下几类:

  1) 普通字符作为原子。

  2) 非打印字符作为原子。

  3) 通用字符作为原子。

  4) 原子表。

  接下来详细介绍每个分类。

  (1). 普通字符作为原子

  普通的字符包括数字、大小写字母、下画线等,都可以作为原子使用。例如查询“qianfeng” 字符串,该字符串中每一个字母都是原子。具体代码如例2-2所示。

  【例2-2】 匹配普通字符串

  1 import re # 正则模块
  2 exam = "qianfeng" # 字符作为原子
  3 str1= "qianfengedu" # 需要匹配的字符串
  4 ret = re.search(exam,str1) # search函数
  5 print(ret)

  运行结果如图2.7所示。

  图2.7 运行结果

  以上程序导入Python内置的re正则模块,使用其中的search()函数从字符串“qianfengedu”中搜索“qianfeng”第一次出现的匹配情况,如果匹配成功,返回匹配对象,否则,返回None。

  (2). 非打印字符作为原子

  所谓的非打印字符,是一些在字符串中的格式控制符号,例如空格、回车及制表符号。接下来实现一个换行符的匹配,如例2-3所示。

  【例2-3】 匹配换行符

  1 import re
  2 exam = '\n'
  3 str1 = '''http://www.1000phone.com
  4 http://www.codingke.com''' # str1字符串包含换行符
  5 ret = re.search(exam,str1) # search函数匹配正则表达式
  6 print(ret)

  运行结果如图2.8所示。

  图2.8 运行结果

  从程序运行结果可看出,search()函数成功匹配出'\n'。

  (3). 通用字符作为原子

  通用字符即一个原子可以匹配一类字符,在实际项目中最常用的就是这类原子。例如“\w\dcodingke\w”,其中\w表示一个字母、数字或者下划线,字符前一位\d是一个任意的十进制数[0-9],如“666codingke666”、“z6codingke_”都可以匹配成功,如例2-4所示。

  【例2-4】使用通用字符匹配字符串

  1 import re
  2 exam = "\w\dcodingke\w"
  3 str1 = "abcdasdase1231z4codingke_asd"
  4 ret = re.search(exam,str1)
  5 print(ret)

  运行结果如图2.9所示。

  图2.9 运行结果

  从程序运行结果可看出,“z4codingke_”匹配“\w\dcodingke\w”成功。

  常见的通用字符除了“\w”、“\d”外还包含它们的大写表示“\W”与“\D”,大写通用字符表示与小写相反的含义,例如“\w”表示匹配任意一个字母、数字或下划线,“\W”则表示除字母、数字或下划线以外的任意一个字符。

  (4). 原子表

  Python中原子表使用[]表示,它可以定义一组地位平等的原子,匹配时会取该原子表中的任意一个原子进行匹配,例如[xyz]、[^a-zA-Z]原子表中原子地位平等,[^]代表除了原子表内的原子均可以匹配,如例2-5所示。

  【例2-5】

  1 import re
  2 exam = "\w\dcodingke[xyz]\w" # \w字母、数字、下画线,\d十进制数,含有xyz
  3 exam1 = "\w\dcodingke[^xyz]" # [^zyx] 除x、y、z以外
  4 exam2 = "\w\dcodingke[xyz]\W" # \W 除字母、数字、下画线外
  5 str1 = "1000phone6codingke_666"
  6 ret = re.search(exam,str1)
  7 ret1 = re.search(exam1,str1)
  8 ret2 = re.search(exam2,str1)
  9 print(ret)
  10 print(ret1)
  11 print(ret2)

  运行程序,结果如图2.10所示。

  图2.10 运行结果

  从程序运行结果可看出,只有ret1是符合正则规则并匹配成功。

  2. 元字符

  所谓元字符就是正则表达式中具有特殊意义的字符,元字符分为任意匹配元字符、边界限制元字符、限定符、模式选择符、模式单元等。

  常用的元字符如表2.1所示。

  表2.1 常用元字符

  (1). 任意匹配元字符

  任意匹配元字符“.”可以匹配一个除换行符以外的任意字符。例如,正则表达式“codingke......”表示匹配codingke后面六位除换行符以外格式的字符,如例2-6所示。

  【例2-6】

  1 import re
  2 exam = "codingke......"
  3 str1 = "aaa666codingke66666666"
  4 ret = re.search(exam,str1)
  5 print(ret)

  运行程序,可以看到使用正则表达式“codingke......”匹配出“codingke666666”。

  (2). 边界限制元字符

  边界限制元字符使用“^”匹配字符串的开头,使用“$”匹配字符串的结束,如例2-7所示。

  【例2-7】

 1	import re
 2	exam1 = "^codingke" 	#以 codingke开头
 3	exam2 = "^codingkee"	#以 codingkeee开头
 4	exam3 = "ke$"  			#以 ke 结尾
 5	exam4 = "_jy$"  	 	#以 _jy 结尾
 6	str1 = "codingke_jy" 
 7	ret1 = re.search(exam1,str1)
 8	ret2 = re.search(exam2,str1)
 9	ret3 = re.search(exam3,str1)
 10	ret4 = re.search(exam4,str1)
 11	print(ret1)
 12	print(ret2)
 13	print(ret3)
 14	print(ret4)

  运行结果如图2.11所示。

  图2.11 程序结果

  上述结果,ret2、ret3没有匹配出结果,ret1、ret4匹配出结果。程序里限制了正则表达式exam1必须“codingke”开头,否则匹配失败。因为str1是“codingke_jy”,所以ret1匹配成功,exam2表达式限制必须以“codingkeee”开头,str1字符串中没有符合的条件,故而返回None。

  (3). 限定符

  限定符也是常用元字符的一种,常见的限定符包括*、?、+、{n}、{n,}、{n,m}。下面通过一个实例展示限定符的使用,具体代码如例2-8所示。

  【例2-8】

 1	import re
 2	exam1 = "py.*n"					  #py到n的任意字符且出现任意次数
 3	exam2 = "cd{2}"					  #d出现2 次
 4	exam3 = "cd{3}"				 	  #d出现3次
 5	exam4 = "cd{2,}"			       #d出现2次以上
 6	str1 = "abcdddfphp345python_py"   #源字符串是 "abcdddfphp345python_py"
 7	ret1 = re.search(exam1,str1) 	   #search函数匹配
 8	ret2 = re.search(exam2,str1)
 9	ret3 = re.search(exam3,str1)
 10	ret4 = re.search(exam4,str1)
 11	print(ret1)
 12	print(ret2)
 13	print(ret3)
 14	print(ret4)

  运行结果如图2.12所示。

  图2.12 程序结果

  上述代码4个正则表达式均匹配了结果,不同的正则表达式过滤结果也不一样。在

  exam1中,本文设置的格式是“py”与“n”之间可以是除换行符以外的任意字符,并且该任意字符可以出现0次、1次或多次,因此结果是“python”。正则表达式exam2中,规则是cd{2},字符串“cd”中的“d”要求出现2次,此时匹配出结果“cdd”。正则表达式exam3与exam2表达的意思一样。正则表达式exam4中,要求“cd”字符串中的“d”至少出现两次,所以会在源字符串中尽可能多匹配更多的匹配字符,结果是“cddd”。

  (4). 模式选择符

  使用模式选择符,可以设置多个模式,匹配时可以从中选择任意一个模式匹配。例如正

  则表达式“Python|php”中,字符串“Python”和“Php”均满足匹配条件,如例2-9所示。

  【例2-9】

 1	import re
 2	exam1 = "python|java" 					# 用于匹配python或java
 3	str1 = "abcdefgpython666java"			# 定义字符串
 4	ret1 = re.search(exam1,str1).group()	# group()调出第一个匹配结果 		
 5	print(ret1)

  运行结果如图2.13所示。

  图2.13 程序结果

  该正则表达式从源字符串中匹配出结果“python”。由于“|”模式选择符,优先匹配

  字符串中第一个结果,在字符串“str1”中,“python”存在“java”之前,因此得出结果。

  2.3 标记语言讲解

  W3C 指万维网联盟(World Wide Web Consortium),是Web技术领域最具权威和影响力的国际中立性技术标准机构。W3C是一系列标准的集合,Web标准由三大部分组成:结构(Structure)、表现(Presentation)和行为(Behavior)。

  1. 内容

  “内容”是指开发者放在页面内的,真正想要访问者浏览的信息,可以包含数据、文档、图片等。注意这里强调的“真正”,是指数据信息本身,而不包含辅助的信息(如导航菜单、装饰性图片等)。“内容”是网页的基础,在网页中具有重要的地位。

  2. 结构

  XML(Extensible Markup Language)——可扩展标记语言。XML目前遵循的是W3C于2000年10月发布的XML 1.0。与HTML一样,XML同样来源于标准通用标记语言(Standard Generalized Markup Language),但XML是一种能定义其他语言的语言。XML最初设计的目的是弥补HTML的不足,以强大的扩展性满足网络信息发布的需要,后来逐渐用于网络数据的转换和描述。

  XHTML(The Extensible HyperText Markup Language)——可扩展超文本标记语言。XML虽然数据转换能力强大,但是还不能完全替换HTML。因此,在HTML的基础上,用XML的规则对其进行扩展,得到了XHTML。简单而言,建立XHTML的目的就是实现HTML向XML的过渡。

  3. 表现

  CSS(Cascading Style Sheets)——层叠样式表。

  W3C创建CSS标准的目的是用CSS取代HTML表格布局,以及其他基于表现层的语言,使站点的访问与维护更加容易。

  4. 行为

  DOM(Document Object Model)——文档对象模型。

  DOM是W3C颁布的一种标准,用于对结构化文档建立对象模型,从而使得用户可以通过程序语言(包括脚本)来控制其内部结构。简单地理解,DOM解决了Netscape的JavaScript和Microsoft的JavaScript之间的冲突,给予Web设计师和开发者一个标准的方法,让他们来访问站点中的数据、脚本和表现对象。

  2.3.1 HTML标记语言

  HTML不是编程语言,是一种表示网页信息的符号标记语言。Web浏览器的作用是读取HTML文档,并以网页的形式显示。浏览器不会显示HTML标记,而是使用标记来解释页面的内容。

  HTML语言的特点包括:

  l 设置文本格式,如字体大小、颜色等。

  l 可以创建链接、列表、表格等。

  l 跨平台性。

  l 简易性,扩展灵活。

  首先查看网页的源代码结构,访问千锋互联教育官网,如图2.14所示。

  图2.14 千锋互联官网

  右键查看源代码如图2.15所示。

  图2.15 千锋互联官网源码

  1. 从源码中分析HTML基本结构

  l 内容:HTML文档是由包裹,分别位于网页的最前端和最后端。

  l 内容:HTML头信息标记,包含网页title、关键词、样式等标记。

  l 内容:HTML文件标题标记,显示网页标题。

  l 内容:HTML网页主题,包含

  、

  、

  等标签。

  l 内容:页面的元信息,提供有关页面的元信息,例如针对搜索引擎和更新频度的描述、关键词。

  2. 文档设置标签

  接下来通过案例演示文档设置标签,如例2-10所示。

  【例2-10】

 1	<!DOCTYPE html>
 2	<html lang="en">
 3	<head>
 4		<meta charset="UTF-8">
 5		<title>千锋互联教育</title>
 6	</head>
 7	<body>
 8		文档设置标记<br>
 9		<p>这是段落。千锋教育</p>
 10		<hr>
 11		<center>居中标记。千锋教育</center>
 12		<hr>
 13		<br>
 14		<ul>
 15			<li>扣丁学堂</li>
 16			<li>好程序员</li>
 17		</ul>
 18		<ol type="A">
 19			<li>扣丁学堂</li>
 20			<li>好程序员</li>
 21		</ol>
 22		<div>
 23			<h3>千锋教育</h3>
 24			<p>做有情怀、有良心、有品质的IT职业教育机构</p>
 25		</div>
 26		<dl>
 27			<dt>  帮助  </dt>
 28			<dd>学习流程</dd>
 29		</dl>
 30	</body>
 31	</html>

  使用浏览器打开以上代码,运行结果如图2.16所示。

  图2.16 运行结果

  常用的格式标签如表2.2所示。

  表2.2 常用标签

  3. 文本标签设置

  接下来通过案例演示文本标签的设置,如例2-11所示。

  【例2-11】

 1	<!DOCTYPE html>
 2	<html lang="en">
 3	<head>
 4		<meta charset="UTF-8">
 5		<title>千锋教育</title>
 6	</head>
 7	<body>
 8		h标题标签>>
 9		<br>
 10		<h1>千锋教育</h1>
 11		<h2>千锋教育</h2>
 12		<h3>千锋教育</h3>
 13		<h4>千锋教育</h4>
 14		<h5>千锋教育</h5>
 15		<h6>千锋教育</h6>
 16		font字体标签>>
 17		<font size="5" color="blue" face="宋体">扣丁学堂</font>
 18		<br>
 19		b加粗>>
 20		<b>好程序员</b>
 21		<br>
 22		i斜体>>
 23		<i>好程序员</i>
 24		<br>
 25		sup上标>>
 26		2<sup>2</sup>
 27		<br>
 28		引用标签>>
 29		<cite>好程序员</cite>
 30		<br>
 31		strong强调,显示加粗>>
 32		<strong>好程序员</strong>
 33		em调强,显示斜体>>
 34		<em>好程序员</em>
 35		<br>
 36		small标签,显示小一号字体,可嵌套使用>>
 37		<small>好程序员</small>
 38		<small><small>好程序员</small></small>
 39		<small><small><small>好程序员</small></small></small>
 40	</body>
 41	</html>

  选择在浏览器中运行,效果如图2.17所示。

  图2.17 运行结果

  文本标记包括:

  l :标记标题,n的范围是1~6,不同级别对应不同标题,h1最大,h6最小。

  l :字体设置标签。常用属性有。

  l :粗字体标记。

  l :斜字体标记。

  l :文字下标字体标记。

  l :文字上标字体标记。

  l :打印机字体标记。

  l :引用方式的字体,通常是斜体。

  l :表示强调,通常是斜体。

  l :表示强调,通常显示为粗体。

  l :小号字体标签。

  l :下划线字体标签。

  2.3.2 XPATH介绍

  1. XPath节点

  XPath是一种XML路径语言,被用于在XML文档中通过元素和属性进行导航。Xpath设计被用来搜寻XML文档,同样也能用于HTML文档,并且大部分浏览器也支持通过Xpath来查询节点。在Python爬虫开发中,也会频繁使用XPath查找提取网页信息。

  XPath以路径表达式来指定元素,称作XPath selector,比如使用“/”选择某个标签,使用多个“/”可选择多层标签,常用的路径表达式如表2.3所示。

  表2.3 路径表达式

  下面通过一个简单示例示范使用路径表达式查找信息。现有如下代码:


<?xml version="1.0" encoding="ISO-8859-1"?>
<classroom>
     <student>
          <id>1000</id>
          <name lang="en">1000phone</name>
			<age>25</age>
          <country>China</country>
     </student>
	    <student>
			<id>1001</id>
			<name lang=”en”>codingke</name>
			<age>18</age>
			<country>China</country>
		</student>
</classroom>


  现使用Xpath路径表达式查询上面代码中的信息。若选取所有的student子元素,可通过“classroom/student”表达式实现,若选取classroom子元素的第一个student元素,则可通过“/classroom/student[1]”表达式实现。

  表2.4、2.5和2.6展示了更多表达式,用于在上面代码中查询想要的信息。

  表2.4 节点选取

  以上是选取所有符合条件的节点,若要选择特定的节点或者带有特定值的节点,就需要使用谓语,具体如表2.5所示。

  表2.5 谓语

  XPath在进行节点选取时可以使用通配符“*”匹配未知的元素,同时使用操作符“|”一次选取多条路径,具体如表2.6所示。

  表2.6 通配符的使用

  2.3.3 JSON介绍

  JSON的全称是“JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,且独立于语言的轻量级数据交换格式。JSON比XML更加轻量、更易解析,在Web前端中运用非常广泛。JSON使用JavaScript语法来描述数据对象,但JSON仍然独立于语言和平台。JSON解析器和JSON库支持许多不同的编程语法,其语法如表2.7所示。

  表2.7 JSON语法

  2.4 BeautifulSoup简介

  BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库,它能够通过转换器实现大家惯用的文档导航、查找、修改文档等功能。使用BeautifulSoup可以快速实现一个完整的爬虫应用程序。

  2.4.1 安装BeautifulSoup

  由于BeautifulSoup并不是Python标准库,因此需要单独安装。本书推荐安装BeautifulSoup4(以下简称BS4)版本。如果使用Windows系统,大家可通过下载源码的方式安装,下载地址为:https://pypi.python.org/pypi/beautifulsoup4/,选择“Download files”下载后缀名为“.tar.gz”后解压,使用命令行进入解压后的文件中,执行如下命令即可安装成功:

  python setup.py install

  对于Mac系统,可以通过pip包管理器(一个Python包管理工具)来安装,首先需要通过命令安装该管理器,命令如下:

  sudo easy_install pip

  注意Mac系统中自带Python2版本,当使用pip包管理器将BS4安装到Python3下时,安装命令如下:

  pip3 install beautifulsoup4

  至此BS4库安装完成,下面讲解它的用法。

  2.4.2 BeautifulSoup的使用

  下面通过一个示例示范BeautifulSoup的简单使用,现有一段格式不良好的HTML内容,需要用BeautifulSoup确定其格式。

  首先导入BS4库,接着创建HTML代码的字符串,最后创建BeautifulSoup对象。以下字符串“html_doc”中是需要确定格式的HTML内容,使用BeautifulSoup处理的具体代码如下所示:

from bs4 import BeautifulSoup
html_doc ="""
<html><head><title>The Dormouse's story</title></head>
<body>
<!--注释-->
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">
Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body>
</html>
"""
# 通过字符串html_doc创建BeautifulSoup对象
soup = BeautifulSoup(html_doc,'html.parser')
# 格式化输出
print(soup.prettify())


  运行示例代码后,输出结果如下所示:


html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <!--注释-->
  <p class="title">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister" href="http://example.com/elsie" id="link1">
    Elsie
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>

  从上面的输出结果中可以看出,BeautifulSoup正确补全缺失的标签并格式化该HTML文档。

  此外,通过文件也可以创建BeautifulSoup对象,将字符串html_doc中的内容保存为index.html文件,具体创建方法如下所示:

  # 通过index.html文件创建BeautifulSoup对象

  soup = BeautifulSoup(open('index.html','html.parser'))

  BeautifulSoup将复杂HTML文档转换为一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag、NavigableString、BeautifulSoup、Comment。

  下面还是通过一个示例简单示范这四种对象的使用,具体代码如例2-12所示。

  【例2-12】

  1 from bs4 import BeautifulSoup
  2 html_doc = """
  3
  4
  5
  6
  7
  The Dormouse's story
  8
  Once upon a time there were three little sisters;
  9 and their names were
  10 Elsie,
  11 Lacie and
  12 Tillie;
  13 and they lived at the bottom of a well.
  14
  ...
  15 """
  16 soup = BeautifulSoup(html_doc, 'html.parser')
  17 tag = soup.title # 获取标签title
  18 string = tag.string # 获取title的文字内容
  19 comment = soup.b.string # 获取 b标签的注释文字内容
  20 print type(soup) #
  21 print type(tag) #
  22 print type(string) #
  23 print type(comment) #

  上面示例简单示例了这四种对象的用法,关于BeautifulSoup的其他使用方法可参考其官方文档,地址为“https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/”。

  2.5 本章小结

  本章主要介绍了在爬虫开发中经常用到的知识,首先介绍了Cookie的概念以及在爬虫中的应用,以及Python中正则表达式的用法,接着介绍了网络爬虫所需掌握的Web基础知识,包括HTML标签、XML、JSON数据格式等。除了掌握上述三个知识点外,大家更要重点掌握BeautifulSoup模块的使用方法。

  2.6 习题

  1.填空题

  (1) 是服务器在本地机器上存储的小段文本并随每一个请求发送至服务器。

  (2) 标签的作用是 。

  (3)

  标签的作用是 。

  (4) 是一种XML路径语言,被用于在XML文档中通过元素和属性进行导航。

  (5) 写一个JSON体数据 。

  2.选择题

  (1) Cookie存储在( )。

  A.服务端 B.代理层

  C.客户端 D.消息队列

  (2) XML是( )。

  A.数据体 B.逻辑代码

  C.语言 D.超文本传输协议

  (3) 下列选项中,( )属于JSON体格式。

  A.{“name”:”codingke”} B.[‘time’:’2017’]

  C.{‘age’:18} D.(1,2)

  (4) 下列数据中,( )可以使用BeautifulSoup提取。

  A.tuple B.xml

  C.dict D.int

  (5) 对于bytes数据,如何解码为”utf-8”格式( )。

  A.encode(‘utf-8’) B.decode(“utf-8”)

  C.encode(utf8) D.decode(utf8)

  3.思考题

  (1) 简述Cookie的工作方式。

  (2) 简述BeautifulSoup的含义以及如何使用。

  4.编程题

  编写程序使用BeautifulSoup从下面HTML文档中获取所有文字,HTML内容如下。

  The Dormouse's story

  Once upon a time there were three little sisters; and their

  names were

  Elsie,

  Lacie and

  Tillie;

  and they lived at the bottom of a well.

  ...

  Tip:使用BeautifulSoup对象的get_text()方法。

上一篇:HTML5工具初识之网页编辑器

下一篇:认识HTML

QQ技术交流群

千锋Python官方①群
790693323

加入群聊