网络爬虫笔记【7】 利用 XPATH 实现 XML 和 HTML 文本信息提取

XML(Extensible Markup Language)指可扩展标记语言,被设计用来传输和存储数据。详细信息可参考 http://www.w3school.com.cn/xml
HTML指的是超文本标记语言 (Hyper Text Markup Language),是WWW上用于编写网页的主要工具,详细信息请参考 http://www.w3school.com.cn/html

XML和HTML都是一种标记语言 (markup language),使用标记标签来描述数据,这些标签可用于查找和定位数据。

下面是 xml 文档的一个例子:

<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
    <book>
        <title lang="eng">Harry Potter</title>
        <price>29.99</price>
    </book>
    <book>
        <title lang="eng">Learning XML</title>
        <price>39.95</price>
    </book>
</bookstore>
  • 父(Parent)每个元素以及属性都有一个父,上例中book 元素是 title、price 元素的父结点;
  • 子(Children)元素节点可有零个、一个或多个子,上例中 title、price 元素都是 book 元素的子结点;
  • 同胞(Sibling)拥有相同的父的节点,上例中title、price 为同胞结点;
  • 先辈(Ancestor)某节点的父、父的父等等,上例中title、price 的先辈结点是bookstore。
  • 后代(Descendant)某个节点的子,子的子,上例中bookstore的后代结点为 book、title、price。

XPath 语法

XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。细节可以参考W3School官方文档:http://www.w3school.com.cn/xpath/index.asp

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

XPath 开发工具有:

  • 开源的XPath表达式编辑工具:XMLQuire(XML格式文件可用)
  • Chrome插件 XPath Helper
  • Firefox插件 XPath Checker
# XPath 常用路径表达式学习
'''
<bookstore>
    <book>
        <title lang="eng">Harry Potter</title>
        <price>29.99</price>
    </book>
    <book>
        <title lang="eng">Learning XML</title>
        <price>39.95</price>
    </book>
</bookstore>
'''

# 下面列出了最常用的路径表达式
'bookstore'   # 选取 bookstore 元素的所有子节点
'/bookstore'  # 选取根元素 bookstore (假如路径起始于 / ,则此路径始终代表到某元素的绝对路径)
'bookstore/book'  # 选取属于 bookstore 的子元素的所有的 book 元素 
'//book'      # 选取所有的 book 元素,不管其位置在哪
'bookstore//book' # 选择 bookstore 后代元素中的所有 book 元素
'//@lang'     # 选取名为 lang 的所有属性

# 谓语
'/bookstore/book[1]'    # 选取属于 bookstore 子元素的第一个book 元素
'/bookstore/book[last()]'    # 选取属于 bookstore 子元素的最后一个 book 元素
'/bookstore/book[last()-1]'  # 选取属于 bookstore 子元素的倒数第二个 book 元素
'/bookstore/book[position < 3]'    # 选取属于 bookstore 子元素的前两个 book 元素
'//title[@lang]'        # 选取所有拥有名为 lang 的属性的 title 元素
'//title[@lang="lang"]'      # 选取所有 lang 属性值为 eng 的 title 元素
'/bookstore/book[price > 35.00]'   # 选取 bookstore 下,所有 price 元素值大于 35.00 的 book 元素
'/bookstore/book[price > 35.00]/title'  # 选取 bookstore 下,所有 price 元素值大于 35.00 的 book 元素的 title 子元素

# XPath 通配符
'/bookstore/*'  # 选取 bookstore 元素的所有子元素
'//*'           # 选取文档中的所有元素
'//title[@*]'   # 选取所有带属性的 title 元素

# | 运算符,可以选择若干条路径
'//book/title | //book/price'   # 选取 book 元素的所有 title 和 price 元素
'//title | //price'             # 选取文档中的所有 title 和 price 元素
'/bookstore/book/title | //price'   # 选取 bookstore/book 下的所有 title 元素,以及文档中所有的 price 元素

lxml 库

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

# lxml 解析 xml 文档的使用示例

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>
'''

# 利用 etree.HTML,将字符串解析为 HTML 文档
html = etree.HTML(text)
# 按字符串序列化 HTML 文档
result = etree.tostring(html)
print(result.decode('utf-8'))

# 注意:lxml 会自动补全缺少的 </li>闭合标签
运行结果:

<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>

除了直接读取字符串,lxml 还支持从文件里读取内容

# lxml 读取 xml 文档 的示例
from lxml import etree

# 读取外部文件 axmldoc.xml
html = etree.parse('./axmldoc.xml')
result = etree.tostring(html,pretty_print=True)

print(result.decode('utf-8'))

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 的标签名
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"><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(text)

# 获取所有的 li 标签
result = html.xpath('//li')
print(result)
print('---'*10)

# 获取 li 标签的所有 class 属性
result = html.xpath('//li/@class')
print(result)
print('---'*10)

# 继续获取 li 标签下href为 link1.html 的 a 标签
result = html.xpath('//li/a[@href="link1.html"]')
print(result)
print('---'*10)

# 获取li 标签下的所有span 标签
result = html.xpath('//li//span')
print(result)
print('---'*10)

# 获取 li 标签下的 a 标签里的所有 class
result = html.xpath('//li/a//@class')
print(result)
print('---'*10)

# 获取最后一个li 的 a 的 href
result = html.xpath('//li[last()]/a/@href')
print(result)
print('---'*10)

# 获取倒数第二个元素的内容
result = html.xpath('//li[last()-1]/a/text()')
print(result)
print('---'*10)

# 获取 class 值为 bold 的标签名
result = html.xpath('//*[@class="bold"]')
print(result[0].tag)

运行结果:

[<Element li at 0x1ef3eea6608>, <Element li at 0x1ef3eebd1c8>, <Element li at 0x1ef3eebd208>, <Element li at 0x1ef3eebd248>, <Element li at 0x1ef3eebd288>]
------------------------------
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
------------------------------
[<Element a at 0x1ef3eebd308>]
------------------------------
[<Element span at 0x1ef3ee0e088>]
------------------------------
['bold']
------------------------------
['link5.html']
------------------------------
['fourth item']
------------------------------
span
已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页