Linux迷+Python粉 - 公众号//blog.pythonwood.com/2017-11-27T22:12:00+08:00微信开发python+django两个月的成功经历,django是个好框架!2014-06-28T20:12:00+08:002014-06-28T20:12:00+08:00pythonwoodtag:blog.pythonwood.com,2014-06-28:/2014/06/微信开发python+django两个月的成功经历,django是个好框架!/<h3 id="_1">时间:大三<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>上学期没有用微信内置浏览器而纯对话开发,坑了自己好一下。</p> <p>下学期选错bottle框架,以为轻量好,谁知开发中什么都自己来很痛苦。</p> <p>选对了框架django,终于在大三最后的个把月里写出了里程碑式的现在这个微信端,自己都感动到,作为我大三一年web开发的终结吧。</p> <p>亮点1:自带后台管理</p> <p>亮点2:后台权限管理</p> <p>亮点3:微信回复规则设置去代码化,图形界面。</p> <p>亮点4:一平台多网店 …</p><h3 id="_1">时间:大三<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>上学期没有用微信内置浏览器而纯对话开发,坑了自己好一下。</p> <p>下学期选错bottle框架,以为轻量好,谁知开发中什么都自己来很痛苦。</p> <p>选对了框架django,终于在大三最后的个把月里写出了里程碑式的现在这个微信端,自己都感动到,作为我大三一年web开发的终结吧。</p> <p>亮点1:自带后台管理</p> <p>亮点2:后台权限管理</p> <p>亮点3:微信回复规则设置去代码化,图形界面。</p> <p>亮点4:一平台多网店</p> <p>亮点5:图片自动缩略成200*300px大小(使用了七牛空间)</p> <p>亮点6:gzip压缩,网络流量为原来33%左右。<span class="caps">SAE</span>中Gzip压缩设置</p> <p>亮点7:保存接受的所以文本消息,记录永存!</p> <p>亮点8:购买者可查看历史订单,购买总额等。</p> <p>亮点9:后台可查看用户下单总额,最近下单时间等等。</p> <p>亮点10:商店信息,商品信息均在后台直接修改。</p> <p>亮点11:平台创始人可强制商店下线。</p> <p>技巧:微信规则不匹配时不能回复吗?不是,规则包含空字符总能匹配任意文本,请看下面的微信规则截图。</p> <h3 id="_2">后台<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h3> <p>选择botlle框架,自己写sql,便学边用,很痛苦的换了20天作出来了微信<a href="http://2.aozhouwine.sinaapp.com/buy.html?openid=abcdefgabcdefgabcdefgabcdefg" title="顾客演示入口地址">第一版</a>。这版其实很简陋,但其给我的经验很重要。演示地址:<a href="http://2.aozhouwine.sinaapp.com/buy.html?openid=abcdefgabcdefgabcdefgabcdefg" title="顾客演示入口地址">点击入口</a>。</p> <p>抛弃bottle,选择django,后来证明我的选择是对的,虽然学习坡度比较大,但是其框架本身带来的效率和效益却是学习框架本身的好几倍。我喜欢它的自带后台管理,和后台权限管理,更喜欢它的<span class="caps">ORM</span>,省去很多sql的事情,比如sql语句编写,sql防注问题,sql迁移方便等等。这次用上了这三大功能,另外还巧用django的模板渲染实现微信回复功能,但这不是django特有。</p> <p>微信已经实现了多店功能。这也是当初我为什么坚定选择django,因为django的一project多app的架构刚好契合这个一平台多店铺的想法。后来我学scrapy框架,发现也是一project多app,方便不少。同时说明一project多app是先进的,是趋势之一。</p> <h3 id="_3">前台<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h3> <p>我比较喜欢后端的开发,前端的我就修改已有好的前端代码,参考了微信公众号“果然美”,“微果大爱”,“华农果满堂”,“微盟”,“乐外卖”等前端设计。技术上使用html5+css3。</p> <p>现在平台上有果色天香和澳洲红酒两个店铺</p> <p><img alt="平台上有果色天香和澳洲红酒两个店铺1.png" height="50%" src="//blog.pythonwood.com/static/img/平台上有果色天香和澳洲红酒两个店铺1.png" title="1" width="30%"> <img alt="平台上有果色天香和澳洲红酒两个店铺2.jpg" height="50%" src="//blog.pythonwood.com/static/img/平台上有果色天香和澳洲红酒两个店铺2.jpg" title="2" width="30%"> <img alt="平台上有果色天香和澳洲红酒两个店铺3.jpg" height="50%" src="//blog.pythonwood.com/static/img/平台上有果色天香和澳洲红酒两个店铺3.jpg" title="3" width="30%"></p> <h3 id="_4">代码统计<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h3> <p>使用linux&nbsp;shell统计 </p> <p>合理版 cat $(find . -name &ldquo;<em>.py&rdquo; -or -name &ldquo;</em>.yaml&rdquo; -or -name &ldquo;*.rst&rdquo; -or -name &ldquo;sell_detail.html&rdquo;) | wc | sed &ldquo;1i static:\nlines | words |&nbsp;bytes&rdquo; </p> <p><img alt="tu" src="//blog.pythonwood.com/static/img/代码统计1.png" title="1"></p> <p>纯净版 cat $(find . -path &ldquo;./guosetianxiang&rdquo; -prune -or -name &ldquo;<em>.py&rdquo; -or -name &ldquo;</em>.yaml&rdquo; -or -name &ldquo;*.rst&rdquo; -or -name &ldquo;sell_detail.html&rdquo;) | wc | sed &ldquo;1i static:\nlines | words |&nbsp;bytes&rdquo; </p> <p><img alt="tu" src="//blog.pythonwood.com/static/img/代码统计2.png" title="2"></p> <p>完全版 cat $(find . -name &ldquo;<em>.py&rdquo; -or -name &ldquo;</em>.yaml&rdquo; -or -name &ldquo;<em>.rst&rdquo; -or -name &ldquo;</em>.html&rdquo;) | wc | sed &ldquo;1i static:\nlines | words |&nbsp;bytes&rdquo; </p> <p><img alt="tu" src="//blog.pythonwood.com/static/img/代码统计3.png" title="3"></p> <h3 id="_5">前端展示:感谢前人成果!<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h3> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/前端展示1.png" title="1" width="40%"> <img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/前端展示2.png" title="2" width="40%"></p> <h3 id="_6">=============================后台是亮点=============================<a class="headerlink" href="#_6" title="Permanent link">&para;</a></h3> <p>后台首页</p> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/后台首页.png" title="1" width="90%"></p> <p>微信回复规则,使用模板渲染自定义变量!</p> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/微信回复规则,使用模板渲染自定义变量.png" title="1" width="90%"></p> <p>功能代码:</p> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/功能代码.png" title="1" width="90%"></p> <p>微信用户</p> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/微信用户.png" title="1" width="90%"></p> <p>订单截图</p> <p><img alt="tu" height="50%" src="//blog.pythonwood.com/static/img/订单截图.png" title="1" width="90%"></p> <h3 id="django">看到这里,你是否也认为django是个好框架呢?<a class="headerlink" href="#django" title="Permanent link">&para;</a></h3> <p>在新浪云上运行得还好,不算慢,请那些嫌弃django臃肿庞大,速度慢的人,不要再误导他人,这就好像那些说python慢的人一样,我至今没有实践证明出过慢在哪。</p> <p>django是python作者本身都很喜欢的框架,又是那么多商用网站的框架,经得其考验。</p> <p>如果可以,当然希望你可以作出一个比django更好的框架,可是至少现在还不大可能。python的django和ruby的rails都得经过时间的考验。我相信 django&nbsp;是经得住考验的,正如我相信python一样。</p> <h3 id="_7">附上 增加微店步骤(澳洲红酒为例)<a class="headerlink" href="#_7" title="Permanent link">&para;</a></h3> <p>复制guosetianxiang 改名&nbsp;aozhouwine</p> <p>修改setting.py 安装app&nbsp;&lsquo;aozhouwine&rsquo;</p> <p>访问/syncdb-online完成数据库同步</p> <p>根app的url.py&nbsp;加入两行:</p> <div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">aozhouwine</span> <span class="o">...</span> <span class="n">url</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^aozhouwine/&#39;</span><span class="p">,</span> <span class="n">include</span><span class="p">(</span><span class="s1">&#39;aozhouwine.urls&#39;</span><span class="p">)),</span> </pre></div> <p>admin管理,weixinshop应用商店表中增加一条,并增加账户给商店所有者A,然后授权。</p> <p>A在自己的应用商店信息表中增加一条记录,(token在此设置)。</p> <p>微信开发者url: /aozhouwine/weixin/&nbsp;token为之前设置的。</p> <p>访问/aozhouwine/sync_shopinfo完成商店同步。</p> <p>A增加消息,回复规则表中的记录。</p> <p>A上架商品。</p> <p>依然涉及少量代码操作,以及有一点繁琐。</p>微信公众平台开发(免费云BAE+高效优雅的Python+网站开放的API)2013-10-16T23:44:00+08:002017-11-27T22:12:00+08:00pythonwoodtag:blog.pythonwood.com,2013-10-16:/2013/10/微信公众平台开发(免费云BAE+高效优雅的Python+网站开放的API)/<p>虽然校园App是个我认为的绝对的好主意,但最近有个也不错的营销+开发的模式出现:微信平台+固定域名服务器。</p> <p>微信公众平台的运行模式不外两个:</p> <p>一、机器人模式或称转发模式,将说话内容转发到服务器上完成,拿服务器的回复再一次转发,就完成一次问答谈话。</p> <p>二、人控模式,一个自然人登陆公众平台上,能直接接触到所有关注者,与之交互,这一定也是最累的。</p> <p>微信公众平台若是服务号,用来做微网站,省去了登录认证过程 …</p><p>虽然校园App是个我认为的绝对的好主意,但最近有个也不错的营销+开发的模式出现:微信平台+固定域名服务器。</p> <p>微信公众平台的运行模式不外两个:</p> <p>一、机器人模式或称转发模式,将说话内容转发到服务器上完成,拿服务器的回复再一次转发,就完成一次问答谈话。</p> <p>二、人控模式,一个自然人登陆公众平台上,能直接接触到所有关注者,与之交互,这一定也是最累的。</p> <p>微信公众平台若是服务号,用来做微网站,省去了登录认证过程。但说白了就是微信定制版的微网站。这我一学期后才搞懂,如果早些弄懂就不会做那么多无用功。</p> <p>微信公众平台须有正面头像+身份证的照片来实名认证,非常严格。顺便一说,微信公众平台官方说法是偏支持大企而非个人。</p> <p>服务器(准确的说只是一个引擎)有新浪云<span class="caps">SAE</span>,百度云<span class="caps">BAE</span>,阿里云<span class="caps">AAE</span>。</p> <p><span class="caps">SAE</span>最早,但使用云豆消费,注册只送500个。到现在,<span class="caps">BAE</span>允许创建10个应用而不用实名认证,<span class="caps">SAE</span>是需实名认证的。还有<span class="caps">BAE</span>比<span class="caps">SAE</span>强的就是支持git,虽然两者都支持svn,非常合时,刚好我学习git中,我果断选择<span class="caps">BAE</span>。云上建的每个应用可有20个版本,但任一个版都可以并且唯一上线。<span class="caps">AAE</span>(阿里云)一直不支持python,很让人失望。</p> <h3 id="_1">第一阶段:入门——轻轻走过飘过。<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h3> <p>下面是用数天时间借鉴前人成果Kingson的《<a href="http://kingson.org/?p=259" title>一个用Python和Bottle实现基于微信公众平台<span class="caps">API</span>和<span class="caps">SAE</span>查询豆瓣电影的简单应用</a>》开发的。</p> <p>这个例子非常适合在用Python的开发人员。经过一番狠狠的折腾,我还弄懂了其它问题:云的概念、OAuth、token、微信<span class="caps">API</span>调用,网站<span class="caps">API</span>调用、python等,百度谷歌都会有答案。</p> <p>还有很多像微信<span class="caps">API</span>通信认证(话说竞然用xml而不用json通信,不过这是取舍问题,无可厚非),python&nbsp;web框架,git对接云服务器……用了我许多时间。过程曲折复杂,看起来只是转移一下云平台,但实名认证,开发者域名的认证等浪费了我很多时间,因为没经验,很多各种问题都撞上了,尤其是我这种粗心大意,心眼碗粗的人,整个过程实在不算顺利,但我相信别人都会比我顺利,因为我连最低级的错都犯了。不多说,贴上关键代码代码。</p> <p>下载地址:http://pan.baidu.com/s/1d1g3l</p> <table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174</pre></div></td><td class="code"><div class="highlight"><pre><span></span><span class="ch">#! /usr/bin/env python</span> <span class="c1"># coding=utf-8</span> <span class="n">__author__</span> <span class="o">=</span> <span class="s1">&#39;jszhou&#39;</span> <span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="o">*</span> <span class="kn">import</span> <span class="nn">hashlib</span> <span class="kn">import</span> <span class="nn">xml.etree.ElementTree</span> <span class="kn">as</span> <span class="nn">ET</span> <span class="kn">import</span> <span class="nn">urllib2</span> <span class="c1"># import requests</span> <span class="kn">import</span> <span class="nn">json</span> <span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd">Change Log:</span> <span class="sd">03-04--03-08 完成微信API+Python自动回复代码雏形,可以通过电影ID查询电影信息,以Text形式返回给用户电影</span> <span class="sd">Title和电影summary</span> <span class="sd"># 03-11 完成通过电影名称查询并返回图文格式的数据</span> <span class="sd"># 03-13 1.增加给新关注的用户自动返回“欢迎关注豆瓣电影,输入电影名称即可快速查询电影讯息哦!”信息的功能</span> <span class="sd"> 2.完善注释信息</span> <span class="sd">关于本地调试问题:</span> <span class="sd">微信没有提供本地调试功能,给用户造成不小的麻烦。</span> <span class="sd">打开Bottle的Debug功能,在本地运行自己的代码(启动Server),使用Chrome或Firefox上的Advanced Rest Client插件来模拟微信服务器向自己的应用发送请求,</span> <span class="sd">这样就可以看到详细的报错信息,方便开发者定位修复问题,其相当于,自己的应用是SAE,而Advanced Rest Client模拟的是新微信客户端和微信服务器。</span> <span class="sd">也有同学自己写脚本,模拟微信服务器发送数据,这也是同样的道理。</span> <span class="sd">遗留问题:</span> <span class="sd">1.从豆瓣拿到的海报图片都是竖向的,而微信中显示的是横向的,所以在微信看图片就被裁了一节,不过还好能看,</span> <span class="sd"> 如何能完整显示海报图片,有待进一步research;</span> <span class="sd">2.现在的通过电影名称返回的结果,实际上是拿的豆瓣返回的第一条数据,这样就有可能不准确,如何精确匹配用户的</span> <span class="sd"> 查询条件,也还需要进一步研究。</span> <span class="sd">&quot;&quot;&quot;</span> <span class="nd">@app.get</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">checkSignature</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> 这里是用来做接口验证的,从微信Server请求的URL中拿到“signature”,“timestamp”,&quot;nonce&quot;和“echostr”,</span> <span class="sd"> 然后再将token, timestamp, nonce三个排序并进行Sha1计算,并将计算结果和拿到的signature进行比较,</span> <span class="sd"> 如果相等,就说明验证通过。</span> <span class="sd"> 话说微信的这个验证做的很渣,因为只要把echostr返回去,就能通过验证,这也就造成我看到一个Blog中,</span> <span class="sd"> 验证那儿只返回了一个echostr,而纳闷了半天。</span> <span class="sd"> 附微信Server请求的Url示例:http://yoursaeappid.sinaapp.com//?signature=730e3111ed7303fef52513c8733b431a0f933c7c</span> <span class="sd">&amp;echostr=5853059253416844429&amp;timestamp=1362713741&amp;nonce=1362771581</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="n">token</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span> <span class="c1"># 你在微信公众平台上设置的TOKEN</span> <span class="n">signature</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;signature&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="c1"># 拼写不对害死人那,把signature写成singnature,直接导致怎么也认证不成功</span> <span class="n">timestamp</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;timestamp&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="n">nonce</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;nonce&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="n">echostr</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;echostr&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="n">tmpList</span> <span class="o">=</span> <span class="p">[</span><span class="n">token</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">,</span> <span class="n">nonce</span><span class="p">]</span> <span class="n">tmpList</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span> <span class="n">tmpstr</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">%s%s%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">tmpList</span><span class="p">)</span> <span class="n">hashstr</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">(</span><span class="n">tmpstr</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">if</span> <span class="n">hashstr</span> <span class="o">==</span> <span class="n">signature</span><span class="p">:</span> <span class="k">return</span> <span class="n">echostr</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="s2">&quot;wws:indentify error&quot;</span> <span class="k">def</span> <span class="nf">parse_msg</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> 这里是用来解析微信Server Post过来的XML数据的,取出各字段对应的值,以备后面的代码调用,也可用lxml等模块。</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="n">recvmsg</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="c1"># 严重卡壳的地方,最后还是在Stack OverFlow上找到了答案</span> <span class="n">root</span> <span class="o">=</span> <span class="n">ET</span><span class="o">.</span><span class="n">fromstring</span><span class="p">(</span><span class="n">recvmsg</span><span class="p">)</span> <span class="n">msg</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">root</span><span class="p">:</span> <span class="n">msg</span><span class="p">[</span><span class="n">child</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="n">text</span> <span class="k">return</span> <span class="n">msg</span> <span class="k">def</span> <span class="nf">query_movie_info</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> 这里使用豆瓣的电影search API,通过关键字查询电影信息,这里的关键点是,一是关键字取XML中的Content值,</span> <span class="sd"> 二是如果Content中存在汉字,就需要先转码,才能进行请求</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="n">movieurlbase</span> <span class="o">=</span> <span class="s2">&quot;http://api.douban.com/v2/movie/search&quot;</span> <span class="n">DOUBAN_APIKEY</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span> <span class="c1"># 这里需要填写你自己在豆瓣上申请的应用的APIKEY</span> <span class="n">movieinfo</span> <span class="o">=</span> <span class="n">parse_msg</span><span class="p">()</span> <span class="n">searchkeys</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">movieinfo</span><span class="p">[</span><span class="s2">&quot;Content&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">&quot;utf-8&quot;</span><span class="p">))</span> <span class="c1"># 如果Content中存在汉字,就需要先转码,才能进行请求</span> <span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1">?q=</span><span class="si">%s</span><span class="s1">&amp;apikey=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">movieurlbase</span><span class="p">,</span> <span class="n">searchkeys</span><span class="p">,</span> <span class="n">DOUBAN_APIKEY</span><span class="p">)</span> <span class="c1"># return &quot;&lt;p&gt;{&#39;url&#39;: %s}&lt;/p&gt;&quot; % url</span> <span class="c1"># url = &#39;%s%s?apikey=%s&#39; % (movieurlbase, id[&quot;Content&quot;], DOUBAN_APIKEY)</span> <span class="c1"># resp = requests.get(url=url, headers=header)</span> <span class="n">resp</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="n">movie</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">read</span><span class="p">())</span> <span class="c1"># return &quot;&lt;p&gt;{&#39;movie&#39;: %s}&lt;/p&gt;&quot; % movie</span> <span class="c1"># info = movie[&quot;subjects&quot;][0][&quot;title&quot;] + movie[&quot;subjects&quot;][0][&quot;alt&quot;]</span> <span class="c1"># info = movie[&#39;title&#39;] + &#39;: &#39; + &#39;&#39;.join(movie[&#39;summary&#39;])</span> <span class="k">return</span> <span class="n">movie</span> <span class="c1"># return info</span> <span class="k">def</span> <span class="nf">query_movie_details</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> 这里使用豆瓣的电影subject API,通过在query_movie_info()中拿到的电影ID,来获取电影的summary。</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="n">movieurlbase</span> <span class="o">=</span> <span class="s2">&quot;http://api.douban.com/v2/movie/subject/&quot;</span> <span class="n">DOUBAN_APIKEY</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span> <span class="c1"># 这里需要填写你自己在豆瓣上申请的应用的APIKEY</span> <span class="nb">id</span> <span class="o">=</span> <span class="n">query_movie_info</span><span class="p">()</span> <span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">%s%s</span><span class="s1">?apikey=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">movieurlbase</span><span class="p">,</span> <span class="nb">id</span><span class="p">[</span><span class="s2">&quot;subjects&quot;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;id&quot;</span><span class="p">],</span> <span class="n">DOUBAN_APIKEY</span><span class="p">)</span> <span class="n">resp</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="n">description</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">read</span><span class="p">())</span> <span class="n">description</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">description</span><span class="p">[</span><span class="s1">&#39;summary&#39;</span><span class="p">])</span> <span class="k">return</span> <span class="n">description</span> <span class="nd">@app.post</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span> <span class="k">def</span> <span class="nf">response_msg</span><span class="p">():</span> <span class="sd">&quot;&quot;&quot;</span> <span class="sd"> 这里是响应微信Server的请求,并返回数据的主函数,判断Content内容,如果是“Hello2BizUser”,就</span> <span class="sd"> 表明是一个新注册用户,调用纯文本格式返回,如果是其他的内容就组织数据以图文格式返回。</span> <span class="sd"> 基本思路:</span> <span class="sd"> # 拿到Post过来的数据</span> <span class="sd"> # 分析数据(拿到FromUserName、ToUserName、CreateTime、MsgType和content)</span> <span class="sd"> # 构造回复信息(将你组织好的content返回给用户)</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="c1">#拿到并解析数据</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">parse_msg</span><span class="p">()</span> <span class="c1">#设置返回数据模板</span> <span class="c1">#纯文本格式</span> <span class="n">textTpl</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;&lt;xml&gt;</span> <span class="s2"> &lt;ToUserName&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/ToUserName&gt;</span> <span class="s2"> &lt;FromUserName&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/FromUserName&gt;</span> <span class="s2"> &lt;CreateTime&gt;</span><span class="si">%s</span><span class="s2">&lt;/CreateTime&gt;</span> <span class="s2"> &lt;MsgType&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/MsgType&gt;</span> <span class="s2"> &lt;Content&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/Content&gt;</span> <span class="s2"> &lt;FuncFlag&gt;0&lt;/FuncFlag&gt;</span> <span class="s2"> &lt;/xml&gt;&quot;&quot;&quot;</span> <span class="c1">#图文格式</span> <span class="n">pictextTpl</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;&lt;xml&gt;</span> <span class="s2"> &lt;ToUserName&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/ToUserName&gt;</span> <span class="s2"> &lt;FromUserName&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/FromUserName&gt;</span> <span class="s2"> &lt;CreateTime&gt;</span><span class="si">%s</span><span class="s2">&lt;/CreateTime&gt;</span> <span class="s2"> &lt;MsgType&gt;&lt;![CDATA[news]]&gt;&lt;/MsgType&gt;</span> <span class="s2"> &lt;ArticleCount&gt;1&lt;/ArticleCount&gt;</span> <span class="s2"> &lt;Articles&gt;</span> <span class="s2"> &lt;item&gt;</span> <span class="s2"> &lt;Title&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/Title&gt;</span> <span class="s2"> &lt;Description&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/Description&gt;</span> <span class="s2"> &lt;PicUrl&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/PicUrl&gt;</span> <span class="s2"> &lt;Url&gt;&lt;![CDATA[</span><span class="si">%s</span><span class="s2">]]&gt;&lt;/Url&gt;</span> <span class="s2"> &lt;/item&gt;</span> <span class="s2"> &lt;/Articles&gt;</span> <span class="s2"> &lt;FuncFlag&gt;1&lt;/FuncFlag&gt;</span> <span class="s2"> &lt;/xml&gt; &quot;&quot;&quot;</span> <span class="c1">#判断Content内容,如果等于&quot;Hello2BizUser&quot;,表明是一个新关注用户,如果不是,就返回电影标题,电影简介</span> <span class="c1">#和电影海报组成的图文信息</span> <span class="k">if</span> <span class="n">msg</span><span class="p">[</span><span class="s2">&quot;Content&quot;</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;Hello2BizUser&quot;</span><span class="p">:</span> <span class="n">echostr</span> <span class="o">=</span> <span class="n">textTpl</span> <span class="o">%</span> <span class="p">(</span> <span class="n">msg</span><span class="p">[</span><span class="s1">&#39;FromUserName&#39;</span><span class="p">],</span> <span class="n">msg</span><span class="p">[</span><span class="s1">&#39;ToUserName&#39;</span><span class="p">],</span> <span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())),</span> <span class="n">msg</span><span class="p">[</span><span class="s1">&#39;MsgType&#39;</span><span class="p">],</span> <span class="sa">u</span><span class="s2">&quot;欢迎关注豆瓣电影,输入电影名称即可快速查询电影讯息哦!&quot;</span><span class="p">)</span> <span class="k">return</span> <span class="n">echostr</span> <span class="k">else</span><span class="p">:</span> <span class="n">Content</span> <span class="o">=</span> <span class="n">query_movie_info</span><span class="p">()</span> <span class="n">description</span> <span class="o">=</span> <span class="n">query_movie_details</span><span class="p">()</span> <span class="n">echostr</span> <span class="o">=</span> <span class="n">pictextTpl</span> <span class="o">%</span> <span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="s1">&#39;FromUserName&#39;</span><span class="p">],</span> <span class="n">msg</span><span class="p">[</span><span class="s1">&#39;ToUserName&#39;</span><span class="p">],</span> <span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())),</span> <span class="n">Content</span><span class="p">[</span><span class="s2">&quot;subjects&quot;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;title&quot;</span><span class="p">],</span> <span class="n">description</span><span class="p">,</span> <span class="n">Content</span><span class="p">[</span><span class="s2">&quot;subjects&quot;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;images&quot;</span><span class="p">][</span><span class="s2">&quot;large&quot;</span><span class="p">],</span> <span class="n">Content</span><span class="p">[</span><span class="s2">&quot;subjects&quot;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s2">&quot;alt&quot;</span><span class="p">])</span> <span class="k">return</span> <span class="n">echostr</span> <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span> <span class="c1"># Interactive mode</span> <span class="n">debug</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="p">,</span><span class="n">host</span><span class="o">=</span><span class="s1">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># Mod WSGI launch</span> <span class="c1"># import sae</span> <span class="c1"># debug(True)</span> <span class="c1"># os.chdir(os.path.dirname(__file__))</span> <span class="c1"># app = default_app()</span> <span class="c1"># application = sae.create_wsgi_app(app)</span> <span class="c1">#################################################</span> <span class="c1">#os.chdir(os.path.dirname(__file__))#Forbidden to access</span> <span class="kn">from</span> <span class="nn">bae.core.wsgi</span> <span class="kn">import</span> <span class="n">WSGIApplication</span> <span class="n">application</span> <span class="o">=</span> <span class="n">WSGIApplication</span><span class="p">(</span><span class="n">app</span><span class="p">)</span> </pre></div> </td></tr></table> <p>注:代码中用json.dumps会更好。&nbsp;后注:此注不对。</p> <h2 id="httpwwwcnblogscommchinatage5beaee4bfa1e585ace4bc97python">深入阶段,将http://www.cnblogs.com/mchina/tag/%E5%<span class="caps">BE</span>%<span class="caps">AE</span>%E4%<span class="caps">BF</span>%A1%E5%85%<span class="caps">AC</span>%E4%<span class="caps">BC</span>%97/里的功能用python实现之。<a class="headerlink" href="#httpwwwcnblogscommchinatage5beaee4bfa1e585ace4bc97python" title="Permanent link">&para;</a></h2> <p>……</p> <p>本代码需要与bottle.py一并上传到服务器空间。</p> <p>附上一些特别信息:</p> <p>微信开发调试小工具下载:http://www.cnblogs.com/linkbiz/archive/2013/05/16/3080306.html</p> <p>本人微信公众号pythonwoodpub,&nbsp;开发项目澳洲红酒微信服务号,</p> <p><img alt="本人微信公众号pythonwoodpub.jpg" height="50%" src="//blog.pythonwood.com/uploads/2013/本人微信公众号pythonwoodpub.jpg" title="1" width="40%"> <img alt="开发项目澳洲红酒微信服务号.jpg" height="50%" src="//blog.pythonwood.com/uploads/2013/开发项目澳洲红酒微信服务号.jpg" title="1" width="40%"></p>