Python爬虫技术系列-02HTML解析-xpath与lxml

news2024/11/22 13:50:39

Python爬虫技术系列-02HTML解析-xpath与lxml

  • 2 XPath介绍与lxml库
    • 2.1 XPath概述
    • 2.2 lxml库介绍
      • 2.2.1 lxml库安装
      • 2.2.2 lxml库基本使用
      • 2.2.3 lxml案例
        • a.读取数据并补全
        • b.读取数据并选取节点:

2 XPath介绍与lxml库

参考连接:
XPath教程
https://www.w3school.com.cn/xpath/index.asp
lxml文档
https://lxml.de/index.html#support-the-project
爬虫专栏
https://blog.csdn.net/m0_38139250/category_12001010.html

2.1 XPath概述

XPath的中文名称为XML路径语言(XML Path Language),其最初的设计是用来搜索 XML 文档,但也适用于HTML文档搜索。1996年11月,XPath 成为W3C标准, XQuery 和 XPointer 都构建于 XPath 表达之上。
XPath有着强大的搜索选择功能,提供了简洁的路径选择表达式, 提供了100+的内建函数,可以完成XML和HTML的绝大部分的定位搜索需求。
XML和HTML均可通过树形结构的DOM(文档对象模型,Document Object Model)表示,DOM中包含元素节点,文本节点,属性节点三种节点。

其中元素节点是DOM的基础,元素就是DOM中的标签,
如<html>是根元素,代表整个文档,其他的元素还包括<head><body><div><ul><span>等,元素节点之间可以相互包含。

文本节点:包含在元素节点中,
比如<span>文本节点</span>。

属性节点:元素节点可以包含一些属性,属性的作用是对元素做出更具体的描述,
如<span class="属性节点值">文本节点</span>

XPath的核心思想就是写地址,通过地址查找到XML和HTML中的元素,文本,属性等信息。
获取元素n:

//标签[@属性1="属性值1"]/标签[@属性2="属性值2"]/.../标签n

获取文本:

//标签[@属性1="属性值1"]/标签[@属性2="属性值2"]/.../text()

获取属性n的值:

//标签[@属性1="属性值1"]/标签[@属性2="属性值2"]/.../@属性n

[@属性1=“属性值1”]是谓语,用于过滤相同的标签,如果不需要通过属性过滤标签,可以不加谓语过滤。
下面介绍XPath的节点类型和常用语法。

1)节点(Node): XPath包括元素、属性、文本、命名空间、处理指令、注释以及文档(根)等七种类型的节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。节点之间的关系包括父(Parent),子(Children),同胞(Sibling),先辈(Ancestor),后代(Descendant)。

2)语法:
XPath中,通过路径(Path)和步(Step)在XML文档中获取节点。
a.常用的路径表达式
常见的路径表达式如下表所示:
表 XPath表达式与示例
在这里插入图片描述b.谓语(Predicates)
为查找特点节点或包含某个指定值的节点,可以使用谓语(Predicates),谓语用方括号[]表示,如:
//div[@class=‘useful’]
表示选取所有div 元素,且这些元素拥有值为 useful的 class属性。
//div[@class=‘useful’]//li[last()]
表示选取具有class值为useful的div标签下的任意li元素的最后一个li元素。
c.选取未知节点
XPath可以通过通配符搜索未知节点,如*表示匹配任何元素,@*表示匹配任何带有属性的节点,node()表示匹配任何类型的节点。如:
//title[@*]
表示选取所有带有属性的title元素。
d.选取若干路径
XPath可以通过“|”运算符表示选取若干路径。如
//title | //price
表示选取文档中的所有 title 和 price 元素

3)轴与步:
a.XPath轴(axis)
轴表示当前节点的节点集XPath轴的名称见表13-2所示:
表13-2 XPath轴名称与结果
在这里插入图片描述
b.步(Step)
步可以根据当前节点集中的节点来进行计算搜索。
步的语法:
轴名称::节点测试[谓语]
其中,轴(axis)表示所选节点与当前节点之间的关系,节点测试(node-test)表示是某给定轴内部的节点,谓语(predicate)用于搜索特定的节点集。
步的使用如表13-3所示:
在这里插入图片描述
步的使用案例如下:
//div[@class=“useless”]/descendant::a’)
获取任意class属性值为useless的div标签下得所有子孙a标签节点。

2.2 lxml库介绍

Web数据展示都通过HTML格式,如果采用正则表达式匹配lxml是Python中的第三方库,主要用于处理搜索XML和HTML格式数据。

2.2.1 lxml库安装

安装lxml:

pip install lxml==4.8.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

如果安装不成,可以在

https://www.lfd.uci.edu/~gohlke/pythonlibs/

下载对应的whl安装包,然后安装即可。
如果部分读者还是安装不成,可以把whl包解压,然后把解压后的两个文件夹放在python安装文件夹下的Lib\site-packages目录下即可。

2.2.2 lxml库基本使用

lxml的使用首先需要导入lxml的etree模块:

from lxml import etree

etree模块可以对HTML文件进行自动修正,lxml中的相关使用方法如下:
读取数据:

etree.HTML(text, parser=None, base_url=None,)

第一个参数text为一个字符串,字符串应该可以转换为HTML或XML文档,如果字符串中的标签存在不闭合等问题,本方法会自动修正,并把文本转换成为HTML格式文档。返回结果类型为’lxml.etree._Element’。

etree.fromstring(text, parser=None, base_url=None)

与etree.HTML()类似,但转换过程中,要求text字符串为标准的XML或HTML格式,否则会抛出异常。返回结果类型为’lxml.etree._Element’。

etree.parse(source, parser=None, base_url=None) 

可如果没有解析器作为第二个参数提供,则使用默认解析器。返回一个加载了源元素的ElementTree对象,返回结果类型为’lxml.etree._ElementTree’。

etree.tostring(element_or_tree, encoding=None,)

输出修正后的HTML代码,返回结果为bytes类型。

搜索数据:
假定有变量html为etree模块读取数据后返回’lxml.etree._Element’或’lxml.etree._ElementTree’类型,可以调用:

html.xpath(self, _path, namespaces=None, extensions=None, smart_strings=True, **_variables)

_path为xpath中的路径表达式和步,xpath函数可以通过_path参数值实现对文档的搜索。

2.2.3 lxml案例

下面根据具体案例来介绍lxml的基本使用。

a.读取数据并补全
from lxml import etree
# 定义一个不规则的html文本
text = '''
<html><body><div><ul>
        <li class="item-0">01 item</a></li>
'''

html = etree.HTML(text)  # etree把不规则文本进行修正
complete_html = etree.tostring(html)  # toString可输出修正后的HTML代码,返回结果为bytes
print("原数据------->", text)
print("修正后的数据--->\n",complete_html.decode('utf-8'))  # 输出修正后的html

输出结果如下:

原数据-------> 
<html><body><div><ul>
        <li class="item-0">01 item</a></li>

修正后的数据--->
 <html><body><div><ul>
        <li class="item-0">01 item</li>
</ul></div></body></html>

从输出结果可以看出,etree.toString()可以对缺少闭合标签的HTML文档进行自动修正。

etree模块可以调用HTML读取字符串,也可以调用parse()方法读取一个HTML格式的文件。把上面代码中的text变量保存在文本文件中,文件命名为lxml.html。

from lxml import etree

# 读取html文件
html = etree.parse("./lxml.html",etree.HTMLParser())  # etree把不规则文本进行修正
complete_html = etree.tostring(html)  # toString可输出修正后的HTML代码,返回结果为bytes
print(complete_html.decode('utf-8'))

输出结果如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>&#13;
<div><ul>&#13;
    <li class="item-0"><a href="/link1.html">01 item</a></li></ul></div></body></html>

从输出结果看可以看出,etree完成了HTML自动修正,同时还加上了!DOCTYPE标签。

b.读取数据并选取节点:

创建Demo11-03.html文件,内容如下:

<!DOCTYPE html>
<html>
<body>
<div class="useful">
    <ul>
        <li class="cla-0" id="id-0"><a href="/link1">01</a></li>
        <li class="cla-1"><a href="/link2">02</a></li>
        <li><strong><a href="/link3">03</a></strong></li>
        <li class="cla-1"><a href="/link4">04</a></li>
        <li class="cla-0"><a href="/link5">05</a></li>
    </ul>
</div>
<div class="useless">
    <ul>
        <li class="cla-0"><a href="/link1">useless-01</a></li>
        <li class="cla-1"><a href="/link2">useless-02</a></li>
    </ul>
</div>
</body>
</html>

导入库,并通过etree读取html文档:

from lxml import etree
# 加载HTML文档
html = etree.parse("./Demo11-03.html",etree.HTMLParser())

00.获取根路径的div元素:

print('--result00----/div-----')
result00 = html.xpath('/div')  # 匹配/div节点
print(result00)

输出如下:

--result00----/div-----
[]

因为根路径下标签为,所以无法匹配度根路径下的div标签。

01.获取任意路径的div元素:

print('--result01----/div-----')
result00 = html.xpath('/div')  # 匹配所有div节点
print(result01)

输出如下:

--result01----//div-----
[<Element div at 0x182e1169e80>, <Element div at 0x182e1169e00>]

匹配到两个div元素。//表示任意路径。

02.获取任意路径div元素的所以子节点:

print('--result02----//div/*-----')
result02 = html.xpath('//div/*')  # 匹配所有div节点的子节点
print(result02)

输出如下:

--result02----//div/*-----
[<Element ul at 0x182e1169f80>, <Element ul at 0x182e1169fc0>]

*表示匹配任意节点。

03.匹配所有class属性的值:

print('--result03----//@class-----')
result03 = html.xpath('//@class')  # 匹配所有class属性的值
print(result03)

输出如下:

--result03----//@class-----
['useful', 'cla-0', 'cla-1', 'cla-1', 'cla-0', 'useless', 'cla-0', 'cla-1']

@class表示获取属性class的值。

04.获取任意路径下li标签的a标签子节点:

print('--result04----//li/a-----')
result04 = html.xpath('//li/a')  # 匹配所有li标签下的子节点a标签
print(result04)

输出如下:

--result04----//li/a-----
[<Element a at 0x182e116a400>, <Element a at 0x182e116a480>, <Element a at 0x182e116a4c0>, <Element a at 0x182e116a500>, <Element a at 0x182e116a540>, <Element a at 0x182e116a5c0>]

原始数据中一共7个a标签,返回值为6个a标签,是因为如下原始数据

<li><strong><a href="/link3">03</a></strong></li>

a标签不是li标签的子节点。

05.获取任意路径下li标签的任意a标签子孙节点:

print('--result05----//li//a-----')
result05 = html.xpath('//li//a')  # 匹配所有li标签下的所有a标签
print(result05)

输出如下:

--result05----//li//a-----
[<Element a at 0x182e116a400>, <Element a at 0x182e116a480>, <Element a at 0x182e116a600>, <Element a at 0x182e116a4c0>, <Element a at 0x182e116a500>, <Element a at 0x182e116a540>, <Element a at 0x182e116a5c0>]

原始数据中一共7个a标签,返回值为7个a标签,全部获取到。

06. 匹配具有herf属性为/link2的元素的父元素的class属性的值:

print('--result06----//a[@href="/link2"]/../@class-----')
result06 = html.xpath('//a[@href="/link2"]/../@class')print(result06)

输出如下:

--result06----//a[@href="/link2"]/../@class-----
['cla-1', 'cla-1']

…表示当前节点的父元素。

07.查找所有class="cla-0"的li节点:

print('--result07----//li[@class="cla-0"]-----')
result07 = html.xpath('//li[@class="cla-0"]')  # 查找所有class="cla-0"的li节点:
print(result07)

输出如下:

--result07----//li[@class="cla-0"]-----
[<Element li at 0x182e116a140>, <Element li at 0x182e116a2c0>, <Element li at 0x182e116a3c0>]

//表示匹配任意路径,[]代表谓语,@class="cla-0"代表过滤出class属性值为cla-0的元素。

08.获取a节点下的文本:

print('--result08----//li[@class="cla-0"]/a/text()-----')
result08_1 = html.xpath('//li[@class="cla-0"]/a/text()')  # 先选取a节点,再获取a节点下的文本
print(result08_1)

输出如下:

--result08----//li[@class="cla-0"]/a/text()-----
['01', '05', 'useless-01']

text()表示获取匹配节点的文本内容。

09.获取li节点下a节点的href属性:

print('--result09----//li/a/@href-----')
result09 = html.xpath('//li/a/@href')  # 获取li节点下a节点的href属性
print(result09)

输出如下:

--result09----//li/a/@href-----
['/link1', '/link2', '/link4', '/link5', '/link1', '/link2']

//li/a/@href表示匹配任意路径下的li元素的a标签子节点的href属性值。

10.获取li节点下所有a节点的href属性:

print('--result10----//li//a/@href-----')
result10 = html.xpath('//li//a/@href')  # 获取li节点下所有a节点的href属性
print(result10)

输出如下:

--result10----//li//a/@href-----
['/link1', '/link2', '/link3', '/link4', '/link5', '/link1', '/link2']

相比result9,本次结果匹配到了/link3。

11.获取class属性值包含-0的li元素下的a标签的文本:

print('--result11----//li[contains(@class,"-0")]/a/text()-----')
result11 = html.xpath('//li[contains(@class,"-0")]/a/text()') # 获取class属性值包含-0的li元素下的a标签的文本
print(result11)

输出如下:

--result11----//li[contains(@class,"-0")]/a/text()-----
['01', '05', 'useless-01']

contains(@class,“-0”)表示过滤条件为class属性包含-0。于此类似的还有starts-with,starts-with表示以什么开头。

12.用多个属性获取:

print('--result12----//li[contains(@class,"-0") and @id="id-0"]/a/text()-----')
result12 = html.xpath('//li[contains(@class,"-0") and @id="id-0"]/a/text()')  # 多个属性用and运算符来连接
print(result12)

输出如下:

--result12----//li[contains(@class,"-0") and @id="id-0"]/a/text()-----
['01']

contains(@class,“-0”) and @id="id-0"表示待匹配的元素需要具有满足以上两种条件。and 操作符也可以替换为or 操作符。由于同时包含两种属性条件的a标签只有一个,所以返回的文本只有01。

13.按照顺序获取节点:

print('--result13----//li[last()]/a/text()-----')
result13 = html.xpath('//li[last()]/a/text()')  # 取最后一个li节点下a节点的文本
print(result13)

输出如下:

--result13----//li[last()]/a/text()-----
['05', 'useless-02']

返回结果表示,通过last()返回了两个li列表中的最后一个节点。

14.通过ancestor轴获取所有的祖先节点:

print('--result14----//li[1]/ancestor::*-----')
result14 = html.xpath('//li[1]/ancestor::*') # ancestor轴可以获取所有的祖先节点
print(result14)

输出如下:

--result14----//li[1]/ancestor::*-----
[<Element html at 0x182e0de9c80>, <Element body at 0x182e116abc0>, <Element div at 0x182e1169e80>, <Element ul at 0x182e1169f80>, <Element div at 0x182e1169e00>, <Element ul at 0x182e1169fc0>]

//li[1]表示获取任意路径的li中的第一个元素,/ancestor::*表示获取当前节点的任意祖先节点。

15.通过ancestor轴获取祖先div节点:

print('--result15----//li[1]/ancestor::div-----')
# 只获取div这个祖先节点
result15 = html.xpath('//li[1]/ancestor::div')
print(result15)
for result15_1 in result15:
    print(result15_1.xpath('.//li[contains(@class,"-0")]/a/text()'))

输出如下:

--result15----//li[1]/ancestor::div-----
[<Element div at 0x182e1169e80>, <Element div at 0x182e1169e00>]
['01', '05']
['useless-01']

result15的返回结果为div节点,然后对result15进行遍历,在遍历中,通过xpath路径进一步获取a标签的文本。这里需要注意的是循环内的xpath路径以“.”开头,表示相对于当前div元素下,第一次输出为[‘01’, ‘05’],第二次输出为[‘useless-01’]。如果循环内的xpath路径去掉“.”,则循环内的两次输出是一致,应该都为[‘01’, ‘05’, ‘useless-01’]。

16.获取所有属性值:

print('--result16----//li[1]/attribute::*-----')
result16 = html.xpath('.//li[1]/attribute::*')
print(result16)

输出如下:

--result16----//li[1]/attribute::*-----
['cla-0', 'id-0', 'cla-0']

输出结果为所有li中的第1个节点的属性值。

17.获取所有子孙节点a标签:

print('--result17----//div/descendant::a-----')
result17 = html.xpath('//div[@class="useless"]/descendant::a')
print(result17)

输出如下:

--result17----//div/descendant::a-----
[<Element a at 0x1f34cf2a540>, <Element a at 0x1f34cf2a5c0>]

descendant表示匹配子孙节点。
以上就是lxml的基本操作,更多操作可以自行组合或参考官网,需要说明的是,在浏览器端通过开发者工具–查看器–选择元素–右键复制–选择XPath路径,可以获取选择元素的XPath路径,通过这种方法可以加快XPath路径构建。
另外需要注意的是,xpath()函数的返回值为列表,可以通过先抓取外层的数据,然后通过遍历或是索引的方式获取节点数据,然后通过相对路径的方式进一步读取内层元素节点。案例如下:

18.先获取外层元素,再通过相对路径的方式获取内部元素:
print('--result18----//li[1]/ancestor::div-----')
result18 = html.xpath('//li[1]/ancestor::div')
print(result18)
print(result18[0].xpath('./ul/li/a/text()'))

在上面代码中 ,result18[0]表示获取列表中的第一个Element 类型元素,然后对Element 类型元素进行xpath操作。./ul/li/a/text()中的“.”表示相对当前节点。
输出为:

--result18----//li[1]/ancestor::div-----
[<Element div at 0x28e3b83a000>, <Element div at 0x28e3b83a0c0>]
['01', '02', '04', '05']

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

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

相关文章

85、Redis连接相关的命令, key相关命令

本次讲解要点&#xff1a; Redis连接相关的命令&#xff0c; key相关命令&#xff0c; 启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-serve…

「UG/NX」Block UI 选择单元SelectElement

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

SpringBoot 学习(三)Web 开发

3. SpringBoot Web 开发 3.1 导入静态资源 (1) webjars 导入 jquery 依赖 <dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.6.0</version> </dependency>访问 jquery.js 文件 http:/…

python将中文标点符号转换成英文标点符号然后再替换成回车符实现换行

一段文字如下&#xff1a; 你发现没,杭州亚运会首个比赛日上午&#xff0c;中国体育代表团竟然狂揽11金&#xff01;这一壮丽景象背后&#xff0c;是中国体育事业的坚实基础和精湛训练的见证。 标点符号都是中文状态下的。现在要替换成英文标点符号。参考了文章&#xff1a; …

Linux基本命令总结练习(过命令关)

1.新建网卡配置文件的软连接NIC1 [rootserver ~]# ln /etc/NetworkManager/system-connections/ens160.nmconnection NIC1 [rootserver ~]# stat /etc/NetworkManager/system-connections/ens160.nmconnection [rootserver ~]# stat NIC1 2.使用普通账户新建如下结构的2个目录&…

Vue中如何进行跨域处理

Vue中的跨域请求处理&#xff1a;解决前端开发中的常见问题 跨域请求是前端开发中常见的问题之一。Vue.js是一款流行的前端框架&#xff0c;如何在Vue中处理跨域请求是每个Vue开发者都需要了解的重要课题。本文将深入探讨什么是跨域请求&#xff0c;为什么它会出现&#xff0c…

burpsuite只有intruder中文乱码

burpsuite 只有intruder模块中文乱码 现象&#xff1a;解决方案 现象&#xff1a; 在proxy、repeater等模块下中文均可正常显示&#xff0c;如下图&#xff1a; 在intruder模块&#xff0c;中文显示乱码 解决方案 在payloads标签下payload processing中添加“Decode”

【跟小嘉学 Rust 编程】三十、Rust 使用 Slint UI

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…

聊聊并发编程——多线程之synchronized

目录 一.多线程下数据不一致问题 二.锁和synchronized 2.1 并发编程三大特性 2.2引入锁概念 三.synchronized的锁实现原理 3.1 monitorenter和monitorexit 3.2synchronized 锁的升级 3.2.1偏向锁的获取和撤销 3.2.2轻量级锁的加锁和解锁 自适应自旋锁 轻量级锁的解锁…

位运算练习题(Java)

package KeepCoding.algorithm; //位运算知识点 /* 1. 0 ^ x x x ^ x 1 * 2. 位运算满足结合律和交换律&#xff0c;即运算顺序无关 */ //位运算练习题 //1.整数数组中有一个出现次数为奇数的整数&#xff0c;其余整数的出现次数均为偶数个&#xff0c;请找出数组中这位…

oracle

title: “Oracle” createTime: 2021-12-13T16:35:4108:00 updateTime: 2021-12-13T16:35:4108:00 draft: false author: “name” tags: [“oracle”] categories: [“db”] description: “测试的” 时间字段分析 timestamp 精确到秒后面6位 createTime: 2021-12-13T16:35:…

微积分学习笔记(2):用Go语言画函数图像

使用的Go库 gonum.org/v1/plotimage/color 待绘图函数 直接使用三角函 s i n sin sin: func f(x float64) float64 {return math.Sin(x) }绘图过程 1 创建一个绘图 p : plot.New()assert.NotNil(t, p)p.Title.Text "Function Image"p.X.Label.Text "X&qu…

基于微信小程序的中医知识库系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌…

crypto:Url编码

题目 下载题目所给的压缩包后解压&#xff0c;打开文件可得 由题目可知为url编码&#xff0c;所以使用解码工具解码即可得到flag

【深度学习实验】卷积神经网络(二):实现简单的二维卷积神经网络

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 二维互相关运算&#xff08;corr2d&#xff09; 2. 二维卷积层类&#xff08;Conv2D&#xff09; a. __init__&#xff08;初始化&#xff09; b. forward(前向传…

React基础教程(四):组件理解

1、函数式组件 实现代码 <script type"text/babel"> /*此处一定要写babel*/ // 1、创建函数式组件 function MyComponent() {console.log(this); // 此处的this是undefined&#xff0c;因为babel编译后开启了严格模式return <h2>我是用函数定义的组件&am…

unable to access xxxx: Failed to connect to xxxx

问题&#xff1a; 1、GitLab仓库加上双重验证后&#xff0c;设置GIt得 Manage Remotes时报错 unable to access xxxx: Failed to connect to xxxx SSL certificate problem:self signed certificate 解决 1、返回前面得操作步骤检查了一遍 没有问题 2、最后尝试一些方法解…

SPA项目之主页面--Mock.js以及组件通信(总线)的运用

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于VueElementUI的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Mock.js是什么 二.为什么要使用…