zoukankan      html  css  js  c++  java
  • [python]微信公众号+python+新浪SAE实现实时天气预报功能

    本文主要谈谈如何做一个具有天气预报功能的公众号。

    话不多说先上图,实现的功能如下图所示:

    点击微信右下角的“+”号,分享任意一个位置信息,公众号后台自动回复当地的天气情况。这里的天气预报是用python从中国天气网抓取的雷达数据。有没有更精准的数据源呢,当然有啦,但这不是本文的重点,这里我就不详说了。

    用到的工具:新浪SAE + 微信公众平台 + python2.7(新浪SAE目前仅支持2.7版本)

    由于本文的重点不是使用python搭建微信公众平台,网上已经有很多不错的教程,为了避免重复造轮子,我在这里贴一个不错的教程,很适合新手入门:

    使用python一步一步搭建微信公众平台

    在开始之前我们有必要了解一下微信公众平台的开发者文档,查阅可知,微信的消息是以XML(可扩展标记语言)的形式传输的,其中地理位置信息的具体格式是:

    相应的参数意义如下:

    因此天气预报功能的实现流程为:

    在读取经纬度时涉及到一个问题,由于百度地图与谷歌地图采用的是不同协议的坐标,腾讯、高德地图与谷歌地图采用的是同种协议。而微信的经纬度信息是腾讯地图给出的,在网站上查看中国天气网发送的url请求可知,中国天气网采用的是百度地图,因此在查询之前需要对经纬度信息做一次转换。具体的转换方式请查看:

    百度经纬度和谷歌经纬度转换

    如何根据经纬度查询当地天气信息?

    1.用chrome浏览器进入中国天气网临近预报页面

    2.按F12打开控制台,点击地图上任意一个点

    3.查看Network,发现有一条萌萌哒url

    4.点击url查看请求和响应信息,发现响应的是一段Json信息,猜想可能是天气信息;

    5.打开该url,发现一段萌萌哒数据

    红色部分就是我们想要的东西了

    6.接下来要做的就是利用Python抓取这段数据了,由于这段数据并不是严格的Json数据(可能是为了防爬虫而采取的简单措施吧),所以需要先截取出Json部分。不过相对还是比较简单的。

    下面就直接上代码啦,此处默认读者已经会使用web.py搭建微信公众号了。代码里面有彩蛋请自行查阅~这里不方便宣传,因为偷偷用了人家的url…

      1 # -*- coding: utf-8 -*-
      2 import hashlib
      3 import web
      4 import lxml
      5 import time
      6 import os
      7 import urllib2,json
      8 import urllib
      9 import re
     10 import random
     11 import hashlib
     12 import cookielib
     13 import requests
     14 import math
     15 import re
     16 import sys
     17 reload(sys)
     18 sys.setdefaultencoding('utf8')
     19 from bs4 import BeautifulSoup
     20 from urllib import urlencode
     21 from lxml import etree
     22 from smtplib import SMTP_SSL
     23 from email.header import Header
     24 from email.mime.text import MIMEText
     25 
     26 #session = requests.Session()
     27 #s.config['keep_alivesession = requests.Session()
     28 class WeixinInterface:
     29 
     30     def __init__(self):
     31         self.app_root = os.path.dirname(__file__)
     32         self.templates_root = os.path.join(self.app_root, 'templates')
     33         self.render = web.template.render(self.templates_root)
     34 
     35     def GET(self):
     36         #获取输入参数
     37         data = web.input()
     38         signature=data.signature
     39         timestamp=data.timestamp
     40         nonce=data.nonce
     41         echostr = data.echostr
     42         #自己的token
     43         token="" #这里改写你在微信公众平台里输入的token
     44         #字典序排序
     45         list=[token,timestamp,nonce]
     46         list.sort()
     47         sha1=hashlib.sha1()
     48         map(sha1.update,list)
     49         hashcode=sha1.hexdigest()
     50         #sha1加密算法
     51 
     52         #如果是来自微信的请求,则回复echostr
     53         if hashcode == signature:
     54             return echostr
     55 
     56     def POST(self): 
     57         str_xml = web.data() #获得post来的数据 
     58         xml = etree.fromstring(str_xml)#进行XML解析 
     59         msgType=xml.find("MsgType").text
     60         fromUser=xml.find("FromUserName").text 
     61         toUser=xml.find("ToUserName").text 
     62         if msgType == 'location':
     63             wdu = xml.find("Location_X").text
     64             wdu = float(wdu)
     65             
     66             jdu = xml.find("Location_Y").text
     67             jdu = float(jdu)
     68             #转换为百度标准
     69             x_pi = 3.14159265358979324 * 3000.0 / 180.0
     70             x = jdu
     71             y = wdu
     72             z = math.sqrt(x * x + y * y) + 0.00002 * math.sin(y * x_pi)
     73             theta = math.atan2(y, x) + 0.000003 * math.cos(x * x_pi)
     74             jdu = z * math.cos(theta) + 0.0065
     75             wdu = z * math.sin(theta) + 0.006
     76             wdu = str(wdu)
     77             jdu = str(jdu)
     78             Lmesag = u"您的位置:"
     79             Lmesag += xml.find("Label").text
     80             myres = requests.get('http://d3.weather.com.cn/webgis_rain_new/webgis/ele?lat='+ wdu + '&lon='+ jdu + '&callback=fc5m&_=1470809429568')
     81             if myres.status_code != 200:
     82                 if myres.status_code == 500:
     83                     status_error = u"服务器未响应,请稍后再试~"
     84                     return self.render.reply_text(fromUser,toUser,int(time.time()), status_error)
     85             myres.encoding = 'utf-8'
     86             text = myres.text
     87             text = text[9:-2]
     88             data = json.loads(text)
     89             pretime = data['time']
     90             msg = data['msg']
     91             pretime1 = u"查询时间:"
     92             pretime1 += pretime
     93             msg1 = "天气预报:
    中国天气网雷达数据(雷达外推数据,仅供参考):"
     94             msg1 += msg
     95             Lmesag += '
    '
     96             Lmesag += pretime1
     97             Lmesag += '
    '
     98             Lmesag += msg1
     99             cyres = requests.get('http://www.caiyunapp.com/fcgi-bin/v1/api.py?lonlat=' + jdu + ',' + wdu + '&format=json&product=minutes_prec&token=96Ly7wgKGq6FhllM&random=0.8600497214532319')
    100             cyres.encoding = "utf-8"
    101             cyData = json.loads(cyres.text)
    102             cymsg = u"
    
    彩云天气数据(准确率较高):"
    103             #cymsg += cyData['summary']
    104             cytemp = u"
    温度:"
    105             cytemp += str(cyData['temp'])
    106             cymsg += cytemp
    107             cymsg +=u"
    未来1小时天气预报:"
    108             cymsg += cyData['summary']
    109             Lmesag += cymsg
    110             return self.render.reply_text(fromUser,toUser,int(time.time()), Lmesag)
    111         else:
    112             pass
  • 相关阅读:
    接口的幂等性原则
    SpringBoot热部署-解决方案
    @Resource 与 @Service注解的区别
    软件概要设计做什么,怎么做
    First Show
    Glide源码解析一,初始化
    android使用giflib加载gif
    android的APT技术
    RxJava的concat操作符
    RxJava基本使用
  • 原文地址:https://www.cnblogs.com/wxj233/p/6084143.html
Copyright © 2011-2022 走看看