博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用Python了解微信通信机制,实现查询有多少好友删除你!!
阅读量:6818 次
发布时间:2019-06-26

本文共 15101 字,大约阅读时间需要 50 分钟。

此篇文章参考微信通信机制,收益匪浅!:

QQ交流群127591054

当然也可以写发送消息的代码,机制和上述文章介绍的一样,大家可以参考学习!

偶遇:偶尔在论坛发现有外国友人在开源社区发布的Python微信删除好友查看,但是这个作者的代码我这边运行出现了点问题,就是各种问题,我在作者基础上进行研究修改!最终在Python2.7成功运行,之后又用了两天时间把运行环境转移到Python3.5。几乎完美执行!但是有一个问题我真的无能为力!在当我输出第三组好友名单的时候,就报错了!

报错如下:没办法我就去掉输出好友,就正常了,完整代码在下面,几乎每一句做了详细的注释!

#UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 138-138: Non-BMP character not supported in Tk

原理:简单点就是把好友分组拉入群组,不超过40,别人是看不到的,拉不进俩就代表你被删了!!

但是问题来了,我最近发现腾讯web端操作容易被受限制,我拉了一组或者两组就被限制,说操作频繁了!!所以大家可以拿来学习微信通讯机制!!,不可以用来做坏事哦!虽然可以得到这个用户所有的信息!

完整代码如下:祝大家学习进步!详细注释代码中有写。^~^,就不一句一句讲了。

1、运行代码,会跳出二维码,扫描在手机确认登陆,然后关闭图片,程序自动运行!!
这里写图片描述
2、按操作一步一步执行就可以了~~,具体实现看注释其实不难。

# coding=utf-8  #Python 3.5#Author Jack Chiangimport os  import urllib import re  import http.cookiejar  import time  import xml.dom.minidom  import json  import sysimport mathimport matplotlib.pyplot as plt  import matplotlib.cbook as cbookimport matplotlibfrom matplotlib.font_manager import FontPropertiesDEBUG = True #确定当前测试是否查看服务器返回的Json数据  max_group = 35 # 每组人数  QRImagePath = os.getcwd() + '/qrcode.jpg'  tip = 0 #全局变量:标识是否扫描二维码登陆uuid = ''  #全局变量:获取登陆值 base_uri = ''  redirect_uri = ''  skey = ''  wxsid = ''  wxuin = ''  pass_ticket = ''  deviceId = 'e000000000000000'#这个参数是一个15个字节的随机数,所以写死了  BaseRequest = {}  ContactList = []  My = []  def getUUID():      global uuid    url = 'https://login.weixin.qq.com/jslogin'      params = {          'appid': 'wx782c26e4c19acffb',          'fun': 'new',          'lang': 'zh_CN',          '_': int(time.time()),      }          #使用get方法,通过请求地址:https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&fun=new&lang=zh_CN&_=时间戳        #其中,时间戳这个值是当前距离林威治标准时间的毫秒。    request = urllib.request.Request(url = url, data = urllib.parse.urlencode(params).encode(encoding='UTF-8'))      response = urllib.request.urlopen(request)    #成功则返回:window.QRLogin.code = 200; window.QRLogin.uuid = "UUID"    data = response.read()    #1970纪元后经过的浮点秒数time.time()    #print (time.time())    #print(data)        #只要有UUID就可以登陆微信网页版    # window.QRLogin.code = 200; window.QRLogin.uuid = "oZwt_bFfRg==";      regx = r'window.QRLogin.code = (\d+?); window.QRLogin.uuid = "(\S+?)"'  #利用正则表达式匹配      pm = re.search(regx,str(data))      code = pm.group(1)  #200    uuid = pm.group(2)  #oZwt_bFfRg==    if code == '200':          return True      return False  #下载微信登陆图片然后打开def showQRImage():      global tip      #3、查询是否扫描二维码登录    #使用get方法,查询地址:https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=XXXXXX&tip=1&_=时间戳    tip=1    url = 'https://login.weixin.qq.com/qrcode/%s?tip=%d&_=%d' % (uuid,tip,int(time.time()))      """params = {                    'tip': '1',                     '_': int(time.time()),                  }"""      #这里的XXXXXX是我们刚才获取的uuid,时间戳同上。tip在第一次获取时应为1,这个数是每次查询要变的。    #拼接地址            request  = urllib.request.Request(url = url)  #等价request = urllib.request.Request(url = url, data = urllib.parse.urlencode(params))    response = urllib.request.urlopen(request)      f = open(QRImagePath, 'wb')      f.write(response.read())      f.close()      #使用matplotlib显示图片    image_file = cbook.get_sample_data(QRImagePath)      image = plt.imread(image_file)    font = FontProperties(fname=r"D:/Develop//Python27//Lib//site-packages//matplotlib//mpl-data//fonts//ttf//Veral.ttc", size=20)    s = u'~扫描二维码,然后关闭继续哦~'    plt.imshow(image)    plt.title(s,fontproperties=font)    plt.axis('off') # clear x- and y-axes    plt.show()    plt.close()    #判断当前执行是哪种环境,然后对呀的环境打开图片    """if sys.platform.find('darwin') >= 0:  #MAC        os.system('open %s' % QRImagePath)      elif sys.platform.find('linux') >= 0:  #Linux        os.system('xdg-open %s' % QRImagePath)      else:                                  #win32        os.system('call %s' % QRImagePath)"""      print('请使用微信扫描二维码以登录')  def waitForLogin():      global tip, base_uri, redirect_uri      url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (tip, uuid, int(time.time()))      print(url)    request = urllib.request.Request(url = url)      response = urllib.request.urlopen(request)  #如果不扫描会停在这个位置    data = response.read()      #print(data)    # window.code=500;      regx = r'window.code=(\d+);'      pm = re.search(regx, str(data))      code = pm.group(1)      # window.code=408;    if code == '201': #已扫描          print('扫描成功!,请在手机上点击确认以登录')        tip = 0      elif code == '200': #已登录        #window.code=200;        #下面链接为个人登陆的网页版,你可以把自己获取的链接复制到百度试一下,看看效果!直接跳到网页版自己的微信。        #window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A7YkJKTtu09JTsy7f6zy3w8e@qrticket_0        #&uuid=********&lang=zh_CN&scan=*********";        print('正在登录...')          regx = r'window.redirect_uri="(\S+?)";'          pm = re.search(regx, str(data))        redirect_uri = pm.group(1) + '&fun=new'          base_uri = redirect_uri[:redirect_uri.rfind('/')]        #print(redirect_uri)        #print(base_uri)    elif code == '408': #超时不做操作         pass       return code  def login():      global skey, wxsid, wxuin, pass_ticket, BaseRequest      #访问登录地址在获取地址后面加&fun=new,获得uin、sid、pass_ticket、skey    request = urllib.request.Request(url = redirect_uri)      response = urllib.request.urlopen(request)      data = response.read()      # print(data)      #根据data链接访问得到一下xml数据,进行解析    '''''         
0
xxx
xxx
xxx
xxx
1
''' doc = xml.dom.minidom.parseString(data) root = doc.documentElement for node in root.childNodes: if node.nodeName == 'skey': skey = node.childNodes[0].data elif node.nodeName == 'wxsid': wxsid = node.childNodes[0].data elif node.nodeName == 'wxuin': wxuin = node.childNodes[0].data elif node.nodeName == 'pass_ticket': pass_ticket = node.childNodes[0].data # print('skey: %s, wxsid: %s, wxuin: %s, pass_ticket: %s' % (skey, wxsid, wxuin, pass_ticket)) if skey == '' or wxsid == '' or wxuin == '' or pass_ticket == '': return False #拼接成一个字典后面登陆会用到 BaseRequest = { 'Uin': int(wxuin), 'Sid': wxsid, 'Skey': skey, 'DeviceID': deviceId, } return True #微信初始化def webwxinit(): #要使用POST方法,访问地址:https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=时间戳&lang=ch_ZN&pass_ticket=XXXXXX url = base_uri + '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (pass_ticket, skey, int(time.time())) #print(url) #当然这个url需要post方式访问,参数就是之前形成的字典值 #(BaseRequest)uin、sid、skey分别对应上面步骤4获取的字符串,DeviceID是e后面跟着一个15字节的随机数。 params = { 'BaseRequest': BaseRequest } request = urllib.request.Request(url = url, data = json.dumps(params).encode(encoding='UTF-8')) request.add_header('ContentType', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) data = response.read() #data = data.encode() global ContactList, My dic = json.loads(str(data,encoding='utf-8')) #读取服务器通过重重验证过来返回的数据,dic就是当前用户所有信息 ContactList = dic['ContactList'] My = dic['User'] #User就是你的个人信息 #print(os.getcwd() + '/webwxinit.json'); if DEBUG == True: f = open(os.getcwd() + '/webwxinit.json', 'wb') f.write(data) f.close() ErrMsg = dic['BaseResponse']['ErrMsg']#捕获服务器异常信息 if len(ErrMsg) > 0: print(ErrMsg) Ret = dic['BaseResponse']['Ret'] if Ret != 0: return False return True # print(data) Ret = dic['BaseResponse']['Ret'] if Ret != 0: return False return True #获取好友列表数据def webwxgetcontact(): url = base_uri + '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (pass_ticket, skey, int(time.time())) request = urllib.request.Request(url = url) request.add_header('ContentType', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) data = response.read() if DEBUG == True: f = open(os.getcwd() + '/webwxgetcontact.json', 'wb') f.write(data) f.close() # print(data) #data是这个用户所有好友数据 dic = json.loads(str(data,encoding='utf-8')) MemberList = dic['MemberList'] # 倒序遍历,不然删除的时候出问题.. SpecialUsers = ['newsapp', 'fmessage', 'filehelper', 'weibo', 'qqmail', 'fmessage', 'tmessage', 'qmessage', 'qqsync', 'floatbottle', 'lbsapp', 'shakeapp', 'medianote', 'qqfriend', 'readerapp', 'blogapp', 'facebookapp', 'masssendapp', 'meishiapp', 'feedsapp', 'voip', 'blogappweixin', 'weixin', 'brandsessionholder', 'weixinreminder', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'officialaccounts', 'notification_messages', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'wxitil', 'userexperience_alarm', 'notification_messages'] for i in range(len(MemberList) - 1, -1, -1): #range(x-1,-1,-1)是倒序便利 例如range(10,-1,-1) 10,...0 Member = MemberList[i] if Member['VerifyFlag'] & 8 != 0: # 公众号/服务号 24&8=8 其他都是0 MemberList.remove(Member) elif Member['UserName'] in SpecialUsers: # 特殊账号 MemberList.remove(Member) elif Member['UserName'].find('@@') != -1: # 群聊 MemberList.remove(Member) elif Member['UserName'] == My['UserName']: # 自己 MemberList.remove(Member) return MemberList #创建群组开始 def createChatroom(UserNames): MemberList = [] for UserName in UserNames: MemberList.append({
'UserName': UserName}) url = base_uri + '/webwxcreatechatroom?pass_ticket=%s&r=%s' % (pass_ticket, int(time.time())) params = { 'BaseRequest': BaseRequest, 'MemberCount': len(MemberList), 'MemberList': MemberList, 'Topic': '', } request = urllib.request.Request(url = url, data = json.dumps(params).encode(encoding='UTF-8')) request.add_header('ContentType', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) data = response.read() if DEBUG == True: #测试数据 f = open(os.getcwd() + '/webwxChatroo.json', 'wb') f.write(data) f.close() # print(data) dic = json.loads(str(data,encoding='utf-8')) ChatRoomName = dic['ChatRoomName'] MemberList = dic['MemberList'] DeletedList = [] for Member in MemberList: if Member['MemberStatus'] == 4: #被对方删除了 DeletedList.append(Member['UserName']) ErrMsg = dic['BaseResponse']['ErrMsg'] if len(ErrMsg) > 0: print(ErrMsg) return (ChatRoomName, DeletedList) #删除群组成员,最后删除自己def deleteMember(ChatRoomName, UserNames): url = base_uri + '/webwxupdatechatroom?fun=delmember&pass_ticket=%s' % (pass_ticket) params = { 'BaseRequest': BaseRequest, 'ChatRoomName': ChatRoomName, 'DelMemberList': ','.join(UserNames), } request = urllib.request.Request(url = url, data = json.dumps(params).encode(encoding='UTF8')) request.add_header('ContentType', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) data = response.read() # print(data) dic = json.loads(str(data,encoding='utf-8')) ErrMsg = dic['BaseResponse']['ErrMsg'] if len(ErrMsg) > 0: print(ErrMsg) Ret = dic['BaseResponse']['Ret'] if Ret != 0: return False return True def addMember(ChatRoomName, UserNames): url = base_uri + '/webwxupdatechatroom?fun=addmember&pass_ticket=%s' % (pass_ticket) params = { 'BaseRequest': BaseRequest, 'ChatRoomName': ChatRoomName, 'AddMemberList': ','.join(UserNames), } request = urllib.request.Request(url = url, data = json.dumps(params).encode(encoding='UTF-8')) request.add_header('ContentType', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) data = response.read() # print(data) dic = json.loads(str(data,encoding='utf-8')) MemberList = dic['MemberList'] DeletedList = [] for Member in MemberList: if Member['MemberStatus'] == 4: #被对方删除了 DeletedList.append(Member['UserName']) ErrMsg = dic['BaseResponse']['ErrMsg'] if len(ErrMsg) > 0: print(ErrMsg) return DeletedList def main(): #模拟登陆凭证 opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar())) urllib.request.install_opener(opener) if getUUID() == False: print ('获取uuid失败') return showQRImage() #下载微信登陆图片然后登陆 time.sleep(1) while waitForLogin() != '200': pass #循环验证直到为200返回true成功扫描 os.remove(QRImagePath) if login() == False: print ('登录失败') return if webwxinit() == False: print ('初始化失败') return MemberList = webwxgetcontact() MemberCount = len(MemberList) print ('通讯录共%s位好友' % MemberCount) ChatRoomName = '' result = [] #开始分组 好友总数/要分组人数 for i in range(0, int(math.ceil(MemberCount / float(max_group)))): UserNames = [] NickNames = [] DeletedList = '' for j in range(0, max_group): if i * max_group + j >= MemberCount: #判断 第N组人数是否超过总人数 break Member = MemberList[i * max_group + j] UserNames.append(Member['UserName']) #Username是一丢字母,不断变化的 NickNames.append(Member['NickName'].encode('utf-8')) #NickName是好友昵称 print('第%s组...' % (i + 1)) for k in range(0,NickNames.__len__()): NickNames[k] = str(NickNames[k],'utf-8') #str1 = ", " #str1 = str1.join(NickNames) #print(str1) #但是下面输出好友会出现问题,在出现第三组的时候就报下面错,不知道如何解决!!,去掉输出完美运行! #UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 138-138: Non-BMP character not supported in Tk #print(', '.join(NickNames)) #会出现css标签,我想了想那是表情啊~~~哈哈 print('按回车键继续。。。') input() # 新建群组/添加成员 if ChatRoomName == '': (ChatRoomName, DeletedList) = createChatroom(UserNames) else: DeletedList = addMember(ChatRoomName, UserNames) DeletedCount = len(DeletedList) if DeletedCount > 0: result += DeletedList print('找到%s个被删好友' % DeletedCount) #input() # 删除成员 deleteMember(ChatRoomName, UserNames) # todo 删除群组 resultNames = [] for Member in MemberList: if Member['UserName'] in result: NickName = Member['NickName'] if Member['RemarkName'] != '': NickName += '(%s)' % Member['RemarkName'] resultNames.append(NickName.encode('utf-8')) for k in range(0,resultNames.__len__()): resultNames[k] = str(resultNames[k],'utf-8') print ('---------- 被删除的好友列表 ----------') print ('\n'.join(resultNames)) print ('-----------------------------------') if __name__ == '__main__' : print ('开始查询微信删除你的好友信息...') input('回车键继续...') main() input('回车键结束')

4、测试结果如下:我最近容易受限制!!

这里写图片描述

你可能感兴趣的文章
《Visual C++入门经典》学习笔记二(为类添加消息处理函数与成员变量)
查看>>
Linq to Sql : 动态构造Expression进行动态查询
查看>>
c++基础 explicit
查看>>
ArcGIS Server9.2服务器搭建时的一个错误及解决方法
查看>>
webpy使用笔记(二) session的使用
查看>>
Windows Azure HandBook (1) IaaS相关技术
查看>>
【温故而知新-Javascript】使用 Ajax
查看>>
c#如何处理自定义消息
查看>>
毅力----如何培养自律的习惯(漫画版)
查看>>
POP3与IMAP协议
查看>>
[C]有符号数和无符号数
查看>>
结构变量作为方法的参数调用,在方法内部使用的“坑”你遇到过吗?
查看>>
Windows Mobile打包时增加快捷方式到开始菜单的方法
查看>>
深度解析C++拷贝构造函数
查看>>
今天的主角:豆豆。
查看>>
Oracle: 四、对scott用户的基本查询操作(上篇)
查看>>
[Map 3D开发实战系列] Map Resource Explorer 之三-- 添加AutoCAD风格的Palette界面
查看>>
QC在win7远程执行QTP脚本excel不能读取,及其其他win7问题解决方案(图解转)
查看>>
LVS
查看>>
iOS:iPad和iPhone开发的异同(UIPopoverController、UISplitViewController)
查看>>