In [1]:
#我的Python版本是:
import sys  
print(sys.version)
print(sys.version_info)


2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118]
sys.version_info(major=2, minor=7, micro=13, releaselevel='final', serial=0)

=======注意=======

这里我用Python2.7,实际上代码在Python3.6,3.5运行一切正常。itchat更新后就没有再测试啦。

注意微信更新了反广告机制,注意不要一次性发太多东西,避免被微信封号。

=======注意=======

核心

  • itchat读取微信好友列表和头像
  • 用pillow拼接头像画图

登录微信网页版,itchat.auto_login()会生成QR码,使用手机扫一扫即可登录。

提示Please scan the QR code to log in.时,用手机扫描弹出的二维码

命令行二维码技巧:

  1. 通过以下命令可以在登陆的时候使用命令行显示二维码:itchat.auto_login(enableCmdQR=True)
  2. 若背景色为浅色(白色),可以将enableCmdQR赋值为负值:itchat.auto_login(enableCmdQR=-1)

In [2]:
import itchat
itchat.auto_login()


Getting uuid of QR code.
Downloading QR code.
Please scan the QR code to log in.
Please press confirm on your phone.
Loading the contact, this may take a little while.
Login successfully as 小尧

使用friends储存好友列表,update=True可以确保好友列表是最新的。注意好友列表第0个是自己


In [3]:
friends = itchat.get_friends(update=True)[0:]

friends好友列表第0个是自己,我们可以看一下。顺带说一下,好友列表的顺序 (貌似) 是按照好友添加顺序


In [4]:
friends[0]


Out[4]:
<User: {'UserName': u'@bcc23ca9f9dc5f417d7e6b1234a266b3', 'City': u'\u53a6\u95e8', 'DisplayName': '', 'UniFriend': 0, 'OwnerUin': 0, 'MemberList': <ContactList: []>, 'PYQuanPin': u'xiaoyao', 'RemarkPYInitial': u'', 'Uin': 31873955, 'AppAccountFlag': 0, 'VerifyFlag': 0, 'Province': u'\u798f\u5efa', 'KeyWord': u'Lai', 'RemarkName': u'', 'PYInitial': u'XY', 'ChatRoomId': 0, u'IsOwner': 0, 'HideInputBarFlag': 0, u'HeadImgFlag': 1, 'EncryChatRoomId': '', 'AttrStatus': 4318311, 'SnsFlag': 177, 'MemberCount': 0, u'WebWxPluginSwitch': 3, 'Alias': '', 'Signature': u'\u68a6\u60f3\u8981\u6709\uff0c\u8d76\u8def\u8981\u7d27\u3002\u5927\u7ea6\u534a\u5e74\u53d1\u4e00\u6b21\u670b\u53cb\u5708\u3002', 'ContactFlag': 7, 'NickName': u'\u5c0f\u5c27', 'RemarkPYQuanPin': u'', 'HeadImgUrl': u'/cgi-bin/mmwebwx-bin/webwxgeticon?seq=621078783&username=@bcc23ca9f9dc5f417d7e6b1234a266b3&skey=@crypt_a6fa4b82_b0d6710e5b4d50da49d2b6c28f0153d4', 'Sex': 1, 'StarFriend': 0, 'Statues': 0}>

创建一个目录,用来保存所有好友头像。注意使用os.chdir(user)切换个到工作目录,方便后续保存图片。


In [5]:
import os
user = friends[0]["PYQuanPin"][0:]
print(user)
os.mkdir(user)
os.chdir(user)
os.getcwd()


xiaoyao
Out[5]:
'/home/yao/\xe6\x96\x87\xe6\xa1\xa3/PythonApplication1/jupyter_notebook/xiaoyao'

批量下载好友头像,储存到friends[i]['img']中。然后我们print(friends[0]看看有没有变化(正常情况下应该可以看到增加了img,以二进制方式储存头像)。因为我家网络经常链接失败,所以用try...except...来写这一段。

"UserName"这个字段开头总有个@符号,直接暴力去除。如果不喜欢的话,可以把"UserName"换成"PYQuanPin",不过不保证重名。

同时把头像保存在user目录地下,方便下一步使用。

python使用open经常报错:TypeError: an integer is required的解决方案

错误是由于从os模块引入了所有的函数导致的,os模块下有一个open函数,接受整型的文件描述符和打开模式,from os import *引入os模块的open函数,覆盖了python内建的open函数,导致错误。删除from os import *这行,然后再根据需要,指定引入os模块下的函数


In [6]:
for i in friends:
    try:
        i['img'] = itchat.get_head_img(userName=i["UserName"])
        i['ImgName']=i["UserName"][1:] + ".jpg"
    except ConnectionError:
        print('get '+i["UserName"][1:]+' fail')
    fileImage=open(i['ImgName'],'wb')
    fileImage.write(i['img'])
    fileImage.close()
#这里不建议看friends[0],太长了

看看我有多少个好友(friends里面有多少条记录),看看下载了多少头像(os.listdir(os.getcwd())看目录底下有多少文件)


In [7]:
friendsSum=len(friends)
imgList=os.listdir(os.getcwd())
numImages=len(imgList)
print('I have ',friendsSum,'friend(s), and I got ',numImages,'image(s)')


('I have ', 1873, 'friend(s), and I got ', 1872, 'image(s)')

单个图像边长eachsize=64像素,一行eachline=int(sqrt(numImages))+1个头像,最终图像边长eachSize*eachline


In [8]:
import math
eachSize=64
eachLine=int(math.sqrt(numImages))+1
print("单个图像边长",eachSize,"像素,一行",eachLine,"个头像,最终图像边长",eachSize*eachLine)


('\xe5\x8d\x95\xe4\xb8\xaa\xe5\x9b\xbe\xe5\x83\x8f\xe8\xbe\xb9\xe9\x95\xbf', 64, '\xe5\x83\x8f\xe7\xb4\xa0\xef\xbc\x8c\xe4\xb8\x80\xe8\xa1\x8c', 44, '\xe4\xb8\xaa\xe5\xa4\xb4\xe5\x83\x8f\xef\xbc\x8c\xe6\x9c\x80\xe7\xbb\x88\xe5\x9b\xbe\xe5\x83\x8f\xe8\xbe\xb9\xe9\x95\xbf', 2816)

import图像处理Python图像处理库:PIL中Image

  1. 新建一块画布
  2. 在坐标(0,0)位置放上第一个人头像
  3. 向右平移坐标

In [9]:
import PIL.Image as Image
toImage = Image.new('RGBA', (eachSize*eachLine,eachSize*eachLine))#新建一块画布
x = 0
y = 0
for i in imgList:
    try:
        img = Image.open(i)#打开图片
    except IOError:
        print("Error: 没有找到文件或读取文件失败",i)
    else:
        img = img.resize((eachSize, eachSize), Image.ANTIALIAS)#缩小图片
        toImage.paste(img, (x * eachSize, y * eachSize))#拼接图片
        x += 1
    if x == eachLine:
        x = 0
        y += 1
print("图像拼接完成")


('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', '31d9b5166d2287bf4c39401689d632fe29c6df9318364542e0324e8579651ac2.jpg')
('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', '2c6620196046ec98aeafbd6ad9188195f1fc6aa5376e3a5dc3933220ffbff56f.jpg')
('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', 'b24f5cff7c6ef31a4d56bc4aac6724b37bd697905b65dfe3e3cc578105befa03.jpg')
('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', '47481e9f379d0bfa5ad9b111d316f70fd9d64f8bf11f90949ce02aeb177bb13b.jpg')
('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', '3b5a4f9b62eee2d97998013ddb8d708089818754edf811553d53947f242ae6cc.jpg')
('Error: \xe6\xb2\xa1\xe6\x9c\x89\xe6\x89\xbe\xe5\x88\xb0\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe8\xaf\xbb\xe5\x8f\x96\xe6\x96\x87\xe4\xbb\xb6\xe5\xa4\xb1\xe8\xb4\xa5', '9b3368415032299de77d6d8c7f4220c6cb1008185da2607c8a54d310898756d0.jpg')
图像拼接完成

看一下拼接好的图像是什么样的(注意文件过大是常有的现象,请先去掉注释) 回到上一级目录(没人想在一堆文件里面找拼图吧?) 然后保存文件,顺带发送给文件传输助手


In [14]:
toImage.show()

os.chdir(os.path.pardir)
os.getcwd()

toImage.save(friends[0]["PYQuanPin"][0:]+".jpg")
itchat.send_image(friends[0]["PYQuanPin"][0:]+".jpg", 'filehelper')


Out[14]:
'/home/yao/\xe6\x96\x87\xe6\xa1\xa3/PythonApplication1'

至此,大功告成,别忘记退出网页版微信


In [15]:
itchat.logout()


LOG OUT!
Out[15]:
<ItchatReturnValue: {'BaseResponse': {'Ret': 0, 'ErrMsg': u'\u8bf7\u6c42\u6210\u529f', 'RawMsg': 'logout successfully.'}}>