Python-XiaCaiP

原文地址: 知乎-Python爬虫之xpath使用技巧

XPath是一种表达式语言,它的返回值可能是节点,节点集合,原子值,以及节点和原子值的混合等。XPath2.0是XPath1.0的超集。它是对XPath1.0的扩展,它可以支持更加丰富的数据类型,并且XPath2.0保持了对XPath1.0的相对很好的向后兼容性,几乎所有的XPath2.0的返回结果都可以和XPath1.0保持一样。另外XPath2.0也是XSLT2.0和XQuery1.0的用于查询定位节点的主表达式语言。XQuery1.0是对XPath2.0的扩展。

模块安装

pip install lxml -i https://pypi.doubanio.com/simple/

测试文件

test.html

<!DOCTYPE html>
<html>
<head>
    <title>xpath测试文件</title>
</head>
<body>
<div>
    <ul>
        <li class="item-1 active first"><a href="link1.html">first item</a></li>
        <li class="item-2 li"><a href="link2.html">second item</a></li>
        <li class="item-3 li"><a href="link3.html">third item</a></li>
        <li class="item-4"><a href="link4.html">fourth item</a></li>
        <li class="item-5 last"><a href="link5.html">fifth item</a></li>
    </ul>
</div>
<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>
        </ol>
        <ul>
            <li code="84">84</li>
            <li code="104">104</li>
            <li code="223">223</li>
        </ul>
    </div>
    <div>
        <h3>这里是H3的内容
            <a href="http://www.baidu.com">百度一下</a>
            <ul>
                <li>test1</li>
                <li>test2</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>
        </ul>
    </div>
</div>
</body>
</html>
测试文件test.html

基础语法

导入lxml库

from lxml import etree

​读取html文件

html = etree.parse(\'test.html\')

​获取html内容

html_data = etree.tostring(html, pretty_print=True)
res = html_data.decode(\'utf-8\')
print(res)

输出结果

 

获取所有a标签href属性

hrefs = html.xpath(\'//a/@href\')
print(hrefs)
>> [\'link1.html\', \'link2.html\', \'link3.html\', \'link4.html\', \'link5.html\', \'http://www.baidu.com\']

查找a标签href属性等于link1.html的内容

a_href_link1_text = html.xpath(\'//a[@href="link1.html"]/text()\')
print(a_href_link1_text)
>> [\'first item\']

查找所有li标签下的a标签内容

li_children_a_text = html.xpath(\'//li/a/text()\')
print(li_children_a_text)
>> [\'first item\', \'second item\', \'third item\', \'fourth item\', \'fifth item\']

查找第一个li标签里的a标签的href属性值

li_first_a_href = html.xpath(\'//li[1]/a/@href\')
print(li_first_a_href)
>> [\'link1.html\']

查找最后一个li标签里的a标签的href属性值

li_last_a_href = html.xpath(\'//li[last()]/a/@href\')
print(li_last_a_href)
>> [\'link5.html\']

查找倒数第二个li标签里的a标签的href属性值

li_secondLast_a_href = html.xpath(\'//li[last()-1]/a/@href\')
print(li_secondLast_a_href)
>> [\'link4.html\'] 

高级语法

查找class属性中包含active关键字的标签下的a标签的href属性值

contains_active_a_href = html.xpath(\'//*[contains(@class, "active")]/a/@href\')
print(contains_active_a_href)
>> [\'link1.html\']

查找class属性中开始位置包含item-4关键字的标签下的a标签的href属性值

start_item4_a_href = html.xpath(\'//*[starts-with(@class,"item-5")]/a/@href\')
print(start_item4_a_href)
>> [\'link5.html\']

查找class属性中含有item-2和li等关键词的内容

contains_item2AndLi_text = html.xpath(\'//*[contains(@class,"item-2") and contains(@class,"li")]//text()\')
print(contains_item2AndLi_text)
>> [\'second item\']

匹配包含code属性的所有属性值

code_values = html.xpath(\'//@code\')
print(code_values)
>> [\'84\', \'104\', \'223\']

多条件匹配

terms_text = html.xpath(\'//div[@id="testid"]/h2/text() | //li[@data]/text()\')
print(terms_text)
>> [\'这里是个小标题\', \'1\', \'2\', \'3\']

选取div标签id属性为testid下的所有子节点ul标签下的li标签的内容

div_childrens_ul_li_text = html.xpath(\'//div[@id="testid"]/child::ul/li/text()\')
print(div_childrens_ul_li_text)
>> [\'84\', \'104\', \'223\']

选取div标签中的所有属性值

div_attributes = html.xpath(\'//div/attribute::*\')
print(div_attributes)
>> [\'99.8\', \'testid\', \'first\', \'go\']

定位div标签id属性为testid的父元素的price属性

div_ancestor_price = html.xpath(\'//div[@id="testid"]/ancestor::div/@price\')
print(div_ancestor_price)
>> [\'99.8\']

定位div标签id属性为testid的节点和父元素的节点的所有属性值

div_ancestorOrSelf_attributes = html.xpath(\'//div[@id="testid"]/ancestor-or-self::div/attribute::*\')
print(div_ancestorOrSelf_attributes)
>> [\'99.8\', \'testid\', \'first\']

定位div标签id属性为testid之后不包含id属性的div标签下所有的li中第一个li的text属性

div_notID_li1_text = html.xpath(\'//div[@id="testid"]/following::div[not(@id)]/.//li[1]/text()\')
print(div_notID_li1_text)
>> [\'test1\']

选取div标签id属性为testid节点下的所有命名空间节点

div_namespaces = html.xpath(\'//div[@id="testid"]/namespace::*\')
print(div_namespaces)
>> [(\'xml\', \'http://www.w3.org/XML/1998/namespace\')]

选取data值为one的父节点的子节点中最后一个节点的值 ps:注意这里的用法,parent::父节点的名字

parent_dataOne_ol_li1_text = html.xpath(\'//li[@data="one"]/parent::ol/li[last()]/text()\')
print(parent_dataOne_ol_li1_text)
>> [\'3\']

选取div标签id属性为testid节点标签开始之前的div标签下的ul标签第一个li标签的内容

div_preceding_div_ul_li1_text = html.xpath(\'//div[@id="testid"]/preceding::div/ul/li[1]/text()\')
print(div_preceding_div_ul_li1_text)
>> [\'时间\']

统计li标签属性为data的数量

li_data_count = html.xpath(\'count(//li[@data])\')
print(li_data_count)
>> 3.0

 

>> 第六篇|非结构化与结构化数据提取之Xpath

关注公众号【时光python之旅】,在这里你能学到更多Python知识。

分类:

技术点:

相关文章: