Python+Selenium自动化入门

本章内容需有一定Python基础,如何不懂的,请先学习Python。

什么??没有好的学习资料,给你准备好了!!

Web自动化环境搭建

1、软件准备

  • python64位安装包
  • chrome64位浏览器&驱动
  • 浏览器驱动下载

注意:chromedriver与chrome版本要对应。具体可查看该对应表

另外:本文主要以chromedirver为例

2、开始环境搭建

安装python:双击自定义安装 或者 在cmd中输入python-3.7.0-amd64.exe的路径,即在电脑中存放的位置,回车即可弹出安装页面,勾选Add Python 3.7 to PATH,即自动配置环境变量。

如图:

下图显示安装成功:

注:可以查看系统环境变量,发现D:\My pyhton3.7.0\Scripts;D:\My pyhton3.7.0;已经自动添加到了path中,这就是勾选Add Python 3.7 to PATH的效果.

python安装完成后可以在cmd界面输入python,会出现下图内容,说明python安装成功

3、安装selenium:

  • 在cmd中运行pip install selenium 即可在线安装selenium,(ps:安装指定的版本可用pip install selenium==3.14.0)如图提示selenium安装成功。

  • 使用pip show selenium 查看selenium版本信息

4、安装chrome浏览器
​ 该处使用谷歌浏览器64位的版本号为70.0.3538.67

5、将chromedriver.exe放到python的安装目录下(或者目录下的scripts下)

以上5步就搭建好python+selenium环境了

如果步骤还不够清楚的话,直接领取资料包,里面有步骤教学视频,按照视频一步步来操作,就很清晰了↓↓


浏览器和驱动下载

在我学习Ui自动化时,总会遇到浏览器驱动版本问题,小伙伴也是一头雾水也找不到下载的地方,今天给大家整理。

不同版本的下载地址,大家可以去查一下,我的资料包里面也会有,大家可以自己领取,自行下载就好了~


浏览器基本操作

开始自动化测试之前,需了解浏览器的一些基本操作,以方便后续的自动测试。码上开始吧!

导入Selenium模块

浏览器基本操作

  • 打开网站

  • 设置休眠

  • 页面刷新

  • 前进和后退

  • 设置窗口大小

  • 截屏

  • 退出


为什么要学习定位

  • 让程序操作指定元素,就必须先找到此元素;
  • 程序不像人类用眼睛直接定位到元素;
  • webDriver提供了八种定位元素的方式。

定位总结

  • id、name、class_name、tag_name:根据元素的标签或元素的属性来进行定位
  • link_text、partial_link_text:根据超链接的文本来进行定位(a标签)
  • xpath:为元素路径定位–重点
  • css:为css选择器定位(样式定位)

常见定位方式

id

  • 说明:HTML规定id属性在整个HTML文档中必须是唯一的,id定位就是通过元素的id属性来定位元素;
  • 前提:元素有id属性
  • id定位方法:find_element_by_id()
  • 实现案例-1需求:打开百度界面(https://www.baidu.com/),通过id定位,输入信息,点击百度的钮

name

  • 说明:HTML规定name属性来指定元素名称,name定位就是根据name属性来定位
  • 前提:元素有name属性
  • name定位方法:find_element_by_name()
  • 实现案例-2需求:打开百度(https://www.baidu.com/),通过name定位

class_name

  • 说明:HTML规定class来指定元素的类名,class定位就是根据class属性来定位,用法和name,id类似。
  • 前提:元素有class属性
  • class_name定位方法:find_element_by_class_name()
  • 实现案例-3需求:打开百度界面(https://www.baidu.com/),通过class定位

tag_name

tag_name是通过标签名称来定位的,如:a标签

注:由于HTML源码中,经常会出现很多相同的的标签名,所以一般不使用该定位方式

link_text

  • 说明:link_text定位于前面4个定位有所不同,它专门用来定位超链接文本(文本值)
  • 前提:定位的元素是链接标签(a标签)
  • link_text定位方法:find_element_by_link_text()
  • 实现案例-5需求:打开百度首页,通过link_text(链接文本)定位到【新闻】按钮,并进行点击操作

partial_link_text

  • 说明:partial_link_text定位是对link_text定位的补充,partial_link_text为模糊匹配;link_text为全部匹配。
  • 前提:定位的元素是链接标签(a标签)
  • partial_link_text定位方法:find_element_by_partial_link_text()
  • 通过传入a标签局部文本或全部文本来定位元素,要求输入的文本能够唯一找到这个元素
  • 实现案例-6需求:打开百度新闻(http://news.baidu.com/),通过partial_link_text定位任何一条新闻,并进行点击操作

元素组

元素组定位方式:find_elements_by_xxx

作用:

查找返还定位所有符合条件的元素

返还的定位元素格式为列表格式
说明:

  • 列表数据格式的读取需要指定下标(下标从0开始)
  • 案例要求:打开百度页面https://www.baidu.com/,通过元素组定位

定位:"//*[@id=‘s-top-left’]/a"


xpath定位详解

通过常见属性定位

通过其它属性

  • 如果一个元素id、name、class属性都没有,这时候也可以通过其它属性定位到

标签

有时候同一个属性,同名的比较多,这时候可以通过标签筛选下,定位更准一点

如果不想制定标签名称,可以用*号表示任意标签

如果想制定具体某个标签,就可以直接写标签名称

层级定位

  • 如果一个元素,它的属性不是很明显,无法直接定位到,这时候我们可以先找它老爸(图中数字1)
  • 找到它老爸后,再找下个层级就能定位到了

  • 如上图所示,要定位的是input这个标签,它的老爸的 class=“sec-input-box yuyin-cur”
  • 要是它老爸的属性也不是很明显,就找它爷爷id=form(图中数字2)
  • 于是就可以通过层级关系定位到

索引

  • 百度主页–设置–搜索设置

1.如果一个元素它的兄弟元素跟它的标签一样,这时候无法通过层级定位到。因为都是一个父亲生的,多胞胎兄弟。

2.虽然双胞胎兄弟很难识别,但是出生是有先后的,于是可以通过它在家里的排行老几定位到。

3.如下图三胞胎兄弟

4.用xpath定位老大、老二和老三(这里索引是从1开始算起的,跟Python的索引不一样)


逻辑

1.xpath还有一个比较强的功能,是可以多个属性逻辑运算的,可以支持与(and)、或(or)、非(not)

2.一般用的比较多的是and运算,同时满足两个属性


定位总结

定位单个元素

1.id定位:find_element_by_id(self, id_)

2.name定位:find_element_by_name(self, name)

3.class定位:find_element_by_class_name(self, name)

4.tag定位:find_element_by_tag_name(self, name)

5.link定位:find_element_by_link_text(self, link_text)

6.partial_link定位find_element_by_partial_link_text(self, link_text)

下面两种要重点掌握其中一种,两者都会是更好的。现在我比较喜欢用xpath定位

7.xpath定位:find_element_by_xpath(self, xpath)

8.css定位:find_element_by_css_selector(self, css_selector)

定位一组元素

1.id复数定位find_elements_by_id(self, id_)

2.name复数定位find_elements_by_name(self, name)

3.class复数定位find_elements_by_class_name(self, name)

4.tag复数定位find_elements_by_tag_name(self, name)

5.link复数定位find_elements_by_link_text(self, text)

6.partial_link复数定位find_elements_by_partial_link_text(self, link_text)

7.xpath复数定位find_elements_by_xpath(self, xpath)

8.css复数定位find_elements_by_css_selector(self, css_selector)

如何定位多个元素呢?

操作元素


数据驱动

  • 我个人的理解就是说,把自动化测试中需要用到的数据和代码分开。
  • 当我们需要用到这个数据时,直接读取里边的数据就可以。
  • 工作中常用到的文本格式有:txt、csv。假设我要搜索一组数据,进行一个简单的登录操作

txt文件

excel

  • 小伙伴都知道,测试用例是写在Excel里的,如果是少量的用例很容易处理,如果用例成百上千条呢?
  • 自动化测试的话,需要对用例数据进行读取,那必须循环读取才可以实现自动化。那么问题来了,怎么做呢?

问题解析:
1、用列表存放这些用例数据,所以要用到列表
2、每一行用例要存放在字典内,所以需要用到字典
3、循环写入到字典,然后存放到列表内

运行结果

yaml

  • yaml文件后缀名为yaml,如文名件.yaml
  • yaml为第3方模块,需另行安装pip install pyyaml
    问题解析:
    1.定义文件地址
    2.打开yaml文件
    3.读取文件后转成字典以方便读取

运行结果


键盘操作

什么是键盘事件
  • 在web产品测试中我们经常还会用到其它键盘操作,如删除,空格,回车,Ctrl+C等
  • 这些操作都包含在Keys类中,所以要模拟键盘操作是首先要导入keys包。
  • 所有的键盘操作都是在最后的 send_keys()里面通过改变参数实现的。

键盘常见操作

案例操作


鼠标操作

  • 前面我们已经学习到可以用 click()来模拟鼠标的单击操作
  • 在实际的 web 产品测试中发现,有关鼠标的操作,不仅只有单击,有时候还要用到右击,双击,拖动等操作
  • 这些操作都包含在ActionChains 类中,所以要模拟鼠标操作是首先要导入ActionChains

鼠标常见操作

左击操作

  • 对ActionChains类进行实例化对象操作
  • 调用click(元素)方法
  • 执行操作perform方法
  • 案例1: 对百度的搜索输入hello,左击百度一下按钮

右击操作

操作思路:

  • 对ActionChains类进行实例化对象操作
  • 调用context_click(元素)方法
  • 执行操作perform()方法
  • 案例2: 对百度的搜索框进行右击操作

双击操作

操作思路:

  • 对ActionChains类进行实例化对象操作
  • 调用double_click(元素)方法
  • 执行操作perform()方法
  • 案例3: 对百度的搜索框输入:好好学习,双击鼠标选中文本

拖动操作

操作思路:

  • 对ActionChains类进行实例化对象操作
  • 调用drag_and_drop(元素1,元素2)方法
  • 执行操作perform()方法
  • http://127.0.0.1:5000/signin,点击练习鼠标拖拽,再将drag me元素分别拖动到item1,item2等元素位置

悬停操作

操作思路:

  • 对ActionChains类进行实例化对象操作
  • 调用move_to_element(元素)方法
  • 执行操作perform()方法
    -案例5: 进入百度,悬停到设置元素上

按下左键操作

操作思路:

  • 对ActionChains类进行实例化对象操作
  • 调用click_and_hold(元素)方法
  • 执行操作perform方法
  • 案例6: 进入百度,在贴吧元素上按着不松

鼠标其它操作


获取元素属性

  • 我们要设计功能测试用例时,一般会有预期结果,有些预期结果测试人员无法通过肉眼进行判断的。
  • 自动化测试运行过程是无人值守,一般情况下,脚本运行成功,没有异样信息就标识用户执行成功。
  • 那怎么才能知道我打开这个网页,是不是我想要打开的这个网页呢?

-通常我们可以通过获得页面的 title 、URL 地址,页面上的标识性信息(如,登录成功的“欢迎,xxx”信息)来判断用例执行成功。

获取title

获取URL

获取元素标签

获取输入框文本值

获取元素其它属性

1.获取其它属性方法:get_attribute(“属性”),这里的参数可以是class、name,value等任意属性

2.如获取百度一下按钮的value属性

文本超链接text

如下图这种显示在页面上的文本信息,可以直接获取到

查看元素属性:

获取浏览器名字


判断是否存在

title(title_is)

  • 获取页面title的方法可以直接用driver.title获取到,然后也可以把获取到的结果用做断言。

1.首先导入expected_conditions模块:from selenium.webdriver.support import expected_conditions

2.由于这个模块名称比较长,所以为了后续的调用方便,重新命名为EC了(有点像数据库里面多表查询时候重命名)

3.打开博客首页后判断title,返回结果是True或False

判断title包含:title(title_contains)

判断元素是否存在

  • selenium是没有方法判断元素是否存的,所以需要自己写.元素不存在的话,操作元素会报错,或者元素有多个,不唯一的时候也会报错

find_elements方法判断

1.find_elements方法是查找页面上所有相同属性的方法,这个方法其实非常好用

2.由于元素定位的方法很多,所以判断的时候定位方法不统一也比较麻烦,我选择xpath定位

3.写一个函数判断,找到就返回Ture,没找到就返回False(或者不止一个)


判断元素文本

如果要判断按钮上的文本,就不能用上面那个方法

导入模块:


多窗口(句柄)

有些页面的链接打开后,会重新打开一个窗口,对于这种情况,想在新页面上操作,就得先切换窗口了。获取窗口的唯一标识用句柄表示,所以只需要切换句柄,我们就能在多个页面上灵活自如的操作了。

1.什么是多窗口

2.获取当前窗口句柄

  • 元素有属性,浏览器的窗口其实也有属性的,只是你看不到,浏览器窗口的属性用句柄(handle)来识别。
  • 人为操作的话,可以通过眼睛看,识别不同的窗口点击切换。但是脚本没长眼睛,它不知道你要操作哪个窗口,这时候只能句柄来判断了。
  • 获取当前页面的句柄:driver.current_window_handle

3.获取所有句柄

  • 定位赶集网招聘求职按钮,并点击
  • 点击后,获取当前所以的句柄:window_handles

4.切换句柄


selenium三种等待方式详解

为什么要使用等待?

  • 在自动化测试脚本的运行过程中,webdriver操作浏览器的时候,对于元素的定位是有一定的超时时间,大致在1-3秒
  • 如果这个时间内仍然定位不到元素,就会抛出异常,中止脚本执行
  • 我们可以通过在脚本中设置等待的方式来避免由于网络延迟或浏览器卡顿导致的偶然失败

常用的三种等待方式

  • 强制等待
  • 隐式等待
  • 显示等待

强制等待

  • 利用time模块的sleep方法来实现,最简单粗暴的等待方法
  • 强制等待,不管你浏览器是否加载完成,都得给我等待3秒,3秒一到,继续执行下面的代码,

弊端

  • 不建议用这种等待方法,严重影响代码的执行速度

隐式等待

  • implicitly_wait()方法用来等待页面加载完成(直观的就是浏览器tab页上的小圈圈转完)网页加载完成则执行下一步
  • **隐式等待只需要声明一次,**一般在打开浏览器后进行声明
  • 声明之后对整个drvier的生命周期都有效,后面不用重复声明

弊端

  • 程序会一直等待整个页面加载完成,直到超时
  • 有时候我需要的那个元素早就加载完成了,只是页面上有个别其他元素加载特别慢,我仍要等待页面全部加载完成才能执行下一步

显示等待

  • WebDriverWait,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了
  • 它主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步
  • 否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException
  • 显示等待必须在每个需要等待的元素前面进行声明

四个参数

  • driver:浏览器驱动
  • timeout:等待时间
  • poll_frequency:检测的间隔时间,默认0.5s
  • ignored_exceptions:超时后的异常信息,默认抛出NoSuchElementException

expected_conditions

  • expected_conditions是selenium的一个模块
  • 包含一系列可用于判断的条件
  • 可以对网页上元素是否存在,可点击等等进行判断,一般用于断言或与WebDriverWait配合使用

模块用法汇总


无头模式

  • 在使用seleinum的时候经常会打开浏览器,如果电脑配置不在了的时候,会出现卡,有没有一种方式不弹出浏览器又把想要的操作执行完呢??
  • 这时候firefox和chrome就有了无头模式,也就是没有界面的浏览器,在内存中执行。

Firefox

Chrome


logging模块

  • 你可以控制消息的级别,过滤掉那些并不重要的消息。
  • 你可决定输出到什么地方,以及怎么输出。有许多的重要性别级可供选择,debug、info、warning、error 以及 critical
  • 通过赋予 logger 或者 handler 不同的级别,你就可以只输出错误消息到特定的记录文件中,或者在调试时只记录调试信息。

日志级别

  • 级别从高到低

运行结果

  • 默认打印WARNING及以上的日志信息
  • level=“DEBUG” 设置级别名必须都是大写
  • 如果我想打印日志的时间、在哪一行等格式?可以实现吗??

实现日志格式

  • 使用basicConfig中的参数format

运行结果

  • 默认名字显示的root(可否显示一个自定义名字?继续往下看)


日志流程

第1步:创建日志器

  • 提供程序使用的接口,可以理解就创建一个logging实例化类
  • 默认日志级别为:WARNING

第2步:创建处理器

  • 由处理器来处理日成生的位置(控制台或文件或两者同时存在)
  • 重点:日志器添加处理器

控制台处理器

运行结果

  • 如果日志器级别 >处理器级别则显示日志器级别,反之显示处理器级别
  • 默认级别为WARING,所以只打印这三条日志

文件处理器

第3步:格式器

  • 决定日志生成的最终输出格式
  • 重点:处理器添加格式器

运行结果:

日志同时生成在控制台和文本

  • 重点就是创建1个控制台/文本处理器
  • 小伙伴可能会发现,我们的代码没有进行封装,那最后一步,我们封装日志模块


封装日志模块

  • 第1步:创建日志器

  • 第2步:创建处理器

  • 第3步:创建格式器

  • 第4步:日志器添加格式器


完整代码


POM模型

Page Object Model (POM) 直译为“页面对象模型”,这种设计模式旨在为每个待测试的页面创建一个页面对象(class),将那些繁琐的定位操作封装到这个页面对象中,只对外提供必要的操作接口,是一种封装思想。

POM优势有哪些

  • 让UI自动化更早介入项目中,可项目开发完再进行元素定位的适配与调试
  • POM 将页面元素定位和业务操作流程分开,分离了测试对象和测试脚本
  • 如果UI页面元素更改,测试脚本不需要更改,只需要更改页面对象中的某些代码就可以
  • POM能让我们的测试代码变得可读性更好,高可维护性,高复用性
  • 可多人共同维护开发脚本,利于团队协作

为什么使用POM设计模式

  • 少数的自动化测试用例维护起来看起来是很容易的。但随着时间的迁移,测试套件将持续的增长。脚本也将变得越来越臃肿庞大。
  • 如果变成我们需要维护10个页面,100个页面,甚至1000个呢?而且页面元素很多是公用的。那页面元素的任何改变都会让我们的脚本维护变得繁琐复杂,而且变得耗时易出错。

思路解析

  • 需要一个文件用于管理页面元素,如login_page.py
  • 封装一个公用的操作方法
  • 最后需要一个文件用于编写测试用例

login_page.py文件

  • 该文件用于管理登录页面所有的元素,操作这些元素的方法

common.py

  • 该文件有用于封装一些共用的操作方法

TestCase.py

  • 该文件用于管理测试用例

unittest介绍

  • unittest是Python自带的测试框架,可用于单元测试
  • unittest测试框架可组织执行测试用例
  • unittest提供丰富的断言方法

unittest语法

  • 用import unittest导入unittest模块
  • 继承unittest.TestCase类,如class xxx(unittest.TestCase)
  • 每个测试用例执行前先执行setUp或setUpClass方法,执行完毕后执行tearDown或tearDownClass方法
  • 用例必须名以test开头,否则unittest不能识别
  • 调用unittest.main(),执行测试用例

unittest四大组件

test case

  • 测试用例,方法命名基于test开头,测试用例自行排序执行顺序规则A-Z, a-z, 0-9
  • 如用例test01/test02
  • add的用例不是用test开始就不会被识别,所以不会运行

  • 成功是 .失败是 F,出错是 E

test fixture

  • 设置前置条件(setUp),后置条件(tearDown),每个测试用例方法执行前后都要执行前后置条件
  • 用例前后都执行了setUp和tearDown,且运行了两次了?能否只打开一次浏览器和关闭浏览器一次

  • 设置前置条件(setUpClass),后置条件(tearDownClass),所有用例只会执行一次setUpClass和tearDownClass
  • 方法前必须加装饰器: @classmethod
  • 打开浏览器和关闭浏览器只运行了一次

test suite

  • 先通过unittest.TestSuite() 创建测试套件实例对象,如:suite = unittest.TestSuite()
  • 再通过addTest() 方法添加单个测试用例,或通过addTests([…]) 添加多个测试用例(列表中为用例方法名)
  • 执行测试套件里的测试用例

方式一:加载测试用例

方式二:加载测试用例类

  • 先通过unittest.TestSuite() 创建测试套件实例对象。
  • 再通过unittest.TestLoader()创建加载对象,加载测试用例类

方法三:加载指定路径里的测试用例

  • 通过unittest.defaultTestLoader.discover()将指定路径的测试用例加载至测试用例集
  • 注意:这里不需要创建unittest.TestSuite对象
  • test_dir为指定路径, pattern=test_*.py 表示加载以test_开头的模块中的测试用例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wI6KlwyE-1634193811891)(C:\Users\zhichao\AppData\Roaming\Typora\typora-user-images\image-20210228152457445.png)]

test runner

unittest框架执行测试用例之前,需先创建TextTestRunner实例,

再调用该实例的run()方法执行用例


unittest生成测试报告

  • unittest框架执行测试用例完成后会在控制台输出如上的结果
  • 实际测试过程中,我们需要输出测试报告,这个时候我们需要使用第三方模块

下载HTMLTestRunner

  • 下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

文件修改

  • 94行引入的名称要改,从 import StringIO修改成 import io
  • 539行self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer=io.StringIO()
  • 631行 print >>sys.stderr, ‘\nTime Elapsed: %s’ % (self.stopTime-self.startTime)修改成print (sys.stderr, - ‘\nTime Elapsed: %s’ %(self.stopTime-self.startTime))
  • 642行,if not rmap.has_key(cls): 修改成 if not cls in rmap:
  • 766行的uo = o.decode(‘latin-1’),修改成 uo=o
  • 772行,把 ue = e.decode(‘latin-1’) 直接改成 ue = e

存放路径

  • 将修改完成的模块存放在Python路径下Lib目录里即可
  • D:\Program Files\python37\Lib

实例


unittest断言

  • 断言即测试用例执行结果和预期做对比,符合就即测试用例通过,反之不通过
  • 只能在继承 unittest.TestCase 的类中使用这些方法
  • 常见的几个断言方法(更多断言方法请自行查询)

跳过用例的执行(skip)

  • unittest提供了一些跳过指定用例的方法
  • @unittest.skip(reason):强制跳转, reason是跳转原因
  • @unittest.skipIf(condition, reason):condition为True的时候跳转
  • @unittest.skipUnless(condition, reason):condition为False的时候跳转
  • @unittest.expectedFailure:如果test失败了,这个test不计入失败的case数目

总结

当我们再次使用登录时,只需要修改login_page.py里的定位元素方法和值就可以了

以上代码当然还有很多不足的地方,比如账号密码没有提出来,小伙伴可自行尝试

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

聚道云软件连接器:打破壁垒,实现数电票与航信的无缝对接

一、客户介绍 某网络科技有限公司是一家专注于数字化解决方案的创新型企业。公司致力于为企业提供高效、便捷的科技服务,尤其在发票管理领域具有深厚的技术积累和丰富的实践经验。该公司凭借先进的软件连接技术和优质的服务,赢得了众多客户的信赖和好评…

TF-IDF在现代搜索引擎优化策略中的作用

TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于文本挖掘和信息检索的统计方法,用来评估一个词语对于一个文档或一个语料库的重要程度。TF-IDF算法结合了词频(TF)和逆文档频率(IDF&#xff0…

TOPGP-TIPTOP调用外部Webservice

功能要求:ERP作业调用外部系统的webserice更新数据。 演示环境:ERP作业cooi002(员工档案)录入后更新到外部系统员工档案表。 1、外部系统的WebSerice使用.net搭建 2、在Service.cs中写一个调用方法erp_other erp_other中两个参数…

32.基于分隔符解决黏包和半包

LineBasedFrameDecoder 基于换行/n (linux)或回车换行/r/n(windows)进行分割。 使用LIneBasedFrameDecoder构造方法,需要设定一个最大长度。 如果超过了最大长度,还是没有找到换行符,就这位这个数据段太长了,抛出ToolLongFrameException DelimiterBasedFrameDecoder …

个体核定征收双免个体户0税率大额核定税率全行业筹划

工商银行的会计政策和程序规定 工商银行会计政策和程序规定 工商银行的会计政策和程序规定 https://www.9733.cn/shop/ssch 一、个体工商户核定征收 核定征收是一种简化税收管理方式,适用于簿记不健全、难以准确核算收入和成本的个体。以下是主要特点&#xff1a…

使用Naive UI的级联选择器 Cascader进行省市区选择

序言: 在进行PC版的功能开发时,进行客户管理时老板要让客户便捷的选择自己的省市区等信息,而不是让他们一个个去填写,这时就需要使用级联选择器来进行省市区的选择。 注:element ui/plus的级联选择器也是可以的。 步骤…

美国众议院通过ENFORCE ACT草案:AI领域的潜在冷战?

近日,美国众议院通过了“增强关键出口海外限制国家框架法案”(ENFORCE ACT),该法案旨在限制AI/ML技术和人才向中国的流动。这一举动引发了广泛讨论和担忧,许多人认为这将对在美从事AI相关工作的中国人造成重大影响。本…

基于STM32的智能病房监控和人脸识别系统设计(毕业设计)

摘 要 随着技术的不断进步和医疗需求的不断增长,智能病房控制系统有望在医疗领域发挥更大的作用。基于此,本文研究设计了一款低成本、操作简单、适用性强的基于STM32的智能病房监控和人脸识别系统。该系统通过STM32作为控制器和OpenMV对人脸分辨进行门…

微信小程序开发---自定义底部tabBar

自定义tabBar注意事项: 在自定义 tabBar 模式下 ,为了保证低版本兼容以及区分哪些页面是 tab 页,app.json文件中 tabBar 的相关配置项需完整声明,但这些字段不会作用于自定义 tabBar 的渲染。所有 tabBar 的样式都由该自定义组件…

实现一个渐进优化的 Linux cp 命令

1&#xff0c;第1版 copy 先写个轮廓 selfcp.c &#xff1a; #include <stdio.h>int main() {FILE *source, *destination;char ch;source fopen("H222.txt", "r");if (source NULL) {printf("Error opening source file!\n");retur…

ISO14001认证:引领企业迈向绿色未来

在当今全球环境日益恶化的背景下&#xff0c;绿色发展已成为企业和社会共同追求的目标。ISO14001环境管理体系作为由国际标准化组织&#xff08;ISO&#xff09;制定的环境管理国际标准&#xff0c;为企业提供了系统和全面的环境管理框架&#xff0c;适用于各种类型和规模的组织…

ubuntu 20.04 访问csdn报错 Secure connection failed

打扰了&#xff0c;csdn服务器的问题&#xff0c;和源没关系&#xff0c;后面又重新测试了一下。刚好那一刻网站连上了。 暂时没有好办法&#xff0c;等待一段时间就连上了&#xff0c;改host似乎也不太行。 问题原因&#xff1a; 我一边更新源 sudo apt update & apt up…

计算机组成原理 —— 存储系统(主存储器基本组成)

计算机组成原理 —— 存储系统&#xff08;主存储器基本组成&#xff09; 0和1的硬件表示整合结构寻址按字寻址和按字节寻址按字寻址按字节寻址区别总结 字寻址到字节寻址转化 我们今天来看一下主存储器的基本组成&#xff1a; 0和1的硬件表示 我们知道一个主存储器是由存储体…

Webstorm vue项目@路径不能跳转到对应资源,提示Cannot find declaration to go to

Webstorm vue项目路径不能跳转到对应资源,提示Cannot find declaration to go to 我们 ctrl加鼠标左键点击方法会失效&#xff0c;看了网上很多教程在说需要在此处配置一下webpack.config.js的文件路径&#xff0c;而且指向了node_modules\vue\cli-service\webpack.config.js 我…

MURF3040CTR-ASEMI智能AI应用MURF3040CTR

编辑&#xff1a;ll MURF3040CTR-ASEMI智能AI应用MURF3040CTR 型号&#xff1a;MURF3040CTR 品牌&#xff1a;ASEMI 封装&#xff1a;TO-220F 恢复时间&#xff1a;35ns 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;30A 最大循环峰值反向电压&#xff08;VR…

优选免单模式:电商销售的新篇章

随着电商市场的日益繁荣&#xff0c;各种创新销售模式层出不穷。其中&#xff0c;优选免单模式以其独特的运作方式和激励机制&#xff0c;吸引了大量消费者的目光。该模式的核心在于通过降低商品售价、引入社交元素以及设计阶梯式奖励&#xff0c;激发消费者的购买热情&#xf…

ES全文检索支持繁简和IK分词检索

ES全文检索支持繁简和IK分词检索 1. 前言2. 引入繁简转换插件analysis-stconvert2.1 下载已有作者编译后的包文件2.2 下载源码进行编译2.3 复制解压插件到es安装目录的plugins文件夹下 3. 引入ik分词器插件3.1 已有作者编译后的包文件3.2 只有源代码的版本3.3 安装ik分词插件 4…

Python-日志模块

目录 一、日志级别 二、日志配置 1、日志基本配置 2、日志配置字典&#xff08;知道咋么改就可以&#xff09; 3、日志的使用 一、日志级别 import logginglogging.debug(调试日志) logging.info(消息日志) logging.warning(警告日志) logging.error(错误日志) logging.cr…

1931java Web披萨店订餐系统idea开发mysql数据库web结构java编程计算机网页源码servlet项目

一、源码特点 java Web 披萨店订餐系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。 视频地址&#xff1a;…

sixLabors.ImageSharp图片截取

一、nuget <PackageReference Include"SixLabors.ImageSharp" Version"3.1.4" /> 二、代码 using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; u…