一样平常来讲对我们而言,须要抓取的是某个网站或者某个运用的内容,提取有用的代价。
内容一样平常分为两部分,非构造化的数据和构造化的数据。

非构造化数据:先有数据,再有构造。

构造化数据:先有构造、再有数据。

php网页爬虫cooking手把手教python3接口主动化非构造化数据提取一 SQL

不同类型的数据,我们须要采取不同的办法来处理。

13.1 正则表达式

13.1.1 为什么要学正则表达式

实际上爬虫一共就四个紧张步骤:

1. 明确目标 (要知道你准备在哪个范围或者网站去搜索)

2. 爬 (将所有的网站的内容全部爬下来)

3. 取 (去掉对我们没用途的数据)

4. 处理数据(按照我们想要的办法存储和利用)

之前的案例里实际上省略了第3步,也便是"取"的步骤。
由于我们down下了的数据是全部的网页,这些数据很弘大并且很混乱,大部分的东西使我们不关心的,因此我们须要将之按我们的须要过滤和匹配出来。

那么对付文本的过滤或者规则的匹配,最强大的便是正则表达式,是Python爬虫天下里必不可少的神兵利器。

13.1.2 什么是正则表达式

正则表达式,又称规则表达式,常日被用来检索、更换那些符合某个模式(规则)的文本。

正则表达式是对字符串操作的一种逻辑公式,便是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

1. 给定的字符串是否符合正则表达式的过滤逻辑(“匹配”);

2. 通过正则表达式,从文本字符串中获取我们想要的特定部分(“过滤”)。

13.1.3正则表达式匹配规则

1. 字符匹配规则。

2. 预定义字符集(可以写在字符集[…]中)。

3. 数词量(用在字符或者(...)之后)

4.边界匹配。

13.1.4 Python3下正则表达式的模块的加载

在 Python 中,我们可以利用内置的 re 模块来利用正则表达式。

import re

有一点须要特殊把稳的是,正则表达式利用 对分外字符进行转义,以是如果我们要利用原始字符串,只需加一个 r 前缀。

例子:

import re

#例子一

str1='nihao\tinghai'

print(str1)

#例子二

str2=r'nihao\tinghai'

print(str2)

运行结果:

nihao inghai

nihao\tinghai

13.1.5 compile 函数

compile 函数用于编译正则表达式,天生一个正则表达式( Pattern )工具,供 match() 和 search() 这两个函数利用。

语法格式为:

re.compile(pattern[, flags])

参数:

pattern : 一个字符串形式的正则表达式

flags 可选,表示匹配模式,比如忽略大小写,多行模式等,详细参数为:

re.I 忽略大小写

re.L 表示分外字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境

re.M 多行模式

re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)

re.U 表示分外字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库

re.X 为了增加可读性,忽略空格和' # '后面的注释

例子:

import re

pattern = re.compile(r'\d+') # 用于匹配至少一个数字

m = pattern.match('one12twothree34four') # 查找头部,没有匹配

print(m)

m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配

print(m)

m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,恰好匹配

print(m)

运行结果:

None

None

<_sre.SRE_Match object; span=(3, 5), match='12'>

13.1.6 正则表达式工具

re.compile() 返回 RegexObject 工具。

re.MatchObject

group() 返回被 RE 匹配的字符串。

start() 返回匹配开始的位置。

end() 返回匹配结束的位置。

span() 返回一个元组包含匹配 (开始,结束) 的位置。

13.1.7 Python3 re模块的2种利用办法

第一种办法:利用compile 函数

1.利用 compile() 函数将正则表达式的字符串形式编译为一个 Pattern 工具

2.通过 Pattern 工具供应的一系列方法对文本进行匹配查找,得到匹配结果,一个 Match 工具。

3.末了利用 Match 工具供应的属性和方法得到信息,根据须要进行其他的操作

compile 函数用于编译正则表达式,天生一个 Pattern 工具,它的一样平常利用形式如下:

import re

# 将正则表达式编译成 Pattern 工具。

pattern = re.compile(r'\d+')

在上面,我们已将一个正则表达式编译成 Pattern 工具,接下来,我们就可以利用 pattern 的一系列方法对文本进行匹配查找了。

Pattern 工具的一些常用方法紧张有:

match 方法:从起始位置开始查找,一次匹配

search 方法:从任何位置开始查找,一次匹配

findall 方法:全部匹配,返回列表

finditer 方法:全部匹配,返回迭代器

split 方法:分割字符串,返回列表

sub 方法:更换

第二种办法:直策应用re. search()/re. findall ()办法。

例子:

import re

old_url = 'http://www.jikexueyuan.com/course/android/?pageNum=2'

total_page =20

html = """

<html lang="en">

<head>

<title>爬虫测试</title>

</head>

<body>

<div class='topic'> <a href="http://jikexueyuan.com/welcone.html">欢迎参加《听海的Python3接口自动化测试》

<div class='list'>

<ul>

<li><a href="http://jikexueyuan.com/1.html">这是第一条</a></li>

<li><a href="http://jikexueyuan.com/2.html">这是第二条</a></li>

<li><a href="http://jikexueyuan.com/3.html">这是第三条</a></li>

</ul>

</div>

</div>

</body>

</html>

"""

# f.close()

# #任务一:爬取网页标题

#

# title = re.search('<title>(.?)</title>',html,re.S).group(1)

# print(title)

#

# #任务二:爬取链接

# links=re.findall('href="(.?)">',html)

# print(links)

# #任务三:爬取部分笔墨内容

# u_text =re.findall('<ul>(.?)</ul>',html,re.S)[0]

# texts =re.findall('">(.?)</a>',u_text,re.S)

# for every_text in texts:

# print(texts)

#任务四:sub实现翻页

for i in range(2,total_page+1):

new_link =re.sub('pageNum=\d','pageNum=%d'%i,old_url,re.S)

print(new_link)

13.1.8 re模块之match 方法

match 方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。
它的一样平常利用形式如下:

match(string,begin,end)

个中,string 是待匹配的字符串,begin 和end 是可选参数,指定字符串的起始和终点位置,当你指定begin 和end 时,match 方法会根据指定的范围去查询,如果不指定begin 和end 时,match 方法默认匹配字符串的头部。

当匹配成功时,返回一个 Match 工具,如果没有匹配上,则返回 None。

综合例子:

import re

#例子一

str1='ting123hai456'

pattern = re.compile(r'\d+') # 用于匹配至少一个数字

m1 = pattern.match(str1) # 查找头部,没有匹配

print(m1)

#例子二

str2='ting123hai456'

pattern = re.compile(r'\d+') # 用于匹配至少一个数字

m2 = pattern.match(str2,3,8) # 从'g'的位置开始匹配,没有匹配

print(m2)

#例子三

str3='ting123hai456'

pattern = re.compile(r'\d+') # 用于匹配至少一个数字

m3 = pattern.match(str3,4,8) # 从'1'的位置开始匹配,恰好匹配

print(m3) # 返回一个 Match 工具

print(m3.group(0))

print(m3.start(0))

print(m3.end(0))

print(m3.span(0))

运行结果:

None

None

<_sre.SRE_Match object; span=(4, 7), match='123'>

123

4

7

(4, 7)

在上面,当匹配成功时返回一个 Match 工具,个中:

group([group1, …]) 方法:用于得到一个或多个分组匹配的字符串,当要得到全体匹配的子串时,可直策应用 group() 或 group(0);

start([group]) 方法:用于获取分组匹配的子串在全体字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;

end([group]) 方法:用于获取分组匹配的子串在全体字符串中的结束位置(子串末了一个字符的索引+1),参数默认值为 0;

span([group]) 方法:返回 (start(group), end(group))。

re.I 与re.S

1. re.I 表示忽略大小写。

2. re.S 表示全文匹配。

例子一:re.I 表示忽略大小写。

import re

pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写

m = pattern.match('Welcome To Reptiles')

print(m) # 匹配成功,返回一个 Match 工具

print(m.group(0)) # 返回匹配成功的全体子串

print(m.span(0)) # 返回匹配成功的全体子串的索引

print(m.group(1)) # 返回第一个分组匹配成功的子串

print(m.span(1)) # 返回第一个分组匹配成功的子串的索引

print(m.group(2)) # 返回第二个分组匹配成功的子串

print(m.span(2)) # 返回第二个分组匹配成功的子串

print(m.groups()) # 等价于 (m.group(1), m.group(2), ...)

print(m.group(3)) # compile(r'([a-z]+) ([a-z]+)')只是匹配了2组规则,不存在第三个分组

运行结果:

<_sre.SRE_Match object; span=(0, 10), match='Welcome To'>

Welcome To

(0, 10)

Welcome

(0, 7)

To

(8, 10)

('Welcome', 'To')

IndexError: no such group

re.S表示全文匹配,讲findall()方法的时候,再用具体的例子展示。

13.1.9 re模块之search 方法

search 方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果,它的一样平常利用形式如下:

search(string,begin,end)

个中,string 是待匹配的字符串,begin 和end 是可选参数,指定字符串的起始和终点位置,当你指定begin 和end 时,search 方法会根据指定的范围去查询,如果不指定begin 和end 时,match 方法默认任何位置,只要找到了一个匹配的结果就返回。

当匹配成功时,返回一个 Match 工具,如果没有匹配上,则返回 None。

综合例子1:

import re

#例子一

str1='ting123hai456'

pattern = re.compile('\d+')

m1 = pattern.search(str1) # 查找字符串任意位置,这里如果利用 match 方法则不匹配

print(m1)

print(m1.group())

print(m1.span())

#例子二

str2='ting123hai456'

pattern = re.compile('\d+')

m2 = pattern.search(str2,4,8) # 指定字符串区间

print(m2)

print(m2.group())

print(m2.span())

运行结果:

<_sre.SRE_Match object; span=(4, 7), match='123'>

123

(4, 7)

<_sre.SRE_Match object; span=(4, 7), match='123'>

123

(4, 7)

综合例子2:

import re

#例子一

str1='ting123hai456'

pattern = re.compile('\d+')

m1 = pattern.search(str1) # 查找字符串任意位置,这里如果利用 match 方法则不匹配

print(m1)

print(m1.group())

print(m1.span())

#例子二

str2='ting123hai456'

pattern = re.compile('\d+')

m2 = pattern.search(str2,7,13) # 指定字符串区间

print(m2)

print(m2.group())

print(m2.span())

运行结果:

<_sre.SRE_Match object; span=(4, 7), match='123'>

123

(4, 7)

<_sre.SRE_Match object; span=(10, 13), match='456'>

456

(10, 13)

13.1.10 re模块之findall 方法

上面的 match 和 search 方法都是一次匹配,只要找到了一个匹配的结果就返回。
然而,在大多数时候,我们须要搜索全体字符串,得到所有匹配的结果。

findall 方法的利用形式如下:

findall(string,begin,end)

个中,string 是待匹配的字符串,begin 和end 是可选参数,指定字符串的起始和终点位置,当你指定begin 和end 时,findall 方法会根据指定的范围去查询,以列脸色势返回全部能匹配的子串,如果不指定begin 和end 时,match 方法会全文搜索,以列脸色势返回全部能匹配的子串。

findall 以列脸色势返回全部能匹配的子串,如果没有匹配,则返回一个空列表。

综合例子:

import re

#例子一

str1 = 'hello123hell world456hel'

pattern = re.compile('hel') # 查找数字

m1 = pattern.findall(str1)

print(m1)

#例子二

str2 = 'hello123hell world456hel'

pattern = re.compile('hel') # 查找 hel

m2 = pattern.findall(str2, 7, 14)

print(m2)

#例子三

str3 = 'hello123hell world456hel'

pattern = re.compile('hel') # 查找 hel

m3 = pattern.findall(str3, 7, 25)

print(m3)

运行结果:

['hel', 'hel', 'hel']

['hel']

['hel', 'hel']

13.1.11 re模块之finditer 方法

finditer 方法的行为跟 findall 的行为类似,也是搜索全体字符串,得到所有匹配的结果。
但它返回一个顺序访问每一个匹配结果(Match 工具)的迭代器。

例子:

import re

pattern = re.compile(r'\d+')

m1 = pattern.finditer('hello 123456 789')

m2 = pattern.finditer('one1two2three3four4', 0, 10)

print(type(m1))

print(type(m2))

print('----- m1 ------')

for a1 in m1: # a1 是 Match 工具

print('matching string: {}, position: {}'.format(a1.group(), a1.span()))

print('----- m2 ------')

for a2 in m2:

print('matching string: {}, position: {}'.format(a2.group(), a2.span()))

运行结果:

<class 'callable_iterator'>

<class 'callable_iterator'>

----- m1 ------

matching string: 123456, position: (6, 12)

matching string: 789, position: (13, 16)

----- m2 ------

matching string: 1, position: (3, 4)

matching string: 2, position: (7, 8)

13.1.12 split 方法

split 方法按照能够匹配的子串将字符串分割后返回列表,它的利用形式如下:

split(string[, maxsplit])

个中,maxsplit 用于指定最大分割次数,不指定将全部分割。

例子:

import re

p = re.compile(r'[\s\,\;]+')

print(p.split('a,b;; c d'))

运行结果:

['a', 'b', 'c', 'd']

13.1.13 sub 方法

sub 方法用于更换。
它的利用形式如下:

sub(repl, string[, count])

个中,repl 可以是字符串也可以是一个函数:

如果 repl 是字符串,则会利用 repl 去更换字符串每一个匹配的子串,并返回更换后的字符串,其余,repl 还可以利用 id 的形式来引用分组,但不能利用编号 0;

如果 repl 是函数,这个方法应该只接管一个参数(Match 工具),并返回一个字符串用于更换(返回的字符串中不能再引用分组)。

count 用于指定最多更换次数,不指定时全部更换。

例子一:

import re

p = re.compile('123(.?)123')

s = '123asdfxxIxxxxLovexxded123'

f = p.sub('123456789',s)

print(f)

运行结果:

123456789

例子二:

import re

p = re.compile(r'(\w+) (\w+)') # \w = [A-Za-z0-9]

s = 'hello 123, hello 456'

print(p.sub(r'hello world', s)) # 利用 'hello world' 更换 'hello 123' 和 'hello 456'

print(p.sub(r'\2 \1', s)) # 引用分组

def func(m):

return 'hi' + ' ' + m.group(2)

print(p.sub(func, s))

print(p.sub(func, s, 1)) # 最多更换一次

运行结果:

hello world, hello world

123 hello, 456 hello

hi 123, hi 456

hi 123, hello 456

13.1.14 贪婪模式与非贪婪模式

在利用正则匹配的时候,有2种模式:

【贪婪模式】:在全体表达式匹配成功的条件下,尽可能多的匹配 ( );

【非贪婪模式】:在全体表达式匹配成功的条件下,尽可能少的匹配 ( ? );

Python里数量词默认是贪婪的。

综合例子一:

import re

#例子一 贪婪模式

s = 'abbbc'

p = re.compile('ab')

f1 = p.findall(s)

print(f1)

#例子二 非贪婪模式

s = 'abbbc'

p = re.compile('ab?')

f2 = p.findall(s)

print(f2)

运行结果:

['abbb']

['a']

运行结果解释:

利用贪婪的数量词的正则表达式 ab ,匹配结果: abbb。

决定了尽可能多匹配 b,以是a后面所有的 b 都涌现了。

利用非贪婪的数量词的正则表达式ab?,匹配结果: a。

纵然前面有 ,但是 ? 决定了尽可能少匹配 b,以是没有 b。

综合例子二:

import re

html="aa<div>test1</div>bb<div>test2</div>cc"

#例子一 贪婪模式

p = re.compile('<div>.</div>')

f1 = p.findall(html)

print(f1)

#例子二 非贪婪模式

p = re.compile('<div>.?</div>')

f2 = p.findall(html)

print(f2)

运行结果:

['<div>test1</div>bb<div>test2</div>']

['<div>test1</div>', '<div>test2</div>']

运行结果解释:

利用贪婪的数量词的正则表达式:<div>.</div>

匹配结果:<div>test1</div>bb<div>test2</div>

这里采取的是贪婪模式。
在匹配到第一个“</div>”时已经可以使全体表达式匹配成功,但是由于采取的是贪婪模式,以是仍旧要向右考试测验匹配,查看是否还有更长的可以成功匹配的子串。
匹配到第二个“</div>”后,向右再没有可以成功匹配的子串,匹配结束,匹配结果为“<div>test1</div>bb<div>test2</div>”

利用非贪婪的数量词的正则表达式:<div>.?</div>

匹配结果:<div>test1</div>

正则表达式二采取的是非贪婪模式,在匹配到第一个“</div>”时使全体表达式匹配成功,由于采取的是非贪婪模式,以是结束匹配,不再向右考试测验,匹配结果“<div>test1</div>”。

13.1.15 利用正则表达式的爬虫的案例

学会了正则表达式提取数据的干系方法之后,我们就可以进行对爬取到的全部网页源代码进行筛选了,下面讲案例。

案例一:爬取极客学院课程

代码:

import re,requests

class spider(object):

def __init__(self):

print("开始爬取内容")

def getsource(self,source):

html = requests.get(source)

return html.text

def changepage(self,url,total_page):

now_page =int(re.search('pageNum=(\d+)',url,re.S).group(1))

page_group = []

for i in range(now_page,total_page+1):

link = re.sub('pageNum=(\d+)','pageNum=%s'%i,url,re.S)

page_group.append(link)

return page_group

def geteveryclass(self,html):

everyclass = re.findall('<li id="(.?)</li>',html,re.S)

return everyclass

def getinfo(self,eachclass):

info ={ } #定义一个空的字典

info['title']=re.search('title="(.?)" alt="',eachclass,re.S).group(1)

info['content'] = re.findall('display: none;">[\s]([\s\S]?)[\s]</p>', eachclass)[0]

classlevel=re.findall('<em>(.?)</em>',eachclass, re.S)

info['classtime'] =classlevel[0]

info['classlevel'] = classlevel[1]

info['learnnum'] = re.search('"learn-number">(.?)</em>', eachclass, re.S).group(1)

return info

def saveinfo(self,classinfo):

f=open(u'info.txt','a')

for each in classinfo:

f.writelines('title:'+each['title']+'\n')

f.writelines('content:' + each['content'] + '\n')

f.writelines('classtime:' + each['classtime'] + '\n')

f.writelines('classlevel:' + each['classlevel'] + '\n')

f.writelines('learnnum:' + each['learnnum'] + '\n')

f.close()

if __name__=='__main__':

classinfo =[] #定义一个空的列表

url='http://www.jikexueyuan.com/course/?pageNum=1' # 初始的url

jikespider = spider() #实例化一个类 jikespider

all_links =jikespider.changepage(url,20) #调用jikespider里的changepage(url,20)方法,获取1~20页的url

for link in all_links:

print("正在处理页面:"+ link)

html =jikespider.getsource(link) # 调用jikespider里的getsource()方法,获取每个html的text

everyclass = jikespider.geteveryclass(html) #调用jikespider里的geteveryclass()方法爬取everyclassh的html的text存到everyclass列表里

#print(everyclass)

for each in everyclass:

#print(each)

info = jikespider.getinfo(each) #调用jikespider里的getinfo()方法,获取每个视频的title、content、classtime、classlevel、learnnum

classinfo.append(info)

print(classinfo)

jikespider.saveinfo(classinfo)

13.2 XPath先容

正则虽然很强大,但是正则语法相比拟较繁芜,比较难节制,还有其余一种方法:XPath,我们可以先将 HTML文件 转换成XML文档,然后用 XPath 查找 HTML 节点或元素。

13.2.1 什么是XML

XML 指可扩展标记措辞(EXtensible Markup Language)

XML 是一种标记措辞,很类似 HTML

XML 的设计宗旨是传输数据,而非显示数据

XML 的标签须要我们自行定义。

XML 被设计为具有自我描述性。

XML 是 W3C 的推举标准

13.2.2 XML 和 HTML 的差异

XML文档示例:

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

<book category="cooking">

<title lang="en">Everyday Italian</title>

<author>Giada De Laurentiis</author>

<year>2005</year>

<price>30.00</price>

</book>

<book category="children">

<title lang="en">Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

<book category="web">

<title lang="en">XQuery Kick Start</title>

<author>James McGovern</author>

<author>Per Bothner</author>

<author>Kurt Cagle</author>

<author>James Linn</author>

<author>Vaidyanathan Nagarajan</author>

<year>2003</year>

<price>49.99</price>

</book>

<book category="web" cover="paperback">

<title lang="en">Learning XML</title>

<author>Erik T. Ray</author>

<year>2003</year>

<price>39.95</price>

</book>

</bookstore>

HTML DOM 模型示例:

HTML DOM 定义了访问和操作 HTML 文档的标准方法,以树构造办法表达 HTML 文档。

13.2.3 XML的节点关系

1. 父节点(Parent)

每个元素以及属性都有一个父。

下面是一个大略的XML例子中,book 元素是 title、author、year 以及 price 元素的父:

<?xml version="1.0" encoding="utf-8"?>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

2. 子节点(Children)

元素节点可有零个、一个或多个子。

不才面的例子中,title、author、year 以及 price 元素都是 book 元素的子:

<?xml version="1.0" encoding="utf-8"?>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

3. 同胞(Sibling)

拥有相同的父的节点。

不才面的例子中,title、author、year 以及 price 元素都是同胞:

<?xml version="1.0" encoding="utf-8"?>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

4. 先辈(Ancestor)

某节点的父、父的父,等等。

不才面的例子中,title 元素的先辈是 book 元素和 bookstore 元素:

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

</bookstore>

5. 后代(Descendant)

某个节点的子,子的子,等等。

不才面的例子中,bookstore 的后代是 book、title、author、year 以及 price 元素:

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

</book>

</bookstore>

13.2.4 什么是XPath

XPath (XML Path Language) 是一门在 XML 文档中查找信息的措辞,可用来在 XML 文档中对元素和属性进行遍历。

W3School官方文档:http://www.w3school.com.cn/xpath/index.asp

13.2.5 XPath 开拓工具

1.开源的XPath表达式编辑工具:XMLQuire(XML格式文件可用)

2.Chrome插件 XPath Helper

3.Firefox插件 XPath Checker

13.2.6 选取节点

XPath 利用路径表达式在 XML 文档中选取节点。
节点是通过沿着路径或者 step 来选取的。

下面列出了最有用的路径表达式:

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

实例

不才面的表格中,我们已列出了一些路径表达式以及表达式的结果:

实例

不才面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式

结果

/bookstore/book[1]

选取属于 bookstore 子元素的第一个 book 元素。

/bookstore/book[last()]

选取属于 bookstore 子元素的末了一个 book 元素。

/bookstore/book[last()-1]

选取属于 bookstore 子元素的倒数第二个 book 元素。

/bookstore/book[position()<3]

选取最前面的两个属于 bookstore 元素的子元素的 book 元素。

//title[@lang]

选取所有拥有名为 lang 的属性的 title 元素。

//title[@lang='eng']

选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。

/bookstore/book[price>35.00]

选取 bookstore 元素的所有 book 元素,且个中的 price 元素的值须大于 35.00。

/bookstore/book[price>35.00]/title

选取 bookstore 元素中的 book 元素的所有 title 元素,且个中的 price 元素的值须大于 35.00。

【选取未知节点】

XPath 通配符可用来选取未知的 XML 元素。

实例

不才面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

【选取多少路径】

通过在路径表达式中利用“|”运算符,您可以选取多少个路径。

实例

不才面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

13.2.7 XPath 运算符

下面列出了可用在 XPath 表达式中的运算符: