基于Python实现通过微信搜索功能查看谁把你删除了


Posted in Python onJanuary 27, 2016

场景:查找who删了我,直接copy代码保存到一个python文件who.py,在python环境下运行此文件

基于Python实现通过微信搜索功能查看谁把你删除了

代码如下,copy保存到who.py文件在python环境直接运行:

#!/usr/bin/env python
# coding=utf-8
from __future__ import print_function
import os
try:
from urllib import urlencode, quote_plus
except ImportError:
from urllib.parse import urlencode, quote_plus
try:
import urllib2 as wdf_urllib
from cookielib import CookieJar
except ImportError:
import urllib.request as wdf_urllib
from http.cookiejar import CookieJar
import re
import time
import xml.dom.minidom
import json
import sys
import math
import subprocess
import ssl
import thread
DEBUG = False
MAX_GROUP_NUM = 35 # 每组人数
INTERFACE_CALLING_INTERVAL = 20 # 接口调用时间间隔, 间隔太短容易出现"操作太频繁", 会被限制操作半小时左右
MAX_PROGRESS_LEN = 50
QRImagePath = os.path.join(os.getcwd(), 'qrcode.jpg')
tip = 0
uuid = ''
base_uri = ''
redirect_uri = ''
push_uri = ''
skey = ''
wxsid = ''
wxuin = ''
pass_ticket = ''
deviceId = 'e000000000000000'
BaseRequest = {}
ContactList = []
My = []
SyncKey = []
try:
xrange
range = xrange
except:
# python 3
pass
def responseState(func, BaseResponse):
ErrMsg = BaseResponse['ErrMsg']
Ret = BaseResponse['Ret']
if DEBUG or Ret != 0:
print('func: %s, Ret: %d, ErrMsg: %s' % (func, Ret, ErrMsg))
if Ret != 0:
return False
return True
def getRequest(url, data=None):
try:
data = data.encode('utf-8')
except:
pass
finally:
return wdf_urllib.Request(url=url, data=data)
def getUUID():
global uuid
url = 'https://login.weixin.qq.com/jslogin'
params = {
'appid': 'wx782c26e4c19acffb',
'fun': 'new',
'lang': 'zh_CN',
'_': int(time.time()),
}
request = getRequest(url=url, data=urlencode(params))
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
# window.QRLogin.code = 200; window.QRLogin.uuid = "oZwt_bFfRg==";
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 = getRequest(url=url, data=urlencode(params))
response = wdf_urllib.urlopen(request)
tip = 1
f = open(QRImagePath, 'wb')
f.write(response.read())
f.close()
if sys.platform.find('darwin') >= 0:
subprocess.call(['open', QRImagePath])
elif sys.platform.find('linux') >= 0:
subprocess.call(['xdg-open', QRImagePath])
else:
os.startfile(QRImagePath)
print('请使用微信扫描二维码以登录')
def waitForLogin():
global tip, base_uri, redirect_uri, push_uri
url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (
tip, uuid, int(time.time()))
request = getRequest(url=url)
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
# 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('/')]
# push_uri与base_uri对应关系(排名分先后)(就是这么奇葩..)
services = [
('wx2.qq.com', 'webpush2.weixin.qq.com'),
('qq.com', 'webpush.weixin.qq.com'),
('web1.wechat.com', 'webpush1.wechat.com'),
('web2.wechat.com', 'webpush2.wechat.com'),
('wechat.com', 'webpush.wechat.com'),
('web1.wechatapp.com', 'webpush1.wechatapp.com'),
]
push_uri = base_uri
for (searchUrl, pushUrl) in services:
if base_uri.find(searchUrl) >= 0:
push_uri = 'https://%s/cgi-bin/mmwebwx-bin' % pushUrl
break
# closeQRImage
if sys.platform.find('darwin') >= 0: # for OSX with Preview
os.system("osascript -e 'quit app \"Preview\"'")
elif code == '408': # 超时
pass
# elif code == '400' or code == '500':
return code
def login():
global skey, wxsid, wxuin, pass_ticket, BaseRequest
request = getRequest(url=redirect_uri)
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
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 not all((skey, wxsid, wxuin, 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 = getRequest(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read()
if DEBUG:
f = open(os.path.join(os.getcwd(), 'webwxinit.json'), 'wb')
f.write(data)
f.close()
data = data.decode('utf-8', 'replace')
# print(data)
global ContactList, My, SyncKey
dic = json.loads(data)
ContactList = dic['ContactList']
My = dic['User']
SyncKey = dic['SyncKey']
state = responseState('webwxinit', dic['BaseResponse'])
return state
def webwxgetcontact():
url = base_uri + \
'/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (
pass_ticket, skey, int(time.time()))
request = getRequest(url=url)
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read()
if DEBUG:
f = open(os.path.join(os.getcwd(), 'webwxgetcontact.json'), 'wb')
f.write(data)
f.close()
# print(data)
data = data.decode('utf-8', 'replace')
dic = json.loads(data)
MemberList = dic['MemberList']
# 倒序遍历,不然删除的时候出问题..
SpecialUsers = ["newsapp", "fmessage", "filehelper", "weibo", "qqmail", "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", "wxitil", "userexperience_alarm"]
for i in range(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 = [{'UserName': UserName} for UserName in UserNames]
url = base_uri + \
'/webwxcreatechatroom?pass_ticket=%s&r=%s' % (
pass_ticket, int(time.time()))
params = {
'BaseRequest': BaseRequest,
'MemberCount': len(MemberList),
'MemberList': MemberList,
'Topic': '',
}
request = getRequest(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
dic = json.loads(data)
ChatRoomName = dic['ChatRoomName']
MemberList = dic['MemberList']
DeletedList = []
BlockedList = []
for Member in MemberList:
if Member['MemberStatus'] == 4: # 被对方删除了
DeletedList.append(Member['UserName'])
elif Member['MemberStatus'] == 3: # 被加入黑名单
BlockedList.append(Member['UserName'])
state = responseState('createChatroom', dic['BaseResponse'])
return ChatRoomName, DeletedList, BlockedList
def deleteMember(ChatRoomName, UserNames):
url = base_uri + \
'/webwxupdatechatroom?fun=delmember&pass_ticket=%s' % (pass_ticket)
params = {
'BaseRequest': BaseRequest,
'ChatRoomName': ChatRoomName,
'DelMemberList': ','.join(UserNames),
}
request = getRequest(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
dic = json.loads(data)
state = responseState('deleteMember', dic['BaseResponse'])
return state
def addMember(ChatRoomName, UserNames):
url = base_uri + \
'/webwxupdatechatroom?fun=addmember&pass_ticket=%s' % (pass_ticket)
params = {
'BaseRequest': BaseRequest,
'ChatRoomName': ChatRoomName,
'AddMemberList': ','.join(UserNames),
}
request = getRequest(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
dic = json.loads(data)
MemberList = dic['MemberList']
DeletedList = []
BlockedList = []
for Member in MemberList:
if Member['MemberStatus'] == 4: # 被对方删除了
DeletedList.append(Member['UserName'])
elif Member['MemberStatus'] == 3: # 被加入黑名单
BlockedList.append(Member['UserName'])
state = responseState('addMember', dic['BaseResponse'])
return DeletedList, BlockedList
def syncKey():
SyncKeyItems = ['%s_%s' % (item['Key'], item['Val'])
for item in SyncKey['List']]
SyncKeyStr = '|'.join(SyncKeyItems)
return SyncKeyStr
def syncCheck():
url = push_uri + '/synccheck?'
params = {
'skey': BaseRequest['Skey'],
'sid': BaseRequest['Sid'],
'uin': BaseRequest['Uin'],
'deviceId': BaseRequest['DeviceID'],
'synckey': syncKey(),
'r': int(time.time()),
}
request = getRequest(url=url + urlencode(params))
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
# window.synccheck={retcode:"0",selector:"2"}
regx = r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}'
pm = re.search(regx, data)
retcode = pm.group(1)
selector = pm.group(2)
return selector
def webwxsync():
global SyncKey
url = base_uri + '/webwxsync?lang=zh_CN&skey=%s&sid=%s&pass_ticket=%s' % (
BaseRequest['Skey'], BaseRequest['Sid'], quote_plus(pass_ticket))
params = {
'BaseRequest': BaseRequest,
'SyncKey': SyncKey,
'rr': ~int(time.time()),
}
request = getRequest(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8')
response = wdf_urllib.urlopen(request)
data = response.read().decode('utf-8', 'replace')
# print(data)
dic = json.loads(data)
SyncKey = dic['SyncKey']
state = responseState('webwxsync', dic['BaseResponse'])
return state
def heartBeatLoop():
while True:
selector = syncCheck()
if selector != '0':
webwxsync()
time.sleep(1)
def main():
try:
ssl._create_default_https_context = ssl._create_unverified_context
opener = wdf_urllib.build_opener(
wdf_urllib.HTTPCookieProcessor(CookieJar()))
opener.addheaders = [
('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36')]
wdf_urllib.install_opener(opener)
except:
pass
if not getUUID():
print('获取uuid失败')
return
print('正在获取二维码图片...')
showQRImage()
time.sleep(1)
while waitForLogin() != '200':
pass
os.remove(QRImagePath)
if not login():
print('登录失败')
return
if not webwxinit():
print('初始化失败')
return
MemberList = webwxgetcontact()
print('开启心跳线程')
thread.start_new_thread(heartBeatLoop, ())
MemberCount = len(MemberList)
print('通讯录共%s位好友' % MemberCount)
ChatRoomName = ''
result = []
d = {}
for Member in MemberList:
d[Member['UserName']] = (Member['NickName'].encode(
'utf-8'), Member['RemarkName'].encode('utf-8'))
print('开始查找...')
group_num = int(math.ceil(MemberCount / float(MAX_GROUP_NUM)))
for i in range(0, group_num):
UserNames = []
for j in range(0, MAX_GROUP_NUM):
if i * MAX_GROUP_NUM + j >= MemberCount:
break
Member = MemberList[i * MAX_GROUP_NUM + j]
UserNames.append(Member['UserName'])
# 新建群组/添加成员
if ChatRoomName == '':
(ChatRoomName, DeletedList, BlockedList) = createChatroom(
UserNames)
else:
(DeletedList, BlockedList) = addMember(ChatRoomName, UserNames)
# todo BlockedList 被拉黑列表
DeletedCount = len(DeletedList)
if DeletedCount > 0:
result += DeletedList
# 删除成员
deleteMember(ChatRoomName, UserNames)
# 进度条
progress = MAX_PROGRESS_LEN * (i + 1) / group_num
print('[', '#' * progress, '-' * (MAX_PROGRESS_LEN - progress), ']', end=' ')
print('新发现你被%d人删除' % DeletedCount)
for i in range(DeletedCount):
if d[DeletedList[i]][1] != '':
print(d[DeletedList[i]][0] + '(%s)' % d[DeletedList[i]][1])
else:
print(d[DeletedList[i]][0])
if i != group_num - 1:
print('正在继续查找,请耐心等待...')
# 下一次进行接口调用需要等待的时间
time.sleep(INTERFACE_CALLING_INTERVAL)
# todo 删除群组
print('\n结果汇总完毕,20s后可重试...')
resultNames = []
for r in result:
if d[r][1] != '':
resultNames.append(d[r][0] + '(%s)' % d[r][1])
else:
resultNames.append(d[r][0])
print('---------- 被删除的好友列表(共%d人) ----------' % len(result))
# 过滤emoji
resultNames = map(lambda x: re.sub(r'<span.+/span>', '', x), resultNames)
if len(resultNames):
print('\n'.join(resultNames))
else:
print("无")
print('---------------------------------------------')
# windows下编码问题修复
# http://blog.csdn.net/heyuxuanzee/article/details/8442718
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__':
print('本程序的查询结果可能会引起一些心理上的不适,请小心使用...')
main()
print('回车键退出...')

以上所述是基于Python实现微信搜索查看谁把你删除了的相关内容,希望对大家有所帮助。

Python 相关文章推荐
Python通过select实现异步IO的方法
Jun 04 Python
Python首次安装后运行报错(0xc000007b)的解决方法
Oct 18 Python
使用python编写简单的小程序编译成exe跑在win10上
Jan 15 Python
Python中sort和sorted函数代码解析
Jan 25 Python
TensorFlow实现RNN循环神经网络
Feb 28 Python
在python里面运用多继承方法详解
Jul 01 Python
PyCharm搭建Spark开发环境的实现步骤
Sep 05 Python
Python如何对XML 解析
Jun 28 Python
2020年10款优秀的Python第三方库,看看有你中意的吗?
Jan 12 Python
python基于爬虫+django,打造个性化API接口
Jan 21 Python
超级详细实用的pycharm常用快捷键
May 12 Python
如何在pycharm中快捷安装pip命令(如pygame)
May 31 Python
Python图像灰度变换及图像数组操作
Jan 27 #Python
让python在hadoop上跑起来
Jan 27 #Python
CentOS安装pillow报错的解决方法
Jan 27 #Python
python实现文本去重且不打乱原本顺序
Jan 26 #Python
举例讲解Python设计模式编程中的访问者与观察者模式
Jan 26 #Python
Python函数中*args和**kwargs来传递变长参数的用法
Jan 26 #Python
python中的编码知识整理汇总
Jan 26 #Python
You might like
php中return的用法实例分析
2015/02/28 PHP
Laravel 数据库加密及数据库表前缀配置方法
2019/10/10 PHP
javascript 当前日期加(天、周、月、年)
2009/08/09 Javascript
JavaScript 精粹读书笔记(1,2)
2010/02/07 Javascript
网络之美 JavaScript中Get和Set访问器的实现代码
2010/09/19 Javascript
JavaScript中valueOf函数与toString方法深入理解
2012/12/02 Javascript
原生js操作checkbox用document.getElementById实现
2013/10/12 Javascript
jQuery 事件的命名空间简单了解
2013/11/22 Javascript
jquery判断小数点两位和自动删除小数两位后的数字
2014/03/19 Javascript
对Web开发中前端框架与前端类库的一些思考
2015/03/27 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
Angularjs注入拦截器实现Loading效果
2015/12/28 Javascript
javaScript中的原型解析【推荐】
2016/05/05 Javascript
jQuery Easyui Datagrid实现单行的上移下移及保存移动的结果
2016/08/15 Javascript
JS实现简单拖拽效果
2017/06/21 Javascript
vue router学习之动态路由和嵌套路由详解
2017/09/21 Javascript
js实现轮播图的两种方式(构造函数、面向对象)
2017/09/30 Javascript
pm2 部署 node的三种方法示例
2017/10/20 Javascript
微信小程序wx.uploadfile 本地文件转base64的实现代码
2018/06/28 Javascript
浅谈VUE中演示v-for为什么要加key
2020/01/16 Javascript
[02:23]2014DOTA2国际邀请赛中国战队回顾
2014/08/01 DOTA
详解python使用Nginx和uWSGI来运行Python应用
2018/01/09 Python
详解Python3.6安装psutil模块和功能简介
2018/05/30 Python
Python实现读取txt文件中的数据并绘制出图形操作示例
2019/02/26 Python
Python代理IP爬虫的新手使用教程
2019/09/05 Python
python 如何在测试中使用 Mock
2021/03/01 Python
CSS伪类与CSS伪元素的区别及由来具体说明
2012/12/07 HTML / CSS
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
英国第一的滑雪服装和装备零售商:Snow+Rock
2020/02/01 全球购物
JSF面试题:Jsf中的核心类用那些?有什么作用?LiftCycle六大生命周期是什么?
2014/07/17 面试题
财务部岗位职责
2013/11/19 职场文书
初一家长会邀请函
2014/01/31 职场文书
优秀护士先进事迹
2014/05/08 职场文书
幼儿园见习报告
2014/10/30 职场文书
2015年消费者权益日活动总结
2015/02/09 职场文书
2015年库房工作总结
2015/04/30 职场文书