Python自动采集微信联系人_ 批量改备注_发消息

import pywinauto
from pywinauto.application import Application
from pywinauto.keyboard import *
import os
import sys
import time

from win32con import WM_INPUTLANGCHANGEREQUEST
import win32gui
import win32api

from ctypes.wintypes import tagPOINT
import pywinauto


class Tools(object):
    @staticmethod
    def set_english_inputer():
        # 0x0409为英文输入法的lid_hex的 中文一般为0x0804
        hwnd = win32gui.GetForegroundWindow()
        # title = win32gui.GetWindowText(hwnd)
        # im_list = win32api.GetKeyboardLayoutList()
        # print(im_list)
        # im_list = list(map(hex, im_list))
        # print(im_list)
        result = win32api.SendMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, 0, 0x8040804)
        if result == 0:
            print("英文输入法切换成功!")

    @staticmethod
    def readtxt(filename, s_str = ",", isprint = False):
        wxlist = []
        with open(filename,"r", encoding="utf-8") as f:
            while True:
                line = f.readline()
                if line == "": break
                wxline = line.split(s_str)    # , \t
                wxlist.append(wxline)
                if isprint:
                    print(wxline)
            print("\n")
        return wxlist

    @staticmethod
    def saveTxt(filename, data):
        with open(filename, 'a', encoding="utf-8") as f:
            f.write(data)
        print(sys._getframe().f_lineno, filename,":",data)


class WxObject(object):
    ok = 1
    err = 0
    exit = 2
    def __init__(self):
        self.win = ""
        self.page = {u'呢称': '', u'备   注': '', u'地   区': '', u'微信号': '', u'来   源': ''}

    # 连接 微信
    def _connect_wx(self):
        # 连接微信
        try:
            self.app = Application(backend='uia').connect(path="C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
            if not self.app.微信.is_normal():
                self.app.微信.restore()
        except:
            self.app = Application(backend='uia').start(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
            time.sleep(2)
            self.app.微信.登录.click_input(button="left")
            self.app.微信.wait("visible")
        self.app.微信.通讯录.wait('visible',timeout=300)
        self.win = self.app[u'微信']
        self.win.draw_outline()
    # 单击 通讯录 按钮
    def _click_address(self):  # 点击通讯录
        # 找到通讯录点击--> 在点击右边联系人
        self.addresslist = self.app[u"微信"][u"通讯录"]
        self.addresslist.click_input(button='left')
        self.coords = self.addresslist.rectangle()

    # 搜索框 输入联系人
    def _wx_search(self, search_str):
       #搜索,输入昵称
        try:             #微信电脑客户端升级,可能会变
            search_edit = self.win.child_window(title=u"搜索", control_type="Edit")
        except:
            print(sys._getframe().f_lineno, "搜索框的标识没有找到!")
            sys.exit()
        search_edit.click_input(button="left")
        Tools.set_english_inputer()
        search_edit.type_keys(search_str)
        time.sleep(1)
    # 得到 搜索结果
    def _search_ret_items(self):
        found_list = []  # 定义找到的联系人列表
        try:
            con_list = self.win.child_window(title=u"搜索结果", control_type="List")  # 联系人
        except:
            print(sys._getframe().f_lineno, "搜索结果的标识没有找到!")
            sys.exit()
        time.sleep(1)

        item_list = con_list.children()  # 搜索结果的所有item项
        item_num = len(item_list)
        print(sys._getframe().f_lineno, "打印搜索结果:",item_num, "行", item_list)
        if item_list[0].friendly_class_name()!= "Pane":
            print(sys._getframe().f_lineno, "搜索结果:第一行不是标签项,返回空值")
            return []
        for i in range(1, item_num):  # 第二项开始 项类属性为"ListItem",则是匹配到的联系人
            if item_list[i].friendly_class_name() == "ListItem":
                if item_list[i].window_text()[0:3] == "搜一搜":
                    return found_list
                found_list.append(item_list[i])
                print(item_list[i].window_text())
            else:
                break
        print(sys._getframe().f_lineno, "找到几个?:", len(found_list), found_list, "\n")
        return found_list
    def _search_ret_items_wait(self,filename = "search_ret.txt", wait_time=10):
        found_list = []  # 定义找到的联系人列表
        try:
            con_list = self.win.child_window(title=u"搜索结果", control_type="List")  # 联系人
        except:
            print(sys._getframe().f_lineno, "搜索结果的标识没有找到!")
            sys.exit()
        time.sleep(wait_time)

        item_list = con_list.children()  # 搜索结果的所有item项
        item_num = len(item_list)
        print(sys._getframe().f_lineno, "打印搜索结果:",item_num, "行", item_list)
        if item_list[0].friendly_class_name()!= "Pane":
            print(sys._getframe().f_lineno, "搜索结果:第一行不是标签项,返回空值")
            return []
        for i in range(1, item_num):  # 第二项开始 项类属性为"ListItem",则是匹配到的联系人
            if item_list[i].friendly_class_name() == "ListItem":
                if item_list[i].window_text()[0:3] == "搜一搜":
                    return found_list
                found_list.append(item_list[i])
                print(item_list[i].window_text())
                Tools.saveTxt(filename, item_list[i].window_text()+"\n")
            else:
                break
        print(sys._getframe().f_lineno, "找到几个?:", len(found_list),  "\n")

    def _next(self, num=1):   # 下一个联系人
        win = self.win
        self._click_address()            # 单击通讯录
        titel_str = self.page['备   注']
        if titel_str == "点击添加备注" or self.page['备   注'] == "":
            titel_str = self.page['呢称']
        lxr = self.win.child_window(title=u"%s" % titel_str, control_type="ListItem")
        # 点击上次联系人
        lxr.click_input(button='left')
        while num:
            send_keys("{VK_DOWN}")
            # self.lxr.type_keys("{DOWN}")
            num -= 1
    # 循环往下 发消息
    def next_send(self, sendinfo):        # 发送消息
        # 连接微信
        self._connect_wx()
        # 点击 联系人
        pywinauto.mouse.click(button="left", coords=(self.coords.left + 150, self.coords.top + 20))
        while True:     # 循环读取资料、发送消息
            if self. _by_address_get_wxinfo():
                # 点击-发消息
                self.app.微信.发消息.click_input(button='left')
                # 发送消息内容
                self._send_info_edit(sendinfo)
                self._next()
            else:
                self._next(2)  # 发送消息,此条取消注释

    def _write_address_txt(self, filename, header=False):   # 把通讯录写入文件
        page = self.page
        with open(filename, 'a', encoding='utf-8') as f:
            if header:
                f.write(u'微信号,备注,地区,来源,呢称\r')
            else:
                f.write(
                    '%s,%s,%s,%s,%s\r' % (page[u'微信号'], page[u'备   注'], page[u'地   区'], page[u'来   源'], page[u'呢称']))
    def _by_address_get_wxinfo(self):            # 读联系人资料
        win = self.win
        self.page[u'呢称'] = ""
        self.page[u'备   注'] = ""
        self.page[u'地   区'] = ""
        self.page[u'来   源'] = ""
        try:
            static_wxh = win.child_window(title=u"微信号", control_type="Text")  # 获取 静态微信号控件
            if static_wxh.window_text() != "微信号":
                return WxObject.err
            Pane = static_wxh.parent().parent()  # 获取详情
            for item in Pane.children():
                item.draw_outline()
                lines = item.children()
                key = lines[0].window_text()
                value = lines[1].window_text()
                if key == "微信号" and value ==self.page[key]:
                    return WxObject.exit
                self.page[key] = value
        except:
            time.sleep(3)
            return WxObject.err

        nick_edit = win.Edit2  # 获取呢称控件
        nick_name = nick_edit.get_value()
        self.page['呢称'] = nick_name
        print(self.page)
        return WxObject.ok
    # 读的文件,最后一列是修改列
    def _click_lxr_item(self, filename, exefunc, okfile="ret_ok.txt", errfile="ret_err.txt"):
        # 连接微信
        self._connect_wx()
        # 读需要修改的文件
        wxlist = Tools.readtxt(filename, isprint=True)
        # 循环读取资料、发送消息
        for wxline in wxlist:
            self.cols = len(wxline)
            # 1.打印 更新内容
            print(sys._getframe().f_lineno, self.cols, wxline)
            ret_detile = ""
            # 2. 循环搜索  微信号,备注, 呢称
            for i in range(0, self.cols - 1):
                print(sys._getframe().f_lineno, i, "搜索:", wxline[i])
                try:
                    # 2.1 搜索
                    if wxline[i] == "":
                        continue
                    self._wx_search(wxline[i])
                    print(sys._getframe().f_lineno, "搜索结束,往下得到搜索结果!")
                    # 2.2 返回搜索结果项
                    items = self._search_ret_items()
                    # 2.3 结果项为1
                    if len(items) == 1:
                        # 2.3.1 单击 选中的联系人项
                        items[0].click_input(button="left")
                        # 2.3.2 修改 备注内容
                        # print(sys._getframe().f_lineno, exefunc)
                        eval(exefunc)  # 微信号,修改内容
                        break  # 跳出循环,继续下一条。
                    # 2.4 结果项不为1
                    else:
                        self.app.微信.清空.click_input(button="left")
                        ret_detile = ret_detile + wxline[i] + " 匹配到:" + str(len(items)) + "个\n"
                except:
                    Tools.saveTxt(errfile, "搜索时,出错异常!!!****************\n")
                    Tools.saveTxt(errfile, ",".join(wxline)+ "\n")
                    if not self.app.微信.is_active():
                        break
                    self.app.微信.通讯录.click_input(button="left")
            # 3.循环结束,结果项都不为1
            else:
                print(sys._getframe().f_lineno, wxline, ":搜索:没找到,或匹配到多个项:", ret_detile)
                Tools.saveTxt(errfile, ret_detile)
    # 读的文件,最后一列不是修改列
    def _click_lxr_item2(self, filename, exefunc, okfile="ret_ok.txt", errfile="ret_err.txt"):
        # 连接微信
        self._connect_wx()
        # 读需要修改的文件
        wxlist = Tools.readtxt(filename, isprint=True)
        # 循环读取资料、发送消息
        for wxline in wxlist:
            self.cols = len(wxline)
            # 1.打印 更新内容
            print(sys._getframe().f_lineno, self.cols, wxline)
            ret_detile = ""
            # 2. 循环搜索  微信号,备注, 呢称
            for i in range(0, self.cols):
                print(sys._getframe().f_lineno, i, "搜索:", wxline[i])
                try:
                    # 2.1 搜索
                    if wxline[i] == "":
                        continue
                    self._wx_search(wxline[i])
                    print(sys._getframe().f_lineno, "搜索结束,往下得到搜索结果!")
                    # 2.2 返回搜索结果项
                    items = self._search_ret_items()
                    # 2.3 结果项为1
                    if len(items) == 1:
                        # 2.3.1 单击 选中的联系人项
                        items[0].click_input(button="left")
                        # 2.3.2 修改 备注内容
                        try:
                            eval(exefunc)  # 微信号,修改内容
                        except:
                            print(sys._getframe().f_lineno, exefunc, "\neval(exefunc)调用错误!")
                        break  # 跳出循环,继续下一条。
                    # 2.4 结果项不为1
                    else:
                        self.app.微信.清空.click_input(button="left")
                        ret_detile = ret_detile + wxline[i] + " 匹配到:" + str(len(items)) + "个\n"
                except:
                    print(sys._getframe().f_lineno,  "搜索时,出错异常!!!****************\n")
                    Tools.saveTxt(errfile, "搜索时,出错异常!!!****************\n")
                    Tools.saveTxt(errfile, ",".join(wxline)+ "\n")
                    if not self.app.微信.is_active():
                        break
                    self.app.微信.通讯录.click_input(button="left")
            # 3.循环结束,结果项都不为1
            else:
                print(sys._getframe().f_lineno, wxline, ":搜索:没找到,或匹配到多个项:", ret_detile)
                Tools.saveTxt(errfile, ret_detile)
    def _memo_chang_verify_wxh(self, wxh, editstr, wxline, okfile, errfile):  # 修改备注
        # 聊天信息
        self.app.微信.聊天信息.click_input(button="left")

        # 添加按钮
        addbtn = self.win.child_window(title=u"添加", control_type="Button")
        addbtn.parent().parent().parent()[1].click_input(button="left")

        # 微信号:
        get_wxh = self.win.Edit2.get_value()
        # 修改备注内容
        static_wxh = self.win.child_window(title=u'备   注', control_type="Text")
        Pane46 = static_wxh.parent().parent()
        for item in Pane46.children():
            # item.draw_outline()
            lines = item.children()
            key = lines[0].window_text()
            # value = lines[1].window_text()
            if key == u'备   注' and wxh == get_wxh:
                lines[1].click_input(button="left")
                lines[1].type_keys("^A" + editstr)
                # send_keys("{VK_ENTER}")
                Tools.saveTxt(okfile, ",".join(wxline))
                break
        else:
            Tools.saveTxt(errfile, "1.详情页未出现,2.异常退出,3.匹配的结果错误——————————\n")
            Tools.saveTxt(errfile, ",".join(wxline)+"\n")
            ret = False
        send_keys("{VK_ESCAPE}")
        send_keys("{VK_ESCAPE}")
        time.sleep(1)
    def _memo_chang_verify_no(self, editstr, wxline, okfile, errfile):  # 修改备注
        # 聊天信息
        self.app.微信.聊天信息.click_input(button="left")

        # 添加按钮
        addbtn = self.win.child_window(title=u"添加", control_type="Button")
        addbtn.parent().parent().parent()[1].click_input(button="left")

        # 修改备注内容
        static_wxh = self.win.child_window(title=u'备   注', control_type="Text")
        Pane46 = static_wxh.parent().parent()
        for item in Pane46.children():
            lines = item.children()
            key = lines[0].window_text()
            if key == u'备   注':
                lines[1].click_input(button="left")
                lines[1].type_keys("^A" + editstr)
                Tools.saveTxt(okfile, ",".join(wxline))
                break
        else:
            Tools.saveTxt(errfile, ",".join(wxline)+"\n")
        # 回退二页
        send_keys("{VK_ESCAPE}")
        send_keys("{VK_ESCAPE}")
        time.sleep(1)
    def _send_info_edit(self, infolist):  # 发送消息
        try:
            # 内容编辑框
            send_edit = self.win.child_window(title=u"输入", control_type="Edit")
            send_edit.click_input(button='left')
            # 发送内容
            send_edit.type_keys("^A")
            for info in infolist:
                send_edit.type_keys(info+"+{ENTER}")
            # 点击发送按钮
            send_btn = self.win.child_window(title=u"发送(S)", control_type="Button")
            send_btn.click_input(button='left')
        except:
            print(sys._getframe().f_lineno, "_send_info_edit() 出错了")

    # 1、保存通讯录
    def save_address(self, filename):  # 保存通讯录
        #1、连接微信
        self._connect_wx()
        #2、点击 通讯录
        self._click_address()

        pywinauto.mouse.click(button="left", coords=(self.coords.left + 150, self.coords.top + 30))

        #3、写保存通讯录的标题
        self._write_address_txt(filename, header=True)
        #4、循环读取资料、写进通讯录文本
        while True:
            #4.1 读wx信息
            ret = self._by_address_get_wxinfo()
            #4.2 ok,写文件
            if ret == WxObject.ok:
                self._write_address_txt(filename)
            # 4.3 exit,到末尾退出
            elif ret == WxObject.exit:
                break
            if self.app.微信.is_active():
                # self.con_list.type_keys("{DOWN}")
                send_keys("{VK_DOWN}")  # 继续下一条
            else:
                print(sys._getframe().f_lineno, "微信窗口失去焦点!!!")
                break

    # 2、搜索成功后,更新备注内容
    def update_memo_verify(self, filename, okfile="ret_ok.txt", errfile="ret_err.txt"):
        exefunc = "self._memo_chang_verify_wxh((wxline[0], wxline[self.cols-1], wxline, okfile, errfile)"
        wx._click_lxr_item(filename, exefunc, okfile, errfile)

    def update_memo(self, filename, okfile="ret_ok.txt", errfile="ret_err.txt"):
        exefunc = "self._memo_chang_verify_no(wxline[self.cols-1], wxline, okfile, errfile)"
        wx._click_lxr_item(filename, exefunc, okfile, errfile)

    # 3、搜索成功后,发消息
    def send_message(self, filename, infolist, okfile="ret_ok.txt", errfile="ret_err.txt"):
        exefunc = "self._send_info_edit(infolist)"
        # exefunc = "self._send_info_edit('"+infolist+"')"
        wx._click_lxr_item2(filename, exefunc, okfile, errfile)

    # 4、模糊查询,返回结果
    def fuzzy_query_rets(self,search_txt = "TG"):
        self._connect_wx()
        self._wx_search(search_txt)
        self._search_ret_items_wait()

    def test(self):
        # 1、连接微信
        self._connect_wx()
        # 2、点击 通讯录
        self._click_address()
        self._wx_search("TG-")
        time.sleep(5)
        ret = self._search_ret_items()
        print(ret)


if __name__ == '__main__':
    wx = WxObject()
    # Tools.set_english_inputer()

    # 1、保存通讯录 [微信号,备注,地区,呢称]
    # wx.save_address("address_0908.txt")                    # 保存通讯录

    # 通过通讯录,自动往下发消息
    # wx.next_send("打扰了,此条消息为测试,勿需回复,谢谢!")

    #2、给特定联系人发送消息 ,内容为列表。
    infolist = ["打扰了,", "此条消息为测试", "勿需回复,谢谢!"]
    wx.send_message("hyh210908.txt",infolist) # 给联系人发送消息

    # 3、更新备注 [微信号 备注 呢称 修改的备注内容]
    # wx.update_memo_verify("hyh210907.txt", "ret_ok.txt", "ret_err.txt")
    # 3.1 更新备注,不校验
    # wx.update_memo("hyh210907.txt", "ret_ok.txt", "ret_err.txt")

    # 4、模糊查询,返回结果
    # wx.fuzzy_query_rets(search_txt = "TG.")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容