xpath学习之路-01xpath语法

2,847次阅读
一条评论

前言:

最近有个项目,需要用一个通用化的html提取规则,之前是使用bs4的,但是考虑到bs4的速度慢和规则繁琐,就想弃坑。同时正则也是可以提取

xpath(XML Path Language)重要吗,那是肯定的,因为这是一套标准,类似于是正则表达式,起初是 XML 路径语言,用于对元素和属性进行查找,而且解析速度超级快。

看到这里,你就知道了,为什么我要学习 xpath 了,因为爬虫中最重要的就是数据提取。Python中的主流的提取库有:

  • BeautifulSoup(bs4):美丽汤,语法多,文档完善。缺点:速度慢,因为是建立在别的解析器的基础上的封装。
  • lxml:支持xpath中的部分语法,并有额外的功能
  • re:正则,适用于少量数据提取。

另外有网友对比了 bs4 和 lxml 的解析速度,发现还是 lxml 最快最方便,所以我选择系统的学习xpath语法和lxml库。

xpath的语法扫盲:

下面我将从一个初学者的角度来写文章,

1、 xpath节点

xpath中的有七种节点有:元素、属性、文本、命名空间、处理指令、评论、文档节点。通常把 xml 的代码看做是节点树,里面的所有内容都可以看做是节点,这样就利于数据的提取。

<bookstore>

  <book>
    <title>Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>

</bookstore>

1.1 父节点(Parent)

其实是相对而言的,比如 titleyear 的父节点就是book,而book的父节点就是bookstore

1.2 孩子节点

一个节点的孩子节点可以有很多,比如 book 节点的子节点有:title、author、year、price

1.3 兄弟节点(Sibling)

比如:title、author、year、price都是兄弟节点

1.4 祖先节点(Ancestor)

节点的父节点,以及父节点的父节点,父节点的父节点,依次类推都是祖先,说直白点就是该节点上的所有父节点都是被称为:祖先节点。

1.5 后代节点(Descendant)

某个节点的所有后代子节点,子节点以及子节点的子节点依次类推。比如 bookstore 的所有所有字节就有:book、title、author、year、price。

2、xpath语法:

2.1 选取节点

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点开始取元素
// 从当前匹配的节点后选择节点,不考虑位置
. 选取当前节点
.. 选取当前节点的父节点
@ 取节点的属性

说实在的上面的解释确实抽象,尤其是第一次学习的时候,所以建议配合下面的xpath实战例子进行理解。

1)实战例子:

光说不练假把式,下面请看实际例子。我以网页:https://www.w3cschool.cn/xpath/xpath-syntax.html作为例子,使用xpath

/> /> /> /> /> />
路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。xpath学习之路-01xpath语法
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!xpath学习之路-01xpath语法
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。例如下面的xpath学习之路-01xpath语法
//book 选取所有 book 子元素,而不管它们在文档中的位置。xpath学习之路-01xpath语法
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。xpath学习之路-01xpath语法
//@lang 选取名为 lang 的属性的所有节点。例如,这里面我是://@class:表示选取所有带有class 属性的节点,返回的结果是 class 属性对应的属性值。xpath学习之路-01xpath语法

2.2 xpath谓语

按照谓语的字面意思就是,具有动作的xpath语法,比如取某个节点的孩子节点中的第3个、取 class=“test”的 div 节点等。前面学习的选取语法就做不到了,需要使用谓语进行筛选结果。

谓语都是放在[]中,具有筛选作用。

<bookstore>

  <book price="45">
    <name>book1</name>
    <title class="book1_title">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29</price>
  </book>
  <book price="68">
    <name>book2</name>
    <title class="book2_title">Harry Potter02</title>
    <author>J K. Rowling02</author>
    <year>2005 02</year>
    <price>68</price>
  </book>

</bookstore>

下面表格中的结果,我以

路径表达式 含义 结果
/bookstore/book[1]或者//book[1] 取bookstore的子节点中第一个 book 元素。[index],index是索引号,从1开始。 book1
/bookstore/book[last()] 取bookstore的子节点中最后一个 book 元素。last()表示最后一个元素 book2
/bookstore/book[last()-1] 取bookstore的子节点中倒数第二个 book 元素。last()-index,表示取倒数第index个元素。 book1
/bookstore/book[positon()<2] 取bookstore的子节点中位置序号小于2 book 元素。position()是位置序号,从1开始,positon()<2=1,positon()>2=3, 4, …… book1
/name[@lang] 表示所有拥有名为 lang 的属性的 name 节点。例如:/name[@class],则结果为:book1和book2
/name[@lang=“ch”] 选取所有名为 lang 的属性,且值为 ch 的 name 节点。例如:/name[@class=“book1_title”],则结果为:book1
/bookstore/book[price>30] 选取 bookstore 下所有 book 节点中,其中book的子节点 price 的值大于30。 book1, book2
/bookstore/book[price>30]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 30。

其他用法:

通配符 描述
* 匹配任何节点。比如://book[1]/*,表示匹配到第一个 book 节点下的所有节点,结果:name、title、price、author、year
@* 匹配任何属性节点。比如://name[@*],表示所有带有属性的 name 节点。
node() 匹配任何类型的节点。比如://book/node(),结果:name、title、price、author、year

2.3 xpath轴

总结:

参考链接:

https://www.w3schools.com/xml/xpath_intro.asp

https://learnku.com/articles/50459

5
西园公子
版权声明:本站原创文章,由西园公子2021-07-07发表,共计2943字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(一条评论)
载入中...
西园公子 博主
2021-09-14 16:34:19 回复

:smile: