python微信公众号自动推送(十分简单的教程)

b3b0f8a7d0434498920c018a4a44fcbb.jpeg

目录

一、注册微信公众号

     1.注册链接

    2.登录成功

3.关注该公众号

4.创建模板

二、代码实现

1.爬取天气信息

2.计算生日天数

 3.获取access token

4.获取关注者的openid

5.向用户广播消息

6.最终代码


2023年五月五日更:

   自五月四日起原来的微信公众号模版将不再生效,可根据最新的开发文档更新的规则对自己的模版进行修改,修改过后即可重新获取到有内容的微信公众号推送

基础消息能力 / 模板消息接口 (qq.com)

4e7ac03f274e4a01b7245da3831dc180.png

也就是说现在的公众号模板的格式必须是正文中的第二种模板也就是下面这样 关键词:{ {xxx.DATA}},而且现在\n也不能使用无法换行了,只能到达字数限制后自动换行而且字数太多还会省...... 我只能说钩史微信还老子女神!!!

一、注册微信公众号

     1.注册链接

https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/indexhttps://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

a5d25c810a1347519ad3aa02a16ff062.png

到达这个界面微信扫码登录即可(若出现登录失败问题则建议换一个更好的网络环境再尝试或者尝试刷新网页)

    2.登录成功

 66a30a81c61a46bd9e6f312eb08d9011.jpeg

登录成功后会自动生成你的appid和appsecret(后面会用到) 接口信息等暂时不用管若后期想完全实现自动推送则需要挂自己的服务器(后续会更新)

3.关注该公众号

9814f436792f4ddb91cb3ebd808c3346.jpeg

 扫码关注即可(建议不要心急自己调试好了再让npy关注)

4.创建模板

 创建模板时既可以将所有的 文本文字+数据 放在一起当作数据像这样

0e1c775f4dc24345993ca2a150474633.png

 也可以再模板内先写出来,但是这种方法会让模板的灵活性变小做大的修改只能重新创建新的模板 

 bff0ecfa04f94e739eeff756a1cf0115.png

 创建好模板微信公众号注册的工作就结束了

二、代码实现

首先了解以下的几个库

import requests
import json
import datetime
import time
from bs4 import BeautifulSoup
from zhdate import ZhDate
#用到的库

1.爬取天气信息

def get_weather(self):
        """
        该方法中用到了beautifulsoup的一些基本用法
        感兴趣可以深入了解python爬虫
        """
        url = 'http://www.weather.com.cn/weather/101290101.shtml'     #昆明天气网站
        sysdate = datetime.date.today()
        r = requests.get(url, timeout=30)                             # 用requests抓取网页
        r.raise_for_status()                                          # 异常时停止
        r.encoding = r.apparent_encoding                              # 编码格式
        html = r.text
        final_list = []
        soup = BeautifulSoup(html, 'html.parser')       # 用BeautifulSoup库解析网页
        body = soup.body                                  # 从soup里截取body的一部分
        data = body.find('div', {'id': '7d'})        #在网页浏览器按F12遍历div 找到 id = 7d                                                                 
                                             #的对应标签 会发现七天的天气信息都包括在子节点中
        ul = data.find('ul')                                          #用find方法找ul标签
        lis = ul.find_all('li')                                       #找到ul中的li标签也就是列表其中存放着 日期 天气 风力等信息 
 
        for day in lis:
            temp_list = []
 
            date = day.find('h1').string                              # 找到日期
            if date.string.split('日')[0] == str(sysdate.day):
                temp_list = []
 
                date = day.find('h1').string                          # 找到日期
                temp_list.append(date)
 
                info = day.find_all('p')                              # 找到所有的p标签
                temp_list.append(info[0].string)
 
                if info[1].find('span') is None:                      # 找到p标签中的第二个值'span'标签——最高温度
                    temperature_highest = ' '                         # 用一个判断是否有最高温度
                else:
                    temperature_highest = info[1].find('span').string
                    temperature_highest = temperature_highest.replace('℃', ' ')
 
                if info[1].find('i') is None:                         # 找到p标签中的第二个值'i'标签——最高温度
                    temperature_lowest = ' '                          # 用一个判断是否有最低温度
                else:
                    temperature_lowest = info[1].find('i').string
                    temperature_lowest = temperature_lowest.replace('℃', ' ')
 
                temp_list.append(temperature_highest)                 # 将最高气温添加到temp_list中
                temp_list.append(temperature_lowest)                  # 将最低气温添加到temp_list中
 
                final_list.append(temp_list)                          # 将temp_list列表添加到final_list列表中
                return '天气情况:' + final_list[0][1] + '\n温度:' + final_list[0][3].strip() + '~' + \
                               final_list[0][2].strip() + '℃'

2.计算生日天数

 def get_herbirthday(self):
        """
        获取npy生日 这里还用到了农历时间库
        可以去网上查阅 ZhDate库 其他基本上是datetime中的一些获取当前日期和toordinal
        没什么特别难的
        """
        today = datetime.datetime.now()                               #获取现在时间信息
        data_str = today.strftime('%Y-%m-%d')
        herbirthDay = ZhDate(today.year, 1, 18).to_datetime()          #将农历1.18号的时间转换为公历时间再转换为datetime类型的时间
        if herbirthDay >today :                                        #如果ta的生日日期比今天靠后则直接计算这两天的序号之差
            difference = herbirthDay.toordinal() - today.toordinal()
            return ("\n距离xxx生日,还有 %d 天。" % (difference))
        elif herbirthDay <today:                                       #如果ta的生日日期比今天靠前则给ta的生日加上一年再计算这两天的序号之差
            herbirthDay = herbirthDay.replace(today.year+1)
            difference = herbirthDay.toordinal() - today.toordinal()
            return ("\n距离xxx生日,还有 %d 天。" % (difference))
        else:
            return ('生日快乐bb!!')

 3.获取access token

获取公众号的access_token值,access_token是公众号全局唯一接口调用凭据,公众号调用各接口时都需要使用access_token。api接口:接口调用请求说明
https请求方式:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={你的appid}&secret={你的appsecret}
 def get_access_token(self):
        """
        获取access_token
        通过查阅微信公众号的开发说明就清晰明了了
        """
        url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.\
            format(self.appID, self.appsecret)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36'
        }
        response = requests.get(url, headers=headers).json()
        access_token = response.get('access_token')
        return access_token

4.获取关注者的openid

   opend_id是(有关注公众号的微信账号)用户id,想要消息推送过去就必须要获取open_id

获取open id的https请求方式为

https://api.weixin.qq.com/cgi-bin/user/get?access_token={获取的access token}&next_openid={}
def get_openid(self):
        """
        获取所有用户的openid
        微信公众号开发文档中可以查阅获取openid的方法
        """
        next_openid = ''
        url_openid = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s' % (self.access_token, next_openid)
        ans = requests.get(url_openid)
        open_ids = json.loads(ans.content)['data']['openid']
        return open_ids

5.向用户广播消息

http请求方式:

 POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
def sendmsg(self):  
        """
        给所有用户发送消息
        """
        url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}".format(self.access_token)
 
        if self.opend_ids != '':
            for open_id in self.opend_ids:
                body = {
                        "touser": open_id,
                        "template_id": self.template_id,
                        "url": "https://www.baidu.com/",
                        "topcolor": "#FF0000",
                         #对应模板中的数据模板
                        "data": {
                            "frist": {
                                "value": self.dataJson.get("frist"),               
                                "color": "#FF99CC"                                  #文字颜色
                            },
                            "body": {
                                "value": self.dataJson.get("body"),
                                "color": "#EA0000"
                            },
                            "weather": {
                                "value": self.dataJson.get("weather"),
                                "color": "#00EC00"
                            },
                             "date": {
                                "value": self.dataJson.get("date"),
                                "color": "#6F00D2"
                            },
                            "remark": {
                                "value": self.dataJson.get("remark"),
                                "color": "#66CCFF"
                            }
                        }
                    }
                data = bytes(json.dumps(body, ensure_ascii=False).encode('utf-8'))  #将数据编码json并转换为bytes型
                response = requests.post(url, data=data)                    
                result = response.json()                                            #将返回信息json解码
                print(result)                                                       # 根据response查看是否广播成功
        else:
            print("当前没有用户关注该公众号!")
 

6.最终代码

import requests
import json
import datetime
import time
from bs4 import BeautifulSoup
from zhdate import ZhDate
 
class SendMessage():                                                 #定义发送消息的类
    def __init__(self):                                              
        date = self.get_date()                                       #获取当前日期
        weather = self.get_weather()                                 #获取天气信息
        lovedate = self.get_loveday()                                #获取纪念日
        herbirthday = self.get_herbirthday()                         #获取npy生日
        body =lovedate+"\n"+herbirthday+mybirthday                   
        self.dataJson ={"frist":"早上好bb!❤\n",                     #最终要发送的json
                        "date":date+'\n',
                        "body":body+" ",
                        "weather":weather+'\n城市:昆明'+'\n',        #因为还没写获取地理位置的所以城市暂时写死 后续将会改为获取当前位置并爬取对应城市的天气信息版本
                        "last":'\n今天也是爱bb🐖的一天捏!!!'      
                        }
        self.appID = ''                             #appid 注册时有
        self.appsecret = ''           #appsecret 同上
        self.template_id = ''  # 模板id
        self.access_token = self.get_access_token()                   #获取 access token
        self.opend_ids = self.get_openid()                            #获取关注用户的openid
 
 

 
    def get_weather(self):
        """
        该方法中用到了beautifulsoup的一些基本用法
        感兴趣可以深入了解python爬虫
        """
        url = 'http://www.weather.com.cn/weather/101290101.shtml'     #昆明天气网站
        sysdate = datetime.date.today()
        r = requests.get(url, timeout=30)                             # 用requests抓取网页信息
        r.raise_for_status()                                          # 异常时停止
        r.encoding = r.apparent_encoding                              # 编码格式
        html = r.text
        final_list = []
        soup = BeautifulSoup(html, 'html.parser')                     # 用BeautifulSoup库解析网页 #soup里有对当前天气的建议
        body = soup.body                                              # 从soup里截取body的一部分
        data = body.find('div', {'id': '7d'})                         #在网页浏览器按F12遍历div 找到 id = 7d 的对应标签 会发现七天的天气信息都包括在子节点中
        ul = data.find('ul')                                          #用find方法找ul标签
        lis = ul.find_all('li')                                       #找到ul中的li标签也就是列表其中存放着 日期 天气 风力等信息 
 
        for day in lis:
            temp_list = []
 
            date = day.find('h1').string                              # 找到日期
            if date.string.split('日')[0] == str(sysdate.day):
                temp_list = []
 
                date = day.find('h1').string                          # 找到日期
                temp_list.append(date)
 
                info = day.find_all('p')                              # 找到所有的p标签
                temp_list.append(info[0].string)
 
                if info[1].find('span') is None:                      # 找到p标签中的第二个值'span'标签——最高温度
                    temperature_highest = ' '                         # 用一个判断是否有最高温度
                else:
                    temperature_highest = info[1].find('span').string
                    temperature_highest = temperature_highest.replace('℃', ' ')
 
                if info[1].find('i') is None:                         # 找到p标签中的第二个值'i'标签——最高温度
                    temperature_lowest = ' '                          # 用一个判断是否有最低温度
                else:
                    temperature_lowest = info[1].find('i').string
                    temperature_lowest = temperature_lowest.replace('℃', ' ')
 
                temp_list.append(temperature_highest)                 # 将最高气温添加到temp_list中
                temp_list.append(temperature_lowest)                  # 将最低气温添加到temp_list中
 
                final_list.append(temp_list)                          # 将temp_list列表添加到final_list列表中
                return '天气情况:' + final_list[0][1] + '\n温度:' + final_list[0][3].strip() + '~' + \
                               final_list[0][2].strip() + '℃'
    def get_date(self):
        """
        这些都是datetime库中的用法
        若零基础可以去python的开发文档中查阅
        """
        sysdate = datetime.date.today()                 # 只获取日期
        now_time = datetime.datetime.now()              # 获取日期加时间
        week_day = sysdate.isoweekday()                 # 获取周几
        week = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天']
        return '现在是' + str(now_time)[0:16] + ' ' + week[week_day - 1]
 
    def get_herbirthday(self):
        """
        获取npy生日 这里还用到了农历时间库
        可以去网上查阅 ZhDate库 其他基本上是datetime中的一些获取当前日期和toordinal
        没什么特别难的
        """
        today = datetime.datetime.now()                               #获取现在时间信息
        data_str = today.strftime('%Y-%m-%d')
        herbirthDay = ZhDate(today.year, 1, 18).to_datetime()          #将农历1.18号的时间转换为公历时间再转换为datetime类型的时间
        if herbirthDay >today :                                        #如果ta的生日日期比今天靠后则直接计算这两天的序号之差
            difference = herbirthDay.toordinal() - today.toordinal()
            return ("\n距离熊又又生日,还有 %d 天。" % (difference))
        elif herbirthDay <today:                                       #如果ta的生日日期比今天靠前则给ta的生日加上一年再计算这两天的序号之差
            herbirthDay = herbirthDay.replace(today.year+1)
            difference = herbirthDay.toordinal() - today.toordinal()
            return ("\n距离熊又又生日,还有 %d 天。" % (difference))
        else:
            return ('生日快乐bb!!')
    
    def get_loveday(self):
        """用法同上"""
        today = datetime.datetime.now()
        data_str = today.strftime('%Y-%m-%d')
        oneDay = datetime.date(2022, 4, 4)
        d =  today.toordinal()-oneDay.toordinal()
        return ("我们已经相爱 %d 天。\n%d 年 %d 个月 %d 天。\n%d 个月 %d 天。\n%d 周 %d 天。" % (d,d // 365, (d % 365) // 30, (d % 365) % 30, d // 30, d % 30, d // 7, d % 7))
 
    def get_access_token(self):
        """
        获取access_token
        通过查阅微信公众号的开发说明就清晰明了了
        """
        url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.\
            format(self.appID, self.appsecret)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36'
        }
        response = requests.get(url, headers=headers).json()
        access_token = response.get('access_token')
        return access_token
 
    def get_openid(self):
        """
        获取所有用户的openid
        微信公众号开发文档中可以查阅获取openid的方法
        """
        next_openid = ''
        url_openid = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s' % (self.access_token, next_openid)
        ans = requests.get(url_openid)
        open_ids = json.loads(ans.content)['data']['openid']
        return open_ids
 
    def sendmsg(self):  
        """
        给所有用户发送消息
        """
        url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}".format(self.access_token)
 
        if self.opend_ids != '':
            for open_id in self.opend_ids:
                body = {
                        "touser": open_id,
                        "template_id": self.template_id,
                        "url": "https://www.baidu.com/",
                        "topcolor": "#FF0000",
                         #对应模板中的数据模板
                        "data": {
                            "frist": {
                                "value": self.dataJson.get("frist"),               
                                "color": "#FF99CC"                                  #文字颜色
                            },
                            "body": {
                                "value": self.dataJson.get("body"),
                                "color": "#EA0000"
                            },
                            "weather": {
                                "value": self.dataJson.get("weather"),
                                "color": "#00EC00"
                            },
                             "date": {
                                "value": self.dataJson.get("date"),
                                "color": "#6F00D2"
                            },
                            "last": {
                                "value": self.dataJson.get("last"),
                                "color": "#66CCFF"
                            }
                        }
                    }
                data = bytes(json.dumps(body, ensure_ascii=False).encode('utf-8'))  #将数据编码json并转换为bytes型
                response = requests.post(url, data=data)                    
                result = response.json()                                            #将返回信息json解码
                print(result)                                                       # 根据response查看是否广播成功
        else:
            print("当前没有用户关注该公众号!")
 
if __name__ == "__main__":
    sends = SendMessage()
    sends.sendmsg()

代码还有很多需要改进的地方

大佬轻喷!!!

### 关于微信公众号推送消息API的使用 #### 获取Access Token 为了能够调用微信公众号消息推送接口,开发者首先需要获得`access_token`。这是微信公众平台提供的一种凭证机制,用于验证请求的身份合法性。获取此令牌的过程涉及向特定URL发起GET请求,并附带应用ID(AppID)和应用密钥(AppSecret),这些参数可以在公众平台设置页面找到[^1]。 ```java // Java示例代码片段:获取 access_token 的 HTTP 请求构建 String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APP_ID&secret=APP_SECRET"; HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection(); conn.setRequestMethod("GET"); ``` #### 创建并发送模板消息 一旦成功取得有效的`access_token`之后,就可以准备创建想要推送给用户的模板消息了。这一步骤通常包括定义消息的内容结构、指定接收者的OpenID以及其他必要的字段如模板ID等。需要注意的是,每种类型的模板都有其固定的格式要求,因此建议参照官方提供的样例来填充相应部分的数据[^3]。 ```json { "touser":"OPENID", "template_id":"TEMPLATE_ID", "url":"http://weixin.qq.com/download", // 可选链接地址 "miniprogram":{ "appid":"MINI_PROGRAM_APPID", // 小程序 AppId "pagepath":"/pages/index/index" // 页面路径 }, "data": { ... } } ``` #### 发送POST请求至服务器端口 最后一步则是将上述构造好的JSON对象作为body内容,连同之前得到的`access_token`一起提交给微信服务器。这里采用HTTP POST方式发送请求,目标网址形似如下所示: `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=TOKEN_VALUE` 确保所使用的IP已被加入到微信公众账号的安全中心->服务器配置下的合法域名列表内;对于测试环境中同样适用这一规则[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值