A-A+

python 实现微信好友发送消息

2019年03月15日 23:50 汪洋大海 暂无评论 阅读 440 views 次

在Python语言中,有一个微信接口模块itchat,可以用来实现微信的一些功能,本主题专门使用itchat来实现一些应用:

  1. 掌握iChat的API结构;
  2. 应用iChat的API实现用户需求;

前提:安装iChat模块

pip install itchat

安装过程截图:

Python3.6版本下,itchat模块安装过程


一、itchat的API结构

使用dir函数可以获取itchat中的API信息;
代码:

import  itchat
  print(dir(itchat))

上述代码在python交互编程模式下,与ipython中都可以使用。
获取的API信息如下(从ipython中拷贝的):

['Core', 'VERSION', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'add_friend', 'add_member_into_chatroom', 'auto_login', 'check_login', 'components', 'config', 'configured_reply', 'content', 'core', 'create_chatroom', 'delete_member_from_chatroom', 'dump_login_status', 'get_QR', 'get_QRuuid', 'get_chatrooms', 'get_contact', 'get_friends', 'get_head_img', 'get_mps', 'get_msg', 'instanceList', 'load_login_status', 'log', 'login', 'logout', 'msg_register', 'new_instance', 'originInstance', 'returnvalues', 'revoke', 'run', 'search_chatrooms', 'search_friends', 'search_mps', 'send', 'send_file', 'send_image', 'send_msg', 'send_raw_msg', 'send_video', 'set_alias', 'set_chatroom_name', 'set_logging', 'set_pinned', 'show_mobile_login', 'start_receiving', 'storage', 'update_chatroom', 'update_friend', 'upload_file', 'utils', 'web_init']

根据字面意思,大致也知道上述函数的作用,具体的使用可以使用help函数获取。代码如下:

help(itchat.login)

或者

help('itchat.login')

获取的帮助结果如下:

Help on method login in module itchat.components.login:

login(enableCmdQR=False, picDir=None, qrCallback=None, loginCallback=None, exitCallback=None) method of itchat.core.Core instance

帮助输出截图


二、itchat的使用

1. 登录/登出

(1)登录函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
               enableCmdQR=False, picDir=None, qrCallback=None,
               loginCallback=None, exitCallback=None):
    ''' log in like web wechat does   像web wechat一样登录
        for log in
            - a QR code will be downloaded and opened
            - then scanning status is logged, it paused for you confirm
            - finally it logged in and show your nickName
将下载并打开QR码(二维码) - 然后记录扫描状态,它会暂停以供您确认 - 最后它登录并显示你的nickName
        for options
            - hotReload: enable hot reload  启用热重载。 通过此命令登陆,即使程序关闭,一定时间内重新开启也可以不用重新扫码。
            - statusStorageDir: dir for storing log in status  用于存储登录状态的目录
            - enableCmdQR: show qrcode in command line
                - integers can be used to fit strange char length 在命令行中显示二维码,值为整数,可用于拟合奇怪的char长度,用方块模拟二维码
            - picDir: place for storing qrcode  储存二维码的地址
            - loginCallback: callback after successfully logged in   成功登录后回调如果未设置,则清除屏幕并删除qrcode
                - if not set, screen is cleared and qrcode is deleted
            - exitCallback: callback after logged out
                - it contains calling of logout  注销后回调包含调用注销
            - qrCallback: method that should accept uuid, status, qrcode   生成登陆二维码后调用这个函数,应接受uuid,status,qrcode的方法
        for usage
            ..code::python
 
                import itchat
                itchat.auto_login()
 
        it is defined in components/register.py
        and of course every single move in login can be called outside
            - you may scan source code to see how
            - and modified according to your own demond
    '''
    raise NotImplementedError()

使用代码

#coding=utf-8
import  itchat
itchat.login()

login函数执行过程中会产生一个二维码图片,more存放在login运行的当前工作目录,并且使用工具打开。

login登录运行过程

在用户使用手机扫描登录前,login处于阻塞状态;等扫描登录完成,会提示登录成功。登录成功后的输出:

登录成功后的输出截图

通过设置qrCallback与loginCallback可以控制登录过程,比如使用定制二维码显示,以及登录成功后的一些定制处理。qrCallback回调在长时间没有登录的情况,会被反复调用。
同时还可以使用命令行显示二维码,命令行模式下qrCallback参数设置后无效,在命令行(或者控制台)显示二维码注意:enableCmdQR参数可以设置为True或者False,也可以是整数,整数也是True,但可以指定二维码显示的宽度,某些平台下控制台一个字符占用2个字符,可以设置为2,这样二维码显示才会正常,否则显示不是太正常。
代码:

#命令行模式
itchat.login(enableCmdQR=2,loginCallback=login_cb)

效果:

命令行二维码

可以将enableCmdQR赋值为负值改变命令行二维码的背景与前景色。

还有一个auto_login函数也可以实现自动登录,该函数的声明如下:

auto_login(hotReload=False, statusStorageDir='itchat.pkl', enableCmdQR=False, picDir=None, qrCallback=None, loginCallback=None, exitCallback=None)

第一个参数是掉线后,短时间内登录,不扫描二维码。

(2)登出函数

1
2
3
4
5
6
7
8
def logout(self):
    ''' logout
        if core is now alive
            logout will tell wechat backstage to logout
        and core gets ready for another login
        it is defined in components/login.py
    '''
    raise NotImplementedError()

(3)登录状态检测

def check_login(self, uuid=None):
    ''' check login status
        for options:
            - uuid: if uuid is not set, latest uuid you fetched will be used
        for return values:
            - a string will be returned
            - for meaning of return values
                - 200: log in successfully  成功登录
                - 201: waiting for press confirm  未确认,等待确认
                - 408: uuid timed out  超时
                - 0  : unknown error  未知错误
        for processing:
            - syncUrl and fileUrl is set
            - BaseRequest is set
        blocks until reaches any of above status
        it is defined in components/login.py
    '''
    raise NotImplementedError()

如果uuid参数为None,默认是最后一次登录的uuid。

2. 信息获取

与操作文件系统一样,登录后,就是微信信息获取,主要是好友信息,群信息,公众号信息等。
好友、群聊、公众号信息提供常见的操作函数:

#函数类型说明1 get_XXX 获取2 update_XXX 更新3 search_XXX 搜索4 add_XXX 添加5 delete_XXX 删除6 set_XXX 修改

下面我们仅仅列出get_XXXX相关的函数声明。
(1)get_contact获取群聊信息
get_contact与get_chatrooms作用一样。

def get_contact(self, update=False):
    ''' fetch part of contact
        for part
            - all the massive platforms and friends are fetched
            - if update, only starred chatrooms are fetched
        for options
            - update: if not set, local value will be returned
        for results
            - chatroomList will be returned
        it is defined in components/contact.py
    '''

(2)get_friends获取好友

def get_friends(self, update=False):
    ''' fetch friends list
        for options
            - update: if not set, local value will be returned
        for results
            - a list of friends' info dicts will be returned
        it is defined in components/contact.py
    '''
    raise NotImplementedError()

(3)get_chatrooms获取群聊

def get_chatrooms(self, update=False, contactOnly=False):
    ''' fetch chatrooms list
        for options
            - update: if not set, local value will be returned
            - contactOnly: if set, only starred chatrooms will be returned
        for results
            - a list of chatrooms' info dicts will be returned
        it is defined in components/contact.py
    '''
    raise NotImplementedError()

(4)get_mps获取公众号

def get_mps(self, update=False):
    ''' fetch massive platforms list
        for options
            - update: if not set, local value will be returned
        for results
            - a list of platforms' info dicts will be returned
        it is defined in components/contact.py
    '''
    raise NotImplementedError()

(5)获取好友,群聊、公众号的例子

#coding=utf-8
import  itchat
from  itchat.storage.templates import ContactList
itchat.auto_login()
print(itchat.get_contact())
print(itchat.get_chatrooms())
print(itchat.get_friends())
print(itchat.get_mps())

print(type(itchat.get_contact()))
print(type(itchat.get_chatrooms()))
print(type(itchat.get_friends()))
print(type(itchat.get_mps()))

获取的好友、群聊、公众号信息如下:

获取的信息输出

获取的信息返回的都是列表,列表的类型如下:

<class 'itchat.storage.templates.ContactList'>
<class 'itchat.storage.templates.ContactList'>
<class 'itchat.storage.templates.ContactList'>
<class 'itchat.storage.templates.ContactList'>

(6)ContactList类型定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class ContactList(list):
    ''' when a dict is append, init function will be called to format that dict '''
    def __init__(self, *args, **kwargs):
        super(ContactList, self).__init__(*args, **kwargs)
        self.__setstate__(None)
    @property
    def core(self):
        return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
    @core.setter
    def core(self, value):
        self._core = ref(value)
    def set_default_value(self, initFunction=None, contactClass=None):
        if hasattr(initFunction, '__call__'):
            self.contactInitFn = initFunction
        if hasattr(contactClass, '__call__'):
            self.contactClass = contactClass
    def append(self, value):
        contact = self.contactClass(value)
        contact.core = self.core
        if self.contactInitFn is not None:
            contact = self.contactInitFn(self, contact) or contact
        super(ContactList, self).append(contact)
    def __deepcopy__(self, memo):
        r = self.__class__([copy.deepcopy(v) for v in self])
        r.contactInitFn = self.contactInitFn
        r.contactClass = self.contactClass
        r.core = self.core
        return r
    def __getstate__(self):
        return 1
    def __setstate__(self, state):
        self.contactInitFn = None
        self.contactClass = User
    def __str__(self):
        return '[%s]' % ', '.join([repr(v) for v in self])
    def __repr__(self):
        return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
            self.__str__())

ContactList继承是是内置列表类型list。

3. 好友、群聊、公众号信息处理

(1)好友、群聊、公众号信息结构定义
实际上上面代码返回的列表中元素类型是不同的,下面可以使用代码输出:

#coding=utf-8
import  itchat
from  itchat.storage.templates import ContactList
itchat.auto_login()
list_contact=itchat.get_contact()
list_chatrooms=itchat.get_chatrooms()
list_friends=itchat.get_friends()
list_mps=itchat.get_mps()

print(type( list_contact[0]))
print(type( list_chatrooms[0]))
print(type( list_friends[0]))
print(type( list_mps[0]))

列表中类型分别是:

<class 'itchat.storage.templates.Chatroom'>
<class 'itchat.storage.templates.Chatroom'>
<class 'itchat.storage.templates.User'>
<class 'itchat.storage.templates.MassivePlatform'>

(2)Chatroom信息结构
Chatroom最上层父类是dict类型,继承结构:

class Chatroom(AbstractUserDict)
class AbstractUserDict(AttributeDict)
class AttributeDict(dict)

根据字典的特点,信息的索引主要靠key,获取其key如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import  itchat
 
from itchat.storage.templates import  Chatroom
from itchat.storage.templates import User
from itchat.storage.templates import MassivePlatform
 
 
itchat.auto_login()
list_contact=itchat.get_contact()
list_chatrooms=itchat.get_chatrooms()
list_friends=itchat.get_friends()
list_mps=itchat.get_mps()
 
print(list_contact[0].keys())
print(list_chatrooms[0].keys())
print(list_friends[0].keys())
print(list_mps[0].keys())

字典keys如下:

dict_keys(['MemberList', 'Uin', 'UserName', 'NickName', 'HeadImgUrl', 'ContactFlag', 'MemberCount', 'RemarkName', 'HideInputBarFlag', 'Sex', 'Signature', 'VerifyFlag', 'OwnerUin', 'PYInitial', 'PYQuanPin', 'RemarkPYInitial', 'RemarkPYQuanPin', 'StarFriend', 'AppAccountFlag', 'Statues', 'AttrStatus', 'Province', 'City', 'Alias', 'SnsFlag', 'UniFriend', 'DisplayName', 'ChatRoomId', 'KeyWord', 'EncryChatRoomId', 'IsOwner', 'IsAdmin', 'Self'])

(3)User信息结构
User与Chatroom基本上一样。

class User(AbstractUserDict)
class AbstractUserDict(AttributeDict)
class AttributeDict(dict)

User是字典key如下:

dict_keys(['MemberList', 'UserName', 'City', 'DisplayName', 'PYQuanPin', 'RemarkPYInitial', 'Province', 'KeyWord', 'RemarkName', 'PYInitial', 'EncryChatRoomId', 'Alias', 'Signature', 'NickName', 'RemarkPYQuanPin', 'HeadImgUrl', 'UniFriend', 'Sex', 'AppAccountFlag', 'VerifyFlag', 'ChatRoomId', 'HideInputBarFlag', 'AttrStatus', 'SnsFlag', 'MemberCount', 'OwnerUin', 'ContactFlag', 'Uin', 'StarFriend', 'Statues', 'WebWxPluginSwitch', 'HeadImgFlag'])

(4)MassivePlatform信息结构
MassivePlatform与Chatroom基本上一样。

class MassivePlatform(AbstractUserDict)
class AbstractUserDict(AttributeDict)
class AttributeDict(dict)

MassivePlatform是字典key如下:

dict_keys(['MemberList', 'Uin', 'UserName', 'NickName', 'HeadImgUrl', 'ContactFlag', 'MemberCount', 'RemarkName', 'HideInputBarFlag', 'Sex', 'Signature', 'VerifyFlag', 'OwnerUin', 'PYInitial', 'PYQuanPin', 'RemarkPYInitial', 'RemarkPYQuanPin', 'StarFriend', 'AppAccountFlag', 'Statues', 'AttrStatus', 'Province', 'City', 'Alias', 'SnsFlag', 'UniFriend', 'DisplayName', 'ChatRoomId', 'KeyWord', 'EncryChatRoomId', 'IsOwner'])

下面是用户信息的获取:

1
2
3
4
5
6
7
8
9
#coding=utf-8
import  itchat
 
itchat.auto_login()
list_friends=itchat.get_friends()
 
one_user=list_friends[0]
for key in one_user:
    print(key,":",one_user[key])

下面是获取的的部分用户信息:

微信用户本人信息

4. 用户信息接收

接收消息采用的是类似事件处理的注册方式,一单某个函数注册以后(注册时函数需要与某个消息类型关联),当接收到相应类型的消息,该函数就调用。
(1)消息注册的方式
消息的注册,使用的是python的装饰器技术,装饰器的定义如下:


def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=False):

参数说明:

msgType: 指定该方法用于处理的消息类型
isFriendChar: 处理好友消息
isGroupChat: 处理群消息
isMpChat: 处理公众号消息

(2)消息的类型
其中msgType的值支持如下集中:

消息类型类型说明TEXT 文本PICTURE 图片FRIENDS 好友CARD 名片MAP 位置SHARING 共享RECORDING 语音=VOICEATTACHMENT 附件VIDEO 视频VIOCE 音频= RECORDINGNOTE 消息撤回SYSTEM 系统

上述消息类型的定义如下:

TEXT       = 'Text'
MAP        = 'Map'
CARD       = 'Card'
NOTE       = 'Note'
SHARING    = 'Sharing'
PICTURE    = 'Picture'
RECORDING  = VOICE = 'Recording'
ATTACHMENT = 'Attachment'
VIDEO      = 'Video'
FRIENDS    = 'Friends'
SYSTEM     = 'System'

提示:在itchat的安装库文件content.py中定义。使用的时候,需要import itchat.content,省事的import方式:

from itchat.content import *

下面是一段接收所有类型的信息的代码:

#coding=utf-8
import  itchat
from itchat.content import *

@itchat.msg_register(msgType=INCOME_MSG,isFriendChat=True,isGroupChat=True,isMpChat=True)
def recv_msg(msg):
    print(msg);
#登录
itchat.auto_login()
#运行
itchat.run(debug=True)
#退出登录
itchat.logout()

获得消息显示如下:

获取没有经过分析的聊天信息

5. 用户信息类型与处理

通过注册消息处理函数,实现异步回调的方式来接收聊天信息,传递过来的消息类型是:

class 'itchat.storage.messagequeue.Message'

Message类与上面User本质也是一个字典类型,继承结构如下:

Message-> AttributeDict->dict

class Message(AttributeDict):
class AttributeDict(dict):

不同类型的信息,其字典keys是不同的,就是内容有差别:

dict_keys(['MsgId', 'FromUserName', 'ToUserName', 'MsgType', 'Content', 'Status', 'ImgStatus', 'CreateTime', 'VoiceLength', 'PlayLength', 'FileName', 'FileSize', 'MediaId', 'Url', 'AppMsgType', 'StatusNotifyCode', 'StatusNotifyUserName', 'RecommendInfo', 'ForwardFlag', 'AppInfo', 'HasProductId', 'Ticket', 'ImgHeight', 'ImgWidth', 'SubMsgType', 'NewMsgId', 'OriContent', 'EncryFileName', 'User', 'Type', 'Text', 'SystemInfo'])
dict_keys(['Type', 'Text', 'SystemInfo', 'FromUserName', 'ToUserName', 'User'])

下面是一个专门接收好友文本信息的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#coding=utf-8
import  itchat
from itchat.content import *
 
@itchat.msg_register(msgType=INCOME_MSG,isFriendChat=True,isGroupChat=False,isMpChat=False)
def recv_msg(msg):
    print(msg['Type'])
    if msg['Type'] == TEXT :
        print(msg['Text'])
 
#登录
itchat.auto_login()
#运行
itchat.run(debug=True)
#退出登录
itchat.logout()

接收到信息如下:

简单的用户聊天信息接收,可以根据需要做更加复杂的处理

6. 用户信息发送

发送用户消息,有两种方式:
(1)原生消息发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def send_raw_msg(self, msgType, content, toUserName):
    ''' many messages are sent in a common way
        for demo
            .. code:: python
 
                @itchat.msg_register(itchat.content.CARD)
                def reply(msg):
                    itchat.send_raw_msg(msg['MsgType'], msg['Content'], msg['FromUserName'])
 
        there are some little tricks here, you may discover them yourself
        but remember they are tricks
        it is defined in components/messages.py
    '''
    raise NotImplementedError()
 
 
def send(self, msg, toUserName=None, mediaId=None):
    ''' wrapped function for all the sending functions
        for options
            - msg: message starts with different string indicates different type
                - list of type string: ['@fil@', '@img@', '@msg@', '@vid@']
                - they are for file, image, plain text, video
                - if none of them matches, it will be sent like plain text
            - toUserName: 'UserName' key of friend dict
            - mediaId: if set, uploading will not be repeated
        it is defined in components/messages.py
    '''
    raise NotImplementedError()

(2)快捷发送函数

#发送文本
  def send_msg(self, msg='Test Message', toUserName=None)
#发送文件
  def send_file(self, fileDir, toUserName=None, mediaId=None)
#发送图像
  def send_image(self, fileDir, toUserName=None, mediaId=None)
#发送视频
  def send_video(self, fileDir=None, toUserName=None, mediaId=None):

下面简单的展示一个发动短信的例子(其他视频,语音基本上类似)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#coding=utf-8
import  itchat
import  time
 
#登录
itchat.auto_login()
 
#根据昵称找用户
user=itchat.search_friends(nickName='赵德柱')[0]
 
#每隔5秒给用户发一个短信
for i in range(10):
    itchat.send_msg(msg="辣鸡短信,不必理会!",toUserName=user['UserName'])
    time.sleep(5)
 
#退出登录
itchat.logout()

上面代码可以改成个人好友信息测试。

文章来源:https://zhuanlan.zhihu.com/p/55454720

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

给我留言