一样平常来讲对我们而言,须要抓取的是某个网站或者某个运用的内容,提取有用的代价。内容一样平常分为两部分,非构造化的数据和构造化的数据。
非构造化数据:先有数据,再有构造。
构造化数据:先有构造、再有数据。
不同类型的数据,我们须要采取不同的办法来处理。
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=39;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 表达式中的运算符: