原文地址: 知乎-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>
基础语法
导入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知识。