XPath
Xpath是一门在XML文档中查找信息的语言,被用于在XML文档中通过元素和属性进行导航。XPath虽然是被设计用来搜寻XML文档,不过它也能很好的在HTML文档中工作,并且大部分浏览器也支持通过XPath来查询节点经常使用XPath查找提取网页中的信息。
XPath既然叫Path,就是以路径表达式的形式还指定元素,这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。由于XPath一开始是用来搜寻XML文档的,所以接下来就以XML文档为例子来讲解XPath。
1.XPath节点
在XPath中,XML文档是被作为节点树来对待的,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。树的根被称为文档节点或者根节点。以下面的XML文档为例进行说明,文档如下:
<xml version="1.0" encoding="ISO-8859-1"> <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> </classroom>
上面的XML文档中的节点例子包括:<classroom>(文档节点)、<id>1001</id>(元素节点)、lang=“en”(属性节点)、marry(文本)。
接着说一下节点关系,包括父(Parent)、子(Children)、同胞(Sibling)、先辈(Ancestor)、后代(Descendant)。在上面的文档中:
·student元素是id、name、age以及country元素的父。
·id、name、age以及country元素都是student元素的子。
·id、name、age以及country元素都是同胞节点,拥有相同的父节点。
·name元素的先辈是student元素和classroom元素,也就是此节点的父、父的父等。
·classroom的后代是id、name、age以及country元素,也就是此节点的子,子的子等。2.XPath语法
2.XPath语法
XPath使用路径表达式来选取XML文档中的节点或节点集。节点是沿着路径(path)或者步(steps)来选取的。接下来的重点是如何选取节点,下面给出一个XML文档进行分析:
<xml version="1.0" encoding="ISO-8859-1"> <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> <student> <id>1002</id> <name lang="en">jack</name> <age>25</age> <country>USA</country> </student> </classroom>
首先列举出一些常用的路径表达式进行节点的选取:
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点 |
| / | 从根节点选取 |
| // | 选择任意位置的某个节点 |
| . | 选取当前节点 |
| .. | 选取当前节点的父节点 |
| @ | 选取属性 |
通过上表中的表达式,尝试着对上面的文档进行节点选取。以表格的形式说明。
| 实现效果 | 路径表达式 |
|---|---|
| 选取classroom元素的所有子节点 | classroom |
| 选取根元素classroom | /classroom |
| 选取属于classroom的子元素的所有student元素 | classroom/student |
| 选取所有student子元素,而不管他们在文档中的位置 | //student |
| 选取classroom元素的后代的所有student元素,而不管它们在classroom之下的什么位置 | classroom//student |
| 选取名为lang的所有属性 | //@lang |
上面选取的例子最后实现的效果都是选取了所有符合条件的节点,是否能选取某个特定的节点或者包含某一个指定的值的节点呢?这就要用到谓语,谓语被嵌套在方括号中,如下表:
| 实现效果 | 路径表达式 |
|---|---|
| 选取属于classroom子元素的第一个student元素 | /classroom/student[1] |
| 选取属于classroom子元素的最后一个student元素 | /classroom/student[last()] |
| 选取属于classroom子元素的倒数第二个student元素 | /classroom/student[last() 1] |
| 选取最前面的两个属于classroom元素的子元素的student元素 | /classroom/student[position()<3] |
| 选取所有拥有名为lang的属性的name元素 | //name[@lang] |
| 选取所有name元素,且这些元素拥有值为en的lang属性 | //name[@lang="en"] |
| 选取classroom元素的所有student元素,且其中的age元素的值须大于20 | /classroom/student[age>20] |
| 选取classroom元素中的student元素的所有name元素,且其中的age元素的值须大于20 | /classroom/student[age>20]/name |
XPath在进行节点选取的时候可以使用通配符“*”匹配未知的元素,同时使用操作符“|”一次选取多条路径,如下表:
| 实现效果 | 路径表达式 |
|---|---|
| 选取classroom元素的所有子元素 | /classroom/* |
| 选取文档中的所有元素 | //* |
| 选取所有带有属性的name元素 | //name[@*] |
| 选取student元素的所有name和age元素 | //student/name | //student/age |
| 选取属于classroom元素的student元素的所有name元素,以及文档中所有的age元素 | /classroom/student/name | //age |
3.XPath轴
轴定义了所选节点与当前节点之间的树关系。在Python爬虫开发中,提取网页中的信息会遇到这种情况:首先提取到一个节点的信息,然后想在在这个节点的基础上提取它的子节点或者父节点,这时候就会用到轴的概念。轴的存在会使提取变得更加灵活和准确。
在说轴的用法之前,需要了解位置路径表达式中的相对位置路径、绝对位置路径和步的概念。位置路径可以是绝对的,也可以是相对的。绝对路径起始于正斜杠(/),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:/step/step/……(绝对位置路径),step/step/……(相对位置路径)。
(step)包括:轴(axis)、节点测试(node-test)、零个或者更多谓语(predicate),用来更深入地提炼所选的节点集。步的语法为:轴名称:节点测试[谓语],大家可能觉比较抽象,通过之后的示例分析,会明白如何使用它。
XPath轴中使用的节点集:
| 轴名称 | 含义 |
|---|---|
| child | 选取当前节点的所有子元素 |
| parent | 选取当前节点的父节点 |
| ancestor | 选取当前节点的所有先辈 |
| ancestor-or-self | 选取当前节点的所有先辈以及节点本身 |
| descendent | 选取当前节点的所有后代元素 |
| descendent-or-self | 选取当前节点的所有后代元素以及元素本身 |
| preceding | 选取文档中当前节点的开始标记之前的所有节点 |
| following | 选取文档中当前节点的结束标记之后的所有节点 |
| preceding-sibling | 选取当前节点之前的所有同级节点 |
| following-sibling | 选取当前节点之后的所有同级节点 |
| self | 选取当前节点 |
| attribute | 选取当前节点的所有属性 |
| namespace | 选取当前节点的所有命名空间节点 |
首先给出一个XML文档,实例分析就按照这个文档来进行,文档如下:
<xml version="1.0" encoding="ISO-8859-1"> <classroom> <student> <id>1001</id> <name lang="en">marry</name> <age>20</age> <country>China</country> </student> <student> <id>1002</id> <name lang="en">jack</name> <age>25</age> <country>USA</country> </student> <teacher> <classid>1</classid> <name lang="en">tom</name> <age>50</age> <country>USA</country> </teacher> </classroom>
针对上面的文档进行示例演示:
| 实现效果 | 路径表达式 |
|---|---|
| 选取当前classroom节点中子元素的teacher节点 | /classroom/child::teacher |
| 选取所有id节点的父节点 | //id/parend::* |
| 选取所有以classid为子节点的祖先节点 | //classid/ancestor::* |
| 选取classroom节点下所有的后代节点 | /classroom/descendent::* |
| 选取所有以student元素为父节点的id元素 | //student/descendent::id |
| 选取classid元素的祖先节点及本身 | //classid/ancestor-or-self::* |
| 选取/classroom/student本身及所有后代元素 | /classroom/student/descendent-or-self::* |
| 选取/classroom/teacher之前的所有同级节点 | /classroom/teacher/preceding-sibling::* |
| 选取classroom中第二个student之后的所有同级节点 | /classroom/student[2]/following-sibling::* |
| 选取/classroom/teacher/节点所有之前的节点(除其祖先外),不仅仅是student节点,还有里面的子节点 | /classroom/teacher/preceding::* |
| 选取/classroom中第二个student之后的所有节点,结果就是选取了teacher节点及其子节点 | /classroom/student[2]/following::* |
| 选取student节点本身 | //student/self::* |
| 选取/classroom/teacher/name节点下的所有属性 | /classroom/teacher/name/attribute::* |
4.XPath运算符
XPath表达式可返回节点集、字符串、逻辑值以及数字。下表列举了可用在XPath表达式中的运算符。
| 运算符 | 描述 | 实例 | 含义 |
|---|---|---|---|
| | | 计算两个节点 | //student/name | //student/age | 选取student元素的所有name和age元素 |
| + | 加法 | /classroom/student[age=19+1] | 选取classroom元素所有age等于20的student元素 |
| - | 减法 | /classroom/student[age=21-1] | 选取classroom元素所有age等于20的student元素 |
| * | 乘法 | /classroom/student[age=4*5] | 选取classroom元素所有age等于20的student元素 |
| div | 除法 | /classroom/student[age=40 div 2] | 选取classroom元素所有age等于20的student元素 |
| = | 等于 | /classroom/student[age=20] | 选取classroom元素所有age等于20的student元素 |
| != | 不等于 | /classroom/student[age!=20] | 选取classroom元素所有age不等于20的student元素 |
| < | 小于 | /classroom/student[age<20] | 选取classroom元素所有age小于20的student元素 |
| <= | 小于等于 | /classroom/student[age<=20] | 选取classroom元素所有age小于等于20的student元素 |
| or | 或 | /classroom/student[age25] | 选取classroom元素所有age小于20或大于25的student元素 |
| and | 与 | /classroom/student[age>20 and age<25] | 选取classroom元素所有age大于20且小于25的student元素 |
| mod | 计算除法的余数 | 5 mod 2 | 1 |

浙公网安备 33010602011771号