V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
NxnXgpuPSfsIT
V2EX  ›  Python

手把手教你利用个人微信号 API(微信控制器、群发助手、好友删除检测)

  NxnXgpuPSfsIT ·
littlecodersh · 2016-10-15 00:29:54 +08:00 · 33161 次点击
这是一个创建于 2956 天前的主题,其中的信息可能已经有所发展或是发生改变。

现在的日常生活已经离不开微信,本文将会抛砖引玉演示如何使用 Python 调用微信 API 做一些有意思的东西。

看完这一系列教程,你就能从头开始实现自己关于微信的想法。

本文为教程的第二部分,主要以微信控制器、群发助手、好友删除检测为例演示如何调用微信 API 。

Python 基础并不困难,所以即使没有这方面基础辅助搜索引擎也完全可以学习本教程。

关于本教程有任何建议或者疑问,都欢迎邮件与我联系( [email protected] ),或者在github上提出。

当然最近我们新建了一个 itchat 使用的交流群,欢迎加入: 549762872 。

教程流程简介

这一系列教程从如何分析微信协议开始,第一部分教你如何从零开始获取并模拟扩展个人微信号所需要的协议。

第二部分将会就这些协议进行利用,以各项目为例介绍一些微信有意思功能的实现。

第三部分就协议的一些高级用法进行介绍,对框架做进一步介绍与扩展。

本文为教程的第二部分。

简单成果展示

完成了本文的学习,你将会完成三个小项目:(出于方便二次阅读,括号中都放上了源码链接)

  • 通过微信操作的音乐播放器(源码
  • 消息内容与对象可自定义的消息群发助手(源码
  • 特定好友删除检测(源码

使用微信协议完成机器人较为平常,如果对具体细节感兴趣,可以添加个人号littlecodersh并回复“源代码”。

本文主要基于微信 API 的第三方包 itchat ,你可以在项目主页获取更多信息。

本部分所需环境

本文是这一教程的第二部分,需要基本的 pip 可用的 Python 环境。

本教程使用的环境如下:

  • Windows 8.1 (其他平台也可用)
  • Python 2 or 3
  • 微信版本 6.3.25

微信控制器

pic0 pic1

在项目主页上,专门有人就微信作为智能家居入口向我提出了很多想法。

如果微信可以作为控制器,就可以不必自制手机端客户端的麻烦。

其实这个需求实现起来非常简单,这里我借鉴了 yaphone 的RasWxMusicbox,使用了其中部分的代码作为演示。

这是一个通过微信控制电脑播放音乐的小项目,那么主要就是三个功能:

  • 输入“帮助”,显示帮助
  • 输入“关闭”,关闭音乐播放
  • 输入具体歌名,进入歌曲的选择

换成代码就是这样一个逻辑:

if msg == u'关闭':
    close_music()
    print(u'音乐已关闭')
if msg == u'帮助':
    print(u'帮助信息')
else:
    print(interact_select_song(msg))

那么现在需要解决的就是如何关闭音乐,如何选择音乐和如何使用微信交互。

关闭音乐我们这里使用打开空文件的方式,而选择音乐我们使用网易云音乐的 API 完成:

import os
# 通过该命令安装该 API : pip install NetEaseMusicApi
from NetEaseMusicApi import interact_select_song

with open('stop.mp3', 'w') as f: pass
def close_music():
    os.startfile('stop.mp3')

而微信的调用可以通过 itchat 包简单的完成,这里要注意的是:

  • 有些账号无法与自己通信,所以我们选择与文件传输助手( filehelper )通信
  • 为了防止对于其他消息的响应,我们在第一行过滤了无关信息
  • itchat.run 的选项分别为允许热拔插,方便调试
# 接上段程序
# 通过该命令安装该 API : pip install itchat
import itchat

@itchat.msg_register(itchat.content.TEXT)
def music_player(msg):
    if msg['ToUserName'] != 'filehelper': return
    if msg['Text'] == u'关闭':
        close_music()
        itchat.send(u'音乐已关闭', 'filehelper')
    if msg['Text'] == u'帮助':
        itchat.send(u'帮助信息', 'filehelper')
    else:
        itchat.send(interact_select_song(msg['Text']), 'filehelper')

itchat.auto_login(True)
itchat.send(HELP_MSG, 'filehelper') 
itchat.run()

itchat 对常用功能都做好了封装,调用还是非常容易的。

完整的程序我放在了gist上面,使用时不要忘记安装第三方包。

通过与文件传输助手的交互,微信就能够轻松变成其他程序的入口。

群发助手

在短信的时代,逢年过节都会需要接收和发送大量的短信。

虽然自己也看到短信就烦,但不发又怕会错过什么。

所以当时就产生了各式各样的群发工具,最简单的比如在消息中加入昵称,让人感觉不像群发。

不过可惜的是,微信自带的群发助手真的只是群发。

当然,稍加操作,一切皆有可能。

例如在消息中加入昵称:

  • 通过get_friends方法可以轻松获取所有的好友(好友首位是自己)
  • 基于不同的好友可以发送不同的消息
  • 这条程序运行后是真的会发消息出去,如果只是演示目的,把itchat.send改为print即可
#coding=utf8
import itchat, time

itchat.auto_login(True)

SINCERE_WISH = u'祝%s 新年快乐!'

friendList = itchat.get_friends(update=True)[1:]
for friend in friendList:
    # 如果是演示目的,把下面的方法改为 print 即可
    itchat.send(SINCERE_WISH % (friend['DisplayName']
        or friend['NickName']), friend['UserName'])
    time.sleep(.5)

又例如给特定的人发送特定的消息。

我们这里通过群聊实现,划定一个群聊,在群聊内则私信发送祝福。

  • 如果仅是创建群聊不说话,对方是不会有提示的
  • 群聊如果不保存到通讯录,是无法在各设备之间同步的(所以 itchat 也无法读取到)
  • 群聊在被获取的时候不会自带用户列表,所以需要使用update_chatroom更新用户列表
  • 当然,如果只是演示目的,把itchat.send改为print即可
#coding=utf8
import itchat, time

itchat.auto_login(True)

REAL_SINCERE_WISH = u'祝%s 新年快乐!!'

chatroomName='wishgroup'
itchat.get_chatrooms(update=True)
chatrooms = itchat.search_chatrooms(name=chatroomName)
if chatrooms is None:
    print(u'没有找到群聊:' + chatroomName)
else:
    chatroom = itchat.update_chatroom(chatrooms[0]['UserName'])
    for friend in chatroom['MemberList']:
        friend = itchat.search_friends(userName=friend['UserName'])
        # 如果是演示目的,把下面的方法改为 print 即可
        itchat.send(REAL_SINCERE_WISH % (friend['DisplayName']
            or friend['NickName']), friend['UserName'])
        time.sleep(.5)

所以我的通讯录里会有从来不用的客户群、教师群什么的。

完整的程序我放在了gist上面,使用时不要忘记安装第三方包。

当然,为了防止误操作,完整程序中我把所有的itchat.send换成了print

另外,不只有文字可以发送,文件、图片也都是可行的,具体操作见 itchat 的文档了。

itchat 获取微信可以获取到的各种内容也都非常方便。

其余的例如生日,节日什么的就看具体需求了。

好友删除检测

pic

有时候我们会想知道某个好友有没有删除自己或者把自己拉入黑名单。

这一操作使用 itchat 也会变的非常简单。

原理的话,在于将好友拉入群聊时,非好友和黑名单好友不会被拉入群聊。

所以群聊的返回值中就有了好友与你关系的数据。

另外,群聊在第一次产生普通消息时才会被除创建者以外的人发现的(系统消息不算普通消息)。

这样,就可以隐蔽的完成好友检测。

写成代码的话,这个操作就是这样的:(只是演示,不能运行,运行版本在段末)

chatroomUserName = '@1234567'
friend = itchat.get_friends()[1]

r = itchat.add_member_into_chatroom(chatroomUserName, [friend])
if r['BaseResponse']['ErrMsg'] == '':
    status = r['MemberList'][0]['MemberStatus']
    itchat.delete_member_from_chatroom(chatroom['UserName'], [friend])
    return { 3: u'该好友已经将你加入黑名单。',
        4: u'该好友已经将你删除。', }.get(status,
        u'该好友仍旧与你是好友关系。')

其中,通过add_member_into_chatroom操作获取我们需要的返回值,即可得到好友的状态。

同样的,这次我们也将文件传输助手作为终端,具体方法与控制器一节类似。

这次我们确定的交互方式是接收“名片”消息,并判断名片中的好友与自己的关系。

那么获取名片信息的内容可以这么写:

import itchat

@itchat.msg_register(itchat.content.CARD)
def get_friend(msg):
    if msg['ToUserName'] != 'filehelper': return
    friendStatus = get_friend_status(msg['RecommendInfo'])
    itchat.send(friendStatus['NickName'], 'filehelper')

itchat.auto_login(True)
itchat.run()

那么我们所需要的所有部分就都解决了,下面将他们组合起来即可。

完整的程序我放在了gist上面,使用时不要忘记安装第三方包。

在网页版微信的接口受到限制之前完全可以批量进行这一操作,检测哪些好友删除了自己。

但目前显然操作存在频率限制,所以只能做一些变通了。

之后的内容

到这里这一篇文章的主要内容就结束了。

主要从微信作为终端使用、自定义的消息交互、微信协议研究三方面开了一个简单的头。

其余有一些过于大众,如机器人,就不再赘述。

而另一些,需要一定的基础或者不适合分享,就留给各位自行研究。

如果要留个悬念,可以想象添加好友的方法 status 传 2 ,轻松实现好友病毒式扩张。

利用微信的 API 可以做很多事情,文档我放在这里,祝好运!

结束语

希望读完这篇文章能对你有帮助,有什么不足之处万望指正(鞠躬)。

有什么想法或者想要关注我的更新,欢迎来GithubStar或者Fork

161015

LittleCoder

EOF

39 条回复    2017-10-03 10:35:00 +08:00
AZLisme
    1
AZLisme  
   2016-10-15 08:39:42 +08:00
send 方法只有 toUserName?
假如想给群聊发送消息怎么做呢?谢谢
AZLisme
    2
AZLisme  
   2016-10-15 08:44:34 +08:00 via iPhone
研究出来了, ChatRoom 也有个特殊的 UserName
NxnXgpuPSfsIT
    3
NxnXgpuPSfsIT  
OP
   2016-10-15 10:05:19 +08:00 via Android
对的,我这里还处理了群聊消息发送消息人的对应 UserName ,在 ActualUserName 键里面。
likai
    4
likai  
   2016-10-15 10:42:34 +08:00
ltchat?关注这个好久了.
@AZLisme 群也有一个动态的 userName.前面是两个 @@
NxnXgpuPSfsIT
    5
NxnXgpuPSfsIT  
OP
   2016-10-15 11:39:25 +08:00
@likai 哈哈,好的
102400
    6
102400  
   2016-10-15 16:48:12 +08:00
这接口不太稳定,经常莫名其妙掉线
NxnXgpuPSfsIT
    7
NxnXgpuPSfsIT  
OP
   2016-10-15 16:53:09 +08:00 via Android
@102400
很多用户专门测试过稳定性这个问题。
另,演示号自从上次版本更新重启以后已经稳定在线三个月了。
网络不稳定不要怪接口哦。
102400
    8
102400  
   2016-10-15 16:58:59 +08:00
@NxnXgpuPSfsIT 难道是我服务器的问题?我看 log 都是接受某个消息时报错然后退出
NxnXgpuPSfsIT
    9
NxnXgpuPSfsIT  
OP
   2016-10-15 17:02:59 +08:00 via Android
@102400 你可以把报错信息贴一下
102400
    10
102400  
   2016-10-15 17:03:57 +08:00
@NxnXgpuPSfsIT 另外,我用的是 QCloud ,我看一休里面很多人都是掉线
102400
    11
102400  
   2016-10-15 17:05:02 +08:00
@NxnXgpuPSfsIT 上个月的事了,试了后感觉不能长期做 Robot 后我就删了
NxnXgpuPSfsIT
    12
NxnXgpuPSfsIT  
OP
   2016-10-15 17:12:48 +08:00 via Android
@102400 就从你的描述来看,是接收某个消息时报错。
就这个特征,比较可能的情况是你的调用出错抛出了异常。
我向你保证这个接口的稳定,如果你还有需求欢迎再次你尝试。
另,尝试的过程中碰到问题希望还是报 issue ,否则很可能产生不必要的误解。
102400
    13
102400  
   2016-10-15 17:15:22 +08:00
@NxnXgpuPSfsIT 我今晚试试用 py3 ,有问题再去加群报告?
NxnXgpuPSfsIT
    14
NxnXgpuPSfsIT  
OP
   2016-10-15 17:15:41 +08:00 via Android   ❤️ 1
@102400 你看到的那个 issue 应该就是我开的专门处理这个问题的 issue ,你看一下最新进展,这个问题已经解决了。
NxnXgpuPSfsIT
    15
NxnXgpuPSfsIT  
OP
   2016-10-15 17:16:10 +08:00 via Android
@102400 好,随时欢迎!
nellace
    16
nellace  
   2016-10-15 17:36:53 +08:00
以前 star 这个项目 https://github.com/0x5e/wechat-deleted-friends
据说现在已经没办法看好友是否删除了
NxnXgpuPSfsIT
    17
NxnXgpuPSfsIT  
OP
   2016-10-15 20:06:20 +08:00
@nellace 可以的,但是接口限制变得很严格,没法大批量的检测了。
pasturn
    18
pasturn  
   2016-10-15 20:47:42 +08:00 via iPhone
只想知道有没有能够实现自动定时转发某公众号的文章功能
zhangneww
    19
zhangneww  
   2016-10-16 00:41:24 +08:00
我只想知道能够坚持在线多久
NxnXgpuPSfsIT
    20
NxnXgpuPSfsIT  
OP
   2016-10-16 07:24:00 +08:00 via Android
@pastum 目前还不行
@zhangneww 没有特殊情况可以一直在线下去
coolloves
    21
coolloves  
   2016-10-16 08:36:59 +08:00 via Android
mark,感觉分享
Echoldman
    22
Echoldman  
   2016-10-16 08:52:29 +08:00
教程会在 github 上更新吗
NxnXgpuPSfsIT
    23
NxnXgpuPSfsIT  
OP
   2016-10-16 09:40:21 +08:00 via Android
@Echoldman 会在文档那里更新的
regent
    24
regent  
   2016-10-16 09:53:07 +08:00 via iPhone
谢谢,研究一下看
klausgao
    25
klausgao  
   2016-10-16 14:32:59 +08:00 via iPhone
楼主,我是在那条研究稳定在线的 issue 里的其中一位,现在也有半个月没掉线了😄
blueset
    26
blueset  
   2016-10-16 18:08:24 +08:00
感谢楼主分享。忽然发现大概六七个月前 Fork 走魔改的那个微信 API 就是楼主的作品。当时还自己翻译了 Python 3 的版本,加了一些 Feature (终端二维码之类的)。
这次才发现半年来更新了不少,是时候重新 Pull 来更新了。
blueset
    27
blueset  
   2016-10-16 18:15:55 +08:00
顺便问一下,微信网页 API 有提供那种重启后不会变的用户唯一 ID 吗?每次重启完之后用户的 UserName 都是不一样的。
NxnXgpuPSfsIT
    28
NxnXgpuPSfsIT  
OP
   2016-10-16 18:53:01 +08:00
@klausgao 哈哈,好的,能解决这个问题都要感谢你们的支持!
NxnXgpuPSfsIT
    29
NxnXgpuPSfsIT  
OP
   2016-10-16 18:56:25 +08:00
@blueset 魔改的功能和我后来加的差的不多呀,如果 pr 了多好呢!
目前好友的话可以通过 set_alias 设置昵称变相达到这个目的。
相对来说公众号的话这个功能就原生支持,我最近在写一个类似的项目 itchatmp ,可能能更方便的满足这个需求,这个项目可以在我的主页上找到。
blueset
    30
blueset  
   2016-10-16 21:15:49 +08:00
@NxnXgpuPSfsIT 本来是想改完善些之后一起 PR 的,结果中间开始申请大学就耽误了。后来连同那个 Tunnel Bot 一起搁置在了那边,一直没有时间继续做。
NxnXgpuPSfsIT
    31
NxnXgpuPSfsIT  
OP
   2016-10-16 22:20:02 +08:00   ❤️ 1
@blueset 好,之后有时间欢迎继续魔改了 pr
kangsgo
    32
kangsgo  
   2016-10-17 00:01:26 +08:00
收藏了,非常感谢分享,虽然还没有看的特别明白,可能是新手的原因,改天认真阅读
xxstop
    33
xxstop  
   2016-10-17 12:33:27 +08:00
mark 正准备使用
oliver134
    34
oliver134  
   2016-10-17 17:46:07 +08:00
main.py 发送我自己的 gif 图,发送失败。 jpg 可以发送成功。请问下是为什么呢?
GreatMartial
    35
GreatMartial  
   2016-10-18 00:19:40 +08:00 via Android
能写个微信内的语音助手吗?
我看着别人博客分享的代码,写了个语音输入,调用图灵机器人文字输出的项目,后边想改进一下,把返回的文字利用百度的语音合成 API 返回给微信,可是我自己写不出来,大大有兴趣做这个项目吗?
NxnXgpuPSfsIT
    36
NxnXgpuPSfsIT  
OP
   2016-10-18 10:49:49 +08:00
@oliver134 你可以开个 issue 把代码贴一下
NxnXgpuPSfsIT
    37
NxnXgpuPSfsIT  
OP
   2016-10-18 10:50:52 +08:00   ❤️ 1
@GreatMartial 你想要写的话可以邮件或者加 q 群联系我,我给你一些指导
GreatMartial
    38
GreatMartial  
   2016-10-18 12:17:39 +08:00
@NxnXgpuPSfsIT 谢谢大大回复,我加 qq 群咨询你 O(∩_∩)O
baiyuexingchen
    39
baiyuexingchen  
   2017-10-03 10:35:00 +08:00
现在有新的版本删除好友的代码吗
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2907 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 28ms · UTC 15:02 · PVG 23:02 · LAX 07:02 · JFK 10:02
Developed with CodeLauncher
♥ Do have faith in what you're doing.