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

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.rhkb.cn/news/141514.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高效管理生活:Microsoft To Do for Mac 微软待办事项软件

在日常生活中&#xff0c;我们经常面临着琐碎的任务和繁忙的安排。为了更好地管理自己的时间和事务&#xff0c;一款强大而智能的待办事项软件是必不可少的。Microsoft To Do for Mac 微软待办事项软件将助您高效管理生活&#xff0c;让每件事都尽在掌握。 Microsoft To Do fo…

腾讯mini项目-【指标监控服务重构-会议记录】2023-07-26

2023-07-26组长会议纪要 A组 项目对齐和问题 分配需求&#xff0c;SLI指标上报&#xff0c;暂时没有实际效果 每个人负责一条指标&#xff0c;同步代码&#xff0c;时间问题还是难题跟B组同学请教&#xff0c;答疑 问题&#xff1a;启动 Tracer 【已解决】 环境问题&#xf…

数据结构:堆的简单介绍

目录 堆的介绍:(PriorityQueue) 大根堆:根节点比左右孩子节点大 小根堆:根节点比左右孩子节点小 堆的存储结构: 为什么二叉树在逻辑上用满二叉树结构,而不是普通二叉树呢? 因为如果是普通二叉树会造成资源的浪费​编辑 堆的介绍:(PriorityQueue) 堆又称优先级队列,何为优先…

uni-app使用HBuilder X编辑器本地打包apk步骤说明

1.下载安装Android Studio 下载地址官方地址&#xff1a;Android Studio 下载文件归档 | Android 开发者 | Android Developers 安装Android SDK和Google USB Driver即可&#xff0c;后者主要是为了后期使用USB设置的&#xff0c;如果不需要可以不点。 2.下载uni-app提供…

ElementUI之登陆+注册->饿了吗完成用户登录界面搭建,axios之get请求,axios之post请求,跨域,注册界面

饿了吗完成用户注册登录界面搭建axios之get请求axios之post请求跨域注册界面 1.饿了吗完成用户注册登录界面搭建 将端口号8080改为8081 导入依赖&#xff0c;在项目根目录使用命令npm install element-ui -S&#xff0c;添加Element-UI模块 -g&#xff1a;将依赖下载node_glod…

大数据flink篇之一-基础知识

一、起源 2010至2014年间&#xff0c;由柏林工业大学、柏林洪堡大学和哈索普拉特纳研究所联合发起名Stratosphere的研究项目。2014年4月&#xff0c;项目贡献给Apache基金会&#xff0c;成为孵化项目。更名为Flink2014年12月&#xff0c;成为基金会顶级项目2015年9月&#xff…

02 MIT线性代数-矩阵消元 Elimination with matrices

一, 消元法 Method of Elimination 消元法是计算机软件求解线形方程组所用的最常见的方法。任何情况下&#xff0c;只要是矩阵A可逆&#xff0c;均可以通过消元法求得Axb的解 eg: 我们将矩阵左上角的1称之为“主元一”&#xff08;the first pivot&#xff09;&#xff0c;第…

算法-贪心+优先级队列-IPO

算法-贪心优先级队列-IPO 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/ipo/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 回溯法 2.1 思路 2.2 代码 class Solution {int result 0;public int findMaximizedCapital(int …

【C语言】进阶——结构体+枚举+联合

①前言&#xff1a; 在之前【C语言】初阶——结构体 &#xff0c;简单介绍了结构体。而C语言中结构体的内容还有更深层次的内容。 一.结构体 结构体(struct)是由一系列具有相同类型或不同类型的数据项构成的数据集合&#xff0c;这些数据项称为结构体的成员。 1.结构体的声明 …

[LLM+AIGC] 01.应用篇之中文ChatGPT初探及利用ChatGPT润色论文对比浅析(文心一言 | 讯飞星火)

近年来&#xff0c;人工智能技术火热发展&#xff0c;尤其是OpenAI在2022年11月30日发布ChatGPT聊天机器人程序&#xff0c;其使用了Transformer神经网络架构&#xff08;GPT-3.5&#xff09;&#xff0c;能够基于在预训练阶段所见的模式、统计规律和知识来生成回答&#xff0c…

pytest之parametrize()实现数据驱动

第一个参数是字符串&#xff0c;多个参数中间用逗号隔开 第二个参数是list,多组数据用元组类型;传三个或更多参数也是这样传。list的每个元素都是一个元组&#xff0c;元组里的每个元素和按参数顺序一一对应 传一个参数 pytest.mark.parametrize(‘参数名’&#xff0c;list)…

CMU15-213 课程笔记 04-Floating Point

文章目录 浮点数如何用二进制表示IEEE 浮点数标准IEEE 浮点数实现IEEE 浮点数在内存里 E exp - bias 计算指数M 1.xxx 尾数计算举例&#xff1a;对一个浮点数进行转换一些关于浮点数的计算等等 浮点数如何用二进制表示 计算机内部的浮点数不是这样存在内存里的&#xff08;至…

【RabbitMQ实战】05 RabbitMQ后台管理

一、多租户与权限 1.1 vhost的概念 每一个 RabbitMQ服务器都能创建虚拟的消息服务器&#xff0c;我们称之为虚拟主机(virtual host),简称为 vhost。每一个 vhost本质上是一个独立的小型RabbitMQ服务器&#xff0c;拥有自己独立的队列、交换器及绑定关系等&#xff0c;并且它拥…

知识储备--基础算法篇-贪心算法

1.贪心算法 1.1贪心算法与背包问题的区别 贪心算法能够通过局部最优去推出全局最优&#xff0c;而背包问题不行&#xff0c;需要用动态规划的方法来解决。 1.2套路 贪心算法没有套路&#xff01;&#xff01; 主要想清楚怎么得到该阶段的局部最优解&#xff0c;如何通过局…

spring的ThreadPoolTaskExecutor装饰器传递调用线程信息给线程池中的线程

概述 需求是想在线程池执行任务的时候&#xff0c;在开始前将调用线程的信息传到子线程中&#xff0c;在子线程完成后&#xff0c;再清除传入的数据。 下面使用了spring的ThreadPoolTaskExecutor来实现这个需求. ThreadPoolTaskExecutor 在jdk中使用的是ThreadPoolExecutor…

前端web常用的基础案例

html案例&#xff1a; <!DOCTYPE html> <html> <head><title>My Website</title> </head> <body><header><h1>Welcome to My Website</h1><nav><ul><li><a href"#">Home</a…

阿里云效自动构建python自动测试脚本

之前一直用的是jenkins自动构建自动化脚本&#xff0c;因为现在的公司统一在阿里云效的流水线上做代码的管理&#xff0c;构建&#xff0c;要求自动化测试也在上面自动构建&#xff0c;故而学习了一下。为自己做一个记录&#xff0c;也给有需要的朋友做一个参考。 1. 新建流水…

Mysql备份恢复、与日志管理

Mysql日志管理、备份与恢复 一、Mysql日志管理1.1、日志分类1.1.1、错误日志1.1.2 、通用查询日志1.1.3、 二进制日志1.1.4 、慢查询日志1.1.5 、配置日志 1.2、日志的查询 二、备份与恢复2.1、 数据备份的必要性2.2 、造成数据丢失的原因2.3、 数据库备份的分类2.3.1、 物理备…

python 正则表达式

一、特殊字符-需要转义 eg&#xff1a;转义符&#xff1a; 待匹配的字符串&#xff1a;lr的值&#xff0c;及下图中字符串lr[和字符串&#xff0c;之间的数据 正则写法&#xff1a; learning_rate re.findall(".*lr\[(.*?), *", content) 处理结果&#xff1a;…

OpenCV实现模板匹配和霍夫线检测,霍夫圆检测

一&#xff0c;模板匹配 1.1代码实现 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [SimHei]#图像和模板的读取 img cv.imread("cat.png") template cv.imread(r"E:\All_in\o…