Skip to content

Latest commit

 

History

History
694 lines (568 loc) · 43.8 KB

ext.rst

File metadata and controls

694 lines (568 loc) · 43.8 KB

微信非官方接口操作 WechatExt

.. py:class:: wechat_sdk.ext.WechatExt(username, password [, token=None, cookies=None, appid=None, plugin_token=None, ifencodepwd=False, login=True, checkssl=False])

   微信扩展功能类

   :param str username: 你的微信公众平台账户用户名
   :param str password: 你的微信公众平台账户密码
   :param str token: 直接导入的 ``token`` 值, 该值需要在上一次该类实例化之后手动进行缓存并在此传入, 如果不传入, 将会在实例化的时候自动获取
   :param str cookies: 直接导入的 ``cookies`` 值, 该值需要在上一次该类实例化之后手动进行缓存并在此传入, 如果不传入, 将会在实例化的时候自动获取
   :param str appid: 直接导入的 ``appid`` 值, 该值需要在上一次该类实例化之后手动进行缓存并在此传入, 如果不传入, 将会在调用 ``stat_`` 开头的方法(统计分析类)时自动获取
   :param str plugin_token: 直接导入的 ``plugin_token`` 值, 该值需要在上一次该类实例化之后手动进行缓存并在此传入, 如果不传入, 将会在调用 ``stat_`` 开头的方法(统计分析类)时自动获取
   :param boolean ifencodepwd: 密码是否已经经过编码, 如果密码已经经过加密, 此处为 ``True`` , 如果传入的密码为明文, 此处为 ``False``
   :param boolean login: **是否在实例化过程中尝试登录 (推荐此处设置为 False, 然后手动执行登录以方便进行识别验证码等操作, 此处默认值为 True 为兼容历史版本**
   :param boolean checkssl: 是否检查 SSL, 默认为 False, 可避免 urllib3 的 InsecurePlatformWarning 警告

   **实例化说明:**

   1. 请注意实例化时的 ``login`` 参数,它的默认值为 ``True`` ,但这仅仅是为了兼容历史版本(v0.4.2及以前),在新版本中,强烈推荐将该参数设置为 ``False`` ,然后手动执行 :func:`login` 以有效应对可能出现的验证码问题。

   2. 当实例化 WechatExt 时,你必须传入 ``username`` 和 ``password`` ,对于 ``token`` 和 ``cookies`` 参数,如果传入了它们,将会自动省略登录过程(无论 ``login`` 参数被设置为了 ``True`` 还是 ``False`` )。

   3. 请保证你的代码中会捕获 ``NeedLoginError`` 异常,一旦发生此异常,你需要重新调用 :func:`login` 方法登录来获取新的 ``token`` 及 ``cookies`` 。

   4. **详细说明一下 token 及 cookies 参数的传入问题:**

      因为此开发包并不打算以服务器的方式常驻,所以,每次请求均会重新实例化 ``WechatExt`` ,所以需要你以你自己的方式去保存上一次请求中实例化后的 ``WechatExt`` 中 ``token`` 及 ``cookies`` 参数,并在下一次的实例化的过程中传入,以此来保证不会频繁登录。

      获取 ``token`` 及 ``cookies`` 的方式为调用 :func:`get_token_cookies` 方法

      下一版本将会考虑更为简单通用的方法,在新版本发布之前,请用你自己的方式把得到的 ``token`` 及 ``cookies`` 保存起来,不管是文件,缓存还是数据库都可以,只要在实例化后,你可以在任何时间调用 :func:`get_token_cookies` 方法。

   5. ``appid`` 及 ``plugin_token`` 参数是用于统计分析类的方法的(以 ``stat_`` 开头),如果不需要调用这些方法,可以无需理会这两个参数。

      它们和 ``token`` 及 ``cookies`` 一样,可由开发者自行缓存,获取它们的方式为调用 :func:`get_plugin_token_appid` 方法。唯一需要注意的是,如果传入了 ``appid`` 及 ``plugin_token`` 参数,那么也必须要传入 ``token`` 和 ``cookies`` 参数,否则无效。

   .. py:method:: login(verify_code='')

        登录微信公众平台

        当你刚刚实例化 ``WechatExt`` 完或者捕获到 ``NeedLoginError`` 异常时,需要调用此方法进行登录或登录重试。

        **如何应对登录时的验证码:**

        默认情况下,如果微信服务器认为你的账号正常,那么直接调用一次 :func:`login` 就可以完成登录操作,但如果不幸出现了验证码,本方法会抛出 ``LoginVerifyCodeError`` 异常,这时你需要通过下面的 :func:`get_verify_code` 方法来获取验证码图片,然后通过你自己的方式识别这张图片并得出结果,并将验证码识别结果作为本方法的 ``verify_code`` 参数值来重新调用本方法,可多次尝试。

        **如何识别验证码:**

        鉴于腾讯的验证码基本无法通过机器进行识别,所以推荐网络上的人工识别验证码服务。因为 ``token`` 和 ``cookies`` 都有一定时间的有效期,所以一次验证码识别可以使用不短的时间,响应时间和价格完全可以承受。

        :param str verify_code: 验证码, 不传入则为无验证码
        :raises: LoginVerifyCodeError 需要验证码或验证码出错,该异常为 ``LoginError`` 的子类
        :raises: LoginError 登录出错,异常内容为微信服务器响应的内容,可作为日志记录下来


   .. py:method:: get_verify_code(file_path)

        获取登录验证码并存储到本地路径

        :param str file_path: 将验证码图片保存的文件路径

   .. py:method:: get_token_cookies()

        获取当前 token 及 cookies, 供手动缓存使用

        返回 dict 示例::

            {
                'cookies': 'bizuin=3086177907;data_bizuin=3086177907;data_ticket=AgWTXTpLL+FV+bnc9yLbb3V8;slave_sid=TERlMEJ1bWFCbTlmVnRLX0lLdUpRV0pyN2k1eVkzbWhiY0NfTHVjNFRZQk1DRDRfal82UzZKWTczR3I5TFpUYjRXUDBtN1h1cmJMRTkzS3hianBHOGpHaFM0eXJiNGp6cDFWUGpqbFNyMFlyQ05GWGpseVg2T2s2Sk5DRWpnRlE=;slave_user=gh_1b2959761a7d;',
                'token': 373179898
            }

        :return: 一个 dict 对象, key 为 ``token`` 和 ``cookies``

   .. py:method:: get_plugin_token_appid()

        获取当前 plugin_token 及 appid, 供手动缓存使用

        返回 dict 示例::

            {
                'plugin_token': 'll1D85fGDCTr4AAxC_RrFIsfaM1eajMksOjZN_eXodroIeT77QkrMfckyYdG0qj8CnvWGUPp7-mpBOs07dbuG-iwULOcyjoEvlTsghm1K34C0oj3AI8egAxGqixxhRs8',
                'appid': 'wxd0c09648a48b3798'
            }

        :return: 一个 dict 对象, key 为 ``plugin_token`` 和 ``appid``

   .. py:method:: send_message(fakeid, content)

        主动发送文本消息

        :param str fakeid: 用户的 UID (即 fakeid )
        :param str content: 发送的内容
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 具体内容有 ``fake id not exist``

   .. py:method:: get_user_list(page=0, pagesize=10, groupid=0)

        获取用户列表

        返回JSON示例 ::

            {
                "contacts": [
                    {
                        "id": 2431798261,
                        "nick_name": "Doraemonext",
                        "remark_name": "",
                        "group_id": 0
                    },
                    {
                        "id": 896229760,
                        "nick_name": "微信昵称",
                        "remark_name": "",
                        "group_id": 0
                    }
                ]
            }

        :param integer page: 页码 (从 0 开始)
        :param integer pagesize: 每页大小
        :param integer groupid: 分组 ID
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: stat_article_detail_list(page=1, start_date=str(date.today()+timedelta(days=-30)), end_date=str(date.today()))

        获取图文分析数据

        返回JSON示例 ::

            {
                "hasMore": true,  // 说明是否可以增加 page 页码来获取数据
                "data": [
                    {
                        "index": [
                            "20,816",  // 送达人数
                            "1,944",  // 图文页阅读人数
                            "2,554",  // 图文页阅读次数
                            "9.34%",  // (图文页阅读人数 / 送达人数)
                            "0",  // 原文页阅读人数
                            "0",  // 原文页阅读次数
                            "0%",  // (原文页阅读人数 / 图文页阅读人数)
                            "47",  // 分享转发人数
                            "61",  // 分享转发次数
                            "1"  // 微信收藏人数
                        ],
                        "time": "2015-01-21",
                        "table_data": "{\"fields\":{\"TargetUser\":{\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"number\":false,\"colAlign\":\"center\",\"needOrder\":false,\"precision\":0},\"IntPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"IntPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"PageConversion\":{\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"OriPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"OriPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"Conversion\":{\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"ShareUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"ShareCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"AddToFavUser\":{\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0}},\"data\":[{\"MsgId\":\"205104027_1\",\"Title\":\"\\u56de\\u5bb6\\u5927\\u4f5c\\u6218 | \\u5feb\\u6765\\u5e26\\u6211\\u56de\\u5bb6\",\"RefDate\":\"20150121\",\"TargetUser\":\"20,816\",\"IntPageReadUser\":\"1,944\",\"IntPageReadCount\":\"2,554\",\"OriPageReadUser\":\"0\",\"OriPageReadCount\":\"0\",\"ShareUser\":\"47\",\"ShareCount\":\"61\",\"AddToFavUser\":\"1\",\"Conversion\":\"0%\",\"PageConversion\":\"9.34%\"}],\"fixedRow\":false,\"cssSetting\":{\"\":\"\"},\"complexHeader\":[[{\"field\":\"TargetUser\",\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"rowSpan\":2,\"colSpan\":1},{\"thText\":\"\\u56fe\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u539f\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u5206\\u4eab\\u8f6c\\u53d1\",\"colSpan\":2},{\"field\":\"AddToFavUser\",\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"rowSpan\":2,\"enable\":true}],[{\"field\":\"IntPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"IntPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"PageConversion\",\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"OriPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"OriPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"Conversion\",\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"ShareUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"ShareCount\",\"thText\":\"\\u6b21\\u6570\"}]]}",
                        "id": "205104027_1",
                        "title": "回家大作战 | 快来带我回家"
                    },
                    {
                        "index": [
                            "20,786",  // 送达人数
                            "2,598",  // 图文页阅读人数
                            "3,368",  // 图文页阅读次数
                            "12.5%",  // (图文页阅读人数 / 送达人数)
                            "0",  // 原文页阅读人数
                            "0",  // 原文页阅读次数
                            "0%",  // (原文页阅读人数 / 图文页阅读人数)
                            "73",  // 分享转发人数
                            "98",  // 分享转发次数
                            "1"  // 微信收藏人数
                        ],
                        "time": "2015-01-20",
                        "table_data": "{\"fields\":{\"TargetUser\":{\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"number\":false,\"colAlign\":\"center\",\"needOrder\":false,\"precision\":0},\"IntPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"IntPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"PageConversion\":{\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"OriPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"OriPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"Conversion\":{\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"ShareUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"ShareCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"AddToFavUser\":{\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0}},\"data\":[{\"MsgId\":\"205066833_1\",\"Title\":\"\\u56de\\u5bb6\\u5927\\u4f5c\\u6218 | \\u5982\\u4f55\\u4f18\\u96c5\\u5730\\u53bb\\u5f80\\u8f66\\u7ad9\\u548c\\u673a\\u573a\",\"RefDate\":\"20150120\",\"TargetUser\":\"20,786\",\"IntPageReadUser\":\"2,598\",\"IntPageReadCount\":\"3,368\",\"OriPageReadUser\":\"0\",\"OriPageReadCount\":\"0\",\"ShareUser\":\"73\",\"ShareCount\":\"98\",\"AddToFavUser\":\"1\",\"Conversion\":\"0%\",\"PageConversion\":\"12.5%\"}],\"fixedRow\":false,\"cssSetting\":{\"\":\"\"},\"complexHeader\":[[{\"field\":\"TargetUser\",\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"rowSpan\":2,\"colSpan\":1},{\"thText\":\"\\u56fe\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u539f\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u5206\\u4eab\\u8f6c\\u53d1\",\"colSpan\":2},{\"field\":\"AddToFavUser\",\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"rowSpan\":2,\"enable\":true}],[{\"field\":\"IntPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"IntPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"PageConversion\",\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"OriPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"OriPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"Conversion\",\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"ShareUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"ShareCount\",\"thText\":\"\\u6b21\\u6570\"}]]}",
                        "id": "205066833_1",
                        "title": "回家大作战 | 如何优雅地去往车站和机场"
                    },
                    {
                        "index": [
                            "20,745",  // 送达人数
                            "1,355",  // 图文页阅读人数
                            "1,839",  // 图文页阅读次数
                            "6.53%",  // (图文页阅读人数 / 送达人数)
                            "145",  // 原文页阅读人数
                            "184",  // 原文页阅读次数
                            "10.7%",  // (原文页阅读人数 / 图文页阅读人数)
                            "48",  // 分享转发人数
                            "64",  // 分享转发次数
                            "5"  // 微信收藏人数
                        ],
                        "time": "2015-01-19",
                        "table_data": "{\"fields\":{\"TargetUser\":{\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"number\":false,\"colAlign\":\"center\",\"needOrder\":false,\"precision\":0},\"IntPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"IntPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"PageConversion\":{\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"OriPageReadUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"OriPageReadCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"Conversion\":{\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":\"2\"},\"ShareUser\":{\"thText\":\"\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"ShareCount\":{\"thText\":\"\\u6b21\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0},\"AddToFavUser\":{\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"number\":true,\"colAlign\":\"right\",\"needOrder\":false,\"precision\":0}},\"data\":[{\"MsgId\":\"205028693_1\",\"Title\":\"\\u5145\\u7535\\u65f6\\u95f4 | \\u542c\\u542c\\u7535\\u53f0\\uff0c\\u4f18\\u96c5\\u5730\\u63d0\\u5347\\u5b66\\u4e60\\u6548\\u7387\",\"RefDate\":\"20150119\",\"TargetUser\":\"20,745\",\"IntPageReadUser\":\"1,355\",\"IntPageReadCount\":\"1,839\",\"OriPageReadUser\":\"145\",\"OriPageReadCount\":\"184\",\"ShareUser\":\"48\",\"ShareCount\":\"64\",\"AddToFavUser\":\"5\",\"Conversion\":\"10.7%\",\"PageConversion\":\"6.53%\"}],\"fixedRow\":false,\"cssSetting\":{\"\":\"\"},\"complexHeader\":[[{\"field\":\"TargetUser\",\"thText\":\"\\u9001\\u8fbe\\u4eba\\u6570\",\"rowSpan\":2,\"colSpan\":1},{\"thText\":\"\\u56fe\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u539f\\u6587\\u9875\\u9605\\u8bfb\",\"colSpan\":3},{\"thText\":\"\\u5206\\u4eab\\u8f6c\\u53d1\",\"colSpan\":2},{\"field\":\"AddToFavUser\",\"thText\":\"\\u5fae\\u4fe1\\u6536\\u85cf\\u4eba\\u6570\",\"rowSpan\":2,\"enable\":true}],[{\"field\":\"IntPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"IntPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"PageConversion\",\"thText\":\"\\u56fe\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"OriPageReadUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"OriPageReadCount\",\"thText\":\"\\u6b21\\u6570\"},{\"field\":\"Conversion\",\"thText\":\"\\u539f\\u6587\\u8f6c\\u5316\\u7387\"},{\"field\":\"ShareUser\",\"thText\":\"\\u4eba\\u6570\"},{\"field\":\"ShareCount\",\"thText\":\"\\u6b21\\u6570\"}]]}",
                        "id": "205028693_1",
                        "title": "充电时间 | 听听电台,优雅地提升学习效率"
                    }
                ]
            }

        :param integer page: 页码 (由于腾讯接口限制,page 从 1 开始,3 条数据为 1 页)
        :param str start_date: 开始时间,默认是今天-30天 (类型: str 格式示例: "2015-01-15")
        :param str end_date: 结束时间,默认是今天 (类型: str 格式示例: "2015-02-01")
        :return: 返回的 JSON 数据,具体的各项内容解释参见上面的 JSON 返回示例
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_group_list()

        获取分组列表

        返回JSON示例::

            {
                "groups": [
                    {
                        "cnt": 8,
                        "id": 0,
                        "name": "未分组"
                    },
                    {
                        "cnt": 0,
                        "id": 1,
                        "name": "黑名单"
                    },
                    {
                        "cnt": 0,
                        "id": 2,
                        "name": "星标组"
                    }
                ]
            }

        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_news_list(page, pagesize=10)

        获取图文信息列表

        返回JSON示例::

            [
                {
                    "multi_item": [
                        {
                            "seq": 0,
                            "title": "98路公交线路",
                            "show_cover_pic": 1,
                            "author": "",
                            "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3GQgcgkDSoEm668gClFVDt3BR8GGQ5eB8HoL4vDezzKtSblIjckOf7A/0",
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204884970&idx=1&sn=bf25c51f07260d4ed38305a1cbc0ce0f#rd",
                            "source_url": "",
                            "file_id": 204884939,
                            "digest": "98路线路1.农大- 2.金阳小区- 3.市客运司- 4.市制药厂- 5.新农大- 6.独山子酒店- 7.三"
                        }
                    ],
                    "seq": 0,
                    "title": "98路公交线路",
                    "show_cover_pic": 1,
                    "author": "",
                    "app_id": 204884970,
                    "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204884970&idx=1&sn=bf25c51f07260d4ed38305a1cbc0ce0f#rd",
                    "create_time": "1405237966",
                    "file_id": 204884939,
                    "img_url": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3GQgcgkDSoEm668gClFVDt3BR8GGQ5eB8HoL4vDezzKtSblIjckOf7A/0",
                    "digest": "98路线路1.农大- 2.金阳小区- 3.市客运司- 4.市制药厂- 5.新农大- 6.独山子酒店- 7.三"
                },
                {
                    "multi_item": [
                        {
                            "seq": 0,
                            "title": "2013年新疆软件园大事记",
                            "show_cover_pic": 0,
                            "author": "",
                            "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3icvFgkxZRyIrkLbic9I5ZKLa3XB8UqNlkT8CYibByHuraSvVoeSzdTRLQ/0",
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204883415&idx=1&sn=68d62215052d29ece3f2664e9c4e8cab#rd",
                            "source_url": "",
                            "file_id": 204883412,
                            "digest": "1月1.新疆软件园展厅设计方案汇报会2013年1月15日在维泰大厦4楼9号会议室召开新疆软件园展厅设计工作完"
                        },
                        {
                            "seq": 1,
                            "title": "2012年新疆软件园大事记",
                            "show_cover_pic": 0,
                            "author": "",
                            "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3oErGEhSicRQc82icibxZOZ2YAGNgiaGYfOFYppmPzOOS0v1xfZ1nvyT58g/0",
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204883415&idx=2&sn=e7db9b30d770c85c61008d2f523b8610#rd",
                            "source_url": "",
                            "file_id": 204883398,
                            "digest": "1月1.新疆软件园环评顺利通过专家会评审2012年1月30日,新疆软件园环境影响评价顺利通过专家会评审,与会"
                        },
                        {
                            "seq": 2,
                            "title": "2011年新疆软件园大事记",
                            "show_cover_pic": 0,
                            "author": "",
                            "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3qA7tEN8GvkgDwnOfKsGsicJeQ6PxQSgWuJXfQaXkpM4VNlQicOWJM4Tg/0",
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204883415&idx=3&sn=4cb1c6d25cbe6dfeff37f52a62532bd0#rd",
                            "source_url": "",
                            "file_id": 204883393,
                            "digest": "6月1.软件园召开第一次建设领导小组会议2011年6月7日,第一次软件园建设领导小组会议召开,会议认为,新疆"
                        },
                        {
                            "seq": 3,
                            "title": "2010年新疆软件园大事记",
                            "show_cover_pic": 0,
                            "author": "",
                            "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3YG4sSuf9X9ecMPjDRju842IbIvpFWK7tuZs0Po4kZCz4URzOBj5rnQ/0",
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204883415&idx=4&sn=4319f7f051f36ed972e2f05a221738ec#rd",
                            "source_url": "",
                            "file_id": 204884043,
                            "digest": "5月1.新疆软件园与开发区(头屯河区)管委会、经信委签署《新疆软件园建设战略合作协议》2010年5月12日,"
                        }
                    ],
                    "seq": 1,
                    "title": "2013年新疆软件园大事记",
                    "show_cover_pic": 0,
                    "author": "",
                    "app_id": 204883415,
                    "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204883415&idx=1&sn=68d62215052d29ece3f2664e9c4e8cab#rd",
                    "create_time": "1405232974",
                    "file_id": 204883412,
                    "img_url": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3icvFgkxZRyIrkLbic9I5ZKLa3XB8UqNlkT8CYibByHuraSvVoeSzdTRLQ/0",
                    "digest": "1月1.新疆软件园展厅设计方案汇报会2013年1月15日在维泰大厦4楼9号会议室召开新疆软件园展厅设计工作完"
                }
            ]

        :param integer page: 页码 (从 0 开始)
        :param integer pagesize: 每页数目
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_dialog_message(fakeid [, last_msgid=0, create_time=0])

        获取与指定用户的对话内容, 获取的内容由 ``last_msgid`` (需要获取的对话中时间最早的 **公众号发送给用户** 的消息ID) 和 ``create_time`` (需要获取的对话中时间最早的消息时间戳) 进行过滤

        消息过滤规则:

        1. 首先按照 ``last_msgid`` 过滤 (不需要按照 ``last_msgid`` 过滤则不需要传入此参数)

            a. ``fakeid`` 为用户 UID
            b. 通过 ``last_msgid`` 去匹配公众号过去发送给用户的某一条消息
            c. 如果匹配成功, 则返回这条消息之后与这个用户相关的所有消息内容 (包括发送的消息和接收的)
            d. 如果匹配失败 (没有找到), 则返回与这个用户相关的所有消息 (包括发送的消息和接收的)

        2. 第一条规则返回的消息内容接着按照 ``create_time`` 进行过滤, 返回 ``create_time`` 时间戳之时及之后的所有消息 (不需要按照 ``create_time`` 过滤则不需要传入此参数)

        返回JSON示例::

            {
                "to_nick_name": "Doraemonext",
                "msg_items": {
                    "msg_item": [
                        {
                            "date_time": 1408671873,
                            "has_reply": 0,
                            "multi_item": [ ],
                            "msg_status": 4,
                            "nick_name": "Doraemonext",
                            "to_uin": 2391068708,
                            "content": "你呢",
                            "source": "",
                            "fakeid": "844735403",
                            "send_stat": {
                                "fail": 0,
                                "succ": 0,
                                "total": 0
                            },
                            "refuse_reason": "",
                            "type": 1,
                            "id": 206439567
                        },
                        {
                            "date_time": 1408529750,
                            "send_stat": {
                                "fail": 0,
                                "succ": 0,
                                "total": 0
                            },
                            "app_sub_type": 3,
                            "multi_item": [
                                {
                                    "seq": 0,
                                    "title": "软件企业有望拎包入住新疆软件园",
                                    "show_cover_pic": 1,
                                    "author": "",
                                    "cover": "https://mmbiz.qlogo.cn/mmbiz/D2pflbZwStFibz2Sb1kWOuHrxtDMPKJic3oErGEhSicRQc82icibxZOZ2YAGNgiaGYfOFYppmPzOOS0v1xfZ1nvyT58g/0",
                                    "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204885255&idx=1&sn=40e07d236a497e36d2d3e9711dfe090a#rd",
                                    "source_url": "",
                                    "content": "",
                                    "file_id": 204885252,
                                    "vote_id": [ ],
                                    "digest": "12月8日,国家软件公共服务平台新疆分平台在乌鲁木齐经济技术开发区(头屯河区)揭牌。这意味着,软件企业有"
                                }
                            ],
                            "msg_status": 2,
                            "title": "软件企业有望拎包入住新疆软件园",
                            "nick_name": "Doraemonext",
                            "to_uin": 844735403,
                            "content_url": "http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODcwOA==&mid=204885255&idx=1&sn=40e07d236a497e36d2d3e9711dfe090a#rd",
                            "show_type": 1,
                            "content": "",
                            "source": "biz",
                            "fakeid": "2391068708",
                            "file_id": 204885252,
                            "has_reply": 0,
                            "refuse_reason": "",
                            "type": 6,
                            "id": 206379033,
                            "desc": "12月8日,国家软件公共服务平台新疆分平台在乌鲁木齐经济技术开发区(头屯河区)揭牌。这意味着,软件企业有"
                        }
                    ]
                }
            }

        :param str fakeid: 用户 UID (即 fakeid )
        :param str last_msgid: 公众号之前发送给用户(fakeid)的消息 ID, 为 0 则表示全部消息
        :param str create_time: 获取这个时间戳之时及之后的消息,为 0 则表示全部消息
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: send_news(fakeid, msgid)

        向指定用户发送图文消息 (必须从图文库里选取消息ID传入)

        :param str fakeid: 用户的 UID (即 fakeid)
        :param str msgid: 图文消息 ID
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 具体内容有 ``fake id not exist`` 及 ``message id not exist``

   .. py:method:: add_news(news)

        在素材库中创建图文消息

        :param list news: list 对象, 其中的每个元素为一个 dict 对象, 代表一条图文, key 值分别为 ``title``, ``author``, ``summary``, ``content``, ``picture_id``, ``from_url``, 对应内容为标题, 作者, 摘要, 内容, 素材库里的图片ID(可通过 ``upload_file`` 函数上传获取), 来源链接。

                          其中必须提供的 key 值为 ``title`` 和 ``content``

                          示例::

                              [
                                  {
                                      'title': '图文标题',
                                      'author': '图文作者',
                                      'summary': '图文摘要',
                                      'content': '图文内容',
                                      'picture_id': '23412341',
                                      'from_url': 'http://www.baidu.com',
                                  },
                                  {
                                      'title': '最少图文标题',
                                      'content': '图文内容',
                                  }
                              ]
        :raises: ValueError 参数提供错误时抛出
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: upload_file(filepath)

        上传素材 (图片/音频/视频)

        :param str filepath: 本地文件路径
        :return: 直接返回上传后的文件 ID (fid)
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可 (常见错误内容: ``file not exist``: 找不到本地文件, ``audio too long``: 音频文件过长, ``file invalid type``: 文件格式不正确, 还有其他错误请自行检查)

   .. py:method:: send_file(fakeid, fid, type)

        向特定用户发送媒体文件

        :param str fakeid: 用户 UID (即 fakeid)
        :param str fid: 文件 ID
        :param integer type: 文件类型 (2: 图片, 3: 音频, 4: 视频)
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可 (常见错误内容: ``system error`` 或 ``can not send this type of msg``: 文件类型不匹配, ``user not exist``: 用户 fakeid 不存在, ``file not exist``: 文件 fid 不存在, 还有其他错误请自行检查)

   .. py:method:: get_file_list(type, page [, count=10])

        获取素材库文件列表

        返回JSON示例::

            {
                "type": 2,
                "file_item": [
                    {
                        "update_time": 1408723089,
                        "name": "Doraemonext.png",
                        "play_length": 0,
                        "file_id": 206471048,
                        "type": 2,
                        "size": "53.7 K"
                    },
                    {
                        "update_time": 1408722328,
                        "name": "Doraemonext.png",
                        "play_length": 0,
                        "file_id": 206470809,
                        "type": 2,
                        "size": "53.7 K"
                    }
                ],
                "file_cnt": {
                    "voice_cnt": 1,
                    "app_msg_cnt": 10,
                    "commondity_msg_cnt": 0,
                    "video_cnt": 0,
                    "img_cnt": 29,
                    "video_msg_cnt": 0,
                    "total": 40
                }
            }

        :param integer type: 文件类型 (2: 图片, 3: 音频, 4: 视频)
        :param integer page: 页码 (从 0 开始)
        :param integer count: 每页大小
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: send_image(fakeid, fid)

        给指定用户 fakeid 发送图片信息

        :param str fakeid: 用户的 UID (即 fakeid)
        :param str fid: 文件 ID
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可 (常见错误内容: ``system error`` 或 ``can not send this type of msg``: 文件类型不匹配, ``user not exist``: 用户 fakeid 不存在, ``file not exist``: 文件 fid 不存在, 还有其他错误请自行检查)

   .. py:method:: send_audio(fakeid, fid)

        给指定用户 fakeid 发送语音信息

        :param str fakeid: 用户的 UID (即 fakeid)
        :param str fid: 文件 ID
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可 (常见错误内容: ``system error`` 或 ``can not send this type of msg``: 文件类型不匹配, ``user not exist``: 用户 fakeid 不存在, ``file not exist``: 文件 fid 不存在, 还有其他错误请自行检查)

   .. py:method:: send_video(fakeid, fid)

        给指定用户 fakeid 发送视频消息

        :param str fakeid: 用户的 UID (即 fakeid)
        :param str fid: 文件 ID
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可 (常见错误内容: ``system error`` 或 ``can not send this type of msg``: 文件类型不匹配, ``user not exist``: 用户 fakeid 不存在, ``file not exist``: 文件 fid 不存在, 还有其他错误请自行检查)

   .. py:method:: get_user_info(fakeid)

        获取指定用户的个人信息

        返回JSON示例::

            {
                "province": "湖北",
                "city": "武汉",
                "gender": 1,
                "nick_name": "Doraemonext",
                "country": "中国",
                "remark_name": "",
                "fake_id": 844735403,
                "signature": "",
                "group_id": 0,
                "user_name": ""
            }

        :param str fakeid: 用户的 UID (即 fakeid)
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_avatar(fakeid)

        获取用户头像信息

        :param str fakeid: 用户的 UID (即 fakeid)
        :return: 二进制 JPG 数据字符串, 可直接作为 File Object 中 write 的参数
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_new_message_num(lastid=0)

        获取新消息的数目

        :param lastid: 最近获取的消息 ID, 为 0 时获取总消息数目
        :return: 消息数目
        :rtype: int

   .. py:method:: get_top_message()

        获取最新一条消息

        返回JSON示例::

            {
                "msg_item": [
                    {
                        "id": 206448489,
                        "type": 2,
                        "fakeid": "844735403",
                        "nick_name": "Doraemonext",
                        "date_time": 1408696938,
                        "source": "",
                        "msg_status": 4,
                        "has_reply": 0,
                        "refuse_reason": "",
                        "multi_item": [ ],
                        "to_uin": 2391068708,
                        "send_stat": {
                            "total": 0,
                            "succ": 0,
                            "fail": 0
                        }
                    }
                ]
            }

        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_message_list(lastid=0, offset=0, count=20, day=7, star=False)

        获取消息列表

        返回JSON示例 ::

            {
                "msg_item": [
                    {
                        "id": 206439583,
                        "type": 1,
                        "fakeid": "844735403",
                        "nick_name": "Doraemonext",
                        "date_time": 1408671892,
                        "content": "测试消息",
                        "source": "",
                        "msg_status": 4,
                        "has_reply": 0,
                        "refuse_reason": "",
                        "multi_item": [ ],
                        "to_uin": 2391068708,
                        "send_stat": {
                            "total": 0,
                            "succ": 0,
                            "fail": 0
                        }
                    },
                    {
                        "id": 206439579,
                        "type": 1,
                        "fakeid": "844735403",
                        "nick_name": "Doraemonext",
                        "date_time": 1408671889,
                        "content": "wechat-python-sdk",
                        "source": "",
                        "msg_status": 4,
                        "has_reply": 0,
                        "refuse_reason": "",
                        "multi_item": [ ],
                        "to_uin": 2391068708,
                        "send_stat": {
                            "total": 0,
                            "succ": 0,
                            "fail": 0
                        }
                    }
                ]
            }

        :param integer lastid: 传入最后的消息 id 编号, 为 0 则从最新一条起倒序获取
        :param integer offset: lastid 起算第一条的偏移量
        :param integer count: 获取数目
        :param integer day: 最近几天消息 (0: 今天, 1: 昨天, 2: 前天, 3: 更早, 7: 全部), 这里的全部仅有5天
        :param boolean star: 是否只获取星标消息
        :return: 返回的 JSON 数据
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据

   .. py:method:: get_message_image(msgid, mode='large')

        根据消息 ID 获取图片消息内容

        :param str msgid: 消息 ID
        :param str mode: 图片尺寸 ('large'或'small')
        :return: 二进制 JPG 图片字符串, 可直接作为 File Object 中 write 的参数
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可, 错误内容: ``image message not exist``: msg参数无效, ``mode error``: mode参数无效

   .. py:method:: get_message_voice(msgid)

        根据消息 ID 获取语音消息内容

        :param str msgid: 消息 ID
        :return: 二进制 MP3 音频字符串, 可直接作为 File Object 中 write 的参数
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可, 错误内容: ``voice message not exist``: msg参数无效

   .. py:method:: get_message_video(msgid)

        根据消息 ID 获取视频消息内容

        :param str msgid: 消息 ID
        :return: 二进制 MP4 视频字符串, 可直接作为 File Object 中 write 的参数
        :raises: NeedLoginError 操作未执行成功, 需要再次尝试登录, 异常内容为服务器返回的错误数据
        :raises: ValueError 参数出错, 错误原因直接打印异常即可, 错误内容: ``video message not exist``: msg参数无效