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. 近日使用Taro框架的一点小心得

    1.yarn npm安装的包,跟权限问题有关,与网络也有关 2.Vue框架首先,是解决了view-model的问题,解放开发的双手,使得显示和数据和控制分开 3.当你觉得最近没有技术文章看时,就看收藏 ...

  2. js模块化规范—commonjs

    commonjs规范说明 每个js文件都可当作一个模块 在服务器端: 模块的加载是运行时同步加载的(不会阻塞,等待时间回比较长).在浏览器端: 模块需要提前编译打包处理 commonjs规范基本语法 ...

  3. MySQL高级知识(十四)——行锁

    前言:前面学习了表锁的相关知识,本篇主要介绍行锁的相关知识.行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高. 0.准备 #1.创建相关测试表tb_ ...

  4. windows通过node环境搭建安装npm,cnpm,vue-cli

    1首先下载node,官网地址:https://nodejs.org/en/ 左边是稳定版,右边是最新版,安装过程一样,我选择的是稳定版. 按照步骤一步一步的安装就行,注意路径就可以了. 友情链接:ht ...

  5. ASP.NET 应用程序遭遇Server Application Unavailable问题的解决的方法

    公司服务器有.NET2的应用在执行,而我使用了.NET4平台开发,本机測试没问题,扔服务器发现要么我的新平台不好使,要么.NET2的旧平台不好使,各种重新启动IIS服务和WWW服务都无济于事 当我意识 ...

  6. oracle 多版本

    并发控制 concurrency control 数据库提供的函数集合,允许多个人同时访问和修改数据. 锁(lock)是Oracle管理共享数据库资源并发访问并防止并发数据库事务之间“相互干涉”的核心 ...

  7. UVA12569-Planning mobile robot on Tree (EASY Version)(BFS+状态压缩)

    Problem UVA12569-Planning mobile robot on Tree (EASY Version) Accept:138  Submit:686 Time Limit: 300 ...

  8. SpringBoot注册登录(三):注册--验证账号密码是否符合格式及后台完成注册功能

    SpringBoot注册登录(一):User表的设计点击打开链接SpringBoot注册登录(二):注册---验证码kaptcha的实现点击打开链接      SpringBoot注册登录(三):注册 ...

  9. 【转】Android多进程总结一:生成多进程(android:process属性)

    前言 正常情况下,一个apk启动后只会运行在一个进程中,其进程名为apk的包名,所有的组件都会在这个进程中运行,以下为DDMS的进程截屏: com.biyou.multiprocess为进程名,也是a ...

  10. Centos7 安装配置mysql5.6

    Centos7下完美安装并配置mysql5.6   Centos7将默认数据库mysql替换成了Mariadb,对于我们这些还想用mysql的人来说并不是一个好消息. 最近我搜罗了网上各种安装教程,各 ...