一、什么是xml
1、定义:可扩展标记性语言
2、特点:xml的是具有自描述结构的半结构化数据。
3、作用:xml主要设计宗旨是用来传输数据的。它还可以作为配置文件。
二、xml和html的区别
1、语法要求不同
xml的语法要求更严格。
- html不区分大小写,xml区分。
- html有时可以省略尾标签。xml不能省略任何标签,严格按照嵌套首尾结构。
- 只有xml中有自闭标签(没有内容的标签,只有属性。)
<a class='abc'/>
- 在html中属性名可以不带属性值。xml必须带属性值。
- 在xml中属性 必须用引号括起来,html中可以不加引号。
2、作用不同
html 主要设计用来显示数据以及更好的显示数据。
xml 主要设计宗旨就是用来传输数据。
3、标记不同
xml 没有固定 标记,html的标记都是固定的,不能自定义。
三、xpath
1、什么是xpath
xpath 是一种筛选 html或者xml页面元素的【语法】。
2、xml和html的一些名词
3、xml的两种解析方法
4、xpath语法
(1)选取节点
nodename | 选取此标签及其所有子标签 |
---|---|
/ | 从根节点开始选取 |
// | 从任意节点开始,不考虑他们的位置。 |
. | 当前节点开始找。 |
… | 当前节点的父节点 |
@ | 选取属性 |
text() | 选取内容 |
(2)谓语
【谓语】:起限定的作用,限定他前面的内容。
[ ]写在谁的后面,就限定谁,一般用于限定元素或者标签。
常见的谓语:
[@class] | 选取有class属性 |
---|---|
[@class=‘abc’] | 选取class属性为abc的节点。 |
[contains(@href,‘baidu’)] | 选取href属性包含baidu的标签 |
[1] | 选取第一个 |
[last()] | 选取最后一个 |
[last()-1] | 选取倒数第二个 |
[position()>2] | 跳过前两个 |
book[price>30] | 价格大于30的book标签 |
(3)通配符
* | 匹配任意节点 |
---|---|
@* | 匹配任意属性 |
(4)选取若干路径
| ---- 左边和右边的xpath选的内容都要 — and
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.获取倒数第二个元素的内容
contents = tree.xpath('//*[last()-1]/text()')
print(contents)
# 8.获取 class 值为 bold 的标签名
tags = tree.xpath('//*[@class="bold"]')
# 标签元素.tag可以获取标签的内容
for tag in tags:
print(tag.tag)
运行结果:
[<Element li at 0x212ab609688>, <Element li at 0x212ab609608>, <Element li at 0x212ab609748>, <Element li at 0x212ab609788>, <Element li at 0x212ab6097c8>]
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
[<Element a at 0x212ab609888>]
[<Element span at 0x212ab6098c8>, <Element span at 0x212ab609908>]
['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)
#(1)获取文档中bookstore节点下的第一个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属性
p_hrefs = first_book.xpath('..//book/@href')
print(p_hrefs)
#(5)获取价格小于40的书的书名
book1_names = tree.xpath('//book[price<40]/title/text()')
print(book1_names)
#(6)获取价格等于99.95的书的书名
book2_names = tree.xpath('//book[price=99.95]/title/text()')
print(book2_names)
#(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)匹配任何属性节点
nodename_attrs = tree.xpath('//*[@*]')
print(nodename_attrs)
#(11)获取所有带有属性的title标签,获取此标签的内容
title_contents = tree.xpath('//title[@*]/text()')
print(title_contents)
运行结果:
<Element book at 0x129c23f8708>
['http://www.langlang2017.com/']
['http://www.langlang2017.com/', 'www.baidu.com']
['Harry Potter', 'Learning XML']
['python 大全']
[<Element title at 0x129c23f8808>, <Element price at 0x129c23f8888>, <Element title at 0x129c23f8848>, <Element price at 0x129c23f88c8>, <Element title at 0x129c23f8748>, <Element price at 0x129c23f8b88>]
['python 大全']
['Harry Potter', 'Learning XML']
[<Element book at 0x129c23f8708>, <Element title at 0x129c23f8808>, <Element title at 0x129c23f8848>, <Element book at 0x129c23f8788>]
['Harry Potter', 'Learning XML']
5、lxml模块(python处理xml和html的模块。)
(1)解析字符串类型xml
from lxml import etree
text = '''
html页面内容
'''
tree = etree.HTML(text) # 返回一个element对象
# element对象有xpath方法,可以通过xpath表达式来筛选内容。
# 选取class属性为item-1的li下面的a标签的内容
a_contents = tree.xpath('//li[@class="item-1"]/a/text()')
# 将element对象变成字符串的方法
html_str = etree.tostring(tree,pretty_print=True).decode('utf-8')
print(type(html_str))
总结:
-
element对象 xpath方法来筛选,返回值是一个list对象。
-
xpath表达式最后一个是一个元素(标签),list中都是element对象。
-
xpath表达式最后一个是属性,list都是属性字符串。
-
xpath表达式最后一个是内容,list都是内容字符串。
(2)解析xml或者html文件
from lxml import etree
# parse方法是按照xml的方式来解析,如果语法出问题,就会报错。
html = etree.parse('demo.html')
# print(html) #_ElementTree
print(li_texts)
作业
药网数据爬取
url:https://www.111.com.cn/categories/953710-a0-b0-c31-d0-e0-f0-g0-h0-i0-j2.html
要求:抓取50页
字段:单价,描述,评论数量,详情页链接,(功能主治,有效期,用法用量)
(1)用xpath爬取数据。
(2)将数据保存到excel中
来源:CSDN
作者:梦醒时光@
链接:https://blog.csdn.net/qq_32718195/article/details/104180128