├── LICENSE ├── README.md ├── main.py └── requirements.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 TechShrimp技术爬爬虾 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 免费微信推送 2 | 原理:申请免费的测试版公众号,可获得免费的模板推送功能。 3 | 4 | ### 视频教程 5 | 6 | https://www.bilibili.com/video/BV1Ng4y1r7EP/ 7 | 8 | 作者 **技术爬爬虾** 全网同名,转载请注明作者 9 | 10 | ### 申请公众号测试账户 11 | 12 | 使用微信扫码即可 13 | https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 14 | 15 | 进入页面以后我们来获取到这四个值 16 | #### appID appSecret openId template_id 17 | ![image](https://github.com/tech-shrimp/FreeWechatPush/assets/154193368/bdb27abd-39cb-4e77-9b89-299afabc7330) 18 | 19 | 想让谁收消息,谁就用微信扫二维码,然后出现在用户列表,获取微信号(openId) 20 | ![image](https://github.com/tech-shrimp/FreeWechatPush/assets/154193368/1327c6f5-5c92-4310-a10b-6f2956c1dd75) 21 | 22 | 新增测试模板获得 template_id(模板ID) 23 | ![image](https://github.com/tech-shrimp/FreeWechatPush/assets/154193368/ec689f4d-6c0b-44c4-915a-6fd7ada17028) 24 | 25 | 模板标题随便填,模板内容如下,可以根据需求自己定制 26 | 27 | 模板一 天气预报: 28 | ```copy 29 | 今天:{{date.DATA}} 30 | 地区:{{region.DATA}} 31 | 天气:{{weather.DATA}} 32 | 气温:{{temp.DATA}} 33 | 风向:{{wind_dir.DATA}} 34 | 对你说的话:{{today_note.DATA}} 35 | ``` 36 | 37 | 模板二 课程提醒: 38 | ```copy 39 | 消息:{{message.DATA}} 40 | ``` 41 | 42 | ### 配置代码 43 | 44 | 将上面获得的几个值填入代码这几行 45 | ![image](https://github.com/tech-shrimp/FreeWechatPush/assets/154193368/fe5a78ad-b4eb-45f8-a271-eda55f33a617) 46 | ### 配置定时任务 47 | 48 | 修改这几行 49 | ![image](https://github.com/tech-shrimp/FreeWechatPush/assets/154193368/58b7c58c-ac22-4a1a-b3e8-2eacc01b7329) 50 | 51 | ### 安装python依赖,启动项目 52 | ```copy 53 | pip3 install -r requirements.txt 54 | python main.py 55 | ``` 56 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # 安装依赖 pip3 install requests html5lib bs4 schedule 2 | 3 | import time 4 | import requests 5 | import json 6 | import schedule 7 | from bs4 import BeautifulSoup 8 | 9 | 10 | # 从测试号信息获取 11 | appID = "" 12 | appSecret = "" 13 | #收信人ID即 用户列表中的微信号,见上文 14 | openId = "" 15 | # 天气预报模板ID 16 | weather_template_id = "" 17 | # 时间表模板ID 18 | timetable_template_id = "" 19 | 20 | 21 | def get_weather(my_city): 22 | urls = ["http://www.weather.com.cn/textFC/hb.shtml", 23 | "http://www.weather.com.cn/textFC/db.shtml", 24 | "http://www.weather.com.cn/textFC/hd.shtml", 25 | "http://www.weather.com.cn/textFC/hz.shtml", 26 | "http://www.weather.com.cn/textFC/hn.shtml", 27 | "http://www.weather.com.cn/textFC/xb.shtml", 28 | "http://www.weather.com.cn/textFC/xn.shtml" 29 | ] 30 | for url in urls: 31 | resp = requests.get(url) 32 | text = resp.content.decode("utf-8") 33 | soup = BeautifulSoup(text, 'html5lib') 34 | div_conMidtab = soup.find("div", class_="conMidtab") 35 | tables = div_conMidtab.find_all("table") 36 | for table in tables: 37 | trs = table.find_all("tr")[2:] 38 | for index, tr in enumerate(trs): 39 | tds = tr.find_all("td") 40 | # 这里倒着数,因为每个省会的td结构跟其他不一样 41 | city_td = tds[-8] 42 | this_city = list(city_td.stripped_strings)[0] 43 | if this_city == my_city: 44 | 45 | high_temp_td = tds[-5] 46 | low_temp_td = tds[-2] 47 | weather_type_day_td = tds[-7] 48 | weather_type_night_td = tds[-4] 49 | wind_td_day = tds[-6] 50 | wind_td_day_night = tds[-3] 51 | 52 | high_temp = list(high_temp_td.stripped_strings)[0] 53 | low_temp = list(low_temp_td.stripped_strings)[0] 54 | weather_typ_day = list(weather_type_day_td.stripped_strings)[0] 55 | weather_type_night = list(weather_type_night_td.stripped_strings)[0] 56 | 57 | wind_day = list(wind_td_day.stripped_strings)[0] + list(wind_td_day.stripped_strings)[1] 58 | wind_night = list(wind_td_day_night.stripped_strings)[0] + list(wind_td_day_night.stripped_strings)[1] 59 | 60 | # 如果没有白天的数据就使用夜间的 61 | temp = f"{low_temp}——{high_temp}摄氏度" if high_temp != "-" else f"{low_temp}摄氏度" 62 | weather_typ = weather_typ_day if weather_typ_day != "-" else weather_type_night 63 | wind = f"{wind_day}" if wind_day != "--" else f"{wind_night}" 64 | return this_city, temp, weather_typ, wind 65 | 66 | 67 | def get_access_token(): 68 | # 获取access token的url 69 | url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}' \ 70 | .format(appID.strip(), appSecret.strip()) 71 | response = requests.get(url).json() 72 | print(response) 73 | access_token = response.get('access_token') 74 | return access_token 75 | 76 | 77 | def get_daily_love(): 78 | # 每日一句情话 79 | url = "https://api.lovelive.tools/api/SweetNothings/Serialization/Json" 80 | r = requests.get(url) 81 | all_dict = json.loads(r.text) 82 | sentence = all_dict['returnObj'][0] 83 | daily_love = sentence 84 | return daily_love 85 | 86 | 87 | def send_weather(access_token, weather): 88 | # touser 就是 openID 89 | # template_id 就是模板ID 90 | # url 就是点击模板跳转的url 91 | # data就按这种格式写,time和text就是之前{{time.DATA}}中的那个time,value就是你要替换DATA的值 92 | 93 | import datetime 94 | today = datetime.date.today() 95 | today_str = today.strftime("%Y年%m月%d日") 96 | 97 | body = { 98 | "touser": openId.strip(), 99 | "template_id": weather_template_id.strip(), 100 | "url": "https://weixin.qq.com", 101 | "data": { 102 | "date": { 103 | "value": today_str 104 | }, 105 | "region": { 106 | "value": weather[0] 107 | }, 108 | "weather": { 109 | "value": weather[2] 110 | }, 111 | "temp": { 112 | "value": weather[1] 113 | }, 114 | "wind_dir": { 115 | "value": weather[3] 116 | }, 117 | "today_note": { 118 | "value": get_daily_love() 119 | } 120 | } 121 | } 122 | url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}'.format(access_token) 123 | print(requests.post(url, json.dumps(body)).text) 124 | 125 | 126 | def send_timetable(access_token, message): 127 | body = { 128 | "touser": openId, 129 | "template_id": timetable_template_id.strip(), 130 | "url": "https://weixin.qq.com", 131 | "data": { 132 | "message": { 133 | "value": message 134 | }, 135 | } 136 | } 137 | url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}'.format(access_token) 138 | print(requests.post(url, json.dumps(body)).text) 139 | 140 | 141 | def weather_report(city): 142 | # 1.获取access_token 143 | access_token = get_access_token() 144 | # 2. 获取天气 145 | weather = get_weather(city) 146 | print(f"天气信息: {weather}") 147 | # 3. 发送消息 148 | send_weather(access_token, weather) 149 | 150 | 151 | def timetable(message): 152 | # 1.获取access_token 153 | access_token = get_access_token() 154 | # 3. 发送消息 155 | send_timetable(access_token, message) 156 | 157 | 158 | if __name__ == '__main__': 159 | weather_report("青岛") 160 | # timetable("第二教学楼十分钟后开始英语课") 161 | 162 | # schedule.every().day.at("18:30").do(weather_report, "南京") 163 | # schedule.every().monday.at("13:50").do(timetable, "第二教学楼十分钟后开始英语课") 164 | #while True: 165 | # schedule.run_pending() 166 | # time.sleep(1) 167 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | schedule 3 | bs4 4 | html5lib 5 | --------------------------------------------------------------------------------