XPATH、CSS选择器及正则表达式

在爬虫采集数据的过程中,如何定位及匹配数据是必须解决的一项任务。最常用的定位方式有三种:XPATH,CSS选择器及正则表达式。以下我们来系统的学习他们。

一、XPATH 语法

参考文档:XPATH教程 from runoob

1. Xpath是什么

XPath是一个W3C标准,可以供XSLT、XPointer以及其他XML解析软件使用;它包含一个标准函数库;使用路径表达式在XML文档中进行导航。在爬虫学习中,我们最需要了解的就是最后一项:如何使用XPath路径表达式进行导航。在此之前,首先让我们学习下XPath的基本概念之一:节点。

2. XPath节点及相关

XPath中有七种类型的节点:元素,属性,文本,命名空间,处理指令,注释以及文档(根)节点。除了节点之外,还有基本值(Atomic value)的概念。

基本值:无父或无子的节点。从定义上看,基本值是一种特殊节点,常见于文本。

项目(Item):基本值或者节点。

XML是被作为文档树来对待的,也因此会涉及根节点、父子节点等概念,下面让我们总结下节点关系。

3. XPath节点关系

父(Parent): 每个元素或属性都有一个父,即其直接上级节点。

子(Children):元素节点可以有0、1或多个子,即其直接下级节点。

兄弟(Sibling):拥有相同的父的节点或节点集合。

先辈(Ancestor):某节点的父,父的父,以此类推十八代(虚指)。

后代(Descendant):某节点的子,子的子,以此类推。

了解了基本概念,接下来是语法。

4. XPath语法

4.1 节点选取

nodename 选取当前节点的所有nodename子节点;

/ 从根节点选取,即绝对路径;

// 从当前节点选取,即相对路径;

. 选取当前节点;

.. 选取当前节点的父节点;

@ 选取属性。

4.2 谓语(Predicates)

结合实例解释如下:

/bookstore/book[1] 选取bookstore子元素的第一个book元素;

/bookstore/book[last()] 选取bookstore子元素的最后一个book元素;

/bookstore/book[position()<3] 选取bookstore元素的前两个book元素;

*之前提到XPath中包含一个标准函数库;last()和position()就是其中常见的例子。

//title[@lang] 选取拥有lang属性的title元素;

//title[@lang='eng'] 选取lang属性为'eng'的title元素;

/bookstore/book[price>35.00] 选取bookstore元素中的所有book元素,且其中的price元素大于35.00。

4.3 通配符

* 匹配任何元素节点; @*匹配任何属性节点;node()匹配任何类型的节点。

4.4 路径组合

//book/title | //book/price 选取book元素的所有title和price元素。

之前我们介绍了节点关系的概念,那么如何利用节点关系来定位节点呢,请看XPath轴。

5. XPath轴(Axes)

ancestor 选取当前节点的所有先辈;

ancestor-or-self 选取当前节点及其所有先辈;

descendant 选取当前节点的所有后辈;

descendant-or-self 选取当前节点及其所有后辈;

parent 选取当前节点的父节点;

child 选取当前节点的子节点;

following 选取当前节点之后的所有节点;

following-sibling 选取当前节点之后的所有兄弟节点;

preceding 选取当前节点之前的所有节点;

preceding-sibling 选取当前节点之前的所有兄弟节点;

self 选取当前节点;

attribute 选取当前节点所有属性;

namespace 选取当前节点的所有命名空间节点。

用法,比如要查找<a>元素之后的<span>元素,使用'//a/following::span'。

6. XPath运算符

| 计算两个节点集;

+ - * div mod加减乘除求余;

= != < <= > >= 比较;

or and 或与。

二、CSS选择器语法

参考资料:CSS选择器 from w3school

在定位元素时,CSS选择器和XPath经常可以相互替代。常用的CSS选择器如下:

.class 根据class属性选择元素;

#id 根据id属性选择元素;

* 选择所有元素;

element 选择所有element元素;

element,element1 选择所有element及element1元素;

element element1 选择element内部的所有element1元素;

element>element1 选择element的element1子元素;

element+element1 选择紧接在element之后的element1元素;

[attribute] 选择带有attribute属性的所有元素;

[attribute=value] 选择attribute属性值为value的所有元素;

[attribute~=value] 选择attribute属性值包含value的所有元素;

[attribute|=value] 选择attribute属性值以value开头的所有元素;

a:link 选择所有未被访问的链接;a:visited 选择所有已被访问链接;a:hover 选择活动链接;

element:focus 选择获得焦点的element元素;

element:first-letter 选择element元素首字母;element:first-line 选择element元素首行;

element:first-child 选择属于element父元素的第一个子元素的每个element元素;

element:lang(language) 选择带有以language开头的lang属性值得每个element元素;

ele1~ele2 选择前面有ele1元素的每个ele2元素;

ele[attribute^=value] 选择attribute属性值以value开头的每个ele元素;

ele[attribute$=value] 选择attribute属性值以value结尾的每个ele元素;

ele[attribute*=value] 选择attribute属性值包含value的每个ele元素;

ele:first-of-type 选择属于其父元素的首个ele元素的每个ele元素;

ele:last-of-type 选择属于其父元素的最后ele元素的每个ele元素;

ele:only-of-type 选择属于其父元素唯一的ele元素的每个ele元素;

ele:only-child 选择属于其父元素的唯一子元素的每个ele元素;

ele:nth-child(n) 选择属于其父元素的第n个子元素的每个ele元素;

ele:nth-last-child(n) 选择属于其父元素的倒数第n个子元素的每个ele元素;

ele:nth-of-type(n) 选择属于其父元素的第n个元素的每个ele元素;

ele:nth-last-of-type(n) 选择属于其父元素的倒数第n个元素的每个ele元素;

ele:last-child 选择属于其父元素最后一个子元素的每个ele元素;

:root 选择文档根元素;

ele:empty 选择没有子元素的每个ele元素;

ele:target 选择当前活动的ele元素;

ele:enabled 选择每个启用的ele元素;ele:disabled 选择每个禁用的ele元素;

ele:checked 选择每个被选中的ele元素;

:not(selector) 选择非selector的每个元素;

::selection 选择被用户选取的元素部分。

三、正则表达式语法

参考教程:正则表达式 from runoob

当我们使用word或text之类的办公软件时,经常用到搜索和筛选来定位查找词语。这个功能很便利,但是它的不足之处也很明显。其中之一就是:作为过滤器的模式非常有限。相比之下,正则表达式可以实现前者的所有工作,而且更加强大和灵活。下面让我来看看,它是如何做到这一点的。

1. 正则表达式记号

普通字符 大小写字母,所有数字,所有标点和一些其他字符(如非打印字符)。

非打印字符 

\cx 匹配由x指明的控制字符;x的值必须为A-Za-z之一;否则c将被视为字母c;

\f 匹配换页符;\n 匹配换行符;\r 匹配回车符; \s 匹配任何空白字符,包括空格、制表符、换页符等;\S 匹配任何非空白字符;\t 匹配任何制表符;\v 匹配垂直制表符。

特殊字符

^ 匹配开始位置,在方括号中时,表示否定,即不接受该字符集合;$ 匹配结尾位置;

* 匹配前面的子表达式0或多次; + 匹配前面的子表达式1或多次;

? 匹配前面的子表达式0或1次,或指定一个非贪婪限定符;

. 匹配除换行符\n之外的任何单字符;

\ 转义字符;

| 指明两项之间的其中一个。

() 标记一个子表达式的开始和结束位置。子表达式可以获得,供以后使用;

[] 标记一个中括号表达式的开始;

{ } 标记限定符表达式的开始;

限定符

* + ? 见特殊字符

{n} 匹配确定的n次;{n,} 至少匹配n次;{n,m} 匹配n到m次。

定位符

^ $ 见特殊字符

\b 匹配字边界(字与空格间的位置);\B 非字符边界

子表达式

前面提到,()可以标记一个子表达式,且该表达式可以被捕获缓存。如果这并不是你想要的,那么可以使用?:消除这种副作用,即将子表达式标记为非捕获元。

除此之外,还有另外两个很重要的非捕获元?=和?!,前者称为正向预查,后者称为反向预查。两者还经常被称为零宽断言(正向、反向);此外还有逆序正向预查和逆序反向预查。

正向预查(?=exp) a. 当单词同时满足前部匹配条件和exp时,返回前部匹配; b. exp非捕获

举例: \b\w+(?=ing\b)  输入 singing and dancing 输出 sing和danc

反向预查(?!exp) a. 当单词满足前部匹配条件且不满足exp时,返回前部匹配,b. exp非捕获

逆序正向预查(?<=exp) a. 当单词同时满足exp和后部匹配条件时,返回后部匹配;b. exp非捕获;

逆序反向预查(?<!exp) a. 当单词不满足exp且满足后部匹配条件时,返回后部匹配;b. exp非捕获;

*名字很拗口,可以这么理解:正向、反向指的是要匹配的字符是在前面还是后面;正序、逆序指的是肯定还是否定子表达式。

引用

每个被捕获的子表达式都会存储在缓冲区,且被编号为1-99。每个缓冲区可以通过\n来访问,其中n为标识特定缓冲区的一位或两位十进制数。最简单,最有用的应用为查找文本中两个相同的相邻单词。

2. 元字符

\ ^ $ * + ? {n} {n,} {n,m} (pattern) (?:pattern) (?=pattern) (?!pattern) x|y [xyz] [^xyz] [a-z] [^a-z]

\b \B \cx \f \n \r \s \S \t \v

以上这些已经介绍过了,下面再看些常用的元字符。

\d 匹配一个数字字符,即[0-9];\D 匹配一个非数字字符;

\w 匹配包括下划线的任何单词字符,即[A-Za-z0-9];

\W 匹配任何非单词字符;

\xn 匹配n,其中n为十六进制,必须为确定的两个数字;

\num 如果前面至少num个被捕获子表达式,则表示引用;否则,如果num为0-7的数字,则匹配八进制;

\un 匹配n,其中n是四个十六进制数字表示的字符。

了解了这么多的符号和运算,很容易想到一个问题,这些运算符的优先级是怎么样的?

3. 运算符优先级

优先级从高到低为:

\ 转义符;

(),[] 子表达式和中括号表达式;

*,+,?,{} 限定符;

^,$,\任何元字符,任何字符 定位点和普通字符;

| 选择。



作者:han0710
链接:https://www.jianshu.com/p/9b7eed50e653
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

转载于:https://my.oschina.net/u/2345713/blog/1625111

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值