爬虫(四):xpath

给你一囗甜甜゛ 提交于 2020-02-06 05:28:28

一、什么是xml

1、定义:可扩展标记性语言

2、特点:xml的是具有自描述结构的半结构化数据。

3、作用:xml主要设计宗旨是用来传输数据的。它还可以作为配置文件。

二、xml和html的区别

1、语法要求不同

xml的语法要求更严格。

  1. html不区分大小写,xml区分。
  2. html有时可以省略尾标签。xml不能省略任何标签,严格按照嵌套首尾结构。
  3. 只有xml中有自闭标签(没有内容的标签,只有属性。)<a class='abc'/>
  4. 在html中属性名可以不带属性值。xml必须带属性值。
  5. 在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中

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!