python使用xpath返回一个整形_Python XPath的使用

```

我们要注意/和//的区别,其中/是用于获取直接子节点,//用于获取子孙节点。

获取父节点

我们已经知道了获取子节点和子孙节点,获取父节点可以用..来实现。比如我们想获取href属性为/films/1218273的a节点的父节点的class属性,也就是p的class属性,可以这样来实现:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//a[@href="/films/1218273"]/../@class')

print(result)

运行结果如下:

['name']

0x05 属性匹配

上面我们获取父节点的属性时已经用到了属性的知识,在xpath中我们可以用@符号来进行属性过滤。比如这里要选取class为star的p节点,可以这样实现:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p[@class="star"]') # 属性匹配

print(result)

这里我们通过加入[@class="star"],限制了节点的class属性为star,而在案例的HTML文本中符合条件的p节点有两个,所以结果应该返回两个匹配到的元素。结果如下:

[, ]

0x06文本获取

我们可以利用XPath中的test()方法来获取文本内容,接下来尝试获取属性为class的p节点的文本,也就是我们的电影名称

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p[@class="name"]/text()')

print(result)

运行结果如下:

[]

我们可以看到我们并没有获取到任何文本,书上给的解释是:XPath中text()前面是/,而此处/的含义是选取直接子节点,p的直接子节点都是a节点,文本都是在a节点内部的。我们错误的使用了/使得我们没有匹配到想要获取的内容

如果想要获取p节点的内部文本,就有两种获取方式,一种是先获取a节点在获取文本,另一种就是使用//。接下来,我们来看一下二者的区别:

首先,选取到a节点在获取文本,代码如下:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p[@class="name"]/a/text()')

print(result)

运行结果如下:

['误杀', '叶问4:完结篇']

可以看到这里的返回值是两个,内容都是属性为name的p节点的文本。这里我们是逐层选取的,先选取了p节点,有利用/选取了其直接子节点a,然后再选取文本,得到的结果恰好是我们预期的两个结果

再来看下用另外一种方式(即使用//)选取的结果,代码如下:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p[@class="name"]//text()') # 使用//获取p节点下的文本

print(result)

运行结果如下:

['误杀', '叶问4:完结篇']

我们可以看到我们还是得到了预期的结果,但是如果我们想获取属性为star的p节点下的文本,代码如下:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p[@class="star"]//text()')

print(result)

运行结果:

['\n 主演:肖央,谭卓,陈冲\n', '\n 主演:甄子丹,吴樾,吴建豪\n ']

我们发现虽然获取到了我们想要的内容,但是里面还有一些换行符。所以说,如果想要获取子孙节点内部的所有文本,可以直接使用//加text()方式,这样可以保证获取到最全面的文本信息,但是可能会夹杂一些换行符等特殊字符。如果想要获取某些特定子孙节点下的所有文本,可以先获取到特定的子孙节点,然后再调用text()方法获取其内部文本,这样可以保证我们的结果是整洁的

0x07 属性获取

我们知道用text()可以获取节点内部文本,那么节点属性该怎样获取呢?其实还是用@符号就可以。例如,我们想获取所有p节点下所有a节点的href属性,代码如下:

from lxml import etree

text = '''

误杀

主演:肖央,谭卓,陈冲

上映时间:2019-12-13

叶问4:完结篇

主演:甄子丹,吴樾,吴建豪

上映时间:2019-12-20

'''

html = etree.HTML(text)

result = html.xpath('//p/a/@href')

print(result)

这里我们通过@href即可获取节点的href属性。注意,此处和属性匹配的方法不同,属性匹配是中括号加属性名和值来限定某个属性,如[@href="/films/1218273"],而此处的@href指的是获取节点的某个属性,二者需要做好区分。

运行结果如下:

['/films/1218273', '/films/1190122']

我们成功获取了所有p节点下的a节点的href属性,他们以列表的形式返回

0x08 属性多值匹配

有时候,某些节点的某个属性可能有多个值,例如:

from lxml import etree

text = '''

first item

'''

html = etree.HTML(text)

result = html.xpath('//li[@class="li"]/a/text()')

print(result)

这里HTML文本中li节点的class属性有两个值li和li-first,此时如果还想用之前的属性匹配获取,就无法匹配了,此时的运行结果如下:

[]

这时就需要用到contains()函数了,代码可以改写如下:

from lxml import etree

text = '''

first item

'''

html = etree.HTML(text)

result = html.xpath('//li[contains(@class, "li")]/a/text()')

print(result)

这样通过contains()方法,第一个参数传入属性名称,第二个参数传入属性值,只要此属性包含所传入的属性值,就可以完成匹配了。

此时运行结果如下:

['first item']

0x09 多属性匹配

另外,我们可能遇到一种情况,那就是根据多个属性确定一个节点,这时就需要同时匹配多个属性。此时可以使用运算符and来连接,示例如下:

from lxml import etree

text = '''

first item

'''

html = etree.HTML(text)

result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')

print(result)

这里的li节点有增加了一个属性name。要确定这个节点,需要同时根据class和name属性来选择,一个条件是class属性里面包含li字符串,另一个条件是name属性为item字符串,二者需要同时满足,需要用and操作符相连,相连之后置于中括号内进行条件筛选。运行结果如下:

['first item']

0x10 按序选择

有时候我们在选择的时候某些属性可能同时匹配了多个节点,但是又想要其中的某个节点,这是我们可以利用中括号传入索引的方法来获取特定次序的节点,示例如下:

from lxml import etree

text = '''

'''

html = etree.HTML(text)

result_1 = html.xpath('//li[1]/a/text()')

print(result_1)

result_2 = html.xpath('//li[last()]/a/text()')

print(result_2)

result_3 = html.xpath('//li[position()<3]/a/text()')

print(result_3)

result_4 = html.xpath('//li[last()-2]/a/text()')

print(result_4)

第一次选择时我们选取第一个li节点,中括号传入数字1即可。第二次选择时我们选取最后一个li节点,中括号中传入last()即可。第三次选择时,我们选取了位置小于3的li节点,也就是位置序号为1和2的li节点。第四次选择时,我们选取了倒数第三个li节点

运行结果如下:

['first item']

['fifth item']

['first item', 'second item']

结语

XPath选择器的功能十分强大,使用起来简单方便,大大的提升了我们爬虫的效率。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值