2.网页解析
2.1.网页解析概述
除了学会向服务器发出请求、下载HTML源码,要获取结构化的数据还面临一个最常见的任务,就是从HTML源码中提取数据。
三种方法:
- 正则表达式
- lxml库
- BeautifulSoup
针对文本的解析, 用正则表达式
针对html/xml的解析, 有Xpath、 BeautifulSoup、 正则表达式
针对JSON的解析, 有JSONPath
几种解析网页技术的区别
- 正则表达式基于文本的特征来匹配或查找指定的数据,可以处理任何格式的字符串文档,类似于模糊匹配的效果(re模块支持正则表达式语法的使用)
- XPath和BeautifulSoup基于HTML/XML文档的层次结构来确定到达指定节点的路径,更适合出层级比较明显的数据
- JSONPath专门用来JSON文档的数据解析
- lxml库支持XPath语法的使用
- json模块支持JSONPath语法的使用
- BeautifulSoup本身就是一个Python库,是官方推荐的使用方法
2.2. XPath语法和lxml模块
-
xpath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历。
-
选取节点
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似,代表着从一个节点到另一个或者一组节点的顺序,并以“/”字符进行分隔
2.2.1. XPath语法
-
选取节点
节点是按照路径选取的,既可以从根节点开始,也可以从任意位置开始
表达式 说明 nodename 选取此节点的所有子节点 / 从根节点选取 // 从匹配选择的当前节点选取文档中的节点,而不用考虑它们的位置 . 选取当前节点 . . 选取当前节点的父节点 @ 选取属性 -
谓词
谓词指的是路径表达式的附加条件,用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中,表示对节点进行进一步筛选,用于查找某个特定节点或者包含某个指定值的节点。
格式:
元素[表达式]
表达式 说明 /bookstore/book[1] 选取bookstore子元素的第一个book元素 /bookstore/book[last()] 选取bookstore子元素的最后一个book元素。 bookstore/book[position() < 3] 选取最前面的两个属于bookstore元素的子元素的book元素。 //book[@price] 选取拥有price属性的book元素 //book[@price=10] 选取所有属性price等于10的book元素 -
选取未知节点
表示通配符,Xpath用选取未知的节点
表达式 说明 * 匹配任何元素节点 @* 匹配节点中的任何属性 -
选取若干路径
通过在路径表达式中使用“|”运算符,可以选取若干个路径。
如:
//bookstore/book | //book/title # 选取所有book元素以及book元素下所有的title元素
2.2.2. 插件的下载
- XPath Helper : Chrome浏览器插件
- Try Xpath : FireFox 插件
2.3. lxml 库
lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。
lxml和正则一样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器,我们可以利用之前学习的XPath语法,来快速的定位特定元素以及节点信息。
-
文档:lxml python 官方文档:http://lxml.de/index.html
-
依赖:需要安装C语言库
-
安装方式:可使用 pip 安装:pip install lxml
2.3.1. 基本使用
-
我们可以利用他来解析HTML代码,并且在解析HTML代码的时候,如果HTML代码不规范,他会自动的进行补全
-
使用 lxml 的 etree 库 from lxml import etree
-
python 3.5后的lxml模块中不能再直接引入etree模块,需要使用以下方法引用
from lxml import html
etree=html.etree
2.3.2. 从字符串或文件中解析XML
为了能够将XML文件解析为树结构,etree模块提供了如下3个函数:
- fromstring()
- XML()
- HTML()
- XML()函数的行为类似于fromstring()函数,通常用于将XML字面量直接写入到源码中,HTML()函数可以自动补全缺少的
<html>
和<body>
标签
还可以调用parse()函数从XML文件中直接解析,在调用函数时,如果没有提供解析器,则使用默认的XML解析器,函数会返回一个ElementTree类的对象。
HTML文件不规范时,则需要自己指定解析器parser=etree.HTMLParser() htmlEle=etree.parse(文件名,parser=parser)
对于Element对象,使用tostring()函数,将元素序列化为XML树的编码字符串表示形式
2.3.3.lxml库的相关类
- Element类: XML的结点
- ElementTree类: 一个完整的XML文档树
- ElementPath类: 可以理解为Xpath, 用于搜索和定位节点
①Element类
-
节点操作
root=etree.Element(“book”)
-
节点属性操作
a.root=etree.Element(“book”, interesting=‘totally’)
b. root.set(‘age’,‘30’)
-
节点内文本的操作:通过text、tail属性或者xpath()方法来访问文本内容
②ElementPath类
- 在ElementTree或者Element中,使用如下3个方法,可以满足搜索和查询需求,这3个方法的参数都是XPath语句
- find()方法:返回匹配的第一个子元素
- findall()方法:以列表形式返回所有匹配的子元素
- iterfind()方法:返回一个所有匹配元素的迭代器html=etree.HTML(text)alist=html.findall(".//a[@href]")for a in alist: print(a.text)
2.3.4. lxml中使用XPath语法
-
使用lxml库中的路径表达式技巧,通过调用xpath()方法匹配选取的节点
-
1.获取所有li标签html.xpath(“//li”)
2.获取所有li元素下的所有class属性的值
aattr=html.xpath("//li/@class")
-
3.获取li标签下href为www.baidu.com的a标签
alist=html.xpath("//li/a[@href=‘www.baidu.com’]")
-
4.获取最后一个li的a的href属性对应的值
aattr=html.xpath("//li[last()]/a/@href")
-
5.获取倒数第二个li元素的内容
(1)t=html.xpath("//li[last()-1]/a") t[0].text
(2)t=html.xpath("//li[last()-1]/a/text()")
2.3.5. 案例: 使用requests+lxml 爬取电影天堂
from<