[转载]Python爬虫之xpath使用技巧

原文地址: 知乎-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知识。

posted @ 2021-03-01 10:27  Python不秋  阅读(201)  评论(0编辑  收藏  举报