提交 35277aaf 编写于 作者: L LittleCoder

Find a better looking way of showing docs

上级 89b1acdf
......@@ -234,12 +234,14 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f
[Chyroc][Chyroc]: 完成第一版本的Python3构架。
## 参考资料
## 类似项目
[liuwons/wxBot][liuwons-wxBot]: 类似的基于Python的微信机器人
[zixia/wechaty][zixia-wechaty]: 基于Javascript(ES6)的微信个人账号机器人NodeJS框架/库
[sjdy521/Mojo-Weixin][Mojo-Weixin]: 使用Perl语言编写的微信客户端框架,可通过插件提供基于HTTP协议的api接口供其他语言调用
## 问题和建议
如果有什么问题或者建议都可以在这个[Issue][issue#1]和我讨论
......@@ -266,4 +268,5 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f
[Chyroc]: https://github.com/Chyroc
[liuwons-wxBot]: https://github.com/liuwons/wxBot
[zixia-wechaty]: https://github.com/zixia/wechaty
[Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin
[issue#1]: https://github.com/littlecodersh/ItChat/issues/1
......@@ -238,7 +238,9 @@ A: Some account simply can't send messages to yourself, so use `filehelper` inst
[liuwons/wxBot][liuwons-wxBot]: A wechat robot similiar to the robot branch
[zixia/wechaty][zixia-wechaty]: wechat for bot in Javascript(ES6), Personal Account Robot Framework/Library.
[zixia/wechaty][zixia-wechaty]: wechat for bot in Javascript(ES6), Personal Account Robot Framework/Library
[sjdy521/Mojo-Weixin][Mojo-Weixin]: wechat web api in Perl, available with HTTP requests
## Comments
......@@ -263,4 +265,5 @@ Or you may also use [![Gitter][gitter-picture]][gitter]
[Chyroc]: https://github.com/Chyroc
[liuwons-wxBot]: https://github.com/liuwons/wxBot
[zixia-wechaty]: https://github.com/zixia/wechaty
[Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin
[issue#1]: https://github.com/littlecodersh/ItChat/issues/1
## 稳定性
Q: itchat稳定性如何?
A: 测试用机器人能稳定在线多个月。如果你在测试过程中发现无法稳定登陆,请检查**登陆手机**及主机是否稳定连接网络。
## 中文文件名文件上传
Q: 为什么中文的文件没有办法上传?
A: 这是由于`requests`的编码问题导致的。若需要支持中文文件传输,将[fields.py][fields.py-2](py3版本见[这里][fields.py-3])文件放入requests包的packages/urllib3下即可
## 命令行显示二维码
Q: 为什么我在设定了`itchat.auto_login()``enableCmdQR``True`后还是没有办法在命令行显示二维码?
A: 这是由于没有安装可选的包`pillow`,可以使用右边的命令安装:`pip install pillow`
## 如何通过itchat实现控制器
Q: 如何通过这个包将自己的微信号变为控制器?
A: 有两种方式:发送、接受自己UserName的消息;发送接收文件传输助手(filehelper)的消息
Q: 如何保持itchat长时间稳定登陆?
## 无法给自己发送消息
Q: 为什么我发送信息的时候部分信息没有成功发出来?
A: 有些账号是天生无法给自己的账号发送信息的,建议使用`filehelper`代替。
A: 目前建议使用IOS客户端扫码登陆并保持网络稳定。
[fields.py-2]: https://gist.github.com/littlecodersh/9a0c5466f442d67d910f877744011705
[fields.py-3]: https://gist.github.com/littlecodersh/e93532d5e7ddf0ec56c336499165c4dc
# API 列表
目前API列表暂时没有翻译的版本:
最新的API列表可以见core.py。
```python
def login(self, enableCmdQR=False, picDir=None, qrCallback=None,
loginCallback=None, exitCallback=None):
''' log in like web wechat does
for log in
- a QR code will be downloaded and opened
- then scanning status is logged, it paused for you confirm
- finally it logged in and show your nickName
for options
- enableCmdQR: show qrcode in command line
- integers can be used to fit strange char length
- picDir: place for storing qrcode
- qrCallback: method that should accept uuid, status, qrcode
- loginCallback: callback after successfully logged in
- if not set, screen is cleared and qrcode is deleted
- exitCallback: callback after logged out
- it contains calling of logout
for usage
..code::python
import itchat
itchat.login()
it is defined in components/login.py
and of course every single move in login can be called outside
- you may scan source code to see how
- and modified according to your own demond
'''
raise NotImplementedError()
def get_QRuuid(self):
''' get uuid for qrcode
uuid is the symbol of qrcode
- for logging in, you need to get a uuid first
- for downloading qrcode, you need to pass uuid to it
- for checking login status, uuid is also required
if uuid has timed out, just get another
it is defined in components/login.py
'''
raise NotImplementedError()
def get_QR(self, uuid=None, enableCmdQR=False, picDir=None, qrCallback=None):
''' download and show qrcode
for options
- uuid: if uuid is not set, latest uuid you fetched will be used
- enableCmdQR: show qrcode in cmd
- picDir: where to store qrcode
- qrCallback: method that should accept uuid, status, qrcode
it is defined in components/login.py
'''
raise NotImplementedError()
def check_login(self, uuid=None):
''' check login status
for options:
- uuid: if uuid is not set, latest uuid you fetched will be used
for return values:
- a string will be returned
- for meaning of return values
- 200: log in successfully
- 201: waiting for press confirm
- 408: uuid timed out
- 0 : unknown error
for processing:
- syncUrl and fileUrl is set
- BaseRequest is set
blocks until reaches any of above status
it is defined in components/login.py
'''
raise NotImplementedError()
def web_init(self):
''' get info necessary for initializing
for processing:
- own account info is set
- inviteStartCount is set
- syncKey is set
- part of contact is fetched
it is defined in components/login.py
'''
raise NotImplementedError()
def show_mobile_login(self):
''' show web wechat login sign
the sign is on the top of mobile phone wechat
sign will be added after sometime even without calling this function
it is defined in components/login.py
'''
raise NotImplementedError()
def start_receiving(self, finishCallback=None):
''' open a thread for heart loop and receiving messages
for options:
- finishCallback: callback after logged out
- it contains calling of logout
for processing:
- messages: msgs are formatted and passed on to registered fns
- contact : chatrooms are updated when related info is received
it is defined in components/login.py
'''
raise NotImplementedError()
def get_msg(self):
''' fetch messages
for fetching
- method blocks for sometime util
- new messages are to be received
- or anytime they like
- synckey is updated with returned synccheckkey
it is defined in components/login.py
'''
raise NotImplementedError()
def logout(self):
''' logout
if core is now alive
logout will tell wechat backstage to logout
and core gets ready for another login
it is defined in components/login.py
'''
raise NotImplementedError()
def update_chatroom(self, userName, detailedMember=False):
''' update chatroom
for chatroom contact
- a chatroom contact need updating to be detailed
- detailed means members, encryid, etc
- auto updating of heart loop is a more detailed updating
- member uin will also be filled
- once called, updated info will be stored
for options
- userName: 'UserName' key of chatroom or a list of it
- detailedMember: whether to get members of contact
it is defined in components/contact.py
'''
raise NotImplementedError()
def update_friend(self, userName):
''' update chatroom
for friend contact
- once called, updated info will be stored
for options
- userName: 'UserName' key of a friend or a list of it
it is defined in components/contact.py
'''
raise NotImplementedError()
def get_contact(self, update=False):
''' fetch part of contact
for part
- all the massive platforms and friends are fetched
- if update, only starred chatrooms are fetched
for options
- update: if not set, local value will be returned
for results
- chatroomList will be returned
it is defined in components/contact.py
'''
raise NotImplementedError()
def get_friends(self, update=False):
''' fetch friends list
for options
- update: if not set, local value will be returned
for results
- a list of friends' info dicts will be returned
it is defined in components/contact.py
'''
raise NotImplementedError()
def get_chatrooms(self, update=False, contactOnly=False):
''' fetch chatrooms list
for options
- update: if not set, local value will be returned
- contactOnly: if set, only starred chatrooms will be returned
for results
- a list of chatrooms' info dicts will be returned
it is defined in components/contact.py
'''
raise NotImplementedError()
def get_mps(self, update=False):
''' fetch massive platforms list
for options
- update: if not set, local value will be returned
for results
- a list of platforms' info dicts will be returned
it is defined in components/contact.py
'''
raise NotImplementedError()
def set_alias(self, userName, alias):
''' set alias for a friend
for options
- userName: 'UserName' key of info dict
- alias: new alias
it is defined in components/contact.py
'''
raise NotImplementedError()
def set_pinned(self, userName, isPinned=True):
''' set pinned for a friend or a chatroom
for options
- userName: 'UserName' key of info dict
- isPinned: whether to pin
it is defined in components/contact.py
'''
raise NotImplementedError()
def add_friend(self, userName, status=2, verifyContent='', autoUpdate=True):
''' add a friend or accept a friend
for options
- userName: 'UserName' for friend's info dict
- status:
- for adding status should be 2
- for accepting status should be 3
- ticket: greeting message
- userInfo: friend's other info for adding into local storage
it is defined in components/contact.py
'''
raise NotImplementedError()
def get_head_img(self, userName=None, chatroomUserName=None, picDir=None):
''' place for docs
for options
- if you want to get chatroom header: only set chatroomUserName
- if you want to get friend header: only set userName
- if you want to get chatroom member header: set both
it is defined in components/contact.py
'''
raise NotImplementedError()
def create_chatroom(self, memberList, topic=''):
''' create a chatroom
for creating
- its calling frequency is strictly limited
for options
- memberList: list of member info dict
- topic: topic of new chatroom
it is defined in components/contact.py
'''
raise NotImplementedError()
def set_chatroom_name(self, chatroomUserName, name):
''' set chatroom name
for setting
- it makes an updating of chatroom
- which means detailed info will be returned in heart loop
for options
- chatroomUserName: 'UserName' key of chatroom info dict
- name: new chatroom name
it is defined in components/contact.py
'''
raise NotImplementedError()
def delete_member_from_chatroom(self, chatroomUserName, memberList):
''' deletes members from chatroom
for deleting
- you can't delete yourself
- if so, no one will be deleted
- strict-limited frequency
for options
- chatroomUserName: 'UserName' key of chatroom info dict
- memberList: list of members' info dict
it is defined in components/contact.py
'''
raise NotImplementedError()
def add_member_into_chatroom(self, chatroomUserName, memberList,
useInvitation=False):
''' add members into chatroom
for adding
- you can't add yourself or member already in chatroom
- if so, no one will be added
- if member will over 40 after adding, invitation must be used
- strict-limited frequency
for options
- chatroomUserName: 'UserName' key of chatroom info dict
- memberList: list of members' info dict
- useInvitation: if invitation is not required, set this to use
it is defined in components/contact.py
'''
raise NotImplementedError()
def send_raw_msg(self, msgType, content, toUserName):
''' many messages are sent in a common way
for demo
.. code:: python
@itchat.msg_register(itchat.content.CARD)
def reply(msg):
itchat.send_raw_msg(msg['MsgType'], msg['Content'], msg['FromUserName'])
there are some little tricks here, you may discover them yourself
but remember they are tricks
it is defined in components/messages.py
'''
raise NotImplementedError()
def send_msg(self, msg='Test Message', toUserName=None):
''' send plain text message
for options
- msg: should be unicode if there's non-ascii words in msg
- toUserName: 'UserName' key of friend dict
it is defined in components/messages.py
'''
raise NotImplementedError()
def upload_file(self, fileDir, isPicture=False, isVideo=False):
''' upload file to server and get mediaId
for options
- fileDir: dir for file ready for upload
- isPicture: whether file is a picture
- isVideo: whether file is a video
for return values
will return a ReturnValue
if succeeded, mediaId is in r['MediaId']
it is defined in components/messages.py
'''
raise NotImplementedError()
def send_file(self, fileDir, toUserName=None, mediaId=None):
''' send attachment
for options
- fileDir: dir for file ready for upload
- mediaId: mediaId for file.
- if set, file will not be uploaded twice
- toUserName: 'UserName' key of friend dict
it is defined in components/messages.py
'''
raise NotImplementedError()
def send_image(self, fileDir, toUserName=None, mediaId=None):
''' send image
for options
- fileDir: dir for file ready for upload
- if it's a gif, name it like 'xx.gif'
- mediaId: mediaId for file.
- if set, file will not be uploaded twice
- toUserName: 'UserName' key of friend dict
it is defined in components/messages.py
'''
raise NotImplementedError()
def send_video(self, fileDir=None, toUserName=None, mediaId=None):
''' send video
for options
- fileDir: dir for file ready for upload
- if mediaId is set, it's unnecessary to set fileDir
- mediaId: mediaId for file.
- if set, file will not be uploaded twice
- toUserName: 'UserName' key of friend dict
it is defined in components/messages.py
'''
raise NotImplementedError()
def send(self, msg, toUserName=None, mediaId=None):
''' wrapped function for all the sending functions
for options
- msg: message starts with different string indicates different type
- list of type string: ['@fil@', '@img@', '@msg@', '@vid@']
- they are for file, image, plain text, video
- if none of them matches, it will be sent like plain text
- toUserName: 'UserName' key of friend dict
- mediaId: if set, uploading will not be repeated
it is defined in components/messages.py
'''
raise NotImplementedError()
def dump_login_status(self, fileDir=None):
''' dump login status to a specific file
for option
- fileDir: dir for dumping login status
it is defined in components/hotreload.py
'''
raise NotImplementedError()
def load_login_status(self, fileDir,
loginCallback=None, exitCallback=None):
''' load login status from a specific file
for option
- fileDir: file for loading login status
- loginCallback: callback after successfully logged in
- if not set, screen is cleared and qrcode is deleted
- exitCallback: callback after logged out
- it contains calling of logout
it is defined in components/hotreload.py
'''
raise NotImplementedError()
def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
enableCmdQR=False, picDir=None, qrCallback=None,
loginCallback=None, exitCallback=None):
''' log in like web wechat does
for log in
- a QR code will be downloaded and opened
- then scanning status is logged, it paused for you confirm
- finally it logged in and show your nickName
for options
- hotReload: enable hot reload
- statusStorageDir: dir for storing log in status
- enableCmdQR: show qrcode in command line
- integers can be used to fit strange char length
- picDir: place for storing qrcode
- loginCallback: callback after successfully logged in
- if not set, screen is cleared and qrcode is deleted
- exitCallback: callback after logged out
- it contains calling of logout
- qrCallback: method that should accept uuid, status, qrcode
for usage
..code::python
import itchat
itchat.auto_login()
it is defined in components/register.py
and of course every single move in login can be called outside
- you may scan source code to see how
- and modified according to your own demond
'''
raise NotImplementedError()
def configured_reply(self):
''' determine the type of message and reply if its method is defined
however, I use a strange way to determine whether a msg is from massive platform
I haven't found a better solution here
The main problem I'm worrying about is the mismatching of new friends added on phone
If you have any good idea, pleeeease report an issue. I will be more than grateful.
'''
raise NotImplementedError()
def msg_register(self, msgType,
isFriendChat=False, isGroupChat=False, isMpChat=False):
''' a decorator constructor
return a specific decorator based on information given
'''
raise NotImplementedError()
def run(self, debug=True):
''' start auto respond
for option
- debug: if set, debug info will be shown on screen
it is defined in components/register.py
'''
raise NotImplementedError()
def search_friends(self, name=None, userName=None, remarkName=None, nickName=None,
wechatAccount=None):
return self.storageClass.search_friends(name, userName, remarkName,
nickName, wechatAccount)
def search_chatrooms(self, name=None, userName=None):
return self.storageClass.search_chatrooms(name, userName)
def search_mps(self, name=None, userName=None):
return self.storageClass.search_mps(name, userName)
```
<!DOCTYPE html>
<html lang="en">
<head>
{%- block site_meta %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% if config.site_description %}<meta name="description" content="{{ config.site_description }}">{% endif %}
{% if config.site_author %}<meta name="author" content="{{ config.site_author }}">{% endif %}
{% if page.canonical_url %}<link rel="canonical" href="{{ page.canonical_url }}">{% endif %}
<link rel="shortcut icon" href="{{ base_url }}/img/favicon.ico">
{%- endblock %}
{%- block htmltitle %}
<title>{% if page and page.title %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
{%- endblock %}
{%- block styles %}
<link href="{{ base_url }}/css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link href="{{ base_url }}/css/font-awesome-4.0.3.css" rel="stylesheet">
<link rel="stylesheet" href="{{ base_url }}/css/highlight.css">
<link href="{{ base_url }}/css/base.css" rel="stylesheet">
{%- for path in extra_css %}
<link href="{{ path }}" rel="stylesheet">
{%- endfor %}
{%- endblock %}
{%- block libs %}
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script src="{{ base_url }}/js/jquery-1.10.2.min.js"></script>
<script src="{{ base_url }}/js/bootstrap-3.0.3.min.js"></script>
<script src="{{ base_url }}/js/highlight.pack.js"></script>
{%- endblock %}
{%- block analytics %}
{% if config.google_analytics %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '{{ config.google_analytics[0] }}', '{{ config.google_analytics[1] }}');
ga('send', 'pageview');
</script>
{% endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body>
{% include "nav.html" %}
<div class="container">
{%- block content %}
<div class="col-md-3">{% include "toc.html" %}</div>
<div class="col-md-9" role="main">{% include "content.html" %}</div>
{%- endblock %}
</div>
<footer class="col-md-12">
{%- block footer %}
<hr>
{% if config.copyright %}
<center>{{ config.copyright }}</center>
{% endif %}
{%- endblock %}
</footer>
{%- block scripts %}
<script src="{{ base_url }}/js/base.js"></script>
{%- for path in extra_javascript %}
<script src="{{ path }}"></script>
{%- endfor %}
{%- endblock %}
</body>
</html>
{% if page and page.meta and page.meta.source %}
<div class="source-links">
{% for filename in page.meta.source %}
<span class="label label-primary">{{ filename }}</span>
{% endfor %}
</div>
{% endif %}
{% if page and page.content %}{{ page.content }}{% endif %}
body {
padding-top: 70px;
}
h1[id]:before, h2[id]:before, h3[id]:before, h4[id]:before, h5[id]:before, h6[id]:before {
content: "";
display: block;
margin-top: -75px;
height: 75px;
}
ul.nav li.main {
font-weight: bold;
}
div.col-md-3 {
padding-left: 0;
}
div.col-md-9 {
padding-bottom: 100px;
}
div.source-links {
float: right;
}
div.col-md-9 img {
max-width: 100%;
}
/*
* Side navigation
*
* Scrollspy and affixed enhanced navigation to highlight sections and secondary
* sections of docs content.
*/
/* By default it's not affixed in mobile views, so undo that */
.bs-sidebar.affix {
position: static;
}
.bs-sidebar.well {
padding: 0;
}
/* First level of nav */
.bs-sidenav {
margin-top: 30px;
margin-bottom: 30px;
padding-top: 10px;
padding-bottom: 10px;
border-radius: 5px;
}
/* All levels of nav */
.bs-sidebar .nav > li > a {
display: block;
padding: 5px 20px;
z-index: 1;
}
.bs-sidebar .nav > li > a:hover,
.bs-sidebar .nav > li > a:focus {
text-decoration: none;
border-right: 1px solid;
}
.bs-sidebar .nav > .active > a,
.bs-sidebar .nav > .active:hover > a,
.bs-sidebar .nav > .active:focus > a {
font-weight: bold;
background-color: transparent;
border-right: 1px solid;
}
/* Nav: second level (shown on .active) */
.bs-sidebar .nav .nav {
display: none; /* Hide by default, but at >768px, show it */
margin-bottom: 8px;
}
.bs-sidebar .nav .nav > li > a {
padding-top: 3px;
padding-bottom: 3px;
padding-left: 30px;
font-size: 90%;
}
/* Show and affix the side nav when space allows it */
@media (min-width: 992px) {
.bs-sidebar .nav > .active > ul {
display: block;
}
/* Widen the fixed sidebar */
.bs-sidebar.affix,
.bs-sidebar.affix-bottom {
width: 213px;
}
.bs-sidebar.affix {
position: fixed; /* Undo the static from mobile first approach */
top: 80px;
}
.bs-sidebar.affix-bottom {
position: absolute; /* Undo the static from mobile first approach */
}
.bs-sidebar.affix-bottom .bs-sidenav,
.bs-sidebar.affix .bs-sidenav {
margin-top: 0;
margin-bottom: 0;
}
}
@media (min-width: 1200px) {
/* Widen the fixed sidebar again */
.bs-sidebar.affix-bottom,
.bs-sidebar.affix {
width: 263px;
}
}
此差异已折叠。
此差异已折叠。
/*
This is the GitHub theme for highlight.js
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
-webkit-text-size-adjust: none;
}
.hljs-comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.hljs-dartdoc,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
此差异已折叠。
/* Highlight */
$( document ).ready(function() {
hljs.initHighlightingOnLoad();
$('table').addClass('table table-striped table-hover');
});
$('body').scrollspy({
target: '.bs-sidebar',
});
/* Prevent disabled links from causing a page reload */
$("li.disabled a").click(function() {
event.preventDefault();
});
此差异已折叠。
此差异已折叠。
此差异已折叠。
{% extends "base.html" %}
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
{%- block site_name %}
<a class="navbar-brand" href="{{ nav.homepage.url }}">{{ config.site_name }}</a>
{%- endblock %}
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
{%- block site_nav %}
<!-- Main navigation -->
<ul class="nav navbar-nav">
{% for nav_item in nav %}
{% if nav_item.children %}
<li class="dropdown{% if nav_item.active %} active{% endif %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ nav_item.title }} <b class="caret"></b></a>
<ul class="dropdown-menu">
{% for nav_item in nav_item.children %}
<li {% if nav_item.active %}class="active"{% endif %}>
<a href="{{ nav_item.url }}">{{ nav_item.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li {% if nav_item.active %}class="active"{% endif %}>
<a href="{{ nav_item.url }}">{{ nav_item.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{%- endblock %}
<!-- Search, Navigation and Repo links -->
<ul class="nav navbar-nav navbar-right">
{%- block search_button %} {%- endblock %}
{%- block next_prev %}
{%- if page and (page.next_page or page.previous_page) %}
<li {% if not page.previous_page %}class="disabled"{% endif %}>
<a rel="next" {% if page.previous_page %}href="{{ page.previous_page.url }}"{% endif %}>
<i class="fa fa-arrow-left"></i> Previous
</a>
</li>
<li {% if not page.next_page %}class="disabled"{% endif %}>
<a rel="prev" {% if page.next_page %}href="{{ page.next_page.url }}"{% endif %}>
Next <i class="fa fa-arrow-right"></i>
</a>
</li>
{%- endif %}
{%- endblock %}
{%- block repo %}
{% if config.repo_url %}
<li>
<a href="{{ config.repo_url }}">
{% if config.repo_name == 'GitHub' %}
<i class="fa fa-github"></i>
{% elif config.repo_name == 'Bitbucket' %}
<i class="fa fa-bitbucket"></i>
{% endif %}
{{ config.repo_name }}
</a>
</li>
{% endif %}
{%- endblock %}
</ul>
</div>
</div>
</div>
<div class="bs-sidebar hidden-print affix well" role="complementary">
<ul class="nav bs-sidenav">
{% if page %}
{% for toc_item in page.toc %}
<li class="main {% if toc_item.active %}active{% endif %}"><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% for toc_item in toc_item.children %}
<li><a href="{{ toc_item.url }}">{{ toc_item.title }}</a></li>
{% endfor %}
{% endfor %}
{% endif %}
</ul>
</div>
......@@ -168,35 +168,45 @@ def download_files(msg):
f.write(msg['Text']())
```
## 常见问题与解答
### 用户多开
Q: 为什么中文的文件没有办法上传?
使用如下命令可以完成多开的操作:
A: 这是由于`requests`的编码问题导致的。若需要支持中文文件传输,将[fields.py][fields.py-2](py3版本见[这里][fields.py-3])文件放入requests包的packages/urllib3下即可
Q: 为什么我在设定了`itchat.auto_login()``enableCmdQR``True`后还是没有办法在命令行显示二维码?
```python
import itchat
A: 这是由于没有安装可选的包`pillow`,可以使用右边的命令安装:`pip install pillow`
newInstance = itchat.new_instance()
newInstance.auto_login(hotReload=True, statusStorageDir='newInstance.pkl')
Q: 如何通过这个包将自己的微信号变为控制器?
@newInstance.msg_register(TEXT)
def reply(msg):
return msg['Text']
A: 有两种方式:发送、接受自己UserName的消息;发送接收文件传输助手(filehelper)的消息
newInstance.run()
```
Q: 为什么我发送信息的时候部分信息没有成功发出来?
### 退出及登陆完成后调用特定方法
A: 有些账号是天生无法给自己的账号发送信息的,建议使用`filehelper`代替。另外,接口调用是有频率限制,限制一下连续发送信息之间的时间间隔即可
登陆完成后的方法需要赋值在`loginCallback`
## 作者
而退出后的方法需要赋值在`exitCallback`中。
[LittleCoder][littlecodersh]: 整体构架及完成Python2 Python3版本。
```python
import time
[Chyroc][Chyroc]: 完成第一版本的Python3构架。
import itchat
## 参考资料
def lc():
print('finish login')
def ec():
print('exit')
[liuwons/wxBot][liuwons-wxBot]: 类似的基于Python的微信机器人
itchat.auto_login(loginCallback=lc, exitCallback=ec)
time.sleep(3)
itchat.logout()
```
[zixia/wechaty][zixia-wechaty]: 基于Javascript(ES6)的微信个人账号机器人NodeJS框架/库
若不设置loginCallback的值,则将会自动删除二维码图片并清空命令行显示。
## 问题和建议
......@@ -220,7 +230,9 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f
[fields.py-2]: https://gist.github.com/littlecodersh/9a0c5466f442d67d910f877744011705
[fields.py-3]: https://gist.github.com/littlecodersh/e93532d5e7ddf0ec56c336499165c4dc
[littlecodersh]: https://github.com/littlecodersh
[tempdban]: https://github.com/tempdban
[Chyroc]: https://github.com/Chyroc
[liuwons-wxBot]: https://github.com/liuwons/wxBot
[zixia-wechaty]: https://github.com/zixia/wechaty
[Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin
[issue#1]: https://github.com/littlecodersh/ItChat/issues/1
# itchat
[![Gitter][gitter-picture]][gitter] ![py27][py27] ![py35][py35] [English version][english-version]
itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单。
使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人。
当然,该api的使用远不止一个机器人,更多的功能等着你来发现,比如[这些][tutorial2]
如今微信已经成为了个人社交的很大一部分,希望这个项目能够帮助你扩展你的个人的微信号、方便自己的生活。
## 安装
可以通过本命令安装itchat:
```python
pip install itchat
```
## 简单入门实例
有了itchat,如果你想要给文件传输助手发一条信息,只需要这样:
```python
import itchat
itchat.auto_login()
itchat.send('Hello, filehelper', toUserName='filehelper')
```
如果你想要回复发给自己的文本消息,只需要这样:
```python
import itchat
@itchat.msg_register(itchat.content.TEXT)
def text_reply(msg):
return msg['Text']
itchat.auto_login()
itchat.run()
```
一些进阶应用可以在下面的开源机器人的源码和进阶应用中看到,或者你也可以阅览[文档][document]
## 试一试
这是一个基于这一项目的[开源小机器人][robot-source-code],百闻不如一见,有兴趣可以尝试一下。
![QRCode][robot-qr]
## 截屏
![file-autoreply][robot-demo-file] ![login-page][robot-demo-login]
## 进阶应用
### 各类型消息的注册
通过如下代码,微信已经可以就日常的各种信息进行获取与回复。
```python
#coding=utf8
import itchat, time
from itchat.content import *
@itchat.msg_register([TEXT, MAP, CARD, NOTE, SHARING])
def text_reply(msg):
itchat.send('%s: %s' % (msg['Type'], msg['Text']), msg['FromUserName'])
@itchat.msg_register([PICTURE, RECORDING, ATTACHMENT, VIDEO])
def download_files(msg):
msg['Text'](msg['FileName'])
return '@%s@%s' % ({'Picture': 'img', 'Video': 'vid'}.get(msg['Type'], 'fil'), msg['FileName'])
@itchat.msg_register(FRIENDS)
def add_friend(msg):
itchat.add_friend(**msg['Text']) # 该操作会自动将新好友的消息录入,不需要重载通讯录
itchat.send_msg('Nice to meet you!', msg['RecommendInfo']['UserName'])
@itchat.msg_register(TEXT, isGroupChat=True)
def text_reply(msg):
if msg['isAt']:
itchat.send(u'@%s\u2005I received: %s' % (msg['ActualNickName'], msg['Content']), msg['FromUserName'])
itchat.auto_login(True)
itchat.run()
```
### 命令行二维码
通过以下命令可以在登陆的时候使用命令行显示二维码:
```python
itchat.auto_login(enableCmdQR=True)
```
部分系统可能字幅宽度有出入,可以通过将enableCmdQR赋值为特定的倍数进行调整:
```python
# 如部分的linux系统,块字符的宽度为一个字符(正常应为两字符),故赋值为2
itchat.auto_login(enableCmdQR=2)
```
默认控制台背景色为暗色(黑色),若背景色为浅色(白色),可以将enableCmdQR赋值为负值:
```python
itchat.auto_login(enableCmdQR=-1)
```
### 退出程序后暂存登陆状态
通过如下命令登陆,即使程序关闭,一定时间内重新开启也可以不用重新扫码。
```python
itchat.auto_login(hotReload=True)
```
### 用户搜索
使用`search_friends`方法可以搜索用户,有四种搜索方式:
1. 仅获取自己的用户信息
2. 获取特定`UserName`的用户信息
3. 获取备注、微信号、昵称中的任何一项等于`name`键值的用户
4. 获取备注、微信号、昵称分别等于相应键值的用户
其中三、四项可以一同使用,下面是示例程序:
```python
# 获取自己的用户信息,返回自己的属性字典
itchat.search_friends()
# 获取特定UserName的用户信息
itchat.search_friends(userName='@abcdefg1234567')
# 获取任何一项等于name键值的用户
itchat.search_friends(name='littlecodersh')
# 获取分别对应相应键值的用户
itchat.search_friends(wechatAccount='littlecodersh')
# 三、四项功能可以一同使用
itchat.search_friends(name='LittleCoder机器人', wechatAccount='littlecodersh')
```
关于公众号、群聊的获取与搜索在文档中有更加详细的介绍。
### 附件的下载与发送
itchat的附件下载方法存储在msg的Text键中。
发送的文件的文件名(图片给出的默认文件名)都存储在msg的FileName键中。
下载方法接受一个可用的位置参数(包括文件名),并将文件相应的存储。
```python
@itchat.msg_register(['Picture', 'Recording', 'Attachment', 'Video'])
def download_files(msg):
msg['Text'](msg['FileName'])
itchat.send('@%s@%s'%('img' if msg['Type'] == 'Picture' else 'fil', msg['FileName']), msg['FromUserName'])
return '%s received'%msg['Type']
```
如果你不需要下载到本地,仅想要读取二进制串进行进一步处理可以不传入参数,方法将会返回图片的二进制串。
```python
@itchat.msg_register(['Picture', 'Recording', 'Attachment', 'Video'])
def download_files(msg):
with open(msg['FileName'], 'wb') as f:
f.write(msg['Text']())
```
### 用户多开
使用如下命令可以完成多开的操作:
```python
import itchat
newInstance = itchat.new_instance()
newInstance.auto_login(hotReload=True, statusStorageDir='newInstance.pkl')
@newInstance.msg_register(TEXT)
def reply(msg):
return msg['Text']
newInstance.run()
```
### 退出及登陆完成后调用特定方法
登陆完成后的方法需要赋值在`loginCallback`中。
而退出后的方法需要赋值在`exitCallback`中。
```python
import time
import itchat
def lc():
print('finish login')
def ec():
print('exit')
itchat.auto_login(loginCallback=lc, exitCallback=ec)
time.sleep(3)
itchat.logout()
```
若不设置loginCallback的值,则将会自动删除二维码图片并清空命令行显示。
## 问题和建议
如果有什么问题或者建议都可以在这个[Issue][issue#1]和我讨论
或者也可以在gitter上交流:[![Gitter][gitter-picture]][gitter]
当然也可以加入我们新建的QQ群讨论:549762872
[gitter-picture]: https://badges.gitter.im/littlecodersh/ItChat.svg
[gitter]: https://gitter.im/littlecodersh/ItChat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
[py27]: https://img.shields.io/badge/python-2.7-ff69b4.svg
[py35]: https://img.shields.io/badge/python-3.5-red.svg
[english-version]: https://github.com/littlecodersh/ItChat/blob/master/README_EN.md
[document]: https://itchat.readthedocs.org/zh/latest/
[tutorial2]: http://python.jobbole.com/86532/
[robot-source-code]: https://gist.github.com/littlecodersh/ec8ddab12364323c97d4e36459174f0d
[robot-qr]: http://7xrip4.com1.z0.glb.clouddn.com/ItChat%2FQRCode2.jpg?imageView/2/w/400/
[robot-demo-file]: http://7xrip4.com1.z0.glb.clouddn.com/ItChat%2FScreenshots%2F%E5%BE%AE%E4%BF%A1%E8%8E%B7%E5%8F%96%E6%96%87%E4%BB%B6%E5%9B%BE%E7%89%87.png?imageView/2/w/300/
[robot-demo-login]: http://7xrip4.com1.z0.glb.clouddn.com/ItChat%2FScreenshots%2F%E7%99%BB%E5%BD%95%E7%95%8C%E9%9D%A2%E6%88%AA%E5%9B%BE.jpg?imageView/2/w/450/
[fields.py-2]: https://gist.github.com/littlecodersh/9a0c5466f442d67d910f877744011705
[fields.py-3]: https://gist.github.com/littlecodersh/e93532d5e7ddf0ec56c336499165c4dc
[littlecodersh]: https://github.com/littlecodersh
[tempdban]: https://github.com/tempdban
[Chyroc]: https://github.com/Chyroc
[liuwons-wxBot]: https://github.com/liuwons/wxBot
[zixia-wechaty]: https://github.com/zixia/wechaty
[Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin
[issue#1]: https://github.com/littlecodersh/ItChat/issues/1
## 一、课程介绍
本文最佳阅读方式为[实验楼的会员课程][vip],建议点击链接在实验楼内阅读。
### 1. 课程来源
关于itchat进一步使用的问题你可以在[主页][itchat]加入官方交流群也可以在课程下面向我提问。
课程在常见的三种系统中都可以进行操作,itchat建议使用可以安装的最新版本。
本课程通过聊天机器人为例,介绍如何使用Python完成微信的点对点信息交互。
### 2. 内容简介
* 课程实现微信个人号聊天机器人
* 通过自定义消息处理方法加入聊天功能
### 3. 课程知识点
本课程项目完成过程中将学习:
* 微信消息的基本获取与处理
* 微信消息的指定发送
其中将重点介绍微信消息的获取与处理。
## 二、实验环境
在终端中输入以下命令,完成微信的API包itchat的安装。
我们这里使用python3的环境(python2也是可行的):
```bash
sudo pip3 install itchat --upgrade
```
通过该命令判断是否安装成功:
```bash
python3 -c "import itchat"
```
如果没有报错信息说明你已经将实验环境安装完成。
![install][install]
## 三、实验原理
通过微信的Python接口itchat获取微信消息。
将微信消息传输到机器人接口(这里以图灵为例),获取机器人的返回消息。
将返回消息返回给微信消息的发送人。
实现将微信个人号变为聊天机器人的目的。
## 四、实验步骤
### 0. 基础知识
为了照顾一些从未使用过Python的新用户与使用其他语言的用户,这里简单的讲一下以下的代码如何使用。
下面的每一段描述都给出了相应的测试代码,如果没有特殊说明这段代码可以这样使用:
打开桌面的Xfce终端,先将目录通过以下命令切到桌面。
```bash
cd Desktop
```
之后使用gedit编辑器编辑我们的主程序。
你也完全可以使用vim,会使用vim的话想必也知道这里应该输入什么命令了。
```bash
gedit test.py
```
最后将给出的代码复制进编辑器,保存并退出,使用如下命令就可以使用了。
```bash
python3 test.py
```
那么,就让我们开始正式进入Python操作微信的探索之旅吧。
### 1. 实现微信消息的获取
itchat的注册时根据类型注册的。
在获取相应类型的信息时会调用该函数。
我们现在只需要获取最简单的文本消息,那么只需要这样注册:
```python
import itchat
@itchat.msg_register(itchat.content.TEXT)
def print_content(msg):
print(msg['Text'])
itchat.auto_login()
itchat.run()
```
其中第三行即注册的操作,通过装饰符将`print_content`注册为处理文本消息的函数。
微信有各种类型的数据,例如图片、语音、名片、分享等,也对应不同的注册参数:
* 图片对应`itchat.content.PICTURE`
* 语音对应`itchat.content.RECORDING`
* 名片对应`itchat.content.CARD`
* 其余的这里就不一一列举,更具体的内容可以自行搜索itchat阅读[文档][document]
执行命令
```
python3 test.py
```
就可看到我们开始登陆微信:
![login][login]
扫码完成以后最基础的文本信息的接收就完成了,你可以尝试用他人的微信给自己发一条信息。
如果你不想要每次运行程序都扫码,可以在登陆命令中进行设置:
```python
itchat.auto_login(hotReload=True)
```
### 2. 实现微信消息的发送
微信可以发送各类消息,文本、图片、文件等,不过我们现在只需要使用文本的发送。
其余的消息的发送有兴趣可以自行阅读。
```python
itchat.send('Message Content', 'toUserName')
```
该发送消息的函数需要两个参数,消息的内容与接受者的UserName,即标识符。
那么我们试着向文件传输助手发送一条消息:
```python
#coding=utf8
import itchat
itchat.auto_login(hotReload=True)
# 注意实验楼环境的中文输入切换
itchat.send(u'测试消息发送', 'filehelper')
```
打开手机看一下是否就完成了消息的发送。
保存代码后,执行命令:
```
python3 test.py
```
扫描登录后的效果如下:
![send-hello][send-hello]
当然,还有一种更加快捷的回复方法就是在注册函数中直接回复。
例如下面的例子将会将文本消息原封不动的返回。
```python
import itchat
@itchat.msg_register(itchat.content.TEXT)
def print_content(msg):
return msg['Text']
itchat.auto_login()
itchat.run()
```
这种方式显然更加直观也更加简单(不需要输入接受者的UserName)
我们本次实践将会采用这种方式。
### 3. 实现最简单的与图灵机器人的交互
要做一个能够与人交流的机器人有很多种方法,最简单的莫过于使用他人提供的接口。
我们这里以图灵机器人为例,演示这一功能。
图灵机器人简单而言就是以一定的规则给图灵的服务器发送数据包(包含你对他说的话)
图灵的服务器会以一定的规则给你返回数据包(包含他回复你的话)
你需要一个Tuling Key来告诉图灵服务器你有权和他对话,我这里免费提供一些:
```bash
8edce3ce905a4c1dbb965e6b35c3834d
eb720a8970964f3f855d863d24406576
1107d5601866433dba9599fac1bc0083
71f28bf79c820df10d39b4074345ef8c
```
下面我做一个配置图灵机器人的简单介绍,你想要自行了解或者申请Tuling Key可以看[这里][tuling]
发送的规则简而言之是这样的:
```json
{
'key' : 'TULING_KEY',
'info' : 'YOUR_MSG',
'userid' : 'USERID',
}
```
其中userId是用户的标志,让机器人知道你是你。(也就是一个Tuling Key可以有多个用户)
而返回的内容基本是这样的:
```json
{
'code': 0,
'text': 'RETURN_MSG',
}
```
我们需要的内容就在text键里面。
这里我们使用requests包完成整个操作(已经包含在itchat包的安装中了)。
最后值得一提的就是这是一个post请求,那么直接上代码应该比我絮絮叨叨的说要直观很多。
```python
#coding=utf8
import requests
apiUrl = 'http://www.tuling123.com/openapi/api'
data = {
'key' : '8edce3ce905a4c1dbb965e6b35c3834d', # 如果这个Tuling Key不能用,那就换一个
'info' : 'hello', # 这是我们发出去的消息
'userid' : 'wechat-robot', # 这里你想改什么都可以
}
# 我们通过如下命令发送一个post请求
r = requests.post(apiUrl, data=data).json()
# 让我们打印一下返回的值,看一下我们拿到了什么
print(r)
```
我们可以看到他回复了你好。
![reply-hello][reply-hello]
至此我们已经理解并掌握了所有需要的内容,下面将其组装起来即可。
## 五、实验程序
我先从概念上说一下组装是一个怎么样的过程。
当然,如果你觉得代码更直观,我也在代码中为你写好了注释。
这里我们首先将与图灵服务器的交互定义为一个函数。
我们需要这个函数接收我们要发送给图灵的消息,返回图灵返回给我们的消息。
再将与图灵交互并返回图灵返回结果的操作写成函数并在itchat中注册。
最后启动itchat,我们的程序就完成了。
```python
#coding=utf8
import requests
import itchat
KEY = '8edce3ce905a4c1dbb965e6b35c3834d'
def get_response(msg):
# 这里我们就像在“3. 实现最简单的与图灵机器人的交互”中做的一样
# 构造了要发送给服务器的数据
apiUrl = 'http://www.tuling123.com/openapi/api'
data = {
'key' : KEY,
'info' : msg,
'userid' : 'wechat-robot',
}
try:
r = requests.post(apiUrl, data=data).json()
# 字典的get方法在字典没有'text'值的时候会返回None而不会抛出异常
return r.get('text')
# 为了防止服务器没有正常响应导致程序异常退出,这里用try-except捕获了异常
# 如果服务器没能正常交互(返回非json或无法连接),那么就会进入下面的return
except:
# 将会返回一个None
return
# 这里是我们在“1. 实现微信消息的获取”中已经用到过的同样的注册方法
@itchat.msg_register(itchat.content.TEXT)
def tuling_reply(msg):
# 为了保证在图灵Key出现问题的时候仍旧可以回复,这里设置一个默认回复
defaultReply = 'I received: ' + msg['Text']
# 如果图灵Key出现问题,那么reply将会是None
reply = get_response(msg['Text'])
# a or b的意思是,如果a有内容,那么返回a,否则返回b
# 有内容一般就是指非空或者非None,你可以用`if a: print('True')`来测试
return reply or defaultReply
# 为了让实验过程更加方便(修改程序不用多次扫码),我们使用热启动
itchat.auto_login(hotReload=True)
itchat.run()
```
## 六、实验结果
在本机上通过如下命令可以运行该程序
```bash
python3 main.py
```
扫码登陆后程序就成功运行了。
之后在手机上使用别的账号给自己的微信号发送消息即可获得机器人的回复。
这里给出使用的效果图:
![demo][demo]
如果你想要通过与其他用户的交互完成该操作,自行在注册的函数中进行修改即可。
如果你想要进一步了解使用Python控制微信的细节,你也可以去到项目主页[itchat][itchat]
或者直接阅读[文档][document]也是不错的选择。
如果你的本地环境并非Python3也没有关系,itchat同样完美支持Python2。
## 七、代码获取
我将整个项目目录做了一个打包,你可以直接下载后运行。
你可以在[这里][code-package]下载。
如果有什么问题,欢迎在我的[主页][author]留言或者[邮件][email]联系我。
[vip]: https://www.shiyanlou.com/courses/684
[author]: https://github.com/littlecodersh
[install]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/install.png?imageView/2/h/300/
[tuling]: http://tuling123.com/help/h_cent_webapi.jhtml
[login]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/login.png?imageView/2/h/300/
[send-hello]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/send-hello.png?imageView/2/h/400
[reply-hello]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/reply-hello.png?imageView/2/h/300/
[demo]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/demo.png?imageView/2/h/400/
[code-package]: http://7xrip4.com1.z0.glb.clouddn.com/shiyanlou/itchat/2/main.py
[email]: mailto:i7meavnktqegm1b@qq.com
[itchat]: https://github.com/littlecodersh/itchat
[document]: http://itchat.readthedocs.io/zh/latest/
#手把手教你扩展个人微信号(1)
# 手把手教你扩展个人微信号(1)
现在的日常生活已经离不开微信,难免会生出微信有没有什么API可以使用的想法。
......@@ -14,7 +14,7 @@ Python与基本的网络基础都不困难,所以即使没有这方面基础
关于本教程有任何建议或者疑问,都欢迎邮件与我联系,或者在[github上提出](https://github.com/littlecodersh/ItChat)(i7meavnktqegm1b@qq.com)
##教程流程简介
## 教程流程简介
教程将会从如何分析微信协议开始,第一部分将教你如何从零开始获取并模拟扩展个人微信号所需要的协议。
......@@ -22,7 +22,7 @@ Python与基本的网络基础都不困难,所以即使没有这方面基础
第三部分就项目基本框架开发插件,以消息聚合等功能为例对框架做进一步介绍与扩展。
##简单成果展示
## 简单成果展示
目前的样例微信号被扩展为了能够完成信息上传下载的机器人,用于展示信息交互功能。
......@@ -40,7 +40,7 @@ Python与基本的网络基础都不困难,所以即使没有这方面基础
* Wireshark 2.0.2
* 微信版本6.3.15
###Wireshark配置
### Wireshark配置
Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页端的流量。
......@@ -48,11 +48,11 @@ Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页
配置完成以后开始抓包,载入`https://www.baidu.com`后若能看到http请求则配置成功。
##分析并模拟扫码,并获取登录状态
## 分析并模拟扫码,并获取登录状态
微信网页端登陆分为很多步,这里以第一步扫码为例讲解如何从抓包开始完成模拟。
###分析过程
### 分析过程
在抓包以前,我们需要先想清楚这是一个什么样的过程。
......@@ -66,7 +66,7 @@ Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页
有了这些概念以后就可以开始将这四步和包对应起来。
###对应过程与实际的包
### 对应过程与实际的包
开启wireshark抓包后登陆网页端微信,完成扫码登陆,然后关闭wireshark抓包。
......@@ -129,7 +129,7 @@ Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页
这里做一个简单的小结,这一部分简单的介绍了分析数据包的基本思路,以及一些小的技巧。当然这些仅供参考,在具体的抓包中完全可以根据具体的交互过程自由发挥。而目前留下来的问题有:第一步时的appid与第三步时的r,留待模拟时在做研究。
###使用Python模拟扫码
### 使用Python模拟扫码
这一部分我们使用python的requests模块,可以通过`pip install requests`安装。
......@@ -303,7 +303,7 @@ print('Log in as %s'%dic['User']['NickName'])
* session的get,post方法返回一个量,可以通过r.text自动编码显示。
* 存储图片有特殊的方式与配置。
##小结
## 小结
到现在为止我展示了一个完整的抓包、分析、模拟的过程完成了模拟登陆,其他一些事情其实也都是类似的过程,想清楚每一步要做些什么即可。
......@@ -321,7 +321,7 @@ print('Log in as %s'%dic['User']['NickName'])
另外,每次获取数据时(webwxsync)记得更新SyncKey。
###某个特定请求不知道如何模拟
### 某个特定请求不知道如何模拟
在项目中已经模拟好了几乎所有的请求,你可以通过参考我的方法与数据包。
......@@ -329,7 +329,7 @@ print('Log in as %s'%dic['User']['NickName'])
项目中的微信网页端接口见[这里](https://github.com/littlecodersh/ItChat/blob/master/itchat/client.py)
###无法上传中文文件名的文件与图片
### 无法上传中文文件名的文件与图片
这是因为使用requests包会自动将中文文件名编码为服务器端无法识别的格式,所以需要修改requests包或者使用别的方法上传文件。
......@@ -352,15 +352,15 @@ def format_header_param(name, value):
return value
```
###登录时出现不安全的提示
### 登录时出现不安全的提示
建议更新Python版本至2.7.11
##小练习答案
## 小练习答案
源码可在该地址下载:[这里](https://github.com/littlecodersh/EasierLife/blob/master/Scripts/SendToMyself.py)
##结束语
## 结束语
希望读完这篇文章能对你有帮助,有什么不足之处万望指正(鞠躬)。
......
......@@ -435,7 +435,7 @@ class Core(object):
''' start auto respond
for option
- debug: if set, debug info will be shown on screen
it is defined in components/hotreload.py
it is defined in components/register.py
'''
raise NotImplementedError()
def search_friends(self, name=None, userName=None, remarkName=None, nickName=None,
......
site_name: 'itchat'
pages:
- '介绍':
- '项目简介': 'index.md'
- '快速入门': 'intro/start.md'
- '登陆配置': 'intro/login.md'
- '回复方法': 'intro/reply.md'
- '注册方法': 'intro/handler.md'
- '消息内容': 'intro/messages.md'
- '各类账号': 'intro/contact.md'
- '部署程序': 'intro/deploy.md'
- 'API列表': 'api.md'
- 'FAQ': 'FAQ.md'
- '教程文章':
- '基础新手入门': 'tutorial/tutorial0.md'
- '实践项目分享': 'tutorial/tutorial2.md'
- '抓包及原理入门': 'tutorial/tutorial1.md'
extra_css: ['docs/bootstrap/css']
extra_javascript: ['docs/bootstrap/js']
theme_dir: 'docs/bootstrap'
repo_url: 'https://github.com/littlecodersh/itchat'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册