{"componentChunkName":"component---src-templates-best-practice-detail-tsx","path":"/best-practice/2020-05-05-ai-wechat","result":{"data":{"currentBlog":{"id":"d1450693-7418-5532-8bd4-4fe42f275bdf","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020512/1589274622959-J2kmfdLCPpX436WYvs0D.jpg","authors":["Anycodes"],"categories":["best-practice"],"date":"2020-05-05T00:00:00.000Z","title":"Serverless 与人工智能实现微信公众号的智能服务","description":"一般情况下，想给公众号增加更多的功能，需要我们在服务器上搭建后台服务。那么在 Serverless 架构下，能否更简单地实现相同的后台服务呢？","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["Serverless","人工智能"],"keywords":"Serverless 多环境配置,Serverless 管理环境,Serverless配置方案","outdated":true},"wordCount":{"words":519,"sentences":119,"paragraphs":119},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-05-05-ai-wechat.md","fields":{"slug":"/best-practice/2020-05-05-ai-wechat/","keywords":["python","serverless","函数计算","函数计算服务","event","json","media","time"]},"html":"<p>一般来说，想给微信公众号增加更多的功能，需要有一台服务器，来进行公众号后台服务的搭建。那么在 Serverless 架构下，是否有更简便的方法来实现这么一个公众号后台呢？我们试试？</p>\n<h2 id=\"初步搭建\"><a href=\"#%E5%88%9D%E6%AD%A5%E6%90%AD%E5%BB%BA\" aria-label=\"初步搭建 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>初步搭建</h2>\n<h3 id=\"serverless-原生开发\"><a href=\"#serverless-%E5%8E%9F%E7%94%9F%E5%BC%80%E5%8F%91\" aria-label=\"serverless 原生开发 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Serverless 原生开发</h3>\n<p>首先我们当然要有一个微信公众号！</p>\n<p>接下来，我们要为我们的函数计算服务申请固定 IP：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-2.jpeg\"></p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-3.jpeg\"></p>\n<p>点击白名单之后，我们可以填写表单，完成固定公网出口 IP 的申请。</p>\n<p>接下来进行代码开发。</p>\n<ol>\n<li>将函数绑定到公众号后台，参考文档：<a href=\"https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html\">https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html</a>\n我们可以先在函数中按照文档完成一个基本的鉴定功能：</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"35593793641127780000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def checkSignature(param):\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html\n    :param param:\n    :return:\n    '''\n    signature = param['signature']\n    timestamp = param['timestamp']\n    nonce = param[&quot;nonce&quot;]\n    tmparr = [wxtoken, timestamp, nonce]\n    tmparr.sort()\n    tmpstr = ''.join(tmparr)\n    tmpstr = hashlib.sha1(tmpstr.encode(&quot;utf-8&quot;)).hexdigest()\n    return tmpstr == signature`, `35593793641127780000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">checkSignature</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html\n    :param param:\n    :return:\n    '''</span>\n    signature <span class=\"token operator\">=</span> param<span class=\"token punctuation\">[</span><span class=\"token string\">'signature'</span><span class=\"token punctuation\">]</span>\n    timestamp <span class=\"token operator\">=</span> param<span class=\"token punctuation\">[</span><span class=\"token string\">'timestamp'</span><span class=\"token punctuation\">]</span>\n    nonce <span class=\"token operator\">=</span> param<span class=\"token punctuation\">[</span><span class=\"token string\">\"nonce\"</span><span class=\"token punctuation\">]</span>\n    tmparr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>wxtoken<span class=\"token punctuation\">,</span> timestamp<span class=\"token punctuation\">,</span> nonce<span class=\"token punctuation\">]</span>\n    tmparr<span class=\"token punctuation\">.</span>sort<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    tmpstr <span class=\"token operator\">=</span> <span class=\"token string\">''</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>tmparr<span class=\"token punctuation\">)</span>\n    tmpstr <span class=\"token operator\">=</span> hashlib<span class=\"token punctuation\">.</span>sha1<span class=\"token punctuation\">(</span>tmpstr<span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>hexdigest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> tmpstr <span class=\"token operator\">==</span> signature</code></pre></div>\n<p>再定义一个基本的回复方法：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"52165425737083690000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def response(body, status=200):\n    return {\n        &quot;isBase64Encoded&quot;: False,\n        &quot;statusCode&quot;: status,\n        &quot;headers&quot;: {&quot;Content-Type&quot;: &quot;text/html&quot;},\n        &quot;body&quot;: body\n    }`, `52165425737083690000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">response</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> status<span class=\"token operator\">=</span><span class=\"token number\">200</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"isBase64Encoded\"</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">False</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"statusCode\"</span><span class=\"token punctuation\">:</span> status<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"headers\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"Content-Type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"text/html\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"body\"</span><span class=\"token punctuation\">:</span> body\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>然后在函数入口处：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"93269029466690980000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def main_handler(event, context):\n    if 'echostr' in event['queryString']:  # 接入时的校验\n        return response(event['queryString']['echostr'] if checkSignature(event['queryString']) else False)`, `93269029466690980000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">if</span> <span class=\"token string\">'echostr'</span> <span class=\"token keyword\">in</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 接入时的校验</span>\n        <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'echostr'</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">if</span> checkSignature<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">else</span> <span class=\"token boolean\">False</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>配置我们 Yaml：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"93863840084240330000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# serverless.yml\nWeixin_GoServerless:\n  component: &quot;@serverless/tencent-scf&quot;\n  inputs:\n    name: Weixin_GoServerless\n    codeUri: ./Admin\n    handler: index.main_handler\n    runtime: Python3.6\n    region: ap-shanghai\n    description: 微信公众号后台服务器配置\n    memorySize: 128\n    timeout: 20\n    environment:\n      variables:\n        wxtoken: 自定义一个字符串\n        appid: 暂时不写\n        secret: 暂时不写\n    events:\n      - apigw:\n          name: Weixin_GoServerless\n          parameters:\n            protocols:\n              - https\n            environment: release\n            endpoints:\n              - path: /\n                method: ANY\n                function:\n                  isIntegratedResponse: TRUE`, `93863840084240330000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token comment\"># serverless.yml</span>\n<span class=\"token key atrule\">Weixin_GoServerless</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">component</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"@serverless/tencent-scf\"</span>\n  <span class=\"token key atrule\">inputs</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Weixin_GoServerless\n    <span class=\"token key atrule\">codeUri</span><span class=\"token punctuation\">:</span> ./Admin\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> index.main_handler\n    <span class=\"token key atrule\">runtime</span><span class=\"token punctuation\">:</span> Python3.6\n    <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> ap<span class=\"token punctuation\">-</span>shanghai\n    <span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> 微信公众号后台服务器配置\n    <span class=\"token key atrule\">memorySize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">128</span>\n    <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n    <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">variables</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">wxtoken</span><span class=\"token punctuation\">:</span> 自定义一个字符串\n        <span class=\"token key atrule\">appid</span><span class=\"token punctuation\">:</span> 暂时不写\n        <span class=\"token key atrule\">secret</span><span class=\"token punctuation\">:</span> 暂时不写\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Weixin_GoServerless\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">protocols</span><span class=\"token punctuation\">:</span>\n              <span class=\"token punctuation\">-</span> https\n            <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token key atrule\">endpoints</span><span class=\"token punctuation\">:</span>\n              <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /\n                <span class=\"token key atrule\">method</span><span class=\"token punctuation\">:</span> ANY\n                <span class=\"token key atrule\">function</span><span class=\"token punctuation\">:</span>\n                  <span class=\"token key atrule\">isIntegratedResponse</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">TRUE</span></code></pre></div>\n<p>执行代码，完成部署：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-4.jpeg\"></p>\n<p>接下来在公众号后台，选择基本配置：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-5.jpeg\"></p>\n<p>选择修改配置：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-6.jpeg\"></p>\n<p>这里要注意：</p>\n<ul>\n<li>URL，写我们刚才部署完成返回给我们的地址，并且在最后加一个 /</li>\n<li>Token，写我们 Yaml 中的 wxtoken，两个地方要保持一样的字符串</li>\n<li>EncodingAESKey，可以点击随机生成</li>\n<li>消息加密方法可以选择明文</li>\n</ul>\n<p>完成之后，我们可以点击提交：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-7.jpeg\"></p>\n<p>看到提交成功，就说明我们已经完成了第一步骤的绑定。接下来，我们到函数的后台：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-8.jpeg\"></p>\n<p>打开固定出口 IP，看到 IP 地址之后，复制 IP 地址：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-9.jpeg\"></p>\n<p>点击查看->修改，并将 IP 地址复制粘贴进来，保存。\n同时我们查看开发者 ID 和密码：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-10.jpeg\"></p>\n<p>并将这两个内容复制粘贴，放到我们环境变量中：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-11.jpeg\"></p>\n<p>至此，我们完成了一个公众号后台服务的绑定。</p>\n<p>为了方便之后的操作，先获取一下全局变量：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"68856581189509830000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`wxtoken = os.environ.get('wxtoken')\nappid = os.environ.get('appid')\nsecret = os.environ.get('secret')`, `68856581189509830000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">wxtoken <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'wxtoken'</span><span class=\"token punctuation\">)</span>\nappid <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'appid'</span><span class=\"token punctuation\">)</span>\nsecret <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<ol start=\"2\">\n<li>接下来对各个模块进行编辑（本文只提供部分简单基础的模块，更多功能实现可以参考微信公众号文档实现）</li>\n<li>获取 AccessToken 模块：</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"46569939281512340000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def getAccessToken():\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html\n    正常返回：{&quot;access_token&quot;:&quot;ACCESS_TOKEN&quot;,&quot;expires_in&quot;:7200}\n    异常返回：{&quot;errcode&quot;:40013,&quot;errmsg&quot;:&quot;invalid appid&quot;}\n    :return:\n    '''\n    url = &quot;https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s&quot; % (appid, secret)\n    accessToken = json.loads(urllib.request.urlopen(url).read().decode(&quot;utf-8&quot;))\n    print(accessToken)\n    return None if &quot;errcode&quot; in accessToken else accessToken[&quot;access_token&quot;]`, `46569939281512340000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">getAccessToken</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html\n    正常返回：{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}\n    异常返回：{\"errcode\":40013,\"errmsg\":\"invalid appid\"}\n    :return:\n    '''</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=%s&amp;secret=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>appid<span class=\"token punctuation\">,</span> secret<span class=\"token punctuation\">)</span>\n    accessToken <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>accessToken<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">None</span> <span class=\"token keyword\">if</span> <span class=\"token string\">\"errcode\"</span> <span class=\"token keyword\">in</span> accessToken <span class=\"token keyword\">else</span> accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">]</span></code></pre></div>\n<ul>\n<li>创建自定义菜单模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"54352626708101145000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def setMenu(menu):\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html\n    正确返回：{&quot;errcode&quot;:0,&quot;errmsg&quot;:&quot;ok&quot;}\n    异常返回：{&quot;errcode&quot;:40018,&quot;errmsg&quot;:&quot;invalid button name size&quot;}\n    :return:\n    '''\n    accessToken = getAccessToken()\n    if not accessToken:\n        return &quot;Get Access Token Error&quot;\n\n    url = &quot;https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s&quot; % accessToken\n    postData = urllib.parse.urlencode(menu).encode(&quot;utf-8&quot;)\n    requestAttr = urllib.request.Request(url=url, data=postData)\n    responseAttr = urllib.request.urlopen(requestAttr)\n    responseData = json.loads(responseAttr.read())\n    return responseData['errmsg'] if &quot;errcode&quot; in responseData else &quot;success&quot;`, `54352626708101145000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">setMenu</span><span class=\"token punctuation\">(</span>menu<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html\n    正确返回：{\"errcode\":0,\"errmsg\":\"ok\"}\n    异常返回：{\"errcode\":40018,\"errmsg\":\"invalid button name size\"}\n    :return:\n    '''</span>\n    accessToken <span class=\"token operator\">=</span> getAccessToken<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> accessToken<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"Get Access Token Error\"</span>\n\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s\"</span> <span class=\"token operator\">%</span> accessToken\n    postData <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">.</span>urlencode<span class=\"token punctuation\">(</span>menu<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    requestAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span> data<span class=\"token operator\">=</span>postData<span class=\"token punctuation\">)</span>\n    responseAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>requestAttr<span class=\"token punctuation\">)</span>\n    responseData <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>responseAttr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> responseData<span class=\"token punctuation\">[</span><span class=\"token string\">'errmsg'</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">if</span> <span class=\"token string\">\"errcode\"</span> <span class=\"token keyword\">in</span> responseData <span class=\"token keyword\">else</span> <span class=\"token string\">\"success\"</span></code></pre></div>\n<ul>\n<li>常见消息回复模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"14020825441749252000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def textXML(body, event):\n    '''\n    :param body: {&quot;msg&quot;: &quot;test&quot;}\n        msg: 必填，回复的消息内容（换行：在content中能够换行，微信客户端就支持换行显示）\n    :param event:\n    :return:\n    '''\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[text]]></MsgType>\n              <Content><![CDATA[{msg}]]></Content></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                                                   fromUser=event[&quot;ToUserName&quot;],\n                                                                   time=int(time.time()),\n                                                                   msg=body[&quot;msg&quot;])\n\n\ndef pictureXML(body, event):\n    '''\n    :param body:  {&quot;media_id&quot;: 123}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id。\n    :param event:\n    :return:\n    '''\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[image]]></MsgType>\n              <Image>\n                <MediaId><![CDATA[{media_id}]]></MediaId>\n              </Image></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                       fromUser=event[&quot;ToUserName&quot;],\n                                       time=int(time.time()),\n                                       media_id=body[&quot;media_id&quot;])\n\n\ndef voiceXML(body, event):\n    '''\n    :param body: {&quot;media_id&quot;: 123}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id\n    :param event:\n    :return:\n    '''\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[voice]]></MsgType>\n              <Voice>\n                <MediaId><![CDATA[{media_id}]]></MediaId>\n              </Voice></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                       fromUser=event[&quot;ToUserName&quot;],\n                                       time=int(time.time()),\n                                       media_id=body[&quot;media_id&quot;])\n\n\ndef videoXML(body, event):\n    '''\n    :param body: {&quot;media_id&quot;: 123, &quot;title&quot;: &quot;test&quot;, &quot;description&quot;: &quot;test}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id\n        title:：选填，视频消息的标题\n        description：选填，视频消息的描述\n    :param event:\n    :return:\n    '''\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[video]]></MsgType>\n              <Video>\n                <MediaId><![CDATA[{media_id}]]></MediaId>\n                <Title><![CDATA[{title}]]></Title>\n                <Description><![CDATA[{description}]]></Description>\n              </Video></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                       fromUser=event[&quot;ToUserName&quot;],\n                                       time=int(time.time()),\n                                       media_id=body[&quot;media_id&quot;],\n                                       title=body.get('title', ''),\n                                       description=body.get('description', ''))\n\n\ndef musicXML(body, event):\n    '''\n    :param body:  {&quot;media_id&quot;: 123, &quot;title&quot;: &quot;test&quot;, &quot;description&quot;: &quot;test}\n        media_id：必填，缩略图的媒体id，通过素材管理中的接口上传多媒体文件，得到的id\n        title：选填，音乐标题\n        description：选填，音乐描述\n        url：选填，音乐链接\n        hq_url：选填，高质量音乐链接，WIFI环境优先使用该链接播放音乐\n    :param event:\n    :return:\n    '''\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[music]]></MsgType>\n              <Music>\n                <Title><![CDATA[{title}]]></Title>\n                <Description><![CDATA[{description}]]></Description>\n                <MusicUrl><![CDATA[{url}]]></MusicUrl>\n                <HQMusicUrl><![CDATA[{hq_url}]]></HQMusicUrl>\n                <ThumbMediaId><![CDATA[{media_id}]]></ThumbMediaId>\n              </Music></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                       fromUser=event[&quot;ToUserName&quot;],\n                                       time=int(time.time()),\n                                       media_id=body[&quot;media_id&quot;],\n                                       title=body.get('title', ''),\n                                       url=body.get('url', ''),\n                                       hq_url=body.get('hq_url', ''),\n                                       description=body.get('description', ''))\n\n\ndef articlesXML(body, event):\n    '''\n    :param body: 一个list [{&quot;title&quot;:&quot;test&quot;, &quot;description&quot;: &quot;test&quot;, &quot;picUrl&quot;: &quot;test&quot;, &quot;url&quot;: &quot;test&quot;}]\n        title：必填，图文消息标题\n        description：必填，图文消息描述\n        picUrl：必填，图片链接，支持JPG、PNG格式，较好的效果为大图360*200，小图200*200\n        url：必填，点击图文消息跳转链接\n    :param event:\n    :return:\n    '''\n    if len(body[&quot;articles&quot;]) > 8:  # 最多只允许返回8个\n        body[&quot;articles&quot;] = body[&quot;articles&quot;][0:8]\n    tempArticle = &quot;&quot;&quot;<item>\n      <Title><![CDATA[{title}]]></Title>\n      <Description><![CDATA[{description}]]></Description>\n      <PicUrl><![CDATA[{picurl}]]></PicUrl>\n      <Url><![CDATA[{url}]]></Url>\n    </item>&quot;&quot;&quot;\n    return &quot;&quot;&quot;<xml><ToUserName><![CDATA[{toUser}]]></ToUserName>\n              <FromUserName><![CDATA[{fromUser}]]></FromUserName>\n              <CreateTime>{time}</CreateTime>\n              <MsgType><![CDATA[news]]></MsgType>\n              <ArticleCount>{count}</ArticleCount>\n              <Articles>\n                {articles}\n              </Articles></xml>&quot;&quot;&quot;.format(toUser=event[&quot;FromUserName&quot;],\n                                          fromUser=event[&quot;ToUserName&quot;],\n                                          time=int(time.time()),\n                                          count=len(body[&quot;articles&quot;]),\n                                          articles=&quot;&quot;.join([tempArticle.format(\n                                              title=eveArticle['title'],\n                                              description=eveArticle['description'],\n                                              picurl=eveArticle['picurl'],\n                                              url=eveArticle['url']\n                                          ) for eveArticle in body[&quot;articles&quot;]]))`, `14020825441749252000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">textXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body: {\"msg\": \"test\"}\n        msg: 必填，回复的消息内容（换行：在content中能够换行，微信客户端就支持换行显示）\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[text]]>&lt;/MsgType>\n              &lt;Content>&lt;![CDATA[{msg}]]>&lt;/Content>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                                                   fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                                                   time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                                                   msg<span class=\"token operator\">=</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">pictureXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body:  {\"media_id\": 123}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id。\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[image]]>&lt;/MsgType>\n              &lt;Image>\n                &lt;MediaId>&lt;![CDATA[{media_id}]]>&lt;/MediaId>\n              &lt;/Image>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       media_id<span class=\"token operator\">=</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">voiceXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body: {\"media_id\": 123}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[voice]]>&lt;/MsgType>\n              &lt;Voice>\n                &lt;MediaId>&lt;![CDATA[{media_id}]]>&lt;/MediaId>\n              &lt;/Voice>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       media_id<span class=\"token operator\">=</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">videoXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body: {\"media_id\": 123, \"title\": \"test\", \"description\": \"test}\n        media_id: 必填，通过素材管理中的接口上传多媒体文件，得到的id\n        title:：选填，视频消息的标题\n        description：选填，视频消息的描述\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[video]]>&lt;/MsgType>\n              &lt;Video>\n                &lt;MediaId>&lt;![CDATA[{media_id}]]>&lt;/MediaId>\n                &lt;Title>&lt;![CDATA[{title}]]>&lt;/Title>\n                &lt;Description>&lt;![CDATA[{description}]]>&lt;/Description>\n              &lt;/Video>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       media_id<span class=\"token operator\">=</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       title<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'title'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       description<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'description'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">musicXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body:  {\"media_id\": 123, \"title\": \"test\", \"description\": \"test}\n        media_id：必填，缩略图的媒体id，通过素材管理中的接口上传多媒体文件，得到的id\n        title：选填，音乐标题\n        description：选填，音乐描述\n        url：选填，音乐链接\n        hq_url：选填，高质量音乐链接，WIFI环境优先使用该链接播放音乐\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[music]]>&lt;/MsgType>\n              &lt;Music>\n                &lt;Title>&lt;![CDATA[{title}]]>&lt;/Title>\n                &lt;Description>&lt;![CDATA[{description}]]>&lt;/Description>\n                &lt;MusicUrl>&lt;![CDATA[{url}]]>&lt;/MusicUrl>\n                &lt;HQMusicUrl>&lt;![CDATA[{hq_url}]]>&lt;/HQMusicUrl>\n                &lt;ThumbMediaId>&lt;![CDATA[{media_id}]]>&lt;/ThumbMediaId>\n              &lt;/Music>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       media_id<span class=\"token operator\">=</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                       title<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'title'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       url<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'url'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       hq_url<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'hq_url'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                       description<span class=\"token operator\">=</span>body<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'description'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">articlesXML</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    :param body: 一个list [{\"title\":\"test\", \"description\": \"test\", \"picUrl\": \"test\", \"url\": \"test\"}]\n        title：必填，图文消息标题\n        description：必填，图文消息描述\n        picUrl：必填，图片链接，支持JPG、PNG格式，较好的效果为大图360*200，小图200*200\n        url：必填，点击图文消息跳转链接\n    :param event:\n    :return:\n    '''</span>\n    <span class=\"token keyword\">if</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"articles\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">8</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 最多只允许返回8个</span>\n        body<span class=\"token punctuation\">[</span><span class=\"token string\">\"articles\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> body<span class=\"token punctuation\">[</span><span class=\"token string\">\"articles\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">:</span><span class=\"token number\">8</span><span class=\"token punctuation\">]</span>\n    tempArticle <span class=\"token operator\">=</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;item>\n      &lt;Title>&lt;![CDATA[{title}]]>&lt;/Title>\n      &lt;Description>&lt;![CDATA[{description}]]>&lt;/Description>\n      &lt;PicUrl>&lt;![CDATA[{picurl}]]>&lt;/PicUrl>\n      &lt;Url>&lt;![CDATA[{url}]]>&lt;/Url>\n    &lt;/item>\"\"\"</span>\n    <span class=\"token keyword\">return</span> <span class=\"token triple-quoted-string string\">\"\"\"&lt;xml>&lt;ToUserName>&lt;![CDATA[{toUser}]]>&lt;/ToUserName>\n              &lt;FromUserName>&lt;![CDATA[{fromUser}]]>&lt;/FromUserName>\n              &lt;CreateTime>{time}&lt;/CreateTime>\n              &lt;MsgType>&lt;![CDATA[news]]>&lt;/MsgType>\n              &lt;ArticleCount>{count}&lt;/ArticleCount>\n              &lt;Articles>\n                {articles}\n              &lt;/Articles>&lt;/xml>\"\"\"</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>toUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                          fromUser<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"ToUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                          time<span class=\"token operator\">=</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                          count<span class=\"token operator\">=</span><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">[</span><span class=\"token string\">\"articles\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                          articles<span class=\"token operator\">=</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>tempArticle<span class=\"token punctuation\">.</span><span class=\"token builtin\">format</span><span class=\"token punctuation\">(</span>\n                                              title<span class=\"token operator\">=</span>eveArticle<span class=\"token punctuation\">[</span><span class=\"token string\">'title'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                              description<span class=\"token operator\">=</span>eveArticle<span class=\"token punctuation\">[</span><span class=\"token string\">'description'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                              picurl<span class=\"token operator\">=</span>eveArticle<span class=\"token punctuation\">[</span><span class=\"token string\">'picurl'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                              url<span class=\"token operator\">=</span>eveArticle<span class=\"token punctuation\">[</span><span class=\"token string\">'url'</span><span class=\"token punctuation\">]</span>\n                                          <span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> eveArticle <span class=\"token keyword\">in</span> body<span class=\"token punctuation\">[</span><span class=\"token string\">\"articles\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<ul>\n<li>\n<p>对 main_handler 进行修改，使其：</p>\n<ul>\n<li>识别绑定功能</li>\n<li>识别基本信息</li>\n<li>识别特殊额外请求（例如通过url触发自定义菜单的更新）</li>\n</ul>\n</li>\n</ul>\n<p>整体代码：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"24482174570687554000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def main_handler(event, context):\n    print('event: ', event)\n\n    if event[&quot;path&quot;] == '/setMenu':  # 设置菜单接口\n        menu = {\n            &quot;button&quot;: [\n                {\n                    &quot;type&quot;: &quot;view&quot;,\n                    &quot;name&quot;: &quot;精彩文章&quot;,\n                    &quot;url&quot;: &quot;https://mp.weixin.qq.com/mp/homepage?__biz=Mzg2NzE4MDExNw==&hid=2&sn=168bd0620ee79cd35d0a80cddb9f2487&quot;\n                },\n                {\n                    &quot;type&quot;: &quot;view&quot;,\n                    &quot;name&quot;: &quot;开源项目&quot;,\n                    &quot;url&quot;: &quot;https://mp.weixin.qq.com/mp/homepage?__biz=Mzg2NzE4MDExNw==&hid=1&sn=69444401c5ed9746aeb1384fa6a9a201&quot;\n                },\n                {\n                    &quot;type&quot;: &quot;miniprogram&quot;,\n                    &quot;name&quot;: &quot;在线编程&quot;,\n                    &quot;appid&quot;: &quot;wx453cb539f9f963b2&quot;,\n                    &quot;pagepath&quot;: &quot;/page/index&quot;\n                }]\n        }\n        return response(setMenu(menu))\n\n    if 'echostr' in event['queryString']:  # 接入时的校验\n        return response(event['queryString']['echostr'] if checkSignature(event['queryString']) else False)\n    else:  # 用户消息/事件\n        event = getEvent(event)\n        if event[&quot;MsgType&quot;] == &quot;text&quot;:\n            # 文本消息\n            return response(body=textXML({&quot;msg&quot;: &quot;这是一个文本消息&quot;}, event))\n        elif event[&quot;MsgType&quot;] == &quot;image&quot;:\n            # 图片消息\n            return response(body=textXML({&quot;msg&quot;: &quot;这是一个图片消息&quot;}, event))\n        elif event[&quot;MsgType&quot;] == &quot;voice&quot;:\n            # 语音消息\n            pass\n        elif event[&quot;MsgType&quot;] == &quot;video&quot;:\n            # 视频消息\n            pass\n        elif event[&quot;MsgType&quot;] == &quot;shortvideo&quot;:\n            # 小视频消息\n            pass\n        elif event[&quot;MsgType&quot;] == &quot;location&quot;:\n            # 地理位置消息\n            pass\n        elif event[&quot;MsgType&quot;] == &quot;link&quot;:\n            # 链接消息\n            pass\n        elif event[&quot;MsgType&quot;] == &quot;event&quot;:\n            # 事件消息\n            if event[&quot;Event&quot;] == &quot;subscribe&quot;:\n                # 订阅事件\n                if event.get('EventKey', None):\n                    # 用户未关注时，进行关注后的事件推送（带参数的二维码）\n                    pass\n                else:\n                    # 普通关注\n                    pass\n            elif event[&quot;Event&quot;] == &quot;unsubscribe&quot;:\n                # 取消订阅事件\n                pass\n            elif event[&quot;Event&quot;] == &quot;SCAN&quot;:\n                # 用户已关注时的事件推送（带参数的二维码）\n                pass\n            elif event[&quot;Event&quot;] == &quot;LOCATION&quot;:\n                # 上报地理位置事件\n                pass\n            elif event[&quot;Event&quot;] == &quot;CLICK&quot;:\n                # 点击菜单拉取消息时的事件推送\n                pass\n            elif event[&quot;Event&quot;] == &quot;VIEW&quot;:\n                # 点击菜单跳转链接时的事件推送\n                pass`, `24482174570687554000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'event: '</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"path\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">'/setMenu'</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 设置菜单接口</span>\n        menu <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token string\">\"button\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token string\">\"type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"view\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"精彩文章\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://mp.weixin.qq.com/mp/homepage?__biz=Mzg2NzE4MDExNw==&amp;hid=2&amp;sn=168bd0620ee79cd35d0a80cddb9f2487\"</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token string\">\"type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"view\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"开源项目\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://mp.weixin.qq.com/mp/homepage?__biz=Mzg2NzE4MDExNw==&amp;hid=1&amp;sn=69444401c5ed9746aeb1384fa6a9a201\"</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token string\">\"type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"miniprogram\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"在线编程\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"appid\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"wx453cb539f9f963b2\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"pagepath\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"/page/index\"</span>\n                <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>setMenu<span class=\"token punctuation\">(</span>menu<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token string\">'echostr'</span> <span class=\"token keyword\">in</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 接入时的校验</span>\n        <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'echostr'</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">if</span> checkSignature<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'queryString'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">else</span> <span class=\"token boolean\">False</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 用户消息/事件</span>\n        event <span class=\"token operator\">=</span> getEvent<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"text\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 文本消息</span>\n            <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"这是一个文本消息\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"image\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 图片消息</span>\n            <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"这是一个图片消息\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"voice\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 语音消息</span>\n            <span class=\"token keyword\">pass</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"video\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 视频消息</span>\n            <span class=\"token keyword\">pass</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"shortvideo\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 小视频消息</span>\n            <span class=\"token keyword\">pass</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"location\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 地理位置消息</span>\n            <span class=\"token keyword\">pass</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"link\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 链接消息</span>\n            <span class=\"token keyword\">pass</span>\n        <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"event\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token comment\"># 事件消息</span>\n            <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"subscribe\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 订阅事件</span>\n                <span class=\"token keyword\">if</span> event<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'EventKey'</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">None</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token comment\"># 用户未关注时，进行关注后的事件推送（带参数的二维码）</span>\n                    <span class=\"token keyword\">pass</span>\n                <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token comment\"># 普通关注</span>\n                    <span class=\"token keyword\">pass</span>\n            <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"unsubscribe\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 取消订阅事件</span>\n                <span class=\"token keyword\">pass</span>\n            <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"SCAN\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 用户已关注时的事件推送（带参数的二维码）</span>\n                <span class=\"token keyword\">pass</span>\n            <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"LOCATION\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 上报地理位置事件</span>\n                <span class=\"token keyword\">pass</span>\n            <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"CLICK\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 点击菜单拉取消息时的事件推送</span>\n                <span class=\"token keyword\">pass</span>\n            <span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Event\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"VIEW\"</span><span class=\"token punctuation\">:</span>\n                <span class=\"token comment\"># 点击菜单跳转链接时的事件推送</span>\n                <span class=\"token keyword\">pass</span></code></pre></div>\n<p>在上述代码中可以看到：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"56313282596924100000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`if event[&quot;MsgType&quot;] == &quot;text&quot;:\n    # 文本消息\n    return response(body=textXML({&quot;msg&quot;: &quot;这是一个文本消息&quot;}, event))\nelif event[&quot;MsgType&quot;] == &quot;image&quot;:\n    # 图片消息\n    return response(body=textXML({&quot;msg&quot;: &quot;这是一个图片消息&quot;}, event))`, `56313282596924100000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">if</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"text\"</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># 文本消息</span>\n    <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"这是一个文本消息\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">elif</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"MsgType\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"image\"</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># 图片消息</span>\n    <span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"这是一个图片消息\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>这里就是说，当用户发送了文本消息时候，我们给用户回复一个文本消息：这是一个文本消息。当用户发送了一个图片，我们给用户返回这是一个图片消息，用这两个功能测试我们这个后台的连通性：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-12.jpeg\"></p>\n<p>可以看到，系统已经可以正常返回。</p>\n<p>有人问了，这样一个简单的 Demo 有什么意义呢？可以告诉大家，我们可以很轻量地通过一个函数来实现微信公众号的后端服务；这里都是基础能力，我们可以在这个基础能力之上，尽情添加创新力，例如：</p>\n<ol>\n<li>用户传过来的是图片消息，我们可以通过一些识图 API 告诉用户这个图片包括了什么？</li>\n<li>用户传过来的是文字消息，我们可以先设定一些帮助信息/检索信息进行对比，如果没找到就给用户开启聊天功能（这里涉及到人工智能中的自然语言处理，例如文本相似度检测）</li>\n<li>如果用户发送的是语音，我们还可以将其转成文本，生成对话消息，然后再转换成语音返回给用户</li>\n<li>如果用户发送了地理位置信息，我们可以返回用户所在经纬度的街景信息，或者周边生活服务信息等</li>\n<li>留给大家想象！</li>\n</ol>\n<h3 id=\"使用-werobot-框架\"><a href=\"#%E4%BD%BF%E7%94%A8-werobot-%E6%A1%86%E6%9E%B6\" aria-label=\"使用 werobot 框架 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>使用 Werobot 框架</h3>\n<p>上面的方法，是通过 Serverless 原生开发的方法进行对接。除此之外，我们还可以选择一些已有的框架，例如<code class=\"language-text\">werobot</code>等。</p>\n<p>WeRoBot 是一个微信公众号开发框架。通过 Serverless Component 中的<code class=\"language-text\">tencent-werobot</code>组件快速部署该框架：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"55467483382317130000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`Weixin_Werobot:\n  component: &quot;@serverless/tencent-werobot&quot;\n  inputs:\n    functionName: Weixin_Werobot\n    code: ./test\n    werobotProjectName: app\n    werobotAttrName: robot\n    functionConf:\n      timeout: 10\n      memorySize: 256\n      environment:\n        variables:\n          wxtoken: 你的token\n      apigatewayConf:\n        protocols:\n          - http\n        environment: release`, `55467483382317130000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">Weixin_Werobot</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">component</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"@serverless/tencent-werobot\"</span>\n  <span class=\"token key atrule\">inputs</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">functionName</span><span class=\"token punctuation\">:</span> Weixin_Werobot\n    <span class=\"token key atrule\">code</span><span class=\"token punctuation\">:</span> ./test\n    <span class=\"token key atrule\">werobotProjectName</span><span class=\"token punctuation\">:</span> app\n    <span class=\"token key atrule\">werobotAttrName</span><span class=\"token punctuation\">:</span> robot\n    <span class=\"token key atrule\">functionConf</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">10</span>\n      <span class=\"token key atrule\">memorySize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">256</span>\n      <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">variables</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">wxtoken</span><span class=\"token punctuation\">:</span> 你的token\n      <span class=\"token key atrule\">apigatewayConf</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">protocols</span><span class=\"token punctuation\">:</span>\n          <span class=\"token punctuation\">-</span> http\n        <span class=\"token key atrule\">environment</span><span class=\"token punctuation\">:</span> release</code></pre></div>\n<p>然后新建代码：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"80202547367478920000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import os\nimport werobot\n\nrobot = werobot.WeRoBot(token=os.environ.get('wxtoken'))\n\nrobot.config['SESSION_STORAGE'] = False\nrobot.config[&quot;APP_ID&quot;] = os.environ.get('appid')\nrobot.config[&quot;APP_SECRET&quot;] = os.environ.get('secret')\n\n# @robot.handler 处理所有消息\n@robot.handler\ndef hello(message):\n    return 'Hello World!'\n\nif __name__ == &quot;__main__&quot;:\n    # 让服务器监听在 0.0.0.0:80\n    robot.config['HOST'] = '0.0.0.0'\n    robot.config['PORT'] = 80\n    robot.run()`, `80202547367478920000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">import</span> os\n<span class=\"token keyword\">import</span> werobot\n\nrobot <span class=\"token operator\">=</span> werobot<span class=\"token punctuation\">.</span>WeRoBot<span class=\"token punctuation\">(</span>token<span class=\"token operator\">=</span>os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'wxtoken'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\nrobot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">'SESSION_STORAGE'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">False</span>\nrobot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">\"APP_ID\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'appid'</span><span class=\"token punctuation\">)</span>\nrobot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">\"APP_SECRET\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\"># @robot.handler 处理所有消息</span>\n<span class=\"token decorator annotation punctuation\">@robot<span class=\"token punctuation\">.</span>handler</span>\n<span class=\"token keyword\">def</span> <span class=\"token function\">hello</span><span class=\"token punctuation\">(</span>message<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">'Hello World!'</span>\n\n<span class=\"token keyword\">if</span> __name__ <span class=\"token operator\">==</span> <span class=\"token string\">\"__main__\"</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># 让服务器监听在 0.0.0.0:80</span>\n    robot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">'HOST'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'0.0.0.0'</span>\n    robot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">'PORT'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">80</span>\n    robot<span class=\"token punctuation\">.</span>run<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>并且在本地安装 werobot 相关依赖，完成之后，执行部署：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-13.jpeg\"></p>\n<p>将下面的这个地址复制到公众号后台，开启调用即可。</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-14.jpeg\"></p>\n<p>参考 Git：<a href=\"https://github.com/serverless-tencent/tencent-werobot\">https://github.com/serverless-tencent/tencent-werobot</a>\n这里需要注意的是，我们一定要关掉 Session 或者将 Session 改成云数据库，不能使用本地文件等，例如关闭 Session 配置：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"48902824649632800000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`robot.config['SESSION_STORAGE'] = False`, `48902824649632800000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">robot<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string\">'SESSION_STORAGE'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">False</span></code></pre></div>\n<h2 id=\"文本相似度实现图文检索\"><a href=\"#%E6%96%87%E6%9C%AC%E7%9B%B8%E4%BC%BC%E5%BA%A6%E5%AE%9E%E7%8E%B0%E5%9B%BE%E6%96%87%E6%A3%80%E7%B4%A2\" aria-label=\"文本相似度实现图文检索 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>文本相似度实现图文检索</h2>\n<p>有时候用户不知道我们发了什么文章，也不清楚每个文章具体内容，他可能只需要简单的关键词，来看一下这个公众号是否有他想要的东西。</p>\n<p>例如他搜索：如何上传文件？或者搜索：如何开发Component？而图文检索功能就可以快速把最相关的历史文章推送给用户，这将会是很方便的一件事情。效果图如下：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-15.png\"></p>\n<p>通过简单的问题描述，找到目标结果，这就是我们做的文章搜索功能。当然，我们还可以把它拓展成「客服系统」，这是后话了。</p>\n<p>回到正题，我们在之前的代码基础上，新增两个函数：</p>\n<ul>\n<li>函数 1：索引建立函数</li>\n</ul>\n<p>主要功能：通过触发该函数，可以将现有的公众号数据进行整理，并且建立适当的索引文件，存储到 COS 中。</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"40385285353456690000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# -*- coding: utf8 -*-\nimport os\nimport re\nimport json\nimport random\nfrom snownlp import SnowNLP\nfrom qcloud_cos_v5 import CosConfig\nfrom qcloud_cos_v5 import CosS3Client\n\nbucket = os.environ.get('bucket')\nsecret_id = os.environ.get('secret_id')\nsecret_key = os.environ.get('secret_key')\nregion = os.environ.get('region')\nclient = CosS3Client(CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key))\n\n\ndef main_handler(event, context):\n    response = client.get_object(\n        Bucket=bucket,\n        Key=event[&quot;key&quot;],\n    )\n    response['Body'].get_stream_to_file('/tmp/output.txt')\n\n    with open('/tmp/output.txt') as f:\n        data = json.loads(f.read())\n\n    articlesIndex = []\n    articles = {}\n    tempContentList = [\n        &quot;_&quot;, &quot;&nbsp;&quot;,\n    ]\n    for eveItem in data:\n        for i in range(0, len(eveItem['content']['news_item'])):\n            content = eveItem['content']['news_item'][i]['content']\n            content = re.sub(r'<code(.*?)</code>', '_', content)\n            content = re.sub(r'<.*?>', '', content)\n            for eve in tempContentList:\n                content = content.replace(eve, &quot;&quot;)\n            desc = &quot;%s。%s。%s&quot; % (\n                eveItem['content']['news_item'][i]['title'],\n                eveItem['content']['news_item'][i]['digest'],\n                &quot;。&quot;.join(SnowNLP(content).summary(3))\n            )\n            tempKey = &quot;&quot;.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 5))\n            articlesIndex.append(\n                {\n                    &quot;media_id&quot;: tempKey,\n                    &quot;description&quot;: desc\n                }\n            )\n            articles[tempKey] = eveItem['content']['news_item'][i]\n\n    client.put_object(\n        Bucket=bucket,\n        Body=json.dumps(articlesIndex).encode(&quot;utf-8&quot;),\n        Key=event['index_key'],\n        EnableMD5=False\n    )\n    client.put_object(\n        Bucket=bucket,\n        Body=json.dumps(articles).encode(&quot;utf-8&quot;),\n        Key=event['key'],\n        EnableMD5=False\n    )`, `40385285353456690000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token comment\"># -*- coding: utf8 -*-</span>\n<span class=\"token keyword\">import</span> os\n<span class=\"token keyword\">import</span> re\n<span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> random\n<span class=\"token keyword\">from</span> snownlp <span class=\"token keyword\">import</span> SnowNLP\n<span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosConfig\n<span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosS3Client\n\nbucket <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'bucket'</span><span class=\"token punctuation\">)</span>\nsecret_id <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret_id'</span><span class=\"token punctuation\">)</span>\nsecret_key <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret_key'</span><span class=\"token punctuation\">)</span>\nregion <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'region'</span><span class=\"token punctuation\">)</span>\nclient <span class=\"token operator\">=</span> CosS3Client<span class=\"token punctuation\">(</span>CosConfig<span class=\"token punctuation\">(</span>Region<span class=\"token operator\">=</span>region<span class=\"token punctuation\">,</span> SecretId<span class=\"token operator\">=</span>secret_id<span class=\"token punctuation\">,</span> SecretKey<span class=\"token operator\">=</span>secret_key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    response <span class=\"token operator\">=</span> client<span class=\"token punctuation\">.</span>get_object<span class=\"token punctuation\">(</span>\n        Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n        Key<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"key\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span>\n    response<span class=\"token punctuation\">[</span><span class=\"token string\">'Body'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>get_stream_to_file<span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/output.txt'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/output.txt'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n        data <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>f<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    articlesIndex <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    articles <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n    tempContentList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token string\">\"_\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"&amp;nbsp;\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">for</span> eveItem <span class=\"token keyword\">in</span> data<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>eveItem<span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_item'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            content <span class=\"token operator\">=</span> eveItem<span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_item'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span>\n            content <span class=\"token operator\">=</span> re<span class=\"token punctuation\">.</span>sub<span class=\"token punctuation\">(</span><span class=\"token string\">r'&lt;code(.*?)&lt;/code>'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'_'</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span>\n            content <span class=\"token operator\">=</span> re<span class=\"token punctuation\">.</span>sub<span class=\"token punctuation\">(</span><span class=\"token string\">r'&lt;.*?>'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">for</span> eve <span class=\"token keyword\">in</span> tempContentList<span class=\"token punctuation\">:</span>\n                content <span class=\"token operator\">=</span> content<span class=\"token punctuation\">.</span>replace<span class=\"token punctuation\">(</span>eve<span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span>\n            desc <span class=\"token operator\">=</span> <span class=\"token string\">\"%s。%s。%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n                eveItem<span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_item'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'title'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                eveItem<span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_item'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'digest'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"。\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>SnowNLP<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>summary<span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">)</span>\n            tempKey <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>random<span class=\"token punctuation\">.</span>sample<span class=\"token punctuation\">(</span><span class=\"token string\">'zyxwvutsrqponmlkjihgfedcba'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            articlesIndex<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">:</span> tempKey<span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">:</span> desc\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">)</span>\n            articles<span class=\"token punctuation\">[</span>tempKey<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> eveItem<span class=\"token punctuation\">[</span><span class=\"token string\">'content'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_item'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n\n    client<span class=\"token punctuation\">.</span>put_object<span class=\"token punctuation\">(</span>\n        Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n        Body<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>articlesIndex<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Key<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'index_key'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        EnableMD5<span class=\"token operator\">=</span><span class=\"token boolean\">False</span>\n    <span class=\"token punctuation\">)</span>\n    client<span class=\"token punctuation\">.</span>put_object<span class=\"token punctuation\">(</span>\n        Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n        Body<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>articles<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Key<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">'key'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        EnableMD5<span class=\"token operator\">=</span><span class=\"token boolean\">False</span>\n    <span class=\"token punctuation\">)</span></code></pre></div>\n<p>这一部分，可能定制化比较多一些。首先是 tempContentList 变量，这里可以写上一些公众号中可能出现但不重要的话，例如公众号末尾的引导关注文案，这些文案一般不参与搜索，所以最好在建立索引的时候进行替换去除。然后我们还通过上述代码去掉了 code 标签里面的内容，因为代码也会影响结果。同时我还去掉了 html 标签。</p>\n<p>原始的文件大概是这样的：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-16.png\"></p>\n<p>处理好的文件（通过标题+描述+SnowNLP提取的摘要）：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-17.png\"></p>\n<p>这些文件将存储到 COS 中。</p>\n<p>这一部分的核心就是，正确让我们提取出来的 description 尽可能准确地描述文章的内容。一般情况下，标题就是文章的核心，但是标题可能有一些信息丢失。</p>\n<p>例如文章「用腾讯云 Serverless 你要知道他们两个的区别」，但实际上描述的是 Plugin 和 Component 的区别。虽然标题知道是两个东西，但是却缺少了核心的目标，所以再加上我们下面的描述：什么是 Serverless Framework Plugin？什么是Component？Plugin与Component 有什么区别？想要入门 Serverless CLI，这两个产品必须分的清楚，本文将会分享这二者区别与对应的特点、功能。</p>\n<p>当然，加上描述之后内容变得已经相当精确，但是正文中，可能有更加精准的描述或者额外的内容，所以采用的是标题+描述+摘要（textRank 提取出来的前三句，属于提取式文本）。</p>\n<ul>\n<li>函数 2: 搜索函数</li>\n</ul>\n<p>主要功能：当用户向微信号发送了指定关键词，通过该函数获取的结果。</p>\n<p>思考：函数 1 和函数 2，都可以集成在之前的函数中，为什么要把这两个函数单独拿出来做一个独立的函数存在呢？将它们放在同一个函数中不好么？</p>\n<p>原因是 —— 主函数触发次数相对来说是最多的，而且这个函数本身不需要太多的资源配置（64M 就够了），而函数 1 和函数 2，可能需要消耗更多的资源，如果三个函数合并放在一起，可能函数的内存大小需要整体调大，满足三个函数需求。这样可能会消耗更多资源，</p>\n<p>例如：主函数触发了 10 次（64M，每次 1S），函数 1 触发了 2 次（512 M，每次 5S），函数 2 触发了 4 次（384M，每次 3S）</p>\n<p>如果将三个函数放在一起，资源消耗是：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-19.png\"></p>\n<p>如果将其变成三个函数来执行，资源消耗是：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-20.png\"></p>\n<p>前者总计资源消耗 13308，后者 10432。调用次数越多，主函数的调用比例越大，所以节约的资源也就会越多。因此此处建议将资源消耗差距比较大的模块，分成不同函数进行部署。</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"4909922017984237000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import os\nimport json\nimport jieba\nfrom qcloud_cos_v5 import CosConfig\nfrom qcloud_cos_v5 import CosS3Client\nfrom collections import defaultdict\nfrom gensim import corpora, models, similarities\n\nbucket = os.environ.get('bucket')\nsecret_id = os.environ.get('secret_id')\nsecret_key = os.environ.get('secret_key')\nregion = os.environ.get('region')\nclient = CosS3Client(CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key))\n\n\ndef main_handler(event, context):\n    response = client.get_object(\n        Bucket=bucket,\n        Key=event[&quot;key&quot;],\n    )\n    response['Body'].get_stream_to_file('/tmp/output.txt')\n\n    with open('/tmp/output.txt') as f:\n        data = json.loads(f.read())\n\n    articles = []\n    articlesDict = {}\n    for eve in data:\n        articles.append(eve['description'])\n        articlesDict[eve['description']] = eve['media_id']\n\n    sentence = event[&quot;sentence&quot;]\n\n    documents = []\n    for eve_sentence in articles:\n        tempData = &quot; &quot;.join(jieba.cut(eve_sentence))\n        documents.append(tempData)\n    texts = [[word for word in document.split()] for document in documents]\n    frequency = defaultdict(int)\n    for text in texts:\n        for word in text:\n            frequency[word] += 1\n    dictionary = corpora.Dictionary(texts)\n    new_xs = dictionary.doc2bow(jieba.cut(sentence))\n    corpus = [dictionary.doc2bow(text) for text in texts]\n    tfidf = models.TfidfModel(corpus)\n    featurenum = len(dictionary.token2id.keys())\n    sim = similarities.SparseMatrixSimilarity(\n        tfidf[corpus],\n        num_features=featurenum\n    )[tfidf[new_xs]]\n    answer_list = [(sim[i], articles[i]) for i in range(1, len(articles))]\n    answer_list.sort(key=lambda x: x[0], reverse=True)\n    result = []\n    print(answer_list)\n    for eve in answer_list:\n        if eve[0] > 0.10:\n            result.append(articlesDict[eve[1]])\n    if len(result) >= 8:\n        result = result[0:8]\n    return {&quot;result&quot;: json.dumps(result)}`, `4909922017984237000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">import</span> os\n<span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> jieba\n<span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosConfig\n<span class=\"token keyword\">from</span> qcloud_cos_v5 <span class=\"token keyword\">import</span> CosS3Client\n<span class=\"token keyword\">from</span> collections <span class=\"token keyword\">import</span> defaultdict\n<span class=\"token keyword\">from</span> gensim <span class=\"token keyword\">import</span> corpora<span class=\"token punctuation\">,</span> models<span class=\"token punctuation\">,</span> similarities\n\nbucket <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'bucket'</span><span class=\"token punctuation\">)</span>\nsecret_id <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret_id'</span><span class=\"token punctuation\">)</span>\nsecret_key <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'secret_key'</span><span class=\"token punctuation\">)</span>\nregion <span class=\"token operator\">=</span> os<span class=\"token punctuation\">.</span>environ<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'region'</span><span class=\"token punctuation\">)</span>\nclient <span class=\"token operator\">=</span> CosS3Client<span class=\"token punctuation\">(</span>CosConfig<span class=\"token punctuation\">(</span>Region<span class=\"token operator\">=</span>region<span class=\"token punctuation\">,</span> SecretId<span class=\"token operator\">=</span>secret_id<span class=\"token punctuation\">,</span> SecretKey<span class=\"token operator\">=</span>secret_key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    response <span class=\"token operator\">=</span> client<span class=\"token punctuation\">.</span>get_object<span class=\"token punctuation\">(</span>\n        Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n        Key<span class=\"token operator\">=</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"key\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span>\n    response<span class=\"token punctuation\">[</span><span class=\"token string\">'Body'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>get_stream_to_file<span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/output.txt'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/output.txt'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n        data <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>f<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    articles <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    articlesDict <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">for</span> eve <span class=\"token keyword\">in</span> data<span class=\"token punctuation\">:</span>\n        articles<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>eve<span class=\"token punctuation\">[</span><span class=\"token string\">'description'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n        articlesDict<span class=\"token punctuation\">[</span>eve<span class=\"token punctuation\">[</span><span class=\"token string\">'description'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> eve<span class=\"token punctuation\">[</span><span class=\"token string\">'media_id'</span><span class=\"token punctuation\">]</span>\n\n    sentence <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"sentence\"</span><span class=\"token punctuation\">]</span>\n\n    documents <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">for</span> eve_sentence <span class=\"token keyword\">in</span> articles<span class=\"token punctuation\">:</span>\n        tempData <span class=\"token operator\">=</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>jieba<span class=\"token punctuation\">.</span>cut<span class=\"token punctuation\">(</span>eve_sentence<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        documents<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>tempData<span class=\"token punctuation\">)</span>\n    texts <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span>word <span class=\"token keyword\">for</span> word <span class=\"token keyword\">in</span> document<span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">for</span> document <span class=\"token keyword\">in</span> documents<span class=\"token punctuation\">]</span>\n    frequency <span class=\"token operator\">=</span> defaultdict<span class=\"token punctuation\">(</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">for</span> text <span class=\"token keyword\">in</span> texts<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> word <span class=\"token keyword\">in</span> text<span class=\"token punctuation\">:</span>\n            frequency<span class=\"token punctuation\">[</span>word<span class=\"token punctuation\">]</span> <span class=\"token operator\">+=</span> <span class=\"token number\">1</span>\n    dictionary <span class=\"token operator\">=</span> corpora<span class=\"token punctuation\">.</span>Dictionary<span class=\"token punctuation\">(</span>texts<span class=\"token punctuation\">)</span>\n    new_xs <span class=\"token operator\">=</span> dictionary<span class=\"token punctuation\">.</span>doc2bow<span class=\"token punctuation\">(</span>jieba<span class=\"token punctuation\">.</span>cut<span class=\"token punctuation\">(</span>sentence<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    corpus <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>dictionary<span class=\"token punctuation\">.</span>doc2bow<span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> text <span class=\"token keyword\">in</span> texts<span class=\"token punctuation\">]</span>\n    tfidf <span class=\"token operator\">=</span> models<span class=\"token punctuation\">.</span>TfidfModel<span class=\"token punctuation\">(</span>corpus<span class=\"token punctuation\">)</span>\n    featurenum <span class=\"token operator\">=</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>dictionary<span class=\"token punctuation\">.</span>token2id<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    sim <span class=\"token operator\">=</span> similarities<span class=\"token punctuation\">.</span>SparseMatrixSimilarity<span class=\"token punctuation\">(</span>\n        tfidf<span class=\"token punctuation\">[</span>corpus<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        num_features<span class=\"token operator\">=</span>featurenum\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span>tfidf<span class=\"token punctuation\">[</span>new_xs<span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n    answer_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">(</span>sim<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> articles<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>articles<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n    answer_list<span class=\"token punctuation\">.</span>sort<span class=\"token punctuation\">(</span>key<span class=\"token operator\">=</span><span class=\"token keyword\">lambda</span> x<span class=\"token punctuation\">:</span> x<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> reverse<span class=\"token operator\">=</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">)</span>\n    result <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>answer_list<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">for</span> eve <span class=\"token keyword\">in</span> answer_list<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">if</span> eve<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">></span> <span class=\"token number\">0.10</span><span class=\"token punctuation\">:</span>\n            result<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>articlesDict<span class=\"token punctuation\">[</span>eve<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span> <span class=\"token operator\">>=</span> <span class=\"token number\">8</span><span class=\"token punctuation\">:</span>\n        result <span class=\"token operator\">=</span> result<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">:</span><span class=\"token number\">8</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"result\"</span><span class=\"token punctuation\">:</span> json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>这一部分的代码也是很简单，主要是通过文本的相似度对每个文本进行评分，然后按照评分从高到低进行排序，给定一个阈值（此处设定的阈值为 0.1），输出阈值之前的数据。</p>\n<p>另外要注意，此处引用了两个依赖是 jieba 和 gensim，这两个依赖都可能涉及到二进制文件，所以强烈推荐在 CentOS 系统下进行打包。</p>\n<p>接下来就是主函数中的调用，为了实现上述功能，需要在主函数中新增方法：</p>\n<ol>\n<li>获取全部图文消息</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"77865492008328400000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def getTheTotalOfAllMaterials():\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_the_total_of_all_materials.html\n    :return:\n    '''\n    accessToken = getAccessToken()\n    if not accessToken:\n        return &quot;Get Access Token Error&quot;\n    url = &quot;https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=%s&quot; % accessToken\n    responseAttr = urllib.request.urlopen(url=url)\n    return json.loads(responseAttr.read())\n\n\ndef getMaterialsList(listType, count):\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_materials_list.html\n    :return:\n    '''\n    accessToken = getAccessToken()\n    if not accessToken:\n        return &quot;Get Access Token Error&quot;\n\n    url = &quot;https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=%s&quot; % accessToken\n    materialsList = []\n    for i in range(1, int(count / 20) + 2):\n        requestAttr = urllib.request.Request(url=url, data=json.dumps({\n            &quot;type&quot;: listType,\n            &quot;offset&quot;: 20 * (i - 1),\n            &quot;count&quot;: 20\n        }).encode(&quot;utf-8&quot;), headers={\n            &quot;Content-Type&quot;: &quot;application/json&quot;\n        })\n        responseAttr = urllib.request.urlopen(requestAttr)\n        responseData = json.loads(responseAttr.read().decode(&quot;utf-8&quot;))\n        materialsList = materialsList + responseData[&quot;item&quot;]\n    return materialsList`, `77865492008328400000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">getTheTotalOfAllMaterials</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_the_total_of_all_materials.html\n    :return:\n    '''</span>\n    accessToken <span class=\"token operator\">=</span> getAccessToken<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> accessToken<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"Get Access Token Error\"</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=%s\"</span> <span class=\"token operator\">%</span> accessToken\n    responseAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>responseAttr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">getMaterialsList</span><span class=\"token punctuation\">(</span>listType<span class=\"token punctuation\">,</span> count<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_materials_list.html\n    :return:\n    '''</span>\n    accessToken <span class=\"token operator\">=</span> getAccessToken<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> accessToken<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"Get Access Token Error\"</span>\n\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=%s\"</span> <span class=\"token operator\">%</span> accessToken\n    materialsList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>count <span class=\"token operator\">/</span> <span class=\"token number\">20</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        requestAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span> data<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n            <span class=\"token string\">\"type\"</span><span class=\"token punctuation\">:</span> listType<span class=\"token punctuation\">,</span>\n            <span class=\"token string\">\"offset\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">\"count\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> headers<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>\n            <span class=\"token string\">\"Content-Type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"application/json\"</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n        responseAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>requestAttr<span class=\"token punctuation\">)</span>\n        responseData <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>responseAttr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        materialsList <span class=\"token operator\">=</span> materialsList <span class=\"token operator\">+</span> responseData<span class=\"token punctuation\">[</span><span class=\"token string\">\"item\"</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">return</span> materialsList</code></pre></div>\n<p>可以通过以下代码调用：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"45079980302879290000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`rticlesList = getMaterialsList(&quot;news&quot;, getTheTotalOfAllMaterials()['news_count'])`, `45079980302879290000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">rticlesList <span class=\"token operator\">=</span> getMaterialsList<span class=\"token punctuation\">(</span><span class=\"token string\">\"news\"</span><span class=\"token punctuation\">,</span> getTheTotalOfAllMaterials<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_count'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></code></pre></div>\n<ol start=\"2\">\n<li>将图文消息存储到 COS，并且通过函数的 Invoke 接口，实现函数间调用：</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87032746451372110000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def saveNewsToCos():\n    global articlesList\n    articlesList = getMaterialsList(&quot;news&quot;, getTheTotalOfAllMaterials()['news_count'])\n    try:\n        cosClient.put_object(\n            Bucket=bucket,\n            Body=json.dumps(articlesList).encode(&quot;utf-8&quot;),\n            Key=key,\n            EnableMD5=False\n        )\n        req = models.InvokeRequest()\n        params = '{&quot;FunctionName&quot;:&quot;Weixin_GoServerless_GetIndexFile&quot;, &quot;ClientContext&quot;:&quot;{\\\\&quot;key\\\\&quot;: \\\\&quot;%s\\\\&quot;, \\\\&quot;index_key\\\\&quot;: \\\\&quot;%s\\\\&quot;}&quot;}' % (\n            key, indexKey)\n        req.from_json_string(params)\n        resp = scfClient.Invoke(req)\n        resp.to_json_string()\n        response = cosClient.get_object(\n            Bucket=bucket,\n            Key=key,\n        )\n        response['Body'].get_stream_to_file('/tmp/content.json')\n        with open('/tmp/content.json') as f:\n            articlesList = json.loads(f.read())\n        return True\n    except Exception as e:\n        print(e)\n        return False`, `87032746451372110000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">saveNewsToCos</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">global</span> articlesList\n    articlesList <span class=\"token operator\">=</span> getMaterialsList<span class=\"token punctuation\">(</span><span class=\"token string\">\"news\"</span><span class=\"token punctuation\">,</span> getTheTotalOfAllMaterials<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'news_count'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        cosClient<span class=\"token punctuation\">.</span>put_object<span class=\"token punctuation\">(</span>\n            Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n            Body<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>articlesList<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            Key<span class=\"token operator\">=</span>key<span class=\"token punctuation\">,</span>\n            EnableMD5<span class=\"token operator\">=</span><span class=\"token boolean\">False</span>\n        <span class=\"token punctuation\">)</span>\n        req <span class=\"token operator\">=</span> models<span class=\"token punctuation\">.</span>InvokeRequest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        params <span class=\"token operator\">=</span> <span class=\"token string\">'{\"FunctionName\":\"Weixin_GoServerless_GetIndexFile\", \"ClientContext\":\"{\\\\\"key\\\\\": \\\\\"%s\\\\\", \\\\\"index_key\\\\\": \\\\\"%s\\\\\"}\"}'</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n            key<span class=\"token punctuation\">,</span> indexKey<span class=\"token punctuation\">)</span>\n        req<span class=\"token punctuation\">.</span>from_json_string<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">)</span>\n        resp <span class=\"token operator\">=</span> scfClient<span class=\"token punctuation\">.</span>Invoke<span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">)</span>\n        resp<span class=\"token punctuation\">.</span>to_json_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        response <span class=\"token operator\">=</span> cosClient<span class=\"token punctuation\">.</span>get_object<span class=\"token punctuation\">(</span>\n            Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n            Key<span class=\"token operator\">=</span>key<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">)</span>\n        response<span class=\"token punctuation\">[</span><span class=\"token string\">'Body'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>get_stream_to_file<span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/content.json'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/content.json'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n            articlesList <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>f<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">True</span>\n    <span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">False</span></code></pre></div>\n<ol start=\"3\">\n<li>根据搜索反馈回来的 Key 实现文章内容的对应</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"25475166972296100000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def searchNews(sentence):\n    req = models.InvokeRequest()\n    params = '{&quot;FunctionName&quot;:&quot;Weixin_GoServerless_SearchNews&quot;, &quot;ClientContext&quot;:&quot;{\\\\&quot;sentence\\\\&quot;: \\\\&quot;%s\\\\&quot;, \\\\&quot;key\\\\&quot;: \\\\&quot;%s\\\\&quot;}&quot;}' % (\n        sentence, indexKey)\n    req.from_json_string(params)\n    resp = scfClient.Invoke(req)\n    print(json.loads(json.loads(resp.to_json_string())['Result'][&quot;RetMsg&quot;]))\n    media_id = json.loads(json.loads(json.loads(resp.to_json_string())['Result'][&quot;RetMsg&quot;])[&quot;result&quot;])\n    return media_id if media_id else None`, `25475166972296100000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">searchNews</span><span class=\"token punctuation\">(</span>sentence<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    req <span class=\"token operator\">=</span> models<span class=\"token punctuation\">.</span>InvokeRequest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    params <span class=\"token operator\">=</span> <span class=\"token string\">'{\"FunctionName\":\"Weixin_GoServerless_SearchNews\", \"ClientContext\":\"{\\\\\"sentence\\\\\": \\\\\"%s\\\\\", \\\\\"key\\\\\": \\\\\"%s\\\\\"}\"}'</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n        sentence<span class=\"token punctuation\">,</span> indexKey<span class=\"token punctuation\">)</span>\n    req<span class=\"token punctuation\">.</span>from_json_string<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">)</span>\n    resp <span class=\"token operator\">=</span> scfClient<span class=\"token punctuation\">.</span>Invoke<span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>resp<span class=\"token punctuation\">.</span>to_json_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'Result'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"RetMsg\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    media_id <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>resp<span class=\"token punctuation\">.</span>to_json_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'Result'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"RetMsg\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"result\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> media_id <span class=\"token keyword\">if</span> media_id <span class=\"token keyword\">else</span> <span class=\"token boolean\">None</span></code></pre></div>\n<p>最后在 main_handler 中，增加使用逻辑：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-22.png\"></p>\n<p>逻辑很简答，就是根据用户发的消息，去查找对应的结果.拿到结果之后判断结果个数，如果有 1 个相似内容，则返回一个图文，如果有多个则返回带有链接的文本。</p>\n<p>另外一个逻辑是建立索引，直接是通过 API 网关触发即可。当然，如果怕不安全或者有需要的话，可以增加权限坚定的参数：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-23.png\"></p>\n<p>额外优化：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-24.png\"></p>\n<p>在接口列表中，我们可以看到获取 accessToken 的接口实际上是有次数限制的，每次获取有效期两个小时。所以，我们就要在函数中，对这部分内容做持久化。为了这个小东西，弄一个 MySQL 并不划算，所以决定用 COS：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"89472490379765700000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def getAccessToken():\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html\n    正常返回：{&quot;access_token&quot;:&quot;ACCESS_TOKEN&quot;,&quot;expires_in&quot;:7200}\n    异常返回：{&quot;errcode&quot;:40013,&quot;errmsg&quot;:&quot;invalid appid&quot;}\n    :return:\n    '''\n    global accessToken\n\n    # 第一次判断是判断本地是否已经有了accessToken，考虑到容器复用情况\n    if accessToken:\n        if int(time.time()) - int(accessToken[&quot;time&quot;]) <= 7000:\n            return accessToken[&quot;access_token&quot;]\n\n    # 如果本地没有accessToken，可以去cos获取\n    try:\n        response = cosClient.get_object(\n            Bucket=bucket,\n            Key=accessTokenKey,\n        )\n        response['Body'].get_stream_to_file('/tmp/token.json')\n        with open('/tmp/token.json') as f:\n            accessToken = json.loads(f.read())\n    except:\n        pass\n\n    # 这一次是看cos中是否有，如果cos中有的话，再次进行判断段\n    if accessToken:\n        if int(time.time()) - int(accessToken[&quot;time&quot;]) <= 7000:\n            return accessToken[&quot;access_token&quot;]\n\n    # 如果此时流程还没停止，则说明accessToken还没获得到，就需要从接口获得，并且同步给cos\n    url = &quot;https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s&quot; % (appid, secret)\n    accessTokenResult = json.loads(urllib.request.urlopen(url).read().decode(&quot;utf-8&quot;))\n    accessToken = {&quot;time&quot;: int(time.time()), &quot;access_token&quot;: accessTokenResult[&quot;access_token&quot;]}\n    print(accessToken)\n    response = cosClient.put_object(\n        Bucket=bucket,\n        Body=json.dumps(accessToken).encode(&quot;utf-8&quot;),\n        Key=accessTokenKey,\n        EnableMD5=False\n    )\n    return None if &quot;errcode&quot; in accessToken else accessToken[&quot;access_token&quot;]`, `89472490379765700000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">getAccessToken</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html\n    正常返回：{\"access_token\":\"ACCESS_TOKEN\",\"expires_in\":7200}\n    异常返回：{\"errcode\":40013,\"errmsg\":\"invalid appid\"}\n    :return:\n    '''</span>\n    <span class=\"token keyword\">global</span> accessToken\n\n    <span class=\"token comment\"># 第一次判断是判断本地是否已经有了accessToken，考虑到容器复用情况</span>\n    <span class=\"token keyword\">if</span> accessToken<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">if</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"time\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> <span class=\"token number\">7000</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token comment\"># 如果本地没有accessToken，可以去cos获取</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        response <span class=\"token operator\">=</span> cosClient<span class=\"token punctuation\">.</span>get_object<span class=\"token punctuation\">(</span>\n            Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n            Key<span class=\"token operator\">=</span>accessTokenKey<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">)</span>\n        response<span class=\"token punctuation\">[</span><span class=\"token string\">'Body'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>get_stream_to_file<span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/token.json'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/tmp/token.json'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n            accessToken <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>f<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span>\n\n    <span class=\"token comment\"># 这一次是看cos中是否有，如果cos中有的话，再次进行判断段</span>\n    <span class=\"token keyword\">if</span> accessToken<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">if</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"time\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> <span class=\"token number\">7000</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token comment\"># 如果此时流程还没停止，则说明accessToken还没获得到，就需要从接口获得，并且同步给cos</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=%s&amp;secret=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>appid<span class=\"token punctuation\">,</span> secret<span class=\"token punctuation\">)</span>\n    accessTokenResult <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    accessToken <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"time\"</span><span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">:</span> accessTokenResult<span class=\"token punctuation\">[</span><span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>accessToken<span class=\"token punctuation\">)</span>\n    response <span class=\"token operator\">=</span> cosClient<span class=\"token punctuation\">.</span>put_object<span class=\"token punctuation\">(</span>\n        Bucket<span class=\"token operator\">=</span>bucket<span class=\"token punctuation\">,</span>\n        Body<span class=\"token operator\">=</span>json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>accessToken<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        Key<span class=\"token operator\">=</span>accessTokenKey<span class=\"token punctuation\">,</span>\n        EnableMD5<span class=\"token operator\">=</span><span class=\"token boolean\">False</span>\n    <span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">None</span> <span class=\"token keyword\">if</span> <span class=\"token string\">\"errcode\"</span> <span class=\"token keyword\">in</span> accessToken <span class=\"token keyword\">else</span> accessToken<span class=\"token punctuation\">[</span><span class=\"token string\">\"access_token\"</span><span class=\"token punctuation\">]</span></code></pre></div>\n<p>当然这段代码可以继续优化，这里只是一个思路。</p>\n<h2 id=\"为公众号增加机器人功能\"><a href=\"#%E4%B8%BA%E5%85%AC%E4%BC%97%E5%8F%B7%E5%A2%9E%E5%8A%A0%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8A%9F%E8%83%BD\" aria-label=\"为公众号增加机器人功能 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>为公众号增加机器人功能</h2>\n<p>上文我们已经完成了公众号的基本框架的搭建，也完成了基于NLP知识的图文检索功能，可以说之前的内容都是原生开发，无论是公众号基础能力建设还是图文检索能力，而这一部分将会在之前的基础上，通过云服务商为我们提供的AI能力，将智能聊天功能接入其中。</p>\n<p>首先假设一个场景：用户关注这个公众号之后，他给公众号发送文本消息，我们首先进行图文检索，如果没找到合适的结果，我们就默认进入“聊天功能”；如果用户发送了语音，我们同样先进行图文检索，如果没有找得到相似图文，则通过语音进入“聊天功能”，这样看来是不是整个功能变得非常有趣？</p>\n<p>首先整体看一下机器人功能的基本形态：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-25.jpeg\"></p>\n<h3 id=\"聊天功能增加\"><a href=\"#%E8%81%8A%E5%A4%A9%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%8A%A0\" aria-label=\"聊天功能增加 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>聊天功能增加</h3>\n<p>聊天功能我们可以借助云厂商提供的聊天机器人服务：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-26.png\"></p>\n<p>开通和使用这个服务，可以为我们创建一个简单的机器人：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-27.png\"></p>\n<p>创建完成机器人，我们可以通过云API对其进行代码的编写，云API代码比较难写也不怕，有API Explorer：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-28.png\"></p>\n<p>系统会为我们自动编写好基本的代码，我们只需要稍加修改，就可以复制到项目中：</p>\n<p>在最外层进行相关初始化：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"31219512849546514000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`tbpClient = tbp_client.TbpClient(credential.Credential(secret_id, secret_key), region)`, `31219512849546514000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">tbpClient <span class=\"token operator\">=</span> tbp_client<span class=\"token punctuation\">.</span>TbpClient<span class=\"token punctuation\">(</span>credential<span class=\"token punctuation\">.</span>Credential<span class=\"token punctuation\">(</span>secret_id<span class=\"token punctuation\">,</span> secret_key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> region<span class=\"token punctuation\">)</span></code></pre></div>\n<p>初始化完成，增加聊天机器人函数：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"39597653155679310000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def chatBot(user, content):\n    '''\n    开发文档：https://cloud.tencent.com/document/product/1060/37438\n    :param user: 用户id\n    :param content: 聊天内容\n    :return: 返回机器人说的话，如果出现故障返回None\n    '''\n    try:\n        req = tbp_models.TextProcessRequest()\n        params = '{&quot;BotId&quot;:&quot;%s&quot;,&quot;BotEnv&quot;:&quot;release&quot;,&quot;TerminalId&quot;:&quot;%s&quot;,&quot;InputText&quot;:&quot;%s&quot;}' % (\n            bot_id, user, content\n        )\n        req.from_json_string(params)\n        resp = tbpClient.TextProcess(req)\n        return json.loads(resp.to_json_string())['ResponseMessage']['GroupList'][0]['Content']\n    except Exception as e:\n        print(e)\n        return None`, `39597653155679310000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">chatBot</span><span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">,</span> content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    开发文档：https://cloud.tencent.com/document/product/1060/37438\n    :param user: 用户id\n    :param content: 聊天内容\n    :return: 返回机器人说的话，如果出现故障返回None\n    '''</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        req <span class=\"token operator\">=</span> tbp_models<span class=\"token punctuation\">.</span>TextProcessRequest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        params <span class=\"token operator\">=</span> <span class=\"token string\">'{\"BotId\":\"%s\",\"BotEnv\":\"release\",\"TerminalId\":\"%s\",\"InputText\":\"%s\"}'</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n            bot_id<span class=\"token punctuation\">,</span> user<span class=\"token punctuation\">,</span> content\n        <span class=\"token punctuation\">)</span>\n        req<span class=\"token punctuation\">.</span>from_json_string<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">)</span>\n        resp <span class=\"token operator\">=</span> tbpClient<span class=\"token punctuation\">.</span>TextProcess<span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>resp<span class=\"token punctuation\">.</span>to_json_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'ResponseMessage'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'GroupList'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'Content'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">None</span></code></pre></div>\n<h3 id=\"文本转音频功能增加\"><a href=\"#%E6%96%87%E6%9C%AC%E8%BD%AC%E9%9F%B3%E9%A2%91%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%8A%A0\" aria-label=\"文本转音频功能增加 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>文本转音频功能增加</h3>\n<p>同样的方法，这不过是使用的另一个产品：</p>\n<p><img src=\"https://img.serverlesscloud.cn/202058/3-4-29.png\"></p>\n<p>同样通过Explorer编写代码，然后初始化：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"2074942372140276000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`ttsClient = tts_client.TtsClient(credential.Credential(secret_id, secret_key), region)`, `2074942372140276000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">ttsClient <span class=\"token operator\">=</span> tts_client<span class=\"token punctuation\">.</span>TtsClient<span class=\"token punctuation\">(</span>credential<span class=\"token punctuation\">.</span>Credential<span class=\"token punctuation\">(</span>secret_id<span class=\"token punctuation\">,</span> secret_key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> region<span class=\"token punctuation\">)</span></code></pre></div>\n<p>增加相关的方法实现文本到函数的转换：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87083956533384410000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def text2Voice(text):\n    '''\n    文档地址：https://cloud.tencent.com/document/product/1073/37995\n    :param text: 带转换的文本\n    :return: 返回转换后的文件地址\n    '''\n    try:\n        req = tts_models.TextToVoiceRequest()\n        params = '{&quot;Text&quot;:&quot;%s&quot;,&quot;SessionId&quot;:&quot;%s&quot;,&quot;ModelType&quot;:1,&quot;VoiceType&quot;:1002}' % (\n            text, &quot;&quot;.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 7)))\n        req.from_json_string(params)\n        resp = ttsClient.TextToVoice(req)\n        file = '/tmp/' + &quot;&quot;.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 7)) + &quot;.wav&quot;\n        with open(file, 'wb') as f:\n            f.write(base64.b64decode(json.loads(resp.to_json_string())[&quot;Audio&quot;]))\n        return file\n\n    except Exception as e:\n        print(e)\n        return None`, `87083956533384410000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">text2Voice</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://cloud.tencent.com/document/product/1073/37995\n    :param text: 带转换的文本\n    :return: 返回转换后的文件地址\n    '''</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        req <span class=\"token operator\">=</span> tts_models<span class=\"token punctuation\">.</span>TextToVoiceRequest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        params <span class=\"token operator\">=</span> <span class=\"token string\">'{\"Text\":\"%s\",\"SessionId\":\"%s\",\"ModelType\":1,\"VoiceType\":1002}'</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n            text<span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>random<span class=\"token punctuation\">.</span>sample<span class=\"token punctuation\">(</span><span class=\"token string\">'zyxwvutsrqponmlkjihgfedcba'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        req<span class=\"token punctuation\">.</span>from_json_string<span class=\"token punctuation\">(</span>params<span class=\"token punctuation\">)</span>\n        resp <span class=\"token operator\">=</span> ttsClient<span class=\"token punctuation\">.</span>TextToVoice<span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">)</span>\n        <span class=\"token builtin\">file</span> <span class=\"token operator\">=</span> <span class=\"token string\">'/tmp/'</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>random<span class=\"token punctuation\">.</span>sample<span class=\"token punctuation\">(</span><span class=\"token string\">'zyxwvutsrqponmlkjihgfedcba'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token string\">\".wav\"</span>\n        <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">file</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'wb'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n            f<span class=\"token punctuation\">.</span>write<span class=\"token punctuation\">(</span>base64<span class=\"token punctuation\">.</span>b64decode<span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>resp<span class=\"token punctuation\">.</span>to_json_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"Audio\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token builtin\">file</span>\n\n    <span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">None</span></code></pre></div>\n<h3 id=\"增加微信的素材相关逻辑\"><a href=\"#%E5%A2%9E%E5%8A%A0%E5%BE%AE%E4%BF%A1%E7%9A%84%E7%B4%A0%E6%9D%90%E7%9B%B8%E5%85%B3%E9%80%BB%E8%BE%91\" aria-label=\"增加微信的素材相关逻辑 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>增加微信的素材相关逻辑</h3>\n<p>由于我的账号是未认证的订阅号，所以可以使用的功能有限。在这里我需要先将生成的语音素材上传到公众号后台作为永久素材。因为语音类素材最大量为1000个，所以我还要顺便删除多余的素材。</p>\n<p>此处我的做法很简单，先上传素材，然后获得素材总数，接下来根据素材中的时间戳：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87962806413644400000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`{\n\t'media_id': 'HQOG98Gpaa4KcvU1L0MPEW4Zvngs4kBqOyTRzNWBNME',\n\t'name': 'ljpmybc.wav',\n\t'update_time': 1582896372,\n\t'tags': []\n}`, `87962806413644400000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n\t'media_id'<span class=\"token operator\">:</span> 'HQOG<span class=\"token number\">98</span>Gpaa<span class=\"token number\">4</span>KcvU<span class=\"token number\">1</span>L<span class=\"token number\">0</span>MPEW<span class=\"token number\">4</span>Zvngs<span class=\"token number\">4</span>kBqOyTRzNWBNME'<span class=\"token punctuation\">,</span>\n\t'name'<span class=\"token operator\">:</span> 'ljpmybc.wav'<span class=\"token punctuation\">,</span>\n\t'update_time'<span class=\"token operator\">:</span> <span class=\"token number\">1582896372</span><span class=\"token punctuation\">,</span>\n\t'tags'<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>就是<code class=\"language-text\">update_time</code>这个参数，和现在的时间进行判断，超过60S则认为这个素材已经过期，就可以删除，这样保证我们的素材数量不会溢出：</p>\n<p>增加永久素材：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"61519564811931550000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def addingOtherPermanentAssets(file, fileType):\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html\n    返回结果：{\n                &quot;media_id&quot;:&quot;HQOG98Gpaa4KcvU1L0MPEcyy31LSuHhRi8gD3pvebhI&quot;,\n                &quot;url&quot;:&quot;http:\\/\\/mmbiz.qpic.cn\\/sz_mmbiz_png\\/icxY5TTGTBibSyZPfLAEZmeaicUczsoGUpqLgBlRbNxeic4R8r94j60BiaxDLEZTAK7I7qubG3Ik808P8jYLdFJTcOA\\/0?wx_fmt=png&quot;,\n                &quot;item&quot;:[]\n            }\n    :param file:\n    :return:\n    '''\n    typeDict = {\n        &quot;voice&quot;: &quot;wav&quot;\n    }\n    url = &quot;https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&type=%s&quot; % (\n        getAccessToken(), fileType)\n    boundary = '----WebKitFormBoundary7MA4YWxk%s' % &quot;&quot;.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 7))\n    with open(file, 'rb') as f:\n        fileData = f.read()\n    data = {'media': (os.path.split(file)[1], fileData, typeDict[fileType])}\n    headers = {\n        &quot;Content-Type&quot;: &quot;multipart/form-data; boundary=%s&quot; % boundary,\n        &quot;User-Agent&quot;: &quot;okhttp/3.10.0&quot;\n    }\n    reqAttr = urllib.request.Request(url=url,\n                                     data=encode_multipart_formdata(data, boundary=boundary)[0],\n                                     headers=headers)\n    responseData = json.loads(urllib.request.urlopen(reqAttr).read().decode(&quot;utf-8&quot;))\n\n    try:\n        for eveVoice in getMaterialsList(&quot;voice&quot;, getTheTotalOfAllMaterials()['voice_count']):\n            try:\n                if int(time.time()) - int(eveVoice[&quot;update_time&quot;]) > 60:\n                    deletingPermanentAssets(eveVoice['media_id'])\n            except:\n                pass\n    except:\n        pass\n\n    return responseData['media_id'] if &quot;media_id&quot; in responseData else None`, `61519564811931550000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">addingOtherPermanentAssets</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">file</span><span class=\"token punctuation\">,</span> fileType<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html\n    返回结果：{\n                \"media_id\":\"HQOG98Gpaa4KcvU1L0MPEcyy31LSuHhRi8gD3pvebhI\",\n                \"url\":\"http:\\/\\/mmbiz.qpic.cn\\/sz_mmbiz_png\\/icxY5TTGTBibSyZPfLAEZmeaicUczsoGUpqLgBlRbNxeic4R8r94j60BiaxDLEZTAK7I7qubG3Ik808P8jYLdFJTcOA\\/0?wx_fmt=png\",\n                \"item\":[]\n            }\n    :param file:\n    :return:\n    '''</span>\n    typeDict <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"voice\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"wav\"</span>\n    <span class=\"token punctuation\">}</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&amp;type=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>\n        getAccessToken<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> fileType<span class=\"token punctuation\">)</span>\n    boundary <span class=\"token operator\">=</span> <span class=\"token string\">'----WebKitFormBoundary7MA4YWxk%s'</span> <span class=\"token operator\">%</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>random<span class=\"token punctuation\">.</span>sample<span class=\"token punctuation\">(</span><span class=\"token string\">'zyxwvutsrqponmlkjihgfedcba'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">file</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'rb'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> f<span class=\"token punctuation\">:</span>\n        fileData <span class=\"token operator\">=</span> f<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'media'</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span>os<span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span><span class=\"token builtin\">file</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> fileData<span class=\"token punctuation\">,</span> typeDict<span class=\"token punctuation\">[</span>fileType<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n    headers <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"Content-Type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"multipart/form-data; boundary=%s\"</span> <span class=\"token operator\">%</span> boundary<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"User-Agent\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"okhttp/3.10.0\"</span>\n    <span class=\"token punctuation\">}</span>\n    reqAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span>\n                                     data<span class=\"token operator\">=</span>encode_multipart_formdata<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">,</span> boundary<span class=\"token operator\">=</span>boundary<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                                     headers<span class=\"token operator\">=</span>headers<span class=\"token punctuation\">)</span>\n    responseData <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>reqAttr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> eveVoice <span class=\"token keyword\">in</span> getMaterialsList<span class=\"token punctuation\">(</span><span class=\"token string\">\"voice\"</span><span class=\"token punctuation\">,</span> getTheTotalOfAllMaterials<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token string\">'voice_count'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n                <span class=\"token keyword\">if</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>eveVoice<span class=\"token punctuation\">[</span><span class=\"token string\">\"update_time\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">60</span><span class=\"token punctuation\">:</span>\n                    deletingPermanentAssets<span class=\"token punctuation\">(</span>eveVoice<span class=\"token punctuation\">[</span><span class=\"token string\">'media_id'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span>\n                <span class=\"token keyword\">pass</span>\n    <span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span>\n\n    <span class=\"token keyword\">return</span> responseData<span class=\"token punctuation\">[</span><span class=\"token string\">'media_id'</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">if</span> <span class=\"token string\">\"media_id\"</span> <span class=\"token keyword\">in</span> responseData <span class=\"token keyword\">else</span> <span class=\"token boolean\">None</span></code></pre></div>\n<p>删除素材：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"70136296776876360000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def deletingPermanentAssets(media_id):\n    '''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Deleting_Permanent_Assets.html\n    :return:\n    '''\n    url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=%s' % (getAccessToken())\n    data = {\n        &quot;media_id&quot;: media_id\n    }\n    postData = json.dumps(data).encode(&quot;utf-8&quot;)\n    reqAttr = urllib.request.Request(url=url, data=postData)\n    print(urllib.request.urlopen(reqAttr).read())`, `70136296776876360000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">deletingPermanentAssets</span><span class=\"token punctuation\">(</span>media_id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token triple-quoted-string string\">'''\n    文档地址：https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Deleting_Permanent_Assets.html\n    :return:\n    '''</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=%s'</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>getAccessToken<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">:</span> media_id\n    <span class=\"token punctuation\">}</span>\n    postData <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    reqAttr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span> data<span class=\"token operator\">=</span>postData<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>reqAttr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>至此，基础代码已经完成，剩下的逻辑就是在main_handler中进行组合：</p>\n<p>文本消息部分的组合逻辑：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"14089559655790486000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`media_id = searchNews(event[&quot;Content&quot;])\nresult = getNewsResult(media_id, event)\nif not result:\n\tchatBotResponse = chatBot(event[&quot;FromUserName&quot;], event[&quot;Content&quot;])\n\tresult = textXML({&quot;msg&quot;: chatBotResponse if chatBotResponse else &quot;目前还没有类似的文章被发布在这个公众号上&quot;}, event)\n\treturn response(body=result)`, `14089559655790486000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">media_id <span class=\"token operator\">=</span> searchNews<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Content\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\nresult <span class=\"token operator\">=</span> getNewsResult<span class=\"token punctuation\">(</span>media_id<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> result<span class=\"token punctuation\">:</span>\n\tchatBotResponse <span class=\"token operator\">=</span> chatBot<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Content\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n\tresult <span class=\"token operator\">=</span> textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> chatBotResponse <span class=\"token keyword\">if</span> chatBotResponse <span class=\"token keyword\">else</span> <span class=\"token string\">\"目前还没有类似的文章被发布在这个公众号上\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n\t<span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>result<span class=\"token punctuation\">)</span></code></pre></div>\n<p>语音消息部分组合逻辑：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"66517814669381710000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`media_id = searchNews(event[&quot;Recognition&quot;])\nresult = getNewsResult(media_id, event)\nif not result:\n    chatBotResponse = chatBot(event[&quot;FromUserName&quot;], event[&quot;Recognition&quot;])\n    if chatBotResponse:\n        voiceFile = text2Voice(chatBotResponse)\n        if voiceFile:\n            uploadResult = addingOtherPermanentAssets(voiceFile, 'voice')\n            if uploadResult:\n                result = voiceXML({&quot;media_id&quot;: uploadResult}, event)\nif not result:\n    result = textXML({&quot;msg&quot;: &quot;目前还没有类似的文章被发布在这个公众号上&quot;}, event)\nreturn response(body=result)`, `66517814669381710000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">media_id <span class=\"token operator\">=</span> searchNews<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Recognition\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\nresult <span class=\"token operator\">=</span> getNewsResult<span class=\"token punctuation\">(</span>media_id<span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> result<span class=\"token punctuation\">:</span>\n    chatBotResponse <span class=\"token operator\">=</span> chatBot<span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">[</span><span class=\"token string\">\"FromUserName\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"Recognition\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> chatBotResponse<span class=\"token punctuation\">:</span>\n        voiceFile <span class=\"token operator\">=</span> text2Voice<span class=\"token punctuation\">(</span>chatBotResponse<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> voiceFile<span class=\"token punctuation\">:</span>\n            uploadResult <span class=\"token operator\">=</span> addingOtherPermanentAssets<span class=\"token punctuation\">(</span>voiceFile<span class=\"token punctuation\">,</span> <span class=\"token string\">'voice'</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">if</span> uploadResult<span class=\"token punctuation\">:</span>\n                result <span class=\"token operator\">=</span> voiceXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"media_id\"</span><span class=\"token punctuation\">:</span> uploadResult<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> result<span class=\"token punctuation\">:</span>\n    result <span class=\"token operator\">=</span> textXML<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token string\">\"msg\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"目前还没有类似的文章被发布在这个公众号上\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> event<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">return</span> response<span class=\"token punctuation\">(</span>body<span class=\"token operator\">=</span>result<span class=\"token punctuation\">)</span></code></pre></div>\n<h2 id=\"总结\"><a href=\"#%E6%80%BB%E7%BB%93\" aria-label=\"总结 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>总结</h2>\n<p>至此，我们完成了一个简单的公众号开发。通过 Serverless 的原生开发思路（也可以使用 Werobot 等公众号开发框架），将公众号后台服务部署到 Serverless 架构上，再通过自然语言处理技术（特指文本相似度等）实现了一个图文检索功能。我们还能通过与云厂商提供的 AI 能力相结合，实现聊天机器人，用于与用户的文本交流，或者语音沟通。</p>\n<p>Serverless 架构在开发微信公众号这种事件驱动类的触发式场景有着很大的优势，本文也仅仅是一个小探索，更多的功能和应用，能力和价值，还是要看具体业务。希望读者可以通过本文，对 Serverless 架构有更深入的了解。</p>\n<hr>\n<div id='scf-deploy-iframe-or-md'></div>\n<hr>\n<blockquote>\n<p><strong>传送门：</strong></p>\n<ul>\n<li>GitHub: <a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">github.com/serverless</a></li>\n<li>官网：<a href=\"https://serverless.com/\">serverless.com</a></li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文网</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li>\n<p><a href=\"/best-practice/2020-05-05-ai-wechat/#%E5%88%9D%E6%AD%A5%E6%90%AD%E5%BB%BA\">初步搭建</a></p>\n<ul>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#serverless-%E5%8E%9F%E7%94%9F%E5%BC%80%E5%8F%91\">Serverless 原生开发</a></li>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E4%BD%BF%E7%94%A8-werobot-%E6%A1%86%E6%9E%B6\">使用 Werobot 框架</a></li>\n</ul>\n</li>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E6%96%87%E6%9C%AC%E7%9B%B8%E4%BC%BC%E5%BA%A6%E5%AE%9E%E7%8E%B0%E5%9B%BE%E6%96%87%E6%A3%80%E7%B4%A2\">文本相似度实现图文检索</a></li>\n<li>\n<p><a href=\"/best-practice/2020-05-05-ai-wechat/#%E4%B8%BA%E5%85%AC%E4%BC%97%E5%8F%B7%E5%A2%9E%E5%8A%A0%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%8A%9F%E8%83%BD\">为公众号增加机器人功能</a></p>\n<ul>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E8%81%8A%E5%A4%A9%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%8A%A0\">聊天功能增加</a></li>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E6%96%87%E6%9C%AC%E8%BD%AC%E9%9F%B3%E9%A2%91%E5%8A%9F%E8%83%BD%E5%A2%9E%E5%8A%A0\">文本转音频功能增加</a></li>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E5%A2%9E%E5%8A%A0%E5%BE%AE%E4%BF%A1%E7%9A%84%E7%B4%A0%E6%9D%90%E7%9B%B8%E5%85%B3%E9%80%BB%E8%BE%91\">增加微信的素材相关逻辑</a></li>\n</ul>\n</li>\n<li><a href=\"/best-practice/2020-05-05-ai-wechat/#%E6%80%BB%E7%BB%93\">总结</a></li>\n</ul>"},"previousBlog":{"id":"249242aa-c81b-5ff8-9553-90e8792af73e","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020511/1589207417923-ZalNtxgQAC_small.jpg","authors":["Anycodes"],"categories":["best-practice"],"date":"2020-05-08T00:00:00.000Z","title":"云函数 SCF 与对象存储实现 WordCount","description":"本文将通过 MapReduce 模型实现一个简单的 WordCount 算法，区别于传统使用 Hadoop 等大数据框架，本文使用的是对象存储 COS 与云函数 SCF 的结合","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["Serverless","WordCount"],"keywords":"Serverless 多环境配置,Serverless 管理环境,Serverless配置方案","outdated":true},"wordCount":{"words":181,"sentences":28,"paragraphs":28},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-05-08-wordcount.md","fields":{"slug":"/best-practice/2020-05-08-wordcount/","keywords":["python","serverless","云函数","file","cos","bucket","client","event"]}},"nextBlog":{"id":"60cdbe64-7a7b-5d2a-a46c-135944060867","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020511/1589207417692-ZalNtxgQAC_small.jpg","authors":["Anycodes"],"categories":["best-practice"],"date":"2020-05-04T00:00:00.000Z","title":"Serverless 实现图片压缩与水印","description":"图片和 Web 服务非常紧密，在 Serverless 架构下，是否有一种方法，可以对图像的压缩与水印实现「一条龙」服务，而且不会因为用户量比较多，而影响用户整体体验呢？","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["Serverless","图片压缩"],"keywords":"Serverless 多环境配置,Serverless 管理环境,Serverless配置方案","outdated":true},"wordCount":{"words":179,"sentences":36,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/best-practice/2020-05-04-image-compression.md","fields":{"slug":"/best-practice/2020-05-04-image-compression/","keywords":["go","python","serverless","函数计算","云函数","image","width","水印","cos","height","图片","size","txtImage"]}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"d1450693-7418-5532-8bd4-4fe42f275bdf","previousBlogId":"249242aa-c81b-5ff8-9553-90e8792af73e","nextBlogId":"60cdbe64-7a7b-5d2a-a46c-135944060867"}}}