在上⼀课中我们讲到了使⽤Python
获取⽹络资源,如果我们获取到⼀个或多个⻚⾯,需要从⻚⾯中提取出指定的信息,⾸先得掌握解析HTML
⻚⾯的技术。上⼀课中我们把整个
HTML
⻚⾯当成⼀个字符串,使⽤正则表达式的捕获组提取出了需要的内容。但是,写出⼀个正确的正则表达式经常也是⼀件让⼈头疼的事情。为此,我们可以先了解HTML
⻚⾯的结构,在此基础上就可以掌握其他的解析
HTML
⻚⾯的⽅法。
HTML
⻚⾯的结构
我们在浏览器中打开任意⼀个⽹站,然后通过⿏标右键菜单,选择“
显示⽹⻚源代码
”
菜单项,就可以看到⽹⻚对应的HTML
代码。
![](https://img-blog.csdnimg.cn/fe5eb5fe5ad541c2a43acdc4fe486dde.png)
代码的第1
⾏是⽂档类型声明,第
2
⾏的
<html>
标签是整个⻚⾯根标签的开始标签,最后⼀⾏是根标签的结束标签 </html>
。
<html>
标签下⾯有两个⼦标签
<head>
和
<body>
,放在
<body>
标签下的内容会显示在浏览器窗⼝中,这部分内容是⽹⻚的主体;放在 <head>
标签下的内容不会显示在浏览器窗⼝中,但是却包含了⻚⾯重要的元信息,通常称之为⽹⻚的头部。HTML
⻚⾯⼤致的代码结构如下所示。
<!doctype html>
<html>
<head>
<!-- ⻚⾯的元信息,如字符编码、标题、关键字、媒体查询等 -->
</head>
<body>
<!-- ⻚⾯的主体,显示在浏览器窗⼝中的内容 -->
</body>
</html>
标签、层叠样式表(
CSS
)、
JavaScript
是构成
HTML
⻚⾯的三要素,其中标签⽤来承载⻚⾯要显示的内容,CSS
负责对⻚⾯的渲染,⽽
JavaScript
⽤来控制⻚⾯的交互式⾏为。对
HTML
⻚⾯的解析可以使⽤⼀种名为XPath
的语法,根据
HTML
标签的层次结构提取标签中的内容或标签属性;除此之外,也可以使⽤CSS
选择器来定位⻚⾯元素,如果不清楚什么是
CSS
选择器,可以移步到我的
《
Web
前端概述》
⼀⽂进⾏了解。
XPath
解析
XPath
是在
XML
(
eXtensible Markup Language
)⽂档中查找信息的⼀种语法,
XML
跟
HTML
类似也是⼀种⽤标签承载数据的标签语⾔,不同之处在于XML
的标签是可扩展的,可以⾃定义的,⽽且
XML
对语法有更严格的要求。XPath
使⽤路径表达式来选取
XML
⽂档中的节点或者节点集,这⾥所说的节点包括元素、属性、⽂本、命名空间、处理指令、注释、根节点等。下⾯我们通过⼀个例⼦来说明如何使⽤XPath对⻚⾯进⾏解析。
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
对于上⾯的
XML
⽂件,我们可以⽤如下所示的
XPath
语法获取⽂档中的节点。
![](https://img-blog.csdnimg.cn/94c21815d4d841f68c1284018cdb50bb.png)
XPath还⽀持通配符⽤法,如下所示。
如果要选取多个节点,可以使⽤如下所示的⽅法。
说明
:上⾯的例⼦来⾃于
“
菜⻦教程
”
⽹站上的
XPath
教程
,有兴趣的读者可以⾃⾏阅读原⽂。
当然,如果不理解或不熟悉
XPath
语法,可以在浏览器的开发者⼯具中按照如下所示的⽅法查看元素的XPath语法,下图是在
Chrome
浏览器的开发者⼯具中查看⾖瓣⽹电影详情信息中影⽚标题的
XPath
语法。
![](https://img-blog.csdnimg.cn/3f91eabcbe864eca90d98f12e1d1669a.png)
实现XPath解析需要三⽅库 lxml 的⽀持,可以使⽤下⾯的命令安装 lxml 。
pip install lxml
下⾯我们⽤XPath解析⽅式改写之前获取⾖瓣电影Top250的代码,如下所示。
import random
import time
from lxml import etree
import requests
for page in range(1, 11):
resp = requests.get(
url=f'https://movie.douban.com/top250?start={(page - 1) * 25}',
headers={
'User-Agent': 'BaiduSpider',
}
)
tree = etree.HTML(resp.text)
# 通过XPath语法从⻚⾯中提取需要的数据
spans = tree.xpath('//*
[@id="content"]/div/div[1]/ol/li/div/div[2]/div[1]/a/span[1]')
for span in spans:
print(span.text)
time.sleep(random.randint(1, 3))
CSS
选择器解析
对于熟悉
CSS
选择器和
JavaScript
的开发者来说,通过
CSS
选择器获取⻚⾯元素可能是更为简单的选择,因为浏览器中运⾏的JavaScript
本身就可以
document
对象的
querySelector()
和
querySelectorAll() ⽅法基于CSS
选择器获取⻚⾯元素。在
Python
中,我们可以利⽤三⽅库
bs4
(
BeautifulSoup
)或 pyquery
来做同样的事情。
BeautifulSoup
可以⽤来解析
HTML
和
XML
⽂档,修复含有未闭合标签等错误的⽂档,通过为待解析的⻚⾯在内存中创建⼀棵树结构,实现对从⻚⾯中提取数据操作的封装。可以⽤下⾯的命令来安装BeautifulSoup
。
pip install beautifulsoup4
下⾯是使⽤
bs4
改写的获取⾖瓣电影
Top250
电影名称的代码。
import random
import time
import bs4
import requests
for page in range(1, 11):
resp = requests.get(
url=f'https://movie.douban.com/top250?start={(page - 1) * 25}',
headers={
'User-Agent': 'BaiduSpider',
}
)
soup = bs4.BeautifulSoup(resp.text, 'lxml')
# 通过CSS选择器从⻚⾯中提取需要的数据
spans = soup.select('div.info > div.hd > a > span:nth-child(1)')
for span in spans:
print(span.text)
time.sleep(random.randint(1, 3))
关于
BeautifulSoup
更多的知识,可以参考它的
官⽅⽹站
。
简单的总结
下⾯我们对三种解析⽅式做⼀个简单⽐较。
![](https://img-blog.csdnimg.cn/7487df99cec04c209cb0968dcc0a5910.png)