├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── everyday_wechat ├── __init__.py ├── _config.yaml ├── control │ ├── __init__.py │ ├── airquality │ │ ├── __init__.py │ │ └── air_quality_aqicn.py │ ├── bot │ │ ├── __init__.py │ │ ├── ownthink_robot.py │ │ ├── qingyunke.py │ │ ├── qq_nlpchat.py │ │ ├── ruyiai.py │ │ ├── tian_robot.py │ │ ├── tuling123.py │ │ └── yigeai.py │ ├── calendar │ │ ├── __init__.py │ │ ├── rt_calendar.py │ │ └── sojson_calendar.py │ ├── express │ │ ├── __init__.py │ │ └── kdniao_express.py │ ├── horoscope │ │ ├── __init__.py │ │ └── xzw_horescope.py │ ├── moviebox │ │ ├── __init__.py │ │ └── maoyan_movie_box.py │ ├── onewords │ │ ├── __init__.py │ │ ├── acib.py │ │ ├── caihongpi.py │ │ ├── hitokoto.py │ │ ├── juzimi.py │ │ ├── lovelive.py │ │ ├── rtjokes.py │ │ └── wufazhuce.py │ ├── rubbish │ │ ├── __init__.py │ │ └── atoolbox_rubbish.py │ └── weather │ │ ├── __init__.py │ │ ├── _city_sojson.json │ │ ├── rtweather.py │ │ └── sojson.py ├── main.py └── utils │ ├── __init__.py │ ├── common.py │ ├── config.py │ ├── data_collection.py │ ├── db_helper.py │ ├── friend_helper.py │ ├── group_helper.py │ └── itchat_helper.py ├── history.md ├── requirements.txt ├── run.py └── tests ├── __init__.py ├── test_01.py ├── test_alarm ├── __init__.py ├── _trial_temp-1 │ ├── _trial_marker │ └── test.log ├── _trial_temp.lock │ └── symlink ├── _trial_temp │ ├── _trial_marker │ └── test.log └── test_info.py ├── test_config └── __init__.py ├── test_control ├── __init__.py ├── _trial_temp │ ├── _trial_marker │ └── test.log ├── test_one_words.py └── test_rubbish.py ├── test_db ├── __init__.py ├── _trial_temp │ ├── _trial_marker │ └── test.log ├── test_air.py ├── test_db.py └── test_express.py └── test_email_alarm ├── __init__.py └── test_email.py /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git 2 | .git 3 | .gitignore 4 | 5 | # PyCharm 6 | .idea 7 | 8 | # Virtual environment 9 | .env/ 10 | .venv/ 11 | venv/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | __pycache__ 3 | itchat.pkl 4 | QR.png 5 | 6 | venv/ 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 说明该镜像以哪个镜像为基础 2 | FROM python:3.7-slim 3 | 4 | RUN mkdir /app 5 | WORKDIR /app 6 | 7 | COPY requirements.txt requirements.txt 8 | 9 | RUN pip install -r requirements.txt 10 | COPY . /app 11 | 12 | ENV MODE server 13 | 14 | # 构建者的基本信息 15 | MAINTAINER DoubleThunder 16 | 17 | 18 | ENTRYPOINT ["python", "run.py"] 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thunder Bouble 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 | ![python_vesion](https://img.shields.io/badge/Python-3.5%2B-green.svg) [![itchat_vesion](https://img.shields.io/badge/Itchat-1.3.10-brightgreen.svg)](https://github.com/littlecodersh/ItChat) [![codebeat badge](https://codebeat.co/badges/0953014f-dbd3-41f4-bacd-60018e7d5065)](https://codebeat.co/projects/github-com-sfyc23-everydaywechat-master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a278078ba9a14e22bd86740b0807a78e)](https://www.codacy.com/app/sfyc23/EverydayWechat?utm_source=github.com&utm_medium=referral&utm_content=sfyc23/EverydayWechat&utm_campaign=Badge_Grade) [![MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sfyc23/EverydayWechat/blob/master/LICENSE) [![weibo](https://img.shields.io/badge/weibo-@sfyc23-red.svg)](https://www.weibo.com/sfyc23) [![GitHub issues](https://img.shields.io/github/issues/sfyc23/EverydayWechat.svg)](https://github.com/sfyc23/EverydayWechat/issues) [![GitHub contributors](https://img.shields.io/github/contributors/sfyc23/EverydayWechat.svg)](https://github.com/sfyc23/EverydayWechat/graphs/contributors) [![微信群](http://vlog.sfyc.ltd/wechat_everyday/wxgroup_logo.png?imageView2/0/w/60/h/20)](#微信交流群) 2 | 3 | [EverydayWechat](https://github.com/sfyc23/EverydayWechat) 是基于 Python3 与 [Itchat](https://github.com/littlecodersh/ItChat) 的微信小工具。 4 | 可以定时给朋友或者群聊发送每日天气、提醒、每日一句,也可以智能自动回复好友信息。还有群助手功能,让你在好友群中装 X。 5 | 操作简单,小白用户也可快速上手。 6 | 7 | **本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。** 8 | **本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。** 9 | **本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。** 10 | 网页版微信地址:。 11 | 12 | 在北京地区求一份 Python & Android 的工作岗位。 13 | 加微信:[地址](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190614125724.png)。 14 | 15 | [版本更新日志](https://github.com/sfyc23/EverydayWechat/blob/master/hostory.md) 16 | 17 | 最近搞了一个类似,但功能不一样的项目:[微信加群助手](https://github.com/sfyc23/WechatAddGroupHelper)。 18 | 欢迎大家 star。 19 | 20 | **禁止将本工具用于商业用途**,如产生法律纠纷与本人无关。 21 | 22 | > 注意:如果给女朋友添加图灵机器人回复,请慎重考虑!!!! 23 | 并不是你的每一个女朋友都能接受,你用机器人给他回复『暖心话』,安慰她。人工智能也有可能是一个智障机器人。想想如果机器人回复给你女朋友:『我们分手吧』。可能你们真的就分手了。虽然我会在心里默默的点个赞(单身狗的自白) 24 | > 25 | 26 | [![GitHub stars](https://img.shields.io/github/stars/sfyc23/EverydayWechat.svg?style=social)](https://github.com/sfyc23/EverydayWechat/stargazers) [![GitHub forks](https://img.shields.io/github/forks/sfyc23/EverydayWechat.svg?style=social)](https://github.com/sfyc23/EverydayWechat/network/members) `请点击页面顶部靠右 star 与 fork` 27 | 28 | ## 功能说明 29 | 30 | - 支持对多个微信好友自动回复。 31 | - 定时给好友与群聊组发送提醒,内容包括(天气、格言、自定义的话)。 32 | - 群助手功能,可以群自动回复,查询最热门的垃圾分类、天气、日历、实时票房、快递信息、PM2.5等等功能。 33 | 34 | > 如果你没有好友可测试发送提醒,而且只有一个人也玩不了自动回复,怎么办呢(快哭了.jpg)。 35 | > 你可以把『文件传输助手』当成女朋友添加(你说的这个女朋友到底是不是你的双手.jpg)。这样一个号也可以进行测试了,发提醒给文件传输助手,跟文件传输助手智能聊天。 36 | 37 | ## 相关数据来源 38 | 39 | ### 天气信息: 40 | 41 | - SOJSON: 42 | - RollToolsApi:[获取特定城市今日天气](https://github.com/MZCretin/RollToolsApi#%E8%8E%B7%E5%8F%96%E7%89%B9%E5%AE%9A%E5%9F%8E%E5%B8%82%E4%BB%8A%E6%97%A5%E5%A4%A9%E6%B0%94) 43 | 44 | ### 每日一句: 45 | 46 | - ONE ● 一个: 47 | - 金山词霸 ● 每日一句(双语): 48 | - 一言 : 49 | - 土味情话: (土) 50 | - 句子迷-民国情书: (高雅,但最近不可用) 51 | - RollToolsApi: [随机获取笑话段子列表](https://github.com/MZCretin/RollToolsApi#%E9%9A%8F%E6%9C%BA%E8%8E%B7%E5%8F%96%E7%AC%91%E8%AF%9D%E6%AE%B5%E5%AD%90%E5%88%97%E8%A1%A8) 52 | - 彩虹屁: 53 | 54 | ### 人工智能机器人 55 | 56 | - 图灵机器人:(需求实名制认证,并每天免费数量只有 100 条) 57 | - 青云客智能聊天机器人:(无须申请,无数量限制,但有点智障,分手神器。分手神器,慎用) 58 | - 智能闲聊(腾讯): ( 申请使用,免费且无限量。大厂靠谱。) 59 | - 天行机器人 : (认证后有 7 万条免费使用。之后收费:1 万条/1 块钱) 60 | - 海知智能 : (功能很强大,不仅仅用于聊天。需申请 key,免费) 61 | - 思知对话机器人: (免费,可不申请 appid) 62 | - 一个AI:(免费且无数量限制。可自定义回复、对话、场景。但高级功能使用比较复杂。但已长时间没人维护) 63 | 64 | ### 星座运势 65 | - 星座屋 : (基于爬虫获取数据) 66 | 67 | ### 万年历 68 | - RollToolsApi :[指定日期的节假日及万年历信息](https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息) 69 | - SOJSON : 70 | 71 | ### 票房数据: 72 | - 猫眼实时票房: 73 | 74 | ### 垃圾分类查询: 75 | - atoolbox 垃圾分类查询: 76 | 77 | ### 空气质量PM2.5查询: 78 | - aqicn: 79 | 80 | 81 | ## 项目配置 82 | 目前项目所有的配置都是在 **[_config.yaml](https://github.com/sfyc23/EverydayWechat/blob/master/_config.yaml)** 文件中。 83 | 配置文件请严格遵循 yaml 语法格式,yaml 学习地址: 84 | 85 | 86 | 87 | ### 配置自动回复机器人。 88 | 89 | #### 1. 开启自动回复 90 | 91 | - 将 **is_auto_relay** 设置为:True。 92 | 93 | #### 2.选择渠道 94 | 95 | ``` 96 | 机器人渠道(1: 图灵机器人,2: 一个AI ,3 : 青云客,4 腾讯智能闲聊,5:天行机器人,6:海知智能,7:思知机器人) 97 | bot_channel: 7 98 | ``` 99 | 100 | > 默认为思知机器人,可不申请 key 的情况下,最智能的了。。 101 | 102 | #### 3. 指定自动回复的好友名单 103 | 104 | 有两种模式 105 | 106 | (1) 不使用自动回复所有好友的情况下,即:is_auto_reply_all:False 时。 107 | 这时设置可回复的白名单成员,如下: 108 | 109 | ``` 110 | is_auto_reply_all:False 111 | # 指定自动回复的好友名单。 112 | auto_reply_white_list: 113 | - '好友1' 114 | - '好友2' 115 | ``` 116 | (2) 开启自动回复所有好友的情况下,即:is_auto_reply_all:True 时。 117 | 选择不自动回复黑名单成员:如下 118 | 119 | ``` 120 | is_auto_reply_all:True 121 | auto_reply_black_list: 122 | - '好友1' 123 | - '好友2' 124 | ``` 125 | 126 | #### 4. 配置相关器人 127 | 128 | 除了青云客之外,其他的机器人都需要去对应的官网,注册并获取相应的 key。需要哪个就配置哪个。 129 | 130 | ##### I.图灵机器人 131 | 132 | - 打开图灵机器人官网:[http://www.turingapi.com](http://www.turingapi.com/) 进行注册。 133 | - 创建机器人,得到 apikey。将填入到 **_config.yaml** 文件中的: 134 | 135 | > 注意:不要打开『密钥』选项。 136 | 137 | ``` 138 | turing_conf: 139 | apiKey: '你所获取apikey' 140 | ``` 141 | > 图灵机器人必须认证后才能使用,免费版用户,每天可使用 100 条信息,且用且珍惜。 142 | 143 | ##### II.天行机器人 144 | 145 | - 打开天行数据注册页面:[https://www.tianapi.com/signup.html](https://www.tianapi.com/signup.html?source=sf4243841) 进行注册。 146 | - 在个人中心的第一行,即可得到 apikey。 147 | 148 | ``` 149 | txapi_conf: 150 | app_key: '个人中心中的key' 151 | reply_name: '宝宝' # 回复的人的名字(可空)(也可在个人中心->机器人管理 修改) 152 | bot_name: '老公' # 机器人的名字(可空) 153 | ``` 154 | 155 | ##### III.智能闲聊(腾讯) 156 | 157 | - 打开 https://ai.qq.com/product/nlpchat.shtml 并登录。 158 | - 点击免费使用 -> 接入能力 -> 创建应用 -> 创建成功后,会显示出 app_id ,app_key 。 159 | - 点击应用管理 -> 『你创建的项目名』-> 接入能力 -> 智能闲聊 -> 了解更多 -> 接入能力->『选择项目』-> 确认接口。 160 | 将 app_id,app_key 填入 yaml 中。 161 | 162 | ``` 163 | qqnlpchat_conf: 164 | app_id: '你申请的api_id' 165 | app_key: '你申请的app_key' 166 | ``` 167 | 168 | ##### IV.配置「一个AI」 169 | 打开图灵机器人官网:[http://www.yige.ai](http://www.yige.ai) 进行注册。 170 | 创建应用,得到「API密钥」中的 「客户端访问令牌」 171 | 将填入到 **_config.yaml** 文件中的: 172 | 173 | ``` 174 | yigeai_conf: 175 | client_token: '客户访问令牌' 176 | ``` 177 | 178 | ##### V.配置「思知机器人」 179 | 180 | 打开思知官网:[https://www.ownthink.com/](https://www.ownthink.com/) 进行注册。 181 | 创建机器人,得到 appid。 182 | 将填入到 **_config.yaml** 文件中的: 183 | ``` 184 | ownthink_conf: 185 | app_key: '你申请的api_id' 186 | ``` 187 | 188 | 189 | 关于自动回复,目前可以公开的情报: 190 | 1. 只能自动回复文字类消息; 191 | 2. 如果消息发送太频繁,微信会限制登录网页端登录。放心,并不会封号; 192 | 3. 好友里可以填入名称『文件传输助手』,这样你就可以在文件传输助手,发送消息,查看自动回复消息效果。 193 | 194 | ### 配置定时提醒 195 | 196 | #### 1.开启并设置提醒时间 197 | 198 | - 将 **is_alarm** 设置成 **True**。(当为 False 时,则关闭定时) 199 | 200 | ``` 201 | alarm_info: 202 | is_alarm: True 203 | ``` 204 | 205 | #### 2.填写需要发送的好友信息 206 | 207 | 填写好友信息,例如: 208 | ``` 209 | alarm_timed: 210 | - "9:00" 211 | - "12:30" 212 | - "22:00" 213 | wechat_name: 214 | - '文件传输助手' 215 | - '诗风' 216 | group_name: 217 | - 'EverydayWechat 交流群' 218 | is_tomorrow: False 219 | city_name: '桂林' 220 | dictum_channel : 3 221 | start_date: '2017-10-10' 222 | start_date_msg: '爱你的第{}天' 223 | calendar: True 224 | horescope: "处女座" 225 | sweet_words: '你脚下的蚂蚁' 226 | 227 | ``` 228 | 229 | 相关参数说明: 230 | 231 | | 名称 | 示例 | 必填 | 说明 | 232 | | -------- | -------------- | ---------- |---------- | 233 | | wechat_name | '老婆' | 选填 | 好友名:可填多人。好友微信昵称或者备注名(不能输入微信号)| 234 | | alarm_timed | '9:30' | 必填 | 定时时间,可填多个 | 235 | | alarm_jitter | 300 | 可空 | 定时时间的前后300秒内随机发送 | 236 | | group_name | '交流群' | 选填 | 群聊名称,可填多个。必须要把需要的群聊保存到通讯录。| 237 | | is_tomorrow | True | 可空 | 是否发送明日信息(如天气,星座,万年历)。| 238 | | city_name | '成都' | 可空 | 城市名:朋友所在城市,用于发送天气。 | 239 | | air_quality_city | '成都' | 可空 | 空气质量 PM25 的城市。 | 240 | | dictum_channel | 2 | 可空 | 格言渠道(见下表)| 241 | | start_date | '2017-10-10' | 可空 | 相识日期:计算到当天的天数 。 | 242 | | start_date_msg | '爱你的第{}天' | 可空 | 相识日期文案 | 243 | | sweet_words | '来自你俊美的老公' | 可空 | 甜密的后缀。(钢铁直男的直描)| 244 | | horescope | '处女座' | 可空 | 星座名或好友生日。用于发送星座运势 | 245 | | calendar | True | 可空 | 万年历信息 | 246 | 247 | **wechat_name**,**group_name** 至少要有一个。 248 | 249 | 格言渠道 : 1 : ONE●一个,2 : 词霸(每日双语),3: 土味情话, 4 : 一言,5:笑话,6: 民国情书,7: 彩虹屁。 250 | 251 | > Tips:可以把 **wechat_name** 填入『**文件传输助手**』,这样,提醒会发送到自己微信里的 **文件传输助手** 中。在不打扰别人的情况下,方便快速查看效果。 252 | 253 | 254 | - **alarm_time** 设置成需要提醒的时间。之后如果微信没有断线,即每天这个的时间会定时发送提醒。 255 | 256 | > 如果需要快速体验,可将 **alarm_timed** 当前系统时间之后的几分钟。例如当前时间为 11:35,并设置 5 分钟后发送提醒,即:alarm_timed:11:40 257 | 258 | 当然,你也可以根据自己的需求,设置另一套不同的方案。具体参考代码。 259 | 260 | 一例提醒: 261 | 262 | ``` 263 | 2019-06-29 星期六 农历五月廿七 264 | 【宜】嫁娶,祭祀,沐浴,扫舍,修饰垣墙 265 | 【忌】行丧,安葬 266 | 桂林天气预报 267 | 【今日天气】阵雨 268 | 【今日温度】低温 26.0℃,高温 33.0℃ 269 | 【今日风速】南风<3级 270 | 【出行提示】阵雨来袭,出门记得带伞 271 | 【桂林PM2.5】142 轻度污染 272 | 处女座今日运势 273 | 【幸运颜色】2 274 | 【幸运数字】薄荷绿 275 | 【综合运势】今天的你有机会重逢旧同学、旧朋友,对方会为你带来一些小惊喜,可能是某个不错的商机,也可能是某个消息。工作/学习上,今天的你目标性很强,能把当初奋斗的初心捡回来,重新出发。感情方面,有伴者今天要提防烂桃花的挑拨离间,多给对方一些信任。 276 | 你知道五氧化二磷被氧化前是什么样子嘛,什么样子?五二磷。 277 | 宝贝这是我们在一起的第628天 278 | 你脚下的蚂蚁 279 | ``` 280 | 281 | ### 配置群助手功能 282 | 283 | 直接放表格说明吧。 284 | 285 | | 名称 | 示例 | 必填 | 说明 | 286 | | -------- | -------------- | ---------- |---------- | 287 | | is_open | True | 必填 | 是否开启群助手功能 | 288 | | is_all | True | 必填 | 是否对所有群开启。当开启时,只有黑名单的名单才不受影响(慎重开启!) | 289 | | group_name_white_list | 「群名」 | 选填 | 白名单用户。当 is_all:Fase。只处理这个群里的消息| 290 | | group_name_black_list | 「群名」 | 选填 | 黑名单用户。当 is_all :True 。这个群里的用户不受影响。| 291 | | is_at | True | 必填 | 艾特标记。只有当别人艾特自己时,才会处理消息(慎重关闭!)。 | 292 | | is_auto_reply | True | 必填 | # 开启群自动回复(慎重开启!)| 293 | | is_weather | True| 必填 | 是否开启天气查询。 | 294 | | is_calendar | True | 必填 | 是否开启万历年查询 | 295 | | is_rubbish | True | 必填 | 是否开启垃圾查询 | 296 | | is_moviebox | True | 必填 | 是否开启电脑票房查询 | 297 | | is_express | True | 必填 | 是否开启快递信息查询 | 298 | | is_air_quality | True | 必填 | 是否开启空气质量查询 | 299 | 300 | ### 配置数据库(可不配置) 301 | 302 | 首先得安装 mongodb 数据库安装。安装方式,请自行谷歌。 303 | 官方的安装教程也有: 304 | 305 | (1)将 **is_open_db** 设置成 「True」。 306 | (2)设置 host 与 port。tips: 没有特殊要求,或者对数据库不熟悉者不需要设置。 307 | 308 | ## 安装 309 | 首先,把 Python3 安装好,并配置好环境,个人建议新手安装 Anaconda,具体安装教程,可自行谷歌搜索~ 310 | 311 | 312 | 直接下载此项目或 clone 项目到本地。 313 | 314 | 使用 pip 安装依赖: 315 | 316 | ``` 317 | pip3 install -r requirements.txt 318 | # 或者是使用 pip 319 | # pip install -r requirements.txt 320 | ``` 321 | 322 | ## 运行 323 | 324 | 在本地 cmd 中跳转项目目录下,运行: 325 | 326 | ``` 327 | python run.py 328 | ``` 329 | 330 | 第一次运行会跳出二维码,扫码登录。如输出日志中打印成:『登录成功』,则表示运行成功。 331 | 登录成功后一段时间内再运行,微信会保持登录状态,不需要再扫码。 332 | 如果需要切换用户,则在 *_config.yaml* 文件中,修改 *is_forced_switch* 的属性为 True。 333 | 334 | - docker 下运行 335 | - 构建 `docker build -t everyday_wechat:v1 .` 336 | - 运行 `docker run everyday_wechat:v1` 337 | 338 | ## 示例截图: 339 | 340 | ![日志](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190613171703.png) 341 | 342 | ![自动回复](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190613162524.png) 343 | 344 | ## 提 [issues](https://github.com/sfyc23/EverydayWechat/issues) & 加群提问的建议。 345 | 346 | - 当你拋出一个技术问题时,最终是否能得到有用的回答,往往取决于你所提问和追问的方式。推荐阅读:[提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)。 347 | - **检查是否是最新的代码,检查是否是 Python3.5+,检查依赖有没有安装完整**。 348 | - 先检查微信是否可登录 [微信网页版](https://wx.qq.com/),如网页端不能用,此项目也不能用。 349 | - 请更新你的 [itchat](https://github.com/littlecodersh/ItChat) 至最新版本 **1.3.10** 。查看 itchat 版本 **print(itchat.__version__ )**。 350 | - 与微信相关的问题可以先去 itchat [issues](https://github.com/littlecodersh/ItChat/issues), 查看是否有相似问题。 351 | - 微信名只能是昵称或者备注名,不能输入微信号。 352 | - 对群聊操作时,必须要把需要的群聊保存到通讯录。 353 | - 如果有新的思路和建议也欢迎提交。 354 | 355 | ## Credits 致谢 356 | 357 | 本项目受以下项目启发,参考了其中一部分思路,向这些开发者表示感谢。 358 | 359 | - [wechatBot](https://github.com/gengchen528/wechatBot) —— 微信每日说,每日自动发送微信消息(Node + Wechaty)。 360 | - [NodeMail](https://github.com/Vincedream/NodeMail) —— 用 Node 写一个爬虫脚本每天定时给女朋友发一封暖心邮件。 361 | - [wechat-assistant](https://github.com/gengchen528/wechat-assistant) —— koa+wechaty实现的微信个人秘书,把你闲置的微信号利用起来做个个人秘书。 362 | - [WechatRobot](https://github.com/scorego/WechatRobot) ——个人微信号自动回复、陪聊、查天气(Java) 363 | - 364 | - 365 | 366 | 367 | ## 微信交流群 368 | 因为人数已超 100 人,请加 wx: **sfyc1314** 机器人为好友,验证信息写填写:「github」!!!,机器人会自动通过。 369 | 通过后回复:「加群」,会自动拉你入群。 370 | 加群助手也已开源,地址:[https://github.com/sfyc23/WechatAddGroupHelper](https://github.com/sfyc23/WechatAddGroupHelper),欢迎大家 star。 371 | 机器人二维码: 372 | 373 | ![微信交流群](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190614125724.png) 374 | 375 | 376 | ## 捐助 377 | 如果您认为这个项目有帮助,不妨为它捐助一点钱? 378 | 379 | 不管钱有多少,您的捐助将会激励作者持续开发新功能!🎉 380 | 381 | 感谢您的支持! 382 | 383 | 捐助方法如下: 384 | 385 | ![](http://vlog.sfyc.ltd/wechat_everyday/donation_wechat.png?imageView2/0/w/300/h/300)![](http://vlog.sfyc.ltd/wechat_everyday/donation_alipay.png?imageView2/0/w/300/h/300) 386 | 387 | ## LICENSE 388 | [MIT License](https://github.com/sfyc23/EverydayWechat/blob/master/LICENSE) -------------------------------------------------------------------------------- /everyday_wechat/__init__.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Date: 2019/6/23 4 | # Author: snow 5 | 6 | script_name = 'EverydayWechat' 7 | __author__ = 'sfyc23' 8 | __license__ = 'MIT' 9 | __version__ = '0.3.27' 10 | 11 | -------------------------------------------------------------------------------- /everyday_wechat/_config.yaml: -------------------------------------------------------------------------------- 1 | # 配置文件请严格遵循 yaml 语法格式,yaml 学习地址: 2 | # https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html 3 | # http://einverne.github.io/post/2015/08/yaml.html 4 | 5 | # 是否强制切换微信号 (2019年9月27日15:31:22 最近保存最近登录状态出错,所以此设置无效,每次登录得重新扫码。) 6 | is_forced_switch: False 7 | 8 | #---------------------------------------自动回复功能设置--------------------------------------start 9 | auto_reply_info: 10 | # 是否开启自动回复 11 | is_auto_reply: True 12 | 13 | # 是否自动回复所有好友(慎重启动!),开启后,仅仅有黑名单的成员才不会自动回复 14 | is_auto_reply_all: False 15 | 16 | # 自动回复消息前缀(不需要则设置为空) 17 | auto_reply_prefix: '' 18 | # 自动回复消息后缀(不需要则设置为空) 19 | auto_reply_suffix: '--自动回复' 20 | 21 | # 白名单,is_auto_reply_all: False 生效。此名单的用户才可自动回复。(填:文件传输助手,可回复自己,测试效果) 22 | auto_reply_white_list: 23 | - '诗风' 24 | - '文件传输助手' 25 | 26 | # 黑名单,is_auto_reply_all:True 生效。此名单不会自动回复。 27 | auto_reply_black_list: 28 | - '贴心小秘书' 29 | 30 | # 机器人渠道(1: 图灵机器人,2: 一个AI ,3 : 青云客,4 腾讯智能闲聊,5:天行机器人,6:海知智能,7:思知机器人) 31 | bot_channel: 7 32 | 33 | #图灵机器人(http://www.tuling123.com/) 实名后的用户每天免费可用 100 条。 34 | turing_conf: 35 | apiKey: '你申请的apikey' 36 | 37 | # 天行机器人 ( https://www.tianapi.com/apiview/47 )。做完任务大概能免费用7万条,收费:1万条/1块钱 38 | txapi_conf: 39 | app_key: '个人中心中的key' 40 | reply_name: '宝宝' # 回复的人的名字(可空)(也可在个人中心->机器人管理 修改) 41 | bot_name: '老公' # 机器人的名字(可空) 42 | 43 | # 智能闲聊(腾讯)https://ai.qq.com/product/nlpchat.shtml。免费且无限量 44 | qqnlpchat_conf: 45 | app_id: '你申请的api_id' 46 | app_key: '你申请的app_key' 47 | 48 | # 海知智能 功能很强大,不仅仅用于聊天。需申请 key,免费 49 | ruyi_conf: 50 | app_key: '你申请的key' 51 | 52 | # 思知机器人 免费,如果只是简单使用 app_key 可不申请。 53 | ownthink_conf: 54 | app_key: '' 55 | 56 | # 一个 Al (http://www.yige.ai/)(已长时间无人维护) 57 | yigeai_conf: 58 | client_token: '你申请的token' 59 | 60 | 61 | #---------------------------------------自动回复功能设置--------------------------------------end 62 | 63 | 64 | 65 | #---------------------------------------定时提醒功能设置--------------------------------------start 66 | alarm_info: 67 | #True 开启定时提醒,False 关闭 68 | is_alarm: True 69 | 70 | girlfriend_infos: 71 | #女友微信昵称或者备注名,不能输入微信号。(如填:文件传输助手,发消息到文件传输助手,测试效果) 72 | - wechat_name: 73 | - '文件传输助手' 74 | - '诗风' 75 | # 注意:必须要把需要的群聊保存到通讯录 76 | group_name: # 群聊的名称 77 | - '萌萌哒' 78 | - '蕉群' 79 | alarm_timed: # 定时发送的时间 80 | - "13:25" 81 | - "00:33" 82 | alarm_jitter: 300 # 给定时时间加一个随机抖动 300 秒。定时时间【-5,+5】分钟范围内发送。(不然每天固定在同个时间段有点尴尬)(可空) 83 | is_tomorrow: True # 是否发送明日信息(如天气,星座,万年历) 84 | #女友所在城市,用于发送天气。(可空) 85 | city_name: '桂林' 86 | # 此城市的 pm2.5 值。 87 | air_quality_city: '桂林' 88 | # 格言渠道(1 : ONE●一个,2 : 词霸(每日英语,双语)3: 土味情话 4 : 一言,5:笑话,6 民国情书,7彩虹屁)(可空) 89 | dictum_channel: 1 90 | # 从哪天开始勾搭的(可空),配合 start_date_msg 使用。 91 | start_date: '2017-10-10' 92 | # 自定义方案(可空), {}表示用于占位,代表天数,与 start_date 一起使用。单填无意义 93 | # 默认为:『宝贝这是我们在一起的第{}天』,参考:爱你的第{}天 94 | start_date_msg: '宝贝这是我们在一起的第{}天' 95 | # 万历年(可空),(中老年最爱) 96 | calendar: True 97 | # 星座运势(可空)填生日日期:"1980-06-15" or "06-15" or "白羊座" 98 | horescope: "处女座" 99 | # 落款(可空),落款参考:['厌物', '你脚下的蚂蚁', '专说骗人的诳话者', '黄天霸', 'cxk', '魔鬼的叔父', '哺乳类脊椎动物之一', '名字写在水上的人', 'BIG BAD WOLF', '你的兄弟'] 100 | sweet_words: '你脚下的蚂蚁' 101 | 102 | 103 | # 如果你需要另一套方案,如下面复制即可 104 | # 如不需要,则删除或注解下面所有的数据 105 | - group_name: 'EverydayWechat 交流1群' 106 | wechat_name: '贴心小秘书' 107 | city_name: '漳州' 108 | start_date: '2011-11-11' 109 | start_date_msg: '分手后的第{}天' 110 | dictum_channel: 4 111 | sweet_words: '名字写在水上的人' 112 | alarm_timed: "23:02" 113 | is_tomorrow: True 114 | #---------------------------------------定时提醒功能设置--------------------------------------end 115 | 116 | 117 | 118 | ##---------------------------群聊助手设置--------------------------start 119 | group_helper_conf: 120 | is_open: True # 开启群助手 121 | is_all: False # 是否对所有群开启。当开启时,只有黑名单的名单才不受影响(慎重开启!) 122 | 123 | # 白名单用户。当 is_all:Fase。只处理这个群里的消息 124 | group_name_white_list: 125 | - '蕉群' 126 | - '群机器人测试群' 127 | - '小号测试群' 128 | - 'EverydayWechat 交流1群' 129 | - 'EverydayWechat 交流2群' 130 | 131 | # 黑名单用户。当 is_all :True 。这个群里的用户不受影响。 132 | group_name_black_list: 133 | - 'EverydayWechat 交流1群' 134 | - 'EverydayWechat 交流2群' 135 | 136 | is_at: True # 艾特标记。只有当别人艾特机器人,才会处理消息(慎重关闭!) 137 | is_auto_reply: True # 开启群自动回复(慎重开启!) 138 | is_weather: True # 是否开启天气查询 139 | is_calendar: True # 是否开启万历年查询 140 | is_rubbish: True # 是否开启垃圾查询 141 | is_moviebox: True # 是否开启电影票房 142 | is_air_quality: True # 是否开启快递查询。 143 | is_express: True # 是否开启快递查询 144 | express_info: # 快递鸟(http://www.kdniao.com/) 145 | app_id: '你申请的api_id' 146 | app_key: '你申请的app_key' 147 | 148 | 149 | #--------------------------- 群聊助手设置 --------------------------end 150 | 151 | 152 | # start ----------------------------------- 数据库设置 ----------------------------------- start 153 | # 可不安装与设置数据库内容,数据库主要用于群助手功能中,查询数据的缓存。 154 | db_config: # 请安装 mongodb 数据库 155 | is_open_db: True # 是否开启数据库功能 156 | mongodb_conf: 157 | 'host': 'localhost' 158 | 'port': 27017 159 | # end ----------------------------------- 数据库设置 ----------------------------------- end -------------------------------------------------------------------------------- /everyday_wechat/control/__init__.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Date: 2019/6/23 4 | # Author: snow 5 | -------------------------------------------------------------------------------- /everyday_wechat/control/airquality/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-09-30 17:56 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /everyday_wechat/control/airquality/air_quality_aqicn.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-09-30 17:58 6 | Introduction: 获取空气质量 7 | 官网:http://aqicn.org/here/ 8 | 9 | """ 10 | 11 | import requests 12 | 13 | # token,申请地址:http://aqicn.org/data-platform/token/#/ 14 | AQICN_TOKEN = '6382db85ef321ae81f316486de0b5b8aa6c84f62' 15 | 16 | AIR_STATUS_DICT = { 17 | 50: '优', 18 | 100: '良', 19 | 150: '轻度污染', 20 | 200: '中度污染', 21 | 300: '重度污染', 22 | 3000: '严重污染' 23 | } 24 | 25 | 26 | def get_air_quality(city): 27 | """ 28 | 通过城市名获取空气质量 29 | 官网:http://aqicn.org/here/ 30 | token 申请地址:http://aqicn.org/data-platform/token/#/ 31 | :param city: 城市 32 | :return: 33 | """ 34 | 35 | if not city or not city.strip(): 36 | return 37 | print('获取 {} 的空气质量...'.format(city)) 38 | try: 39 | 40 | url = 'http://api.waqi.info/feed/{city}/?token={token}'.format(city=city, token=AQICN_TOKEN) 41 | resp = requests.get(url) 42 | if resp.status_code == 200: 43 | # print(resp.text) 44 | content_dict = resp.json() 45 | if content_dict.get('status') == 'ok': 46 | data_dict = content_dict['data'] 47 | aqi = data_dict['aqi'] 48 | air_status = '严重污染' 49 | for key in sorted(AIR_STATUS_DICT): 50 | if key >= aqi: 51 | air_status = AIR_STATUS_DICT[key] 52 | break 53 | aqi_info = '{city} PM2.5:{aqi} {air_status}'.format(city=city, aqi=aqi, air_status=air_status) 54 | # print(aqi_info) 55 | return aqi_info 56 | else: 57 | print('获取空气质量失败:{}'.format(content_dict['data'])) 58 | return None 59 | print('获取空气质量失败。') 60 | except Exception as exception: 61 | print(str(exception)) 62 | return None 63 | 64 | 65 | if __name__ == '__main__': 66 | city = '长沙' 67 | dd = get_air_quality(city) 68 | print(dd) 69 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/everyday_wechat/control/bot/__init__.py -------------------------------------------------------------------------------- /everyday_wechat/control/bot/ownthink_robot.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-08-27 11:37 6 | Introduction: 思知机器人,接口地址: userid 可为空 7 | """ 8 | import re 9 | import requests 10 | from everyday_wechat.utils import config 11 | from everyday_wechat.utils.common import ( 12 | md5_encode 13 | ) 14 | 15 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 16 | BOT_INDEX = 7 17 | BOT_NAME = '思知机器人' 18 | 19 | 20 | def get_ownthink_robot(text, userid): 21 | """ 22 | 思知机器人,接口地址: 23 | https://api.ownthink.com/bot?appid=xiaosi&userid=user&spoken=姚明多高啊? 24 | :param text: 发出的消息 25 | :param userid: 收到的内容 26 | :return: 27 | """ 28 | try: 29 | # config.init() 30 | info = config.get('auto_reply_info')['txapi_conf'] 31 | app_key = info.get('app_key', '') 32 | if not re.findall(r'^[0-9a-z]{20,}$', app_key): # 验证 app_key 是否有效 33 | app_key = '' 34 | 35 | params = { 36 | 'appid': app_key, 37 | 'userid': md5_encode(userid), 38 | 'spoken': text 39 | } 40 | url = 'https://api.ownthink.com/bot' 41 | resp = requests.get(url, params=params) 42 | if resp.status_code == 200: 43 | # print(resp.text) 44 | content_dict = resp.json() 45 | if content_dict['message'] == 'success': 46 | data = content_dict['data'] 47 | if data['type'] == 5000: 48 | reply_text = data['info']['text'] 49 | return reply_text 50 | else: 51 | print('返回的数据不是文本数据!') 52 | else: 53 | print('思知机器人获取数据失败:{}'.format(content_dict['msg'])) 54 | 55 | print('获取数据失败') 56 | return None 57 | except Exception as exception: 58 | print(str(exception)) 59 | 60 | 61 | get_auto_reply = get_ownthink_robot 62 | 63 | if __name__ == '__main__': 64 | text = '大胸' 65 | userid = '250' 66 | from_text = get_ownthink_robot(text, userid) 67 | print(from_text) 68 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/qingyunke.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | """ 4 | http://api.qingyunke.com/ 5 | 青云客智能聊天机器人API 6 | 可直接使用 7 | """ 8 | import requests 9 | 10 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 11 | BOT_INDEX = 3 12 | BOT_NAME = '青云客机器人' 13 | 14 | URL = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg={}' 15 | 16 | 17 | def get_qingyunke(text, userid=''): 18 | """ 19 | 青云客智能聊天机器人API http://api.qingyunke.com/ 20 | :param text: str 聊天 21 | :param userid: str 无用 22 | :return: str 23 | """ 24 | try: 25 | # print('发出消息:{}'.format(text)) 26 | resp = requests.get(URL.format(text)) 27 | if resp.status_code == 200: 28 | # print(resp.text) 29 | re_data = resp.json() 30 | if re_data['result'] == 0: 31 | return_text = re_data['content'] 32 | return return_text 33 | 34 | error_text = re_data['content'] 35 | print('青云客机器人错误信息:{}'.format(error_text)) 36 | 37 | print('青云客机器人获取失败') 38 | except Exception as exception: 39 | print(str(exception)) 40 | print('青云客机器人获取失败') 41 | 42 | 43 | get_auto_reply = get_qingyunke 44 | 45 | if __name__ == '__main__': 46 | text = '微博加个关注呗' 47 | userid = '250' 48 | rt = get_qingyunke(text, userid) 49 | print('回复:', rt) 50 | pass 51 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/qq_nlpchat.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: HelloWorldPython 4 | Creator: DoubleThunder 5 | Create time: 2019-07-01 23:49 6 | Introduction: 智能闲聊(腾讯) 7 | 官网:https://ai.qq.com/product/nlpchat.shtml 8 | 免费试用,得申请 app_id,app_key。 9 | """ 10 | 11 | import hashlib 12 | from urllib import parse 13 | import time 14 | import random 15 | import string 16 | import requests 17 | from everyday_wechat.utils.common import ( 18 | md5_encode 19 | ) 20 | from everyday_wechat.utils import config 21 | 22 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 23 | BOT_INDEX = 4 24 | BOT_NAME = '腾讯智能闲聊' 25 | 26 | URL = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat' 27 | 28 | 29 | def get_nlp_textchat(text, userId): 30 | """ 31 | 智能闲聊(腾讯) 32 | 接口文档: 33 | :param text: 请求的话 34 | :param userId: 用户标识 35 | :return: str 36 | """ 37 | try: 38 | 39 | # config.init() 40 | info = config.get('auto_reply_info')['qqnlpchat_conf'] 41 | app_id = info['app_id'] 42 | app_key = info['app_key'] 43 | if not app_id or not app_key: 44 | print('app_id 或 app_key 为空,请求失败') 45 | return 46 | 47 | # 产生随机字符串 48 | nonce_str = ''.join(random.sample( 49 | string.ascii_letters + string.digits, random.randint(10, 16))) 50 | time_stamp = int(time.time()) # 时间戳 51 | params = { 52 | 'app_id': app_id, # 应用标识 53 | 'time_stamp': time_stamp, # 请求时间戳(秒级) 54 | 'nonce_str': nonce_str, # 随机字符串 55 | 'session': md5_encode(userId), # 会话标识 56 | 'question': text # 用户输入的聊天内容 57 | } 58 | # 签名信息 59 | params['sign'] = getReqSign(params, app_key) 60 | resp = requests.get(URL, params=params) 61 | if resp.status_code == 200: 62 | # print(resp.text) 63 | content_dict = resp.json() 64 | if content_dict['ret'] == 0: 65 | data_dict = content_dict['data'] 66 | return data_dict['answer'] 67 | 68 | print('智能闲聊 获取数据失败:{}'.format(content_dict['msg'])) 69 | return None 70 | except Exception as exception: 71 | print(str(exception)) 72 | 73 | 74 | def getReqSign(parser, app_key): 75 | ''' 76 | 获取请求签名,接口鉴权 https://ai.qq.com/doc/auth.shtml 77 | 1.将 请求参数对按 key 进行字典升序排序,得到有序的参数对列表 N 78 | 2.将列表 N 中的参数对按 URL 键值对的格式拼接成字符串,得到字符串 T(如:key1=value1&key2=value2), 79 | URL 键值拼接过程 value 部分需要 URL 编码,URL 编码算法用大写字母,例如 %E8,而不是小写 %e8 80 | 3.将应用密钥以 app_key 为键名,组成 URL 键值拼接到字符串 T 末尾,得到字符串 S(如:key1=value1&key2=value2&app_key = 密钥) 81 | 4.对字符串 S 进行 MD5 运算,将得到的 MD5 值所有字符转换成大写,得到接口请求签名 82 | :param parser: dect 83 | :param app_key: str 84 | :return: str,签名 85 | ''' 86 | params = sorted(parser.items()) 87 | uri_str = parse.urlencode(params, encoding="UTF-8") 88 | sign_str = '{}&app_key={}'.format(uri_str, app_key) 89 | # print('sign =', sign_str.strip()) 90 | hash_md5 = hashlib.md5(sign_str.encode("UTF-8")) 91 | return hash_md5.hexdigest().upper() 92 | 93 | 94 | get_auto_reply = get_nlp_textchat 95 | 96 | if __name__ == '__main__': 97 | to_text = '你会爱我吗' 98 | userId = 'userId' 99 | # userId = 250 100 | form_text = get_nlp_textchat(to_text, userId) 101 | print(form_text) 102 | # print() -------------------------------------------------------------------------------- /everyday_wechat/control/bot/ruyiai.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: HelloWorldPython 4 | Creator: DoubleThunder 5 | Create time: 2019-07-02 02:46 6 | Introduction: 海知智能 功能很强大,不仅仅用于聊天。需申请 key,免费 7 | """ 8 | import requests 9 | from everyday_wechat.utils import config 10 | from everyday_wechat.utils.common import ( 11 | md5_encode 12 | ) 13 | 14 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 15 | BOT_INDEX = 6 16 | BOT_NAME = '海知智能机器人' 17 | 18 | URL = 'http://api.ruyi.ai/v1/message' 19 | 20 | 21 | def get_ruyiai_bot(text, userId): 22 | """ 23 | 海知智能 文档说明: 24 | :param text: str 需要发送的话 25 | :param userId: str 用户标识 26 | :return: str 机器人回复 27 | """ 28 | try: 29 | # config.init() 30 | info = config.get('auto_reply_info')['ruyi_conf'] 31 | app_key = info['app_key'] 32 | if not app_key: 33 | print('海知智能 api_key 为空,请求失败') 34 | return 35 | 36 | params = {'q': text, 'user_id': md5_encode(userId), 'app_key': app_key} 37 | headers = {'Content-Type': 'application/json'} 38 | resp = requests.get(URL, headers=headers, params=params) 39 | if resp.status_code == 200: 40 | # print(resp.text) 41 | content_dict = resp.json() 42 | if content_dict['code'] in (0, 200): 43 | outputs = content_dict['result']['intents'][0]['outputs'] 44 | reply_text = outputs[0]['property']['text'] 45 | # print(reply_text) 46 | return reply_text 47 | else: 48 | print('海知智能 获取数据失败:{}'.format(content_dict['msg'])) 49 | return 50 | print('海知智能 获取数据失败') 51 | return None 52 | except Exception as exception: 53 | print(str(exception)) 54 | 55 | 56 | get_auto_reply = get_ruyiai_bot 57 | 58 | if __name__ == '__main__': 59 | # text = '我要飞的更高' 60 | # userid = '250' 61 | # from_text = get_auto_reply(text, userid) 62 | # print(from_text) 63 | pass 64 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/tian_robot.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-02 01:24 6 | Introduction: 天行机器人 申请地址( https://www.tianapi.com/apiview/47 ) 7 | """ 8 | import requests 9 | from everyday_wechat.utils import config 10 | from everyday_wechat.utils.common import ( 11 | md5_encode 12 | ) 13 | 14 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 15 | BOT_INDEX = 5 16 | BOT_NAME = '天行机器人' 17 | 18 | 19 | def get_tianapi_robot(text, userid): 20 | """ 21 | 从天行机器人获取自动回复,接口地址: 22 | :param text: 发出的消息 23 | :param userid: 收到的内容 24 | :return: 25 | """ 26 | try: 27 | # config.init() 28 | info = config.get('auto_reply_info')['txapi_conf'] 29 | app_key = info['app_key'] 30 | if not app_key: 31 | print('天行机器人 app_key 为空,请求失败') 32 | return 33 | reply_name = info.get('reply_name', '') 34 | bot_name = info.get('bot_name', '') 35 | 36 | params = { 37 | 'key': app_key, 38 | 'question': text, 39 | 'userid': md5_encode(userid), 40 | 'limit': 10, # 机器人分析系数,取值1-10 41 | 'mode': 1, # 图文返回数量,取值1-10 42 | 'datatype': '0', # 返回类型,文本0[默认]、语音1 43 | } 44 | url = 'https://api.tianapi.com/txapi/robot/' 45 | resp = requests.get(url, params=params) 46 | if resp.status_code == 200: 47 | # print(resp.text) 48 | content_dict = resp.json() 49 | if content_dict['code'] == 200: 50 | if content_dict['datatype'] == 'text': 51 | data_dict = content_dict['newslist'] 52 | reply_text = data_dict[0]['reply'] 53 | reply_text.replace('{robotname}', bot_name) \ 54 | .replace('{appellation}', reply_name) 55 | return reply_text 56 | else: 57 | return '我不太懂你在说什么' 58 | else: 59 | print('天行机器人获取数据失败:{}'.format(content_dict['msg'])) 60 | 61 | print('获取数据失败') 62 | return None 63 | except Exception as exception: 64 | print(str(exception)) 65 | 66 | 67 | get_auto_reply = get_tianapi_robot 68 | 69 | if __name__ == '__main__': 70 | text = '我是你的谁' 71 | userid = '250' 72 | from_text = get_tianapi_robot(text, userid) 73 | print(from_text) 74 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/tuling123.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | ''' 4 | 图灵机器人自动回复 5 | 官网:http://www.tuling123.com/ 6 | apiKey,userid 需要去官网申请。 7 | ''' 8 | 9 | import requests 10 | from everyday_wechat.utils.common import ( 11 | is_json, 12 | md5_encode 13 | ) 14 | from everyday_wechat.utils import config 15 | 16 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 17 | BOT_INDEX = 1 18 | BOT_NAME = '图灵机器人' 19 | 20 | # 图灵机器人错误码集合 21 | TULING_ERROR_CODE_LIST = ( 22 | 5000, 6000, 4000, 4001, 4002, 23 | 4003, 4005, 4007, 4100, 4200, 24 | 4300, 4400, 4500, 4600, 4602, 25 | 7002, 8008, 0) 26 | URL = "http://openapi.tuling123.com/openapi/api/v2" 27 | 28 | 29 | def get_tuling123(text, userId): 30 | """ 31 | 接口地址:(https://www.kancloud.cn/turing/www-tuling123-com/718227) 32 | 获取图灵机器人对话 33 | :param text: 发送的话 34 | :param userId: 用户唯一标识(最好用微信好友uuid) 35 | :return: 对白 36 | """ 37 | try: 38 | # config.init() 39 | info = config.get('auto_reply_info')['turing_conf'] 40 | apiKey = info['apiKey'] 41 | 42 | if not apiKey: 43 | print('图灵机器人 apikey 为空,请求出错') 44 | return None 45 | userId = md5_encode(userId if userId else '250') 46 | 47 | content = { 48 | 'perception': { 49 | 'inputText': { 50 | 'text': text 51 | } 52 | }, 53 | 'userInfo': { 54 | 'apiKey': apiKey, 55 | 'userId': userId 56 | } 57 | } 58 | # print('发出消息:{}'.format(text)) 59 | resp = requests.post(URL, json=content) 60 | if resp.status_code == 200 and is_json(resp): 61 | # print(resp.text) 62 | re_data = resp.json() 63 | if re_data['intent']['code'] not in TULING_ERROR_CODE_LIST: 64 | return_text = re_data['results'][0]['values']['text'] 65 | return return_text 66 | 67 | error_text = re_data['results'][0]['values']['text'] 68 | print('图灵机器人错误信息:{}'.format(error_text)) 69 | return None 70 | 71 | print('图灵机器人获取数据失败') 72 | except Exception as exception: 73 | print(str(exception)) 74 | print('图灵机器人获取数据失败') 75 | 76 | 77 | get_auto_reply = get_tuling123 78 | 79 | if __name__ == '__main__': 80 | # text = '雷军 are you ok?' 81 | # reply = get_auto_reply(text, 'WE') 82 | # print(reply) 83 | pass 84 | -------------------------------------------------------------------------------- /everyday_wechat/control/bot/yigeai.py: -------------------------------------------------------------------------------- 1 | # 2 | """ 3 | 『一个AI』自动回复 (http://www.yige.ai/) 4 | """ 5 | import requests 6 | 7 | from everyday_wechat.utils.common import ( 8 | is_json, 9 | md5_encode, 10 | ) 11 | 12 | from everyday_wechat.utils import config 13 | 14 | __all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME'] 15 | BOT_INDEX = 2 16 | BOT_NAME = '一个 AI 机器人' 17 | 18 | # 一个AI错误集合 19 | TULING_ERROR_CODE_LIST = ('501', '502', '503', '504', '507', '510') 20 | 21 | 22 | def get_yigeai(text, userid): 23 | """ 24 | 『一个AI』自动回复 (http://www.yige.ai/) 25 | 接口说明:http://docs.yige.ai/Query%E6%8E%A5%E5%8F%A3.html 26 | :param text:str, 需要发送的话 27 | :userid:str,机器唯一标识 28 | :return:str 29 | """ 30 | try: 31 | # config.init() 32 | info = config.get('auto_reply_info')['yigeai_conf'] 33 | token = info['client_token'] 34 | if not token: 35 | print('一个「AI」token 为空,请求出错') 36 | return None 37 | session_id = md5_encode(userid if userid else '250') 38 | 39 | # print('发出的消息:{}'.format(text)) 40 | data = {'token': token, 'query': text, 'session_id': session_id} 41 | resp = requests.post('http://www.yige.ai/v1/query', data=data) 42 | if resp.status_code == 200 and is_json(resp): 43 | # print(resp.text) 44 | re_data = resp.json() 45 | code = re_data['status']['code'] 46 | # 错误码返回有时是数字,有点是str。一起做处理 47 | if code and str(code) not in TULING_ERROR_CODE_LIST: 48 | return_text = re_data['answer'] 49 | return return_text 50 | error_text = re_data['status']['error_type'] 51 | print('『一个AI』机器人错误信息:{}'.format(error_text)) 52 | return None 53 | print('『一个AI』机器人获取数据失败') 54 | except Exception as e: 55 | print(e) 56 | print('『一个AI』机器人获取数据失败') 57 | 58 | 59 | get_auto_reply = get_yigeai 60 | 61 | if __name__ == '__main__': 62 | # text = '我爱北京' 63 | # rt = get_auto_reply(text, 'dd--00') 64 | # print('回复:', rt) 65 | pass 66 | -------------------------------------------------------------------------------- /everyday_wechat/control/calendar/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/everyday_wechat/control/calendar/__init__.py -------------------------------------------------------------------------------- /everyday_wechat/control/calendar/rt_calendar.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息 4 | 指定日期的节假日及万年历信息 5 | 6 | {"code":1,"msg":"数据返回成功","data":{ 7 | "date":"2019-06-27","weekDay":4,"yearTips":"己亥", 8 | "type":0,"typeDes":"工作日","chineseZodiac":"猪","solarTerms":"夏至后", 9 | "avoid":"移徙.入宅.安葬","lunarCalendar":"五月廿五", 10 | "suit":"订盟.纳采.出行.祈福.斋醮.安床.会亲友", 11 | "dayOfYear":178,"weekOfYear":26,"constellation":"巨蟹座"}} 12 | """ 13 | 14 | from datetime import datetime 15 | import requests 16 | 17 | __all__ = ['STFT', 'WEEK_DICT', 'get_rtcalendar'] 18 | 19 | # Twenty-four solar terms list 二十四节气名称 20 | STFT = ( 21 | "冬至", "小寒", "大寒", "立春", "雨水", "惊蛰", 22 | "春分", "清明", "谷雨", "立夏", "小满", "芒种", 23 | "夏至", "小暑", "大暑", "立秋", "处暑", "白露", 24 | "秋分", "寒露", "霜降", "立冬", "小雪", "大雪") 25 | 26 | WEEK_DICT = {1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', 7: '星期日'} 27 | 28 | 29 | def get_rtcalendar(date=''): 30 | """ 31 | 获取指定日期的节假日及万年历信息 32 | https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息 33 | :param data: str 日期 格式 yyyyMMdd 34 | :rtype str 35 | """ 36 | 37 | date_ = date or datetime.now().strftime('%Y%m%d') 38 | 39 | print('获取 {} 的日历...'.format(date_)) 40 | try: 41 | resp = requests.get('https://www.mxnzp.com/api/holiday/single/{}'.format(date_)) 42 | if resp.status_code == 200: 43 | # print(resp.text) 44 | content_dict = resp.json() 45 | if content_dict['code'] == 1: 46 | data_dict = content_dict['data'] 47 | solar_terms = data_dict.get('solarTerms', '') 48 | if solar_terms not in STFT: 49 | solar_terms = '' 50 | 51 | suit = data_dict['suit'] 52 | suit = suit if suit else '无' 53 | avoid = data_dict['avoid'] 54 | avoid = avoid if avoid else '无' 55 | return_text = '{data} {week} 农历{lunarCalendar} {solarTerms}\n【宜】{suit}\n【忌】{avoid}'.format( 56 | data=data_dict['date'], 57 | week=WEEK_DICT[data_dict['weekDay']], 58 | lunarCalendar=data_dict['lunarCalendar'], 59 | solarTerms=solar_terms, 60 | suit=suit, 61 | avoid=avoid, 62 | ) 63 | return return_text 64 | else: 65 | print('获取日历失败:{}'.format(content_dict['msg'])) 66 | return None 67 | 68 | print('获取日历失败。') 69 | except Exception as exception: 70 | print(str(exception)) 71 | return None 72 | 73 | 74 | get_calendar = get_rtcalendar 75 | 76 | if __name__ == '__main__': 77 | # date = (datetime.now() + timedelta(days=1)).strftime('%Y%m%d') 78 | date = '201889' 79 | content = get_calendar(date) 80 | print(content) 81 | pass 82 | -------------------------------------------------------------------------------- /everyday_wechat/control/calendar/sojson_calendar.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | https://www.sojson.com/api/lunar.html 4 | 指定日期的节假日及万年历信息 5 | """ 6 | from datetime import datetime 7 | import requests 8 | from everyday_wechat.utils.common import ( 9 | WEEK_DICT, 10 | SPIDER_HEADERS 11 | ) 12 | 13 | __all__ = ['get_sojson_calendar'] 14 | 15 | 16 | def get_sojson_calendar(date=''): 17 | """ 18 | 获取指定日期的节假日及万年历信息 19 | https://www.sojson.com/api/lunar.html 20 | :param data: str 日期 格式 %Y-%m-%d 21 | :rtype str 22 | """ 23 | date_ = date or datetime.now().strftime('%Y-%m-%d') 24 | # print('获取 {} 的日历...'.format(date_)) 25 | try: 26 | resp = requests.get('https://www.sojson.com/open/api/lunar/json.shtml?date={}'.format(date_), 27 | headers=SPIDER_HEADERS) 28 | if resp.status_code == 200: 29 | """ 30 | {"code":1,"msg":"数据返回成功","data":{ 31 | "date":"2019-06-27","weekDay":4,"yearTips":"己亥", 32 | "type":0,"typeDes":"工作日","chineseZodiac":"猪","solarTerms":"夏至后", 33 | "avoid":"移徙.入宅.安葬","lunarCalendar":"五月廿五", 34 | "suit":"订盟.纳采.出行.祈福.斋醮.安床.会亲友", 35 | "dayOfYear":178,"weekOfYear":26,"constellation":"巨蟹座"}} 36 | """ 37 | # print(resp.text) 38 | content_dict = resp.json() 39 | if content_dict['status'] == 200: 40 | data_dict = content_dict['data'] 41 | # 农历 42 | lunar_calendar = '{}月{}'.format(data_dict['cnmonth'], data_dict['cnday']) 43 | # 二十四节气 44 | # solarTerms = data_dict['jieqi'].get(str(data_dict['day']), '') 45 | # print(data_dict['jieqi']) 46 | suit = data_dict['suit'] 47 | suit = suit if suit else '无' 48 | taboo = data_dict['taboo'] 49 | taboo = taboo if taboo else '无' 50 | return_text = '{date} {week} 农历{lunarCalendar}\n【宜】{suit}\n【忌】{taboo}'.format( 51 | date=date, 52 | week=WEEK_DICT[data_dict['week']], 53 | lunarCalendar=lunar_calendar, 54 | suit=suit, 55 | taboo=taboo, 56 | ) 57 | return return_text 58 | else: 59 | print('获取日历失败:{}'.format(content_dict['message'])) 60 | 61 | print('获取日历失败。') 62 | except Exception as exception: 63 | print(str(exception)) 64 | return None 65 | 66 | 67 | get_calendar = get_sojson_calendar 68 | 69 | if __name__ == '__main__': 70 | # date = datetime.now().strftime('%Y-%m-%d') 71 | # date = '2018-11-06' 72 | # content = get_calendar(date) 73 | # print(content) 74 | pass 75 | -------------------------------------------------------------------------------- /everyday_wechat/control/express/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-09-04 12:23 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /everyday_wechat/control/express/kdniao_express.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-09-04 12:24 6 | Introduction: 快递鸟(http://www.kdniao.com/) 快递查询 7 | """ 8 | 9 | import json 10 | import hashlib 11 | import base64 12 | import requests 13 | 14 | from everyday_wechat.utils import config 15 | 16 | # 此处为快递鸟官网申请的帐号和密码 17 | 18 | URL = 'http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx' 19 | HEADERS = { 20 | "Accept": "application/x-www-form-urlencoded;charset=utf-8", 21 | "Accept-Encoding": "utf-8" 22 | } 23 | # 2-在途中,3-签收,4-问题件 24 | EXPRESS_STATE_DICT = {'0': '无物流', '2': '在途中', '3': '签收', '4': '问题件'} 25 | __all__ = ['get_express_info'] 26 | 27 | 28 | def encrypt(origin_data, app_key): 29 | """ 30 | 数据内容签名:把(请求内容(未编码) + AppKey)进行 MD5 加密,然后 Base64 编码 31 | :param origin_data: str, 请求的数据 32 | :param app_key: 33 | :return: 加密后的数据 34 | """ 35 | encodestr = hashlib.md5((origin_data + app_key).encode("UTF-8")).hexdigest() # MD5 加密 36 | base64_text = base64.b64encode(encodestr.encode(encoding='utf-8')) # Base64 加密 37 | return base64_text.decode() # 再次编码 38 | 39 | 40 | def get_company_info(express_code, app_id, app_key): 41 | """ 42 | 单号识别 API 接口。地址:http://www.kdniao.com/api-recognise 43 | 查询订单号的归属物流公司信息 44 | :param express_code: str 订单号 45 | :return: str 订单信息 46 | """ 47 | data1 = {'LogisticCode': express_code} 48 | d1 = json.dumps(data1, sort_keys=True) 49 | post_data = { 50 | 'RequestData': d1, 51 | 'EBusinessID': app_id, 52 | 'RequestType': '2002', 53 | 'DataType': '2', 54 | 'DataSign': encrypt(d1, app_key) 55 | } 56 | try: 57 | resp = requests.post(URL, data=post_data, headers=HEADERS) 58 | print(resp.text) 59 | if resp.status_code == 200: 60 | content_dict = resp.json() 61 | if not content_dict['Success']: 62 | print('出错原因:{}'.format(content_dict['Reason'])) 63 | return None 64 | elif not any(content_dict['Shippers']): 65 | print("未查到该快递信息,请检查快递单号是否有误!") 66 | return None 67 | else: 68 | shipper_info = content_dict['Shippers'][0] 69 | shipper_name = shipper_info['ShipperName'] 70 | shipper_code = shipper_info['ShipperCode'] 71 | xx = '快递单号 {ecode} 的快递公司是:{sname}({scode})'.format( 72 | sname=shipper_name, 73 | scode=shipper_code, 74 | ecode=express_code) 75 | print(xx) 76 | return {'shipper_code': shipper_code, 'shipper_name': shipper_name} 77 | 78 | except Exception as exception: 79 | print(str(exception)) 80 | 81 | return None 82 | 83 | 84 | def get_logistic_info(logistic_code, shipper_code, app_id, app_key): 85 | """ 86 | 即时查询 api 接口。地址:http://www.kdniao.com/api-track 87 | 对单个订单号进行查询详细的物流信息 88 | :param logistic_code: str, 订单号 89 | :param shipper_code: str, 快递公司编号 90 | :return: 91 | """ 92 | data1 = {'OrderCode': '', 'LogisticCode': logistic_code, 'ShipperCode': shipper_code} 93 | d1 = json.dumps(data1, sort_keys=True) 94 | post_data = { 95 | 'RequestData': d1, 96 | 'EBusinessID': app_id, 97 | 'RequestType': '1002', 98 | # 'RequestType': '1008', 99 | 'DataType': '2', 100 | 'DataSign': encrypt(d1, app_key) 101 | } 102 | try: 103 | resp = requests.post(URL, data=post_data, headers=HEADERS) 104 | print(resp.text) 105 | if resp.status_code == 200: 106 | content_dict = resp.json() 107 | if not content_dict['Success']: 108 | print('出错原因:{}'.format(content_dict['Reason'])) 109 | return None 110 | elif not any(content_dict['Traces']): 111 | print("未查询到该快递物流轨迹!") 112 | return None 113 | else: 114 | return content_dict 115 | except Exception as exception: 116 | print(str(exception)) 117 | return None 118 | 119 | 120 | def get_express_info(express_code, shipper_code='', shipper_name=''): 121 | """ 122 | 查询快递物流信息 123 | :param express_code: str,快递单号 124 | :param shipper_code: str,快递公司简称代号 125 | :param shipper_name: str,快递公司名称(用于结果显示) 126 | :return: 127 | """ 128 | express_config_info = config.get('group_helper_conf')['express_info'] 129 | app_id = express_config_info['app_id'] 130 | app_key = express_config_info['app_key'] 131 | if not shipper_code or not shipper_name: 132 | company_info = get_company_info(express_code, app_id, app_key) 133 | # print(company_info) 134 | if not company_info: 135 | return 136 | shipper_code = company_info['shipper_code'] 137 | shipper_name = company_info['shipper_name'] 138 | trace_data = get_logistic_info(express_code, shipper_code, app_id, app_key) 139 | print(trace_data) 140 | if not trace_data: 141 | return 142 | state_code = trace_data['State'] 143 | express_state = EXPRESS_STATE_DICT.get(state_code, '未知状态') 144 | 145 | info = [] 146 | express_base_info = '物流公司:{shipper_name}\n物流单号:{express_code}\n物流状态:{express_state}'.format( 147 | shipper_name=shipper_name, 148 | express_code=express_code, 149 | express_state=express_state) 150 | info.append(express_base_info) 151 | info.append('------物流详情------') 152 | traces = trace_data['Traces'] 153 | for i, item in enumerate(traces[::-1]): 154 | bb = '{index}. {time} {station}'.format( 155 | index=str(i + 1), 156 | time=item['AcceptTime'], 157 | station=item['AcceptStation']) 158 | # print(bb) 159 | info.append(bb) 160 | return_info = { 161 | 'express_code': express_code, 162 | 'shipper_code': shipper_code, 163 | 'shipper_name': shipper_name, 164 | 'info': '\n'.join(info), 165 | 'state': True if state_code == '3' else False 166 | } 167 | return return_info 168 | 169 | 170 | if __name__ == '__main__': 171 | code = '78109182715352' 172 | code = '78109356970791' 173 | # code = '9860572561560' 174 | # code = 'JD0001855864185' 175 | cc = get_express_info(code) 176 | print(cc) 177 | if cc: 178 | print(cc['info']) 179 | -------------------------------------------------------------------------------- /everyday_wechat/control/horoscope/__init__.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | 星座运势,基于 星座屋 爬取 6 | """ 7 | -------------------------------------------------------------------------------- /everyday_wechat/control/horoscope/xzw_horescope.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | 爬取 星座屋 星座运势 5 | https://www.xzw.com/ 6 | """ 7 | import re 8 | from functools import reduce 9 | import requests 10 | from bs4 import BeautifulSoup 11 | from everyday_wechat.utils.common import SPIDER_HEADERS 12 | 13 | __all__ = ['get_xzw_horoscope', 'get_today_horoscope'] 14 | 15 | XZW_BASE_URL_TODAY = "https://www.xzw.com/fortune/{}" 16 | XZW_BASE_URL_TOMORROW = "https://www.xzw.com/fortune/{}/1.html" 17 | CONSTELLATION_DICT = { 18 | "白羊座": "aries", 19 | "金牛座": "taurus", 20 | "双子座": "gemini", 21 | "巨蟹座": "cancer", 22 | "狮子座": "leo", 23 | "处女座": "virgo", 24 | "天秤座": "libra", 25 | "天蝎座": "scorpio", 26 | "射手座": "sagittarius", 27 | "摩羯座": "capricorn", 28 | "水瓶座": "aquarius", 29 | "双鱼座": "pisces", 30 | } 31 | 32 | 33 | def get_xzw_horoscope(name, is_tomorrow=False): 34 | ''' 35 | 获取星座屋(https://www.xzw.com)的星座运势 36 | :param name: 星座名称 37 | :return: 38 | ''' 39 | if not name in CONSTELLATION_DICT: 40 | print('星座输入有误') 41 | return 42 | try: 43 | const_code = CONSTELLATION_DICT[name] 44 | 45 | req_url = XZW_BASE_URL_TOMORROW.format(const_code) if is_tomorrow \ 46 | else XZW_BASE_URL_TODAY.format(const_code) 47 | 48 | resp = requests.get(req_url, headers=SPIDER_HEADERS) 49 | if resp.status_code == 200: 50 | html = resp.text 51 | lucky_num = re.findall(r'(.*?)', html)[0] 52 | lucky_color = re.findall(r'(.*?)', html)[0] 53 | detail_horoscope = re.findall(r'

.*?(.*?)

', html)[0] 54 | if is_tomorrow: 55 | detail_horoscope = detail_horoscope.replace('今天', '明天') 56 | 57 | return_text = '{name}{_date}运势\n【幸运颜色】{color}\n【幸运数字】{num}\n【综合运势】{horoscope}'.format( 58 | _date='明日' if is_tomorrow else '今日', 59 | name=name, 60 | color=lucky_color, 61 | num=lucky_num, 62 | horoscope=detail_horoscope 63 | ) 64 | return return_text 65 | except Exception as exception: 66 | print(str(exception)) 67 | 68 | 69 | get_today_horoscope = get_xzw_horoscope 70 | 71 | if __name__ == '__main__': 72 | # print (get_constellation(3, 10)) 73 | # print(get_xzw_text("03-18")) 74 | is_tomorrow = True 75 | print(get_xzw_horoscope("水瓶座", is_tomorrow)) 76 | -------------------------------------------------------------------------------- /everyday_wechat/control/moviebox/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-08-30 12:21 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /everyday_wechat/control/moviebox/maoyan_movie_box.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-08-30 12:22 6 | Introduction: 猫眼实时票房 地址:https://piaofang.maoyan.com/dashboard 7 | 接口地址:https://piaofang.maoyan.com/second-box?beginDate=20190924 8 | 9 | """ 10 | import requests 11 | 12 | from datetime import datetime 13 | from everyday_wechat.utils.common import SPIDER_HEADERS 14 | 15 | 16 | def get_maoyan_movie_box(date='', is_expired=False): 17 | """ 18 | 获取特定日期的实时票房日期 19 | https://piaofang.maoyan.com/second-box?beginDate=20190830#指定日期的节假日及万年历信息 20 | :param date: str 日期 格式 yyyyMMdd 21 | :param is_expired 22 | :rtype str 23 | """ 24 | date_ = date or datetime.now().strftime('%Y%m%d') 25 | 26 | print('获取 {} 的票房数据...'.format(date_)) 27 | # try: 28 | url = 'https://piaofang.maoyan.com/second-box?beginDate={}'.format(date_) 29 | resp = requests.get(url, headers=SPIDER_HEADERS) 30 | # print(resp) 31 | if resp.status_code == 200: 32 | # print(resp.text) 33 | content_dict = resp.json() 34 | if content_dict['success']: 35 | data_dict = content_dict['data'] 36 | total_box_info = data_dict['totalBoxInfo'] 37 | box_list = data_dict['list'] 38 | box_info_list = [] 39 | 40 | for i, r in enumerate(box_list[:10]): 41 | movice_name = r['movieName'] 42 | box_info = r['boxInfo'] 43 | sumBoxInfo = r['sumBoxInfo'] 44 | box_info_list.append('{}.《{}》({}万,累积:{})'.format(str(i + 1), movice_name, box_info, sumBoxInfo)) 45 | 46 | cur_date = datetime.strptime(date_, '%Y%m%d').strftime('%Y{}%m{}%d{}').format('年', '月', '日') 47 | 48 | return_text = "{cur_date} {box_name}\n当日总票房:{total_box_info}万\n{box_info}".format( 49 | cur_date=cur_date, 50 | box_name="实时票房" if is_expired else "当日票房", 51 | total_box_info=total_box_info, 52 | box_info='\n'.join(box_info_list) 53 | ) 54 | 55 | return return_text 56 | else: 57 | print('获取票房失败:{}'.format(content_dict['msg'])) 58 | return None 59 | 60 | print('获取票房失败。') 61 | # except Exception as exception: 62 | # print(str(exception)) 63 | return None 64 | 65 | 66 | # __date = '20190925' 67 | # dd = get_maoyan_movie_box(__date, is_expired=False) 68 | # print(dd) 69 | 70 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/everyday_wechat/control/onewords/__init__.py -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/acib.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | """ 4 | 从词霸中获取每日一句,带英文。 5 | """ 6 | 7 | import requests 8 | from everyday_wechat.utils.common import ( 9 | is_json 10 | ) 11 | 12 | __all__ = ['get_acib_info'] 13 | 14 | 15 | def get_acib_info(): 16 | """ 17 | 从词霸中获取每日一句,带英文。 18 | :return:str ,返回每日一句(双语) 19 | """ 20 | print('获取格言信息(双语)...') 21 | try: 22 | resp = requests.get('http://open.iciba.com/dsapi') 23 | if resp.status_code == 200 and is_json(resp): 24 | content_dict = resp.json() 25 | content = content_dict.get('content') 26 | note = content_dict.get('note') 27 | return '{}{}'.format(content, note) 28 | 29 | print('没有获取到格言数据。') 30 | except requests.exceptions.RequestException as exception: 31 | print(exception) 32 | return None 33 | 34 | 35 | get_one_words = get_acib_info 36 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/caihongpi.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | https://chp.shadiao.app/?from_nmsl 4 | 彩虹屁生成器 5 | """ 6 | import requests 7 | 8 | __all__ = ['get_caihongpi_info'] 9 | 10 | 11 | def get_caihongpi_info(): 12 | """ 13 | 彩虹屁生成器 14 | :return: str,彩虹屁 15 | """ 16 | print('获取彩虹屁信息...') 17 | try: 18 | resp = requests.get('https://chp.shadiao.app/api.php') 19 | if resp.status_code == 200: 20 | return resp.text 21 | print('彩虹屁获取失败。') 22 | except requests.exceptions.RequestException as exception: 23 | print(exception) 24 | # return None 25 | # return None 26 | 27 | 28 | get_one_words = get_caihongpi_info 29 | 30 | if __name__ == '__main__': 31 | ow = get_one_words() 32 | print(ow) 33 | pass 34 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/hitokoto.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 获取一言信息 4 | """ 5 | 6 | import requests 7 | 8 | __all__ = ['get_hitokoto_info'] 9 | 10 | 11 | def get_hitokoto_info(): 12 | """ 13 | 从『一言』获取信息。(官网:https://hitokoto.cn/) 14 | :return: str,一言。 15 | """ 16 | print('获取一言...') 17 | try: 18 | resp = requests.get('https://v1.hitokoto.cn/', params={'encode': 'text'}) 19 | if resp.status_code == 200: 20 | return resp.text 21 | print('一言获取失败。') 22 | except requests.exceptions.RequestException as exception: 23 | print(exception) 24 | # return None 25 | # return None 26 | 27 | 28 | get_one_words = get_hitokoto_info 29 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/juzimi.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 句子迷:(https://www.juzimi.com/) 4 | 民国情书:朱生豪先生的情话 && 爱你就像爱生命 5 | Author: ClaireYiu(https://github.com/ClaireYiu) 6 | """ 7 | import random 8 | import requests 9 | 10 | 11 | # from requests_html import HTMLSession 12 | 13 | 14 | def get_zsh_info(): 15 | """ 16 | 句子迷:(https://www.juzimi.com/) 17 | 朱生豪:https://www.juzimi.com/writer/朱生豪 18 | 爱你就像爱生命(王小波):https://www.juzimi.com/article/爱你就像爱生命 19 | 三行情书:https://www.juzimi.com/article/25637 20 | :return: str 情话 21 | """ 22 | print('正在获取民国情话...') 23 | try: 24 | name = [ 25 | ['writer/朱生豪', 38, ], 26 | ['article/爱你就像爱生命', 22], 27 | ['article/25637', 55], 28 | ] 29 | apdix = random.choice(name) 30 | # page 从零开始计数的。 31 | url = 'https://www.juzimi.com/{}?page={}'.format( 32 | apdix[0], random.randint(1, apdix[1])) 33 | # print(url) 34 | resp = requests.get(url) 35 | if resp.status_code == 200: 36 | # print(resp.html) 37 | # results = resp.find('a.xlistju') 38 | # if results: 39 | # re_text = random.choice(results).text 40 | # if re_text and '\n\n' in re_text: 41 | # re_text = re_text.replace('\n\n','\n') 42 | # return re_text 43 | return None 44 | print('获取民国情话失败..') 45 | except Exception as exception: 46 | print(exception) 47 | return None 48 | 49 | 50 | get_one_words = get_zsh_info 51 | 52 | if __name__ == '__main__': 53 | # for _ in range(15): 54 | # ow = get_one_words() 55 | # print(ow) 56 | pass 57 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/lovelive.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 从土味情话中获取每日一句。 4 | """ 5 | import requests 6 | 7 | __all__ = ['get_lovelive_info'] 8 | 9 | 10 | def get_lovelive_info(): 11 | """ 12 | 从土味情话中获取每日一句。 13 | :return: str,土味情话。 14 | """ 15 | print('获取土味情话...') 16 | try: 17 | resp = requests.get('https://api.lovelive.tools/api/SweetNothings') 18 | if resp.status_code == 200: 19 | return resp.text 20 | print('土味情话获取失败。') 21 | except requests.exceptions.RequestException as exception: 22 | print(exception) 23 | # return None 24 | return None 25 | 26 | 27 | get_one_words = get_lovelive_info 28 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/rtjokes.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | https://github.com/MZCretin/RollToolsApi#随机获取笑话段子列表 4 | 随机获取笑话段子列表 5 | """ 6 | import requests 7 | 8 | __all__ = ['get_rtjokes_info'] 9 | 10 | 11 | def get_rtjokes_info(): 12 | """ 13 | 随机获取笑话段子列表(https://github.com/MZCretin/RollToolsApi#随机获取笑话段子列表) 14 | :return: str,笑话。 15 | """ 16 | print('获取随机笑话...') 17 | try: 18 | resp = requests.get('https://www.mxnzp.com/api/jokes/list/random') 19 | # print(resp.text) 20 | if resp.status_code == 200: 21 | content_dict = resp.json() 22 | if content_dict['code'] == 1: 23 | # 每次返回 10 条笑话信息,只取一次 24 | return_text = content_dict['data'][0]['content'] 25 | # print(return_text) 26 | return return_text 27 | else: 28 | print(content_dict['msg']) 29 | print('获取笑话失败。') 30 | except Exception as exception: 31 | print(exception) 32 | return None 33 | return None 34 | 35 | 36 | get_one_words = get_rtjokes_info 37 | 38 | if __name__ == '__main__': 39 | get_rtjokes_info() 40 | -------------------------------------------------------------------------------- /everyday_wechat/control/onewords/wufazhuce.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 从「一个」获取每日一言 4 | """ 5 | import requests 6 | from bs4 import BeautifulSoup 7 | from everyday_wechat.utils.common import SPIDER_HEADERS 8 | 9 | __all__ = ['get_wufazhuce_info'] 10 | 11 | 12 | def get_wufazhuce_info(): 13 | """ 14 | 获取格言信息(从『一个。one』获取信息 http://wufazhuce.com/) 15 | :return: str, 一句格言或者短语。 16 | """ 17 | print('获取 ONE 信息...') 18 | user_url = 'http://wufazhuce.com/' 19 | try: 20 | resp = requests.get(user_url, headers=SPIDER_HEADERS) 21 | if resp.status_code == 200: 22 | soup_texts = BeautifulSoup(resp.text, 'lxml') 23 | # 『one -个』 中的每日一句 24 | every_msg = soup_texts.find('div', class_='fp-one-cita').text # 只取当天的这句 25 | return every_msg 26 | print('获取 ONE 失败。') 27 | except Exception as exception: 28 | print(str(exception)) 29 | return None 30 | return None 31 | 32 | 33 | get_one_words = get_wufazhuce_info 34 | -------------------------------------------------------------------------------- /everyday_wechat/control/rubbish/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-14 01:00 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /everyday_wechat/control/rubbish/atoolbox_rubbish.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-14 01:02 6 | Introduction: http://www.atoolbox.net/Tool.php?Id=804 7 | """ 8 | 9 | import requests 10 | from everyday_wechat.utils.common import SPIDER_HEADERS 11 | 12 | __all__ = ['get_atoolbox_rubbish'] 13 | 14 | 15 | def get_atoolbox_rubbish(key): 16 | """ 17 | # http://www.atoolbox.net/Tool.php?Id=804 18 | :param key: 19 | :return: 20 | """ 21 | params = {'key': key} 22 | resp = requests.get('http://www.atoolbox.net/api/GetRefuseClassification.php', 23 | headers=SPIDER_HEADERS, 24 | params=params) 25 | 26 | if resp.status_code == 200: 27 | # print(resp.text) 28 | content_dict = resp.json() 29 | if not content_dict: 30 | return None, None, None 31 | return_list = list(content_dict.values()) 32 | _type = '' 33 | for rl in return_list: 34 | if key == rl['name']: 35 | _type = rl['type'] 36 | break 37 | other = '' 38 | if not _type: 39 | other = ' '.join(i['name'] for i in return_list[:6]) 40 | return _type, return_list, other 41 | return None, None, None 42 | -------------------------------------------------------------------------------- /everyday_wechat/control/weather/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/everyday_wechat/control/weather/__init__.py -------------------------------------------------------------------------------- /everyday_wechat/control/weather/_city_sojson.json: -------------------------------------------------------------------------------- 1 | { 2 | "北京": "101010100", 3 | "上海": "101020100", 4 | "天津": "101030100", 5 | "重庆": "101040100", 6 | "香港": "101320101", 7 | "澳门": "101330101", 8 | "安庆": "101220601", 9 | "蚌埠": "101220201", 10 | "巢湖市": "101220105", 11 | "池州": "101221701", 12 | "滁州": "101221101", 13 | "阜阳": "101220801", 14 | "淮北": "101221201", 15 | "淮南": "101220401", 16 | "黄山市": "101221001", 17 | "六安": "101221501", 18 | "马鞍山": "101220501", 19 | "宿州": "101220701", 20 | "铜陵": "101221301", 21 | "芜湖市": "101220301", 22 | "宣城": "101221401", 23 | "亳州": "101220901", 24 | "福州": "101230101", 25 | "龙岩": "101230701", 26 | "南平": "101230901", 27 | "宁德": "101230301", 28 | "莆田": "101230401", 29 | "泉州": "101230501", 30 | "三明": "101230801", 31 | "厦门": "101230201", 32 | "漳州": "101230601", 33 | "兰州": "101160101", 34 | "白银市": "101161301", 35 | "定西": "101160201", 36 | "嘉峪关": "101161401", 37 | "金昌": "101160601", 38 | "酒泉": "101160801", 39 | "临夏市": "101161101", 40 | "陇南市": "101161010", 41 | "平凉": "101160301", 42 | "庆阳": "101160401", 43 | "天水": "101160901", 44 | "武威": "101160501", 45 | "张掖": "101160701", 46 | "广州": "101280101", 47 | "深圳": "101280601", 48 | "潮州": "101281501", 49 | "东莞": "101281601", 50 | "佛山": "101280800", 51 | "河源": "101281201", 52 | "惠州": "101280301", 53 | "江门": "101281101", 54 | "揭阳": "101281901", 55 | "茂名": "101282001", 56 | "梅州": "101280401", 57 | "清远": "101281301", 58 | "汕头": "101280501", 59 | "汕尾": "101282101", 60 | "韶关": "101280201", 61 | "阳江": "101281801", 62 | "云浮": "101281401", 63 | "湛江": "101281001", 64 | "肇庆": "101280901", 65 | "中山市": "101281701", 66 | "珠海": "101280701", 67 | "南宁": "101300101", 68 | "桂林": "101300501", 69 | "百色": "101301001", 70 | "北海": "101301301", 71 | "崇左": "101300201", 72 | "防城港": "101301401", 73 | "贵港": "101300801", 74 | "河池": "101301201", 75 | "贺州": "101300701", 76 | "来宾": "101300401", 77 | "柳州": "101300301", 78 | "钦州": "101301101", 79 | "梧州": "101300601", 80 | "玉林": "101300901", 81 | "贵阳": "101260101", 82 | "安顺": "101260301", 83 | "毕节": "101260701", 84 | "六盘水": "101260803", 85 | "黔东南": "101260506", 86 | "黔南": "101260413", 87 | "黔西南": "101260906", 88 | "铜仁市": "101260601", 89 | "遵义": "101260201", 90 | "海口": "101310101", 91 | "三亚": "101310201", 92 | "白沙县": "101310207", 93 | "保亭县": "101310214", 94 | "昌江县": "101310206", 95 | "澄迈县": "101310204", 96 | "定安县": "101310209", 97 | "东方": "101310202", 98 | "乐东县": "101310221", 99 | "临高县": "101310203", 100 | "陵水县": "101310216", 101 | "琼海": "101310211", 102 | "琼中": "101310208", 103 | "屯昌县": "101310210", 104 | "万宁": "101310215", 105 | "文昌": "101310212", 106 | "五指山": "101310222", 107 | "儋州": "101310205", 108 | "石家庄": "101090101", 109 | "保定": "101090201", 110 | "沧州": "101090701", 111 | "承德市": "101090402", 112 | "邯郸市": "101091001", 113 | "衡水": "101090801", 114 | "廊坊": "101090601", 115 | "秦皇岛": "101091101", 116 | "唐山": "101090501", 117 | "邢台市": "101090901", 118 | "张家口": "101090301", 119 | "郑州": "101180101", 120 | "洛阳": "101180901", 121 | "开封市": "101180801", 122 | "安阳市": "101180201", 123 | "鹤壁": "101181201", 124 | "济源市": "101181801", 125 | "焦作": "101181101", 126 | "南阳": "101180701", 127 | "平顶山": "101180501", 128 | "三门峡": "101181701", 129 | "商丘": "101181001", 130 | "新乡市": "101180301", 131 | "信阳": "101180601", 132 | "许昌市": "101180401", 133 | "周口": "101181401", 134 | "驻马店": "101181601", 135 | "漯河": "101181501", 136 | "濮阳市": "101181301", 137 | "哈尔滨": "101050101", 138 | "大庆": "101050901", 139 | "大兴安岭": "101050701", 140 | "鹤岗": "101051201", 141 | "黑河": "101050601", 142 | "鸡西": "101051101", 143 | "佳木斯": "101050401", 144 | "牡丹江": "101050301", 145 | "七台河": "101051002", 146 | "齐齐哈尔": "101050201", 147 | "双鸭山": "101051301", 148 | "绥化": "101050501", 149 | "伊春市": "101050801", 150 | "武汉": "101200101", 151 | "仙桃": "101201601", 152 | "鄂州": "101200301", 153 | "黄冈": "101200501", 154 | "黄石": "101200601", 155 | "荆门": "101201401", 156 | "荆州市": "101200801", 157 | "潜江市": "101201701", 158 | "神农架": "101201201", 159 | "十堰": "101201101", 160 | "随州": "101201301", 161 | "天门市": "101201501", 162 | "咸宁": "101200701", 163 | "襄阳": "101200201", 164 | "孝感": "101200401", 165 | "宜昌": "101200901", 166 | "恩施市": "101201001", 167 | "长沙市": "101250101", 168 | "张家界": "101251101", 169 | "常德": "101250601", 170 | "郴州": "101250501", 171 | "衡阳市": "101250401", 172 | "怀化": "101251201", 173 | "娄底": "101250801", 174 | "邵阳市": "101250901", 175 | "湘潭市": "101250201", 176 | "湘西": "101251509", 177 | "益阳": "101250700", 178 | "永州": "101251401", 179 | "岳阳市": "101251001", 180 | "株洲": "101250301", 181 | "长春": "101060101", 182 | "吉林市": "101060201", 183 | "白城": "101060601", 184 | "白山": "101060901", 185 | "辽源": "101060701", 186 | "四平": "101060401", 187 | "松原": "101060801", 188 | "通化市": "101060501", 189 | "延边": "101060306", 190 | "南京": "101190101", 191 | "苏州": "101190401", 192 | "无锡": "101190201", 193 | "常州": "101191101", 194 | "淮安市": "101190901", 195 | "连云港": "101191001", 196 | "南通": "101190501", 197 | "宿迁": "101191301", 198 | "泰州": "101191201", 199 | "徐州": "101190801", 200 | "盐城": "101190701", 201 | "扬州": "101190601", 202 | "镇江": "101190301", 203 | "南昌市": "101240101", 204 | "抚州": "101240401", 205 | "赣州": "101240701", 206 | "吉安市": "101240601", 207 | "景德镇": "101240801", 208 | "九江市": "101240201", 209 | "萍乡": "101240901", 210 | "上饶市": "101240301", 211 | "新余": "101241001", 212 | "宜春": "101240501", 213 | "鹰潭": "101241101", 214 | "沈阳": "101070101", 215 | "大连市": "101070201", 216 | "鞍山市": "101070301", 217 | "本溪市": "101070501", 218 | "朝阳市": "101071201", 219 | "丹东": "101070601", 220 | "抚顺市": "101070401", 221 | "阜新": "101070901", 222 | "葫芦岛": "101071401", 223 | "锦州": "101070701", 224 | "辽阳市": "101071001", 225 | "盘锦": "101071301", 226 | "铁岭市": "101071101", 227 | "营口": "101070801", 228 | "呼和浩特": "101080101", 229 | "阿拉善盟": "101081213", 230 | "巴彦淖尔": "101080811", 231 | "包头": "101080201", 232 | "赤峰": "101080601", 233 | "鄂尔多斯": "101080701", 234 | "呼伦贝尔市": "101081001", 235 | "通辽": "101080501", 236 | "乌海": "101080301", 237 | "乌兰察布": "101080405", 238 | "锡林郭勒": "101080902", 239 | "兴安盟": "101081108", 240 | "银川": "101170101", 241 | "固原": "101170401", 242 | "石嘴山": "101170201", 243 | "吴忠": "101170301", 244 | "中卫": "101170501", 245 | "西宁": "101150101", 246 | "果洛": "101150507", 247 | "海北": "101150804", 248 | "海东": "101150207", 249 | "共和县": "101150401", 250 | "德令哈市": "101150701", 251 | "黄南": "101150305", 252 | "玉树": "101150601", 253 | "济南": "101120101", 254 | "青岛": "101120201", 255 | "滨州": "101121101", 256 | "德州": "101120401", 257 | "东营区": "101121201", 258 | "菏泽": "101121001", 259 | "济宁": "101120701", 260 | "莱芜": "101121601", 261 | "聊城": "101121701", 262 | "临沂": "101120901", 263 | "日照": "101121501", 264 | "泰安": "101120801", 265 | "威海": "101121301", 266 | "潍坊": "101120601", 267 | "烟台": "101120501", 268 | "枣庄": "101121401", 269 | "淄博": "101120301", 270 | "太原": "101100101", 271 | "长治市": "101100501", 272 | "大同市": "101100201", 273 | "晋城": "101100601", 274 | "晋中": "101100401", 275 | "临汾": "101100701", 276 | "吕梁": "101101100", 277 | "朔州": "101100901", 278 | "忻州": "101101001", 279 | "阳泉": "101100301", 280 | "运城": "101100801", 281 | "西安市": "101110101", 282 | "安康市": "101110701", 283 | "宝鸡": "101110901", 284 | "汉中": "101110801", 285 | "商洛": "101110601", 286 | "铜川": "101111001", 287 | "渭南": "101110501", 288 | "咸阳": "101110200", 289 | "延安": "101110300", 290 | "榆林": "101110401", 291 | "成都": "101270101", 292 | "绵阳": "101270401", 293 | "阿坝": "101271901", 294 | "巴中": "101270901", 295 | "达州": "101270601", 296 | "德阳": "101272001", 297 | "甘孜": "101271801", 298 | "广安市": "101270801", 299 | "广元": "101272101", 300 | "乐山": "101271401", 301 | "凉山": "101271601", 302 | "眉山市": "101271501", 303 | "南充": "101270501", 304 | "内江": "101271201", 305 | "攀枝花": "101270201", 306 | "遂宁": "101270701", 307 | "雅安": "101271701", 308 | "宜宾": "101271101", 309 | "资阳市": "101271301", 310 | "自贡": "101270301", 311 | "泸州": "101271001", 312 | "拉萨": "101140101", 313 | "阿里": "101140701", 314 | "昌都市": "101140501", 315 | "林芝市": "101140401", 316 | "那曲": "101140601", 317 | "日喀则市": "101140201", 318 | "山南": "101140301", 319 | "乌鲁木齐市": "101130101", 320 | "阿克苏市": "101130801", 321 | "阿拉尔市": "101130701", 322 | "巴音郭楞": "101130609", 323 | "博尔塔拉": "101131604", 324 | "昌吉市": "101130401", 325 | "哈密市": "101131201", 326 | "和田市": "101131301", 327 | "喀什市": "101130901", 328 | "克拉玛依市": "101130201", 329 | "石河子市": "101130301", 330 | "吐鲁番市": "101130501", 331 | "伊犁": "101131012", 332 | "昆明": "101290101", 333 | "怒江": "101291201", 334 | "普洱": "101290901", 335 | "丽江": "101291401", 336 | "保山": "101290501", 337 | "楚雄市": "101290801", 338 | "大理市": "101290201", 339 | "德宏": "101291501", 340 | "迪庆": "101291305", 341 | "红河县": "101290301", 342 | "临沧": "101291101", 343 | "曲靖": "101290401", 344 | "文山市": "101290601", 345 | "西双版纳": "101291602", 346 | "玉溪": "101290701", 347 | "昭通": "101291001", 348 | "杭州": "101210101", 349 | "湖州": "101210201", 350 | "嘉兴": "101210301", 351 | "金华": "101210901", 352 | "丽水": "101210801", 353 | "宁波": "101210401", 354 | "绍兴": "101210507", 355 | "台州": "101210601", 356 | "温州": "101210701", 357 | "舟山": "101211101", 358 | "衢州": "101211001", 359 | "桐城市": "101220609", 360 | "怀宁县": "101220605", 361 | "枞阳县": "101221305", 362 | "潜山县": "101220604", 363 | "太湖县": "101220603", 364 | "宿松县": "101220606", 365 | "望江县": "101220607", 366 | "岳西县": "101220608", 367 | "怀远县": "101220202", 368 | "五河县": "101220204", 369 | "固镇县": "101220203", 370 | "庐江县": "101220106", 371 | "无为县": "101220305", 372 | "含山县": "101220503", 373 | "和县": "101220504", 374 | "东至县": "101221702", 375 | "石台县": "101221705", 376 | "青阳县": "101221703", 377 | "天长市": "101221107", 378 | "明光市": "101221103", 379 | "来安县": "101221106", 380 | "全椒县": "101221105", 381 | "定远县": "101221104", 382 | "凤阳县": "101221102", 383 | "界首市": "101220805", 384 | "临泉县": "101220804", 385 | "太和县": "101220806", 386 | "阜南县": "101220802", 387 | "颍上县": "101220803", 388 | "濉溪县": "101221202", 389 | "潘集区": "101220403", 390 | "凤台县": "101220402", 391 | "屯溪区": "101221003", 392 | "黄山区": "101221002", 393 | "歙县": "101221006", 394 | "休宁县": "101221007", 395 | "黟县": "101221005", 396 | "祁门县": "101221004", 397 | "寿县": "101220408", 398 | "霍邱县": "101221502", 399 | "舒城县": "101221507", 400 | "金寨县": "101221505", 401 | "霍山县": "101221506", 402 | "当涂县": "101220502", 403 | "砀山县": "101220702", 404 | "萧县": "101220705", 405 | "灵璧县": "101220703", 406 | "泗县": "101220704", 407 | "义安区": "101221303", 408 | "芜湖县": "101220303", 409 | "繁昌县": "101220302", 410 | "南陵县": "101220304", 411 | "宁国市": "101221404", 412 | "郎溪县": "101221407", 413 | "广德县": "101221406", 414 | "泾县": "101221402", 415 | "绩溪县": "101221405", 416 | "旌德县": "101221403", 417 | "涡阳县": "101220902", 418 | "蒙城县": "101220904", 419 | "利辛县": "101220903", 420 | "海淀区": "101010200", 421 | "朝阳区": "101060110", 422 | "丰台区": "101010900", 423 | "石景山区": "101011000", 424 | "房山区": "101011200", 425 | "门头沟区": "101011400", 426 | "通州区": "101010600", 427 | "顺义区": "101010400", 428 | "昌平区": "101010700", 429 | "怀柔区": "101010500", 430 | "平谷区": "101011500", 431 | "大兴区": "101011100", 432 | "密云区": "101011300", 433 | "延庆区": "101010800", 434 | "福清市": "101230111", 435 | "长乐市": "101230110", 436 | "闽侯县": "101230103", 437 | "连江县": "101230105", 438 | "罗源县": "101230104", 439 | "闽清县": "101230102", 440 | "永泰县": "101230107", 441 | "平潭县": "101230108", 442 | "漳平市": "101230707", 443 | "长汀县": "101230702", 444 | "永定区": "101230706", 445 | "上杭县": "101230705", 446 | "武平县": "101230704", 447 | "连城县": "101230703", 448 | "邵武市": "101230904", 449 | "武夷山市": "101230905", 450 | "建瓯市": "101230910", 451 | "建阳市": "101230907", 452 | "顺昌县": "101230902", 453 | "浦城县": "101230906", 454 | "光泽县": "101230903", 455 | "松溪县": "101230908", 456 | "政和县": "101230909", 457 | "福安市": "101230306", 458 | "福鼎市": "101230308", 459 | "霞浦县": "101230303", 460 | "古田县": "101230302", 461 | "屏南县": "101230309", 462 | "寿宁县": "101230304", 463 | "周宁县": "101230305", 464 | "柘荣县": "101230307", 465 | "城厢区": "101230407", 466 | "涵江区": "101230404", 467 | "荔城区": "101230406", 468 | "秀屿区": "101230405", 469 | "仙游县": "101230402", 470 | "石狮市": "101230510", 471 | "晋江市": "101230509", 472 | "南安市": "101230506", 473 | "惠安县": "101230508", 474 | "安溪县": "101230502", 475 | "永春县": "101230504", 476 | "德化县": "101230505", 477 | "永安市": "101230810", 478 | "明溪县": "101230807", 479 | "清流县": "101230803", 480 | "宁化县": "101230802", 481 | "大田县": "101230811", 482 | "尤溪县": "101230809", 483 | "沙县": "101230808", 484 | "将乐县": "101230805", 485 | "泰宁县": "101230804", 486 | "建宁县": "101230806", 487 | "同安区": "101230202", 488 | "龙海市": "101230605", 489 | "云霄县": "101230609", 490 | "漳浦县": "101230606", 491 | "诏安县": "101230607", 492 | "长泰县": "101230602", 493 | "东山县": "101230608", 494 | "南靖县": "101230603", 495 | "平和县": "101230604", 496 | "华安县": "101230610", 497 | "皋兰县": "101160102", 498 | "永登县": "101160103", 499 | "榆中县": "101160104", 500 | "平川区": "101161304", 501 | "会宁县": "101161303", 502 | "景泰县": "101161305", 503 | "靖远县": "101161302", 504 | "临洮县": "101160205", 505 | "陇西县": "101160203", 506 | "通渭县": "101160202", 507 | "渭源县": "101160204", 508 | "漳县": "101160206", 509 | "岷县": "101160207", 510 | "合作市": "101161201", 511 | "临潭县": "101161202", 512 | "卓尼县": "101161203", 513 | "舟曲县": "101161204", 514 | "迭部县": "101161205", 515 | "玛曲县": "101161206", 516 | "碌曲县": "101161207", 517 | "夏河县": "101161208", 518 | "永昌县": "101160602", 519 | "玉门市": "101160807", 520 | "敦煌市": "101160808", 521 | "金塔县": "101160803", 522 | "瓜州县": "101160805", 523 | "肃北县": "101160806", 524 | "阿克塞": "101160804", 525 | "康乐县": "101161102", 526 | "永靖县": "101161103", 527 | "广河县": "101161104", 528 | "和政县": "101161105", 529 | "东乡族自治县": "101161106", 530 | "积石山": "101161107", 531 | "成县": "101161002", 532 | "徽县": "101161008", 533 | "康县": "101161005", 534 | "礼县": "101161007", 535 | "两当县": "101161009", 536 | "文县": "101161003", 537 | "西和县": "101161006", 538 | "宕昌县": "101161004", 539 | "武都区": "101161001", 540 | "崇信县": "101160304", 541 | "华亭县": "101160305", 542 | "静宁县": "101160307", 543 | "灵台县": "101160303", 544 | "崆峒区": "101160308", 545 | "庄浪县": "101160306", 546 | "泾川县": "101160302", 547 | "合水县": "101160405", 548 | "华池县": "101160404", 549 | "环县": "101160403", 550 | "宁县": "101160407", 551 | "庆城县": "101160409", 552 | "西峰区": "101160402", 553 | "镇原县": "101160408", 554 | "正宁县": "101160406", 555 | "甘谷县": "101160905", 556 | "秦安县": "101160904", 557 | "清水县": "101160903", 558 | "麦积区": "101160908", 559 | "武山县": "101160906", 560 | "张家川": "101160907", 561 | "古浪县": "101160503", 562 | "民勤县": "101160502", 563 | "天祝县": "101160505", 564 | "高台县": "101160705", 565 | "临泽县": "101160704", 566 | "民乐县": "101160703", 567 | "山丹县": "101160706", 568 | "肃南县": "101160702", 569 | "从化区": "101280103", 570 | "天河区": "101280109", 571 | "番禺区": "101280102", 572 | "花都区": "101280105", 573 | "增城区": "101280104", 574 | "南山区": "101280604", 575 | "潮安区": "101281503", 576 | "饶平县": "101281502", 577 | "南海区": "101280803", 578 | "顺德区": "101280801", 579 | "三水区": "101280802", 580 | "高明区": "101280804", 581 | "东源县": "101281206", 582 | "和平县": "101281204", 583 | "连平县": "101281203", 584 | "龙川县": "101281205", 585 | "紫金县": "101281202", 586 | "惠阳区": "101280303", 587 | "博罗县": "101280302", 588 | "惠东县": "101280304", 589 | "龙门县": "101280305", 590 | "江海区": "101281109", 591 | "蓬江区": "101281107", 592 | "新会区": "101281104", 593 | "台山市": "101281106", 594 | "开平市": "101281103", 595 | "鹤山市": "101281108", 596 | "恩平市": "101281105", 597 | "普宁市": "101281903", 598 | "揭东区": "101281905", 599 | "揭西县": "101281902", 600 | "惠来县": "101281904", 601 | "茂港": "101282006", 602 | "高州市": "101282002", 603 | "化州市": "101282003", 604 | "信宜市": "101282005", 605 | "电白区": "101282004", 606 | "梅县区": "101280409", 607 | "兴宁市": "101280402", 608 | "大埔县": "101280404", 609 | "丰顺县": "101280406", 610 | "五华县": "101280408", 611 | "平远县": "101280407", 612 | "蕉岭县": "101280403", 613 | "英德市": "101281307", 614 | "连州市": "101281303", 615 | "佛冈县": "101281306", 616 | "阳山县": "101281305", 617 | "清新区": "101281308", 618 | "连山县": "101281304", 619 | "连南县": "101281302", 620 | "南澳县": "101280504", 621 | "潮阳区": "101280502", 622 | "澄海区": "101280503", 623 | "陆丰市": "101282103", 624 | "海丰县": "101282102", 625 | "陆河县": "101282104", 626 | "曲江区": "101280209", 627 | "浈江区": "101280210", 628 | "武江区": "101280211", 629 | "乐昌市": "101280205", 630 | "南雄市": "101280207", 631 | "始兴县": "101280203", 632 | "仁化县": "101280206", 633 | "翁源县": "101280204", 634 | "新丰县": "101280208", 635 | "乳源县": "101280202", 636 | "阳春市": "101281802", 637 | "阳西县": "101281804", 638 | "阳东区": "101281803", 639 | "罗定市": "101281402", 640 | "新兴县": "101281403", 641 | "郁南县": "101281404", 642 | "云安区": "101281406", 643 | "赤坎区": "101281006", 644 | "霞山区": "101281009", 645 | "坡头区": "101281008", 646 | "麻章区": "101281010", 647 | "廉江市": "101281005", 648 | "雷州市": "101281003", 649 | "吴川市": "101281002", 650 | "遂溪县": "101281007", 651 | "徐闻县": "101281004", 652 | "高要区": "101280908", 653 | "四会市": "101280903", 654 | "广宁县": "101280902", 655 | "怀集县": "101280906", 656 | "封开县": "101280907", 657 | "德庆县": "101280905", 658 | "斗门区": "101280702", 659 | "金湾区": "101280703", 660 | "邕宁区": "101300103", 661 | "武鸣区": "101300108", 662 | "隆安县": "101300105", 663 | "马山县": "101300106", 664 | "上林县": "101300107", 665 | "宾阳县": "101300109", 666 | "横县": "101300104", 667 | "阳朔县": "101300510", 668 | "临桂区": "101300505", 669 | "灵川县": "101300507", 670 | "全州县": "101300508", 671 | "平乐县": "101300512", 672 | "兴安县": "101300506", 673 | "灌阳县": "101300509", 674 | "荔浦县": "101300513", 675 | "资源县": "101300514", 676 | "永福县": "101300504", 677 | "龙胜县": "101300503", 678 | "恭城县": "101300511", 679 | "凌云县": "101301011", 680 | "平果县": "101301007", 681 | "西林县": "101301009", 682 | "乐业县": "101301010", 683 | "德保县": "101301004", 684 | "田林县": "101301012", 685 | "田阳县": "101301003", 686 | "靖西市": "101301005", 687 | "田东县": "101301006", 688 | "那坡县": "101301002", 689 | "隆林县": "101301008", 690 | "合浦县": "101301302", 691 | "凭祥市": "101300204", 692 | "宁明县": "101300207", 693 | "扶绥县": "101300206", 694 | "龙州县": "101300203", 695 | "大新县": "101300205", 696 | "天等县": "101300202", 697 | "防城区": "101301405", 698 | "东兴市": "101301403", 699 | "上思县": "101301402", 700 | "桂平市": "101300802", 701 | "平南县": "101300803", 702 | "宜州市": "101301207", 703 | "天峨县": "101301202", 704 | "凤山县": "101301208", 705 | "南丹县": "101301209", 706 | "东兰县": "101301203", 707 | "都安县": "101301210", 708 | "罗城县": "101301206", 709 | "巴马县": "101301204", 710 | "环江县": "101301205", 711 | "大化县": "101301211", 712 | "钟山县": "101300704", 713 | "昭平县": "101300702", 714 | "富川县": "101300703", 715 | "合山市": "101300406", 716 | "象州县": "101300404", 717 | "武宣县": "101300405", 718 | "忻城县": "101300402", 719 | "金秀县": "101300403", 720 | "柳江区": "101300305", 721 | "柳城县": "101300302", 722 | "鹿寨县": "101300304", 723 | "融安县": "101300306", 724 | "融水县": "101300307", 725 | "三江县": "101300308", 726 | "灵山县": "101301103", 727 | "浦北县": "101301102", 728 | "长洲区": "101300607", 729 | "岑溪市": "101300606", 730 | "苍梧县": "101300604", 731 | "藤县": "101300602", 732 | "蒙山县": "101300605", 733 | "北流市": "101300903", 734 | "容县": "101300904", 735 | "陆川县": "101300905", 736 | "博白县": "101300902", 737 | "兴业县": "101300906", 738 | "南明区": "101260111", 739 | "云岩区": "101260110", 740 | "花溪区": "101260103", 741 | "乌当区": "101260104", 742 | "白云区": "101280110", 743 | "小河": "101260109", 744 | "清镇市": "101260108", 745 | "开阳县": "101260106", 746 | "修文县": "101260107", 747 | "息烽县": "101260105", 748 | "关岭县": "101260306", 749 | "紫云县": "101260305", 750 | "平坝区": "101260304", 751 | "普定县": "101260302", 752 | "大方县": "101260705", 753 | "黔西县": "101260708", 754 | "金沙县": "101260703", 755 | "织金县": "101260707", 756 | "纳雍县": "101260706", 757 | "赫章县": "101260702", 758 | "威宁县": "101260704", 759 | "水城县": "101260801", 760 | "盘县": "101260804", 761 | "凯里市": "101260501", 762 | "黄平县": "101260505", 763 | "施秉县": "101260503", 764 | "三穗县": "101260509", 765 | "镇远县": "101260504", 766 | "岑巩县": "101260502", 767 | "天柱县": "101260514", 768 | "锦屏县": "101260515", 769 | "剑河县": "101260511", 770 | "台江县": "101260510", 771 | "黎平县": "101260513", 772 | "榕江县": "101260516", 773 | "从江县": "101260517", 774 | "雷山县": "101260512", 775 | "麻江县": "101260507", 776 | "丹寨县": "101260508", 777 | "都匀市": "101260401", 778 | "福泉市": "101260405", 779 | "荔波县": "101260412", 780 | "贵定县": "101260402", 781 | "瓮安县": "101260403", 782 | "独山县": "101260410", 783 | "平塘县": "101260409", 784 | "罗甸县": "101260408", 785 | "长顺县": "101260404", 786 | "龙里县": "101260407", 787 | "惠水县": "101260406", 788 | "三都县": "101260411", 789 | "兴义市": "101260901", 790 | "兴仁县": "101260903", 791 | "普安县": "101260909", 792 | "晴隆县": "101260902", 793 | "贞丰县": "101260904", 794 | "望谟县": "101260905", 795 | "册亨县": "101260908", 796 | "安龙县": "101260907", 797 | "江口县": "101260602", 798 | "石阡县": "101260608", 799 | "思南县": "101260605", 800 | "德江县": "101260610", 801 | "玉屏县": "101260603", 802 | "印江县": "101260607", 803 | "沿河县": "101260609", 804 | "松桃县": "101260611", 805 | "红花岗区": "101260215", 806 | "务川县": "101260212", 807 | "道真县": "101260210", 808 | "汇川区": "101260214", 809 | "赤水市": "101260208", 810 | "仁怀市": "101260203", 811 | "遵义县": "101260202", 812 | "桐梓县": "101260207", 813 | "绥阳县": "101260204", 814 | "正安县": "101260211", 815 | "凤冈县": "101260206", 816 | "湄潭县": "101260205", 817 | "余庆县": "101260213", 818 | "习水县": "101260209", 819 | "琼山区": "101310104", 820 | "井陉矿区": "101090122", 821 | "辛集市": "101090114", 822 | "藁城市": "101090115", 823 | "晋州市": "101090116", 824 | "新乐市": "101090117", 825 | "鹿泉区": "101090118", 826 | "井陉县": "101090102", 827 | "正定县": "101090103", 828 | "行唐县": "101090104", 829 | "灵寿县": "101090106", 830 | "高邑县": "101090107", 831 | "深泽县": "101090108", 832 | "赞皇县": "101090109", 833 | "无极县": "101090110", 834 | "平山县": "101090111", 835 | "元氏县": "101090112", 836 | "赵县": "101090113", 837 | "涿州市": "101090218", 838 | "定州市": "101090219", 839 | "安国市": "101090220", 840 | "高碑店市": "101090221", 841 | "满城区": "101090202", 842 | "清苑区": "101090224", 843 | "涞水县": "101090222", 844 | "阜平县": "101090203", 845 | "徐水区": "101090204", 846 | "定兴县": "101090223", 847 | "唐县": "101090205", 848 | "高阳县": "101090206", 849 | "容城县": "101090207", 850 | "涞源县": "101090209", 851 | "望都县": "101090210", 852 | "安新县": "101090211", 853 | "易县": "101090212", 854 | "曲阳县": "101090214", 855 | "蠡县": "101090215", 856 | "顺平县": "101090216", 857 | "博野县": "101090225", 858 | "雄县": "101090217", 859 | "泊头市": "101090711", 860 | "任丘市": "101090712", 861 | "黄骅市": "101090713", 862 | "河间市": "101090714", 863 | "沧县": "101090716", 864 | "青县": "101090702", 865 | "东光县": "101090703", 866 | "海兴县": "101090704", 867 | "盐山县": "101090705", 868 | "肃宁县": "101090706", 869 | "南皮县": "101090707", 870 | "吴桥县": "101090708", 871 | "献县": "101090709", 872 | "孟村县": "101090710", 873 | "承德县": "101090403", 874 | "兴隆县": "101090404", 875 | "平泉市": "101090405", 876 | "滦平县": "101090406", 877 | "隆化县": "101090407", 878 | "丰宁县": "101090408", 879 | "宽城县": "101090409", 880 | "围场县": "101090410", 881 | "峰峰矿区": "101091002", 882 | "武安市": "101091016", 883 | "临漳县": "101091003", 884 | "成安县": "101091004", 885 | "大名县": "101091005", 886 | "涉县": "101091006", 887 | "磁县": "101091007", 888 | "肥乡县": "101091008", 889 | "永年县": "101091009", 890 | "邱县": "101091010", 891 | "鸡泽县": "101091011", 892 | "广平县": "101091012", 893 | "馆陶县": "101091013", 894 | "魏县": "101091014", 895 | "曲周县": "101091015", 896 | "冀州市": "101090810", 897 | "深州市": "101090811", 898 | "枣强县": "101090802", 899 | "武邑县": "101090803", 900 | "武强县": "101090804", 901 | "饶阳县": "101090805", 902 | "安平县": "101090806", 903 | "故城县": "101090807", 904 | "景县": "101090808", 905 | "阜城县": "101090809", 906 | "霸州市": "101090608", 907 | "三河市": "101090609", 908 | "固安县": "101090602", 909 | "永清县": "101090603", 910 | "香河县": "101090604", 911 | "大城县": "101090605", 912 | "文安县": "101090606", 913 | "大厂县": "101090607", 914 | "北戴河区": "101091106", 915 | "昌黎县": "101091103", 916 | "抚宁区": "101091104", 917 | "卢龙县": "101091105", 918 | "青龙县": "101091102", 919 | "丰南区": "101090502", 920 | "丰润区": "101090503", 921 | "遵化市": "101090510", 922 | "迁安市": "101090511", 923 | "滦县": "101090504", 924 | "滦南县": "101090505", 925 | "乐亭县": "101090506", 926 | "迁西县": "101090507", 927 | "玉田县": "101090508", 928 | "曹妃甸区": "101090509", 929 | "南宫市": "101090916", 930 | "沙河市": "101090917", 931 | "临城县": "101090902", 932 | "内丘县": "101090904", 933 | "柏乡县": "101090905", 934 | "隆尧县": "101090906", 935 | "任县": "101090918", 936 | "南和县": "101090907", 937 | "宁晋县": "101090908", 938 | "巨鹿县": "101090909", 939 | "新河县": "101090910", 940 | "广宗县": "101090911", 941 | "平乡县": "101090912", 942 | "威县": "101090913", 943 | "清河县": "101090914", 944 | "临西县": "101090915", 945 | "宣化区": "101090302", 946 | "张北县": "101090303", 947 | "康保县": "101090304", 948 | "沽源县": "101090305", 949 | "尚义县": "101090306", 950 | "蔚县": "101090307", 951 | "阳原县": "101090308", 952 | "怀安县": "101090309", 953 | "万全区": "101090310", 954 | "怀来县": "101090311", 955 | "涿鹿县": "101090312", 956 | "赤城县": "101090313", 957 | "崇礼区": "101090314", 958 | "上街区": "101180108", 959 | "巩义市": "101180102", 960 | "荥阳市": "101180103", 961 | "新密市": "101180105", 962 | "新郑市": "101180106", 963 | "登封市": "101180104", 964 | "中牟县": "101180107", 965 | "吉利区": "101180911", 966 | "偃师市": "101180908", 967 | "孟津县": "101180903", 968 | "新安县": "101180902", 969 | "栾川县": "101180909", 970 | "嵩县": "101180907", 971 | "汝阳县": "101180910", 972 | "宜阳县": "101180904", 973 | "洛宁县": "101180905", 974 | "伊川县": "101180906", 975 | "杞县": "101180802", 976 | "通许县": "101180804", 977 | "尉氏县": "101180803", 978 | "兰考县": "101180805", 979 | "林州市": "101180205", 980 | "汤阴县": "101180202", 981 | "滑县": "101180203", 982 | "内黄县": "101180204", 983 | "浚县": "101181202", 984 | "淇县": "101181203", 985 | "沁阳市": "101181104", 986 | "孟州市": "101181108", 987 | "修武县": "101181102", 988 | "博爱县": "101181106", 989 | "武陟县": "101181103", 990 | "温县": "101181107", 991 | "邓州市": "101180711", 992 | "南召县": "101180702", 993 | "方城县": "101180703", 994 | "西峡县": "101180705", 995 | "镇平县": "101180707", 996 | "内乡县": "101180706", 997 | "淅川县": "101180708", 998 | "社旗县": "101180704", 999 | "唐河县": "101180710", 1000 | "新野县": "101180709", 1001 | "桐柏县": "101180712", 1002 | "石龙区": "101180508", 1003 | "舞钢市": "101180506", 1004 | "汝州市": "101180504", 1005 | "宝丰县": "101180503", 1006 | "叶县": "101180505", 1007 | "鲁山县": "101180507", 1008 | "郏县": "101180502", 1009 | "义马市": "101181705", 1010 | "灵宝市": "101181702", 1011 | "渑池县": "101181703", 1012 | "陕州区": "101181708", 1013 | "卢氏县": "101181704", 1014 | "睢阳区": "101181010", 1015 | "永城市": "101181009", 1016 | "民权县": "101181004", 1017 | "睢县": "101181003", 1018 | "宁陵县": "101181007", 1019 | "虞城县": "101181005", 1020 | "柘城县": "101181006", 1021 | "夏邑县": "101181008", 1022 | "卫辉市": "101180305", 1023 | "辉县市": "101180304", 1024 | "获嘉县": "101180302", 1025 | "原阳县": "101180303", 1026 | "延津县": "101180306", 1027 | "封丘县": "101180307", 1028 | "长垣县": "101180308", 1029 | "罗山县": "101180603", 1030 | "光山县": "101180604", 1031 | "新县": "101180605", 1032 | "商城县": "101180609", 1033 | "固始县": "101180608", 1034 | "潢川县": "101180607", 1035 | "淮滨县": "101180606", 1036 | "息县": "101180602", 1037 | "禹州市": "101180405", 1038 | "长葛市": "101180404", 1039 | "鄢陵县": "101180402", 1040 | "襄城县": "101180403", 1041 | "项城市": "101181407", 1042 | "扶沟县": "101181402", 1043 | "西华县": "101181405", 1044 | "商水县": "101181406", 1045 | "沈丘县": "101181410", 1046 | "郸城县": "101181408", 1047 | "淮阳县": "101181404", 1048 | "太康县": "101181403", 1049 | "鹿邑县": "101181409", 1050 | "西平县": "101181602", 1051 | "上蔡县": "101181604", 1052 | "平舆县": "101181607", 1053 | "正阳县": "101181610", 1054 | "确山县": "101181609", 1055 | "泌阳县": "101181606", 1056 | "汝南县": "101181605", 1057 | "遂平县": "101181603", 1058 | "新蔡县": "101181608", 1059 | "舞阳县": "101181503", 1060 | "临颍县": "101181502", 1061 | "清丰县": "101181304", 1062 | "南乐县": "101181303", 1063 | "范县": "101181305", 1064 | "台前县": "101181302", 1065 | "阿城区": "101050104", 1066 | "呼兰区": "101050103", 1067 | "尚志市": "101050111", 1068 | "双城市": "101050102", 1069 | "五常市": "101050112", 1070 | "方正县": "101050109", 1071 | "宾县": "101050105", 1072 | "依兰县": "101050106", 1073 | "巴彦县": "101050107", 1074 | "通河县": "101050108", 1075 | "木兰县": "101050113", 1076 | "延寿县": "101050110", 1077 | "肇州县": "101050903", 1078 | "肇源县": "101050904", 1079 | "林甸县": "101050902", 1080 | "杜尔伯特": "101050905", 1081 | "呼玛县": "101050704", 1082 | "漠河县": "101050703", 1083 | "塔河县": "101050702", 1084 | "萝北县": "101051203", 1085 | "绥滨县": "101051202", 1086 | "五大连池市": "101050605", 1087 | "北安市": "101050606", 1088 | "嫩江县": "101050602", 1089 | "逊克县": "101050604", 1090 | "孙吴县": "101050603", 1091 | "虎林市": "101051102", 1092 | "密山市": "101051103", 1093 | "鸡东县": "101051104", 1094 | "同江市": "101050406", 1095 | "富锦市": "101050407", 1096 | "桦南县": "101050405", 1097 | "桦川县": "101050404", 1098 | "汤原县": "101050402", 1099 | "抚远市": "101050403", 1100 | "绥芬河市": "101050305", 1101 | "海林市": "101050302", 1102 | "宁安市": "101050306", 1103 | "穆棱市": "101050303", 1104 | "东宁市": "101050307", 1105 | "林口县": "101050304", 1106 | "勃利县": "101051003", 1107 | "讷河市": "101050202", 1108 | "龙江县": "101050203", 1109 | "依安县": "101050206", 1110 | "泰来县": "101050210", 1111 | "甘南县": "101050204", 1112 | "富裕县": "101050205", 1113 | "克山县": "101050208", 1114 | "克东县": "101050209", 1115 | "拜泉县": "101050207", 1116 | "集贤县": "101051302", 1117 | "友谊县": "101051305", 1118 | "宝清县": "101051303", 1119 | "饶河县": "101051304", 1120 | "安达市": "101050503", 1121 | "肇东市": "101050502", 1122 | "海伦市": "101050504", 1123 | "望奎县": "101050506", 1124 | "兰西县": "101050507", 1125 | "青冈县": "101050508", 1126 | "庆安县": "101050509", 1127 | "明水县": "101050505", 1128 | "绥棱县": "101050510", 1129 | "五营区": "101050803", 1130 | "乌伊岭区": "101050802", 1131 | "铁力市": "101050804", 1132 | "嘉荫县": "101050805", 1133 | "东西湖区": "101200106", 1134 | "蔡甸区": "101200102", 1135 | "江夏区": "101200105", 1136 | "黄陂区": "101200103", 1137 | "新洲区": "101200104", 1138 | "梁子湖区": "101200302", 1139 | "麻城市": "101200503", 1140 | "武穴市": "101200509", 1141 | "团风县": "101200510", 1142 | "红安县": "101200502", 1143 | "罗田县": "101200504", 1144 | "英山县": "101200505", 1145 | "浠水县": "101200506", 1146 | "蕲春县": "101200507", 1147 | "黄梅县": "101200508", 1148 | "西塞山区": "101200606", 1149 | "下陆区": "101200605", 1150 | "铁山区": "101200604", 1151 | "大冶市": "101200602", 1152 | "阳新县": "101200603", 1153 | "掇刀区": "101201404", 1154 | "钟祥市": "101201402", 1155 | "京山县": "101201403", 1156 | "沙洋县": "101201405", 1157 | "石首市": "101200804", 1158 | "洪湖市": "101200806", 1159 | "松滋市": "101200807", 1160 | "公安县": "101200803", 1161 | "监利县": "101200805", 1162 | "江陵县": "101200802", 1163 | "张湾区": "101201109", 1164 | "茅箭区": "101201108", 1165 | "丹江口市": "101201107", 1166 | "郧阳区": "101201104", 1167 | "郧西县": "101201103", 1168 | "竹山县": "101201105", 1169 | "竹溪县": "101201102", 1170 | "房县": "101201106", 1171 | "广水市": "101201302", 1172 | "赤壁市": "101200702", 1173 | "嘉鱼县": "101200703", 1174 | "通城县": "101200705", 1175 | "崇阳县": "101200704", 1176 | "通山县": "101200706", 1177 | "襄州区": "101200202", 1178 | "老河口市": "101200206", 1179 | "枣阳市": "101200208", 1180 | "宜城市": "101200205", 1181 | "南漳县": "101200204", 1182 | "谷城县": "101200207", 1183 | "保康县": "101200203", 1184 | "应城市": "101200405", 1185 | "安陆市": "101200402", 1186 | "汉川市": "101200406", 1187 | "孝昌县": "101200407", 1188 | "大悟县": "101200404", 1189 | "云梦县": "101200403", 1190 | "长阳县": "101200908", 1191 | "五峰县": "101200906", 1192 | "夷陵区": "101200912", 1193 | "宜都市": "101200909", 1194 | "当阳市": "101200907", 1195 | "枝江市": "101200910", 1196 | "远安县": "101200902", 1197 | "兴山县": "101200904", 1198 | "秭归县": "101200903", 1199 | "利川市": "101201002", 1200 | "建始县": "101201003", 1201 | "巴东县": "101201008", 1202 | "宣恩县": "101201005", 1203 | "咸丰县": "101201004", 1204 | "来凤县": "101201007", 1205 | "鹤峰县": "101201006", 1206 | "浏阳市": "101250103", 1207 | "长沙县": "101250106", 1208 | "望城区": "101250105", 1209 | "宁乡县": "101250102", 1210 | "武陵源区": "101251104", 1211 | "慈利县": "101251103", 1212 | "桑植县": "101251102", 1213 | "津市市": "101250608", 1214 | "安乡县": "101250602", 1215 | "汉寿县": "101250604", 1216 | "澧县": "101250605", 1217 | "临澧县": "101250606", 1218 | "桃源县": "101250603", 1219 | "石门县": "101250607", 1220 | "苏仙区": "101250512", 1221 | "资兴市": "101250507", 1222 | "桂阳县": "101250502", 1223 | "宜章县": "101250504", 1224 | "永兴县": "101250510", 1225 | "嘉禾县": "101250503", 1226 | "临武县": "101250505", 1227 | "汝城县": "101250508", 1228 | "桂东县": "101250511", 1229 | "安仁县": "101250509", 1230 | "南岳区": "101250409", 1231 | "耒阳市": "101250408", 1232 | "常宁市": "101250406", 1233 | "衡阳县": "101250405", 1234 | "衡南县": "101250407", 1235 | "衡山县": "101250402", 1236 | "衡东县": "101250403", 1237 | "祁东县": "101250404", 1238 | "鹤城区": "101251202", 1239 | "靖州县": "101251205", 1240 | "麻阳县": "101251208", 1241 | "通道县": "101251207", 1242 | "新晃县": "101251209", 1243 | "芷江治县": "101251210", 1244 | "沅陵县": "101251203", 1245 | "辰溪县": "101251204", 1246 | "溆浦县": "101251211", 1247 | "中方县": "101251212", 1248 | "会同县": "101251206", 1249 | "洪江市": "101251213", 1250 | "冷水江市": "101250803", 1251 | "涟源市": "101250806", 1252 | "双峰县": "101250802", 1253 | "新化县": "101250805", 1254 | "城步县": "101250909", 1255 | "武冈市": "101250908", 1256 | "邵东县": "101250905", 1257 | "新邵县": "101250904", 1258 | "邵阳县": "101250910", 1259 | "隆回县": "101250902", 1260 | "洞口县": "101250903", 1261 | "绥宁县": "101250906", 1262 | "新宁县": "101250907", 1263 | "湘乡市": "101250203", 1264 | "韶山市": "101250202", 1265 | "吉首市": "101251501", 1266 | "泸溪县": "101251506", 1267 | "凤凰县": "101251505", 1268 | "花垣县": "101251508", 1269 | "保靖县": "101251502", 1270 | "古丈县": "101251504", 1271 | "永顺县": "101251503", 1272 | "龙山县": "101251507", 1273 | "赫山区": "101250701", 1274 | "沅江市": "101250705", 1275 | "南县": "101250702", 1276 | "桃江县": "101250703", 1277 | "安化县": "101250704", 1278 | "江华瑶族自治县": "101251410", 1279 | "祁阳县": "101251402", 1280 | "东安县": "101251403", 1281 | "双牌县": "101251404", 1282 | "道县": "101251405", 1283 | "江永县": "101251407", 1284 | "宁远县": "101251406", 1285 | "蓝山县": "101251408", 1286 | "新田县": "101251409", 1287 | "汨罗市": "101251004", 1288 | "临湘市": "101251006", 1289 | "华容县": "101251002", 1290 | "湘阴县": "101251003", 1291 | "平江县": "101251005", 1292 | "醴陵市": "101250303", 1293 | "荷塘区": "101250304", 1294 | "攸县": "101250302", 1295 | "茶陵县": "101250305", 1296 | "炎陵县": "101250306", 1297 | "双阳区": "101060106", 1298 | "德惠市": "101060103", 1299 | "九台市": "101060104", 1300 | "榆树市": "101060105", 1301 | "农安县": "101060102", 1302 | "蛟河市": "101060204", 1303 | "桦甸市": "101060206", 1304 | "舒兰市": "101060202", 1305 | "磐石市": "101060205", 1306 | "永吉县": "101060203", 1307 | "洮南市": "101060602", 1308 | "大安市": "101060603", 1309 | "镇赉县": "101060604", 1310 | "通榆县": "101060605", 1311 | "江源区": "101060907", 1312 | "长白县": "101060905", 1313 | "临江市": "101060903", 1314 | "抚松县": "101060906", 1315 | "靖宇县": "101060902", 1316 | "东丰县": "101060702", 1317 | "东辽县": "101060703", 1318 | "伊通满族自治县": "101060405", 1319 | "公主岭市": "101060404", 1320 | "双辽市": "101060402", 1321 | "梨树县": "101060403", 1322 | "前郭县": "101060803", 1323 | "长岭县": "101060804", 1324 | "乾安县": "101060802", 1325 | "扶余市": "101060805", 1326 | "梅河口市": "101060502", 1327 | "集安市": "101060505", 1328 | "通化县": "101060506", 1329 | "辉南县": "101060504", 1330 | "柳河县": "101060503", 1331 | "延吉市": "101060301", 1332 | "图们市": "101060309", 1333 | "敦化市": "101060302", 1334 | "珲春市": "101060308", 1335 | "龙井市": "101060307", 1336 | "和龙市": "101060305", 1337 | "安图县": "101060303", 1338 | "汪清县": "101060304", 1339 | "浦口区": "101190107", 1340 | "江宁区": "101190104", 1341 | "六合区": "101190105", 1342 | "溧水区": "101190102", 1343 | "高淳区": "101190103", 1344 | "吴中区": "101190405", 1345 | "昆山市": "101190404", 1346 | "常熟市": "101190402", 1347 | "张家港市": "101190403", 1348 | "塔城市": "101131101", 1349 | "吴江区": "101190407", 1350 | "太仓市": "101190408", 1351 | "锡山区": "101190204", 1352 | "江阴市": "101190202", 1353 | "宜兴市": "101190203", 1354 | "武进区": "101191104", 1355 | "溧阳市": "101191102", 1356 | "金坛区": "101191103", 1357 | "淮安区": "101190908", 1358 | "淮阴区": "101190906", 1359 | "涟水县": "101190905", 1360 | "洪泽区": "101190904", 1361 | "盱眙县": "101190903", 1362 | "金湖县": "101190902", 1363 | "赣榆区": "101191003", 1364 | "东海县": "101191002", 1365 | "灌云县": "101191004", 1366 | "灌南县": "101191005", 1367 | "启东市": "101190507", 1368 | "如皋市": "101190503", 1369 | "海门市": "101190508", 1370 | "海安县": "101190502", 1371 | "如东县": "101190504", 1372 | "宿豫区": "101191305", 1373 | "沭阳县": "101191302", 1374 | "泗阳县": "101191303", 1375 | "泗洪县": "101191304", 1376 | "兴化市": "101191202", 1377 | "靖江市": "101191205", 1378 | "泰兴市": "101191203", 1379 | "姜堰区": "101191204", 1380 | "新沂市": "101190807", 1381 | "邳州市": "101190805", 1382 | "丰县": "101190803", 1383 | "沛县": "101190804", 1384 | "铜山区": "101190802", 1385 | "睢宁县": "101190806", 1386 | "盐都区": "101190709", 1387 | "东台市": "101190707", 1388 | "大丰区": "101190708", 1389 | "响水县": "101190702", 1390 | "滨海县": "101190703", 1391 | "阜宁县": "101190704", 1392 | "射阳县": "101190705", 1393 | "建湖县": "101190706", 1394 | "邗江区": "101190606", 1395 | "仪征市": "101190603", 1396 | "高邮市": "101190604", 1397 | "江都市": "101190605", 1398 | "宝应县": "101190602", 1399 | "丹徒区": "101190305", 1400 | "丹阳市": "101190302", 1401 | "扬中市": "101190303", 1402 | "句容市": "101190304", 1403 | "南昌县": "101240103", 1404 | "新建区": "101240102", 1405 | "安义县": "101240104", 1406 | "进贤县": "101240105", 1407 | "南城县": "101240408", 1408 | "黎川县": "101240410", 1409 | "南丰县": "101240409", 1410 | "崇仁县": "101240404", 1411 | "乐安县": "101240403", 1412 | "宜黄县": "101240407", 1413 | "金溪县": "101240405", 1414 | "资溪县": "101240406", 1415 | "东乡县": "101240411", 1416 | "广昌县": "101240402", 1417 | "于都县": "101240710", 1418 | "瑞金市": "101240709", 1419 | "南康市": "101240704", 1420 | "赣县": "101240718", 1421 | "信丰县": "101240706", 1422 | "大余县": "101240705", 1423 | "上犹县": "101240703", 1424 | "崇义县": "101240702", 1425 | "安远县": "101240712", 1426 | "龙南县": "101240714", 1427 | "定南县": "101240715", 1428 | "全南县": "101240713", 1429 | "宁都县": "101240707", 1430 | "兴国县": "101240717", 1431 | "会昌县": "101240711", 1432 | "寻乌县": "101240716", 1433 | "石城县": "101240708", 1434 | "安福县": "101240612", 1435 | "井冈山市": "101240608", 1436 | "吉安县": "101240602", 1437 | "吉水县": "101240603", 1438 | "峡江县": "101240605", 1439 | "新干县": "101240604", 1440 | "永丰县": "101240606", 1441 | "泰和县": "101240611", 1442 | "遂川县": "101240610", 1443 | "万安县": "101240609", 1444 | "永新县": "101240607", 1445 | "乐平市": "101240802", 1446 | "浮梁县": "101240803", 1447 | "庐山市": "101240203", 1448 | "瑞昌市": "101240202", 1449 | "武宁县": "101240204", 1450 | "修水县": "101240212", 1451 | "永修县": "101240206", 1452 | "德安县": "101240205", 1453 | "星子县": "101240209", 1454 | "都昌县": "101240210", 1455 | "湖口县": "101240207", 1456 | "彭泽县": "101240208", 1457 | "安源区": "101240904", 1458 | "湘东区": "101240906", 1459 | "莲花县": "101240902", 1460 | "芦溪县": "101240905", 1461 | "上栗县": "101240903", 1462 | "德兴市": "101240307", 1463 | "上饶县": "101240308", 1464 | "广丰区": "101240313", 1465 | "玉山县": "101240312", 1466 | "铅山县": "101240311", 1467 | "横峰县": "101240310", 1468 | "弋阳县": "101240309", 1469 | "余干县": "101240305", 1470 | "鄱阳县": "101240302", 1471 | "万年县": "101240306", 1472 | "婺源县": "101240303", 1473 | "分宜县": "101241002", 1474 | "丰城市": "101240510", 1475 | "樟树市": "101240509", 1476 | "高安市": "101240508", 1477 | "奉新县": "101240507", 1478 | "万载县": "101240504", 1479 | "上高县": "101240505", 1480 | "宜丰县": "101240503", 1481 | "靖安县": "101240506", 1482 | "铜鼓县": "101240502", 1483 | "贵溪市": "101241103", 1484 | "余江县": "101241102", 1485 | "苏家屯区": "101070112", 1486 | "于洪区": "101070114", 1487 | "新民市": "101070106", 1488 | "辽中区": "101070103", 1489 | "康平县": "101070104", 1490 | "法库县": "101070105", 1491 | "旅顺口区": "101070205", 1492 | "金州区": "101070203", 1493 | "瓦房店市": "101070202", 1494 | "普兰店市": "101070204", 1495 | "庄河市": "101070207", 1496 | "长海县": "101070206", 1497 | "岫岩县": "101070303", 1498 | "海城市": "101070304", 1499 | "台安县": "101070302", 1500 | "本溪县": "101070502", 1501 | "桓仁县": "101070504", 1502 | "喀喇沁左翼蒙古族自治县": "101071204", 1503 | "北票市": "101071205", 1504 | "凌源市": "101071203", 1505 | "建平县": "101071207", 1506 | "宽甸县": "101070603", 1507 | "东港市": "101070604", 1508 | "凤城市": "101070602", 1509 | "清原县": "101070403", 1510 | "新宾县": "101070402", 1511 | "彰武县": "101070902", 1512 | "兴城市": "101071404", 1513 | "绥中县": "101071403", 1514 | "建昌县": "101071402", 1515 | "凌海市": "101070702", 1516 | "北镇市": "101070706", 1517 | "黑山县": "101070705", 1518 | "义县": "101070704", 1519 | "弓长岭区": "101071004", 1520 | "灯塔市": "101071003", 1521 | "辽阳县": "101071002", 1522 | "大洼区": "101071302", 1523 | "盘山县": "101071303", 1524 | "调兵山市": "101071105", 1525 | "开原市": "101071102", 1526 | "西丰县": "101071104", 1527 | "昌图县": "101071103", 1528 | "盖州市": "101070803", 1529 | "大石桥市": "101070802", 1530 | "清水河县": "101080105", 1531 | "土默特左旗": "101080102", 1532 | "托克托县": "101080103", 1533 | "和林格尔县": "101080104", 1534 | "武川县": "101080107", 1535 | "阿拉善左旗": "101081201", 1536 | "阿拉善右旗": "101081202", 1537 | "额济纳旗": "101081203", 1538 | "临河区": "101080801", 1539 | "五原县": "101080802", 1540 | "磴口县": "101080803", 1541 | "乌拉特前旗": "101080804", 1542 | "乌拉特中旗": "101080806", 1543 | "乌拉特后旗": "101080807", 1544 | "杭锦后旗": "101080810", 1545 | "石拐区": "101080211", 1546 | "白云鄂博": "101080202", 1547 | "土默特右旗": "101080204", 1548 | "固阳县": "101080205", 1549 | "达茂旗": "101080206", 1550 | "阿鲁科尔沁旗": "101080603", 1551 | "巴林左旗": "101080605", 1552 | "巴林右旗": "101080606", 1553 | "林西县": "101080607", 1554 | "克什克腾旗": "101080608", 1555 | "翁牛特旗": "101080609", 1556 | "喀喇沁旗": "101080611", 1557 | "宁城县": "101080613", 1558 | "敖汉旗": "101080614", 1559 | "东胜区": "101080713", 1560 | "达拉特旗": "101080703", 1561 | "准格尔旗": "101080704", 1562 | "鄂托克前旗": "101080705", 1563 | "鄂托克旗": "101080708", 1564 | "杭锦旗": "101080709", 1565 | "乌审旗": "101080710", 1566 | "伊金霍洛旗": "101080711", 1567 | "莫力达瓦": "101081004", 1568 | "满洲里市": "101081010", 1569 | "牙克石市": "101081011", 1570 | "扎兰屯市": "101081012", 1571 | "额尔古纳市": "101081014", 1572 | "根河市": "101081015", 1573 | "阿荣旗": "101081003", 1574 | "鄂伦春旗": "101081005", 1575 | "鄂温克族旗": "101081006", 1576 | "陈巴尔虎旗": "101081007", 1577 | "新巴尔虎左旗": "101081008", 1578 | "新巴尔虎右旗": "101081009", 1579 | "霍林郭勒市": "101080512", 1580 | "科尔沁左翼中旗": "101080503", 1581 | "科尔沁左翼后旗": "101080504", 1582 | "开鲁县": "101080506", 1583 | "库伦旗": "101080507", 1584 | "奈曼旗": "101080508", 1585 | "扎鲁特旗": "101080509", 1586 | "化德县": "101080403", 1587 | "集宁区": "101080401", 1588 | "丰镇市": "101080412", 1589 | "卓资县": "101080402", 1590 | "商都县": "101080404", 1591 | "兴和县": "101080406", 1592 | "凉城县": "101080407", 1593 | "察哈尔右翼前旗": "101080408", 1594 | "察哈尔右翼中旗": "101080409", 1595 | "察哈尔右翼后旗": "101080410", 1596 | "四子王旗": "101080411", 1597 | "二连浩特市": "101080903", 1598 | "锡林浩特市": "101080901", 1599 | "阿巴嘎旗": "101080904", 1600 | "苏尼特左旗": "101080906", 1601 | "苏尼特右旗": "101080907", 1602 | "东乌珠穆沁旗": "101080909", 1603 | "西乌珠穆沁旗": "101080910", 1604 | "太仆寺旗": "101080911", 1605 | "镶黄旗": "101080912", 1606 | "正镶白旗": "101080913", 1607 | "多伦县": "101080915", 1608 | "乌兰浩特市": "101081101", 1609 | "阿尔山市": "101081102", 1610 | "科尔沁右翼前旗": "101081109", 1611 | "科尔沁右翼中旗": "101081103", 1612 | "扎赉特旗": "101081105", 1613 | "突泉县": "101081107", 1614 | "灵武市": "101170103", 1615 | "永宁县": "101170102", 1616 | "贺兰县": "101170104", 1617 | "西吉县": "101170402", 1618 | "隆德县": "101170403", 1619 | "泾源县": "101170404", 1620 | "彭阳县": "101170406", 1621 | "惠农区": "101170202", 1622 | "大武口区": "101170205", 1623 | "陶乐": "101170204", 1624 | "平罗县": "101170203", 1625 | "青铜峡市": "101170306", 1626 | "盐池县": "101170303", 1627 | "同心县": "101170302", 1628 | "海原县": "101170504", 1629 | "中宁县": "101170502", 1630 | "湟中县": "101150104", 1631 | "湟源县": "101150103", 1632 | "大通县": "101150102", 1633 | "玛沁县": "101150501", 1634 | "班玛县": "101150502", 1635 | "甘德县": "101150503", 1636 | "达日县": "101150504", 1637 | "久治县": "101150505", 1638 | "玛多县": "101150506", 1639 | "海晏县": "101150801", 1640 | "祁连县": "101150803", 1641 | "刚察县": "101150806", 1642 | "门源县": "101150802", 1643 | "平安县": "101150208", 1644 | "乐都区": "101150202", 1645 | "民和县": "101150203", 1646 | "互助县": "101150204", 1647 | "化隆县": "101150205", 1648 | "循化县": "101150206", 1649 | "同德县": "101150408", 1650 | "贵德县": "101150404", 1651 | "兴海县": "101150406", 1652 | "贵南县": "101150407", 1653 | "格尔木市": "101150714", 1654 | "乌兰县": "101150709", 1655 | "都兰县": "101150715", 1656 | "天峻县": "101150708", 1657 | "同仁县": "101150301", 1658 | "尖扎县": "101150302", 1659 | "泽库县": "101150303", 1660 | "河南县": "101150304", 1661 | "杂多县": "101150604", 1662 | "称多县": "101150602", 1663 | "治多县": "101150603", 1664 | "囊谦县": "101150605", 1665 | "曲麻莱县": "101150606", 1666 | "长清区": "101120102", 1667 | "章丘市": "101120104", 1668 | "平阴县": "101120105", 1669 | "济阳县": "101120106", 1670 | "商河县": "101120103", 1671 | "崂山区": "101120202", 1672 | "胶州市": "101120205", 1673 | "即墨市": "101120204", 1674 | "平度市": "101120208", 1675 | "黄岛区": "101120206", 1676 | "莱西市": "101120207", 1677 | "惠民县": "101121105", 1678 | "阳信县": "101121104", 1679 | "无棣县": "101121103", 1680 | "沾化区": "101121106", 1681 | "博兴县": "101121102", 1682 | "邹平县": "101121107", 1683 | "兰陵县": "101120404", 1684 | "乐陵市": "101120406", 1685 | "禹城市": "101120411", 1686 | "宁津县": "101120409", 1687 | "庆云县": "101120407", 1688 | "临邑县": "101120403", 1689 | "齐河县": "101120405", 1690 | "平原县": "101120408", 1691 | "夏津县": "101120410", 1692 | "武城县": "101120402", 1693 | "河口区": "101121202", 1694 | "垦利区": "101121203", 1695 | "利津县": "101121204", 1696 | "广饶县": "101121205", 1697 | "曹县": "101121007", 1698 | "单县": "101121009", 1699 | "成武县": "101121008", 1700 | "巨野县": "101121006", 1701 | "郓城县": "101121003", 1702 | "鄄城县": "101121002", 1703 | "定陶区": "101121005", 1704 | "东明县": "101121004", 1705 | "曲阜市": "101120710", 1706 | "兖州市": "101120705", 1707 | "邹城市": "101120711", 1708 | "微山县": "101120703", 1709 | "鱼台县": "101120704", 1710 | "金乡县": "101120706", 1711 | "嘉祥县": "101120702", 1712 | "汶上县": "101120707", 1713 | "泗水县": "101120708", 1714 | "梁山县": "101120709", 1715 | "临清市": "101121707", 1716 | "阳谷县": "101121703", 1717 | "莘县": "101121709", 1718 | "茌平县": "101121705", 1719 | "东阿县": "101121706", 1720 | "冠县": "101121702", 1721 | "高唐县": "101121704", 1722 | "沂南县": "101120903", 1723 | "郯城县": "101120906", 1724 | "沂水县": "101120910", 1725 | "费县": "101120909", 1726 | "平邑县": "101120908", 1727 | "莒南县": "101120902", 1728 | "蒙阴县": "101120907", 1729 | "临沭县": "101120905", 1730 | "五莲县": "101121502", 1731 | "莒县": "101121503", 1732 | "泰山区": "101120803", 1733 | "新泰市": "101120802", 1734 | "肥城市": "101120804", 1735 | "宁阳县": "101120806", 1736 | "东平县": "101120805", 1737 | "荣成市": "101121303", 1738 | "乳山市": "101121304", 1739 | "文登市": "101121302", 1740 | "青州市": "101120602", 1741 | "诸城市": "101120609", 1742 | "寿光市": "101120603", 1743 | "安丘市": "101120607", 1744 | "高密市": "101120608", 1745 | "昌邑市": "101120606", 1746 | "临朐县": "101120604", 1747 | "昌乐县": "101120605", 1748 | "福山区": "101120508", 1749 | "牟平区": "101120509", 1750 | "龙口市": "101120505", 1751 | "莱阳市": "101120510", 1752 | "莱州市": "101120502", 1753 | "蓬莱市": "101120504", 1754 | "招远市": "101120506", 1755 | "栖霞市": "101120507", 1756 | "海阳市": "101120511", 1757 | "长岛县": "101120503", 1758 | "峄城区": "101121403", 1759 | "台儿庄区": "101121404", 1760 | "薛城区": "101121402", 1761 | "滕州市": "101121405", 1762 | "临淄区": "101120308", 1763 | "淄川区": "101120302", 1764 | "博山区": "101120303", 1765 | "周村区": "101120305", 1766 | "桓台县": "101120307", 1767 | "高青县": "101120304", 1768 | "沂源县": "101120306", 1769 | "清徐县": "101100102", 1770 | "阳曲县": "101100103", 1771 | "娄烦县": "101100104", 1772 | "古交市": "101100105", 1773 | "沁县": "101100508", 1774 | "潞城市": "101100504", 1775 | "襄垣县": "101100505", 1776 | "屯留县": "101100503", 1777 | "平顺县": "101100506", 1778 | "黎城县": "101100502", 1779 | "壶关县": "101100511", 1780 | "长子县": "101100509", 1781 | "武乡县": "101100507", 1782 | "沁源县": "101100510", 1783 | "阳高县": "101100202", 1784 | "天镇县": "101100204", 1785 | "广灵县": "101100205", 1786 | "灵丘县": "101100206", 1787 | "浑源县": "101100207", 1788 | "左云县": "101100208", 1789 | "大同县": "101100203", 1790 | "高平市": "101100605", 1791 | "沁水县": "101100602", 1792 | "阳城县": "101100603", 1793 | "陵川县": "101100604", 1794 | "泽州县": "101100606", 1795 | "榆次区": "101100402", 1796 | "介休市": "101100412", 1797 | "榆社县": "101100403", 1798 | "左权县": "101100404", 1799 | "和顺县": "101100405", 1800 | "昔阳县": "101100406", 1801 | "寿阳县": "101100407", 1802 | "太谷县": "101100408", 1803 | "祁县": "101100409", 1804 | "平遥县": "101100410", 1805 | "灵石县": "101100411", 1806 | "侯马市": "101100714", 1807 | "霍州市": "101100711", 1808 | "曲沃县": "101100702", 1809 | "翼城县": "101100713", 1810 | "襄汾县": "101100707", 1811 | "洪洞县": "101100710", 1812 | "吉县": "101100706", 1813 | "安泽县": "101100716", 1814 | "浮山县": "101100715", 1815 | "古县": "101100717", 1816 | "乡宁县": "101100712", 1817 | "大宁县": "101100705", 1818 | "隰县": "101100704", 1819 | "永和县": "101100703", 1820 | "蒲县": "101100708", 1821 | "汾西县": "101100709", 1822 | "离石区": "101101101", 1823 | "孝义市": "101101110", 1824 | "汾阳市": "101101111", 1825 | "文水县": "101101112", 1826 | "交城县": "101101113", 1827 | "兴县": "101101103", 1828 | "临县": "101101102", 1829 | "柳林县": "101101105", 1830 | "石楼县": "101101106", 1831 | "岚县": "101101104", 1832 | "方山县": "101101107", 1833 | "中阳县": "101101109", 1834 | "交口县": "101101108", 1835 | "平鲁区": "101100902", 1836 | "山阴县": "101100903", 1837 | "应县": "101100905", 1838 | "右玉县": "101100904", 1839 | "怀仁县": "101100906", 1840 | "原平市": "101101015", 1841 | "定襄县": "101101002", 1842 | "五台县": "101101003", 1843 | "代县": "101101008", 1844 | "繁峙县": "101101009", 1845 | "宁武县": "101101007", 1846 | "静乐县": "101101012", 1847 | "神池县": "101101006", 1848 | "五寨县": "101101014", 1849 | "岢岚县": "101101013", 1850 | "河曲县": "101101004", 1851 | "保德县": "101101011", 1852 | "偏关县": "101101005", 1853 | "平定县": "101100303", 1854 | "盂县": "101100302", 1855 | "永济市": "101100810", 1856 | "河津市": "101100805", 1857 | "临猗县": "101100802", 1858 | "万荣县": "101100804", 1859 | "闻喜县": "101100808", 1860 | "稷山县": "101100803", 1861 | "新绛县": "101100806", 1862 | "绛县": "101100807", 1863 | "垣曲县": "101100809", 1864 | "夏县": "101100812", 1865 | "平陆县": "101100813", 1866 | "芮城县": "101100811", 1867 | "临潼区": "101110103", 1868 | "长安区": "101090119", 1869 | "蓝田县": "101110104", 1870 | "周至县": "101110105", 1871 | "户县": "101110106", 1872 | "高陵区": "101110107", 1873 | "汉阴县": "101110704", 1874 | "石泉县": "101110703", 1875 | "宁陕县": "101110710", 1876 | "紫阳县": "101110702", 1877 | "岚皋县": "101110706", 1878 | "平利县": "101110707", 1879 | "镇坪县": "101110709", 1880 | "旬阳县": "101110705", 1881 | "白河县": "101110708", 1882 | "陈仓区": "101110912", 1883 | "凤翔县": "101110906", 1884 | "岐山县": "101110905", 1885 | "扶风县": "101110907", 1886 | "眉县": "101110908", 1887 | "陇县": "101110911", 1888 | "千阳县": "101110903", 1889 | "麟游县": "101110904", 1890 | "凤县": "101110910", 1891 | "太白县": "101110909", 1892 | "南郑县": "101110810", 1893 | "城固县": "101110806", 1894 | "洋县": "101110805", 1895 | "西乡县": "101110807", 1896 | "勉县": "101110803", 1897 | "宁强县": "101110809", 1898 | "略阳县": "101110802", 1899 | "镇巴县": "101110811", 1900 | "留坝县": "101110804", 1901 | "佛坪县": "101110808", 1902 | "商州区": "101110604", 1903 | "洛南县": "101110602", 1904 | "丹凤县": "101110606", 1905 | "商南县": "101110607", 1906 | "山阳县": "101110608", 1907 | "镇安县": "101110605", 1908 | "柞水县": "101110603", 1909 | "耀州区": "101111004", 1910 | "宜君县": "101111003", 1911 | "韩城市": "101110510", 1912 | "华阴市": "101110511", 1913 | "华县": "101110502", 1914 | "潼关县": "101110503", 1915 | "大荔县": "101110504", 1916 | "合阳县": "101110509", 1917 | "澄城县": "101110508", 1918 | "蒲城县": "101110507", 1919 | "白水县": "101110505", 1920 | "富平县": "101110506", 1921 | "兴平市": "101110211", 1922 | "三原县": "101110201", 1923 | "泾阳县": "101110205", 1924 | "乾县": "101110207", 1925 | "礼泉县": "101110202", 1926 | "永寿县": "101110203", 1927 | "彬县": "101110208", 1928 | "长武县": "101110209", 1929 | "旬邑县": "101110210", 1930 | "淳化县": "101110204", 1931 | "武功县": "101110206", 1932 | "吴起县": "101110312", 1933 | "延长县": "101110301", 1934 | "延川县": "101110302", 1935 | "子长县": "101110303", 1936 | "安塞区": "101110307", 1937 | "志丹县": "101110306", 1938 | "甘泉县": "101110308", 1939 | "富县": "101110305", 1940 | "洛川县": "101110309", 1941 | "宜川县": "101110304", 1942 | "黄龙县": "101110311", 1943 | "黄陵县": "101110310", 1944 | "榆阳区": "101110413", 1945 | "神木县": "101110403", 1946 | "府谷县": "101110402", 1947 | "横山区": "101110407", 1948 | "靖边县": "101110406", 1949 | "定边县": "101110405", 1950 | "绥德县": "101110410", 1951 | "米脂县": "101110408", 1952 | "佳县": "101110404", 1953 | "吴堡县": "101110411", 1954 | "清涧县": "101110412", 1955 | "子洲县": "101110409", 1956 | "闵行区": "101020200", 1957 | "浦东新区": "101020600", 1958 | "松江区": "101020900", 1959 | "嘉定区": "101020500", 1960 | "宝山区": "101020300", 1961 | "青浦区": "101020800", 1962 | "金山区": "101020700", 1963 | "奉贤区": "101021000", 1964 | "崇明区": "101021100", 1965 | "龙泉驿区": "101270102", 1966 | "青白江区": "101270115", 1967 | "新都区": "101270103", 1968 | "温江区": "101270104", 1969 | "都江堰市": "101270111", 1970 | "彭州市": "101270112", 1971 | "邛崃市": "101270113", 1972 | "崇州市": "101270114", 1973 | "金堂县": "101270105", 1974 | "双流区": "101270106", 1975 | "郫县": "101270107", 1976 | "大邑县": "101270108", 1977 | "蒲江县": "101270109", 1978 | "新津县": "101270110", 1979 | "江油市": "101270408", 1980 | "盐亭县": "101270403", 1981 | "三台县": "101270402", 1982 | "平武县": "101270407", 1983 | "安县": "101270404", 1984 | "梓潼县": "101270405", 1985 | "北川县": "101270406", 1986 | "马尔康市": "101271910", 1987 | "汶川县": "101271902", 1988 | "理县": "101271903", 1989 | "茂县": "101271904", 1990 | "松潘县": "101271905", 1991 | "九寨沟县": "101271906", 1992 | "金川县": "101271907", 1993 | "小金县": "101271908", 1994 | "黑水县": "101271909", 1995 | "壤塘县": "101271911", 1996 | "若尔盖县": "101271912", 1997 | "红原县": "101271913", 1998 | "通江县": "101270902", 1999 | "南江县": "101270903", 2000 | "平昌县": "101270904", 2001 | "万源市": "101270606", 2002 | "达川区": "101270608", 2003 | "宣汉县": "101270602", 2004 | "开江县": "101270603", 2005 | "大竹县": "101270604", 2006 | "渠县": "101270605", 2007 | "广汉市": "101272003", 2008 | "什邡市": "101272004", 2009 | "绵竹市": "101272005", 2010 | "罗江区": "101272006", 2011 | "中江县": "101272002", 2012 | "康定市": "101271802", 2013 | "丹巴县": "101271804", 2014 | "泸定县": "101271803", 2015 | "炉霍县": "101271808", 2016 | "九龙县": "101271805", 2017 | "雅江县": "101271806", 2018 | "新龙县": "101271809", 2019 | "道孚县": "101271807", 2020 | "白玉县": "101271811", 2021 | "理塘县": "101271814", 2022 | "德格县": "101271810", 2023 | "乡城县": "101271816", 2024 | "石渠县": "101271812", 2025 | "稻城县": "101271817", 2026 | "色达县": "101271813", 2027 | "巴塘县": "101271815", 2028 | "得荣县": "101271818", 2029 | "华蓥市": "101270805", 2030 | "岳池县": "101270802", 2031 | "武胜县": "101270803", 2032 | "邻水县": "101270804", 2033 | "旺苍县": "101272102", 2034 | "青川县": "101272103", 2035 | "剑阁县": "101272104", 2036 | "苍溪县": "101272105", 2037 | "峨眉山市": "101271408", 2038 | "犍为县": "101271402", 2039 | "井研县": "101271403", 2040 | "夹江县": "101271404", 2041 | "沐川县": "101271405", 2042 | "峨边县": "101271406", 2043 | "马边县": "101271407", 2044 | "西昌市": "101271610", 2045 | "盐源县": "101271604", 2046 | "德昌县": "101271605", 2047 | "会理县": "101271606", 2048 | "会东县": "101271607", 2049 | "宁南县": "101271608", 2050 | "普格县": "101271609", 2051 | "布拖县": "101271619", 2052 | "金阳县": "101271611", 2053 | "昭觉县": "101271612", 2054 | "喜德县": "101271613", 2055 | "冕宁县": "101271614", 2056 | "越西县": "101271615", 2057 | "甘洛县": "101271616", 2058 | "美姑县": "101271618", 2059 | "雷波县": "101271617", 2060 | "木里县": "101271603", 2061 | "仁寿县": "101271502", 2062 | "彭山区": "101271503", 2063 | "洪雅县": "101271504", 2064 | "丹棱县": "101271505", 2065 | "青神县": "101271506", 2066 | "阆中市": "101270507", 2067 | "南部县": "101270502", 2068 | "营山县": "101270503", 2069 | "蓬安县": "101270504", 2070 | "仪陇县": "101270505", 2071 | "西充县": "101270506", 2072 | "东兴区": "101271202", 2073 | "威远县": "101271203", 2074 | "资中县": "101271204", 2075 | "隆昌县": "101271205", 2076 | "仁和区": "101270202", 2077 | "米易县": "101270203", 2078 | "盐边县": "101270204", 2079 | "蓬溪县": "101270702", 2080 | "射洪县": "101270703", 2081 | "名山区": "101271702", 2082 | "荥经县": "101271703", 2083 | "汉源县": "101271704", 2084 | "石棉县": "101271705", 2085 | "天全县": "101271706", 2086 | "芦山县": "101271707", 2087 | "宝兴县": "101271708", 2088 | "叙州区": "101271103", 2089 | "南溪区": "101271104", 2090 | "江安县": "101271105", 2091 | "长宁县": "101271106", 2092 | "高县": "101271107", 2093 | "珙县": "101271108", 2094 | "筠连县": "101271109", 2095 | "兴文县": "101271110", 2096 | "屏山县": "101271111", 2097 | "简阳市": "101270121", 2098 | "安岳县": "101271302", 2099 | "乐至县": "101271303", 2100 | "荣县": "101270303", 2101 | "富顺县": "101270302", 2102 | "纳溪区": "101271007", 2103 | "泸县": "101271003", 2104 | "合江县": "101271004", 2105 | "叙永县": "101271005", 2106 | "古蔺县": "101271006", 2107 | "东丽区": "101030400", 2108 | "津南区": "101031000", 2109 | "西青区": "101030500", 2110 | "北辰区": "101030600", 2111 | "滨海新区": "101031100", 2112 | "和平区": "101030800", 2113 | "河东区": "101031200", 2114 | "武清区": "101030200", 2115 | "宝坻区": "101030300", 2116 | "宁河区": "101030700", 2117 | "静海区": "101030900", 2118 | "蓟州区": "101031400", 2119 | "林周县": "101140104", 2120 | "当雄县": "101140102", 2121 | "尼木县": "101140103", 2122 | "曲水县": "101140106", 2123 | "堆龙德庆区": "101140105", 2124 | "达孜县": "101140107", 2125 | "墨竹工卡县": "101140108", 2126 | "噶尔县": "101140707", 2127 | "普兰县": "101140705", 2128 | "札达县": "101140706", 2129 | "日土县": "101140708", 2130 | "革吉县": "101140709", 2131 | "改则县": "101140702", 2132 | "措勤县": "101140710", 2133 | "江达县": "101140509", 2134 | "贡觉县": "101140511", 2135 | "类乌齐县": "101140507", 2136 | "丁青县": "101140502", 2137 | "察雅县": "101140510", 2138 | "八宿县": "101140508", 2139 | "左贡县": "101140505", 2140 | "芒康县": "101140506", 2141 | "洛隆县": "101140504", 2142 | "边坝县": "101140503", 2143 | "工布江达县": "101140405", 2144 | "米林县": "101140403", 2145 | "墨脱县": "101140407", 2146 | "波密县": "101140402", 2147 | "察隅县": "101140404", 2148 | "朗县": "101140406", 2149 | "嘉黎县": "101140603", 2150 | "比如县": "101140609", 2151 | "聂荣县": "101140607", 2152 | "安多县": "101140605", 2153 | "申扎县": "101140611", 2154 | "索县": "101140606", 2155 | "班戈县": "101140604", 2156 | "巴青县": "101140608", 2157 | "尼玛县": "101140602", 2158 | "南木林县": "101140203", 2159 | "江孜县": "101140206", 2160 | "定日县": "101140205", 2161 | "萨迦县": "101140213", 2162 | "拉孜县": "101140202", 2163 | "昂仁县": "101140211", 2164 | "谢通门县": "101140214", 2165 | "白朗县": "101140217", 2166 | "仁布县": "101140220", 2167 | "康马县": "101140219", 2168 | "定结县": "101140212", 2169 | "仲巴县": "101140208", 2170 | "亚东县": "101140218", 2171 | "吉隆县": "101140210", 2172 | "聂拉木县": "101140204", 2173 | "萨嘎县": "101140209", 2174 | "岗巴县": "101140216", 2175 | "乃东区": "101140309", 2176 | "扎囊县": "101140303", 2177 | "贡嘎县": "101140302", 2178 | "桑日县": "101140310", 2179 | "琼结县": "101140313", 2180 | "曲松县": "101140314", 2181 | "措美县": "101140312", 2182 | "洛扎县": "101140311", 2183 | "加查县": "101140304", 2184 | "隆子县": "101140307", 2185 | "错那县": "101140306", 2186 | "浪卡子县": "101140305", 2187 | "达坂城区": "101130105", 2188 | "乌鲁木齐县": "101130113", 2189 | "温宿县": "101130803", 2190 | "库车县": "101130807", 2191 | "沙雅县": "101130806", 2192 | "新和县": "101130805", 2193 | "拜城县": "101130804", 2194 | "乌什县": "101130802", 2195 | "阿瓦提县": "101130809", 2196 | "柯坪县": "101130808", 2197 | "库尔勒": "101130601", 2198 | "轮台县": "101130602", 2199 | "尉犁县": "101130603", 2200 | "若羌县": "101130604", 2201 | "且末县": "101130605", 2202 | "焉耆县": "101130607", 2203 | "和静县": "101130606", 2204 | "和硕县": "101130608", 2205 | "博湖县": "101130612", 2206 | "博乐市": "101131601", 2207 | "精河县": "101131603", 2208 | "温泉县": "101131602", 2209 | "呼图壁县": "101130402", 2210 | "米泉": "101130403", 2211 | "阜康市": "101130404", 2212 | "玛纳斯县": "101130407", 2213 | "奇台县": "101130406", 2214 | "吉木萨尔县": "101130405", 2215 | "木垒县": "101130408", 2216 | "伊吾县": "101131204", 2217 | "巴里坤": "101131203", 2218 | "墨玉县": "101131304", 2219 | "皮山县": "101131302", 2220 | "洛浦县": "101131305", 2221 | "策勒县": "101131303", 2222 | "于田县": "101131307", 2223 | "民丰县": "101131306", 2224 | "疏附县": "101130911", 2225 | "疏勒县": "101130912", 2226 | "英吉沙县": "101130902", 2227 | "泽普县": "101130907", 2228 | "莎车县": "101130905", 2229 | "叶城县": "101130906", 2230 | "麦盖提县": "101130904", 2231 | "岳普湖县": "101130909", 2232 | "伽师县": "101130910", 2233 | "巴楚县": "101130908", 2234 | "塔什库尔干": "101130903", 2235 | "阿图什市": "101131501", 2236 | "阿克陶县": "101131503", 2237 | "阿合奇县": "101131504", 2238 | "乌恰县": "101131502", 2239 | "鄯善县": "101130504", 2240 | "托克逊县": "101130502", 2241 | "阿勒泰": "101131401", 2242 | "和布克赛尔": "101131104", 2243 | "伊宁市": "101131001", 2244 | "布尔津县": "101131406", 2245 | "奎屯市": "101131011", 2246 | "乌苏市": "101131106", 2247 | "额敏县": "101131103", 2248 | "富蕴县": "101131408", 2249 | "伊宁县": "101131004", 2250 | "福海县": "101131407", 2251 | "霍城县": "101131009", 2252 | "沙湾县": "101131107", 2253 | "巩留县": "101131005", 2254 | "哈巴河县": "101131402", 2255 | "托里县": "101131105", 2256 | "青河县": "101131409", 2257 | "新源县": "101131006", 2258 | "裕民县": "101131102", 2259 | "吉木乃县": "101131405", 2260 | "昭苏县": "101131007", 2261 | "特克斯县": "101131008", 2262 | "尼勒克县": "101131003", 2263 | "察布查尔": "101131002", 2264 | "东川区": "101290103", 2265 | "安宁市": "101290112", 2266 | "呈贡区": "101290108", 2267 | "晋宁县": "101290105", 2268 | "富民县": "101290109", 2269 | "宜良县": "101290106", 2270 | "嵩明县": "101290110", 2271 | "石林县": "101290107", 2272 | "禄劝县": "101290111", 2273 | "寻甸县": "101290104", 2274 | "兰坪县": "101291204", 2275 | "泸水市": "101291205", 2276 | "福贡县": "101291203", 2277 | "贡山县": "101291207", 2278 | "宁洱县": "101290912", 2279 | "思茅区": "101290905", 2280 | "墨江县": "101290906", 2281 | "景东县": "101290903", 2282 | "景谷县": "101290902", 2283 | "镇沅县": "101290911", 2284 | "江城县": "101290907", 2285 | "孟连县": "101290908", 2286 | "澜沧县": "101290904", 2287 | "西盟县": "101290909", 2288 | "宁蒗县": "101291404", 2289 | "永胜县": "101291402", 2290 | "华坪县": "101291403", 2291 | "施甸县": "101290504", 2292 | "腾冲市": "101290506", 2293 | "龙陵县": "101290503", 2294 | "昌宁县": "101290505", 2295 | "双柏县": "101290809", 2296 | "牟定县": "101290805", 2297 | "南华县": "101290806", 2298 | "姚安县": "101290804", 2299 | "大姚县": "101290802", 2300 | "永仁县": "101290810", 2301 | "元谋县": "101290803", 2302 | "武定县": "101290807", 2303 | "禄丰县": "101290808", 2304 | "祥云县": "101290207", 2305 | "宾川县": "101290205", 2306 | "弥渡县": "101290206", 2307 | "永平县": "101290204", 2308 | "云龙县": "101290202", 2309 | "洱源县": "101290210", 2310 | "剑川县": "101290209", 2311 | "鹤庆县": "101290211", 2312 | "漾濞县": "101290203", 2313 | "南涧县": "101290212", 2314 | "巍山县": "101290208", 2315 | "芒市": "101291508", 2316 | "瑞丽市": "101291506", 2317 | "梁河县": "101291507", 2318 | "盈江县": "101291504", 2319 | "陇川县": "101291503", 2320 | "香格里拉市": "101291301", 2321 | "德钦县": "101291302", 2322 | "维西县": "101291303", 2323 | "泸西县": "101290311", 2324 | "蒙自市": "101290309", 2325 | "个旧市": "101290308", 2326 | "开远市": "101290307", 2327 | "绿春县": "101290306", 2328 | "建水县": "101290303", 2329 | "石屏县": "101290302", 2330 | "弥勒市": "101290304", 2331 | "元阳县": "101290305", 2332 | "金平县": "101290312", 2333 | "河口县": "101290313", 2334 | "屏边县": "101290310", 2335 | "凤庆县": "101291105", 2336 | "云县": "101291107", 2337 | "永德县": "101291106", 2338 | "镇康县": "101291108", 2339 | "双江县": "101291104", 2340 | "耿马县": "101291103", 2341 | "沧源县": "101291102", 2342 | "宣威市": "101290409", 2343 | "马龙县": "101290405", 2344 | "陆良县": "101290403", 2345 | "师宗县": "101290406", 2346 | "罗平县": "101290407", 2347 | "富源县": "101290404", 2348 | "会泽县": "101290408", 2349 | "沾益区": "101290402", 2350 | "砚山县": "101290605", 2351 | "西畴县": "101290602", 2352 | "麻栗坡县": "101290604", 2353 | "马关县": "101290603", 2354 | "丘北县": "101290606", 2355 | "广南县": "101290607", 2356 | "富宁县": "101290608", 2357 | "景洪市": "101291601", 2358 | "勐海县": "101291603", 2359 | "勐腊县": "101291605", 2360 | "江川区": "101290703", 2361 | "澄江县": "101290702", 2362 | "通海县": "101290704", 2363 | "华宁县": "101290705", 2364 | "易门县": "101290707", 2365 | "峨山县": "101290708", 2366 | "新平县": "101290706", 2367 | "元江县": "101290709", 2368 | "鲁甸县": "101291002", 2369 | "巧家县": "101291006", 2370 | "盐津县": "101291009", 2371 | "大关县": "101291010", 2372 | "永善县": "101291008", 2373 | "绥江县": "101291007", 2374 | "镇雄县": "101291004", 2375 | "彝良县": "101291003", 2376 | "威信县": "101291005", 2377 | "水富县": "101291011", 2378 | "萧山区": "101210102", 2379 | "余杭区": "101210106", 2380 | "建德市": "101210105", 2381 | "富阳区": "101210108", 2382 | "临安市": "101210107", 2383 | "桐庐县": "101210103", 2384 | "淳安县": "101210104", 2385 | "德清县": "101210204", 2386 | "长兴县": "101210202", 2387 | "安吉县": "101210203", 2388 | "海宁市": "101210303", 2389 | "嘉善县": "101210302", 2390 | "平湖市": "101210305", 2391 | "桐乡市": "101210304", 2392 | "海盐县": "101210306", 2393 | "兰溪市": "101210903", 2394 | "义乌市": "101210904", 2395 | "加格达奇": "101050708", 2396 | "新林": "101050706", 2397 | "呼中": "101050705", 2398 | "东阳市": "101210905", 2399 | "永康市": "101210907", 2400 | "武义县": "101210906", 2401 | "浦江县": "101210902", 2402 | "磐安县": "101210908", 2403 | "龙泉市": "101210803", 2404 | "青田县": "101210805", 2405 | "缙云县": "101210804", 2406 | "遂昌县": "101210802", 2407 | "松阳县": "101210808", 2408 | "云和县": "101210806", 2409 | "庆元县": "101210807", 2410 | "景宁县": "101210809", 2411 | "镇海区": "101210412", 2412 | "北仑区": "101210410", 2413 | "鄞州区": "101210411", 2414 | "余姚市": "101210404", 2415 | "慈溪市": "101210403", 2416 | "奉化市": "101210405", 2417 | "象山县": "101210406", 2418 | "宁海县": "101210408", 2419 | "上虞区": "101210503", 2420 | "嵊州市": "101210505", 2421 | "越城区": "101210501", 2422 | "新昌县": "101210504", 2423 | "诸暨市": "101210502", 2424 | "椒江区": "101210611", 2425 | "黄岩区": "101210612", 2426 | "路桥区": "101210613", 2427 | "温岭市": "101210607", 2428 | "临海市": "101210610", 2429 | "玉环县": "101210603", 2430 | "三门县": "101210604", 2431 | "天台县": "101210605", 2432 | "仙居县": "101210606", 2433 | "瑞安市": "101210705", 2434 | "乐清市": "101210707", 2435 | "洞头区": "101210706", 2436 | "永嘉县": "101210708", 2437 | "平阳县": "101210704", 2438 | "苍南县": "101210709", 2439 | "文成县": "101210703", 2440 | "泰顺县": "101210702", 2441 | "定海区": "101211106", 2442 | "普陀区": "101021500", 2443 | "岱山县": "101211104", 2444 | "嵊泗县": "101211102", 2445 | "衢江区": "101211006", 2446 | "江山市": "101211005", 2447 | "常山县": "101211002", 2448 | "开化县": "101211003", 2449 | "龙游县": "101211004", 2450 | "合川区": "101040300", 2451 | "江津区": "101040500", 2452 | "南川区": "101040400", 2453 | "永川区": "101040200", 2454 | "渝北区": "101040700", 2455 | "万盛": "101040600", 2456 | "万州区": "101041300", 2457 | "北碚区": "101040800", 2458 | "沙坪坝区": "101043800", 2459 | "巴南区": "101040900", 2460 | "涪陵区": "101041400", 2461 | "黔江区": "101041100", 2462 | "长寿区": "101041000", 2463 | "綦江区": "101043300", 2464 | "潼南区": "101042100", 2465 | "铜梁区": "101042800", 2466 | "大足区": "101042600", 2467 | "荣昌区": "101042700", 2468 | "璧山区": "101042900", 2469 | "垫江县": "101042200", 2470 | "武隆县": "101043100", 2471 | "丰都县": "101043000", 2472 | "城口县": "101041600", 2473 | "梁平县": "101042300", 2474 | "开州区": "101044100", 2475 | "巫溪县": "101041800", 2476 | "巫山县": "101042000", 2477 | "奉节县": "101041900", 2478 | "云阳县": "101041700", 2479 | "忠县": "101042400", 2480 | "石柱县": "101042500", 2481 | "彭水县": "101043200", 2482 | "酉阳县": "101043400", 2483 | "秀山县": "101043600", 2484 | "九龙": "101320102", 2485 | "台北": "101340101", 2486 | "高雄": "101340201", 2487 | "台中": "101340401", 2488 | "台南": "101340203", 2489 | "新竹": "101340103", 2490 | "嘉义": "101340202", 2491 | "桃园": "101340102", 2492 | "苗栗": "101340402", 2493 | "彰化": "101340403", 2494 | "南投": "101340404", 2495 | "云林": "101340406", 2496 | "屏东": "101340205", 2497 | "台东县": "101340204", 2498 | "花莲": "101340405", 2499 | "合肥": "101220101", 2500 | "长丰县": "101220102", 2501 | "肥东县": "101220103", 2502 | "肥西县": "101220104" 2503 | } -------------------------------------------------------------------------------- /everyday_wechat/control/weather/rtweather.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | https://github.com/MZCretin/RollToolsApi#获取特定城市今日天气 4 | 获取特定城市今日天气 5 | """ 6 | import requests 7 | 8 | __all__ = ['get_rttodayweather'] 9 | 10 | 11 | # {"code":1,"msg":"数据返回成功","data":{"address":"广西壮族自治区 桂林市 全州县", 12 | # "cityCode":"450324","temp":"26℃","weather":"晴","windDirection":"东北","windPower":"≤3级", 13 | # "humidity":"58%","reportTime":"2019-06-14 10:49:37"}} 14 | 15 | def get_rttodayweather(cityname): 16 | """ 17 | 获取特定城市今日天气 18 | https://github.com/MZCretin/RollToolsApi#获取特定城市今日天气 19 | :param cityname:str 传入你需要查询的城市,请尽量传入完整值,否则系统会自行匹配,可能会有误差 20 | :return:str 天气(2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情) 21 | """ 22 | print('获取 {} 的天气...'.format(cityname)) 23 | try: 24 | # forecast 25 | resp = requests.get('https://www.mxnzp.com/api/weather/forecast/{}'.format(cityname)) 26 | print(resp.text) 27 | if resp.status_code == 200: 28 | content_dict = resp.json() 29 | if content_dict['code'] == 1: 30 | data_dict = content_dict['data'] 31 | address = data_dict['address'].strip() 32 | 33 | report_time = data_dict['reportTime'].strip() 34 | report_time = report_time.split(' ')[0] 35 | return_text = ' '.join( 36 | x for x in [ 37 | report_time, address, data_dict['weather'], data_dict['temp'], 38 | data_dict['windDirection'] + '风', data_dict['windPower'], 39 | '湿度:' + data_dict['humidity']] if x) 40 | # print(return_text) 41 | return return_text 42 | else: 43 | print('获取天气失败:{}'.format(content_dict['msg'])) 44 | # return None 45 | print('获取天气失败。') 46 | except Exception as exception: 47 | print(str(exception)) 48 | # return None 49 | # return None 50 | 51 | 52 | get_today_weather = get_rttodayweather 53 | 54 | 55 | 56 | if __name__ == '__main__': 57 | cityname = '香港' 58 | weather = get_today_weather(cityname) 59 | # print(weather) 60 | pass 61 | -------------------------------------------------------------------------------- /everyday_wechat/control/weather/sojson.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import requests 4 | import json 5 | import os 6 | from datetime import datetime 7 | from datetime import timedelta 8 | 9 | __all__ = ['get_sojson_weather', 'get_sojson_weather_tomorrow'] 10 | 11 | with open(os.path.join(os.path.dirname(__file__), '_city_sojson.json'), 'r', encoding='utf-8') as f: 12 | CITY_CODE_DICT = json.loads(f.read()) 13 | 14 | MSG_TOMORROW = '明日{city_name}天气\n{_date} {week}\n【明日天气】{_type}\n【明日气温】{low_temp} {high_temp}\n【明日风速】{speed}\n【出行提醒】{notice}' 15 | MSG_TODAY = '今日{city_name}天气\n{_date},{week}\n【今日天气】{_type}\n【今日气温】{low_temp} {high_temp}\n【今日风速】{speed}\n【出行提醒】{notice}' 16 | 17 | 18 | def get_sojson_weather(city_name, is_tomorrow=False): 19 | """ 20 | 获取天气信息。网址:https://www.sojson.com/blog/305.html . 21 | :param city_name: str,城市名 22 | :return: str ,例如:2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情 23 | """ 24 | if is_tomorrow: 25 | return get_sojson_weather_tomorrow(city_name) 26 | if not city_name: 27 | return None 28 | city_code = CITY_CODE_DICT.get(city_name, None) 29 | if not city_code: 30 | print('没有此城市的消息...') 31 | return None 32 | print('获取天气信息...') 33 | 34 | weather_url = 'http://t.weather.sojson.com/api/weather/city/{}'.format(city_code) 35 | try: 36 | resp = requests.get(url=weather_url) 37 | if resp.status_code == 200: 38 | # print(resp.text) 39 | weather_dict = resp.json() 40 | # 今日天气 41 | # { 42 | # "sunrise": "04:45", 43 | # "high": "高温 34.0℃", 44 | # "low": "低温 25.0℃", 45 | # "sunset": "19:37", 46 | # "aqi": 145, 47 | # "ymd": "2019-06-12", 48 | # "week": "星期三", 49 | # "fx": "西南风", 50 | # "fl": "3-4级", 51 | # "type": "多云", 52 | # "notice": "阴晴之间,谨防紫外线侵扰" 53 | # } 54 | if weather_dict.get('status') == 200: 55 | 56 | today_weather = weather_dict.get('data').get('forecast')[0] 57 | 58 | today_date = datetime.now().strftime('%Y-%m-%d') 59 | # 这个天气的接口更新不及时,有时候当天1点的时候,还是昨天的天气信息,如果天气不一致,则取下一天(今天)的数据 60 | weather_today = today_weather['ymd'] 61 | if today_date != weather_today: 62 | today_weather = weather_dict.get('data').get('forecast')[1] 63 | 64 | weather_info = MSG_TODAY.format( 65 | city_name=city_name, 66 | _date=today_weather['ymd'], 67 | week=today_weather['week'], 68 | _type=today_weather['type'], 69 | low_temp=today_weather['low'], 70 | high_temp=today_weather['high'], 71 | speed=today_weather['fx'] + today_weather['fl'], 72 | notice=today_weather['notice'], 73 | ) 74 | return weather_info 75 | else: 76 | print('天气请求出错:{}'.format(weather_dict.get('message'))) 77 | 78 | except Exception as exception: 79 | print(str(exception)) 80 | return None 81 | 82 | 83 | 84 | def get_sojson_weather_tomorrow(city_name): 85 | """ 86 | 获取明日天气信息。网址:https://www.sojson.com/blog/305.html . 87 | :param city_name: str,城市名 88 | :return: str ,例如:2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情 89 | """ 90 | if not city_name: 91 | return None 92 | city_code = CITY_CODE_DICT.get(city_name, None) 93 | if not city_code: 94 | print('没有此城市的消息...') 95 | return None 96 | print('获取天气信息...') 97 | 98 | weather_url = 'http://t.weather.sojson.com/api/weather/city/{}'.format(city_code) 99 | try: 100 | resp = requests.get(url=weather_url) 101 | # print(resp.text) 102 | if resp.status_code == 200: 103 | weather_dict = resp.json() 104 | if weather_dict.get('status') == 200: 105 | 106 | today_weather = weather_dict.get('data').get('forecast')[1] 107 | today_date = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d') 108 | # 这个天气的接口更新不及时,有时候当天1点的时候,还是昨天的天气信息,如果天气不一致,则取下一天(今天)的数据 109 | weather_today = today_weather['ymd'] 110 | if today_date != weather_today: 111 | today_weather = weather_dict.get('data').get('forecast')[2] 112 | # MSG_TOMORROW = '明日天气预报\n{city_name},{_date},{week}\n【明日天气】{_type}\n 113 | # 【明日温度】{low_temp} {high_temp}\n【明日风速】{speed}\n【出行提醒】{notice}' 114 | 115 | weather_info = MSG_TOMORROW.format( 116 | city_name=city_name, 117 | _date=today_weather['ymd'], 118 | week=today_weather['week'], 119 | _type=today_weather['type'], 120 | low_temp=today_weather['low'], 121 | high_temp=today_weather['high'], 122 | speed=today_weather['fx'] + today_weather['fl'], 123 | notice=today_weather['notice'], 124 | ) 125 | return weather_info 126 | else: 127 | print('天气请求出错:{}'.format(weather_dict.get('message'))) 128 | 129 | except Exception as exception: 130 | print(str(exception)) 131 | return None 132 | 133 | 134 | get_today_weather = get_sojson_weather 135 | 136 | if __name__ == '__main__': 137 | is_tomorrow = True 138 | we = get_sojson_weather('青岛', is_tomorrow) 139 | print(we) 140 | # pass 141 | -------------------------------------------------------------------------------- /everyday_wechat/main.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | """ 4 | 每天定时给多个女友发给微信暖心话 5 | 核心代码。 6 | """ 7 | 8 | import time 9 | # import json 10 | import platform 11 | import os 12 | # from apscheduler.schedulers.blocking import BlockingScheduler 13 | from apscheduler.schedulers.background import BackgroundScheduler 14 | import itchat 15 | from itchat.content import ( 16 | TEXT 17 | ) 18 | 19 | from everyday_wechat.utils.data_collection import ( 20 | get_weather_info, 21 | get_dictum_info, 22 | get_diff_time, 23 | get_calendar_info, 24 | get_constellation_info 25 | ) 26 | from everyday_wechat.control.airquality.air_quality_aqicn import ( 27 | get_air_quality 28 | ) 29 | from everyday_wechat.utils import config 30 | from everyday_wechat.utils.itchat_helper import ( 31 | init_wechat_config, 32 | set_system_notice, 33 | ) 34 | from everyday_wechat.utils.group_helper import ( 35 | handle_group_helper 36 | ) 37 | from everyday_wechat.utils.friend_helper import ( 38 | handle_friend 39 | ) 40 | 41 | __all__ = ['run', 'delete_cache'] 42 | 43 | 44 | def run(): 45 | """ 主运行入口 """ 46 | # 判断是否登录,如果没有登录则自动登录,返回 False 表示登录失败 47 | print('开始登录...') 48 | if not is_online(auto_login=True): 49 | print('程序已退出...') 50 | return 51 | 52 | 53 | def is_online(auto_login=False): 54 | """ 55 | 判断是否还在线。 56 | :param auto_login: bool,当为 Ture 则自动重连(默认为 False)。 57 | :return: bool,当返回为 True 时,在线;False 已断开连接。 58 | """ 59 | 60 | def _online(): 61 | """ 62 | 通过获取好友信息,判断用户是否还在线。 63 | :return: bool,当返回为 True 时,在线;False 已断开连接。 64 | """ 65 | try: 66 | if itchat.search_friends(): 67 | return True 68 | except IndexError: 69 | return False 70 | return True 71 | 72 | if _online(): return True # 如果在线,则直接返回 True 73 | if not auto_login: # 不自动登录,则直接返回 False 74 | print('微信已离线..') 75 | return False 76 | 77 | # hotReload = not config.get('is_forced_switch', False) # 切换微信号,重新扫码。 78 | hotReload = False # 2019年9月27日15:31:22 最近保存最近登录状态出错,所以先设置每次都得扫码登录 79 | loginCallback = init_data 80 | exitCallback = exit_msg 81 | try: 82 | for _ in range(2): # 尝试登录 2 次。 83 | if platform.system() in ('Windows', 'Darwin'): 84 | itchat.auto_login(hotReload=hotReload, 85 | loginCallback=loginCallback, exitCallback=exitCallback) 86 | itchat.run(blockThread=True) 87 | else: 88 | # 命令行显示登录二维码。 89 | itchat.auto_login(enableCmdQR=2, hotReload=hotReload, loginCallback=loginCallback, 90 | exitCallback=exitCallback) 91 | itchat.run(blockThread=True) 92 | if _online(): 93 | print('登录成功') 94 | return True 95 | except Exception as exception: # 登录失败的错误处理。 96 | sex = str(exception) 97 | if sex == "'User'": 98 | print('此微信号不能登录网页版微信,不能运行此项目。没有任何其它解决办法!可以换个号再试试。') 99 | else: 100 | print(sex) 101 | 102 | delete_cache() # 清理缓存数据 103 | print('登录失败。') 104 | return False 105 | 106 | 107 | def delete_cache(): 108 | """ 清除缓存数据,避免下次切换账号时出现 """ 109 | file_names = ('QR.png', 'itchat.pkl') 110 | for file_name in file_names: 111 | if os.path.exists(file_name): 112 | os.remove(file_name) 113 | 114 | 115 | def init_data(): 116 | """ 初始化微信所需数据 """ 117 | set_system_notice('登录成功') 118 | itchat.get_friends(update=True) # 更新好友数据。 119 | itchat.get_chatrooms(update=True) # 更新群聊数据。 120 | 121 | init_wechat_config() # 初始化所有配置内容 122 | 123 | # 提醒内容不为空时,启动定时任务 124 | alarm_dict = config.get('alarm_info').get('alarm_dict') 125 | if alarm_dict: 126 | init_alarm(alarm_dict) # 初始化定时任务 127 | 128 | print('初始化完成,开始正常工作。') 129 | 130 | 131 | def init_alarm(alarm_dict): 132 | """ 133 | 初始化定时任务 134 | :param alarm_dict: 定时相关内容 135 | """ 136 | # 定时任务 137 | scheduler = BackgroundScheduler() 138 | for key, value in alarm_dict.items(): 139 | scheduler.add_job(send_alarm_msg, 'cron', [key], hour=value['hour'], 140 | minute=value['minute'], id=key, misfire_grace_time=600, jitter=value.get("alarm_jitter",0)) 141 | scheduler.start() 142 | 143 | # print('已开启定时发送提醒功能...') 144 | # print(scheduler.get_jobs()) 145 | 146 | 147 | def send_alarm_msg(key): 148 | """ 发送定时提醒 """ 149 | print('\n启动定时自动提醒...') 150 | conf = config.get('alarm_info').get('alarm_dict') 151 | 152 | gf = conf.get(key) 153 | # print(gf)air_quality_city 154 | is_tomorrow = gf.get('is_tomorrow', False) 155 | calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow) 156 | weather = get_weather_info(gf.get('city_name'), is_tomorrow) 157 | horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow) 158 | dictum = get_dictum_info(gf.get('dictum_channel')) 159 | diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg')) 160 | air_quality = get_air_quality(gf.get('air_quality_city')) 161 | 162 | sweet_words = gf.get('sweet_words') 163 | send_msg = '\n'.join( 164 | x for x in [calendar_info, weather, air_quality, horoscope, dictum, diff_time, sweet_words] if x) 165 | # print('\n' + send_msg + '\n') 166 | if not send_msg or not is_online(): return 167 | uuid_list = gf.get('uuid_list') 168 | for uuid in uuid_list: 169 | time.sleep(1) 170 | itchat.send(send_msg, toUserName=uuid) 171 | print('\n定时内容:\n{}\n发送成功...\n\n'.format(send_msg)) 172 | print('自动提醒消息发送完成...\n') 173 | 174 | 175 | @itchat.msg_register([TEXT]) 176 | def text_reply(msg): 177 | """ 监听用户消息,用于自动回复 """ 178 | handle_friend(msg) 179 | # 下面这段代码,可以很直观打印出返回的消息的数据结构。 180 | # 把打印的数据复制到 https://www.json.cn/ 可查看详细的内容。群消息同理 181 | # import json 182 | # print(json.dumps(msg, ensure_ascii=False)) 183 | 184 | 185 | @itchat.msg_register([TEXT], isGroupChat=True) 186 | def text_group(msg): 187 | """ 监听用户消息,用于自动回复 """ 188 | handle_group_helper(msg) 189 | 190 | 191 | def exit_msg(): 192 | """ 退出通知 """ 193 | print('程序已退出') 194 | 195 | 196 | if __name__ == '__main__': 197 | # run() 198 | pass 199 | # config.init() 200 | # init_wechat() 201 | -------------------------------------------------------------------------------- /everyday_wechat/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Date: 2019/6/23 4 | # Author: snow 5 | 6 | 7 | -------------------------------------------------------------------------------- /everyday_wechat/utils/common.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 工具类 4 | """ 5 | import re 6 | import hashlib 7 | import json 8 | 9 | __all__ = [ 10 | 'FILEHELPER_MARK', 'FILEHELPER', 'SPIDER_HEADERS', 'WEEK_DICT', 11 | 'BIRTHDAY_COMPILE', 'CONSTELLATION_NAME_LIST', 'CONSTELLATION_DATE_DICT', 12 | 'is_json', 'md5_encode', 'get_constellation_name'] 13 | 14 | FILEHELPER_MARK = ['文件传输助手', 'filehelper'] # 文件传输助手标识 15 | FILEHELPER = 'filehelper' 16 | 17 | SPIDER_HEADERS = { 18 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; ' 19 | 'WOW64; rv:60.0) Gecko/20100101 Firefox/60.0', 20 | } 21 | 22 | WEEK_DICT = { 23 | 'Monday': '星期一', 'Tuesday': '星期二', 'Wednesday': '星期三', 24 | 'Thursday': '星期四', 'Friday': '星期五', 'Saturday': '星期六', 25 | 'Sunday': '星期日' 26 | } 27 | 28 | BIRTHDAY_COMPILE = re.compile(r'[\-\s]?(0?[1-9]|1[012])[\-\/\s]+(0?[1-9]|[12][0-9]|3[01])$') 29 | CONSTELLATION_NAME_LIST = ( 30 | "摩羯座", "水瓶座", "双鱼座", "白羊座", 31 | "金牛座", "双子座", "巨蟹座", "狮子座", 32 | "处女座", "天秤座", "天蝎座", "射手座") 33 | 34 | CONSTELLATION_DATE_DICT = { 35 | (1, 20): '摩羯座', 36 | (2, 19): '水瓶座', 37 | (3, 21): '双鱼座', 38 | (4, 21): '白羊座', 39 | (5, 21): '金牛座', 40 | (6, 22): '双子座', 41 | (7, 23): '巨蟹座', 42 | (8, 23): '狮子座', 43 | (9, 23): '处女座', 44 | (10, 23): '天秤座', 45 | (11, 23): '天蝎座', 46 | (12, 23): '射手座', 47 | (12, 32): '摩羯座', 48 | } 49 | 50 | 51 | def is_json(resp): 52 | """ 53 | 判断数据是否能被 Json 化。 True 能,False 否。 54 | :param resp: request. 55 | :return: bool, True 数据可 Json 化;False 不能 JOSN 化。 56 | """ 57 | try: 58 | json.loads(resp.text) 59 | return True 60 | except AttributeError as error: 61 | return False 62 | return False 63 | 64 | 65 | def md5_encode(text): 66 | """ 把數據 md5 化 """ 67 | if not isinstance(text, str): 68 | text = str(text) 69 | md5 = hashlib.md5() 70 | md5.update(text.encode('utf-8')) 71 | encodedStr = md5.hexdigest().upper() 72 | return encodedStr 73 | 74 | 75 | def get_constellation_name(date): 76 | ''' 77 | 通过日期来返回星座名,或者檢查星座名是否正確。 78 | :param date: 指定日期或者星座名 79 | :return:rtype str 80 | ''' 81 | if not date: 82 | return 83 | date = date.strip() 84 | if date in CONSTELLATION_NAME_LIST: 85 | return date 86 | 87 | times = BIRTHDAY_COMPILE.findall(date) 88 | if times: 89 | month, day = int(times[0][0]), int(times[0][1]) 90 | for k, v in CONSTELLATION_DATE_DICT.items(): 91 | if k > (month, day): 92 | return v 93 | return None 94 | 95 | 96 | if __name__ == '__main__': 97 | print(md5_encode('aeryou')) 98 | pass 99 | -------------------------------------------------------------------------------- /everyday_wechat/utils/config.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 用于管理缓存的配置数据 4 | 使用前必须先调用 init() 。 5 | """ 6 | import os 7 | import copy as mycopy 8 | import yaml 9 | 10 | __all__ = ['set', 'get', 'copy', 'update', '_print'] 11 | 12 | 13 | # def init(): 14 | # """ 15 | # 将 yaml 里的配置文件导入到 config.py 中 16 | # :return: bool ,true 表示数据导入成功。 17 | # """ 18 | # global opts 19 | # opts = get_yaml() 20 | # if opts: 21 | # return True 22 | # return False 23 | 24 | def get_yaml(): 25 | """ 26 | 解析 yaml 27 | :return: s 字典 28 | """ 29 | path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '_config.yaml') 30 | try: 31 | 32 | with open(path, 'r', encoding='utf-8') as file: 33 | config = yaml.safe_load(file) 34 | # config = yaml.load(file, Loader=yaml.Loader) 35 | return config 36 | except Exception as exception: 37 | print(str(exception)) 38 | print('你的 _config.yaml 文件配置出错...') 39 | return None 40 | 41 | opts = get_yaml() 42 | 43 | def set(key, value): 44 | """ 通过 key 设置某一项值 """ 45 | opts[key] = value 46 | 47 | 48 | def get(key, default=None): 49 | """ 通过 key 获取值 """ 50 | return opts.get(key, default) 51 | 52 | 53 | def copy(): 54 | """ 复制配置 """ 55 | return mycopy.deepcopy(opts) 56 | 57 | 58 | def update(new_opts): 59 | """ 全部替换配置 """ 60 | opts.update(new_opts) 61 | 62 | 63 | def _print(): 64 | print(opts) 65 | 66 | 67 | if __name__ == '__main__': 68 | you = get('is_forced_switch') 69 | print(you) 70 | -------------------------------------------------------------------------------- /everyday_wechat/utils/data_collection.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 获取各种请求的调度管理中心 4 | """ 5 | import importlib 6 | import re 7 | from datetime import datetime 8 | from datetime import timedelta 9 | 10 | # from everyday_wechat.control.weather.rtweather import get_today_weather 11 | from everyday_wechat.control.weather.sojson import get_sojson_weather 12 | from everyday_wechat.utils.common import ( 13 | get_constellation_name, 14 | ) 15 | from everyday_wechat.utils import config 16 | from everyday_wechat.control.horoscope.xzw_horescope import get_today_horoscope 17 | # from everyday_wechat.control.calendar.sojson_calendar import get_sojson_calendar 18 | from everyday_wechat.control.calendar.rt_calendar import get_rtcalendar 19 | 20 | __all__ = [ 21 | 'get_dictum_info', 'get_weather_info', 'get_bot_info', 22 | 'get_diff_time', 'get_constellation_info', 'get_calendar_info', 23 | 'DICTUM_NAME_DICT', 'BOT_NAME_DICT' 24 | ] 25 | 26 | DICTUM_NAME_DICT = { 27 | 1: 'wufazhuce', 2: 'acib', 3: 'lovelive', 4: 'hitokoto', 28 | 5: 'rtjokes', 6: 'juzimi', 7: 'caihongpi' 29 | } 30 | BOT_NAME_DICT = { 31 | 1: 'tuling123', 2: 'yigeai', 3: 'qingyunke', 4: 'qq_nlpchat', 32 | 5: 'tian_robot', 6: 'ruyiai', 7: 'ownthink_robot' 33 | } 34 | # 用于星座的正则表达式 35 | BIRTHDAY_COMPILE = re.compile(r'\-?(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$') 36 | 37 | 38 | def get_dictum_info(channel): 39 | """ 40 | 获取每日一句。 41 | :return:str 42 | """ 43 | if not channel: 44 | return None 45 | source = DICTUM_NAME_DICT.get(channel, '') 46 | if source: 47 | addon = importlib.import_module('everyday_wechat.control.onewords.' + source, __package__) 48 | dictum = addon.get_one_words() 49 | # print(dictum) 50 | return dictum 51 | return None 52 | 53 | 54 | def get_weather_info(cityname, is_tomorrow=False): 55 | """ 56 | 获取天气 57 | :param cityname:str,城市名称 58 | :return: str,天气情况 59 | """ 60 | if not cityname: 61 | return 62 | # return get_today_weather(cityname) 63 | return get_sojson_weather(cityname, is_tomorrow) 64 | 65 | 66 | def get_bot_info(message, userId=''): 67 | """ 68 | 跟机器人互动 69 | # 优先获取图灵机器人API的回复,但失效时,会使用青云客智能聊天机器人API(过时) 70 | :param message:str, 发送的话 71 | :param userId: str, 好友的uid,作为请求的唯一标识。 72 | :return:str, 机器人回复的话。 73 | """ 74 | 75 | channel = config.get('auto_reply_info').get('bot_channel', 7) 76 | source = BOT_NAME_DICT.get(channel, 'ownthink_robot') 77 | # print(source) 78 | if source: 79 | addon = importlib.import_module('everyday_wechat.control.bot.' + source, __package__) 80 | reply_msg = addon.get_auto_reply(message, userId) 81 | return reply_msg 82 | # reply_msg = get_tuling123(message) 83 | # if not reply_msg: 84 | # # reply_msg = get_qingyunke(message) 85 | # reply_msg = get_yigeai(message) 86 | 87 | return None 88 | 89 | 90 | def get_diff_time(start_date, start_msg=''): 91 | """ 92 | # 在一起,一共多少天了。 93 | :param start_date:str,日期 94 | :return: str,eg(宝贝这是我们在一起的第 111 天。) 95 | """ 96 | if not start_date: 97 | return None 98 | rdate = r'^[12]\d{3}[ \/\-](?:0?[1-9]|1[012])[ \/\-](?:0?[1-9]|[12][0-9]|3[01])$' 99 | start_date = start_date.strip() 100 | if not re.search(rdate, start_date): 101 | print('日期填写出错..') 102 | return 103 | start_datetime = datetime.strptime(start_date, '%Y-%m-%d') 104 | day_delta = (datetime.now() - start_datetime).days + 1 105 | if start_msg and start_msg.count('{}') == 1: 106 | delta_msg = start_msg.format(day_delta) 107 | else: 108 | delta_msg = '宝贝这是我们在一起的第 {} 天。'.format(day_delta) 109 | return delta_msg 110 | 111 | 112 | def get_constellation_info(birthday_str, is_tomorrow=False): 113 | """ 114 | 获取星座运势 115 | :param birthday_str: "10-12" 或 "1980-01-08" 或 星座名 116 | :return: 117 | """ 118 | if not birthday_str: 119 | return 120 | const_name = get_constellation_name(birthday_str) 121 | if not const_name: 122 | print('星座名填写错误') 123 | return 124 | return get_today_horoscope(const_name, is_tomorrow) 125 | 126 | 127 | def get_calendar_info(calendar=True, is_tomorrow=False, _date=''): 128 | """ 获取万年历 """ 129 | if not calendar: 130 | return None 131 | if not is_tomorrow: 132 | date = datetime.now().strftime('%Y%m%d') 133 | else: 134 | date = (datetime.now() + timedelta(days=1)).strftime('%Y%m%d') 135 | return get_rtcalendar(date) 136 | 137 | # else: 138 | # time_now = datetime.now() 139 | # week = WEEK_DICT[time_now.strftime('%A')] 140 | # date = time_now.strftime('%Y-%m-%d') 141 | # return '{} {}'.format(date, week) 142 | 143 | 144 | if __name__ == '__main__': 145 | config.init() 146 | text = 'are you ok' 147 | reply_msg = get_bot_info(text) 148 | print(reply_msg) 149 | pass 150 | -------------------------------------------------------------------------------- /everyday_wechat/utils/db_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-12 18:37 6 | Introduction: 7 | """ 8 | 9 | import pymongo 10 | from everyday_wechat.utils import config 11 | from functools import wraps 12 | from datetime import datetime 13 | 14 | __all__ = [ 15 | 'is_open_db', 'udpate_weather', 'udpate_user_city', 'find_user_city', 16 | 'find_weather', 'update_perpetual_calendar', 'find_perpetual_calendar', 17 | 'find_rubbish', 'update_rubbish', 'find_movie_box', 'update_movie_box', 18 | 'find_express', 'update_express', 'find_air_quality', 'udpate_air_quality' 19 | ] 20 | 21 | cache_valid_time = 4 * 60 * 60 # 天气缓存有效时间 22 | db_config = config.get('db_config') 23 | if db_config and db_config.get('is_open_db') and db_config.get('mongodb_conf'): 24 | is_open_db = db_config.get('is_open_db') 25 | mongodb_conf = db_config.get('mongodb_conf') 26 | try: 27 | myclient = pymongo.MongoClient( 28 | host=mongodb_conf.get('host'), 29 | port=mongodb_conf.get('port'), 30 | serverSelectionTimeoutMS=10) 31 | myclient.server_info() # 查看数据库信息,在这里用于是否连接数据的测试 32 | 33 | wechat_helper_db = myclient["wechat_helper"] 34 | weather_db = wechat_helper_db['weather'] 35 | user_city_db = wechat_helper_db['user_city'] 36 | perpetual_calendar_db = wechat_helper_db['perpetual_calendar'] 37 | rubbish_db = wechat_helper_db['rubbish_assort'] 38 | movie_box_db = wechat_helper_db['movie_box'] # 电影票房 39 | express_db = wechat_helper_db['express'] # 快递票房 40 | air_quality_db = wechat_helper_db['air_quality'] # 空气质量票房 41 | 42 | except pymongo.errors.ServerSelectionTimeoutError as err: 43 | # print(str(err)) 44 | # print('数据库连接失败') 45 | is_open_db = False # 把数据库设为不可用 46 | else: 47 | is_open_db = False 48 | 49 | 50 | def db_flag(): 51 | """ 用于数据库操作的 flag 没开启就不进行数据库操作""" 52 | 53 | def _db_flag(func): 54 | @wraps(func) 55 | def wrapper(*args, **kwargs): 56 | if is_open_db: 57 | return func(*args, **kwargs) 58 | else: 59 | return None 60 | 61 | return wrapper 62 | 63 | return _db_flag 64 | 65 | 66 | @db_flag() 67 | def udpate_weather(data): 68 | """ 69 | 更新天气数据 70 | :param data: 71 | """ 72 | key = {'_date': data['_date'], 'city_name': data['city_name']} 73 | weather_db.update_one(key, {"$set": data}, upsert=True) 74 | 75 | 76 | @db_flag() 77 | def udpate_user_city(data): 78 | """ 79 | 更新用户城市信息,用户最后一次查询成功的城市名 80 | :param data: 81 | """ 82 | key = {'userid': data['userid']} 83 | user_city_db.update_one(key, {"$set": data}, upsert=True) 84 | 85 | 86 | @db_flag() 87 | def find_user_city(uuid): 88 | """ 89 | 找到用户的城市,用户最后一次查询的城市名 90 | :param uuid: 91 | :return: 92 | """ 93 | key = {'userid': uuid} 94 | data = user_city_db.find_one(key) 95 | if data: 96 | return data['city_name'] 97 | 98 | 99 | @db_flag() 100 | def find_weather(date, cityname): 101 | """ 102 | 根据日期与城市名获取天气信息,天气信息有效期为 4 小时 103 | :param date: 日期(yyyy-mm-dd) 104 | :param cityname: 城市名 105 | :return: 天气信息 106 | """ 107 | key = {'_date': date, 'city_name': cityname} 108 | data = weather_db.find_one(key) 109 | if data: 110 | diff_second = (datetime.now() - data['last_time']).seconds 111 | if diff_second <= cache_valid_time: 112 | return data['weather_info'] 113 | return None 114 | 115 | 116 | @db_flag() 117 | def update_perpetual_calendar(_date, info): 118 | """ 119 | 更新日历信息 120 | :param _date: 日期(yyyy-mm-dd) 121 | :param info: 内容 122 | :return: None 123 | """ 124 | key = {'_date': _date} 125 | data = { 126 | '_date': _date, 127 | 'info': info, 128 | 'last_time': datetime.now() 129 | } 130 | perpetual_calendar_db.update_one(key, {"$set": data}, upsert=True) 131 | 132 | 133 | @db_flag() 134 | def find_perpetual_calendar(_date): 135 | """ 136 | 查找日历内容 137 | :param _date: str 日期(yyyy-mm-dd) 138 | :return: str 139 | """ 140 | key = {'_date': _date} 141 | data = perpetual_calendar_db.find_one(key) 142 | if data: 143 | return data['info'] 144 | 145 | 146 | @db_flag() 147 | def find_rubbish(name): 148 | """ 149 | 从数据库里查询获取内容 150 | {'name': '爱群主', 'type': '什么垃圾'} 151 | """ 152 | key = {'name': name} 153 | one = rubbish_db.find_one(key, {"_id": 0, "name": 1, "type": 1}) 154 | if one: 155 | return one['type'] 156 | return None 157 | 158 | 159 | # 保存进数据库 160 | # 如果有数据,则更新类别 161 | @db_flag() 162 | def update_rubbish(data): 163 | """ 164 | 将垃圾保存数据库 165 | :param data: 166 | :return: 167 | """ 168 | if isinstance(data, str): 169 | data = [data] 170 | if isinstance(data, list): 171 | for d in data: 172 | key = {'name': d['name']} 173 | value = {"$set": {"type": d['type']}} 174 | rubbish_db.update_one(key, value, upsert=True) 175 | 176 | 177 | @db_flag() 178 | def find_movie_box(date): 179 | """ 180 | 查询电脑票房, 181 | 如果是历史票房,则直接返回数据 182 | 如果不是,保存时间在5分钟内,则直接返回数据。 183 | 其他情况,返回为空 184 | :param date: 查询时间 185 | :return: 186 | """ 187 | key = {'_date': date} 188 | data = movie_box_db.find_one(key) 189 | if data: 190 | is_expired = data['is_expired'] 191 | if is_expired: 192 | return data['info'] 193 | diff_second = (datetime.now() - data['last_time']).seconds 194 | if diff_second <= 5 * 60: 195 | return data['info'] 196 | return None 197 | 198 | 199 | @db_flag() 200 | def update_movie_box(date, info, is_expired=False): 201 | """ 202 | 保存实时票房 203 | :param date: 日期 yyyyDDmm 格式 204 | :param info: 票房内容 205 | :param is_today: 是否是今日实时票房 206 | :return: None 207 | """ 208 | key = {'_date': date} 209 | data = { 210 | '_date': date, 211 | 'info': info, 212 | 'last_time': datetime.now(), 213 | 'is_expired': is_expired 214 | } 215 | movie_box_db.update_one(key, {"$set": data}, upsert=True) 216 | 217 | 218 | @db_flag() 219 | def update_express(data, uuid): 220 | """ 221 | 更新快递内容, 包括 222 | {'express_code': '78109182715352','shipper_code': 'ZTO', 223 | 'shipper_name': '中通速递','info': '很多内容', 'state': True} 224 | :param data: dict 内容数据 225 | :param uuid: str 用户 uid 226 | :return: 227 | """ 228 | key = {'express_code': data['express_code']} 229 | data['userid'] = uuid 230 | data['last_time'] = datetime.now() 231 | express_db.update_one(key, {"$set": data}, upsert=True) 232 | return None 233 | 234 | 235 | @db_flag() 236 | def find_express(express_code='', uuid=''): 237 | """ 238 | 获取缓存快递信息,express_code ,uuid 不可同时为空 239 | 缓存时间:5 分钟 240 | :param express_code: str,快递单号 241 | :param uuid: str,用户 uid 242 | :return: dict ,快递信息 243 | """ 244 | key = {} 245 | if express_code: 246 | key['express_code'] = express_code 247 | elif uuid: 248 | key['userid'] = uuid 249 | else: 250 | return None 251 | data = express_db.find_one(key) 252 | if data: 253 | data['is_forced_update'] = False # 是否需要强制更新 254 | state = data['state'] 255 | if state: # 订单是否已完成所有流程 256 | return data 257 | diff_second = (datetime.now() - data['last_time']).seconds 258 | if diff_second <= 5 * 60: # 有效缓存期 5分钟 259 | return data 260 | else: 261 | data['is_forced_update'] = True 262 | return data 263 | return None 264 | 265 | @db_flag() 266 | def find_air_quality(city): 267 | """ 268 | 根据日期与城市名获取空气信息,pm2.5 记录有效期为 1 小时 269 | :param city: 城市名 270 | :return: 空气信息 271 | """ 272 | key = {'city': city} 273 | data = air_quality_db.find_one(key) 274 | if data: 275 | diff_second = (datetime.now() - data['last_time']).seconds 276 | if diff_second <= 1 * 60 * 60: 277 | return data['info'] 278 | return None 279 | 280 | @db_flag() 281 | def udpate_air_quality(city, info): 282 | """ 283 | :param city: 城市名 284 | :param info: 空气情况 285 | :return: 286 | """ 287 | key = {'city': city} 288 | data = { 289 | 'city': city, 290 | 'info': info, 291 | 'last_time': datetime.now() 292 | } 293 | air_quality_db.update_one(key, {"$set": data}, upsert=True) 294 | 295 | 296 | # if __name__ == '__main__': 297 | # uuid = '123uuid' 298 | # y = find_user_city(uuid) 299 | # print(y) 300 | # 301 | # _date = datetime.now().strftime('%Y-%m-%d') 302 | # cityname = '南京' 303 | # fw = find_weather(_date, cityname) 304 | # print(fw) 305 | -------------------------------------------------------------------------------- /everyday_wechat/utils/friend_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-12 23:07 6 | Introduction: 处理好友消息内容 7 | """ 8 | 9 | import time 10 | import random 11 | import itchat 12 | from everyday_wechat.utils import config 13 | from everyday_wechat.utils.data_collection import ( 14 | get_bot_info, 15 | ) 16 | from everyday_wechat.utils.common import ( 17 | FILEHELPER, 18 | ) 19 | 20 | __all__ = ['handle_friend'] 21 | 22 | 23 | def handle_friend(msg): 24 | """ 处理好友信息 """ 25 | try: 26 | 27 | # 自己通过手机微信发送给别人的消息(文件传输助手除外)不作处理。 28 | if msg['FromUserName'] == config.get('wechat_uuid') and msg['ToUserName'] != FILEHELPER: 29 | return 30 | 31 | conf = config.get('auto_reply_info') 32 | if not conf.get('is_auto_reply'): 33 | return 34 | # 获取发送者的用户id 35 | uuid = FILEHELPER if msg['ToUserName'] == FILEHELPER else msg['FromUserName'] 36 | is_all = conf.get('is_auto_reply_all') 37 | auto_uuids = conf.get('auto_reply_black_uuids') if is_all else conf.get('auto_reply_white_uuids') 38 | # 开启回复所有人,当用户是黑名单,不回复消息 39 | if is_all and uuid in auto_uuids: 40 | return 41 | 42 | # 关闭回复所有人,当用户不是白名单,不回复消息 43 | if not is_all and uuid not in auto_uuids: 44 | return 45 | 46 | receive_text = msg.text # 好友发送来的消息内容 47 | # 好友叫啥,用于打印 48 | nick_name = FILEHELPER if uuid == FILEHELPER else msg.user.nickName 49 | print('\n{}发来信息:{}'.format(nick_name, receive_text)) 50 | reply_text = get_bot_info(receive_text, uuid) # 获取自动回复 51 | if reply_text: # 如内容不为空,回复消息 52 | time.sleep(random.randint(1, 2)) # 休眠一秒,保安全。想更快的,可以直接注释。 53 | 54 | prefix = conf.get('auto_reply_prefix', '') # 前缀 55 | if prefix: 56 | reply_text = '{}{}'.format(prefix, reply_text) 57 | 58 | suffix = conf.get('auto_reply_suffix', '') # 后缀 59 | if suffix: 60 | reply_text = '{}{}'.format(reply_text, suffix) 61 | 62 | itchat.send(reply_text, toUserName=uuid) 63 | print('回复{}:{}'.format(nick_name, reply_text)) 64 | else: 65 | print('自动回复失败\n') 66 | except Exception as exception: 67 | print(str(exception)) 68 | -------------------------------------------------------------------------------- /everyday_wechat/utils/group_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-11 12:55 6 | Introduction: 群消息处理 7 | """ 8 | 9 | import re 10 | from datetime import datetime 11 | import itchat 12 | 13 | from everyday_wechat.utils import config 14 | from everyday_wechat.control.calendar.rt_calendar import get_rtcalendar 15 | from everyday_wechat.utils.data_collection import ( 16 | get_weather_info, 17 | get_bot_info, 18 | # get_calendar_info, 19 | ) 20 | from everyday_wechat.control.rubbish.atoolbox_rubbish import ( 21 | get_atoolbox_rubbish 22 | ) 23 | from everyday_wechat.control.moviebox.maoyan_movie_box import ( 24 | get_maoyan_movie_box 25 | ) 26 | from everyday_wechat.control.express.kdniao_express import ( 27 | get_express_info 28 | ) 29 | from everyday_wechat.control.airquality.air_quality_aqicn import ( 30 | get_air_quality 31 | ) 32 | 33 | from everyday_wechat.utils.db_helper import ( 34 | find_perpetual_calendar, 35 | find_user_city, 36 | find_weather, 37 | udpate_user_city, 38 | udpate_weather, 39 | update_perpetual_calendar, 40 | find_rubbish, 41 | update_rubbish, 42 | find_movie_box, 43 | update_movie_box, 44 | find_express, 45 | update_express, 46 | find_air_quality, 47 | udpate_air_quality 48 | ) 49 | 50 | __all__ = ['handle_group_helper'] 51 | 52 | at_compile = r'(@.*?\s{1,}).*?' 53 | tomorrow_compile = r'明[日天]' 54 | 55 | punct_complie = r'[^a-zA-z0-9\u4e00-\u9fa5]+$' # 去除句子最后面的标点 56 | help_complie = r'^(?:0|帮忙|帮助|help)\s*$' 57 | 58 | weather_compile = r'^(?:\s*(?:1|天气|weather)(?!\d).*?|.*?(?:天气|weather)\s*)$' 59 | weather_clean_compile = r'1|天气|weather|\s' 60 | calendar_complie = r'^\s*(?:2|日历|万年历|calendar)(?=19|2[01]\d{2}|\s|$)' 61 | calendar_date_compile = r'^\s*(19|2[01]\d{2})[\-\/—\s年]*(0?[1-9]|1[012])[\-\/—\s月]*(0?[1-9]|[12][0-9]|3[01])[\s日号]*$' 62 | rubbish_complie = r'^\s*(?:3|垃圾|rubbish)(?!\d)' 63 | moviebox_complie = r'^\s*(?:4|票房|moviebox)(?=19|2[01]\d{2}|\s|$)' 64 | express_complie = r'^\s*(?:5|快递[单号]?|express)\s*([0-9a-zA-Z]+)' 65 | 66 | air_compile = r'^(?:\s*(?:6|空气|pm\s?2\.?5)(?!\d).*?|.*?(?:空气|pm\s?2\.?5)\s*)$' 67 | air_clean_compile = air_clean_compile = r'6|空气(?:质量)?|pm\s?2\.?5|\s' 68 | 69 | common_msg = '@{ated_name}\u2005\n{text}' 70 | weather_error_msg = '@{ated_name}\u2005\n未找到『{city}』城市的天气信息' 71 | weather_null_msg = '@{ated_name}\u2005\n 请输入城市名' 72 | 73 | calendar_error_msg = '@{ated_name}\u2005日期格式不对' 74 | calendar_no_result_msg = '@{ated_name}\u2005未找到{_date}的日历数据' 75 | 76 | rubbish_normal_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』属于{_type}' 77 | rubbish_other_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』无记录\n【推荐查询】:{other}' 78 | rubbish_nothing_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』无记录' 79 | rubbish_null_msg = '@{ated_name}\u2005 请输入垃圾名称' 80 | 81 | moiebox_no_result_msg = '@{ated_name}\u2005未找到{_date}的票房数据' 82 | 83 | air_city_null_msg = '@{ated_name}\u2005\n 请输入城市名' 84 | air_error_msg = '@{ated_name}\u2005\n未找到『{city}』城市的空气质量信息' 85 | 86 | help_group_content = """@{ated_name} 87 | 群助手功能: 88 | 1.输入:天气(weather)+城市名(可空)。例如:天气北京 89 | 2.输入:日历(calendar)+日期(格式:yyyy-MM-dd 可空)。例如:日历2019-07-03 90 | 3.输入:垃圾(rubbish)+名称。例如:3猫粮 91 | 4.输入:票房(moviebox)+日期。例如:票房 92 | 5.输入:快递(express)+ 快递订单号。例如: 快递 1231231231 93 | 6.输入:空气(pm25)+城市名。例如:pm2.5 北京 94 | 更多功能:请输入 0|help|帮助,查看。 95 | """ 96 | 97 | 98 | # import pysnooper 99 | # @pysnooper.snoop() 100 | def handle_group_helper(msg): 101 | """ 102 | 处理群消息 103 | :param msg: 104 | :return: 105 | """ 106 | uuid = msg.fromUserName # 群 uid 107 | ated_uuid = msg.actualUserName # 艾特你的用户的uuid 108 | ated_name = msg.actualNickName # 艾特你的人的群里的名称 109 | text = msg['Text'] # 发送到群里的消息。 110 | 111 | # 自己通过手机端微信发出的消息不作处理 112 | if ated_uuid == config.get('wechat_uuid'): 113 | return 114 | 115 | conf = config.get('group_helper_conf') 116 | if not conf.get('is_open'): 117 | return 118 | 119 | # 如果开启了 『艾特才回复』,而群用户又没有艾特你。不处理消息 120 | if conf.get('is_at') and not msg.isAt: 121 | return 122 | 123 | is_all = conf.get('is_all', False) 124 | user_uuids = conf.get('group_black_uuids') if is_all else conf.get('group_white_uuids') 125 | # 开启回复所有群,而用户是黑名单,不处理消息 126 | if is_all and uuid in user_uuids: 127 | return 128 | 129 | # 未回复所有群,而用户不是白名单,不处理消息 130 | if not is_all and uuid not in user_uuids: 131 | return 132 | # 去掉 at 标记 133 | text = re.sub(at_compile, '', text) 134 | 135 | # 如果是帮助设置 136 | helps = re.findall(help_complie, text, re.I) 137 | if helps: 138 | retext = help_group_content.format(ated_name=ated_name) 139 | itchat.send(retext, uuid) 140 | return 141 | 142 | # 是否是明天,用于日历,天气,星座查询 143 | is_tomorrow = re.findall(tomorrow_compile, text) 144 | if is_tomorrow: 145 | is_tomorrow = True 146 | htext = re.sub(tomorrow_compile, '', text) 147 | else: 148 | is_tomorrow = False 149 | htext = text 150 | 151 | htext = re.sub(punct_complie, '', htext) # 去句末的标点 152 | 153 | # 已开启天气查询,并包括天气关键词 154 | if conf.get('is_weather'): 155 | if re.findall(weather_compile, htext, re.I): 156 | city = re.sub(weather_clean_compile, '', text, flags=re.IGNORECASE).strip() 157 | 158 | if not city: # 如果只是输入城市名 159 | # 从缓存数据库找最后一次查询的城市名 160 | city = find_user_city(ated_uuid) 161 | if not city: # 缓存数据库没有保存,通过用户的资料查城市 162 | city = get_city_by_uuid(ated_uuid) 163 | if not city: 164 | retext = weather_null_msg.format(ated_name=ated_name) 165 | itchat.send(retext, uuid) 166 | return 167 | 168 | _date = datetime.now().strftime('%Y-%m-%d') 169 | weather_info = find_weather(_date, city) 170 | if weather_info: 171 | retext = common_msg.format(ated_name=ated_name, text=weather_info) 172 | itchat.send(retext, uuid) 173 | return 174 | 175 | weather_info = get_weather_info(city) 176 | if weather_info: 177 | # print(ated_name, city, retext) 178 | retext = common_msg.format(ated_name=ated_name, text=weather_info) 179 | itchat.send(retext, uuid) 180 | 181 | data = { 182 | '_date': _date, 183 | 'city_name': city, 184 | 'weather_info': weather_info, 185 | 'userid': ated_uuid, 186 | 'last_time': datetime.now() 187 | } 188 | udpate_weather(data) 189 | # userid,city_name,last_time,group_name udpate_weather_city 190 | data2 = { 191 | 'userid': ated_uuid, 192 | 'city_name': city, 193 | 'last_time': datetime.now() 194 | } 195 | udpate_user_city(data2) 196 | return 197 | else: 198 | retext = weather_error_msg.format(ated_name=ated_name, city=city) 199 | itchat.send(retext, uuid) 200 | return 201 | return 202 | 203 | # 已开启日历,并包含日历 204 | if conf.get('is_calendar'): 205 | if re.findall(calendar_complie, htext, flags=re.IGNORECASE): 206 | 207 | calendar_text = re.sub(calendar_complie, '', htext).strip() 208 | if calendar_text: # 日历后面填上日期了 209 | dates = re.findall(calendar_date_compile, calendar_text) 210 | if not dates: 211 | retext = calendar_error_msg.format(ated_name=ated_name) 212 | itchat.send(retext, uuid) 213 | return 214 | 215 | _date = '{}-{:0>2}-{:0>2}'.format(*dates[0]) # 用于保存数据库 216 | rt_date = '{}{:0>2}{:0>2}'.format(*dates[0]) # 用于查询日历 217 | else: # 日历 后面没有日期,则默认使用今日。 218 | _date = datetime.now().strftime('%Y-%m-%d') 219 | rt_date = datetime.now().strftime('%Y%m%d') 220 | 221 | # 从数据库缓存中记取内容 222 | cale_info = find_perpetual_calendar(_date) 223 | if cale_info: 224 | retext = common_msg.format(ated_name=ated_name, text=cale_info) 225 | itchat.send(retext, uuid) 226 | return 227 | 228 | # 取网络数据 229 | cale_info = get_rtcalendar(rt_date) 230 | if cale_info: 231 | retext = common_msg.format(ated_name=ated_name, text=cale_info) 232 | itchat.send(retext, uuid) 233 | update_perpetual_calendar(_date, cale_info) # 保存数据到数据库 234 | return 235 | else: # 查询无结果 236 | retext = calendar_no_result_msg.format(ated_name=ated_name, _date=_date) 237 | itchat.send(retext, uuid) 238 | return 239 | 240 | # 垃圾分类查询 241 | if conf.get('is_rubbish'): 242 | if re.findall(rubbish_complie, htext, re.I): 243 | key = re.sub(rubbish_complie, '', htext, flags=re.IGNORECASE).strip() 244 | if not key: 245 | retext = rubbish_null_msg.format(ated_name=ated_name) 246 | itchat.send(retext, uuid) 247 | return 248 | 249 | _type = find_rubbish(key) 250 | if _type: 251 | retext = rubbish_normal_msg.format(ated_name=ated_name, name=key, _type=_type) 252 | itchat.send(retext, uuid) 253 | return 254 | _type, return_list, other = get_atoolbox_rubbish(key) 255 | if _type: 256 | retext = rubbish_normal_msg.format(ated_name=ated_name, name=key, _type=_type) 257 | itchat.send_msg(retext, uuid) 258 | elif other: 259 | retext = rubbish_other_msg.format(ated_name=ated_name, name=key, other=other) 260 | itchat.send_msg(retext, uuid) 261 | else: 262 | retext = rubbish_nothing_msg.format(ated_name=ated_name, name=key) 263 | itchat.send_msg(retext, uuid) 264 | if return_list: 265 | update_rubbish(return_list) # 保存数据库 266 | return 267 | 268 | if conf.get('is_moviebox'): 269 | if re.findall(moviebox_complie, htext, re.I): 270 | moviebox_text = re.sub(moviebox_complie, '', htext).strip() 271 | if moviebox_text: # 日历后面填上日期了 272 | dates = re.findall(calendar_date_compile, moviebox_text) 273 | if not dates: 274 | retext = calendar_error_msg.format(ated_name=ated_name) 275 | itchat.send(retext, uuid) 276 | return 277 | _date = '{}{:0>2}{:0>2}'.format(*dates[0]) 278 | else: # 日历 后面没有日期,则默认使用今日。 279 | _date = datetime.now().strftime('%Y%m%d') 280 | # 从数据库缓存中记取内容 281 | mb_info = find_movie_box(_date) 282 | if mb_info: 283 | retext = common_msg.format(ated_name=ated_name, text=mb_info) 284 | itchat.send(retext, uuid) 285 | return 286 | 287 | is_expired = False 288 | cur_date = datetime.now().date() 289 | query_date = datetime.strptime(_date, '%Y%m%d').date() 290 | 291 | if query_date < cur_date: 292 | is_expired = True 293 | 294 | # 取网络数据 295 | mb_info = get_maoyan_movie_box(_date, is_expired) 296 | if mb_info: 297 | retext = common_msg.format(ated_name=ated_name, text=mb_info) 298 | itchat.send(retext, uuid) 299 | update_movie_box(_date, mb_info, is_expired) # 保存数据到数据库 300 | return 301 | else: # 查询无结果 302 | retext = moiebox_no_result_msg.format(ated_name=ated_name, _date=_date) 303 | itchat.send(retext, uuid) 304 | return 305 | 306 | # 处理订单号 307 | if conf.get('is_express'): 308 | express_list = re.findall(express_complie, htext, re.I) 309 | if express_list: 310 | express_code = express_list[0] 311 | db_data = find_express(express_code, uuid) 312 | shipper_code, shipper_name = '', '' 313 | if db_data: 314 | if not db_data['is_forced_update']: 315 | info = db_data['info'] 316 | retext = common_msg.format(ated_name=ated_name, text=info) 317 | itchat.send(retext, uuid) 318 | return 319 | shipper_code = db_data['shipper_code'] 320 | shipper_name = db_data['shipper_name'] 321 | 322 | data = get_express_info( 323 | express_code, 324 | shipper_name=shipper_name, 325 | shipper_code=shipper_code) 326 | if data: 327 | info = data['info'] 328 | retext = common_msg.format(ated_name=ated_name, text=info) 329 | itchat.send(retext, uuid) 330 | update_express(data, uuid) 331 | return 332 | else: 333 | print('未查询到此订单号的快递物流轨迹。') 334 | return 335 | 336 | # 处理空气质量查询号 337 | if conf.get('is_air_quality'): 338 | if re.findall(air_compile, htext, re.I): 339 | city = re.sub(air_clean_compile, '', text, flags=re.IGNORECASE).strip() 340 | if not city: # 如果只是输入城市名 341 | # 从缓存数据库找最后一次查询的城市名 342 | city = find_user_city(ated_uuid) 343 | if not city: # 缓存数据库没有保存,通过用户的资料查城市 344 | city = get_city_by_uuid(ated_uuid) 345 | if not city: 346 | retext = air_city_null_msg.format(ated_name=ated_name) 347 | itchat.send(retext, uuid) 348 | return 349 | 350 | info = find_air_quality(city) 351 | if info: 352 | retext = common_msg.format(ated_name=ated_name, text=info) 353 | itchat.send(retext, uuid) 354 | return 355 | info = get_air_quality(city) 356 | if info: 357 | retext = common_msg.format(ated_name=ated_name, text=info) 358 | itchat.send(retext, uuid) 359 | 360 | udpate_air_quality(city, info) 361 | data2 = { 362 | 'userid': ated_uuid, 363 | 'city_name': city, 364 | 'last_time': datetime.now() 365 | } 366 | udpate_user_city(data2) 367 | return 368 | else: 369 | retext = air_error_msg.format(ated_name=ated_name, city=city) 370 | itchat.send(retext, uuid) 371 | return 372 | return 373 | 374 | # 其他结果都没有匹配到,走自动回复的路 375 | if conf.get('is_auto_reply'): 376 | reply_text = get_bot_info(text, ated_uuid) # 获取自动回复 377 | if reply_text: # 如内容不为空,回复消息 378 | reply_text = common_msg.format(ated_name=ated_name, text=reply_text) 379 | itchat.send(reply_text, uuid) 380 | print('回复{}:{}'.format(ated_name, reply_text)) 381 | else: 382 | print('自动回复失败\n') 383 | 384 | 385 | # 通过用户id找好友 386 | def get_city_by_uuid(uid): 387 | """ 388 | 通过用户的uid得到用户的城市 389 | 最好是与机器人是好友关系 390 | """ 391 | itchat.get_friends(update=True) 392 | info = itchat.search_friends(userName=uid) 393 | # print('info:'+str(info)) 394 | if not info: 395 | return None 396 | city = info.city 397 | # print('city:'+city) 398 | return city 399 | -------------------------------------------------------------------------------- /everyday_wechat/utils/itchat_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-11 14:56 6 | Introduction: 7 | """ 8 | 9 | import itchat 10 | import re 11 | from datetime import datetime 12 | from datetime import timedelta 13 | from importlib import import_module 14 | from everyday_wechat.utils import config 15 | from everyday_wechat.utils.common import ( 16 | md5_encode, 17 | FILEHELPER_MARK, 18 | FILEHELPER, 19 | ) 20 | from everyday_wechat.utils.data_collection import ( 21 | BOT_NAME_DICT 22 | ) 23 | 24 | __all__ = ['init_wechat_config', 'set_system_notice', 'get_group', 'get_friend'] 25 | 26 | TIME_COMPILE = re.compile(r'^\s*([01]?[0-9]|2[0-3])\s*[::\-]\s*([0-5]?[0-9])\s*$') 27 | 28 | 29 | def init_wechat_config(): 30 | """ 初始化微信所需数据 """ 31 | # print('初始化微信所需数据开始..') 32 | # 从config copy ,用于保存新的接口内容。 33 | myset = config.copy() 34 | print('=' * 80) 35 | 36 | base_wechat_info = itchat.search_friends() # 获取此微信号的基础信息 37 | wechat_nick_name = base_wechat_info['NickName'] # 获取此微信号的昵称 38 | wechat_uuid = base_wechat_info['UserName'] # 获取此微信号的uuid 39 | myset['wechat_nick_name'] = wechat_nick_name 40 | myset['wechat_uuid'] = wechat_uuid 41 | 42 | # start---------------------------处理自动回复好友---------------------------start 43 | reply = myset.get('auto_reply_info') 44 | if reply is not None and reply.get('is_auto_reply'): 45 | if reply.get('is_auto_reply_all'): 46 | auto_reply_list_key = 'auto_reply_black_list' 47 | auto_reply_list_uuid_name = 'auto_reply_black_uuids' 48 | else: 49 | auto_reply_list_key = 'auto_reply_white_list' 50 | auto_reply_list_uuid_name = 'auto_reply_white_uuids' 51 | 52 | auto_reply_uuids_list = [] 53 | for name in reply.get(auto_reply_list_key): 54 | if not name.strip(): 55 | continue 56 | if name.lower() in FILEHELPER_MARK: # 判断是否文件传输助手 57 | auto_reply_uuids_list.append(FILEHELPER) 58 | continue 59 | friend = get_friend(name) 60 | if friend: 61 | auto_reply_uuids_list.append(friend['UserName']) 62 | else: 63 | print('自动回复中的好友昵称『{}』有误。'.format(name)) 64 | reply[auto_reply_list_uuid_name] = set(auto_reply_uuids_list) 65 | # print('已开启图灵自动回复...') 66 | 67 | # end---------------------------处理自动回复好友---------------------------end 68 | 69 | # start ----------------------------------- 群功能初始化 ----------------------------------- start 70 | helper = myset.get('group_helper_conf') 71 | if helper is not None and helper.get('is_open'): 72 | if helper.get('is_all', False): 73 | group_list_key = 'group_name_black_list' 74 | group_list_uuid_name = 'group_black_uuids' 75 | else: 76 | group_list_key = 'group_name_white_list' 77 | group_list_uuid_name = 'group_white_uuids' 78 | group_uuid_list = [] 79 | for name in helper.get(group_list_key): 80 | if not name.strip(): 81 | continue 82 | group = get_group(name) 83 | if group: 84 | group_uuid_list.append(group['UserName']) 85 | else: 86 | print('群助手中的群聊名称『{}』有误。' 87 | '(注意:必须要把需要的群聊保存到通讯录)'.format(name)) 88 | helper[group_list_uuid_name] = set(group_uuid_list) 89 | # end ----------------------------------- 群功能初始化 ----------------------------------- end 90 | 91 | alarm = myset.get('alarm_info') 92 | alarm_dict = {} 93 | if alarm is not None and alarm.get('is_alarm'): 94 | for gi in alarm.get('girlfriend_infos'): 95 | ats = gi.get('alarm_timed') 96 | if not ats: 97 | continue 98 | uuid_list = [] 99 | nickname_list = [] 100 | # start---------------------------处理好友---------------------------start 101 | friends = gi.get('wechat_name') 102 | if isinstance(friends, str): 103 | friends = [friends] 104 | if isinstance(friends, list): 105 | for name in friends: 106 | if name.lower() in FILEHELPER_MARK: # 判断是否文件传输助手 107 | uuid_list.append(FILEHELPER) 108 | nickname_list.append(name) 109 | continue 110 | name_info = get_friend(name) 111 | if not name_info: 112 | print('定时提醒中的好友昵称『{}』无效'.format(name)) 113 | else: 114 | uuid_list.append(name_info['UserName']) 115 | nickname_list.append(name) 116 | # end---------------------------处理好友---------------------------end 117 | 118 | # start---------------------------群组处理---------------------------start 119 | group_names = gi.get('group_name') 120 | if isinstance(group_names, str): 121 | group_names = [group_names] 122 | if isinstance(group_names, list): 123 | for name in group_names: 124 | name_info = get_group(name) 125 | if not name_info: 126 | print('定时任务中的群聊名称『{}』有误。' 127 | '(注意:必须要把需要的群聊保存到通讯录)'.format(name)) 128 | else: 129 | uuid_list.append(name_info['UserName']) 130 | nickname_list.append(name) 131 | # end---------------------------群组处理---------------------------end 132 | 133 | # start---------------------------定时处理---------------------------start 134 | 135 | if isinstance(ats, str): 136 | ats = [ats] 137 | if isinstance(ats, list): 138 | for at in ats: 139 | times = TIME_COMPILE.findall(at) 140 | if not times: 141 | print('时间{}格式出错'.format(at)) 142 | continue 143 | hour, minute = int(times[0][0]), int(times[0][1]) 144 | temp_dict = {'hour': hour, 'minute': minute, 'uuid_list': uuid_list, 'nickname_list': nickname_list} 145 | temp_dict.update(gi) 146 | alarm_dict[md5_encode(str(temp_dict))] = temp_dict 147 | # end---------------------------定时处理---------------------------end 148 | alarm['alarm_dict'] = alarm_dict 149 | 150 | # 将解析的数据保存于 config 中。 151 | config.update(myset) 152 | # print(json.dumps(alarm_dict, ensure_ascii=False)) 153 | # print('初始化微信所需数据结束..') 154 | 155 | log_all_config() 156 | 157 | 158 | def set_system_notice(text): 159 | """ 160 | 给文件传输助手发送系统日志。 161 | :param text:str 日志内容 162 | """ 163 | if text: 164 | text = '系统通知:' + text 165 | itchat.send(text, toUserName=FILEHELPER) 166 | 167 | 168 | def get_group(group_name, update=False): 169 | """ 170 | 根据群组名获取群组数据 171 | :param group_name:str, 群组名 172 | :param update: bool 强制更新群组数据 173 | :return: obj 单个群组信息 174 | """ 175 | if update: itchat.get_chatrooms(update=True) 176 | if not group_name: return None 177 | groups = itchat.search_chatrooms(name=group_name) 178 | if not groups: return None 179 | return groups[0] 180 | 181 | 182 | def get_friend(wechat_name, update=False): 183 | """ 184 | 根据用户名获取用户数据 185 | :param wechat_name: str 用户名 186 | :param update: bool 强制更新用户数据 187 | :return: obj 单个好友信息 188 | """ 189 | if update: itchat.get_friends(update=True) 190 | if not wechat_name: return None 191 | friends = itchat.search_friends(name=wechat_name) 192 | if not friends: return None 193 | return friends[0] 194 | 195 | 196 | def get_mps(mp_name, update=False): 197 | """ 198 | 根据公众号的名称获取用户数据 199 | :param mp_name: str 用户名 200 | :param update: bool 强制更新用户数据 201 | :return: obj 单个公众号信息 202 | """ 203 | if update: itchat.get_mps(update=True) 204 | if not mp_name: return None 205 | mps = itchat.search_mps(name=mp_name) 206 | if not mps: return None 207 | # mpuuid = mps[0]['UserName'] 公众号的uuid 208 | return mps[0] 209 | 210 | 211 | # import pysnooper 212 | # @pysnooper.snoop() 213 | def log_all_config(): 214 | """ 215 | 用于打印设置日志 216 | :return: 217 | """ 218 | print('=' * 80) 219 | channel = config.get('auto_reply_info').get('bot_channel', 7) 220 | source = BOT_NAME_DICT.get(channel, 'ownthink_robot') 221 | addon = import_module('everyday_wechat.control.bot.' + source, __package__) 222 | bot_name = addon.BOT_NAME 223 | print('自动回复机器人渠道:{}'.format(bot_name)) 224 | 225 | # start ----------------------------------- 微信好友自动回复的功能日志 ----------------------------------- start 226 | reply = config.get('auto_reply_info', None) 227 | if not reply or not reply.get('is_auto_reply'): 228 | print('未开启微信好友自动回复。') 229 | else: 230 | if reply.get('is_auto_reply_all'): 231 | auto_uuids = reply.get('auto_reply_black_uuids') 232 | nicknames = [] 233 | for auid in auto_uuids: 234 | if auid == 'filehelper': 235 | nicknames.append(auid) 236 | else: 237 | friends = itchat.search_friends(userName=auid) 238 | nickname = friends.nickName 239 | nicknames.append(nickname) 240 | nns = ','.join(nicknames) 241 | print('开启对全部微信好友全部回复,除了:{}'.format(nns)) 242 | else: 243 | auto_uuids = reply.get('auto_reply_white_uuids') 244 | nicknames = [] 245 | for auid in auto_uuids: 246 | if auid == 'filehelper': 247 | nicknames.append(auid) 248 | else: 249 | friends = itchat.search_friends(userName=auid) 250 | nickname = friends.nickName 251 | nicknames.append(nickname) 252 | nns = ','.join(nicknames) 253 | print('对微信好友 {},进行自动回复'.format(nns)) 254 | 255 | print('=' * 80) 256 | 257 | # start ----------------------------------- 群功能日志说明 ----------------------------------- start 258 | helper = config.get('group_helper_conf') 259 | if not helper or not helper.get('is_open'): 260 | print('未开启群助手功能。') 261 | else: 262 | if helper.get('is_all'): 263 | auto_uuids = helper.get('group_black_uuids') 264 | nicknames = [] 265 | for auid in auto_uuids: 266 | chatrooms = itchat.search_chatrooms(userName=auid) 267 | nickname = chatrooms['NickName'] # 群聊名称 268 | nicknames.append(nickname) 269 | nns = ','.join(nicknames) 270 | print('已开启对全部微信群的监听,除了群:{}。'.format(nns)) 271 | else: 272 | auto_uuids = helper.get('group_white_uuids') 273 | nicknames = [] 274 | for auid in auto_uuids: 275 | chatroom = itchat.search_chatrooms(userName=auid) 276 | nickname = chatroom['NickName'] # 群聊名称 277 | nicknames.append(nickname) 278 | nns = ','.join(nicknames) 279 | 280 | print('已对微信群:{},开启了群助手功能。'.format(nns)) 281 | 282 | if helper.get('is_at'): 283 | print('只有群里用户@机器人,才会触发群助手功能。') 284 | if helper.get('is_auto_reply'): 285 | print('已开启对微信群内用户的自动回复。') 286 | if helper.get('is_weather'): 287 | print('已开启天气查询功能,具体使用方法请输入:“help” 查看。') 288 | if helper.get('is_calendar'): 289 | print('已开启日志查询功能,具体使用方法请输入:“help” 查看。') 290 | if helper.get('is_rubbish'): 291 | print('已开启垃圾分类查询功能,具体使用方法请输入:“help” 查看。') 292 | if helper.get('is_moviebox'): 293 | print('已开启票房查询功能,具体使用方法请输入:“help” 查看。') 294 | if helper.get('is_air_quality'): 295 | print('已开启空气质量查询功能,具体使用方法请输入:“help” 查看。') 296 | 297 | print('=' * 80) 298 | 299 | # start ----------------------------------- 提醒功能的日志说明 ----------------------------------- start 300 | alarm = config.get('alarm_info') 301 | if not alarm or not alarm.get('is_alarm'): 302 | print('未开启每日提醒功能。') 303 | else: 304 | print('已开启定时发送提醒功能。') 305 | alarm_dict = alarm.get('alarm_dict') 306 | for value in alarm_dict.values(): 307 | nickname_list = value.get('nickname_list') 308 | nns = ','.join(nickname_list) 309 | # temp_dict = {'hour': hour, 'minute': minute, 'uuid_list': uuid_list, 'nickname_list': nickname_list} 310 | hour = value.get('hour') 311 | minute = value.get('minute') 312 | alarm_time = "{hour:0>2d}:{minute:0>2d}".format(hour=hour, minute=minute) 313 | 314 | # 计算在哪个区间给朋友发送信息 315 | jitter = value.get("alarm_jitter", 0) 316 | if jitter != 0: 317 | set_time = datetime.strptime(alarm_time, '%H:%M') 318 | jitter_time = timedelta(seconds=jitter) 319 | start_time = (set_time - jitter_time).strftime("%H:%M") 320 | end_time = (set_time + jitter_time).strftime("%H:%M") 321 | alarm_time = "{start_time}——{end_time} 期间".format(start_time=start_time, end_time=end_time) 322 | 323 | print('定时:{alarm_time},给:{nicknames},发送提醒内容一次。'.format(alarm_time=alarm_time, nicknames=nns)) 324 | 325 | print('=' * 80) 326 | -------------------------------------------------------------------------------- /history.md: -------------------------------------------------------------------------------- 1 | 2019年11月14日 2 | 3 | vesion: 0.3.27 4 | 定时时间加了一个随时抖动。可以不再是固定时间内发送了 5 | 6 | 2019年10月1日 7 | 8 | vesion: 0.3.26 9 | 新添加一个群助手功能:空气质量PM2.5查询 10 | 也可以添加到每日提醒中。 11 | 12 | 2019年9月5日 13 | 14 | vesion: 0.3.20 15 | 新添加一个群助手功能:快递物流信息查询 16 | 17 | 2019年8月27日 18 | 19 | vesion: 0.3.10 20 | 新添加一个群助手功能:实时票房查询 21 | 22 | 2019年8月27日 23 | 24 | vesion: 0.3.07 25 | 1.添加了一个新的机器人渠道:思知机器人 26 | 27 | 2019年8月14日 28 | 29 | 1. 更新天气更新不及时的 Bug。 30 | 31 | 2019年7月13日 32 | 33 | 1. 天气预报、星座运势、日历的提醒可以用明日。 34 | 2. 自动回复可以回复所有人,添加不受影响的『白名单』。 35 | 3. 新功能:群助手,可自动回复成员,查询天气,日历。 36 | 4. 添加了 mongodb 数据库做缓存处理。 37 | 38 | 2019年7月2日 39 | 40 | 新添三个机器人渠道:「智能闲聊」、「天行机器人」 「海知智能机器人」 41 | 42 | 2019年6月30日 43 | 44 | 新添每日一言渠道:彩虹屁 45 | 46 | 2019年6月29日 47 | 48 | 1.新添内容:万年历。 49 | 2.『在一起』文案可自定义。 50 | 3.可添加多个定时提醒。 51 | 4.更新非 windows 平台登录出现的 Bug. 52 | 5.星座运势可直接填具体星座 53 | 54 | 2019年6月24日 55 | 56 | 重构代码结构。 57 | 58 | 2019年6月20日 59 | 60 | 新添内容:星座运势 61 | 62 | 2019年6月19日 63 | 64 | 新添每日一言渠道:民国情书 65 | 66 | 2019年6月16日 67 | 68 | 新添机器人渠道:一个 AI 69 | 70 | 2019年6月15日 71 | 72 | 1.好友可选『文件传输助手』 73 | 2.定时发送消息可支持群聊组。 74 | 75 | 2019年6月15日 76 | 77 | 代码重构 78 | 79 | 2019年6月12日 80 | 81 | 添加图灵机器人 82 | 83 | 更早,不知道了。 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | itchat==1.3.10 2 | requests 3 | beautifulsoup4 4 | apscheduler 5 | pymongo 6 | pyyaml 7 | lxml -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 程序运行入口 4 | """ 5 | 6 | import sys 7 | import re 8 | from datetime import datetime 9 | 10 | try: 11 | from everyday_wechat import __version__ 12 | 13 | print('EverydayWechat 程序版本号:{}'.format(__version__)) 14 | _date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 15 | print('当前时间:{}'.format(_date)) 16 | except Exception as exception: 17 | print(str(exception)) 18 | print('请将脚本放在项目根目录中运行') 19 | print('请检查项目根目录中的 everyday_wechat 文件夹是否存在') 20 | exit(1) 21 | 22 | 23 | def run(): 24 | """ 主程序入口""" 25 | 26 | # 判断当前环境是否为 python 3 27 | if sys.version_info[0] == 2: 28 | print('此项目不支持 Python 2 版本!') 29 | return 30 | 31 | # 检查依赖库是否都已经安装上 32 | try: 33 | import itchat 34 | import apscheduler 35 | import requests 36 | from bs4 import BeautifulSoup 37 | if itchat.__version__ != '1.3.10': 38 | print('当前 itchat 版本为:{} ,本项目需要 itchat 的版本为 1.3.10。请升级至最新版本!\n' 39 | '升级方法 1:pip install itchat --upgrade \n' 40 | '或者方法 2: pip install -U itchat'.format(itchat.__version__)) 41 | return 42 | 43 | except (ModuleNotFoundError, ImportError) as error: 44 | if isinstance(error, ModuleNotFoundError): 45 | no_modules = re.findall(r"named '(.*?)'$", str(error)) 46 | if no_modules: 47 | print('当前运行环境缺少 {} 库'.format(no_modules[0])) 48 | print(str(error)) 49 | elif isinstance(error, ImportError): 50 | print('当前运行环境引入库出错') 51 | print(str(error)) 52 | return 53 | 54 | # 用于判断数据库功能是否开启 55 | try: 56 | from everyday_wechat.utils import config 57 | from everyday_wechat.utils.db_helper import is_open_db 58 | if not is_open_db: 59 | print('数据库未开启或启动失败!但数据库功能不会影响项目正常运行,主要用于群助手查询数据缓存。') 60 | except Exception as exception: 61 | print(str(exception)) 62 | return 63 | 64 | print('所有环境配置 OK ..') 65 | from everyday_wechat import main 66 | main.run() 67 | 68 | 69 | if __name__ == '__main__': 70 | run() -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Date: 2019/6/23 4 | # Author: snow 5 | 6 | 7 | import os 8 | from unittest import TestCase 9 | from everyday_wechat.utils import config 10 | 11 | here_dir = os.path.dirname(__file__) 12 | 13 | class BaseTestCase(TestCase): 14 | def setUp(self): 15 | # config.init() 16 | pass -------------------------------------------------------------------------------- /tests/test_01.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Date: 2019/6/23 4 | # Author: snow 5 | 6 | import os 7 | 8 | -------------------------------------------------------------------------------- /tests/test_alarm/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-11 12:01 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/test_alarm/_trial_temp-1/_trial_marker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/tests/test_alarm/_trial_temp-1/_trial_marker -------------------------------------------------------------------------------- /tests/test_alarm/_trial_temp-1/test.log: -------------------------------------------------------------------------------- 1 | 2019-11-14 12:15:48+0800 [-] Log opened. 2 | -------------------------------------------------------------------------------- /tests/test_alarm/_trial_temp.lock/symlink: -------------------------------------------------------------------------------- 1 | 15000 -------------------------------------------------------------------------------- /tests/test_alarm/_trial_temp/_trial_marker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/tests/test_alarm/_trial_temp/_trial_marker -------------------------------------------------------------------------------- /tests/test_alarm/_trial_temp/test.log: -------------------------------------------------------------------------------- 1 | 2019-07-16 16:33:53+0800 [-] Log opened. 2 | -------------------------------------------------------------------------------- /tests/test_alarm/test_info.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-11 12:03 6 | Introduction: 7 | """ 8 | from tests import BaseTestCase 9 | from everyday_wechat.utils import config 10 | from everyday_wechat.utils.data_collection import * 11 | from everyday_wechat.control.airquality.air_quality_aqicn import ( 12 | get_air_quality 13 | ) 14 | 15 | class TestJobModel(BaseTestCase): 16 | def test_all_info(self): 17 | """ 18 | 测试获取提醒的所有信息。 19 | :return: 20 | """ 21 | girlfriend_infos = config.get('alarm_info').get('girlfriend_infos') 22 | for gf in girlfriend_infos: 23 | is_tomorrow = gf.get('is_tomorrow', False) 24 | calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow) 25 | weather = get_weather_info(gf.get('city_name'), is_tomorrow) 26 | horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow) 27 | dictum = get_dictum_info(gf.get('dictum_channel')) 28 | diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg')) 29 | air_quality = get_air_quality(gf.get('air_quality_city')) 30 | 31 | sweet_words = gf.get('sweet_words') 32 | send_msg = '\n'.join( 33 | x for x in [calendar_info, weather, air_quality, horoscope, dictum, diff_time, sweet_words] if x) 34 | print(send_msg) 35 | print('\n' + '-' * 50 + '\n') 36 | -------------------------------------------------------------------------------- /tests/test_config/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-10-01 00:52 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/test_control/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-14 01:06 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/test_control/_trial_temp/_trial_marker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/tests/test_control/_trial_temp/_trial_marker -------------------------------------------------------------------------------- /tests/test_control/_trial_temp/test.log: -------------------------------------------------------------------------------- 1 | 2019-08-27 13:27:03+0800 [-] Log opened. 2 | -------------------------------------------------------------------------------- /tests/test_control/test_one_words.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-18 14:07 6 | Introduction: 7 | """ 8 | from unittest import TestCase 9 | import importlib 10 | import path 11 | import os 12 | 13 | from everyday_wechat.control.onewords.wufazhuce import get_wufazhuce_info 14 | 15 | 16 | class BaseTestCase(TestCase): 17 | def test_get_wufazhuce_(self): 18 | ok = get_wufazhuce_info() 19 | print(ok) 20 | 21 | def test_bot_name(self): 22 | _path = os.path.dirname(__file__) 23 | print(_path) 24 | source = 'ownthink_robot' 25 | 26 | addon = importlib.import_module('everyday_wechat.control.bot.' + source, __package__) 27 | name = addon.BOT_NAME 28 | print(name) 29 | 30 | loth = importlib.util.find_spec('everyday_wechat.control.bot') 31 | print(loth) -------------------------------------------------------------------------------- /tests/test_control/test_rubbish.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-14 01:06 6 | Introduction: 7 | """ 8 | from unittest import TestCase 9 | 10 | from everyday_wechat.control.rubbish.atoolbox_rubbish import get_atoolbox_rubbish 11 | 12 | class BaseTestCase(TestCase): 13 | def test_atoolbox_rubbish(self): 14 | key = '牛' 15 | ok = get_atoolbox_rubbish(key) 16 | print(ok) 17 | -------------------------------------------------------------------------------- /tests/test_db/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-12 19:09 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/test_db/_trial_temp/_trial_marker: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfyc23/EverydayWechat/6b81d03dde92cfef584428bc1e59d2858e94204e/tests/test_db/_trial_temp/_trial_marker -------------------------------------------------------------------------------- /tests/test_db/_trial_temp/test.log: -------------------------------------------------------------------------------- 1 | 2019-10-01 00:18:51+0800 [-] Log opened. 2 | -------------------------------------------------------------------------------- /tests/test_db/test_air.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019年9月4日12:41:33 6 | Introduction: 7 | """ 8 | 9 | from tests import BaseTestCase 10 | 11 | from everyday_wechat.utils.db_helper import * 12 | from everyday_wechat.control.airquality.air_quality_aqicn import get_air_quality 13 | import pysnooper 14 | 15 | 16 | class TestDbAirModel(BaseTestCase): 17 | 18 | def test_db_get_data(self): 19 | 20 | city = '天津' 21 | cc = get_air_quality(city) 22 | if cc: 23 | print(cc) 24 | # print(cc['info']) 25 | 26 | def test_db_get_and_save_data(self): 27 | 28 | city = '天津' 29 | info = get_air_quality(city) 30 | if info: 31 | udpate_air_quality(city, info) 32 | 33 | def test_db_find_data(self): 34 | # uid = '05150520' 35 | city = '天津' 36 | 37 | # code = '' 38 | info = find_air_quality(city) 39 | if info: 40 | print(info) 41 | 42 | @pysnooper.snoop() 43 | def test_all_data(self): 44 | city = '宁波' 45 | info = find_air_quality(city) 46 | if info: 47 | print(info) 48 | return 49 | 50 | info = get_air_quality(city) 51 | if info: 52 | print(info) 53 | udpate_air_quality(city, info) 54 | -------------------------------------------------------------------------------- /tests/test_db/test_db.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-12 19:15 6 | Introduction: 7 | """ 8 | 9 | from tests import BaseTestCase 10 | # from everyday_wechat.utils import config 11 | from everyday_wechat.utils.db_helper import * 12 | from everyday_wechat.control.moviebox.maoyan_movie_box import get_maoyan_movie_box 13 | from datetime import datetime 14 | from datetime import timedelta 15 | 16 | 17 | class TestDbModel(BaseTestCase): 18 | 19 | def test_db_get_data(self): 20 | # yy = config.get('db_config')['mongodb_conf'] 21 | # host = yy['host']+'dd' 22 | # port = yy['port'] 23 | # hello = 'mongodb://{host}:{port}/'.format(host=host,port=port) 24 | # 25 | # myclient = pymongo.MongoClient(host=host,port=port) 26 | # dblist = myclient.list_database_names() 27 | # for db in dblist: 28 | # print(db) 29 | # print('8' * 10, db_helper.is_open_db) 30 | uuid = '11' 31 | find_user_city(uuid) 32 | 33 | def test_db_movie(self): 34 | date_ = datetime.now().strftime('%Y%m%d') 35 | 36 | info = find_movie_box(date_) 37 | if info: 38 | print('数据库缓存') 39 | print(info) 40 | else: 41 | mb = get_maoyan_movie_box(date_) 42 | update_movie_box(date_, mb, is_expired=False) 43 | 44 | def test_db_yesterday_movice(self): 45 | date_ = (datetime.now() + timedelta(days=-1)).strftime('%Y%m%d') 46 | print(date_) 47 | -------------------------------------------------------------------------------- /tests/test_db/test_express.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019年9月4日12:41:33 6 | Introduction: 7 | """ 8 | 9 | from tests import BaseTestCase 10 | # from everyday_wechat.utils import config 11 | from everyday_wechat.utils.db_helper import * 12 | from everyday_wechat.control.moviebox.maoyan_movie_box import get_maoyan_movie_box 13 | from datetime import datetime 14 | from datetime import timedelta 15 | from everyday_wechat.control.express.kdniao_express import get_express_info 16 | import pysnooper 17 | 18 | 19 | class TestDbExpressModel(BaseTestCase): 20 | 21 | def test_db_get_data(self): 22 | 23 | code = '78109182715352' 24 | cc = get_express_info(code) 25 | if cc: 26 | print(cc) 27 | print(cc['info']) 28 | 29 | def test_db_get_and_save_data(self): 30 | uid = '05150520' 31 | code = '78109182715352' 32 | cc = get_express_info(code) 33 | if cc: 34 | update_express(cc, uid) 35 | print('保存数据') 36 | 37 | def test_db_find_data(self): 38 | # uid = '05150520' 39 | uid = '' 40 | code = '78109182715352' 41 | # code = '' 42 | info = find_express(code, uid) 43 | if info: 44 | print(info) 45 | 46 | @pysnooper.snoop() 47 | def test_all_data(self): 48 | uid = '05150520' 49 | code = '78109182715352' 50 | # code = '102276593571' 51 | # code = 'JD0001855864185' 52 | db_data = find_express(code, uid) 53 | shipper_code, shipper_name = '', '' 54 | if db_data: 55 | if not db_data['is_forced_update']: 56 | print(db_data['info']) 57 | return 58 | shipper_code = db_data['shipper_code'] 59 | shipper_name = db_data['shipper_name'] 60 | 61 | data = get_express_info( 62 | code, 63 | shipper_name=shipper_name, 64 | shipper_code=shipper_code) 65 | if data: 66 | print(data['info']) 67 | update_express(data, uid) 68 | return 69 | else: 70 | print('未查询到此订单号或者快递物流轨迹') 71 | return 72 | -------------------------------------------------------------------------------- /tests/test_email_alarm/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-10-13 13:16 6 | Introduction: 7 | """ 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/test_email_alarm/test_email.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Project: EverydayWechat-Github 4 | Creator: DoubleThunder 5 | Create time: 2019-07-11 12:03 6 | Introduction: 7 | """ 8 | from tests import BaseTestCase 9 | from everyday_wechat.utils import config 10 | from everyday_wechat.utils.data_collection import * 11 | from wechat_notice import EmailNotice 12 | from everyday_wechat.control.airquality.air_quality_aqicn import ( 13 | get_air_quality 14 | ) 15 | 16 | 17 | class TestEmailModel(BaseTestCase): 18 | def test_all_info(self): 19 | """ 20 | 测试获取提醒的所有信息。 21 | :return: 22 | """ 23 | girlfriend_infos = config.get('alarm_info').get('girlfriend_infos') 24 | for gf in girlfriend_infos: 25 | is_tomorrow = gf.get('is_tomorrow', False) 26 | calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow) 27 | weather = get_weather_info(gf.get('city_name'), is_tomorrow) 28 | horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow) 29 | dictum = get_dictum_info(gf.get('dictum_channel')) 30 | diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg')) 31 | sweet_words = gf.get('sweet_words') 32 | 33 | air_quality = get_air_quality(gf.get('air_quality_city')) 34 | 35 | send_msg = '\n'.join( 36 | x for x in [calendar_info, weather, horoscope, air_quality, dictum, diff_time, sweet_words] if x) 37 | print(send_msg) 38 | print('\n' + '-' * 50 + '\n') 39 | 40 | """ 41 | other_alarm_conf: 42 | email_config: 43 | user: 'sfyc1314@163.com' 44 | password: 'pvQ8sgyCRTyq' 45 | host: 'smtp.163.com' 46 | """ 47 | 48 | def test_send_email(self): 49 | ac = config.get('other_alarm_conf', None) 50 | # if ac: 51 | email_config = ac.get('email_config', None) 52 | user = email_config.get('user', None) 53 | password = email_config.get('password', None) 54 | host = email_config.get('host', None) 55 | email_notice = EmailNotice(user=user, password=password, host=host) 56 | 57 | # yy = email_notice.send('title', 'hello world', receivers='sfyc23@qq.com') 58 | # print(yy) 59 | 60 | girlfriend_infos = config.get('alarm_info').get('girlfriend_infos') 61 | for gf in girlfriend_infos[:1]: 62 | is_tomorrow = gf.get('is_tomorrow', False) 63 | calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow) 64 | weather = get_weather_info(gf.get('city_name'), is_tomorrow) 65 | horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow) 66 | dictum = get_dictum_info(gf.get('dictum_channel')) 67 | diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg')) 68 | sweet_words = gf.get('sweet_words') 69 | send_msg = '\n'.join(x for x in [calendar_info, weather, horoscope, dictum, diff_time, sweet_words] if x) 70 | print(send_msg) 71 | print('\n' + '-' * 50 + '\n') 72 | # email_notice.send('title', send_msg, receivers='sfyc23@qq.com') 73 | 74 | def test_moviebox(self): 75 | pass --------------------------------------------------------------------------------