网络爬虫--11.XPath和lxml

文章目录

  • 一. XML
    • 1. XML 和 HTML 的区别
    • 2. XML文档示例
    • 3. HTML DOM 模型示例
    • 4. XML的节点关系
  • 二. 什么是XPath?
    • 1. 选取节点
    • 2. 谓语(Predicates)
    • 3. 选取未知节点
    • 4. 选取若干路径
    • 5. XPath的运算符
  • 三. lxml库
    • 1. 初步使用
    • 2. 文件读取
  • 四. XPath实例测试
    • 1. 获取所有的 < li> 标签
    • 2. 继续获取< li> 标签的所有 class属性
    • 3. 继续获取< li>标签下href 为 link1.html 的 < a> 标签
    • 4. 获取< li> 标签下的所有 < span> 标签
    • 5. 获取 < li> 标签下的< a>标签里的所有 class
    • 6. 获取最后一个 < li> 的 < a> 的 href
    • 7. 获取倒数第二个元素的内容
    • 8. 获取 class 值为 bold 的标签名

一. XML

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

有!那就是XPath,我们可以先将 HTML文件 转换成 XML文档,然后用 XPath 查找 HTML 节点或元素。

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

W3School官方文档:http://www.w3school.com.cn/xml/index.asp

1. XML 和 HTML 的区别

在这里插入图片描述

2. XML文档示例

<?xml version="1.0" encoding="utf-8"?><bookstore><book category="cooking"><title lang="en">Everyday Italian</title>  <author>Giada De Laurentiis</author>  <year>2005</year>  <price>30.00</price></book>  <book category="children"><title lang="en">Harry Potter</title>  <author>J K. Rowling</author>  <year>2005</year>  <price>29.99</price></book>  <book category="web"><title lang="en">XQuery Kick Start</title>  <author>James McGovern</author>  <author>Per Bothner</author>  <author>Kurt Cagle</author>  <author>James Linn</author>  <author>Vaidyanathan Nagarajan</author>  <year>2003</year>  <price>49.99</price></book><book category="web" cover="paperback"><title lang="en">Learning XML</title>  <author>Erik T. Ray</author>  <year>2003</year>  <price>39.95</price></book></bookstore>

3. HTML DOM 模型示例

HTML DOM 定义了访问和操作 HTML 文档的标准方法,以树结构方式表达 HTML 文档。
在这里插入图片描述

4. XML的节点关系

下面一个简单的XML例子中:

<?xml version="1.0" encoding="utf-8"?><bookstore><book><title>Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book></bookstore>
  1. 父(Parent) 每个元素以及属性都有一个父。book 元素是 title、author、year 以及 price 元素的父。
  2. 子(Children)元素节点可有零个、一个或多个子。title、author、year 以及 price 元素都是 book 元素的子。
  3. 同胞(Sibling)拥有相同的父的节点。title、author、year 以及 price 元素都是同胞。
  4. 先辈(Ancestor)某节点的父、父的父,等等。title 元素的先辈是 book 元素和 bookstore 元素。
  5. 后代(Descendant)某个节点的子,子的子,等等。bookstore 的后代是 book、title、author、year 以及 price 元素。

二. 什么是XPath?

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

W3School官方文档:http://www.w3school.com.cn/xpath/index.asp

XPath 开发工具
开源的XPath表达式编辑工具:XMLQuire(XML格式文件可用)
Chrome插件 XPath Helper
Firefox插件 XPath Checker

1. 选取节点

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

下面列出了最常用的路径表达式:

在这里插入图片描述

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:
在这里插入图片描述

2. 谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

在这里插入图片描述

3. 选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

在这里插入图片描述
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

4. 选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

在这里插入图片描述

5. XPath的运算符

下面列出了可用在 XPath 表达式中的运算符:

在这里插入图片描述

这些就是XPath的语法内容,在运用到Python抓取时要先转换为xml。

三. lxml库

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

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

lxml python 官方文档:http://lxml.de/index.html

需要安装C语言库,可使用 pip 安装:pip install lxml (或通过wheel方式安装)

1. 初步使用

我们利用它来解析 HTML 代码,简单示例:

from lxml import etreetext = '''
<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>
'''#利用etree.HTML,将字符串解析为HTML文档
print('------1------')
print(text)
print (type(text))html = etree.HTML(text)
print('-----2-------')
print(html)
print (type(html))# 按字符串序列化HTML文档
result = etree.tostring(html)
print('-----3-------')
print(result)
print (type(result))

输出结果:

------1------<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><class 'str'>
-----2-------
<Element html at 0x1e839453708>
<class 'lxml.etree._Element'>
-----3-------
b'<html><body><div>\n    <ul>\n         <li class="item-0"><a href="link1.html">first item</a></li>\n         <li class="item-1"><a href="link2.html">second item</a></li>\n         <li class="item-inactive"><a href="link3.html">third item</a></li>\n         <li class="item-1"><a href="link4.html">fourth item</a></li>\n         <li class="item-0"><a href="link5.html">fifth item</a> # &#27880;&#24847;&#65292;&#27492;&#22788;&#32570;&#23569;&#19968;&#20010; </li> &#38381;&#21512;&#26631;&#31614;\n     </ul>\n </div>\n</body></html>'
<class 'bytes'>

lxml 可以自动修正 html 代码,例子里不仅会补全 li 标签,还添加了 body,html 标签。

2. 文件读取

除了直接读取字符串,lxml还支持从文件里读取内容。我们新建一个hello.html文件:

<!-- hello.html --><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>

再利用 etree.parse() 方法来读取文件。

from lxml import etree# 读取外部文件 hello.html
html1 = etree.parse('./hello.html')
result1 = etree.tostring(html1, pretty_print=True)print('--------------------')
print(result1)print('-------如果是文件读取,需要使用prase(),而不是用HTML,否则会出现下边结果:---------')html2 = etree.HTML('./hello.html')
result2 = etree.tostring(html2, pretty_print=True)
print(result2)

运行结果:

--------------------
b'<div>\n    <ul>\n         <li class="item-0"><a href="link1.html">first item</a></li>\n         <li class="item-1"><a href="link2.html">second item</a></li>\n         <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>\n         <li class="item-1"><a href="link4.html">fourth item</a></li>\n         <li class="item-0"><a href="link5.html">fifth item</a></li>\n     </ul>\n </div>\n'
-------如果是文件读取,需要使用prase(),而不是用HTML,否则会出现下边结果:---------
b'<html>\n  <body>\n    <p>./hello.html</p>\n  </body>\n</html>\n'

四. XPath实例测试

1. 获取所有的 < li> 标签

from lxml import etreehtml = etree.parse('hello.html')
print (type(html))  # 显示etree.parse() 返回类型result = html.xpath('//li')print (result)  # 打印<li>标签的元素集合
print (len(result))
print (type(result))
print (type(result[0]))

输出结果:

<class 'lxml.etree._ElementTree'>
[<Element li at 0x21658f02608>, <Element li at 0x21658f02708>, <Element li at 0x21658f02748>, <Element li at 0x21658f02788>, <Element li at 0x21658f027c8>]
5
<class 'list'>
<class 'lxml.etree._Element'>

2. 继续获取< li> 标签的所有 class属性

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/@class')print(result)
print(type(result))

运行结果:

['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
<class 'list'>

3. 继续获取< li>标签下href 为 link1.html 的 < a> 标签


from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a[@href="link1.html"]')print result

输出结果:

[<Element a at 0x23b68132748>]
<class 'list'>

4. 获取< li> 标签下的所有 < span> 标签

from lxml import etreehtml = etree.parse('hello.html')#result = html.xpath('//li/span')
#注意这么写是不对的:
#因为 / 是用来获取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用双斜杠result = html.xpath('//li//span')print(result)
print(type(result))

输出结果:

[<Element span at 0x28d12587508>]
<class 'list'>

5. 获取 < li> 标签下的< a>标签里的所有 class

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a//@class')print(result)
print(type(result))

输出结果:

['bold']
<class 'list'>

6. 获取最后一个 < li> 的 < a> 的 href

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a//@class')print(result)
print(type(result))

输出结果:

['link5.html']
<class 'list'>

7. 获取倒数第二个元素的内容

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li[last()-1]/a')# text 方法可以获取元素内容
print (result[0].text)
print (type(result[0].text))

输出结果:

fourth item
<class 'str'>

8. 获取 class 值为 bold 的标签名

from lxml import etreehtml = etree.parse('hello.html')result = html.xpath('//*[@class="bold"]')# tag方法可以获取标签名
print (result[0].tag)
print (type(result[0].tag))

输出结果:

span
<class 'str'>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/452027.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件测试不是一个功能

今天在工作中我对一个同事说&#xff0c;PyDev 2.5.0现在对TDD&#xff08;测试驱动开发&#xff09;提供了很酷的支持了。我并不是一个对TDD很痴迷的倡导者&#xff0c;对其它事物也一样&#xff0c;但仍不免激起了一场讨论。这个家伙&#xff0c;让我们暂叫他约翰&#xff0c…

Linux 操作系统基础知识

1.操作系统总体介绍 •CPU&#xff1a; 就像人的大脑&#xff0c;主要负责相关事情的判断以及实际处理的机制。查询指令&#xff1a; cat /proc/cpuinfo•内存&#xff1a; 大脑中的记忆区块&#xff0c;将皮肤、眼睛等所收集到的信息记录起来的地方&#xff0c;以供CPU进行判断…

Transaction 那点事儿,Spring事务管理

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Transaction 也就是所谓的事务了&#xff0c;通俗理解就是一件事情。从小&#xff0c;父母就教育我们&#xff0c;做事情要有始有终&…

8.类定义、属性、初始化和析构

类定义 类 是一个独立存放变量(属性/方法)的空间 封装&#xff1a; 类可以把各种对象组织在一起&#xff0c;作为类的属性&#xff0c;通过 . (点)运算符来调用类中封装好的对象 属性&#xff1a; 变量在类中称为属性&#xff0c;但是类中的属性不仅仅只包含变量&#x…

网络爬虫--13.数据提取之JSON与JsonPATH

文章目录一. 前言二. JSON三. json.loads()四. json.dumps()五. json.dump()六. json.load()七. JsonPath八. JsonPath与XPath语法对比九. 案例分析一. 前言 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff0c;它使得人们很容易的进行阅读和编写。同时…

创建型模式二:工厂方法模式

1. 工厂模式介绍 工厂模式&#xff08;Factory Pattern&#xff09;的意义就跟它的名字一样&#xff0c;在面向对象程序设计中&#xff0c;工厂通常是一个用来创建其他对象的对象。工厂模式根据不同的参数来实现不同的分配方案和创建对象。 在工厂模式中&#xff0c;我们在创建…

spring 的4种事务管理(1种编程式+3种声明式)

见&#xff1a;http://blog.csdn.net/sinat_25926481/article/details/48208619 Spring的4种事务管理&#xff08;1种编程式事务三种声明事务&#xff09; 一、Spring事务的介绍 二、编程式事务xml的配置 注入后直接在service层调用模板的方法使用 三、基于AOP方式的声明式事务…

如何创造出更优秀的用户体验?

对于互联网公司来说&#xff0c;用户体验起到至关重要的作用&#xff0c;能否给用户留下深刻的印象&#xff1b;开发出的产品是否实用、易用&#xff1f;等等这些都是开发者必将思考的话题。当有用性一样的时候&#xff0c;大家的竞争重点就是易用性了&#xff0c;这就是互联网…

GitHub(从安装到使用)

一、安装Git for Windows&#xff08;又名msysgit&#xff09; 下载地址: https://git-for-windows.github.io/ 在官方下载完后&#xff0c;安装到Windows Explorer integration的时候&#xff0c;将选项中将“Git Bash here”和“Git GUI here”打对勾。 然后就一直next直到Fi…

Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别、不可重复读与幻读的区别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究&#xff0c;在此之间对Spring的事务配置虽说也配置过&#x…

Google编程之夏入围项目公布

Google编程之夏&#xff08;Google Summer of Code&#xff09;&#xff0c;是由Google公司所主办的年度程式设计比赛&#xff0c;第一届从2005年开始。“Summer of Code”之名取自1967年的“夏日之爱”&#xff08;Summer of Love&#xff09;风潮。比赛的主要目的是鼓励学生参…

微软:软件帝王的复兴之路

可以说在过去的两个月IT界所发生的一切都非同寻常&#xff0c;乔布斯辞职了&#xff0c;Google把Motorola并购了&#xff0c;微软炫了一下Windows 8&#xff0c;还宣布开始用ARM了&#xff0c;Google开始和英特尔合作了&#xff0c;AT&T与T-Mobile的并购也在紧密锣鼓进行中…

Eclipse GBK批量转UTF-8插件(转)

最近需要把Android项目转Android Studio&#xff0c;由于之前是eclipse开发&#xff0c;而且坑爹的是编码还是GBK的&#xff0c;转到Android Studio中文都是乱码&#xff0c;如果一个文件一个文件ctrlc的话&#xff0c;想想就累&#xff0c;几经Google&#xff0c;发现一个很好…

网络爬虫--15.【糗事百科实战】多线程实现

文章目录一. Queue&#xff08;队列对象&#xff09;二. 多线程示意图三. 代码示例一. Queue&#xff08;队列对象&#xff09; Queue是python中的标准库&#xff0c;可以直接import Queue引用;队列是线程间最常用的交换数据的形式 python下多线程的思考 对于资源&#xff0…

网络爬虫--16.BeautifulSoup4

文章目录一. BeautifulSoup4二. 解析实例三. 四大对象种类1. Tag2. NavigableString3. BeautifulSoup4. Comment四. 遍历文档树1.直接子节点 &#xff1a;.contents .children 属性1). .contents2). .children2. 所有子孙节点: .descendants 属性3. 节点内容: .string 属性五. …

【LA3415 训练指南】保守的老师 【二分图最大独立集,最小割】

题意 Frank是一个思想有些保守的高中老师。有一次&#xff0c;他需要带一些学生出去旅行&#xff0c;但又怕其中一些学生在旅行中萌生爱意。为了降低这种事情发生的概率&#xff0c;他决定确保带出去的任意两个学生至少要满足下面四条中的一条。 1.身高相差大于40厘米 2.性别相…

行车记录仪稳定方案:TC358778XBG:RGB转MIPI DSI芯片,M-Star标配IC

原厂&#xff1a;Toshiba型号&#xff1a;TC358778XBG功能&#xff1a;TC358778XBG是一颗将RGB信号转换成MIPI DSI的芯片&#xff0c;最高分辨率支持到1920x1200&#xff0c;其应用图如下&#xff1a;产品特征&#xff1a;MIPI接口&#xff1a;&#xff08;1&#xff09;、支持…

java.sql.SQLException: 无法转换为内部表示之解决

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 这个错是因为 数据库中字段类型和程序中该字段类型不一致。 比如程序将某字段当做Integer类型&#xff0c; 而数据库存储又使用另外一…

网络爬虫--17.【BeautifuSoup4实战】爬取腾讯社招

文章目录一.要求二.代码示例一.要求 以腾讯社招页面来做演示&#xff1a;http://hr.tencent.com/position.php?&start10#a 使用BeautifuSoup4解析器&#xff0c;将招聘网页上的职位名称、职位类别、招聘人数、工作地点、发布时间&#xff0c;以及每个职位详情的点击链接…

彻底搞清楚Android中的 Attr

版权声明&#xff1a;本文为sydMobile原创文章&#xff0c;转载请务必注明出处&#xff01; https://blog.csdn.net/sydMobile/article/details/79978187 相信这个词对于Android开发者来说十分熟悉了&#xff0c;那么你对他到底有多了解呢&#xff1f; 回忆起我刚开始接触Andr…