谁能教教我怎么弄几个微信能申请几个号号,不要网上复制粘贴过来的教程。

Python教程(2)
现在的日常生活已经离不开微信,本文将会抛砖引玉演示如何使用Python调用微信API做一些有意思的东西。
看完这一系列教程,你就能从头开始实现自己关于微信的想法。
本文为教程的第二部分,主要以微信控制器、群发助手、好友删除检测为例演示如何调用微信API。
Python基础并不困难,所以即使没有这方面基础辅助搜索引擎也完全可以学习本教程。
关于本教程有任何建议或者疑问,都欢迎邮件与我联系(),或者在上提出。
教程流程简介
这一系列教程从如何分析微信协议开始,教你如何从零开始获取并模拟扩展个人微信号所需要的协议。
第二部分将会就这些协议进行利用,以各项目为例介绍一些微信有意思功能的实现。
第三部分就协议的一些高级用法进行介绍,对框架做进一步介绍与扩展。
本文为教程的第二部分。
简单成果展示
完成了本文的学习,你将会完成三个小项目:(出于方便二次阅读,括号中都放上了源码链接)
* 通过微信操作的音乐播放器()
* 消息内容与对象可自定义的消息群发助手()
* 特定好友删除检测()
使用微信协议完成机器人较为平常,如果对具体细节感兴趣,可以添加个人号littlecodersh并回复“源代码”。
本文主要基于微信API的第三方包itchat,你可以在获取更多信息。
本部分所需环境
本文是这一教程的第二部分,需要基本的pip可用的Python环境。
本教程使用的环境如下:
* Windows 8.1 (其他平台也可用)
* Python 2 or 3
* 微信版本6.3.25
微信控制器
在项目主页上,专门有人就微信作为智能家居入口向我提出了很多想法。
如果微信可以作为控制器,就可以不必自制手机端客户端的麻烦。
其实这个需求实现起来非常简单,这里我借鉴了yaphone的,使用了其中部分的代码作为演示。
这是一个通过微信控制电脑播放音乐的小项目,那么主要就是三个功能:
* 输入“帮助”,显示帮助
* 输入“关闭”,关闭音乐播放
* 输入具体歌名,进入歌曲的选择
换成代码就是这样一个逻辑:
if msg == u'关闭':
close_music()
print(u'音乐已关闭')
if msg == u'帮助':
print(u'帮助信息')
print(interact_select_song(msg))
那么现在需要解决的就是如何关闭音乐,如何选择音乐和如何使用微信交互。
关闭音乐我们这里使用打开空文件的方式,而选择音乐我们使用网易云音乐的API完成:
from NetEaseMusicApi import interact_select_song
with open('stop.mp3', 'w') as f: pass
def close_music():
os.startfile('stop.mp3')
而微信的调用可以通过itchat包简单的完成,这里要注意的是:
* 有些账号无法与自己通信,所以我们选择与文件传输助手(filehelper)通信
* 为了防止对于其他消息的响应,我们在第一行过滤了无关信息
* itchat.run的选项分别为允许热拔插,方便调试
import itchat
@itchat.msg_register(itchat.content.TEXT)
def music_player(msg):
if msg['ToUserName'] != 'filehelper': return
if msg['Text'] == u'关闭':
close_music()
itchat.send(u'音乐已关闭', 'filehelper')
if msg['Text'] == u'帮助':
itchat.send(u'帮助信息', 'filehelper')
itchat.send(interact_select_song(msg['Text']), 'filehelper')
itchat.auto_login(True)
itchat.send(HELP_MSG, 'filehelper')
itchat.run()
itchat对常用功能都做好了封装,调用还是非常容易的。
完整的程序我放在了上面,使用时不要忘记安装第三方包。
通过与文件传输助手的交互,微信就能够轻松变成其他程序的入口。
在短信的时代,逢年过节都会需要接收和发送大量的短信。
虽然自己也看到短信就烦,但不发又怕会错过什么。
所以当时就产生了各式各样的群发工具,最简单的比如在消息中加入昵称,让人感觉不像群发。
不过可惜的是,微信自带的群发助手真的只是群发。
当然,稍加操作,一切皆有可能。
例如在消息中加入昵称:
* 通过get_friends方法可以轻松获取所有的好友(好友首位是自己)
* 基于不同的好友可以发送不同的消息
* 这条程序运行后是真的会发消息出去,如果只是演示目的,把itchat.send改为print即可
import itchat, time
itchat.auto_login(True)
SINCERE_WISH = u'祝%s新年快乐!'
friendList = itchat.get_friends(update=True)[1:]
for friend in friendList:
itchat.send(SINCERE_WISH % (friend['DisplayName']
or friend['NickName']), friend['UserName'])
time.sleep(.5)
又例如给特定的人发送特定的消息。
我们这里通过群聊实现,划定一个群聊,在群聊内则私信发送祝福。
* 如果仅是创建群聊不说话,对方是不会有提示的
* 群聊如果不保存到通讯录,是无法在各设备之间同步的(所以itchat也无法读取到)
* 群聊在被获取的时候不会自带用户列表,所以需要使用update_chatroom更新用户列表
* 当然,如果只是演示目的,把itchat.send改为print即可
import itchat, time
itchat.auto_login(True)
REAL_SINCERE_WISH = u'祝%s新年快乐!!'
chatroomName='wishgroup'
itchat.get_chatrooms(update=True)
chatrooms = itchat.search_chatrooms(name=chatroomName)
if chatrooms is None:
print(u'没有找到群聊:' + chatroomName)
chatroom = itchat.update_chatroom(chatrooms[0]['UserName'])
for friend in chatroom['MemberList']:
friend = itchat.search_friends(userName=friend['UserName'])
itchat.send(REAL_SINCERE_WISH % (friend['DisplayName']
or friend['NickName']), friend['UserName'])
time.sleep(.5)
所以我的通讯录里会有从来不用的客户群、教师群什么的。
完整的程序我放在了上面,使用时不要忘记安装第三方包。
当然,为了防止误操作,完整程序中我把所有的itchat.send换成了print。
另外,不只有文字可以发送,文件、图片也都是可行的,具体操作见itchat的了。
itchat获取微信可以获取到的各种内容也都非常方便。
其余的例如生日,节日什么的就看具体需求了。
好友删除检测
有时候我们会想知道某个好友有没有删除自己或者把自己拉入黑名单。
这一操作使用itchat也会变的非常简单。
原理的话,在于将好友拉入群聊时,非好友和黑名单好友不会被拉入群聊。
所以群聊的返回值中就有了好友与你关系的数据。
另外,群聊在第一次产生普通消息时才会被除创建者以外的人发现的(系统消息不算普通消息)。
这样,就可以隐蔽的完成好友检测。
写成代码的话,这个操作就是这样的:(只是演示,不能运行,运行版本在段末)
chatroomUserName = '@1234567'
friend = itchat.get_friends()[1]
r = itchat.add_member_into_chatroom(chatroomUserName, [friend])
if r['BaseResponse']['ErrMsg'] == '':
status = r['MemberList'][0]['MemberStatus']
itchat.delete_member_from_chatroom(chatroom['UserName'], [friend])
return { 3: u'该好友已经将你加入黑名单。',
4: u'该好友已经将你删除。', }.get(status,
u'该好友仍旧与你是好友关系。')
其中,通过add_member_into_chatroom操作获取我们需要的返回值,即可得到好友的状态。
同样的,这次我们也将文件传输助手作为终端,具体方法与控制器一节类似。
这次我们确定的交互方式是接收“名片”消息,并判断名片中的好友与自己的关系。
那么获取名片信息的内容可以这么写:
import itchat
@itchat.msg_register(itchat.content.CARD)
def get_friend(msg):
if msg['ToUserName'] != 'filehelper': return
friendStatus = get_friend_status(msg['RecommendInfo'])
itchat.send(friendStatus['NickName'], 'filehelper')
itchat.auto_login(True)
itchat.run()
那么我们所需要的所有部分就都解决了,下面将他们组合起来即可。
完整的程序我放在了上面,使用时不要忘记安装第三方包。
在网页版微信的接口受到限制之前完全可以批量进行这一操作,检测哪些好友删除了自己。
但目前显然操作存在频率限制,所以只能做一些变通了。
之后的内容
到这里这一篇文章的主要内容就结束了。
主要从微信作为终端使用、自定义的消息交互、微信协议研究三方面开了一个简单的头。
其余有一些过于大众,如机器人,就不再赘述。
而另一些,需要一定的基础或者不适合分享,就留给各位自行研究。
如果要留个悬念,可以想象添加好友的方法status传2,轻松实现好友病毒式扩张。
利用微信的API可以做很多事情,文档我放在,祝好运!
希望读完这篇文章能对你有帮助,有什么不足之处万望指正(鞠躬)。
有什么想法或者想要关注我的更新,欢迎来上Star或者Fork。
LittleCoder
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:17756次
排名:千里之外
原创:13篇
(1)(1)(1)(1)(1)(1)(7)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'手把手教你扩展个人微信号(1) - Python - 伯乐在线
& 手把手教你扩展个人微信号(1)
现在的日常生活已经离不开微信,难免会生出微信有没有什么API可以使用的想法。那样就可以拿自己微信做个消息聚合、开个投票什么的,可是显然没有这种东西。不过还好,有网页版微信不就等于有了API么,这个项目就是出于这个想法出现的。
看完这一系列教程,你就能从头开始实现自己关于微信以及类似工具的想法,例如一个。
当然,如果你只对使用微信的API感兴趣,可以直接跳到下一篇教程,直接使用我已经完成的。
本文为该教程的第一部分,主要讲述抓包与伪造,将会以最简单的方法介绍使用Python模拟登陆抓取数据等内容。
Python与基本的网络基础都不困难,所以即使没有这方面基础辅助搜索引擎也完全可以学习本教程。
教程流程简介
教程将会从如何分析微信协议开始,第一部分将教你如何从零开始获取并模拟扩展个人微信号所需要的协议。
第二部分将会就这些协议进行利用,以微信机器人为例介绍我给出的项目基本框架与存储、任务识别等功能。
第三部分就项目基本框架开发插件,以消息聚合等功能为例对框架做进一步介绍与扩展。
简单成果展示:
目前的样例微信号被扩展为了能够完成信息上传下载的机器人,用于展示信息交互功能。
其支持文件、图片、语音的上传下载、投票等功能,可以尝试使用。
本部分所需环境
本文是这一教程的第一部分,需要配置抓包与Python环境。
本教程使用的环境如下:
Windows 8.1
Python 2.7.11 (安装Image, requests)
Wireshark 2.0.2
微信版本6.3.15
Wireshark配置
Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页端的流量。
由于微信网页端使用https,需要特殊的配置才能看到有意义的内容,具体的配置见。
配置完成以后开始抓包,载入后若能看到http请求则配置成功。
分析并模拟扫码,并获取登录状态
微信网页端登陆分为很多步,这里以第一步扫码为例讲解如何从抓包开始完成模拟。
在抓包以前,我们需要先想清楚这是一个什么样的过程。
我们都登录过网页端微信,没有的话可以现在做一个尝试:。
这个过程简单而言可以分为如下几步:
向服务器提供一些用于获取二维码的数据
服务器返回二维码
向服务器询问二维码扫描状态
服务器返回扫描状态
有了这些概念以后就可以开始将这四步和包对应起来。
对应过程与实际的包
开启wireshark抓包后登陆网页端微信,完成扫码登陆,然后关闭wireshark抓包。
筛选http请求(就是菜单栏下面输入的那个http),可以看到这样的界面。
这里需要讲的就是第一列“No.”列的数字就是后文说的几号包,例如第一行就是30号包。数据包的类型则在Info列中可以看到,是GET,POST或是别的请求。
那么我们可以开始分析抓到的包了,我们先粗略的浏览一下数据包。
第325号包引起了我的注意,因为登陆过程当中非常有特征的一个过程是二维码的获取,所以我们尝试打开这一数据包的图片的内容。
325号包是由292号包的请求获取的,292号包又是一个普通的get请求,所以我们尝试直接在浏览器中访问这一网址。(访问自己抓到的网址)
具体的网址通过双击打开292号包即可找到。如需要可以点击看图。
我们发现直接在浏览器中获取了一张二维码,所以这很有可能就是上述一、二步的过程了。
那么我们是向服务器提供了哪些数据获取了二维码呢?
每次我们登录的二维码会变化,且没有随二维码传回的标识,所以我们肯定提供了每次不同的信息
网址中最后一部分看起来比较像标识:https://login./qrcode/4ZtmDT6OPg==
为了进一步验证猜想,再次抓包,发现类似292号包的请求url仅最后一部分存在区别
所以我们提供了4ZtmDT6Opg==获取到了这一二维码。
那么这一标识是随机生成的还是服务器获取的呢?
从最近的包开始分析服务器传回的数据(Source是服务器地址的数据),发现就在上一行,286号包有我们感兴趣的数据。
打开这个包,可以看到其返回的数据为window.QRLogin.code = 200; window.QRLogin.uuid = "4ZtmDT6OPg==";(见下方截图)
显然导致服务器返回这一请求的284号包就是我们获取标识(下称uuid)所需要伪造的包。
那么284号包需要传递给服务器哪些数据?
这是一个get请求,所以我们分析其请求的url:https://login./jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=en_US&_=8。
可以发现需要给出五个量appid, redirect_uri, fun, lang, _。
其中除了appid其余都显然是固定的量(_的格式显然为时间戳)。
然而搜索284号包之前的包也没有发现这一数值的来源,所以暂且认为其也是固定的量,模拟时如果出现问题再做尝试。
到了这里,1,2步的过程我们已经能够对应上相应的包了。
3,4部的最显著特征是在扫描成功以后会获取扫描用的微信号的头像。
我们还是首先大致的浏览一下服务器返回的数据包,试图找到包含图片的数据包。
从325号包(微信头像肯定在二维码之后获取)开始浏览。
我们发现338号包中包含一个base64加密的图片,后可以看到自己的头像。
所以这个数据包就是服务器返回的扫描成功的数据包了,而前面那部分window.code=201显然就是表示状态的代码。(见下方截图)
经过尝试与再次抓包,我们理解状态码的涵义:200:登陆成功 201:扫描成功 408:图片过期
那么第四部我们已经能够完全的理解
我们很容易的找到了在登录过程当中不断出现的请求,那么要怎么模拟呢?
首先这是一个简单的get请求,url为:https://login./cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=4ZtmDT6OPg==&tip=1&r=-&_=9
可以发现需要给出五个量loginicon, uuid, tip, r, _
通过多次抓包发现除了r以外都可以找到简单的规律,那么r的规律等待模拟时再尝试处理
至此你应该已经能将四个过程全部与具体的数据包对应。为了避免有遗漏的过程,我们将没有使用到的与服务器交互的数据包标识出来(右键Mark)。经过简单的浏览,认为其中并没有必须的数据包交互。但值得注意的是,如果之后模拟数据包没有问题却无法登陆的话应当再回到这些数据包中搜寻。
这里做一个简单的小结,这一部分简单的介绍了分析数据包的基本思路,以及一些小的技巧。当然这些仅供参考,在具体的抓包中完全可以根据具体的交互过程自由发挥。而目前留下来的问题有:第一步时的appid与第三步时的r,留待模拟时在做研究。
使用Python模拟扫码
这一部分我们使用python的requests模块,可以通过pip install requests安装。
我们先来简单的讲述一下这个包。
import requests
# 新建一个session对象(就像开了一个浏览器一样)
session = requests.Session()
# 使用get方法获取/s?wd=python
url = '/s'
params = { 'wd': 'python', }
r = session.get(url = url, params = params)
with open('baidu.htm') as f: f.write(r.content) # 存入文件,可以使用浏览器尝试打开
# 举例使用post方法
import json
data = { 'wd': 'python', }
r = session.get(url = url, data = json.dumps(data))
with open('baidu.htm') as f: f.write(r.content)
# 以上代码与下面的代码不连续
123456789101112131415
import requests# 新建一个session对象(就像开了一个浏览器一样)session = requests.Session()# 使用get方法获取/s?wd=pythonurl = '/s'params = { 'wd': 'python', }r = session.get(url = url, params = params)with open('baidu.htm') as f: f.write(r.content) # 存入文件,可以使用浏览器尝试打开# 举例使用post方法import jsonurl = ''data = { 'wd': 'python', }r = session.get(url = url, data = json.dumps(data))with open('baidu.htm') as f: f.write(r.content)# 以上代码与下面的代码不连续
如果想要更多的了解这个包,可以浏览。
你可以尝试获取一个你熟悉的网站来测试使用requests,在测试时可以打开抓包,查看你发送的数据包与想要发送的数据包是否一样。
那么我们开始模拟第一、二个过程,向服务器提供一些用于获取二维码的数据,服务器返回二维码。
向服务器提交284,292号包
从服务器返回数据中提取出uuid与二维码图片
我们需要模拟的地址为:https://login./jslogin?appid=wx782c26e4c19acffb&redirecturi=https%3A%2F%%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=en_US&=8 ,所以我们模拟的代码如下:
#coding=utf8
import time, requests
session = requests.Session()
url = 'https://login./jslogin'
params = {
'appid': 'wx782c26e4c19acffb',
'redirect_uri': '/cgi-bin/mmwebwx-bin/webwxnewloginpage',
'fun': 'new',
'lang': 'en_US',
'_': int(time.time()),
r = session.get(url, params = params)
print('Content: %s'%r.text)
12345678910111213
#coding=utf8import time, requestssession = requests.Session()url = 'https://login./jslogin'params = {&&&&'appid': 'wx782c26e4c19acffb',&&&&'redirect_uri': '/cgi-bin/mmwebwx-bin/webwxnewloginpage',&&&&'fun': 'new',&&&&'lang': 'en_US',&&&&'_': int(time.time()),&&&&}r = session.get(url, params = params)print('Content: %s'%r.text)
当然,将模拟的地址全部写在url里面效果完全一样。
值得一提的是requests会帮我们自动urlencode,如果不需要urlencode(/变为了%2F)可以将所有内容都写在url里面。
提取出uuid
这里使用re,如果不了解正则表达式的话可以直接拿来用,毕竟和这一个教程并不相关。
# 上接上一段程序
regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'
# 我们可以看到返回的量是上述的格式,括号内的内容被提取了出来
data = re.search(regx, r.text)
if data and data.group(1) == '200': uuid = data.group(2)
print('uuid: %s'%uuid)
# 上接上一段程序import reregx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'# 我们可以看到返回的量是上述的格式,括号内的内容被提取了出来data = re.search(regx, r.text)if data and data.group(1) == '200': uuid = data.group(2)print('uuid: %s'%uuid)
如果没能成功获取到uuid可以尝试再运行一次。
我们需要模拟的url为:https://login./qrcode/4ZtmDT6OPg== ,所以我们模拟的代码如下:
# 上接上一段程序
regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'
# 我们可以看到返回的量是上述的格式,括号内的内容被提取了出来
data = re.search(regx, r.text)
if data and data.group(1) == '200': uuid = data.group(2)
print('uuid: %s'%uuid)
# 上接上一段程序import reregx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'# 我们可以看到返回的量是上述的格式,括号内的内容被提取了出来data = re.search(regx, r.text)if data and data.group(1) == '200': uuid = data.group(2)print('uuid: %s'%uuid)
由于我们需要获取图像,所以需要以二进制数据流的形式获取服务器返回的数据包,所以增加stream = True。
而将二进制数据流写入也需要在打开文件时设定二进制写入,即open('QRCode.jpg', 'wb')。
当然,如果获取失败可以再运行一次。
同理的三、四步也可以按照这个方法写出,这里就不再赘述,只给出代码。
而经过测试我们发现,第一步时的appid实际是一个固定的量,第三步时的r甚至不输入也可以登录。
# 上接上一段程序
url = 'https://login./qrcode/' + uuid
r = session.get(url, stream = True)
with open('QRCode.jpg', 'wb') as f: f.write(r.content)
# 现在你可以在你存储代码的位置发现一张存下来的图片,用下面的代码打开它
import platform, os, subprocess
if platform.system() == 'Darwin':
subprocess.call(['open', 'QRCode.jpg'])
elif platform.system() == 'Linux':
subprocess.call(['xdg-open', 'QRCode.jpg'])
os.startfile('QR.jpg')
123456789101112
# 上接上一段程序url = 'https://login./qrcode/' + uuidr = session.get(url, stream = True)with open('QRCode.jpg', 'wb') as f: f.write(r.content)# 现在你可以在你存储代码的位置发现一张存下来的图片,用下面的代码打开它import platform, os, subprocessif platform.system() == 'Darwin':&&&&subprocess.call(['open', 'QRCode.jpg'])elif platform.system() == 'Linux':&&&&subprocess.call(['xdg-open', 'QRCode.jpg'])else:&&&&os.startfile('QR.jpg')
当你看到Login successfully时,说明至此我们已经成功从零开始,通过抓包分析,用python成功模拟了python登陆。
不过是不是看上去没有什么反馈呢?那是因为我们还没有模拟会产生反馈的包,但其实差的只是研究发文字、发图片什么的包了。
为了体现我们已经登陆了,加上后面这段代码就可以看到登陆的账号信息:
# 上接上一段代码
import xml.dom.minidom
def get_login_info(s):
baseRequest = {}
for node in xml.dom.minidom.parseString(s).documentElement.childNodes:
if node.nodeName == 'skey':
baseRequest['Skey'] = node.childNodes[0].data.encode('utf8')
elif node.nodeName == 'wxsid':
baseRequest['Sid'] = node.childNodes[0].data.encode('utf8')
elif node.nodeName == 'wxuin':
baseRequest['Uin'] = node.childNodes[0].data.encode('utf8')
elif node.nodeName == 'pass_ticket':
baseRequest['DeviceID'] = node.childNodes[0].data.encode('utf8')
return baseRequest
baseRequest = get_login_info(baseRequestText)
url = '%s/webwxinit?r=%s' % (redirectUri, int(time.time()))
'BaseRequest': baseRequest,
headers = { 'ContentType': 'application/ charset=UTF-8' }
r = session.post(url, data = json.dumps(data), headers = headers)
dic = json.loads(r.content.decode('utf-8', 'replace'))
print('Log in as %s'%dic['User']['NickName'])
12345678910111213141516171819202122232425
# 上接上一段代码import xml.dom.minidomdef get_login_info(s):&&&&baseRequest = {}&&&&for node in xml.dom.minidom.parseString(s).documentElement.childNodes:&&&&&&&&if node.nodeName == 'skey':&&&&&&&&&&&&baseRequest['Skey'] = node.childNodes[0].data.encode('utf8')&&&&&&&&elif node.nodeName == 'wxsid':&&&&&&&&&&&&baseRequest['Sid'] = node.childNodes[0].data.encode('utf8')&&&&&&&&elif node.nodeName == 'wxuin':&&&&&&&&&&&&baseRequest['Uin'] = node.childNodes[0].data.encode('utf8')&&&&&&&&elif node.nodeName == 'pass_ticket':&&&&&&&&&&&&baseRequest['DeviceID'] = node.childNodes[0].data.encode('utf8')&&&&return baseRequestbaseRequest = get_login_info(baseRequestText)&url = '%s/webwxinit?r=%s' % (redirectUri, int(time.time()))data = {&&&&'BaseRequest': baseRequest,}headers = { 'ContentType': 'application/ charset=UTF-8' }r = session.post(url, data = json.dumps(data), headers = headers)dic = json.loads(r.content.decode('utf-8', 'replace'))&print('Log in as %s'%dic['User']['NickName'])
这里做一个简单的小结:
模拟数据包总体而言是以寻找未知的必须数据为线索,辅助一些技巧,串联起整个过程。
首先需要用python初始化一个session,否则登录过程的存储将会比较麻烦。
模拟数据包的时候首先区分get与post请求,对应session的get与post方法。
get的数据为url后半部分的内容,post是数据包最后一部分的内容。
get方法中传入数据的标示为params, post方法中传入数据的标示为data。
session的get,post方法返回一个量,可以通过r.text自动编码显示。
存储图片有特殊的方式与配置。
到现在为止我展示了一个完整的抓包、分析、模拟的过程完成了模拟登陆,其他一些事情其实也都是类似的过程,想清楚每一步要做些什么即可。
这里用到的软件都只介绍了最简单的一些方法,进一步的内容这里给出一些建议:
wireshark可以直接浏览官方文档,有空可以做一个了解。
requests包的使用通过搜索引擎即可,特殊的功能建议直接阅读源码。
那么做一个小练习好了,测试一下学到的东西:读取命令行的输入并发送给自己。(这部分的源码放在了文末)
在分析包的过程中记得抓好位置的必要数据这个线索,练习之前提到过的一些技巧。
把大的过程拆分成一个一个小的任务可能会让分析简单很多。
如果发现登录过程意料之外的断了,分析不出原因,可以尝试多抓几次包再比较分析。
具体运用时可能遇到的难点
命令行登录一段时间后无法与服务器正常交互
这是因为微信网页端存在心跳机制,一段时间不交互将会断开连接。
另外,每次获取数据时(webwxsync)记得更新SyncKey。
某个特定请求不知道如何模拟
在项目中已经模拟好了几乎所有的请求,你可以通过参考我的方法与数据包。
如果之后微信网页版出现更新我会在本项目中及时更新。
项目中的微信网页端接口见
无法上传中文文件名的文件与图片
这是因为使用requests包会自动将中文文件名编码为服务器端无法识别的格式,所以需要修改requests包或者使用别的方法上传文件。
最简单的方法即将requests包的packages/urlib3中的fields.py中的format_header_param方法改为如下内容:
def format_header_param(name, value):
if not any(ch in value for ch in '"\\\r\n'):
result = '%s="%s"' % (name, value)
result.encode('ascii')
except UnicodeEncodeError:
return result
if not six.PY3:
# Python 2:
value = value.encode('utf-8')
value = email.utils.encode_rfc2231(value, 'utf-8')
value = '%s="%s"' % (name, value.decode('utf8'))
return value
1234567891011121314
def format_header_param(name, value):&&&&if not any(ch in value for ch in '"\\\r\n'):&&&&&&&&result = '%s="%s"' % (name, value)&&&&&&&&try:&&&&&&&&&&&&result.encode('ascii')&&&&&&&&except UnicodeEncodeError:&&&&&&&&&&&&pass&&&&&&&&else:&&&&&&&&&&&&return result&&&&if not six.PY3:&&# Python 2:&&&&&&&&value = value.encode('utf-8')&&&&value = email.utils.encode_rfc2231(value, 'utf-8')&&&&value = '%s="%s"' % (name, value.decode('utf8'))&&&&return value
登录时出现不安全的提示
建议更新Python版本至2.7.11
小练习答案
源码可在该地址下载:
希望读完这篇文章能对你有帮助,有什么不足之处万望指正(鞠躬)。
有什么想法或者想要关注我的更新,欢迎来上Star或者Fork。
打赏支持我写出更多好文章,谢谢!
打赏支持我写出更多好文章,谢谢!
关于作者:
可能感兴趣的话题
o 256 回复
关于 Python 频道
Python频道分享 Python 开发技术、相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线

我要回帖

更多关于 微信公众号能授权几个 的文章

 

随机推荐