小试牛刀,使用影刀完成个人微信PC版的通讯录采集功能,较官方的获取微信好友列表应用靠谱得多
评论
收藏

小试牛刀,使用影刀完成个人微信PC版的通讯录采集功能,较官方的获取微信好友列表应用靠谱得多

经验分享
E
Excel催化剂
2024-06-04 16:52·浏览量:4598
E
Excel催化剂
影刀见习开发者
发布于 2024-06-02 22:31更新于 2024-06-04 16:524598浏览

一开始学习影刀时,我就对获取微信好友功能感兴趣,搜索了一下应用市场,果然有,名字叫:获取微信好友列表

但很坑的是,这个应用,并不能使用,试过运行,采集到几十个好友就失效了,微信PC客户端检测到异常, 强制退出了。

经过一段时间的影刀学习后,获得了高级开发者证书,也重新自己拿这个题目来练习下。

因官方限制个人版帐号分享后查看源代码,方便大家学习,索性全程使用编码版完成所有的代码。


影刀做出来的性能还是有瓶颈,我重新使用.NET写了一版独立程序的,性能非常强悍,有兴趣的可以下载使用。

下载地址:https://easyshu.lanzoue.com/b0hc1wdpg 密码:8888


做了个应用市场,欢迎关注学习: https://www.winrobot360.com/share/accede?inviteKey=566edc0b-1fb3-4682-9a62-5da3695374dd

同样欢迎一同关注我的公众号:Excel催化剂,更多干货给大家送上。

此处关键内容送上,全版源代码

关键技术为:在编码版里,调用可视版的接口xbot_visual.win32.element.get_element,实现在循环过程中,列表与父成员交叉得到唯一元素。

同时,使用了python的一些外部库如pandas做去重数据处理。skimage.metrics库作图片相似度分析,因朋友权限那里,只能采集到图片,采集图片是元素截图,会因为滚动条原因,截图后的结果不是太唯一,可能同样一种权限截图去重后有好几种状态。

吐槽下,性能是个瓶颈,使用xbot_visual.win32.element.get_element循环得到每一行的单元格元素这块,比较慢,下周我会给大家一个参照物,用.NET做一版,感受下性能的差异有多大,欢迎围观。

有了通讯录好友清单,下一步,做一些批量修改备注、标签、朋友权限等操作,就是很刚需的功能,对微信好友较多的营销人员,相信这些功能对他们管理好微信好友带来极大的便利。

# 使用提醒:
# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能
# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能
# 3. 当此模块作为流程独立运行时执行main函数
# 4. 可视化流程中可以通过"调用模块"的指令使用此模块

import xbot
import xbot_visual
from xbot import print, sleep
from .import package
from .package import variables as glv
from PIL import Image

import numpy as np
import pandas as pd
from skimage.metrics import structural_similarity as ssim

import tempfile
import os
import random
import xbot_extensions.activity_excel_v2 as excelExt

def main(args):

    try:

        wd_manage_contacts = None  # 初始化 wd 变量
        try:
            wd_manage_contacts= xbot.win32.get(title="通讯录管理",timeout=1)
            wd_manage_contacts.close()
        except:
            pass

        wd_weixin=xbot.win32.get(title="微信")
        btn_contacts= wd_weixin.find("元素_按钮_通讯录",timeout=3)
        btn_contacts.click()

        btn_new_fans= wd_weixin.find("元素-新的朋友",timeout=3)
        btn_new_fans.click()

        btn_manage_contacts=wd_weixin.find("元素_按钮_通讯录管理",timeout=3)
        btn_manage_contacts.click()

        wd_manage_contacts=xbot.win32.get(title="通讯录管理")
        wd_manage_contacts.move(x=0,y=0)
        screen_size=xbot.win32.get_screen_size()
        wd_manage_contacts.resize(width=screen_size[0]-300,height=screen_size[1]-100) #怕影刀运行遮挡

        # 鼠标移动到中间,用于滚动条使用
        ele_contact_list=wd_manage_contacts.find("元素-通信录列表面板")
        point_x=int( ele_contact_list.get_bounding()[0]+ele_contact_list.get_bounding()[2]/2)
        point_y=int(ele_contact_list.get_bounding()[1]+ele_contact_list.get_bounding()[3]/2) 
        xbot.win32.mouse_move(point_x,point_y)

        temp_dir = tempfile.gettempdir()
        file_name="tmp.png"
        image_path = os.path.join(temp_dir, file_name)

        data=[]
        first_nick_name=""
        iloop=0
        while True:
            iloop+=1
            elements_nick_name=wd_manage_contacts.find_all("元素-昵称列表")
            # if (elements_nick_name[0].get_text()==first_nick_name or iloop==3):
            if (elements_nick_name[0].get_text()==first_nick_name):
                print(f"采集到最后一轮循环,首个昵称为:{first_nick_name},跳出死循环") 
                break
            first_nick_name = elements_nick_name[0].get_text()   
            elements_row=wd_manage_contacts.find_all("元素-行列表")    
            wd_manage_contacts.activate()

            for ele_row in elements_row:
                try:
                    xbot.logging.debug(f"获取昵称列表元素")  
                    ele_nick_name = xbot_visual.win32.element.get_element(window="0", selector=package.selector("元素-昵称列表"), timeout="3", is_related_parent=True, parent=ele_row)
                    xbot.logging.debug(f"获取备注名列表元素")  
                    ele_comments = xbot_visual.win32.element.get_element(window="0", selector=package.selector("元素-备注名列表"), timeout="3", is_related_parent=True, parent=ele_row)
                    xbot.logging.debug(f"获取标签列表元素")  
                    ele_nick_labels = xbot_visual.win32.element.get_element(window="0", selector=package.selector("元素-标签列表"), timeout="3", is_related_parent=True, parent=ele_row)
                    xbot.logging.debug(f"获取朋友权限元素")   
                    ele_nick_pemission = xbot_visual.win32.element.get_element(window="0", selector=package.selector("元素-朋友权限"), timeout="3", is_related_parent=True, parent=ele_row)
                    ele_nick_pemission.screenshot(temp_dir,filename=file_name)
                    # ele_nick_pemission.screenshot(temp_dir)

                    image = Image.open(image_path)
                    # 将图片转换为灰度图像
                    gray_image = image.convert('L')
                    gray_array = np.array(gray_image)
                    new_row = [ele_nick_name.get_text(),ele_comments.get_text(),ele_nick_labels.get_text(),image,gray_array]

                    data.append(new_row)
                except Exception as e:
                    xbot.logging.debug(f"循环获取行元素报错,报错文本为:{e}")   

            print(f"第{iloop}次采集已完成")    
            xbot_visual.dialog.show_notifycation(operation_kind="show", level="info", placement="rightBottom", message=f"第{iloop}次采集已完成", timeout="1")
            scroll_times = random.randint( 5,7)
            xbot.win32.mouse_wheel(wheel_times=scroll_times)
            sleep(1)

        df = pd.DataFrame(data, columns=['nickName', 'nickComment', 'labels','img','imgArray'])
        # 根据第一、二、三列进行去重
        df_unique = df.drop_duplicates(subset=['nickName', 'nickComment', 'labels'])

        # 存储唯一图标及其标识
        unique_icons = []
        unique_imgs = []
        icon_names = []

        icon_images = df['imgArray']
        original_images = df['img']

        # 对每个图标进行去重处理
        for icon, original_img in zip(icon_images, original_images):
            is_unique = True
            for idx, unique_icon in enumerate(unique_icons):
                if ssim(icon, unique_icon) > 0.99:  # 使用 SSIM 进行图像相似性比较
                    is_unique = False
                    icon_names.append(f"图标{idx + 1}")
                    break
            if is_unique:
                unique_icons.append(icon)
                unique_imgs.append(original_img)
                icon_names.append(f"图标{len(unique_icons)}")

        # 将标识添加到 DataFrame 中
        df['icon_labels'] = icon_names
        # 使用 zip 函数将两个列表逐对组合
        # list_icon_info = list(zip( icon_names,unique_imgs))

        # 提取特定列并转换为二维列表
        selected_columns = ['nickName', 'nickComment', 'labels','icon_labels']
        list_data = df[selected_columns].values.tolist()

        xlsx_path = os.path.join(os.environ['USERPROFILE'], 'Desktop','微信通读录.xlsx')
        
        package.resources.copy_to("微信通讯录.xlsx",xlsx_path)
        wkb=xbot.excel.open(xlsx_path)
        # excel_instance = xbot_visual.excel.get_active_workbook()

        unique_img_names = [f"图标{i+1}" for i in range(len(unique_imgs))]           
        sht1=wkb.get_sheet_by_name("朋友图标映射")
        wkb.active_sheet_by_name("朋友图标映射")
        sht1.set_column("A",unique_img_names,2)
        sht1.set_column("B",unique_img_names,2)
        
        for index, unique_img in enumerate(unique_imgs):
            row_num = index + 2  # 动态计算行号
            unique_img.save(image_path)
            excelExt.process18(wkb, image_path, row_num, "C", 37, 15, 0, 2, None, False)


        sht2=wkb.get_sheet_by_name("微信通讯录")
        wkb.active_sheet_by_name("微信通讯录")
        sht2.set_range(2,"A",list_data)
        excelExt.fill_down_formula(wkb,"=VLOOKUP(D2,朋友图标映射!A:B,2)","E",2,-1,"微信通讯录",None)
        
    except Exception as e:
        xbot.logging.error(f"报错,错误为:{e}")
    


收藏2
全部评论1
最新
发布评论
评论