首页 > 编程语言 >python控制UI实现桌面微信自动化

python控制UI实现桌面微信自动化

时间:2024-03-18 22:02:20浏览次数:34  
标签:return Name python 微信 self who UI 聊天 ._

Hello,我是新星博主:小恒不会java

背景

使用 wxpy 或者 itchat 这种第三方库通过Python控制自己的微信号,实现很多自动化操作,用的是微信网页版接口,不过随着微信的发展(信息安全等方面愈加重要,这种不符合官方期望出现的东西,很容易就破产。也由于itchat在 python 的 request 请求中,使用到的 headers 都是非常简单的 headers。而且频繁利用到
config.USER_AGENT ,被发现怀疑用脚本封号是当然的

所以我打算用wxauto,用UI控件的形式操作微信(uiautomation实现)

wxauto第三方库介绍

wxauto是某GitHub某位开源的

https://github.com/cluic/wxauto

功能很基础,毕竟是UI控件,实现的功能有

(1)群发消息包括图片,文件

(2)自动回复和添加好友(有小bug,简单修改一下就行)

(3) 监控群聊人员或者个人聊天框

(4)获取微信好友昵称等信息(有bug,我改了一下没成功)

效果如下

wxauto.py代码

"""
Author: Cluic
Update: 2024-03-10
Version: 3.9.8.15
"""

import uiautomation as uia
from .languages import *
from .utils import *
from .elements import *
from .errors import *
from .color import *
import datetime
import time
import os
import re
try:
    from typing import Literal
except:
    from typing_extensions import Literal

class WeChat(WeChatBase):
    def __init__(self, language='cn') -> None:
        """微信UI自动化实例

        Args:
            language (str, optional): 微信客户端语言版本, 可选: cn简体中文  cn_t繁体中文  en英文, 默认cn, 即简体中文
        """
        self.VERSION = '3.9.8.15'
        self.language = language
        self.lastmsgid = None
        self.listen = dict()
        self._checkversion()
        self.UiaAPI = uia.WindowControl(ClassName='WeChatMainWndForPC', searchDepth=1)
        self._show()
        self.SessionItemList = []
        MainControl1 = [i for i in self.UiaAPI.GetChildren() if not i.ClassName][0]
        MainControl2 = MainControl1.GetChildren()[0]
        # 三个布局,导航栏(A)、聊天列表(B)、聊天框(C)
        # _______________
        # |■|———|    -□×|
        # | |———|       |
        # |A| B |   C   |   <--- 微信窗口布局简图示意
        # | |———|———————|
        # |=|———|       |
        # ———————————————
        self.NavigationBox, self.SessionBox, self.ChatBox  = MainControl2.GetChildren()
        
        # 初始化导航栏,以A开头 | self.NavigationBox  -->  A_xxx
        self.A_MyIcon = self.NavigationBox.ButtonControl()
        self.A_ChatIcon = self.NavigationBox.ButtonControl(Name=self._lang('聊天'))
        self.A_ContactsIcon = self.NavigationBox.ButtonControl(Name=self._lang('通讯录'))
        self.A_FavoritesIcon = self.NavigationBox.ButtonControl(Name=self._lang('收藏'))
        self.A_FilesIcon = self.NavigationBox.ButtonControl(Name=self._lang('聊天文件'))
        self.A_MomentsIcon = self.NavigationBox.ButtonControl(Name=self._lang('朋友圈'))
        self.A_MiniProgram = self.NavigationBox.ButtonControl(Name=self._lang('小程序面板'))
        self.A_Phone = self.NavigationBox.ButtonControl(Name=self._lang('手机'))
        self.A_Settings = self.NavigationBox.ButtonControl(Name=self._lang('设置及其他'))
        
        # 初始化聊天列表,以B开头
        self.B_Search = self.SessionBox.EditControl(Name=self._lang('搜索'))
        
        # 初始化聊天栏,以C开头
        self.C_MsgList = self.ChatBox.ListControl(Name=self._lang('消息'))
        
        self.nickname = self.A_MyIcon.Name
        print(f'初始化成功,获取到已登录窗口:{self.nickname}')
    
    def _checkversion(self):
        self.HWND = FindWindow(classname='WeChatMainWndForPC')
        wxpath = GetPathByHwnd(self.HWND)
        wxversion = GetVersionByPath(wxpath)
        if wxversion != self.VERSION:
            Warnings.lightred(self._lang('版本不一致,需要3.9.8.15版本微信,前往下载:https://github.com/tom-snow/wechat-windows-versions/releases?page=2', 'WARNING').format(wxversion, self.VERSION), stacklevel=2)
            return False
    
    def _show(self):
        self.HWND = FindWindow(classname='WeChatMainWndForPC')
        win32gui.ShowWindow(self.HWND, 1)
        win32gui.SetWindowPos(self.HWND, -1, 0, 0, 0, 0, 3)
        win32gui.SetWindowPos(self.HWND, -2, 0, 0, 0, 0, 3)
        self.UiaAPI.SwitchToThisWindow()
    
    def GetSessionAmont(self, SessionItem):
        """获取聊天对象名和新消息条数
        
        Args:
            SessionItem (uiautomation.ListItemControl): 聊天对象控件
            
        Returns:
            sessionname (str): 聊天对象名
            amount (int): 新消息条数
        """
        matchobj = re.search('\d+条新消息', SessionItem.Name)
        amount = 0
        if matchobj:
            try:
                amount = int([i for i in SessionItem.GetChildren()[0].GetChildren() if type(i) == uia.uiautomation.TextControl][0].Name)
            except:
                pass
        if amount:
            sessionname = SessionItem.Name.replace(f'{amount}条新消息','')
        else:
            sessionname = SessionItem.Name
        return sessionname, amount
    
    def CheckNewMessage(self):
        """是否有新消息"""
        self._show()
        return IsRedPixel(self.A_ChatIcon)
    #self.A_ChatIcon 图像中的红色像素点来判断是否有新消息。在很多应用中,新消息未读时图标会显示为红色,因此通过检测图标的红色像素是否存在,可以间接地确定是否有新消息。
    
    def GetNextNewMessage(self, savepic=False):
        """获取下一个新消息"""
        msgs_ = self.GetAllMessage()
        if self.lastmsgid is not None and self.lastmsgid in [i[-1] for i in msgs_[:-1]]:
            print('获取当前窗口新消息')
            idx = [i[-1] for i in msgs_].index(self.lastmsgid)
            MsgItems = self.C_MsgList.GetChildren()[idx+1:]
            msgs = self._getmsgs(MsgItems, savepic)
            return {self.CurrentChat(): msgs}

        elif self.CheckNewMessage():
            print('获取其他窗口新消息')
            while True:
                self.A_ChatIcon.DoubleClick(simulateMove=False)
                sessiondict = self.GetSessionList(newmessage=True)
                if sessiondict:
                    break
            for session in sessiondict:
                self.ChatWith(session)
                MsgItems = self.C_MsgList.GetChildren()[-sessiondict[session]:]
                msgs = self._getmsgs(MsgItems, savepic)
                self.lastmsgid = msgs[-1][-1]
                return {session:msgs}
        else:
            # print('没有新消息')
            return None
        
        #该函数用于获取下一个新消息。首先,它会尝试获取当前窗口的新消息,如果成功,则返回当前聊天窗口的消息列表。
        #如果当前窗口没有新消息,它会检查是否有其他窗口有新消息。如果有,则会逐个点击聊天图标,打开有新消息的聊天窗口,并返回该窗口的消息列表。
        #函数返回一个字典,包含每个聊天窗口的消息列表。如果没有新消息,则返回None。
        
    
    def GetAllNewMessage(self):
        """获取所有新消息"""
        newmessages = {}
        while True:
            if self.CheckNewMessage():
                self.A_ChatIcon.DoubleClick(simulateMove=False)
                sessiondict = self.GetSessionList(newmessage=True)
                for session in sessiondict:
                    self.ChatWith(session)
                    newmessages[session] = self.GetAllMessage()[-sessiondict[session]:]
            else:
                break
        self.ChatWith(self._lang('文件传输助手'))
        return newmessages
    
    def GetSessionList(self, reset=False, newmessage=False):
        """获取当前聊天列表中的所有聊天对象
        
        Args:
            reset (bool): 是否重置SessionItemList
            newmessage (bool): 是否只获取有新消息的聊天对象
            
        Returns:
            SessionList (dict): 聊天对象列表,键为聊天对象名,值为新消息条数
        """
        self.SessionItem = self.SessionBox.ListItemControl()
        if reset:
            self.SessionItemList = []
        SessionList = {}
        for i in range(100):
            if self.SessionItem.BoundingRectangle.width() != 0:
                try:
                    name, amount = self.GetSessionAmont(self.SessionItem)
                except:
                    break
                if name not in self.SessionItemList:
                    self.SessionItemList.append(name)
                if name not in SessionList:
                    SessionList[name] = amount
            self.SessionItem = self.SessionItem.GetNextSiblingControl()
            if not self.SessionItem:
                break
            
        if newmessage:
            return {i:SessionList[i] for i in SessionList if SessionList[i] > 0}
        return SessionList
    
    def ChatWith(self, who, notfound: Literal['raise', 'ignore']='ignore'):
        '''打开某个聊天框
        
        Args:
            who ( str ): 要打开的聊天框好友名;  * 最好完整匹配,不完全匹配只会选取搜索框第一个
            notfound ( str, optional ): 未找到时的处理方式,可选:raise-抛出异常  ignore-忽略,默认ignore
            
        Returns:
            chatname ( str ): 匹配值第一个的完整名字
        '''
        self._show()
        sessiondict = self.GetSessionList(True)
        if who in list(sessiondict.keys())[:-1]:
            if sessiondict[who] > 0:
                who1 = f"{who}{sessiondict[who]}条新消息"
            else:
                who1 = who
            self.SessionBox.ListItemControl(Name=who1).Click(simulateMove=False)
            return who
        self.UiaAPI.SendKeys('{Ctrl}f', waitTime=1)
        self.B_Search.SendKeys(who, waitTime=1.5)
        SearchResut = self.SessionBox.GetChildren()[1].GetChildren()[1]
        firstresult = [i for i in SearchResut.GetChildren()[0].GetChildren() if who in i.Name][0]
        if firstresult.Name == f'搜索 {who}':
            if len(self.SessionBox.GetChildren()[1].GetChildren()) > 1:
                self.B_Search.SendKeys('{Esc}')
            if notfound == 'raise':
                raise TargetNotFoundError(f'未查询到目标:{who}')
            elif notfound == 'ignore':
                return None
        chatname = firstresult.Name
        firstresult.Click(simulateMove=False)
        return chatname
    
    def SendMsg(self, msg, who=None, clear=True):
        """发送文本消息

        Args:
            msg (str): 要发送的文本消息
            who (str): 要发送给谁,如果为None,则发送到当前聊天页面。  *最好完整匹配,优先使用备注
            clear (bool, optional): 是否清除原本的内容,
        """
        if who in self.listen:
            chat = self.listen[who]
            chat.SendMsg(msg)
            return None
        if not msg:
            return None
        if who:
            try:
                editbox = self.ChatBox.EditControl(searchDepth=10)
                if who in self.CurrentChat() and who in editbox.Name:
                    pass
                else:
                    self.ChatWith(who)
                    editbox = self.ChatBox.EditControl(Name=who, searchDepth=10)
            except:
                self.ChatWith(who)
                editbox = self.ChatBox.EditControl(Name=who, searchDepth=10)
        else:
            editbox = self.ChatBox.EditControl(searchDepth=10)
        if clear:
            editbox.SendKeys('{Ctrl}a', waitTime=0)
        self._show()
        if not editbox.HasKeyboardFocus:
            editbox.Click(simulateMove=False)
        
        t0 = time.time()
        while True:
            if time.time() - t0 > 10:
                raise TimeoutError(f'发送消息超时 --> {editbox.Name} - {msg}')
            SetClipboardText(msg)
            editbox.SendKeys('{Ctrl}v')
            if editbox.GetValuePattern().Value:
                break
        editbox.SendKeys('{Enter}')
        
    def SendFiles(self, filepath, who=None):
        """向当前聊天窗口发送文件
        
        Args:
            filepath (str|list): 要复制文件的绝对路径  
            who (str): 要发送给谁,如果为None,则发送到当前聊天页面。  *最好完整匹配,优先使用备注
            
        Returns:
            bool: 是否成功发送文件
        """
        if who in self.listen:
            chat = self.listen[who]
            chat.SendFiles(filepath)
            return None
        filelist = []
        if isinstance(filepath, str):
            if not os.path.exists(filepath):
                Warnings.lightred(f'未找到文件:{filepath},无法成功发送', stacklevel=2)
                return False
            else:
                filelist.append(os.path.realpath(filepath))
        elif isinstance(filepath, (list, tuple, set)):
            for i in filepath:
                if os.path.exists(i):
                    filelist.append(i)
                else:
                    Warnings.lightred(f'未找到文件:{i}', stacklevel=2)
        else:
            Warnings.lightred(f'filepath参数格式错误:{type(filepath)},应为str、list、tuple、set格式', stacklevel=2)
            return False
        
        if filelist:
            self._show()
            if who:
                try:
                    if who in self.CurrentChat() and who in self.ChatBox.EditControl(searchDepth=10).Name:
                        pass
                    else:
                        self.ChatWith(who)
                except:
                    self.ChatWith(who)
                editbox = self.ChatBox.EditControl(Name=who)
            else:
                editbox = self.ChatBox.EditControl()
            editbox.SendKeys('{Ctrl}a', waitTime=0)
            t0 = time.time()
            while True:
                if time.time() - t0 > 10:
                    raise TimeoutError(f'发送文件超时 --> {filelist}')
                SetClipboardFiles(filelist)
                time.sleep(0.2)
                editbox.SendKeys('{Ctrl}v')
                if editbox.GetValuePattern().Value:
                    break
            editbox.SendKeys('{Enter}')
            return True
        else:
            Warnings.lightred('所有文件都无法成功发送', stacklevel=2)
            return False
            
    def GetAllMessage(self, savepic=False, n=0):
        '''获取当前窗口中加载的所有聊天记录
        
        Args:
            savepic (bool): 是否自动保存聊天图片
            
        Returns:
            list: 聊天记录信息
        '''
        MsgItems = self.C_MsgList.GetChildren()
        msgs = self._getmsgs(MsgItems, savepic)
        return msgs
    
    def LoadMoreMessage(self):
        """加载当前聊天页面更多聊天信息
        
        Returns:
            bool: 是否成功加载更多聊天信息
        """
        loadmore = self.C_MsgList.GetChildren()[0]
        loadmore_top = loadmore.BoundingRectangle.top
        top = self.C_MsgList.BoundingRectangle.top
        while True:
            if loadmore.BoundingRectangle.top > top or loadmore.Name == '':
                isload = True
                break
            else:
                self.C_MsgList.WheelUp(wheelTimes=10, waitTime=0.1)
                if loadmore.BoundingRectangle.top == loadmore_top:
                    isload = False
                    break
                else:
                    loadmore_top = loadmore.BoundingRectangle.top
        self.C_MsgList.WheelUp(wheelTimes=1, waitTime=0.1)
        return isload
    
    def CurrentChat(self):
        '''获取当前聊天对象名'''
        uia.SetGlobalSearchTimeout(1)
        try:
            currentname = self.ChatBox.TextControl(searchDepth=15).Name
            return currentname
        except:
            return None
        finally:
            uia.SetGlobalSearchTimeout(10)

    def GetNewFriends(self):
        """获取新的好友申请列表
        
        Returns:
            list: 新的好友申请列表,元素为NewFriendsElement对象,可直接调用Accept方法

        Example:
            >>> wx = WeChat()
            >>> newfriends = wx.GetNewFriends()
            >>> tags = ['标签1', '标签2']
            >>> for friend in newfriends:
            >>>     remark = f'备注{friend.name}'
            >>>     friend.Accept(remark=remark, tags=tags)  # 接受好友请求,并设置备注和标签
        """
        self._show()
        self.SwitchToContact()
        self.SessionBox.ButtonControl(Name='ContactListItem').Click(simulateMove=False)
        NewFriendsList = [NewFriendsElement(i, self) for i in self.ChatBox.ListControl(Name='新的朋友').GetChildren()]
        AcceptableNewFriendsList = [i for i in NewFriendsList if i.acceptable]
        print(f'获取到 {len(AcceptableNewFriendsList)} 条新的好友申请')
        return AcceptableNewFriendsList
    
    def AddListenChat(self, who, savepic=False):
        """添加监听对象
        
        Args:
            who (str): 要监听的聊天对象名
            savepic (bool, optional): 是否自动保存聊天图片,只针对该聊天对象有效
        """
        exists = uia.WindowControl(searchDepth=1, ClassName='ChatWnd', Name=who).Exists(maxSearchSeconds=0.1)
        if not exists:
            self.ChatWith(who)
            self.SessionBox.ListItemControl(Name=who).DoubleClick(simulateMove=False)
        self.listen[who] = ChatWnd(who, self.language)
        self.listen[who].savepic = savepic

    def GetListenMessage(self):
        """获取监听对象的新消息"""
        msgs = {}
        for who in self.listen:
            chat = self.listen[who]
            chat._show()
            msg = chat.GetNewMessage(savepic=chat.savepic)
            # if [i for i in msg if i[0] != 'Self']:
            if msg:
                msgs[chat] = msg
        return msgs

    def SwitchToContact(self):
        """切换到通讯录页面"""
        self._show()
        self.A_ContactsIcon.Click(simulateMove=False)

    def SwitchToChat(self):
        """切换到聊天页面"""
        self._show()
        self.A_ChatIcon.Click(simulateMove=False)

    def GetGroupMembers(self):
        """获取当前聊天群成员

        Returns:
            list: 当前聊天群成员列表
        """
        ele = self.ChatBox.PaneControl(searchDepth=7, foundIndex=6).ButtonControl(Name='聊天信息')
        try:
            uia.SetGlobalSearchTimeout(1)
            rect = ele.BoundingRectangle
            Click(rect)
        except:
            return 
        finally:
            uia.SetGlobalSearchTimeout(10)
        roominfoWnd = self.UiaAPI.WindowControl(ClassName='SessionChatRoomDetailWnd', searchDepth=1)
        more = roominfoWnd.ButtonControl(Name='查看更多', searchDepth=8)
        try:
            uia.SetGlobalSearchTimeout(1)
            rect = more.BoundingRectangle
            Click(rect)
        except:
            pass
        finally:
            uia.SetGlobalSearchTimeout(10)
        members = [i.Name for i in roominfoWnd.ListControl(Name='聊天成员').GetChildren()]
        while members[-1] in ['添加', '移出']:
            members = members[:-1]
        roominfoWnd.SendKeys('{Esc}')
        return members

def GetAllFriendNicknames(self, keywords=None):
    """获取所有好友昵称列表

    注:
        1. 该方法运行时间取决于好友数量,约每秒6~8个好友的速度
        2. 该方法未经过大量测试,可能存在未知问题,如有问题请微信群内反馈

    Args:
        keywords (str, optional): 搜索关键词,只返回包含关键词的好友昵称列表

    Returns:
        list: 所有好友昵称列表
    """
    self._show()
    self.SwitchToContact()
    self.SessionBox.ListControl(Name="联系人").ButtonControl(Name="通讯录管理").Click(simulateMove=False)
    contactwnd = ContactWnd()
    if keywords:
        contactwnd.Search(keywords)
    friends_nicknames = contactwnd.GetAllFriendNicknames()
    contactwnd.Close()
    self.SwitchToChat()
    return friends_nicknames


代码赏析以及实现原理

  1. 初始化:在类的初始化方法中,首先检查微信是否已经运行,如果没有运行,则尝试启动微信。然后,获取微信的窗口句柄,并设置微信窗口的大小和位置。

  2. 获取会话列表:GetSessionList 方法用于获取当前聊天列表中的所有聊天对象。它会遍历聊天列表,并返回每个聊天对象的名称和新消息数量。

  3. 切换聊天对象:ChatWith 方法用于切换到指定的聊天对象。它会搜索指定的聊天对象,并将其设置为当前聊天对象。如果找不到指定的聊天对象,它会尝试搜索并选取搜索结果中的第一个。

  4. 发送消息:SendMsg 方法用于向当前聊天对象发送文本消息。它会将消息发送到当前聊天对象的编辑框中,并发送回车键以发送消息。

  5. 发送文件:SendFiles 方法用于向当前聊天对象发送文件。它会将文件复制到剪贴板中,并将其粘贴到当前聊天对象的编辑框中,然后发送回车键以发送文件。

  6. 获取聊天记录:GetAllMessage 方法用于获取当前聊天对象的所有聊天记录。它会遍历聊天记录列表,并返回每个聊天记录的信息。

  7. 加载更多聊天记录:LoadMoreMessage 方法用于加载当前聊天对象的更多聊天记录。它会滚动聊天记录列表,并检查是否已经加载了更多的聊天记录。

  8. 获取当前聊天对象名称:CurrentChat 方法用于获取当前聊天对象的名称。

  9. 获取新的好友申请列表:GetNewFriends 方法用于获取新的好友申请列表。它会遍历新的好友申请列表,并返回每个好友申请的信息。

  10. 添加监听对象:AddListenChat 方法用于添加监听对象。它会创建一个新的 ChatWnd 对象,并将其添加到监听对象字典中。

  11. 获取监听对象的新消息:GetListenMessage 方法用于获取监听对象的新消息。它会遍历监听对象字典,并获取每个监听对象的新消息。

  12. 切换到通讯录页面:SwitchToContact 方法用于切换到通讯录页面。切换到聊天页面:SwitchToChat 方法用于切换到聊天页面。

  13. 获取当前聊天群成员:GetGroupMembers 方法用于获取当前聊天群的成员列表。它会遍历聊天群成员列表,并返回每个成员的名称。

  14. 获取所有好友昵称列表:GetAllFriendNicknames 方法用于获取所有好友的昵称列表。它会打开通讯录窗口,并搜索指定的关键词(如果提供了关键词)。然后,它会遍历通讯录列表,并返回每个好友的昵称。最后,它会关闭通讯录窗口,并切换回聊天页面。

标签:return,Name,python,微信,self,who,UI,聊天,._
From: https://blog.csdn.net/2302_81578551/article/details/136821709

相关文章

  • 亲子游戏【华为OD机试JAVA&Python&C++&JS题解】
    题目描述宝宝和妈妈参加亲子游戏,在一个二维矩阵(NN)的格子地图上,宝宝和妈妈抽签决定各自的位置,地图上每个格子有不同的糖果数量,部分格子有障碍物。游戏规则是妈妈必须在最短的时间(每个单位时间只能走一步)到达宝宝的位置,路上的所有糖果都可以拿走,不能走障碍物的格子,只能上下......
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的景区垃圾识别系统(Python+PySide6界面+训练代码)
    摘要:本文介绍了一个先进的基于深度学习的景区垃圾检测系统,该系统集成了最新的YOLOv8算法,并与YOLOv7、YOLOv6、YOLOv5等前代算法进行了性能对比,通过对比实验证明了其在图像、视频、实时视频流和批量文件处理中对景区垃圾进行精确识别和分类的能力。文章深入讲解了YOLOv8算法的工作......
  • 华为OD机试Python - 可以处理的最大任务数
    可以处理的最大任务数前言:本专栏将持续更新互联网大厂机试真题,并进行详细的分析与解答,包含完整的代码实现,希望可以帮助到正在努力的你。关于大厂机试流程、面经、面试指导等,如有任何疑问,欢迎联系我,wechat:steven_moda;email:[email protected];备注:CSDN。题目描述在某个项......
  • 微信小程序学习(第四章总结)
    页面组件4.1组件的定义及属性        组件是页面视图层(WXML)的基本组成单元,组件组合可以构建功能强大的页面结构。小程序框架为开发者提供了容器视图、基础内容、表单、导航、多媒体、地图、画布开放能力等8类(30多个)基础组件。        每一个组件都由一......
  • Python爬虫--1
    Python爬虫小组:255、229、218、219一.安装软件软件名称:PyCharm可以到PyCharm官网下载免费的Community(社区)版本的PyCharm,这个版本虽然不及收费的Professional(专业)版本的PyCharm功能强大,但对于一般应用足够了。(书上抄的)二.匹配数据在根目录上右击,新建一个目录,再在此目录里新建......
  • Python 递归函数实现二分法,带思路解释
            二分法可以大大提升对有序数列的查找,传统的迭代查找会挨个比较数列中的值,如果数列较为庞大会影响查询效率。二分法每次取数列的中间数与待查找数字比较大小,以升序排列为例子 首先要考虑数列长度的奇偶性。        奇数取中间位置的数字,如果比待查找......
  • six,一个神奇的 Python 版本兼容工具库!
    目录前言什么是Pythonsix库?核心功能使用方法 1.安装six库 2.导入six库 3.使用兼容性函数实际应用场景 1.代码库维护 2.项目迁移和重构 3.兼容性包装器总结前言大家好,今天为大家分享一个神奇的Python库-six。Github地址:https://github......
  • toapi,一个强大的 Python Web API库!
    目录前言什么是PythonToapi库?核心功能使用方法 1.安装Toapi库 2.创建Toapi应用 3.定义规则和过滤器 4.运行Toapi应用实际应用场景 1.数据提取与分析 2.自动化爬虫和数据抓取 3.构建自定义搜索引擎高级功能和进阶用法 1.动态页面渲染......
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的血细胞检测与计数系统(Python+PySide6界面+训练代码
    摘要:本文介绍了一种基于深度学习的血细胞检测系统系统的代码,采用最先进的YOLOv8算法并对比YOLOv7、YOLOv6、YOLOv5等算法的结果,能够准确识别图像、视频、实时视频流以及批量文件中的血细胞。文章详细解释了YOLOv8算法的原理,并提供了相应的Python实现代码、训练数据集,以及基于PySid......
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的犬种识别系统(附完整代码资源+UI界面+PyTorch代码)
    摘要:本文介绍了一种基于深度学习的犬种识别系统系统的代码,采用最先进的YOLOv8算法并对比YOLOv7、YOLOv6、YOLOv5等算法的结果,能够准确识别图像、视频、实时视频流以及批量文件中的犬种。文章详细解释了YOLOv8算法的原理,并提供了相应的Python实现代码、训练数据集,以及基于PySide6的......