#-*- coding:utf-8 -*-
'''扫码登陆微信后获取该微信账号的微信群(包括群内人员)和通讯录联系人信息【注:好像不全】'''
importosimportreimporttimeimportsysimportsubprocessimportrequestsimportxml.dom.minidomimportjson#微信登陆
classWebwxLogin(object):def __init__(self):
self.session=requests.session()
self.headers={'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'}
self.QRImgPath= os.path.split(os.path.realpath(__file__))[0] + os.sep + 'webWeixinQr.jpg'self.uuid= ''self.tip=0
self.base_uri= ''self.redirect_uri= ''self.skey= ''self.wxsid= ''self.wxuin= ''self.pass_ticket= ''self.deviceId= 'e000000000000000'self.BaseRequest={}
self.ContactList=[]
self.My=[]
self.SyncKey= ''
defgetUUID(self):
url= 'https://login.weixin.qq.com/jslogin'params={'appid': 'wx782c26e4c19acffb','redirect_uri': 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage','fun': 'new','lang': 'zh_CN','_': int(time.time() * 1000), #时间戳
}
response= self.session.get(url, params=params)
target= response.content.decode('utf-8')
pattern= r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"'ob= re.search(pattern, target) #正则提取uuid
code= ob.group(1)
self.uuid= ob.group(2)if code == '200': #判断请求是否成功
returnTruereturnFalsedefshowQRImage(self):
url= 'https://login.weixin.qq.com/qrcode/' +self.uuid
response=self.session.get(url)
self.tip= 1with open(self.QRImgPath,'wb') as f:
f.write(response.content)
f.close()#打开二维码
if sys.platform.find('darwin') >=0:
subprocess.call(['open', self.QRImgPath]) #苹果系统
elif sys.platform.find('linux') >=0:
subprocess.call(['xdg-open', self.QRImgPath]) #linux系统
else:
os.startfile(self.QRImgPath)#windows系统
print('请使用微信扫描二维码登录')defcheckLogin(self):
url= 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' %(
self.tip, self.uuid, int(time.time()* 1000))
response=self.session.get(url)
target= response.content.decode('utf-8')
pattern= r'window.code=(\d+);'ob=re.search(pattern, target)
code= ob.group(1)if code == '201': #已扫描
print('成功扫描,请在手机上点击确认登录')
self.tip=0elif code == '200': #已登录
print('正在登录中...')
regx= r'window.redirect_uri="(\S+?)";'ob=re.search(regx, target)
self.redirect_uri= ob.group(1) + '&fun=new'self.base_uri= self.redirect_uri[:self.redirect_uri.rfind('/')]elif code == '408': #超时
pass
returncodedeflogin(self):
response= self.session.get(self.redirect_uri, verify=False)
data= response.content.decode('utf-8')
doc=xml.dom.minidom.parseString(data)
root=doc.documentElement#提取响应中的参数
for node inroot.childNodes:if node.nodeName == 'skey':
self.skey=node.childNodes[0].dataelif node.nodeName == 'wxsid':
self.wxsid=node.childNodes[0].dataelif node.nodeName == 'wxuin':
self.wxuin=node.childNodes[0].dataelif node.nodeName == 'pass_ticket':
self.pass_ticket=node.childNodes[0].dataif notall((self.skey, self.wxsid, self.wxuin, self.pass_ticket)):returnFalse
self.BaseRequest={'Uin': int(self.wxuin),'Sid': self.wxsid,'Skey': self.skey,'DeviceID': self.deviceId,
}returnTruedefwebwxinit(self):
url= self.base_uri +\'/webwxinit?pass_ticket=%s&skey=%s&r=%s' %(
self.pass_ticket, self.skey, int(time.time()* 1000))
params={'BaseRequest': self.BaseRequest
}
h=self.headers
h['ContentType'] = 'application/json; charset=UTF-8'response= self.session.post(url, data=json.dumps(params), headers=h, verify=False)
data= response.content.decode('utf-8')print(data)
dic=json.loads(data)
self.ContactList= dic['ContactList']
self.My= dic['User']
SyncKeyList=[]for item in dic['SyncKey']['List']:
SyncKeyList.append('%s_%s' % (item['Key'], item['Val']))
self.SyncKey= '|'.join(SyncKeyList)
ErrMsg= dic['BaseResponse']['ErrMsg']
Ret= dic['BaseResponse']['Ret']if Ret !=0:returnFalsereturnTruedefwebwxgetcontact(self):
url= self.base_uri +\'/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' %(
self.pass_ticket, self.skey, int(time.time()))
h=self.headers
h['ContentType'] = 'application/json; charset=UTF-8'response= self.session.get(url, headers=h, verify=False)
data= response.content.decode('utf-8')#print(data)
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'] == self.My['UserName']: #自己
MemberList.remove(Member)returnMemberListdefmain(self):if notself.getUUID():print('获取uuid失败')returnself.showQRImage()
time.sleep(1)while self.checkLogin() != '200':passos.remove(self.QRImgPath)if notself.login():print('登录失败')return
#登录完成, 下面查询好友
if notself.webwxinit():print('初始化失败')returnMemberList=self.webwxgetcontact()print('通讯录共%s位好友' %len(MemberList))for x inMemberList:
sex= '未知' if x['Sex'] == 0 else '男' if x['Sex'] == 1 else '女'
print('昵称:%s, 性别:%s, 备注:%s, 签名:%s' % (x['NickName'], sex, x['RemarkName'], x['Signature']))if __name__ == '__main__':print('开始')
wx=WebwxLogin()
wx.main()