1.什么是xpath?

Xpath,全称XML Path Language,即XML路径语言。它是一门在XML之后查找信息的语言,也同样适用于HTML文档的搜索。在做爬虫的时候,我们用XPath语言来做相应的信息抽取。

2.为什么要学习xpath?

  • xpath可用于xml和html
  • xpath比正则表达式更加简单和强大
  • scrapy也支持xpath语法

3.节点

  • 父节点
  • 子节点
  • 后代节点
  • 兄弟节点

4.常用规则

实例如下: //title[@lang='eng']  ,这个表达式的意思是选择所有名称为titile,同时属性为eng的节点。

5.demo

#对html2文本的读取
from lxml import etree #从lxml库导入etree模块,lxml是python的一个解析库,支持HTML和XML的解析,而且效率非常高。
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) #对文本进行初始化,构造出一个XPath解析对象,etree模块可以对不完整的代码进行补全修正。
result = etree.tostring(html) #Xpath解析对象是bytes类型,用toString方法转换成string类型
print(result.decode('utf-8')) 运行结果:

C:\Users\Mr.Su\PycharmProjects\KUGOU\venv\Scripts\python.exe C:/Users/Mr.Su/PycharmProjects/KUGOU/venv/test1.py
<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>

Process finished with exit code 0

from lxml import etree

html = etree.parse('./test.html',etree.HTMLParser()) #构造Xpath解析对象
result = etree.tostring(html) #将byte类型转换成String类型
print(result.decode('utf-8')) #以utf-8字符格式打印 运行结果:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<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('./test.html',etree.HTMLParser())
result = html.xpath('//*') #*表示匹配所有节点
print(result) 运行结果:

[<Element html at 0x1b7f972ce48>, <Element body at 0x1b7f972cf48>, <Element div at 0x1b7f972cf88>,

 <Element ul at 0x1b7f972cfc8>, <Element li at 0x1b7f973c048>, <Element a at 0x1b7f973c0c8>,

 <Element li at 0x1b7f973c108>, <Element a at 0x1b7f973c148>, <Element li at 0x1b7f973c188>,

 <Element a at 0x1b7f973c088>, <Element li at 0x1b7f973c1c8>, <Element a at 0x1b7f973c208>, <Element li at 0x1b7f973c248>, <Element a at 0x1b7f973c288>]

#可以看到,返回形式是一个列表,每个元素都是Element类型,后面格式节点的名称:html、body、li等等。


#匹配所有的li节点
from lxml import etree html = etree.parse('./test.html',etree.HTMLParser())
result = html.xpath('//li') #匹配所有的li节点
print(result)
print(result[0]) #获取列表中的第一个li元素 运行结果:[<Element li at 0x267c93acf48>, <Element li at 0x267c93acf88>, <Element li at 0x267c93acfc8>,
<Element li at 0x267c93bc048>, <Element li at 0x267c93bc088>]
         <Element li at 0x267c93acf48>

#匹配li元素的子节点
from lxml import etree html = etree.parse('./test.html',etree.HTMLParser())
result = html.xpath('//li/a') #匹配所有的li节点的直接a子节点
# result = html.xpath('//li//a')
#匹配所有的li节点的子孙a节点
print(result) print(result[])

运行结果:

[<Element a at 0x26fa694cf08>, <Element a at 0x26fa694cf48>, <Element a at 0x26fa694cf88>, <Element a at 0x26fa694cfc8>, <Element a at 0x26fa695c048>]
<Element a at 0x26fa694cf08>

总结: / 用于获取直接子节点,//用于获取所有子孙节点

from lxml import etree

html = etree.parse('./test.html',etree.HTMLParser())
result = html.xpath('//ul/a') #匹配所有的ul节点的a直接子节点
print(result)
print(result[0]) 运行结果:

Traceback (most recent call last):
File "C:/Users/Mr.Su/PycharmProjects/KUGOU/venv/test2.py", line 6, in <module>
print(result[0])
IndexError: list index out of range

#显然无法获取到,因为a节点是ul的子孙节点,而不是直接子节点。将路径表达式改为'//ul/a'即可。


#父节点的获取:获取href为link4.html的a节点,在获取其父节点的class属性
<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>
from  lxml import etree

html = etree.parse('./test.html',etree.HTMLParser())#构造xpath解析对象
result = html.xpath('//a[@href="link4.html"]/../@class')
#
result = html.xpath('//a[@href="link4.html"]/parent::*/@class') 也可以使用parent::来获取
print(result)

运行结果:['item-1']
#属性匹配:匹配class ='item-inactive' 的li节点的直接节点的内容

from lxml import etree html = etree.parse('./test.html',etree.HTMLParser()) #构造XPath解析对象 
result = html.xpath('//li[@class="item-inactive"]/a')
print(result[].text) 运行结果:third item
#用text()方法获取节点中的文本
from lxml import etree html = etree.parse('./test.html',etree.HTMLParser())
resulet = html.xpath('//li[@class="item-0"]/a/text()')
print(resulet)
运行结果:['first item', 'fifth item']
#属性获取:获取li元素的所有直接a节点的href属性
from lxml import etree html = etree.parse('./test.html',etree.HTMLParser())
resulet = html.xpath('//li/a/@href')
print(resulet)
运行结果:['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']
#属性多值匹配
from lxml import etree text = '''
<li class = "li li-first"><a href = "link.html">first item</a></li>
'''
html = etree.HTML(text)
resulet = html.xpath('//li[@class="li"]/a/text()')
print(resulet) 运行结果: []
#在这个案例中,li元素的class属性有多个值,只用其中的一个值来匹配是无法匹配到的。
#遇到这样的情况需要用contains函数来匹配: contains(属性名称,属性值)
resulet = html.xpath('//li[contains(@class,"li")]/a/text()') 
运行结果:
['first item']
#多属性匹配
'''
当我们需要根据多个属性来确定一个节点时就可以用一些运算符来连接多个属性。
from lxml import etree text = '''
<li class = "li li-first" name="item"><a href = "link.html">first item</a></li>
'''
html = etree.HTML(text)
resulet = html.xpath('//li[contains(@class,"li")and @name="item"]/a/text()')
print(resulet)

#按序选择节点
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)
resulet = html.xpath('//li[1]/a/text()') #特别注意,这里的序号是从1开始而不是0
print(resulet)
resulet = html.xpath('//li[last()]/a/text()') #选取最后一个节点
print(resulet)
resulet = html.xpath('//li[position()<3]/a/text()') #选取序号小于3的节点
print(resulet)
resulet = html.xpath('//li[last()-2]/a/text()') #选取倒数第三个
print(resulet) 运行节点:

['first item']
['fifth item']
['first item', 'second item']
['third item']

#用节点轴获取节点
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)
resulet = html.xpath('//li[1]/ancestor::*') #调用了ancestor::轴获取祖先节点,*表示匹配所有祖先节点。
print(resulet)
resulet = html.xpath('//li[1]/ancestor::div') # 获取所有div祖先节点
print(resulet)
resulet = html.xpath('//li[1]/attribute::*') #调用attribute::轴获取属性值,attribute表示所有的属性值
print(resulet)
resulet = html.xpath('//li[1]/child::a[@href="link1.html"]') #调用child::轴获取直接子节点,a[@href="link1.html"]表示href属性等于link1.html的a节点
print(resulet)
result = html.xpath('//li[1]/descendant::span') #调用descendant::轴获取子孙节点。
print(resulet)
resulet = html.xpath('//li[1]/following::*[2]') #调用following::轴获取当前节点之后的所有节点,*[]表示获取所有节点的第二个后续节点。
print(result)
resulet = html.xpath('//li[1]/following-sibling::*') #调用following-sibling::节点获取当前节点之后的所有同级节点。
print(resulet) 运行结果:

[<Element html at 0x152b7c99208>, <Element body at 0x152b7c99188>, <Element div at 0x152b7c99148>, <Element ul at 0x152b7c99248>]
[<Element div at 0x152b7c99148>]
['item-0']
[<Element a at 0x152b7c99248>]
[<Element a at 0x152b7c99248>]
[]
[<Element li at 0x152b7c99148>, <Element li at 0x152b7c99288>, <Element li at 0x152b7c992c8>, <Element li at 0x152b7c99308>]


爬虫——xpath的更多相关文章

  1. 笔记-爬虫-XPATH

    笔记-爬虫-XPATH 1.      xpath XPath是W3C的一个标准.它最主要的目的是为了在XML1.0或XML1.1文档节点树中定位节点所设计.目前有XPath1.0和XPath2.0两 ...

  2. python爬虫xpath

    又是一个大晴天,因为马上要召开十九大,北京地铁就额外的拥挤,人贴人到爆炸,还好我常年挤地铁早已练成了轻功水上漂,挤地铁早已经不在话下. 励志成为一名高级测试工程师的我,目前还只是个菜鸟,难得有机会,公 ...

  3. python爬虫xpath的语法

    有朋友问我正则,,okey,其实我的正则也不好,但是python下xpath是相对较简单的 简单了解一下xpath: XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML ...

  4. Python网络爬虫-xpath模块

    一.正解解析 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线.中文 \W : 非\ ...

  5. [Python 练习爬虫] XPATH基础语法

    XPATH语法: // 定位根标签 / 往下层寻找 /text() 提取文本内容 /@xxx 提取属性内容 Sample: import requests from lxml import etree ...

  6. 爬虫 - xpath 匹配

    例题 import lxml.html test_data = """ <div> <ul> <li class="item-0& ...

  7. 爬虫--XPATH解析

    今天说一下关于爬取数据解析的方式---->XPATH,XPATH是解析方式中最重要的一种方式 1.安装:pip install lxml  2.原理 1. 获取页面源码数据 2.实例化一个etr ...

  8. 爬虫 xpath

    xpath简介 1.xpath使用路径表达式在xml和html中进行导航 2.xpath包含标准函数库 3.xpath是一个w3c的标准 xpath节点关系 1.父节点 2.字节点 3.同胞节点 4. ...

  9. 爬虫 xpath 获取方式

    回顾 bs4 实例化bs对象,将页面源码数据加载到该对象中 定位标签:find('name',class_='xxx') findall() select() 将标签中的文本内容获取 string t ...

随机推荐

  1. C++多线程同步技巧(二)--- 事件

    简介 Windows在线程控制方面提供了多种信号处理机制,其中一种便是使用 CreateEvent() 函数创建事件,然后使用信号控制线程运行.其中将事件变为有信号可使用 SetEvent() 函数, ...

  2. php 计算出一年中每周的周一日期

    最近接到一个任务,归纳起来,就是:要算出每年当中,每周的周一日期.想了一会,看了下date函数,深入了解了一下date函数各个参数的含义之后,终于把这道题做出来了! 在date()函数中,有一个参数对 ...

  3. Java的基础知识三

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  4. Eclipse debug 断点不能调试 ,Eclipse Unable to install breakpoint in 解决办法

    解决:[1]项目工程名 ,右键 --> properties --> java compiler -->class file Generation 位置  Add line numb ...

  5. jQ not()选择器 与 css3 :not( selector )选择器

    1.jQ  not() 2.css3 not  w3c在线演示地址  http://www.w3school.com.cn/tiy/t.asp?f=css_sel_not 总结: 注意两者还是有区别的 ...

  6. Linux平台上轻松安装与配置Domino

    Linux平台上轻松安装与配置Domino Domino Server的编译安装过程中需要用到libstdc++-2.9和glibc-2.1.1(或者其更高的版本)两个编译模块,它们是Linux开发编 ...

  7. (4)Python列表list

       

  8. Python:Day14 集合、函数

    浅copy只copy一层 深copy相当于克隆一份 深copy要引入copy,具体如下: import copy wife = copy.copy() #此为浅copy,括号中要加copy的对象,相当 ...

  9. 002_logging

    Java 中最通用的日志模块莫过于 Log4j 了,在 python 中,也自带了 logging 模块,该模块的用法其实和 Log4j 类似. Python 使用logging模块记录日志涉及四个主 ...

  10. web3js learning

    使用console.log(web3.version.api);来查看了web3的版本是0.20.1, 参考文档在:https://github.com/ethereum/wiki/wiki/Java ...