利用Python了解微信通信机制,实现查询有多少好友删除你!!

此篇文章参考微信通信机制,收益匪浅!:http://lib.csdn.net/article/wechat/63831

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 Chiang
import os
import urllib
import re
import http.cookiejar
import time
import xml.dom.minidom
import json
import sys
import math
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib

from matplotlib.font_manager import FontProperties

DEBUG = 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数据,进行解析
    '''''
        <error>
            <ret>0</ret>
            <message></message>
            <skey>xxx</skey>
            <wxsid>xxx</wxsid>
            <wxuin>xxx</wxuin>
            <pass_ticket>xxx</pass_ticket>
            <isgrayscale>1</isgrayscale>
        </error>
    '''  

    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、测试结果如下:我最近容易受限制!!

时间: 2024-09-10 00:15:10

利用Python了解微信通信机制,实现查询有多少好友删除你!!的相关文章

利用Python开发微信支付的注意事项_python

前言 微信支付是由微信及财付通联合推出的移动支付创新产品.如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及商家申请微信支付时,面临着诸多疑惑. 要想开发顺利进行,首先要对业务流程有个清晰的认识.这里以微信公众号支付为例,因此也借用微信支付官方文档中的业务流程图: 接下来来关注几个开发过程中的关键点,包括:       1.生成商户订单与调用统一下单 API       2.微信服务器交互的数据格式       3.公众号支付下网页内通过 JS-API 调起支付  

利用Oracle执行计划机制提高查询性能

oracle|性能|执行 消耗在准备利用Oracle执行计划机制提高查询性能新的SQL语句的时间是Oracle SQL语句执行时间的最重要的组成部分.但是通过理解Oracle内部产生执行计划的机制,你能够控制Oracle花费在评估连接顺序的时间数量,并且能在大体上提高查询性能. 准备执行SQL语句 当SQL语句进入Oracle的库缓存后,在该语句准备执行之前,将执行下列步骤: 1) 语法检查:检查SQL语句拼写是否正确和词序. 2) 语义分析:核实所有的与数据字典不一致的表和列的名字. 3) 轮

利用Python自动监控网站并发送邮件告警的方法_python

前言 因为有一些网站需要每日检查是否有问题,所以需要一个报警监控的机制,这个需要你指定你发送的邮箱和你接收的邮箱,就可以做到对网站自动监控了. 这里用的是python3.5 需要安装的插件:       1.smtplib:发邮件需要用到       2.pycurl:访问网站时会需要用到       3.linecache:在读取txt网站清单时需要用到 具体思路: python程序从txt里面批量读取到网站的信息,通过Curl.py模拟浏览器去访问网站,并且把访问的结果写入到以自己的网站名称

利用Python实现简单的相似图片搜索的教程

  利用Python实现简单的相似图片搜索的教程         这篇文章主要介绍了利用Python实现简单的相似图片搜索的教程,文中的示例主要在一个图片指纹数据库中实现,需要的朋友可以参考下 大概五年前吧,我那时还在为一家约会网站做开发工作.他们是早期创业公司,但他们也开始拥有了一些稳定用户量.不像其他约会网站,这家公司向来以洁身自好为主要市场形象.它不是一个供你鬼混的网站--是让你能找到忠实伴侣的地方. 由于投入了数以百万计的风险资本(在US大萧条之前),他们关于真爱并找寻灵魂伴侣的在线广告

Linux下利用 Python连接mysql数据库一个很好的例子

原文转载自:http://my.oschina.net/davehe/blog/128361 1 安装Python的Mysql包 root@10.1.1.45:~# apt-get install python-mysqldb root@10.1.1.45:~# python Python 2.5.2 (r252:60911, Jan 4 2009, 21:59:32) [GCC 4.3.2] on linux2 Type "help", "copyright",

深入理解Android组件间通信机制对面向对象特性的影响详解_Android

组件的特点对于Android的四大组件Activity, Service, ContentProvider和Service,不能有Setter和Getter,也不能给组件添加接口.原因是组件都是给系统框架调用的,开发者只能实现其规定的回调接口,组件的创建与销毁都是由系统框架控制的,开发者不能强行干预,更没有办法获取组件的对象.比如Activity,Service,BroadcastReceiver,你没有办法去创建一个Activity,Service或BroadcastReceiver,然后像使

Python实现微信公众平台自定义菜单实例_python

首先先获取access_token,并保存与全局之中 def token(requset): url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % ( Config.AppID, Config.AppSecret) result = urllib2.urlopen(url).read() Config.access_token = json.load

用微信的公众号查询个人信用评分是怎样一种场景?

阿里系的芝麻分来了,腾讯系的信用产品也不远了.用微信的公众号查询个人信用评分是怎样一种场景?也许再过两个月,秘密就能揭晓. 2月11日,经济观察报从腾讯公司人士处获悉,不久腾讯征信将借道微信公众号和手机QQ服务号,推出个人征信查询服务以及针对性的金融产品推荐. 不过,腾讯征信的产品到底啥模样?有别于芝麻信用,腾讯征信前期更看重金融场景. 此前,在财付通内部的一次分享会上,经济观察报记者获悉,腾讯征信将数据分为腾讯信息和非腾讯信息两部分.腾讯信息包括社交.支付.通讯和娱乐.这背后涉及到腾讯QQ.Q

python查看微信好友是否删除自己_python

本文实例为大家分享了python微信好友删除的具体代码,供大家参考,具体内容如下 #weixin.py #coding:utf-8 # !/usr/bin/env python # coding=utf-8 #通过该程序可以发现被删除的好友 import os import urllib, urllib2 import re import cookielib import time import xml.dom.minidom import json import sys import math