python 自动化学习(三) 句柄获取、模拟按键、opencv安装

一、什么是句柄

     句柄是在操作系统中的一种标识符,相当于我们每个人的身份证一样,句柄在电脑中也是有唯一性的,我们启动的每一个程序都有自己的句柄号,表示自己的身份

    为什么要说句柄,我们如果想做自动化操作时,肯定也不想程序占用了我们整个电脑,稍微操作一下程序步骤就乱掉了,更加希望自动化程序在运行的时候能够只针对某个窗口或者某个程序进行操作,即使我们把自动化的程序放入都后台时也不影响两边的操作,这里就需要用到句柄了

所需的包

#配置清华镜像源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
 
#安装依赖库
pip install pywin32

基本使用

#部分参考文档
https://huaweicloud.csdn.net/63803058dacf622b8df86819.html?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~activity-1-122498299-blog-111083068.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~activity-1-122498299-blog-111083068.pc_relevant_vip_default&utm_relevant_index=1

1、获取鼠标所在位置程序的句柄

import time
import win32api
import win32gui


time.sleep(2)

point = win32api.GetCursorPos()  #win32api.GetCursorPos 获取鼠标当前的坐标(x,y)

hwnd = win32gui.WindowFromPoint(point)  #查看坐标位置窗口的句柄

print(hwnd)  #输出句柄

如下图,我执行了3遍分别在执行后将鼠标放在文本、桌面、idea上面,返回了句柄ID

 

2、通过句柄获取类名

 我们每次关闭重新打开一个程序会发现句柄值变了,每次都从头找句柄就太麻烦了

每一个程序在开发之初就存在着一个叫"类名"的概念,类名和句柄每次变更不同,它在定义后几乎是不会发生变化的,所以我们最好是先找到一个程序的类名,后续直接通过类名找到句柄,然后在通过句柄进行真正所需要的操作

 vi main.py

import time
import win32api
import win32gui

# 通过句柄获取窗口类名
def get_clasname(hwnd):
    clasname = win32gui.GetClassName(hwnd)
    print('窗口类名:%s' % (clasname))
    return clasname



time.sleep(2)
point = win32api.GetCursorPos()
hwnd = win32gui.WindowFromPoint(point)

#查看窗口类名
get_clasname(hwnd)

 可以看到上面我们获取到了文档窗口的类名,现在开始我们直接通过类名去获取句柄

3、通过类名获取句柄

没有找到特定的方法,我们下面大概的思路就是先把主机上所有的句柄id都拿到,通过循环把所有句柄id的类名拿出来然后做对比,对的上的id都留在列表中,所以说如果开启了多个相同程序的窗口,我们也会获取到多个句柄

import time
import win32api
import win32gui

#获取当前主机上的所有句柄id
def get_all_windows():
    all_window_handles = []

    # 枚举所有窗口句柄,添加到列表中
    def enum_windows_proc(hwnd, param):
        param.append(hwnd)
        return True

    # 调用枚举窗口API
    win32gui.EnumWindows(enum_windows_proc, all_window_handles)

    return all_window_handles  #返回的是一个句柄id的列表


#查询传入的句柄id、类名
def get_title(window_handle, class_name):
    #查询句柄的类名
    window_class = win32gui.GetClassName(window_handle)

    #判断窗口类名是否和指定的类名相同,如果相同则返回该窗口句柄,否则返回空值
    if window_class == class_name:
        return window_handle

#遍历窗口句柄的所有子窗口
def get_child_windows(parent_window_handle):
    child_window_handles = []
    def enum_windows_proc(hwnd, param):
        param.append(hwnd)
        return True
    #win32gui.EnumChildWindows    遍历窗口句柄的所有子窗口
    win32gui.EnumChildWindows(parent_window_handle, enum_windows_proc, child_window_handles)
    return child_window_handles


# 根据标题查找窗口句柄
def find_hwnd_by_title(title):
    all_windows = get_all_windows()  #查询所有句柄
    matched_windows = []      #存放所有匹配类名的句柄id

    # 在所有窗口中查找标题匹配的窗口句柄
    for window_handle in all_windows:
        #get_title方法  检查传入句柄对应的类名和我们实际的类名是否对应
        window_title = get_title(window_handle, title)
        if window_title:
            matched_windows.append(window_title) #如果对应就写入列表

    # 如果没有匹配到,则在所有子窗口中查找标题匹配的窗口句柄
    if matched_windows:
        return matched_windows
    else:
        child_window_handles = []
        for parent_window_handle in all_windows:
            #不论子窗口是否有数据都追加到列表
            child_window_handles.extend(get_child_windows(parent_window_handle))
        for child_window_handle in child_window_handles:
            if get_title(child_window_handle, title):
                matched_windows.append(get_title(child_window_handle, title))
    return matched_windows

if __name__ == '__main__':
    hwnd = find_hwnd_by_title("Edit")
    print(hwnd)

 可以看到我们能够直接取到相同类名下所有已经打开的窗口句柄,这样我们甚至可以做个循环加多线程,来实现一个窗口并发的效果

二、模拟按键

上面我们已经拿到了文本文档的一个句柄信息,通过句柄我们可以做很多事情,最常见的就是模拟鼠标和键盘的按键操作,每个操作可能都较为细小琐碎,我们定义一个class类来存放

常见消息类型和标识

#官方参考
https://learn.microsoft.com/zh-cn/windows/win32/inputdev/wm-lbuttondown
消息类型作用消息标识作用
WM_MOUSEMOVE鼠标 移动移动通用左键右键标识
WM_RBUTTONDOWN鼠标 右键按下MK_RBUTTON左键按下
WM_RBUTTONUP鼠标 右键释放None释放时无需标识
WM_LBUTTONDOWN鼠标 左键按下MK_LBUTTON右键按下
WM_LBUTTONUP鼠标 左键释放None释放时无需标识

 当按键需要被按下时,需要先声明消息类型,然后标明按键状态
  如果鼠标按键需要被释放时,可以直接通过释放按钮来释放
  如果指定消息类型是移动时,可以当作已经声明了消息类型,可以直接使用按键标识

使用语法

#在win32api下有个函数PostMessage,是用来与windows api交互的,参数如下
1、要发送消息的目标窗口的句柄
2、发送的消息类型
3、以及消息的参数 


win32api.PostMessage(句柄id, 消息类型, 消息标识, 具体的坐标(x,y))

获取目标坐标

#获取坐标
time.sleep(3)
print(win32api.GetCursorPos())

返回

(328, 250)

 

鼠标按键案例

      下面定义了一个类,先去接受我们上面获取到的句柄id,在使用鼠标按键的时候调用win32api.PostMessage函数 去发送给句柄所在的窗口按键信息

   在左右键按下的时候才需要定义标识,比如模拟左键时会使用WM_LBUTTONDOWN和MK_LBUTTON  ,而松开时使用WM_LBUTTONUP和None

   变量pos 是只鼠标按键的坐标,需要通过win32api.MAKELONG 转换数据类型后才能调用


#声明鼠标操作的类
class WinMouse(object):

    #初始化函数,接受传入的句柄id
    def __init__(self, handle_num: int):
        self.handle = handle_num  

    #鼠标左键按下
    def left_button_down(self, pos):
            win32api.PostMessage(self.handle, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, pos)

    #鼠标左键释放
    def left_button_up(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_LBUTTONUP, None, pos)



if __name__ == '__main__':
    hwnd = find_hwnd_by_title("Edit")   #通过类名获取句柄
    bd = WinMouse(hwnd[0])              #实例化WinMouse 类,传入句柄值

    pos = win32api.MAKELONG(328, 250)   #将正常的x,y坐标值转换为特定的数据结构,
                                       #给win32api.PostMessage调用

    #按下、等待1s、松开
    bd.left_button_down(pos)  
    time.sleep(1)             
    bd.left_button_up(pos)    

可以看到在下图中,我们运行程序后,不论文本文档是否在前台还是后台,哪怕被遮挡住后也会照常进行鼠标点击(数字太多看不清,大致就是我把鼠标放到末尾,程序在我上面取坐标的地方点一下左键)

其他按键补全

    #按下鼠标左键并移动
    def mouse_move(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, pos)

    #按下鼠标右键并移动
    def right_button_move(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_MOUSEMOVE, win32con.MK_RBUTTON, pos)

    #指定坐标按下右键
    def right_button_down(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_RBUTTONDOWN, win32con.MK_RBUTTON, pos)
    #右键释放
    def right_button_up(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_RBUTTONUP, None, pos)

    #模拟左键双击
    def left_double_click(self, x_pos:int, y_pos:int, click=2, wait=0.4):
        wait = wait / click  #click 表示点击次数,wait是的等待时间,意思是双击的间隔
        point = win32api.MAKELONG(x_pos, y_pos)
        for i in range(click):
            self.left_button_down(point)
            time.sleep(wait)
            self.left_button_up(point)
    #右键双击
    def right_doubleClick(self, x, y, click=2, wait=0.4):
        wait = wait / click
        pos = win32api.MAKELONG(x, y)
        for i in range(click):
            self.right_button_down(pos)
            time.sleep(wait)
            self.right_button_up(pos)

按键组合函数

上面用一个按左键都要好几行,我们这里在给封装一下

    #让他可以直接接收x,y坐标,wait是松开按键的间隔,一般默认即可
    #左键单击
    def left_click(self, x_pos:int, y_pos:int, wait=0.2):
        point = win32api.MAKELONG(x_pos, y_pos)
        self.left_button_down(point)
        time.sleep(wait)
        self.left_button_up(point)

    #右键单击
    def right_click(self, x_pos:int, y_pos:int, wait=0.2):
        point = win32api.MAKELONG(x_pos, y_pos)
        self.right_button_down(point)
        time.sleep(wait)
        self.right_button_up(point)

    #模拟左键双击
    def left_double_click(self, x_pos:int, y_pos:int, click=2, wait=0.4):
        wait = wait / click  #click 表示点击次数,wait是的等待时间,意思是双击的间隔
        point = win32api.MAKELONG(x_pos, y_pos)
        for i in range(click):
            self.left_button_down(point)
            time.sleep(wait)
            self.left_button_up(point)
    #右键双击
    def right_doubleClick(self, x, y, click=2, wait=0.4):
        wait = wait / click
        pos = win32api.MAKELONG(x, y)
        for i in range(click):
            self.right_button_down(pos)
            time.sleep(wait)
            self.right_button_up(pos)

鼠标滑动拖拽

添加偏移值

 vi main.py

#计算鼠标从起始点到目标点的偏移过程
def getPointOnLine(start_x, start_y, end_x, end_y, ratio):
    x = ((end_x - start_x) * ratio) + start_x
    y = ((end_y - start_y) * ratio) + start_y
    return int(round(x)), int(round(y))


class WinMouse(object):

    def __init__(self, handle_num: int, num_of_steps=80): #添加num_of_steps=80
        self.handle = handle_num
        self.num_of_steps = num_of_steps  #添加偏移值

添加左右键拖动方法

    #模拟点击并拖拽目标,接受两对坐标值
    def left_click_move(self, x1:int, y1:int, x2:int, y2:int, wait=2):
        point1 = win32api.MAKELONG(x1, y1)
        self.left_button_down(point1)  #起始点按下鼠标左键
        #获取我们在init初始化时定义的偏移值
        steps = self.num_of_steps

        #调用我们上面的方法返回具体,循环0-80的值
        #你看这里的循环值是80,也就说会做80次循环操作
        #我们传入了起始坐标和目标坐标,而i / steps就相当于起始到结束的偏移位置
        #可以理解为从左上角到右下角的点
        points = [getPointOnLine(x1, y1, x2, y2,  i / steps) for i in range(steps)]
        points.append((x2, y2))
        wait_time = wait / steps
        unique_points = list(set(points))
        unique_points.sort(key=points.index)
        for point in unique_points:
            x, y = point
            point = win32api.MAKELONG(x, y)
            self.mouse_move(point)
            time.sleep(wait_time)
        self.left_button_up(point)
    #右键单击并滑动批量勾选(与上方函数同理)
    def right_click_move(self, start_x, start_y, end_x, end_y, wait=2):
        pos = win32api.MAKELONG(start_x, start_y)
        self.right_button_down(pos)
        steps = self.num_of_steps
        points = [getPointOnLine(start_x, start_y, end_x, end_y, i / steps) for i in range(steps)]
        points.append((end_x, end_y))
        time_per_step = wait / steps
        distinct_points = list(set(points))
        distinct_points.sort(key=points.index)
        for point in distinct_points:
            x, y = point
            pos = win32api.MAKELONG(x, y)
            self.right_button_move(pos)
            time.sleep(time_per_step)
        self.right_button_up(pos)

演示

    bd.left_click_move(109,180,232,341)

 

全量代码

import ctypes
import time

import cv2
import numpy as np
import win32api
import win32con
import win32gui
import win32ui
from PIL.Image import Image


import main2


#---------------------------------------------------句柄配置的分割线
#获取当前主机上的所有句柄id
def get_all_windows():
    all_window_handles = []

    # 枚举所有窗口句柄,添加到列表中
    def enum_windows_proc(hwnd, param):
        param.append(hwnd)
        return True

    # 调用枚举窗口API
    win32gui.EnumWindows(enum_windows_proc, all_window_handles)

    return all_window_handles  #返回的是一个句柄id的列表

#查询传入的句柄id、类名
def get_title(window_handle, class_name):
    #查询句柄的类名
    window_class = win32gui.GetClassName(window_handle)

    #判断窗口类名是否和指定的类名相同,如果相同则返回该窗口句柄,否则返回空值
    if window_class == class_name:
        return window_handle

#遍历窗口句柄的所有子窗口
def get_child_windows(parent_window_handle):
    child_window_handles = []
    def enum_windows_proc(hwnd, param):
        param.append(hwnd)
        return True
    #win32gui.EnumChildWindows    遍历窗口句柄的所有子窗口
    win32gui.EnumChildWindows(parent_window_handle, enum_windows_proc, child_window_handles)
    return child_window_handles

# 根据标题查找窗口句柄
def find_hwnd_by_title(title):
    all_windows = get_all_windows()  #查询所有句柄
    matched_windows = []      #存放所有匹配类名的句柄id

    # 在所有窗口中查找标题匹配的窗口句柄
    for window_handle in all_windows:
        #get_title方法  检查传入句柄对应的类名和我们实际的类名是否对应
        window_title = get_title(window_handle, title)
        if window_title:
            matched_windows.append(window_title) #如果对应就写入列表

    # 如果没有匹配到,则在所有子窗口中查找标题匹配的窗口句柄
    if matched_windows:
        return matched_windows
    else:
        child_window_handles = []
        for parent_window_handle in all_windows:
            #不论子窗口是否有数据都追加到列表
            child_window_handles.extend(get_child_windows(parent_window_handle))
        for child_window_handle in child_window_handles:
            if get_title(child_window_handle, title):
                matched_windows.append(get_title(child_window_handle, title))
    return matched_windows

#-----------------------------------------------------句柄配置的分割线


def getPointOnLine(start_x, start_y, end_x, end_y, ratio):
    x = ((end_x - start_x) * ratio) + start_x
    y = ((end_y - start_y) * ratio) + start_y
    return int(round(x)), int(round(y))

#声明鼠标操作的类
class WinMouse(object):

    #初始化函数,接受传入的句柄id
    def __init__(self, handle_num: int, num_of_steps=80):
        self.handle = handle_num
        self.num_of_steps = num_of_steps

        #鼠标左键按下
    def left_button_down(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, pos)

    #鼠标左键释放
    def left_button_up(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_LBUTTONUP, None, pos)

    #按下鼠标左键并移动
    def mouse_move(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, pos)

    #按下鼠标右键并移动
    def right_button_move(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_MOUSEMOVE, win32con.MK_RBUTTON, pos)

    #指定坐标按下右键
    def right_button_down(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_RBUTTONDOWN, win32con.MK_RBUTTON, pos)
    #右键释放
    def right_button_up(self, pos):
        win32api.PostMessage(self.handle, win32con.WM_RBUTTONUP, None, pos)

#--------------------------------------------------------封装按键方法的分割线

    #让他可以直接接收x,y坐标,wait是松开按键的间隔,一般默认即可
    #左键单击
    def left_click(self, x_pos:int, y_pos:int, wait=0.2):
        point = win32api.MAKELONG(x_pos, y_pos)
        self.left_button_down(point)
        time.sleep(wait)
        self.left_button_up(point)

    #右键单击
    def right_click(self, x_pos:int, y_pos:int, wait=0.2):
        point = win32api.MAKELONG(x_pos, y_pos)
        self.right_button_down(point)
        time.sleep(wait)
        self.right_button_up(point)

    #模拟左键双击
    def left_double_click(self, x_pos:int, y_pos:int, click=2, wait=0.4):
        wait = wait / click  #click 表示点击次数,wait是的等待时间,意思是双击的间隔
        point = win32api.MAKELONG(x_pos, y_pos)
        for i in range(click):
            self.left_button_down(point)
            time.sleep(wait)
            self.left_button_up(point)
    #右键双击
    def right_doubleClick(self, x, y, click=2, wait=0.4):
        wait = wait / click
        pos = win32api.MAKELONG(x, y)
        for i in range(click):
            self.right_button_down(pos)
            time.sleep(wait)
            self.right_button_up(pos)


    #模拟点击并拖拽目标,接受两对坐标值
    #模拟点击并拖拽目标,接受两对坐标值
    def left_click_move(self, x1:int, y1:int, x2:int, y2:int, wait=2):
        point1 = win32api.MAKELONG(x1, y1)
        self.left_button_down(point1)  #起始点按下鼠标左键
        #获取我们在init初始化时定义的偏移值
        steps = self.num_of_steps

        #调用我们上面的方法返回具体,循环0-80的值
        #你看这里的循环值是80,也就说会做80次循环操作
        #我们传入了起始坐标和目标坐标,而i / steps就相当于起始到结束的偏移位置
        #可以理解为从左上角到右下角的点
        points = [getPointOnLine(x1, y1, x2, y2,  i / steps) for i in range(steps)]
        points.append((x2, y2))
        wait_time = wait / steps
        unique_points = list(set(points))
        unique_points.sort(key=points.index)
        for point in unique_points:
            x, y = point
            point = win32api.MAKELONG(x, y)
            self.mouse_move(point)
            time.sleep(wait_time)
        self.left_button_up(point)
    #右键单击并滑动批量勾选(与上方函数同理)
    def right_click_move(self, start_x, start_y, end_x, end_y, wait=2):
        pos = win32api.MAKELONG(start_x, start_y)
        self.right_button_down(pos)
        steps = self.num_of_steps
        points = [getPointOnLine(start_x, start_y, end_x, end_y, i / steps) for i in range(steps)]
        points.append((end_x, end_y))
        time_per_step = wait / steps
        distinct_points = list(set(points))
        distinct_points.sort(key=points.index)
        for point in distinct_points:
            x, y = point
            pos = win32api.MAKELONG(x, y)
            self.right_button_move(pos)
            time.sleep(time_per_step)
        self.right_button_up(pos)

if __name__ == '__main__':
    hwnd = find_hwnd_by_title("Edit")   #通过类名获取句柄
    bd = WinMouse(hwnd[0])              #实例化WinMouse 类,传入句柄值

    bd.left_click_move(109,180,232,341)

三、准备opencv环境

安装模块

pip install opencv-python
pip install pyautogui
pip install pillow
pip install opencv-contrib-python

我这边在安装上opencv-python 后调用cv2下任意方法都提示报黄,没有代码提示,下面列出解决方法

(venv) PS C:\Users\Administrator\IdeaProjects\test> pip install opencv-python
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: opencv-python in c:\users\administrator\ideaprojects\test\venv\lib\site-packages (4.7.0.72)
Requirement already satisfied: numpy>=1.21.2 in c:\users\administrator\ideaprojects\test\venv\lib\site-packages (from opencv-python) (1.24.3)

我们在安装成功opencv-python模块后会返回一个安装路径,登录这个路径,进入cv2的目录下,将cv2.pyd 文件放到下面的路径下,重启编辑器即可

c:\users\administrator\ideaprojects\test\venv\lib\site-packages

 

测试语句

import cv2
# 加载一张图片
img = cv2.imread('11.png', 1)   #脚本文件旁边自行准备一个图片

# 显示图片
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

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

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

相关文章

分布式项目 11 在项目中使用jsonp发送请求并且处理

在项目中使用jsonp技术 01.相关子系统的搭建 第一步:创建一个新的子系统,叫做jt-sso 选中jt父级项目,然后鼠标右键进行new,然后选中maven Model,进行项目的创建,具体操 作如下图所示: 第二步…

空气中的声压级、声功率级、声强级的区别

空气中的声压级、声功率级、的区别 在学习声学理论时,经常听到,声压级、声强级、声功率级的名称,经常也听到它们的单位为dB.但是它们是怎样的区别呢?下面介绍这几个名词 一、定义和计算 1.声压级 声压级以 L p {L_p} Lp​表示&am…

解决weekofyear跨年问题

目录 前言跨年问题计算当年第几周前言 前段时间,做了一个日期维度表的需求,发现 计算当年第几周 有误,发现 Hive 中 weekofyear 函数存在跨年问题! 跨年问题 这一周算上一年还是下一年,取决于这一周的大多数日期(4天及以上)在哪一年。算在前一年,就是前一年的最后一…

算法修炼之练气篇——练气十二层

博主:命运之光 专栏:算法修炼之练气篇 前言:每天练习五道题,炼气篇大概会练习200道题左右,题目有C语言网上的题,也有洛谷上面的题,题目简单适合新手入门。(代码都是命运之光自己写的…

机械师曙光16电脑开机自动蓝屏怎么解决?

机械师曙光16电脑开机自动蓝屏怎么解决?有的用户在使用机械师曙光16电脑的时候,遇到了一些系统问题,导致自己无法正常的开机使用电脑。因为电脑总会变成蓝屏,无法进行任何操作。那么这个情况怎么去进行问题的解决呢?来…

【2023年电工杯数学建模竞赛B题人工智能对大学生学习影响的评价】完整思路分析+完整代码

1.问题背景与描述 这道题整体还是相对简单的,比较适合新手,选的人多对应获奖数量也会多,所以不要纠结于选题,就选你看上去能做的就好 2.问题分析 2.1 问题一的分析 对附件2中所给数据进行分析和数值化处理,并给出处…

SpringMVC一站式学习,分分钟钟让你上手

文章目录 一、SpringMVC1.1 引言1.2 MVC架构1.2.1 概念1.2.2 好处 二、开发流程2.1 导入依赖2.2 配置核心(前端)控制器2.3 后端控制器2.4 配置文件2.5 访问 三、接收请求参数3.1 基本类型参数3.2 实体收参【重点】3.3 数组收参3.4 集合收参 【了解】3.5 路径参数3.6 中文乱码 四…

【Netty】字节缓冲区 ByteBuf(七)(下)

文章目录 前言一、实现原理二、ByteBuf 的使用案例三、ByteBuf 的3种使用模式3.1 堆缓冲模式3.2 直接缓冲区模式3.3 复合缓冲区模式 总结 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设计(二)Netty Channel 概…

springcloud-alibaba (03)sentinel实现规则持久化-流控规则为例

Sentinel和Nacos的整合可以实现规则动态配置,即在Nacos中修改规则后,Sentinel能够实时地读取并应用新的规则。而规则持久化则是指将规则保存在Nacos中,以避免意外故障或重启时规则被丢失。 实现规则持久化,可以按照以下步骤进行操…

达梦数据库索引的建立使用

达梦数据库支持聚集索引,复合索引,函数索引,唯一索引,位图索引等等。 一.建立索引的准则 1.1在表中插入数据后创建索引 一般情况下,在插入或装载了数据后,为表创建索引会更加有效率。如果在装载数据之前…

进阶篇丨链路追踪(Tracing)很简单:常见问题排查

作者:涯海 经过前面多篇内容的学习,想必大部分同学都已经熟练掌握分布式链路追踪的基础用法,比如回溯链路请求轨迹,定位耗时瓶颈点;配置核心接口黄金三指标告警,第一时间发现流量异常;大促前梳…

电赛E题声源定位跟踪系统制作全过程

声源定位 文章目录 声源定位前言一、题目二、设计步骤1.设计思路2.声源追踪定位的分析3.舵机转角的确定4.声源距离的计算 三、代码编写1.求均值2.卡尔曼滤波 复刻一下电赛的声源定位 前言 2023年的电子设计竞赛快要开始了,同时我也已经大三下了正在准备找工作&…

涨点神器:基于Yolov5/Yolov7的小目标性能提升

1.小目标介绍 目标检测近十年涌现了一大批如Faster R-CNN、RetinaNet、YOLO等可以在工业界实用的目标检测方法,但小目标检测性能差的问题至今也没有被完全解决。因为Swin Transformer的提出,COCO test-dev上的 AP 已经刷到64 ,但小目标检测性能(即APS )和大目标检测性能(…

分享以MM32SPIN0280单片机为主控洗衣机方案

洗衣机是利用电能产生机械作用来洗涤衣物的清洁电器,按驱动方法有3类,直接驱动,皮带驱动,波轮式驱动。 主变一体洗衣机方案以MM32SPIN0280为主控 MCU规格: -ArmCortex-M0内核,最高工作频率可达96MHz -128…

MOSN 基于延迟负载均衡算法——走得更快,期待走得更稳

文|纪卓志(GitHub ID:jizhuozhi) 京东高级开发工程师 MOSN 项目 Committer 专注于云原生网关研发的相关工作,长期投入在负载均衡和流量控制领域 前言 这篇文章主要是介绍 MOSN 在 v1.5.0 中新引入的基于延迟的负载均衡算法#2…

【vimsolo】让vim看起来像VSCode:颜色主题和状态栏的配置

文章目录 1. 目的2. 理念: vimsolo3. vimrc: 配置颜色4. vimrc: 配置状态栏5. 拷贝颜色主题和.vimrc: python安装脚本 1. 目的 习惯了 VSCode 默认的配色:黑色主题,蓝色状态栏。偶尔使用 Vim 时想让 vim 伪装的像 VSCode,不考虑花…

float浮点/double双精度浮点和二进制的相互转换,小白也能看明白!

二进制文件包含了太多的数据,如何看懂二进制文件,决定于基础。 文章目录 前言1、重点知识1.1何为二进制文件1.2浮点和双精度的浮点如何生成二进制1.2.1 float和double的基础知识1.2.2 IEEE754约束的重点1.2.3 浮点是如何表示二进制 1.3 例子说明 双精度d…

市面上常见的语音芯片的IO口有哪些作用

语音芯片的IO口有哪些作用? 语音芯片的IO口一般有多种用途,包括以下几种: 1. 语音输入:可以通过外部麦克风接口,将外部声音信号输入到语音芯片中,进行语音信号处理。 2. 语音输出:语音芯片可…

Java版电子招投标系统源码之了解电子招标投标全流程

随着各级政府部门的大力推进,以及国内互联网的建设,电子招投标已经逐渐成为国内主流的招标投标方式,但是依然有很多人对电子招投标的流程不够了解,在具体操作上存在困难。虽然各个交易平台的招标投标在线操作会略有不同&#xff0…

【MySQL】实验十 E-R图

文章目录 1. 学校2. 院系3. 图书馆4. 舰队5. 工厂6. 网购7. IT8. 医院9. 公司1. 学校 设有如下实体: 班主任:工号、姓名、电话 班级:班号、专业、毕业总学分 学生:学号、姓名、性别、年龄 课程:课程号、课程名 上述实体中存在如下联系: (1)一个班主任管理一个班级,一…