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. SSH 和 Git

    了解SSH SSH 以非对称加密实现身份验证.较常用的非对称加密有 RSA. 两种加密过程: 1.通过用户名密码访问服务器,即使传输的数据是加密的也可能会被劫持到不信任的服务器,泄露用户名和密码. 2 ...

  2. Unity Shader 基础(3) 获取深度纹理

    Unity提供了很多Image Effect效果,包含Global Fog.DOF.Boom.Blur.Edge Detection等等,这些效果里面都会使用到摄像机深度或者根据深度还原世界坐标实现各 ...

  3. 【Teradata】日期类型计算

    1.EXTRACT(抽取年/月/日/时/分/秒)  //抽取年/月/日/时/分/秒 SELECT EXTRACT (YEAR FROM CURRENT_DATE); SELECT EXTRACT (M ...

  4. nginx配置静态webserver

    配置静态的web,须要实现一个虚拟主机. step1: 准备工作             1  查看你的网卡地址(我的 192.168.223.135)                  #ifcon ...

  5. 【js】event(事件对象)详解

    1.事件对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 什么时候会产生Event 对象呢? 例如: 当用户单击某个元素的时候,我们给这个元 ...

  6. 001_HTTP参数中Etag的重要性

    在研究tornado时,有个Etag比较好奇,从网上查询摘录如下:

  7. IBus prior to 15.11 may cause input problems. See IDEA-78860 for details.

    启动 PyCharm 2017.2, 遇到问题: IBus prior to 15.11 may cause input problems. See IDEA-78860 for details. 解 ...

  8. 【Codeforces Round 650】Codeforces #334 (Div. 1)

    模拟CF650,ABC三题,RK90 Codeforces 650 A 思路:首先看式子 \(\sqrt{(x_i-x_j)^2+(y_i-y_j)^2}=|x_i-x_j|+|y_i-y_j|\) ...

  9. Linux中断管理 (1)Linux中断管理机制

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

  10. day95

    Linux基本部署配置及常见扩展应用 Linux软件包安装方法 1. 安装: 整个安装过程可以分为以下几步: 1) 取得应用软件:通过下载.购买光盘的方法获得: 2)解压缩文件:一般tar包,都会再做 ...