文章目录

  • 引入
  • 什么是XML
    • XML的节点关系
  • XPath定义
  • XPath表达式
    • 最常用的路径表达式
    • 常用路径表达式以及表达式的结果
    • 谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中
    • 选取未知节点
    • 选取若干路径,通过在路径表达式中使用“|”运算符,您可以选取若干个路径
    • XPath的运算符
  • lxml库
    • 定义
    • lxml数据转换
    • lxml读取文件
    • XPath具体用法
  • XPath案例

引入

有人说,我正则用的不好,处理HTML文档很累,有没有其他的方法?

有!那就是XPath,我们可以先将网络获取的String类型数据转换成 HTML/XML文档,然后用 XPath 查找 HTML/XML 节点或元素。

什么是XML

大家都知道HTML,那XML又是什么呢?

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种标记语言,很类似 HTML
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 的标签需要我们自行定义。
  • XML 被设计为具有自我描述性。
  • XML 是 W3C 的推荐标准

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vUeRZNSF-1590634079149)(C:\Users\王利钦\Desktop\爬虫总结\XML图解1.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Pxx1cJ1-1590634079153)(C:\Users\王利钦\Desktop\爬虫总结\XML图解2.jpg)]

XML的节点关系

父、子、同胞、先辈、后代

XPath定义

XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。

XPath表达式

  • 最常用的路径表达式
    通配符 描述
    / 从根节点选取。
    // 从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置。
    . 选取当前节点。
    选取当前节点的父节点。
    @ 选取属性。
  • 常用路径表达式以及表达式的结果
    表达式 结果
    /bookstore 选取根元素bookstore。注释:假如路径起始于正斜杆(/),则此路径始终代表到某元素的绝对路径!
    bookstore/book 选取属于bookstore的子元素的所有book元素
    //book 选取所有book子元素,而不管它们在文档中的位置。
    bookstore//book 选取属于bookstore元素的后代的所有book元素,而不管它们位于bookstore之下的什么位置。
    //@lang 选取名为lang的所有属性
  • 谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中
    路径表达式 结果
    /bookstore/book[1] 选取属于bookstore子元素的第一个book元素。
    /bookstore/book[last()] 选取属于bookstore子元素的最后一个book元素。
    /bookstore/book[last()-1] 选取属于bookstore子元素的倒数第二个book元素。
    /bookstore/book[postion()❤️] 选取最前面的两个属于bookstore元素的子元素的book元素。
    //title[@lang] 选取所有拥有名为lang的属性的title元素。
    //title[@lang=‘eng’] 选取所有title元素,且这些元素拥有值为eng的lang属性。
    /bookstore/book[price>35.00] 选取bookstore元素的所有book元素,且其中的price元素的值须大于35.00。
    /bookstore/book[price>35.00]/title 选取bookstore元素中的book元素的所有title元素,且其中的price元素的值须大于35.00。
  • 选取未知节点
    通配符 描述
    * 匹配任何元素节点。
    @* 匹配任何属性节点。
    路径表达式 结果
    /bookstore/* 选取bookstore元素的所有子元素。
    //* 选取文档中的所有元素。
    //title[@*] 选取所有带有属性的title元素。
  • 选取若干路径,通过在路径表达式中使用“|”运算符,您可以选取若干个路径
    路径表达式 结果
    //book/title|//book/price 选取book元素的所有title和price元素。
    //title|//price 选取文档中的所有title和price元素。
    /bookstore/book/title|//price 选取属于bookstore元素的book元素的所有title元素,以及文档中所有的price元素。
  • XPath的运算符
    运算符 描述 实例 返回值
    | 计算两个节点集 //book|//cd 返回所有拥有book和cd元素的节点集
    + 加法 6+4 10
    - 减法 6-4 2
    * 乘法 6*4 24
    div 除法 8div4 2
    = 等于 price=9.80 如果price是9.80,则返回true。如果price是9.90,则返回false。
    != 不等于 price!=9.80 如果price是9.90,则返回true。如果price是9.80,则返回false。
    < 小于 price<9.80 如果price是9.00,则返回true。如果price是9.90,则返回false。
    <= 小于或等于 price<=9.80 如果price是9.00,则返回true。如果price是9.90,则返回false。
    > 大于 price>9.80 如果price是9.90,则返回true。如果price是9.80,则返回false。
    >= 大于或等于 price>=9.80 如果price是9.90,则返回true。如果price是9.70,则返回false。
    or price=9.80 or price=9.70 如果price是9.80或者9.70,则返回true。
    and price>9.00 and price<9.90 如果price是9.80,则返回true。如果price是8.50,则返回false。
    mod 计算除法的余数 5 mod 2 1

lxml库

定义
  • lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。

  • lxml和正则一样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器,我们可以利用XPath语法,来快速的定位特定元素以及节点信息。

lxml数据转换
  • 源码

    from lxml import etreestr = '''<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>
    '''
    #利用etree.HTML,将String字符串解析为HTML文档
    html = etree.HTML(str)
    result = etree.tostring(html)
    print(result.decode('utf-8'))
    
  • 所得数据

 '''<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>
'''
lxml读取文件
  • 源码

    from lxml import etree# 读取外部文件 hello.html
    html = etree.parse('./hello.html')
    print(html)
    
  • 文件数据

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8" /><title>测试页面</title>
</head>
<body><ol><li class="haha">醉卧沙场君莫笑,古来征战几人回</li><li class="heihei">两岸猿声啼不住,轻舟已过万重山</li><li id="hehe" class="nene">一骑红尘妃子笑,无人知是荔枝来</li><li class="xixi">停车坐爱枫林晚,霜叶红于二月花</li><li class="lala">商女不知亡国恨,隔江犹唱后庭花</li></ol><div id="pp"><div><a href="http://www.baidu.com">李白</a></div><ol><li class="huanghe">君不见黄河之水天上来,奔流到海不复回</li><li id="tata" class="hehe">李白乘舟将欲行,忽闻岸上踏歌声</li><li class="tanshui">桃花潭水深千尺,不及汪伦送我情</li></ol><div class="hh"><a href="http://mi.com">雷军</a></div><div class="jj"><b href="http://mi.com"><c>3</c></b><b href="http://mi.com"><c>5</c></b><b href="http://mi.com"><c>6</c></b><b href="http://mi.com"><c>8</c></b><b href="http://mi.com"><c>9</c></b><b href="http://mi.com"><c>3</c></b></div><ol><li class="dudu">are you ok</li><li class="meme">会飞的猪</li></ol></div>
</body>
</html>
XPath具体用法
  • 被解析网页原码

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8" /><title>测试页面</title>
    </head>
    <body><ol><li class="haha">醉卧沙场君莫笑,古来征战几人回</li><li class="heihei">两岸猿声啼不住,轻舟已过万重山</li><li id="hehe" class="nene">一骑红尘妃子笑,无人知是荔枝来</li><li class="xixi">停车坐爱枫林晚,霜叶红于二月花</li><li class="lala">商女不知亡国恨,隔江犹唱后庭花</li></ol><div id="pp"><div><a href="http://www.baidu.com">李白</a></div><ol><li class="huanghe">君不见黄河之水天上来,奔流到海不复回</li><li id="tata" class="hehe">李白乘舟将欲行,忽闻岸上踏歌声</li><li class="tanshui">桃花潭水深千尺,不及汪伦送我情</li></ol><div class="hh"><a href="http://mi.com">雷军</a></div><div class="jj"><b href="http://mi.com"><c>3</c></b><b href="http://mi.com"><c>5</c></b><b href="http://mi.com"><c>6</c></b><b href="http://mi.com"><c>8</c></b><b href="http://mi.com"><c>9</c></b><b href="http://mi.com"><c>3</c></b></div><ol><li class="dudu">are you ok</li><li class="meme">会飞的猪</li></ol></div>
    </body>
    </html>
    
  • 获取所有的< li >标签

    from lxml import etreehtml = etree.parse('hello.html')
    li_list = html.xpath('//li')print(li_list)  # 打印<li>标签的元素集合
    print(len(li_list))
    
  • 继续获取< li > 标签的所有 class属性

    from lxml import etreehtml = etree.parse('hello.html')
    result = html.xpath('//li/@class')
    print(result)
    
  • 继续获取< li >标签下href为 link1.html 的 < a > 标签

    from lxml import etree
    html = etree.parse('./hello.html')
    result = html.xpath('//li/a[@href="link1.html"]')
    print(result)
    
  • 获取< li >标签下的所有< span >标签

    from lxml import etree
    data = '''
    <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"><span class="bold">third item</span></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>'''
    html = etree.HTML(data)
    result = html.xpath('//li//span')
    print(result[0].text)
    
  • 获取< li >标签下的< a >标签的所有class

    # 获取 <li> 标签下的<a>标签里的所有 class
    from lxml import etree
    html = etree.parse('hello.html')
    result = html.xpath('//li/a//@class')print(result)
    
  • 获取最后一个< li >的< a >的href

    from lxml import etreexml = etree.parse('./hello.html')result = xml.xpath('//li[last()]/a/@href')print(result)
    
  • 获取倒数第二个元素的内容

    from lxml import etreehtml = etree.parse('hello.html')
    result = html.xpath('//li[last()-1]/a')
    print(result[0].text)
    print(result)
    
  • 获取class值为bold的标签名

    # 获取 class 值为 bold 的标签名
    from lxml import etree
    html = etree.parse('hello.html')
    result = html.xpath('//*[@class="bold"]')
    # tag方法可以获取标签名
    print(result[0].tag)
    print(result[0].text)
    
  • 条件使用

    • 获取文本数据://li[@id=“hehe”]/text()
    • 包含某个条件://li[contains(@class,“h”)]
    • 等于某个条件://div[@id=“pp”]/ol[last()]/li/@*
    • 条件并用://li[@id=“hehe”] [@class=“nene”]/text()

XPath案例

import requests
from lxml import etree
url1 = 'https://www.neihanba.com/dz/'
url = 'https://www.neihanba.com/dz/list_%d.html'
if __name__ == '__main__':fp = open('./duanzi.csv',mode = 'a',encoding='utf-8')for i in range(1,101):if i == 1:url_duanzi = url1else:url_duanzi = url%(i)response = requests.get(url_duanzi)response.encoding = 'gbk'content = response.texthtml = etree.HTML(content)result = html.xpath('//ul[@class="piclist longList"]/li')for li in result:try:title = li.xpath('.//h4/a/b/text()')[0]content = li.xpath('.//div[@class="f18 mb20"]/text()')[0].strip().strip('\n')info = ''.join(li.xpath('.//div[@class="ft"]/span//text()')[1:])fp.write('%s\t%s\t%s\n'%(title,content,info))except Exception as e:# 异常保存,第二天,分析,单独爬取。passprint('第%d页内容保存成功!'%(i))fp.close()# !!!缺少异常捕获

网络爬虫之网页数据解析(XPath)相关推荐

  1. 网络爬虫之网页数据解析(bs4)

    文章目录 定义 实例数据 遍历文档树 搜索文档树 CSS选择器 bs4实例 定义 和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HT ...

  2. java爬取网页数据_Python网络爬虫实战(二)数据解析

    Python网络爬虫实战 (二)数据解析 本系列从零开始阐述如何编写Python网络爬虫,以及网络爬虫中容易遇到的问题,比如具有反爬,加密的网站,还有爬虫拿不到数据,以及登录验证等问题,会伴随大量网站 ...

  3. python爬虫程序详解_Python网络爬虫之三种数据解析方式

    指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据解析.因为大多数情况下的需求,我们都会指 ...

  4. python爬虫解析数据包_Python网络爬虫之三种数据解析方式

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  5. Python网络爬虫实战(二)数据解析

    上一篇说完了如何爬取一个网页,以及爬取中可能遇到的几个问题.那么接下来我们就需要对已经爬取下来的网页进行解析,从中提取出我们想要的数据. 根据爬取下来的数据,我们需要写不同的解析方式,最常见的一般都是 ...

  6. 数据爬取 mail_Python网络爬虫实战,数据解析!

    上一篇说完了如何爬取一个网页,以及爬取中可能遇到的几个问题.那么接下来我们就需要对已经爬取下来的网页进行解析,从中提取出我们想要的数据. 根据爬取下来的数据,我们需要写不同的解析方式,最常见的一般都是 ...

  7. Python网络爬虫实战,数据解析!

    上一篇说完了如何爬取一个网页,以及爬取中可能遇到的几个问题.那么接下来我们就需要对已经爬取下来的网页进行解析,从中提取出我们想要的数据. 根据爬取下来的数据,我们需要写不同的解析方式,最常见的一般都是 ...

  8. beautifulsoup网页爬虫解析_Python3 网络爬虫快速入门实战解析

    点击上方"Python高校",关注 文末干货立马到手 作者:Jack Cui http://cuijiahua.com/blog/2017/10/spider_tutorial_1 ...

  9. python3 爬虫实例_【实战练习】Python3网络爬虫快速入门实战解析(上)

    原标题:[实战练习]Python3网络爬虫快速入门实战解析(上) 摘要 使用python3学习网络爬虫,快速入门静态网站爬取和动态网站爬取 [ 前言 ] 强烈建议:请在电脑的陪同下,阅读本文.本文以实 ...

最新文章

  1. java robot 控制鼠标_Java-探索Robot类:[2]自动控制鼠标
  2. 那些参加过创业赛事活动的创业者后来怎么样了?
  3. BCGSoft Demo示例展示:菜单示例集合(2/2)
  4. JS-获取class类名为某个的元素-【getClass】函数封装
  5. 使用Anemometer基于pt-query-digest将MySQL慢查询可视化
  6. Dx11DemoBase 基类(二) 初始化 DirectX11 的 4个基本步骤
  7. 英特尔开源WebRTC开发套件OWT
  8. C++ 普通函数与函数模板 区别以及调用规则01
  9. 程序员应该具备的素质(来自csdn)
  10. php调接口post,php模拟post提交请求,调用接口
  11. MYSQL 编码设置
  12. 自动门程序c语言,自动门控制程序共享
  13. linux网卡pci信息,在进行CGKlinux系统网络配置时,使用()命令可以查询出网卡的PCI编号与设备名的对应关系。...
  14. java技术栈_七天串起java技术栈-开篇
  15. mysql报错1241_flask内的mysql插入语句报错:1241, 'Operand should contain 1 column(s)
  16. IE Cookie 文件格式
  17. 简析struct in_addr ,struct sockadd
  18. 本文介绍在Wireshark网络协议分析仪中如果解密SSL和TLS流量
  19. UVALive - 5857 Captain Q's Treasure
  20. 查看Andriod内置浏览器WebView版本

热门文章

  1. Q1营收超预期,耐克离两千亿市值还差“临门一脚”?
  2. CAD如何高效绘制图纸?
  3. 听音室-HIFI入门之音响
  4. 编译recovery及过程中的部分错误解决
  5. laravel模型关联方法总结
  6. 支付战争的终极大决战在哪里?
  7. APS在印刷行业的应用前景和应用效益
  8. #CSS3#文本text-stroke文字描边及渐变
  9. 20220213协整
  10. RDD论文翻译 --弹性分布式数据集:一种基于内存的集群计算的容错性抽象方法