xpath学习记录

<!DOCTYPE html> 
<html> 
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>xpath test</title> 
    </head> 
    <body> 
        <div price="99.8"> 
            <div> 
                <ul>
                 <li>时间</li> 
                 <li>地点</li> 
                 <li>任务</li> 
                </ul> 
            </div> 
            <div id='testid' data-h="first">
             <h2>这里是个小标题</h2>
             <ol>
                 <li data="one">1</li> 
                 <li data="two">2</li> 
                 <li data="three">3</li> 
                 <li data="four">4</li> 
             </ol>
             <ol>
                 <li num="one">one1</li> 
                 <li num="two">two2</li> 
                 <li num="three">three3</li> 
             </ol>
             <ul>
                 <li code="84" id="testid">84</li> 
                 <li code="104">104</li> 
                 <li code="105">105</li> 
                 <li code="223">223</li> 
             </ul>
             <div> 
                 <ul> 
                     <li>11</li> 
                     <li>22</li>
                     <li>33</li> 
                     <li>44</li> 
                     <li>55</li> 
                     <li>66</li>
                     <li>77</li> 
                     <li>88</li> 
                     <li>99</li> 
                 </ul> 
             </div>
            </div> 
             <div id='testid'> 
             <ol>
                 <li code="84">84</li> 
                 <li code="104">104</li> 
                 <li code="223">223</li> 
             </ol>
             <h3>这里是uu的内容 <a href="http://www.baidu.com">百度一下</a> 
                 <ul> 
                 <li>test1</li> 
                 <li>test2</li> 
                 </ul> 
                 <ul> 
                 <li>test3</li> 
                 <li>test4</li> 
                 </ul> 
             </h3> 
             </div> 
             <div id="go"> 
                 <ul> 
                     <li>1</li> 
                     <li>2</li>
                     <li>3</li> 
                     <li>4</li> 
                     <li>5</li> 
                     <li>6</li>
                     <li>7</li> 
                     <li>8</li> 
                     <li>9</li> 
                     <li>10</li> 
                 </ul> 
             </div> 
             <div> 
                 <ul> 
                     <li>11</li> 
                     <li>22</li>
                     <li>33</li> 
                     <li>44</li> 
                     <li>55</li> 
                     <li>66</li>
                     <li>77</li> 
                     <li>88</li> 
                     <li>99</li> 
                 </ul> 
             </div>
         </div> 
     </body> 
 </html>
# !C:Python27 python
# -*- coding: UTF-8 -*-
from lxml import etree
import sys
import io
import HTMLParser

__author__ = 'Allen'
fo = open('D:\pyapp/myPython/xpathTest/htmlForXpath.html', 'r')

html = fo.read()
# html_str = html.decode('utf-8').encode('GBK')
html_str = html
html_parser = etree.HTMLParser()
tree = etree.parse(io.StringIO(html_str.decode('utf-8')), html_parser)
# print tree.xpath('.//')
print tree.xpath('//@code') 

# type(tree.xpath('//div[@]/h2/text() | //li[@data]/text()'))
for item in tree.xpath('//div[@>多个匹配条件
    print item.encode('GBK')

# 1. child:选取当前节点的所有子元素
print tree.xpath('//div[@>
# print tree.xpath('//div[@]/child::ol/text()')
print tree.xpath('//div[@> [<Element li at 0x2665c08>]
print tree.xpath('//div[@>
#定位某节点下为ol的子节点下的所有节点
print tree.xpath('//div[@>) 
print tree.xpath('//div[@> 上面两条语句的输出都是  ['1', '2', '3', 'one1', 'two2', 'three3']
print tree.xpath('//div[@>) 

# 2.attribute:选取当前节点的所有属性
print tree.xpath('//div/attribute::id') #attribute定位id属性值
print tree.xpath('//div[@>定位当前节点的所有属性值

# 3.ancestor:父辈元素 / ancestor-or-self:父辈元素及当前元素
print tree.xpath('//div[@>定位父辈div元素的price属性
print tree.xpath('//div[@> ['good']
print tree.xpath('//div[@>所有父辈div元素
print tree.xpath('//div[@>所有父辈及当前节点div元素

# 4.descendant:后代 / descendant-or-self:后代及当前节点本身,使用方法同上.

# 5. following :选取文档中当前节点的结束标签之后的所有节点
#定位testid之后不包含id属性的div标签下所有的li中第一个li的text属性
print tree.xpath('//div[@>) 
print tree.xpath('//div[@> 上面两行可以显示出 .// 的作用
print tree.xpath('//div[@>) 
print tree.xpath('//div[@>) 
# 6. namespace:选取当前节点的所有命名空间节点
print tree.xpath('//div[@>选取命名空间节点 ????

# 7. 选取data值为one的父节点的子节点中最后一个节点的值
print type(tree.xpath('//li[@data="one"]/parent::ol/li[last()]/text()')) 
print tree.xpath('//li[@data="one"]/parent::ol/li[last()]/text()')
print '==' 
print tree.xpath('//li[@data="one"]/parent::ol/li') 
# 8. preceding:选取文档中当前节点的开始标签之前的所有节点(需要同时有开始标签和结束标签才是一个完整的节点)
print tree.xpath('//div[@>)[0]
print tree.xpath('//div[@>)
print tree.xpath('//div[@> 返回空列表[]
print tree.xpath('//div[@> [<Element meta at 0x22c9c88>]
print type(tree.xpath('//div[@>)[0])
# 9. 下面这两条可以看到其顺序是靠近testid节点的优先
print tree.xpath('//div[@> 任务
print tree.xpath('//div[@> 时间

# 10. 记住只能是同级节点
print tree.xpath('//div[@>)[0] 
print len(tree.xpath('//div[@>))
print tree.xpath('//div[@>这里返回的就是空的了

# 11. 选取带id属性值的div中包含data-h属性的标签的所有属性值
print tree.xpath('//div[@id]/self::div[@data-h]/attribute::*') # ['testid', 'first']
print tree.xpath('//div[@id]/self::div[@data-h]/attribute::data-h')

# 12. 组合:定位id值为testid下的ol下的li属性值data为two的父元素ol的兄弟前节点h2的text值
print tree.xpath('//*[@> 这里是个小标题

# 13. position 定位
print tree.xpath('//*[@>]

# 14. 定位所有h2标签中text值为`这里是个小标题`
print tree.xpath(u'//h2[text()="这里是个小标题"]/text()')[0]   # 这里是个小标题

# xpath中的相关函数
# 15 统计
print tree.xpath('count(//li[@data])') #节点统计

# 16 concat:字符串连接
print tree.xpath('concat(//li[@data="one"]/text(),//li[@data="three"]/text())')

# 17 string只能解析匹配到的第一个节点下的值,也就是作用于list时只匹配第一个
print tree.xpath('string(//li)')  # 时间

# 18 解析节点名称,返回第一个匹配的名称
print tree.xpath('local-name(//*[@>local-name解析节点名称

# 19 contains(string1,string2):如果 string1 包含 string2,则返回 true,否则返回 false
print tree.xpath('//h3[contains(text(),"uu")]/a/text()')[0] 
#使用字符内容来辅助定位 #百度一下 >
#  组合
#匹配带有href属性的a标签的先辈节点中的div,其前一个div节点下ul下li中text属性包含“务”字的节点的值 
print tree.xpath(u'//a[@href]/ancestor::div/preceding::div/ul/li[contains(text(),"务")]/text()')[0]   #任务

# 20 not:布尔值(否)
print tree.xpath('count(//li[not(@data)])') #不包含data属性的li标签统计   18.0

# 21 string-length:返回指定字符串的长度
#string-length函数+local-name函数定位节点名长度小于2的元素
print tree.xpath('//*[string-length(local-name())<2]/text()')[0] #百度一下

#contains函数+local-name函数定位节点名包含di的元素 
print tree.xpath('//div[@> [<Element div at 0x225e108>, <Element div at 0x225e0c8>]

# 22 or:多条件匹配
print tree.xpath('//li[@data="one" or @code="84"]/text()') #or匹配多个条件 ['1', '84']
#也可使用|  ,注意or和|的用法有所不同
print tree.xpath('//li[@data="one"]/text() | //li[@code="84"]/text()')   #|匹配多个条件 ['1', '84']

# 23 position定位+last+div除法,选取中间两个 
print tree.xpath('//div[@>['5', '6']

# 24 隔行定位:position+mod取余
# position+取余运算隔行定位
print tree.xpath('//div[@>) 

# 25 starts-with:以。。开始
# starts-with定位属性值code以8开头的li元素
print tree.xpath('//li[starts-with(@code,"8")]/text()')[0]  # 84

# 数值比较
# 25 所有li的code属性小于200的节点
print tree.xpath('//li[@code<200]/text()')   # ['84', '104', '105', '84', '104']

# 25 div:对某两个节点的属性值做除法
print tree.xpath('//div[@> 2.65476190476
print tree.xpath('89 div 9')

# 组合:根据节点下的某一节点数量定位
# 选取所有ul下li节点数大于5的ul节点
print tree.xpath('//ul[count(li)>5]/li/text()')  # ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

# 26 将对象还原为字符串
s = tree.xpath('//*[@>使用xpath定位一个节点  s <Element div at 0x2b6ffc8> 
s2 = etree.tostring(s) #还原这个对象为html字符串 >>> s2
print type(s2)
print type(s2.decode('utf-8'))
h = HTMLParser.HTMLParser()
print h.unescape(s2)  #得到网页内容的html代码时,网页中的中文都会显示成 NCR 字符的形式,可使用HTMLParser的unescape()方法转换 https://www.jianshu.com/p/fb026309867b

From:https://www.jianshu.com/p/1575db75670f

几个的关键XPath概念:

绝对vs相对XPath(/vs .

  • / 引入绝对位置路径,从文档的根开始。

  • . 从上下文节点开始引入相对位置路径。

命名元素vs任何元素(enamevs *

  • /ename选择一个ename根元素

    • ./ename选择ename当前节点的所有子元素。

  • /* 选择根元素,无论名称如何。

    • ./*或者*选择上下文节点的所有子元素,而不管名称。

后代或自我轴(//*

  • //ename选择ename文档中的所有元素。

    • .//ename选择ename上下文节点或其下的所有元素。

  • //* 选择文档中的所有元素,无论名称如何。

    • .//* 选择上下文节点处或下方的所有元素,无论名称如何。