From 01fd91cbcf4851c3ca5a95e16b1a37ecd9113812 Mon Sep 17 00:00:00 2001 From: lb2281075105 <2281075105@qq.com> Date: Fri, 20 Apr 2018 17:21:34 +0800 Subject: [PATCH] =?UTF-8?q?06=20python=E6=89=93=E5=8D=B0=E5=87=BA=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E8=A2=AB=E5=88=A0=E9=99=A4=E5=A5=BD=E5=8F=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes .../PythonWeChat.py" | 404 ++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 "06 python\346\211\223\345\215\260\345\207\272\345\276\256\344\277\241\350\242\253\345\210\240\351\231\244\345\245\275\345\217\213/PythonWeChat.py" diff --git a/.DS_Store b/.DS_Store index 0cf9dfed0c7ed327b04d11c0c47d1c46c419433e..027d0dd64adc0d24c4c0a916c680b28c007bb418 100644 GIT binary patch delta 250 zcmZp1XmOa}&nU4mU^hRb#N+@0lg$nS`&k&JChrr`lPYTo%1_tHNjD5m&d)7iKmcUv t+MgYu&OxXYc delta 41 xcmZp1XmOa}&nU7nU^hRb$m9S4lg$nS`&l;2i@jjn*r33;nO))s%f>2JW&j?-4Q>Dc diff --git "a/06 python\346\211\223\345\215\260\345\207\272\345\276\256\344\277\241\350\242\253\345\210\240\351\231\244\345\245\275\345\217\213/PythonWeChat.py" "b/06 python\346\211\223\345\215\260\345\207\272\345\276\256\344\277\241\350\242\253\345\210\240\351\231\244\345\245\275\345\217\213/PythonWeChat.py" new file mode 100644 index 0000000..430b66f --- /dev/null +++ "b/06 python\346\211\223\345\215\260\345\207\272\345\276\256\344\277\241\350\242\253\345\210\240\351\231\244\345\245\275\345\217\213/PythonWeChat.py" @@ -0,0 +1,404 @@ +#coding:utf-8 +# 通过该程序可以发现被删除的好友 +import os +import urllib, urllib2 +import re +import cookielib +import time +import xml.dom.minidom +import json +import sys +import math + +DEBUG = False + +MAX_GROUP_NUM = 35 # 每组人数 + +QRImagePath = os.getcwd() + '/qrcode.jpg' + +tip = 0 +uuid = '' + +base_uri = '' +redirect_uri = '' + +skey = '' +wxsid = '' +wxuin = '' +pass_ticket = '' +deviceId = 'e000000000000000' + +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()), + } + + request = urllib2.Request(url=url, data=urllib.urlencode(params)) + response = urllib2.urlopen(request) + data = response.read() + + regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"' + pm = re.search(regx, data) + + code = pm.group(1) + uuid = pm.group(2) + + if code == '200': + return True + + return False + + +def showQRImage(): + global tip + + url = 'https://login.weixin.qq.com/qrcode/' + uuid + params = { + 't': 'webwx', + '_': int(time.time()), + } + + request = urllib2.Request(url=url, data=urllib.urlencode(params)) + response = urllib2.urlopen(request) + + tip = 1 + + f = open(QRImagePath, 'wb') + f.write(response.read()) + f.close() + + if sys.platform.find('darwin') >= 0: + os.system('open %s' % QRImagePath) + elif sys.platform.find('linux') >= 0: + os.system('xdg-open %s' % QRImagePath) + else: + 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())) + + request = urllib2.Request(url=url) + response = urllib2.urlopen(request) + data = response.read() + + # window.code=500; + regx = r'window.code=(\d+);' + pm = re.search(regx, data) + + code = pm.group(1) + + if code == '201': # 已扫描 + print '成功扫描,请在手机上点击确认以登录' + tip = 0 + elif code == '200': # 已登录 + print '正在登录...' + regx = r'window.redirect_uri="(\S+?)";' + pm = re.search(regx, data) + redirect_uri = pm.group(1) + '&fun=new' + base_uri = redirect_uri[:redirect_uri.rfind('/')] + elif code == '408': # 超时 + pass + + return code + +def login(): + global skey, wxsid, wxuin, pass_ticket, BaseRequest + + request = urllib2.Request(url=redirect_uri) + response = urllib2.urlopen(request) + data = response.read() + 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 + + 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(): + url = base_uri + '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (pass_ticket, skey, int(time.time())) + params = { + 'BaseRequest': BaseRequest + } + + request = urllib2.Request(url=url, data=json.dumps(params)) + request.add_header('ContentType', 'application/json; charset=UTF-8') + response = urllib2.urlopen(request) + data = response.read() + +if DEBUG == True: + f = open(os.getcwd() + '/webwxinit.json', 'wb') + f.write(data) + f.close() + + global ContactList, My + dic = json.loads(data) + ContactList = dic['ContactList'] + My = dic['User'] + + ErrMsg = dic['BaseResponse']['ErrMsg'] + if len(ErrMsg) > 0: + print ErrMsg + + 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 = urllib2.Request(url=url) + request.add_header('ContentType', 'application/json; charset=UTF-8') + response = urllib2.urlopen(request) + data = response.read() + + if DEBUG == True: + f = open(os.getcwd() + '/webwxgetcontact.json', 'wb') + f.write(data) + f.close() + + dic = json.loads(data) + 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 xrange(len(MemberList) - 1, -1, -1): + Member = MemberList[i] + # 公众号/服务号 + if Member['VerifyFlag'] & 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 = urllib2.Request(url=url, data=json.dumps(params)) + request.add_header('ContentType', 'application/json; charset=UTF-8') + response = urllib2.urlopen(request) + data = response.read() + + dic = json.loads(data) + 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 = urllib2.Request(url=url, data=json.dumps(params)) + request.add_header('ContentType', 'application/json; charset=UTF-8') + response = urllib2.urlopen(request) + data = response.read() + dic = json.loads(data) + 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 = urllib2.Request(url=url, data=json.dumps(params)) + request.add_header('ContentType', 'application/json; charset=UTF-8') + response = urllib2.urlopen(request) + data = response.read() + dic = json.loads(data) + 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 = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) + urllib2.install_opener(opener) + + if getUUID() == False: + print '获取uuid失败' + return + + showQRImage() + time.sleep(1) + +while waitForLogin() != '200': + pass + + 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 xrange(0, int(math.ceil(MemberCount / float(MAX_GROUP_NUM)))): + UserNames = [] + NickNames = [] + DeletedList = '' + for j in xrange(0, MAX_GROUP_NUM): + if i * MAX_GROUP_NUM + j >= MemberCount: + break + + Member = MemberList[i * MAX_GROUP_NUM + j] + UserNames.append(Member['UserName']) + NickNames.append(Member['NickName'].encode('utf-8')) + + print '第%s组...' % (i + 1) + print ', '.join(NickNames) + print '回车键继续...' + raw_input() + + # 新建群组/添加成员 + if ChatRoomName == '': + (ChatRoomName, DeletedList) = createChatroom(UserNames) + else: + DeletedList = addMember(ChatRoomName, UserNames) + + DeletedCount = len(DeletedList) + if DeletedCount > 0: + result += DeletedList + + print '找到%s个被删好友' % DeletedCount + # 删除成员 + deleteMember(ChatRoomName, UserNames) + + 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')) + + print '---------- 被删除的好友列表 ----------' + print '\n'.join(resultNames) + print '-----------------------------------' + +# windows下编码问题修复 +class UnicodeStreamFilter: + def __init__(self, target): + self.target = target + self.encoding = 'utf-8' + self.errors = 'replace' + self.encode_to = self.target.encoding + + def write(self, s): + if type(s) == str: + s = s.decode('utf-8') + s = s.encode(self.encode_to, self.errors).decode(self.encode_to) + self.target.write(s) + + +if sys.stdout.encoding == 'cp936': + sys.stdout = UnicodeStreamFilter(sys.stdout) + +if __name__ == '__main__': + raw_input('请输入回车键继续本程序:') + main() + raw_input('请输入回车键结束本程序:')