一、什么是xml?
- 定义:可扩展性标记语言
- 特点:xml是具有自描述结构的半结构化数据
- 作用:xml 主要设计宗旨是用来传输数据的,他还可以作为配置文件。
二、xml和html的区别
-
1. 语法要求不同
- html 不区分大小写,xml 区分,xml的语法要求更严格
- html有时可以省去尾标签,xml 不能省略任何标签,严格按照嵌套首位结构
- 只有xml中有自闭标签(没有内容的标签,只有属性)
- 在 html 中属性名可以不带属性值,xml必须带属性值
- 在 xml 中属性必须用引号括起来,html 中可不加引号
-
2. 作用不同
- html 主要设计用来显示数据,以及更好的显示数据
- xml 主要设计宗旨就是用来传输数据
-
3. 标记不同
- xml 没有固定标记,html 的标记都是固定的,不能自定义。
三、xpath
什么是xpath
是一种筛选 HTML 或者 xml 页面元素的【语法】
一些名词:元素,标签,属性,内容
解析方法:dom 和 sax
xpath语法
选取节点
路径表达式 | 意义 |
---|---|
nodename | 选取此标签以及其所有子标签 |
/ | 从根节点开始选取 |
// | 从任意节点开始,不考虑他们的位置。示例://book 从任何位置,取出所有的book标签 |
. | 从当前节点开始找 |
… | 从父节点开始找 |
@ | 选取属性,后面加标签的属性 |
text() | 选取内容 |
谓语
[ ]:写在谁的后面,就限定谁,一般用于限定元素或者标签
常见谓语 | 意义 |
---|---|
[@class] | 选取有class属性的节点 |
[@class=‘abc’] | 选取 class 属性为 abc 的节点 |
[contains(@href,‘baidu’)] | 选取 href 属性包含baidu 的标签 |
[1] | 选取第一个 |
[last()] | 选取最后一个 |
[last() - 1] | 选取倒数第二个 |
[position() > 2] | 跳过前两个 |
book[price > 30] | 选取属性 price 的值大于30的节点 |
通配符
* :匹配任意节点
@* :匹配任意属性
选取若干路径
| : 左边和右边的 xpath 选的内容都要,相当于 and的意思
lxml模块
-
导包
from lxml import etree
-
将字符串形式的 xml内容解析为可以调用 xpath语法的element对象的方法
from lxml import etree
string = '''
<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(string)
print(html)
new_string = etree.tostring(html, pretty_print=True).decode('utf-8')
print(new_string)
引用外部html
from lxml import etree
# 读取外部文件
html = etree.parse('deml.html')
# 解析element对象
string = etree.tostring(html,pretty_print=True).decode('utf-8')
- 返回一个element元素后,使用xpath方法筛选数据
from lxml import etree
text='''
<div>
<ul>
<li class="item-0" >
<a href="link1.html" class = "a_1">first item</a>
</li>
<li class="item-1">
<a href="link2.html">second item</a>
</li>
<li class="item-inactive">
<a href="link3.html" class = "a_2">123</a>
<span class="span_item1" >span_text1</span>
</li>
<li class="item-1">
test
<a href="link4.html" class="bold">fourth item
<span class="span_item2">span_text2</span>
</a>
</li>
<li class="item-0">
<a href="link5.html">fifth item</a>
</li>
</ul>
</div>
'''
tree = etree.HTML(text)
#1. 获取所有的 <li> 标签
li_list = tree.xpath('//li')
print(li_list)
#2.继续获取<li> 标签的所有 class属性
li_class = tree.xpath('//li/@class')
print(li_class)
#3.继续获取<li>标签下href 为 link1.html 的 <a> 标签
a = tree.xpath('//li/a[@href="link1.html"]')
print(a)
#4.获取<li> 标签下的所有 <span> 标签(包括孙子span)
spans = tree.xpath('//li//span')
print(spans)
#5.获取 <li> 标签下的<a>标签里的所有 class
a_class = tree.xpath('//li/a/@class')
print(a_class)
#6.获取最后一个 <li> 的 <a> 的 href
a_href = tree.xpath('//li[last()]/a/@href')
print(a_href)
#7.获取倒数第二个元素的内容
element_c = tree.xpath('//*[last()-1]/text()')
print(element_c)
#8.获取 class 值为 bold 的标签名
tagname = tree.xpath('//*[@class="bold"]')[0]
#标签元素.tag可以获取标签的内容
print(tagname.tag)
打印结果
[<Element li at 0x1cd643eed08>, <Element li at 0x1cd643eec88>, <Element li at 0x1cd643eed88>, <Element li at 0x1cd643eedc8>, <Element li at 0x1cd643eee08>]
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
[<Element a at 0x1cd643eeec8>]
[<Element span at 0x1cd643eef08>, <Element span at 0x1cd643eef48>]
['a_1', 'a_2', 'bold']
['link5.html']
['123', '\n test\n ', '\n ']
a
from lxml import etree
html = '''
<bookstore>
<title>新华书店</title>
<book href="http://www.langlang2017.com/">
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="zh">Learning XML</title>
<price>39.95</price>
</book>
<book href="www.baidu.com">
<title>python 大全</title>
<price>99.95</price>
</book>
</bookstore>
'''
tree = etree.HTML(html)
print(tree)
#(1)获取文档中的所有book节点的第一个book节点
first_book = tree.xpath('//bookstore/book[1]')
#(2)获取第一个book节点
first_book = first_book[0]
print(first_book)
#(3)获取first_book当前节点下的href
href = first_book.xpath('.//@href')
print(href)
#(4)获取当前节点的父节点下的book节点的href属性
hrefs = first_book.xpath('..//book/@href')
print(hrefs)
#(5)获取价格小于40的书的书名
book_name = tree.xpath('//book[price<40]/title/text()')
print(book_name)
#(6)获取价格等于99.95的书的书名
book_name = tree.xpath('//book[price=99.95]/title/text()')
print(book_name)
#(7)获取book标签下面的title和price标签
result = tree.xpath('//book/title|//book/price')
print(result)
#(8)获取属性href含有baidu字符串的book标签,获取此标签的书名
book_name = tree.xpath('//book[contains(@href,"baidu")]/title/text()')
print(book_name)
#(9)获取前面两个属于bookstore标签的字标签的book标签,获取此标签的书名
book_names = tree.xpath('//bookstore/book[position()<3]/title/text()')
print(book_names)
#(10)匹配任何属性节点
tags = tree.xpath('//*[@*]')
print(len(tags))
#(11)获取所有带有属性title标签,获取此标签的内容
name = tree.xpath('//title[@*]/text()')
print(name)
打印结果
<Element html at 0x1c94ec0ec88>
<Element book at 0x1c94ec0ed88>
['http://www.langlang2017.com/']
['http://www.langlang2017.com/', 'www.baidu.com']
['Harry Potter', 'Learning XML']
['python 大全']
[<Element title at 0x1c94ec0eec8>, <Element price at 0x1c94ec0ef08>, <Element title at 0x1c94ec0ef48>, <Element price at 0x1c94ec0ef88>, <Element title at 0x1c94ec0ee48>, <Element price at 0x1c94ec28048>]
['python 大全']
['Harry Potter', 'Learning XML']
4
['Harry Potter', 'Learning XML']