六 . 爬虫 Xpath介绍和使用

一 .Xpath介绍和使用

https://www.cnblogs.com/pythonywy/p/11082153.html

1. 简介

   XPath,全称 XML Path Language,即 XML 路径语言,它是一门在 XML 文档中查找信息的语言。最初是用来搜寻 XML 文档的,
但同样适用于 HTML 文档的搜索。所以在做爬虫时完全可以使用 XPath 做相应的信息抽取。     XPath 的选择功能十分强大,它提供了非常简洁明了的路径选择表达式。另外,它还提供了超过
100 个内建函数,用于字符串、
数值、时间的匹配以及节点、序列的处理等,几乎所有想要定位的节点都可以用 XPath 来选择。

2. 使用

 
   首先导入 lxml 库的 etree 模块,然后声明一段 HTML 文本,调用 HTML 类进行初始化,成功构造一个 XPath 解析对象。注意:HTML 
文本中最后一个 li 节点没有闭合,但是 etree 模块可以自动修正 HTML 文本。     调用 tostring() 方法即可输出修正后的 HTML 代码,但结果是 bytes 类型,可以用 decode() 方法将其转化为 str 类型,结果如下: 经过处理后,li 节点标签被补全,并且还自动添加了 body、html 节点。 还可以直接读取文本文件进行解析:

 


index.html
<html><body><div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li></ul>
</div>
</body></html>
from lxml import etree
html = etree.parse('./index.html', etree.HTMLParser())
result = etree.tostring(html)
print(result.decode('utf-8'))

执行结果:

<html><body><div>&#13;
<ul>&#13;
<li class="item-0"><a href="link1.html">first item</a></li>&#13;
<li class="item-1"><a href="link2.html">second item</a></li>&#13;
<li class="item-inactive"><a href="link3.html">third item</a></li>&#13;
<li class="item-1"><a href="link4.html">fourth item</a></li>&#13;
<li class="item-0"><a href="link5.html">fifth item</a>&#13;
</li></ul>&#13;
</div>&#13;
</body></html>

2.  所有节点(用以 // 开头的 XPath 规则来选取所有符合要求的节点  * 代表匹配所有节点)

from lxml import etree

html = etree.parse('./index.html', etree.HTMLParser())
result = html.xpath('//*')
print(result)


# 运行结果
"""
[<Element html at 0x1d6610ebe08>, <Element body at 0x1d6610ebf08>, 
<Element div at 0x1d6610ebf48>, <Element ul at 0x1d6610ebf88>, 
<Element li at 0x1d6610ebfc8>, <Element a at 0x1d661115088>, 
<Element li at 0x1d6611150c8>, <Element a at 0x1d661115108>, 
<Element li at 0x1d661115148>, <Element a at 0x1d661115048>, 
<Element li at 0x1d661115188>, <Element a at 0x1d6611151c8>, 
<Element li at 0x1d661115208>, <Element a at 0x1d661115248>]
"""
 * 代表匹配所有节点,返回的结果是一个列表,每个元素都是一个 Element 类型,后跟节点名称。
    也可以指定匹配的节点名称:

 

from lxml import etree

html = etree.parse('./index.html', etree.HTMLParser())
result = html.xpath('//li')
print(result)


# 运行结果
"""
[<Element li at 0x1c481fe0648>, 
<Element li at 0x1c481fe0688>, 
<Element li at 0x1c481fe06c8>,
 <Element li at 0x1c481fe0708>, 
 <Element li at 0x1c481fe0748>]
"""

3.  子节点


 通过 / 或 // 即可查找元素的子节点或子孙节点。选择 li 节点的所有直接 a 子节点:

 

from lxml import etree

html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//li/a')
print(result)
此处的 / 用来获取直接子节点,如果要获取所有子孙节点,将 / 换成 // 即可。

4. 父节点


知道子节点,查询父节点可以用 .. 来实现:


#
方法一 from lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//a[@href="link4.html"]/../@class') print(result) # ['item-1'] # 方法二 from lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//a[@href="link4.html"]/parent::*/@class') print(result) # 运行结果:['item-1']

5. 属性匹配


   匹配时可以用@符号进行属性过滤:

 


from
lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//li[@class="item-inactive"]') print(result) # [<Element li at 0x12998cc4688>]

6. 文本获取


 有两种方法:一是获取文本所在节点后直接获取文本,二是使用 //。

#
第一种 from lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//li[@class="item-0"]/a/text()') result.decode('utf-8') print(result) # ['first item¹þ¹þ¹þ', 'fifth itemºÙºÙºÙ']
# 第二种 from lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//li[@class="item-0"]//text()') print(result) # ['first item¹þ¹þ¹þ', 'fifth itemºÙºÙºÙ', '\r\n']
    第二种方法会获取到补全代码时换行产生的特殊字符,推荐使用第一种方法,可以保证获取的结果是整洁的。

7.  属性获取


在 XPath 语法中,@符号相当于过滤器,可以直接获取节点的属性值:

 


from
lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) result = html.xpath('//li/a/@href') print(result) # 运行结果:['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']

8. 属性多值匹配


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

 


from
lxml import etree text = ''' <li class="li li-first"><a href="link.html">first item</a></li> ''' html = etree.HTML(text) result = html.xpath('//li[contains(@class, "li")]/a/text()') print(result) # ['first item']

9. 多属性匹配

当前节点有多个属性时,需要同时进行匹配:

from lxml import etree

text = '''
<li class="li li-first" name="item"><a href="link.html">first item</a></li>
'''
html = etree.HTML(text)
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
print(result)

# 运行结果:['first item']

10. 按序选择


   匹配结果有多个节点,需要选中第二个或最后一个,可以按照中括号内加索引或其他相应语法获得:

 



from
lxml import etree text = ''' <div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a> </ul> </div> ''' html = etree.HTML(text) # 获取第一个 result = html.xpath('//li[1]/a/text()') print(result) # 获取最后一个 result = html.xpath('//li[last()]/a/text()') print(result) # 获取前两个 result = html.xpath('//li[position()<3]/a/text()') print(result) # 获取倒数第三个 result = html.xpath('//li[last()-2]/a/text()') print(result) """ 运行结果: ['first item'] ['fifth item'] ['first item', 'second item'] ['third item'] """

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-11-01 14:52  supreme999  阅读(442)  评论(0编辑  收藏  举报