Full Code of sfyc23/EverydayWechat for AI

master 6b81d03dde92 cached
75 files
178.2 KB
67.6k tokens
104 symbols
1 requests
Download .txt
Repository: sfyc23/EverydayWechat
Branch: master
Commit: 6b81d03dde92
Files: 75
Total size: 178.2 KB

Directory structure:
gitextract_2kqk_pde/

├── .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/
    │   │   ├── _trial_marker
    │   │   └── test.log
    │   ├── _trial_temp-1/
    │   │   ├── _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

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
# Git
.git
.gitignore

# PyCharm
.idea

# Virtual environment
.env/
.venv/
venv/

================================================
FILE: .gitignore
================================================
.idea
__pycache__
itchat.pkl
QR.png

venv/


================================================
FILE: Dockerfile
================================================
# 说明该镜像以哪个镜像为基础
FROM python:3.7-slim

RUN mkdir /app
WORKDIR /app

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt
COPY . /app

ENV MODE server

# 构建者的基本信息
MAINTAINER DoubleThunder <sfyc23@gmail.com>


ENTRYPOINT ["python", "run.py"]


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019  Thunder Bouble

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
![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&amp;utm_medium=referral&amp;utm_content=sfyc23/EverydayWechat&amp;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)](#微信交流群)  
 
[EverydayWechat](https://github.com/sfyc23/EverydayWechat) 是基于 Python3 与 [Itchat](https://github.com/littlecodersh/ItChat) 的微信小工具。    
可以定时给朋友或者群聊发送每日天气、提醒、每日一句,也可以智能自动回复好友信息。还有群助手功能,让你在好友群中装 X。
操作简单,小白用户也可快速上手。  

**本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。**    
**本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。**    
**本项目依赖于网页版微信进行开发,如登录不了,则无法使用此项目;且无任何解决办法。**    
网页版微信地址:<https://wx.qq.com/>。  

在北京地区求一份 Python & Android 的工作岗位。  
加微信:[地址](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190614125724.png)。

[版本更新日志](https://github.com/sfyc23/EverydayWechat/blob/master/hostory.md)

最近搞了一个类似,但功能不一样的项目:[微信加群助手](https://github.com/sfyc23/WechatAddGroupHelper)。  
欢迎大家 star。

**禁止将本工具用于商业用途**,如产生法律纠纷与本人无关。  

> 注意:如果给女朋友添加图灵机器人回复,请慎重考虑!!!!  
并不是你的每一个女朋友都能接受,你用机器人给他回复『暖心话』,安慰她。人工智能也有可能是一个智障机器人。想想如果机器人回复给你女朋友:『我们分手吧』。可能你们真的就分手了。虽然我会在心里默默的点个赞(单身狗的自白)
> 

 [![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`  

## 功能说明

-  支持对多个微信好友自动回复。  
-  定时给好友与群聊组发送提醒,内容包括(天气、格言、自定义的话)。  
-  群助手功能,可以群自动回复,查询最热门的垃圾分类、天气、日历、实时票房、快递信息、PM2.5等等功能。

> 如果你没有好友可测试发送提醒,而且只有一个人也玩不了自动回复,怎么办呢(快哭了.jpg)。  
> 你可以把『文件传输助手』当成女朋友添加(你说的这个女朋友到底是不是你的双手.jpg)。这样一个号也可以进行测试了,发提醒给文件传输助手,跟文件传输助手智能聊天。

## 相关数据来源

### 天气信息:

-  SOJSON:<https://www.sojson.com/blog/305.html>    
-  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)    

### 每日一句:

-  ONE ● 一个: <http://wufazhuce.com/>  
-  金山词霸 ● 每日一句(双语):<http://open.iciba.com/?c=api>  
-  一言 :<https://hitokoto.cn/>  
-  土味情话: <https://www.v2ex.com/t/569853> (土)  
-  句子迷-民国情书: <https://www.juzimi.com/> (高雅,但最近不可用)  
-  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)      
-  彩虹屁: <https://chp.shadiao.app>  

### 人工智能机器人

-  图灵机器人:<http://www.turingapi.com/>(需求实名制认证,并每天免费数量只有 100 条)  
-  青云客智能聊天机器人:<http://api.qingyunke.com/>(无须申请,无数量限制,但有点智障,分手神器。分手神器,慎用)  
-  智能闲聊(腾讯):<https://ai.qq.com/product/nlpchat.shtml> ( 申请使用,免费且无限量。大厂靠谱。)  
-  天行机器人 :<https://www.tianapi.com/apiview/47> (认证后有 7 万条免费使用。之后收费:1 万条/1 块钱)  
-  海知智能 :<https://ruyi.ai/> (功能很强大,不仅仅用于聊天。需申请 key,免费) 
-  思知对话机器人:<https://www.ownthink.com/> (免费,可不申请 appid)
-  一个AI:<http://www.yige.ai/>(免费且无数量限制。可自定义回复、对话、场景。但高级功能使用比较复杂。但已长时间没人维护) 

### 星座运势
-  星座屋 :<https://www.xzw.com/> (基于爬虫获取数据)  

### 万年历
-  RollToolsApi :[指定日期的节假日及万年历信息](https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息)    
-  SOJSON :<https://www.sojson.com/api/lunar.html>  

### 票房数据:
- 猫眼实时票房:<https://piaofang.maoyan.com/dashboard>

### 垃圾分类查询:
- atoolbox 垃圾分类查询:<http://www.atoolbox.net/Tool.php?Id=804>

### 空气质量PM2.5查询:
- aqicn:<http://aqicn.org/here/>


## 项目配置
目前项目所有的配置都是在 **[_config.yaml](https://github.com/sfyc23/EverydayWechat/blob/master/_config.yaml)** 文件中。    
配置文件请严格遵循 yaml 语法格式,yaml 学习地址:  
<https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html>    
<http://einverne.github.io/post/2015/08/yaml.html>

### 配置自动回复机器人。

#### 1. 开启自动回复

-  将 **is_auto_relay** 设置为:True。  

#### 2.选择渠道

```
机器人渠道(1: 图灵机器人,2: 一个AI ,3 : 青云客,4 腾讯智能闲聊,5:天行机器人,6:海知智能,7:思知机器人)
bot_channel: 7
```

> 默认为思知机器人,可不申请 key 的情况下,最智能的了。。

#### 3. 指定自动回复的好友名单

有两种模式 

(1) 不使用自动回复所有好友的情况下,即:is_auto_reply_all:False 时。   
这时设置可回复的白名单成员,如下:  

```
is_auto_reply_all:False
# 指定自动回复的好友名单。
auto_reply_white_list:
  - '好友1'
  - '好友2'
```
(2) 开启自动回复所有好友的情况下,即:is_auto_reply_all:True 时。  
选择不自动回复黑名单成员:如下  

```
is_auto_reply_all:True
auto_reply_black_list:
    - '好友1'
    - '好友2'
```

#### 4. 配置相关器人

除了青云客之外,其他的机器人都需要去对应的官网,注册并获取相应的 key。需要哪个就配置哪个。

##### I.图灵机器人

- 打开图灵机器人官网:[http://www.turingapi.com](http://www.turingapi.com/) 进行注册。 
- 创建机器人,得到 apikey。将填入到 **_config.yaml** 文件中的:  

> 注意:不要打开『密钥』选项。

```
turing_conf:
  apiKey: '你所获取apikey'
```
> 图灵机器人必须认证后才能使用,免费版用户,每天可使用 100 条信息,且用且珍惜。

##### II.天行机器人 

- 打开天行数据注册页面:[https://www.tianapi.com/signup.html](https://www.tianapi.com/signup.html?source=sf4243841) 进行注册。  
- 在个人中心的第一行,即可得到 apikey。  

```
txapi_conf:
  app_key: '个人中心中的key'
  reply_name: '宝宝' # 回复的人的名字(可空)(也可在个人中心->机器人管理 修改)
  bot_name: '老公' # 机器人的名字(可空)
```

##### III.智能闲聊(腾讯)

- 打开 https://ai.qq.com/product/nlpchat.shtml 并登录。  
- 点击免费使用 -> 接入能力 -> 创建应用 -> 创建成功后,会显示出 app_id ,app_key 。  
- 点击应用管理 -> 『你创建的项目名』-> 接入能力 -> 智能闲聊 -> 了解更多 -> 接入能力->『选择项目』-> 确认接口。  
将 app_id,app_key 填入 yaml 中。  

```
qqnlpchat_conf:
    app_id: '你申请的api_id'
    app_key: '你申请的app_key'
```

#####  IV.配置「一个AI」
打开图灵机器人官网:[http://www.yige.ai](http://www.yige.ai) 进行注册。    
创建应用,得到「API密钥」中的 「客户端访问令牌」  
将填入到 **_config.yaml** 文件中的:  

```
yigeai_conf:
  client_token: '客户访问令牌'
```

#####  V.配置「思知机器人」

打开思知官网:[https://www.ownthink.com/](https://www.ownthink.com/) 进行注册。  
创建机器人,得到 appid。  
将填入到 **_config.yaml** 文件中的:  
```
ownthink_conf:
    app_key: '你申请的api_id'
```


关于自动回复,目前可以公开的情报:  
1. 只能自动回复文字类消息;  
2. 如果消息发送太频繁,微信会限制登录网页端登录。放心,并不会封号;  
3. 好友里可以填入名称『文件传输助手』,这样你就可以在文件传输助手,发送消息,查看自动回复消息效果。  

### 配置定时提醒

#### 1.开启并设置提醒时间

-  将 **is_alarm** 设置成 **True**。(当为 False 时,则关闭定时)  

```
alarm_info:
  is_alarm: True
```

#### 2.填写需要发送的好友信息

填写好友信息,例如:
```
alarm_timed:
  - "9:00"
  - "12:30"
  - "22:00"
wechat_name:
  - '文件传输助手'
  - '诗风'
group_name:
  - 'EverydayWechat 交流群'
is_tomorrow: False
city_name: '桂林'
dictum_channel : 3
start_date: '2017-10-10'
start_date_msg: '爱你的第{}天'
calendar: True
horescope: "处女座"
sweet_words: '你脚下的蚂蚁'

```

相关参数说明:

| 名称 | 示例       | 必填 | 说明 |
| -------- | -------------- | ---------- |---------- |
| wechat_name | '老婆' | 选填 | 好友名:可填多人。好友微信昵称或者备注名(不能输入微信号)|
| alarm_timed | '9:30' | 必填 | 定时时间,可填多个 |
| alarm_jitter | 300 | 可空 | 定时时间的前后300秒内随机发送 |
| group_name | '交流群' | 选填 | 群聊名称,可填多个。必须要把需要的群聊保存到通讯录。|
| is_tomorrow | True | 可空 | 是否发送明日信息(如天气,星座,万年历)。|
| city_name | '成都' | 可空 | 城市名:朋友所在城市,用于发送天气。 |
| air_quality_city | '成都' | 可空 | 空气质量 PM25 的城市。 |
| dictum_channel | 2 | 可空 | 格言渠道(见下表)|
| start_date | '2017-10-10' | 可空 | 相识日期:计算到当天的天数 。 |
| start_date_msg | '爱你的第{}天' | 可空 | 相识日期文案 |
| sweet_words | '来自你俊美的老公' | 可空 | 甜密的后缀。(钢铁直男的直描)|
| horescope | '处女座' | 可空 | 星座名或好友生日。用于发送星座运势 |
| calendar | True | 可空 | 万年历信息 |

**wechat_name**,**group_name** 至少要有一个。  

格言渠道 : 1 : ONE●一个,2 : 词霸(每日双语),3: 土味情话, 4 : 一言,5:笑话,6: 民国情书,7: 彩虹屁。    

> Tips:可以把 **wechat_name**  填入『**文件传输助手**』,这样,提醒会发送到自己微信里的 **文件传输助手** 中。在不打扰别人的情况下,方便快速查看效果。


-  **alarm_time** 设置成需要提醒的时间。之后如果微信没有断线,即每天这个的时间会定时发送提醒。  

> 如果需要快速体验,可将 **alarm_timed** 当前系统时间之后的几分钟。例如当前时间为 11:35,并设置 5 分钟后发送提醒,即:alarm_timed:11:40

当然,你也可以根据自己的需求,设置另一套不同的方案。具体参考代码。  

一例提醒:  

```
2019-06-29 星期六 农历五月廿七 
【宜】嫁娶,祭祀,沐浴,扫舍,修饰垣墙 
【忌】行丧,安葬 
桂林天气预报 
【今日天气】阵雨
【今日温度】低温 26.0℃,高温 33.0℃ 
【今日风速】南风<3级
【出行提示】阵雨来袭,出门记得带伞 
【桂林PM2.5】142 轻度污染
处女座今日运势 
【幸运颜色】2
【幸运数字】薄荷绿
【综合运势】今天的你有机会重逢旧同学、旧朋友,对方会为你带来一些小惊喜,可能是某个不错的商机,也可能是某个消息。工作/学习上,今天的你目标性很强,能把当初奋斗的初心捡回来,重新出发。感情方面,有伴者今天要提防烂桃花的挑拨离间,多给对方一些信任。
你知道五氧化二磷被氧化前是什么样子嘛,什么样子?五二磷。 
宝贝这是我们在一起的第628天 
你脚下的蚂蚁
```

### 配置群助手功能 

直接放表格说明吧。

| 名称 | 示例       | 必填 | 说明 |
| -------- | -------------- | ---------- |---------- |
| is_open | True | 必填 | 是否开启群助手功能 |
| is_all | True | 必填 | 是否对所有群开启。当开启时,只有黑名单的名单才不受影响(慎重开启!) |
| group_name_white_list | 「群名」 | 选填 | 白名单用户。当 is_all:Fase。只处理这个群里的消息|
| group_name_black_list | 「群名」 | 选填 | 黑名单用户。当 is_all :True 。这个群里的用户不受影响。|
| is_at | True | 必填 | 艾特标记。只有当别人艾特自己时,才会处理消息(慎重关闭!)。 |
| is_auto_reply | True | 必填 | # 开启群自动回复(慎重开启!)|
| is_weather | True| 必填 | 是否开启天气查询。 |
| is_calendar | True | 必填 | 是否开启万历年查询 |
| is_rubbish | True | 必填 | 是否开启垃圾查询 |
| is_moviebox | True | 必填 | 是否开启电脑票房查询 |
| is_express | True | 必填 | 是否开启快递信息查询 |
| is_air_quality | True | 必填 | 是否开启空气质量查询 |

### 配置数据库(可不配置)

首先得安装 mongodb 数据库安装。安装方式,请自行谷歌。  
官方的安装教程也有:<https://docs.mongodb.com/v3.2/administration/install-community/>  

(1)将 **is_open_db** 设置成 「True」。  
(2)设置 host 与 port。tips: 没有特殊要求,或者对数据库不熟悉者不需要设置。

## 安装
首先,把 Python3 安装好,并配置好环境,个人建议新手安装 Anaconda,具体安装教程,可自行谷歌搜索~  


直接下载此项目或 clone 项目到本地。  

使用 pip 安装依赖:

```
pip3 install -r requirements.txt
# 或者是使用 pip
# pip install -r requirements.txt
```

## 运行

在本地 cmd 中跳转项目目录下,运行:  

```
python run.py
```

第一次运行会跳出二维码,扫码登录。如输出日志中打印成:『登录成功』,则表示运行成功。  
登录成功后一段时间内再运行,微信会保持登录状态,不需要再扫码。  
如果需要切换用户,则在 *_config.yaml* 文件中,修改 *is_forced_switch* 的属性为 True。  

-  docker 下运行
    - 构建 `docker build -t everyday_wechat:v1 .`
    - 运行 `docker run everyday_wechat:v1`

## 示例截图:

![日志](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190613171703.png)

![自动回复](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190613162524.png)

## 提 [issues](https://github.com/sfyc23/EverydayWechat/issues) & 加群提问的建议。

-  当你拋出一个技术问题时,最终是否能得到有用的回答,往往取决于你所提问和追问的方式。推荐阅读:[提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)。    
-  **检查是否是最新的代码,检查是否是 Python3.5+,检查依赖有没有安装完整**。  
-  先检查微信是否可登录 [微信网页版](https://wx.qq.com/),如网页端不能用,此项目也不能用。  
-  请更新你的 [itchat](https://github.com/littlecodersh/ItChat) 至最新版本 **1.3.10** 。查看 itchat 版本 **print(itchat.__version__ )**。    
-  与微信相关的问题可以先去 itchat [issues](https://github.com/littlecodersh/ItChat/issues), 查看是否有相似问题。  
-  微信名只能是昵称或者备注名,不能输入微信号。  
-  对群聊操作时,必须要把需要的群聊保存到通讯录。  
-  如果有新的思路和建议也欢迎提交。  

## Credits 致谢

本项目受以下项目启发,参考了其中一部分思路,向这些开发者表示感谢。  

-  [wechatBot](https://github.com/gengchen528/wechatBot) —— 微信每日说,每日自动发送微信消息(Node + Wechaty)。   
-  [NodeMail](https://github.com/Vincedream/NodeMail) —— 用 Node 写一个爬虫脚本每天定时给女朋友发一封暖心邮件。  
-  [wechat-assistant](https://github.com/gengchen528/wechat-assistant) —— koa+wechaty实现的微信个人秘书,把你闲置的微信号利用起来做个个人秘书。  
-  [WechatRobot](https://github.com/scorego/WechatRobot) ——个人微信号自动回复、陪聊、查天气(Java)  
-  <https://github.com/likaixiang/EverydayWechat>   
-  <https://github.com/0xHJK/music-dl>  


## 微信交流群
因为人数已超 100 人,请加 wx: **sfyc1314** 机器人为好友,验证信息写填写:「github」!!!,机器人会自动通过。  
通过后回复:「加群」,会自动拉你入群。
加群助手也已开源,地址:[https://github.com/sfyc23/WechatAddGroupHelper](https://github.com/sfyc23/WechatAddGroupHelper),欢迎大家 star。  
机器人二维码: 

![微信交流群](https://raw.githubusercontent.com/sfyc23/image/master/vlog/20190614125724.png)


## 捐助
如果您认为这个项目有帮助,不妨为它捐助一点钱?

不管钱有多少,您的捐助将会激励作者持续开发新功能!🎉

感谢您的支持!

捐助方法如下:

![](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)

## LICENSE
[MIT License](https://github.com/sfyc23/EverydayWechat/blob/master/LICENSE)

================================================
FILE: everyday_wechat/__init__.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2019/6/23
# Author: snow

script_name = 'EverydayWechat'
__author__ = 'sfyc23'
__license__ = 'MIT'
__version__ = '0.3.27'



================================================
FILE: everyday_wechat/_config.yaml
================================================
# 配置文件请严格遵循 yaml 语法格式,yaml 学习地址:
#  https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html
#  http://einverne.github.io/post/2015/08/yaml.html

# 是否强制切换微信号 (2019年9月27日15:31:22 最近保存最近登录状态出错,所以此设置无效,每次登录得重新扫码。)
is_forced_switch: False

#---------------------------------------自动回复功能设置--------------------------------------start
auto_reply_info:
  # 是否开启自动回复
  is_auto_reply: True

  # 是否自动回复所有好友(慎重启动!),开启后,仅仅有黑名单的成员才不会自动回复
  is_auto_reply_all: False

  # 自动回复消息前缀(不需要则设置为空)
  auto_reply_prefix: ''
  # 自动回复消息后缀(不需要则设置为空)
  auto_reply_suffix: '--自动回复'

  # 白名单,is_auto_reply_all: False 生效。此名单的用户才可自动回复。(填:文件传输助手,可回复自己,测试效果)
  auto_reply_white_list:
    - '诗风'
    - '文件传输助手'

  # 黑名单,is_auto_reply_all:True 生效。此名单不会自动回复。
  auto_reply_black_list:
    - '贴心小秘书'

  # 机器人渠道(1: 图灵机器人,2: 一个AI ,3 : 青云客,4 腾讯智能闲聊,5:天行机器人,6:海知智能,7:思知机器人)
  bot_channel: 7

  #图灵机器人(http://www.tuling123.com/) 实名后的用户每天免费可用 100 条。
  turing_conf:
    apiKey: '你申请的apikey'

    # 天行机器人 ( https://www.tianapi.com/apiview/47 )。做完任务大概能免费用7万条,收费:1万条/1块钱
  txapi_conf:
    app_key: '个人中心中的key'
    reply_name: '宝宝' # 回复的人的名字(可空)(也可在个人中心->机器人管理 修改)
    bot_name: '老公' # 机器人的名字(可空)

  # 智能闲聊(腾讯)https://ai.qq.com/product/nlpchat.shtml。免费且无限量
  qqnlpchat_conf:
    app_id: '你申请的api_id'
    app_key: '你申请的app_key'

  # 海知智能 <https://ruyi.ai/> 功能很强大,不仅仅用于聊天。需申请 key,免费
  ruyi_conf:
    app_key: '你申请的key'

  # 思知机器人 <https://www.ownthink.com/> 免费,如果只是简单使用 app_key 可不申请。
  ownthink_conf:
    app_key: ''

  # 一个 Al (http://www.yige.ai/)(已长时间无人维护)
  yigeai_conf:
    client_token: '你申请的token'


#---------------------------------------自动回复功能设置--------------------------------------end



#---------------------------------------定时提醒功能设置--------------------------------------start
alarm_info:
  #True 开启定时提醒,False 关闭
  is_alarm: True

  girlfriend_infos:
    #女友微信昵称或者备注名,不能输入微信号。(如填:文件传输助手,发消息到文件传输助手,测试效果)
    - wechat_name:
        - '文件传输助手'
        - '诗风'
      # 注意:必须要把需要的群聊保存到通讯录
      group_name: # 群聊的名称
        - '萌萌哒'
        - '蕉群'
      alarm_timed: # 定时发送的时间
        - "13:25"
        - "00:33"
      alarm_jitter: 300 # 给定时时间加一个随机抖动 300 秒。定时时间【-5,+5】分钟范围内发送。(不然每天固定在同个时间段有点尴尬)(可空)
      is_tomorrow: True # 是否发送明日信息(如天气,星座,万年历)
      #女友所在城市,用于发送天气。(可空)
      city_name: '桂林'
      # 此城市的 pm2.5 值。
      air_quality_city: '桂林'
      # 格言渠道(1 : ONE●一个,2 : 词霸(每日英语,双语)3: 土味情话 4 : 一言,5:笑话,6 民国情书,7彩虹屁)(可空)
      dictum_channel: 1
      # 从哪天开始勾搭的(可空),配合 start_date_msg 使用。
      start_date: '2017-10-10'
      # 自定义方案(可空), {}表示用于占位,代表天数,与 start_date 一起使用。单填无意义
      #  默认为:『宝贝这是我们在一起的第{}天』,参考:爱你的第{}天
      start_date_msg: '宝贝这是我们在一起的第{}天'
      # 万历年(可空),(中老年最爱)
      calendar: True
      # 星座运势(可空)填生日日期:"1980-06-15" or "06-15" or "白羊座"
      horescope: "处女座"
      # 落款(可空),落款参考:['厌物', '你脚下的蚂蚁', '专说骗人的诳话者', '黄天霸', 'cxk', '魔鬼的叔父', '哺乳类脊椎动物之一', '名字写在水上的人', 'BIG BAD WOLF', '你的兄弟']
      sweet_words: '你脚下的蚂蚁'


    #  如果你需要另一套方案,如下面复制即可
    #  如不需要,则删除或注解下面所有的数据
    - group_name: 'EverydayWechat 交流1群'
      wechat_name: '贴心小秘书'
      city_name: '漳州'
      start_date: '2011-11-11'
      start_date_msg: '分手后的第{}天'
      dictum_channel: 4
      sweet_words: '名字写在水上的人'
      alarm_timed: "23:02"
      is_tomorrow: True
#---------------------------------------定时提醒功能设置--------------------------------------end



##---------------------------群聊助手设置--------------------------start
group_helper_conf:
  is_open: True # 开启群助手
  is_all: False # 是否对所有群开启。当开启时,只有黑名单的名单才不受影响(慎重开启!)

  # 白名单用户。当 is_all:Fase。只处理这个群里的消息
  group_name_white_list:
    - '蕉群'
    - '群机器人测试群'
    - '小号测试群'
    - 'EverydayWechat 交流1群'
    - 'EverydayWechat 交流2群'

  # 黑名单用户。当 is_all :True 。这个群里的用户不受影响。
  group_name_black_list:
    - 'EverydayWechat 交流1群'
    - 'EverydayWechat 交流2群'

  is_at: True # 艾特标记。只有当别人艾特机器人,才会处理消息(慎重关闭!)
  is_auto_reply: True # 开启群自动回复(慎重开启!)
  is_weather: True # 是否开启天气查询
  is_calendar: True # 是否开启万历年查询
  is_rubbish: True  # 是否开启垃圾查询
  is_moviebox: True # 是否开启电影票房
  is_air_quality: True # 是否开启快递查询。
  is_express: True # 是否开启快递查询
  express_info: # 快递鸟(http://www.kdniao.com/)
    app_id: '你申请的api_id'
    app_key: '你申请的app_key'


#--------------------------- 群聊助手设置 --------------------------end


# start ----------------------------------- 数据库设置 ----------------------------------- start
# 可不安装与设置数据库内容,数据库主要用于群助手功能中,查询数据的缓存。
db_config: # 请安装 mongodb 数据库
  is_open_db: True # 是否开启数据库功能
  mongodb_conf:
    'host': 'localhost'
    'port': 27017
#   end ----------------------------------- 数据库设置 ----------------------------------- end

================================================
FILE: everyday_wechat/control/__init__.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2019/6/23
# Author: snow


================================================
FILE: everyday_wechat/control/airquality/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-09-30 17:56
Introduction:
"""




================================================
FILE: everyday_wechat/control/airquality/air_quality_aqicn.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-09-30 17:58
Introduction: 获取空气质量
官网:http://aqicn.org/here/

"""

import requests

# token,申请地址:http://aqicn.org/data-platform/token/#/
AQICN_TOKEN = '6382db85ef321ae81f316486de0b5b8aa6c84f62'

AIR_STATUS_DICT = {
    50: '优',
    100: '良',
    150: '轻度污染',
    200: '中度污染',
    300: '重度污染',
    3000: '严重污染'
}


def get_air_quality(city):
    """
    通过城市名获取空气质量
    官网:http://aqicn.org/here/
    token 申请地址:http://aqicn.org/data-platform/token/#/
    :param city: 城市
    :return:
    """

    if not city or not city.strip():
        return
    print('获取 {} 的空气质量...'.format(city))
    try:

        url = 'http://api.waqi.info/feed/{city}/?token={token}'.format(city=city, token=AQICN_TOKEN)
        resp = requests.get(url)
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict.get('status') == 'ok':
                data_dict = content_dict['data']
                aqi = data_dict['aqi']
                air_status = '严重污染'
                for key in sorted(AIR_STATUS_DICT):
                    if key >= aqi:
                        air_status = AIR_STATUS_DICT[key]
                        break
                aqi_info = '{city} PM2.5:{aqi} {air_status}'.format(city=city, aqi=aqi, air_status=air_status)
                # print(aqi_info)
                return aqi_info
            else:
                print('获取空气质量失败:{}'.format(content_dict['data']))
                return None
        print('获取空气质量失败。')
    except Exception as exception:
        print(str(exception))
    return None


if __name__ == '__main__':
    city = '长沙'
    dd = get_air_quality(city)
    print(dd)


================================================
FILE: everyday_wechat/control/bot/__init__.py
================================================


================================================
FILE: everyday_wechat/control/bot/ownthink_robot.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-08-27 11:37
Introduction: 思知机器人,接口地址:<https://www.ownthink.com/> userid 可为空
"""
import re
import requests
from everyday_wechat.utils import config
from everyday_wechat.utils.common import (
    md5_encode
)

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 7
BOT_NAME = '思知机器人'


def get_ownthink_robot(text, userid):
    """
    思知机器人,接口地址:<https://www.ownthink.com/>
    https://api.ownthink.com/bot?appid=xiaosi&userid=user&spoken=姚明多高啊?
    :param text: 发出的消息
    :param userid: 收到的内容
    :return:
    """
    try:
        # config.init()
        info = config.get('auto_reply_info')['txapi_conf']
        app_key = info.get('app_key', '')
        if not re.findall(r'^[0-9a-z]{20,}$', app_key):  # 验证 app_key 是否有效
            app_key = ''

        params = {
            'appid': app_key,
            'userid': md5_encode(userid),
            'spoken': text
        }
        url = 'https://api.ownthink.com/bot'
        resp = requests.get(url, params=params)
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['message'] == 'success':
                data = content_dict['data']
                if data['type'] == 5000:
                    reply_text = data['info']['text']
                    return reply_text
                else:
                    print('返回的数据不是文本数据!')
            else:
                print('思知机器人获取数据失败:{}'.format(content_dict['msg']))

        print('获取数据失败')
        return None
    except Exception as exception:
        print(str(exception))


get_auto_reply = get_ownthink_robot

if __name__ == '__main__':
    text = '大胸'
    userid = '250'
    from_text = get_ownthink_robot(text, userid)
    print(from_text)


================================================
FILE: everyday_wechat/control/bot/qingyunke.py
================================================
# coding=utf-8

"""
http://api.qingyunke.com/
青云客智能聊天机器人API
可直接使用
"""
import requests

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 3
BOT_NAME = '青云客机器人'

URL = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg={}'


def get_qingyunke(text, userid=''):
    """
    青云客智能聊天机器人API http://api.qingyunke.com/
    :param text: str 聊天
    :param userid: str 无用
    :return: str
    """
    try:
        # print('发出消息:{}'.format(text))
        resp = requests.get(URL.format(text))
        if resp.status_code == 200:
            # print(resp.text)
            re_data = resp.json()
            if re_data['result'] == 0:
                return_text = re_data['content']
                return return_text

            error_text = re_data['content']
            print('青云客机器人错误信息:{}'.format(error_text))

        print('青云客机器人获取失败')
    except Exception as exception:
        print(str(exception))
        print('青云客机器人获取失败')


get_auto_reply = get_qingyunke

if __name__ == '__main__':
    text = '微博加个关注呗'
    userid = '250'
    rt = get_qingyunke(text, userid)
    print('回复:', rt)
    pass


================================================
FILE: everyday_wechat/control/bot/qq_nlpchat.py
================================================
# -*- coding: utf-8 -*-
"""
Project: HelloWorldPython
Creator: DoubleThunder
Create time: 2019-07-01 23:49
Introduction: 智能闲聊(腾讯)
官网:https://ai.qq.com/product/nlpchat.shtml
免费试用,得申请 app_id,app_key。
"""

import hashlib
from urllib import parse
import time
import random
import string
import requests
from everyday_wechat.utils.common import (
    md5_encode
)
from everyday_wechat.utils import config

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 4
BOT_NAME = '腾讯智能闲聊'

URL = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat'


def get_nlp_textchat(text, userId):
    """
    智能闲聊(腾讯)<https://ai.qq.com/product/nlpchat.shtml>
    接口文档:<https://ai.qq.com/doc/nlpchat.shtml>
    :param text: 请求的话
    :param userId: 用户标识
    :return: str
    """
    try:

        # config.init()
        info = config.get('auto_reply_info')['qqnlpchat_conf']
        app_id = info['app_id']
        app_key = info['app_key']
        if not app_id or not app_key:
            print('app_id 或 app_key 为空,请求失败')
            return

        # 产生随机字符串
        nonce_str = ''.join(random.sample(
            string.ascii_letters + string.digits, random.randint(10, 16)))
        time_stamp = int(time.time())  # 时间戳
        params = {
            'app_id': app_id,  # 应用标识
            'time_stamp': time_stamp,  # 请求时间戳(秒级)
            'nonce_str': nonce_str,  # 随机字符串
            'session': md5_encode(userId),  # 会话标识
            'question': text  # 用户输入的聊天内容
        }
        # 签名信息
        params['sign'] = getReqSign(params, app_key)
        resp = requests.get(URL, params=params)
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['ret'] == 0:
                data_dict = content_dict['data']
                return data_dict['answer']

            print('智能闲聊 获取数据失败:{}'.format(content_dict['msg']))
            return None
    except Exception as exception:
        print(str(exception))


def getReqSign(parser, app_key):
    '''
    获取请求签名,接口鉴权 https://ai.qq.com/doc/auth.shtml
    1.将 <key, value> 请求参数对按 key 进行字典升序排序,得到有序的参数对列表 N
    2.将列表 N 中的参数对按 URL 键值对的格式拼接成字符串,得到字符串 T(如:key1=value1&key2=value2),
        URL 键值拼接过程 value 部分需要 URL 编码,URL 编码算法用大写字母,例如 %E8,而不是小写 %e8
    3.将应用密钥以 app_key 为键名,组成 URL 键值拼接到字符串 T 末尾,得到字符串 S(如:key1=value1&key2=value2&app_key = 密钥)
    4.对字符串 S 进行 MD5 运算,将得到的 MD5 值所有字符转换成大写,得到接口请求签名
    :param parser: dect
    :param app_key: str
    :return: str,签名
    '''
    params = sorted(parser.items())
    uri_str = parse.urlencode(params, encoding="UTF-8")
    sign_str = '{}&app_key={}'.format(uri_str, app_key)
    # print('sign =', sign_str.strip())
    hash_md5 = hashlib.md5(sign_str.encode("UTF-8"))
    return hash_md5.hexdigest().upper()


get_auto_reply = get_nlp_textchat

if __name__ == '__main__':
    to_text = '你会爱我吗'
    userId = 'userId'
    # userId = 250
    form_text = get_nlp_textchat(to_text, userId)
    print(form_text)
    # print()

================================================
FILE: everyday_wechat/control/bot/ruyiai.py
================================================
# -*- coding: utf-8 -*-
"""
Project: HelloWorldPython
Creator: DoubleThunder
Create time: 2019-07-02 02:46
Introduction: 海知智能 <https://ruyi.ai/> 功能很强大,不仅仅用于聊天。需申请 key,免费
"""
import requests
from everyday_wechat.utils import config
from everyday_wechat.utils.common import (
    md5_encode
)

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 6
BOT_NAME = '海知智能机器人'

URL = 'http://api.ruyi.ai/v1/message'


def get_ruyiai_bot(text, userId):
    """
    海知智能 文档说明:<http://docs.ruyi.ai/502931>
    :param text: str 需要发送的话
    :param userId: str 用户标识
    :return: str 机器人回复
    """
    try:
        # config.init()
        info = config.get('auto_reply_info')['ruyi_conf']
        app_key = info['app_key']
        if not app_key:
            print('海知智能 api_key 为空,请求失败')
            return

        params = {'q': text, 'user_id': md5_encode(userId), 'app_key': app_key}
        headers = {'Content-Type': 'application/json'}
        resp = requests.get(URL, headers=headers, params=params)
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['code'] in (0, 200):
                outputs = content_dict['result']['intents'][0]['outputs']
                reply_text = outputs[0]['property']['text']
                # print(reply_text)
                return reply_text
            else:
                print('海知智能 获取数据失败:{}'.format(content_dict['msg']))
                return
        print('海知智能 获取数据失败')
        return None
    except Exception as exception:
        print(str(exception))


get_auto_reply = get_ruyiai_bot

if __name__ == '__main__':
    # text = '我要飞的更高'
    # userid = '250'
    # from_text = get_auto_reply(text, userid)
    # print(from_text)
    pass


================================================
FILE: everyday_wechat/control/bot/tian_robot.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-02 01:24
Introduction: 天行机器人 申请地址( https://www.tianapi.com/apiview/47 )
"""
import requests
from everyday_wechat.utils import config
from everyday_wechat.utils.common import (
    md5_encode
)

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 5
BOT_NAME = '天行机器人'


def get_tianapi_robot(text, userid):
    """
    从天行机器人获取自动回复,接口地址:<https://www.tianapi.com/apiview/47>
    :param text: 发出的消息
    :param userid: 收到的内容
    :return:
    """
    try:
        # config.init()
        info = config.get('auto_reply_info')['txapi_conf']
        app_key = info['app_key']
        if not app_key:
            print('天行机器人 app_key 为空,请求失败')
            return
        reply_name = info.get('reply_name', '')
        bot_name = info.get('bot_name', '')

        params = {
            'key': app_key,
            'question': text,
            'userid': md5_encode(userid),
            'limit': 10,  # 机器人分析系数,取值1-10
            'mode': 1,  # 图文返回数量,取值1-10
            'datatype': '0',  # 返回类型,文本0[默认]、语音1
        }
        url = 'https://api.tianapi.com/txapi/robot/'
        resp = requests.get(url, params=params)
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['code'] == 200:
                if content_dict['datatype'] == 'text':
                    data_dict = content_dict['newslist']
                    reply_text = data_dict[0]['reply']
                    reply_text.replace('{robotname}', bot_name) \
                        .replace('{appellation}', reply_name)
                    return reply_text
                else:
                    return '我不太懂你在说什么'
            else:
                print('天行机器人获取数据失败:{}'.format(content_dict['msg']))

        print('获取数据失败')
        return None
    except Exception as exception:
        print(str(exception))


get_auto_reply = get_tianapi_robot

if __name__ == '__main__':
    text = '我是你的谁'
    userid = '250'
    from_text = get_tianapi_robot(text, userid)
    print(from_text)


================================================
FILE: everyday_wechat/control/bot/tuling123.py
================================================
# coding=utf-8

'''
图灵机器人自动回复
官网:http://www.tuling123.com/
apiKey,userid 需要去官网申请。
'''

import requests
from everyday_wechat.utils.common import (
    is_json,
    md5_encode
)
from everyday_wechat.utils import config

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 1
BOT_NAME = '图灵机器人'

# 图灵机器人错误码集合
TULING_ERROR_CODE_LIST = (
    5000, 6000, 4000, 4001, 4002,
    4003, 4005, 4007, 4100, 4200,
    4300, 4400, 4500, 4600, 4602,
    7002, 8008, 0)
URL = "http://openapi.tuling123.com/openapi/api/v2"


def get_tuling123(text, userId):
    """
    接口地址:(https://www.kancloud.cn/turing/www-tuling123-com/718227)
    获取图灵机器人对话
    :param text: 发送的话
    :param userId: 用户唯一标识(最好用微信好友uuid)
    :return: 对白
    """
    try:
        # config.init()
        info = config.get('auto_reply_info')['turing_conf']
        apiKey = info['apiKey']

        if not apiKey:
            print('图灵机器人 apikey 为空,请求出错')
            return None
        userId = md5_encode(userId if userId else '250')

        content = {
            'perception': {
                'inputText': {
                    'text': text
                }
            },
            'userInfo': {
                'apiKey': apiKey,
                'userId': userId
            }
        }
        # print('发出消息:{}'.format(text))
        resp = requests.post(URL, json=content)
        if resp.status_code == 200 and is_json(resp):
            # print(resp.text)
            re_data = resp.json()
            if re_data['intent']['code'] not in TULING_ERROR_CODE_LIST:
                return_text = re_data['results'][0]['values']['text']
                return return_text

            error_text = re_data['results'][0]['values']['text']
            print('图灵机器人错误信息:{}'.format(error_text))
            return None

        print('图灵机器人获取数据失败')
    except Exception as exception:
        print(str(exception))
        print('图灵机器人获取数据失败')


get_auto_reply = get_tuling123

if __name__ == '__main__':
    # text = '雷军 are you ok?'
    # reply = get_auto_reply(text, 'WE')
    # print(reply)
    pass


================================================
FILE: everyday_wechat/control/bot/yigeai.py
================================================
#
"""
『一个AI』自动回复 (http://www.yige.ai/)
"""
import requests

from everyday_wechat.utils.common import (
    is_json,
    md5_encode,
)

from everyday_wechat.utils import config

__all__ = ['get_auto_reply', 'BOT_INDEX', 'BOT_NAME']
BOT_INDEX = 2
BOT_NAME = '一个 AI 机器人'

# 一个AI错误集合
TULING_ERROR_CODE_LIST = ('501', '502', '503', '504', '507', '510')


def get_yigeai(text, userid):
    """
    『一个AI』自动回复 (http://www.yige.ai/)
    接口说明:http://docs.yige.ai/Query%E6%8E%A5%E5%8F%A3.html
    :param text:str, 需要发送的话
    :userid:str,机器唯一标识
    :return:str
    """
    try:
        # config.init()
        info = config.get('auto_reply_info')['yigeai_conf']
        token = info['client_token']
        if not token:
            print('一个「AI」token 为空,请求出错')
            return None
        session_id = md5_encode(userid if userid else '250')

        # print('发出的消息:{}'.format(text))
        data = {'token': token, 'query': text, 'session_id': session_id}
        resp = requests.post('http://www.yige.ai/v1/query', data=data)
        if resp.status_code == 200 and is_json(resp):
            # print(resp.text)
            re_data = resp.json()
            code = re_data['status']['code']
            # 错误码返回有时是数字,有点是str。一起做处理
            if code and str(code) not in TULING_ERROR_CODE_LIST:
                return_text = re_data['answer']
                return return_text
            error_text = re_data['status']['error_type']
            print('『一个AI』机器人错误信息:{}'.format(error_text))
            return None
        print('『一个AI』机器人获取数据失败')
    except Exception as e:
        print(e)
        print('『一个AI』机器人获取数据失败')


get_auto_reply = get_yigeai

if __name__ == '__main__':
    # text = '我爱北京'
    # rt = get_auto_reply(text, 'dd--00')
    # print('回复:', rt)
    pass


================================================
FILE: everyday_wechat/control/calendar/__init__.py
================================================


================================================
FILE: everyday_wechat/control/calendar/rt_calendar.py
================================================
# coding=utf-8
"""
https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息
指定日期的节假日及万年历信息

{"code":1,"msg":"数据返回成功","data":{
"date":"2019-06-27","weekDay":4,"yearTips":"己亥",
"type":0,"typeDes":"工作日","chineseZodiac":"猪","solarTerms":"夏至后",
"avoid":"移徙.入宅.安葬","lunarCalendar":"五月廿五",
"suit":"订盟.纳采.出行.祈福.斋醮.安床.会亲友",
"dayOfYear":178,"weekOfYear":26,"constellation":"巨蟹座"}}
"""

from datetime import datetime
import requests

__all__ = ['STFT', 'WEEK_DICT', 'get_rtcalendar']

# Twenty-four solar terms list 二十四节气名称
STFT = (
    "冬至", "小寒", "大寒", "立春", "雨水", "惊蛰",
    "春分", "清明", "谷雨", "立夏", "小满", "芒种",
    "夏至", "小暑", "大暑", "立秋", "处暑", "白露",
    "秋分", "寒露", "霜降", "立冬", "小雪", "大雪")

WEEK_DICT = {1: '星期一', 2: '星期二', 3: '星期三', 4: '星期四', 5: '星期五', 6: '星期六', 7: '星期日'}


def get_rtcalendar(date=''):
    """
    获取指定日期的节假日及万年历信息
     https://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息
    :param data: str 日期 格式 yyyyMMdd
    :rtype str
    """

    date_ = date or datetime.now().strftime('%Y%m%d')

    print('获取 {} 的日历...'.format(date_))
    try:
        resp = requests.get('https://www.mxnzp.com/api/holiday/single/{}'.format(date_))
        if resp.status_code == 200:
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['code'] == 1:
                data_dict = content_dict['data']
                solar_terms = data_dict.get('solarTerms', '')
                if solar_terms not in STFT:
                    solar_terms = ''

                suit = data_dict['suit']
                suit = suit if suit else '无'
                avoid = data_dict['avoid']
                avoid = avoid if avoid else '无'
                return_text = '{data} {week} 农历{lunarCalendar} {solarTerms}\n【宜】{suit}\n【忌】{avoid}'.format(
                    data=data_dict['date'],
                    week=WEEK_DICT[data_dict['weekDay']],
                    lunarCalendar=data_dict['lunarCalendar'],
                    solarTerms=solar_terms,
                    suit=suit,
                    avoid=avoid,
                )
                return return_text
            else:
                print('获取日历失败:{}'.format(content_dict['msg']))
                return None

        print('获取日历失败。')
    except Exception as exception:
        print(str(exception))
    return None


get_calendar = get_rtcalendar

if __name__ == '__main__':
    # date = (datetime.now() + timedelta(days=1)).strftime('%Y%m%d')
    date = '201889'
    content = get_calendar(date)
    print(content)
    pass


================================================
FILE: everyday_wechat/control/calendar/sojson_calendar.py
================================================
# coding=utf-8
"""
https://www.sojson.com/api/lunar.html
指定日期的节假日及万年历信息
"""
from datetime import datetime
import requests
from everyday_wechat.utils.common import (
    WEEK_DICT,
    SPIDER_HEADERS
)

__all__ = ['get_sojson_calendar']


def get_sojson_calendar(date=''):
    """
    获取指定日期的节假日及万年历信息
     https://www.sojson.com/api/lunar.html
    :param data: str 日期 格式 %Y-%m-%d
    :rtype str
    """
    date_ = date or datetime.now().strftime('%Y-%m-%d')
    # print('获取 {} 的日历...'.format(date_))
    try:
        resp = requests.get('https://www.sojson.com/open/api/lunar/json.shtml?date={}'.format(date_),
                            headers=SPIDER_HEADERS)
        if resp.status_code == 200:
            """
            {"code":1,"msg":"数据返回成功","data":{
            "date":"2019-06-27","weekDay":4,"yearTips":"己亥",
            "type":0,"typeDes":"工作日","chineseZodiac":"猪","solarTerms":"夏至后",
            "avoid":"移徙.入宅.安葬","lunarCalendar":"五月廿五",
            "suit":"订盟.纳采.出行.祈福.斋醮.安床.会亲友",
            "dayOfYear":178,"weekOfYear":26,"constellation":"巨蟹座"}}
            """
            # print(resp.text)
            content_dict = resp.json()
            if content_dict['status'] == 200:
                data_dict = content_dict['data']
                # 农历
                lunar_calendar = '{}月{}'.format(data_dict['cnmonth'], data_dict['cnday'])
                # 二十四节气
                # solarTerms = data_dict['jieqi'].get(str(data_dict['day']), '')
                # print(data_dict['jieqi'])
                suit = data_dict['suit']
                suit = suit if suit else '无'
                taboo = data_dict['taboo']
                taboo = taboo if taboo else '无'
                return_text = '{date} {week} 农历{lunarCalendar}\n【宜】{suit}\n【忌】{taboo}'.format(
                    date=date,
                    week=WEEK_DICT[data_dict['week']],
                    lunarCalendar=lunar_calendar,
                    suit=suit,
                    taboo=taboo,
                )
                return return_text
            else:
                print('获取日历失败:{}'.format(content_dict['message']))

        print('获取日历失败。')
    except Exception as exception:
        print(str(exception))
    return None


get_calendar = get_sojson_calendar

if __name__ == '__main__':
    # date = datetime.now().strftime('%Y-%m-%d')
    # date = '2018-11-06'
    # content = get_calendar(date)
    # print(content)
    pass


================================================
FILE: everyday_wechat/control/express/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-09-04 12:23
Introduction:
"""




================================================
FILE: everyday_wechat/control/express/kdniao_express.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-09-04 12:24
Introduction: 快递鸟(http://www.kdniao.com/) 快递查询
"""

import json
import hashlib
import base64
import requests

from everyday_wechat.utils import config

# 此处为快递鸟官网申请的帐号和密码

URL = 'http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx'
HEADERS = {
    "Accept": "application/x-www-form-urlencoded;charset=utf-8",
    "Accept-Encoding": "utf-8"
}
# 2-在途中,3-签收,4-问题件
EXPRESS_STATE_DICT = {'0': '无物流', '2': '在途中', '3': '签收', '4': '问题件'}
__all__ = ['get_express_info']


def encrypt(origin_data, app_key):
    """
    数据内容签名:把(请求内容(未编码) + AppKey)进行 MD5 加密,然后 Base64 编码
    :param origin_data: str, 请求的数据
    :param app_key:
    :return: 加密后的数据
    """
    encodestr = hashlib.md5((origin_data + app_key).encode("UTF-8")).hexdigest()  # MD5 加密
    base64_text = base64.b64encode(encodestr.encode(encoding='utf-8'))  # Base64 加密
    return base64_text.decode()  # 再次编码


def get_company_info(express_code, app_id, app_key):
    """
    单号识别 API 接口。地址:http://www.kdniao.com/api-recognise
    查询订单号的归属物流公司信息
    :param express_code: str 订单号
    :return: str 订单信息
    """
    data1 = {'LogisticCode': express_code}
    d1 = json.dumps(data1, sort_keys=True)
    post_data = {
        'RequestData': d1,
        'EBusinessID': app_id,
        'RequestType': '2002',
        'DataType': '2',
        'DataSign': encrypt(d1, app_key)
    }
    try:
        resp = requests.post(URL, data=post_data, headers=HEADERS)
        print(resp.text)
        if resp.status_code == 200:
            content_dict = resp.json()
            if not content_dict['Success']:
                print('出错原因:{}'.format(content_dict['Reason']))
                return None
            elif not any(content_dict['Shippers']):
                print("未查到该快递信息,请检查快递单号是否有误!")
                return None
            else:
                shipper_info = content_dict['Shippers'][0]
                shipper_name = shipper_info['ShipperName']
                shipper_code = shipper_info['ShipperCode']
                xx = '快递单号 {ecode} 的快递公司是:{sname}({scode})'.format(
                    sname=shipper_name,
                    scode=shipper_code,
                    ecode=express_code)
                print(xx)
                return {'shipper_code': shipper_code, 'shipper_name': shipper_name}

    except Exception as exception:
        print(str(exception))

    return None


def get_logistic_info(logistic_code, shipper_code, app_id, app_key):
    """
    即时查询 api 接口。地址:http://www.kdniao.com/api-track
    对单个订单号进行查询详细的物流信息
    :param logistic_code: str, 订单号
    :param shipper_code: str, 快递公司编号
    :return:
    """
    data1 = {'OrderCode': '', 'LogisticCode': logistic_code, 'ShipperCode': shipper_code}
    d1 = json.dumps(data1, sort_keys=True)
    post_data = {
        'RequestData': d1,
        'EBusinessID': app_id,
        'RequestType': '1002',
        # 'RequestType': '1008',
        'DataType': '2',
        'DataSign': encrypt(d1, app_key)
    }
    try:
        resp = requests.post(URL, data=post_data, headers=HEADERS)
        print(resp.text)
        if resp.status_code == 200:
            content_dict = resp.json()
            if not content_dict['Success']:
                print('出错原因:{}'.format(content_dict['Reason']))
                return None
            elif not any(content_dict['Traces']):
                print("未查询到该快递物流轨迹!")
                return None
            else:
                return content_dict
    except Exception as exception:
        print(str(exception))
    return None


def get_express_info(express_code, shipper_code='', shipper_name=''):
    """
    查询快递物流信息
    :param express_code: str,快递单号
    :param shipper_code: str,快递公司简称代号
    :param shipper_name: str,快递公司名称(用于结果显示)
    :return:
    """
    express_config_info = config.get('group_helper_conf')['express_info']
    app_id = express_config_info['app_id']
    app_key = express_config_info['app_key']
    if not shipper_code or not shipper_name:
        company_info = get_company_info(express_code, app_id, app_key)
        # print(company_info)
        if not company_info:
            return
        shipper_code = company_info['shipper_code']
        shipper_name = company_info['shipper_name']
    trace_data = get_logistic_info(express_code, shipper_code, app_id, app_key)
    print(trace_data)
    if not trace_data:
        return
    state_code = trace_data['State']
    express_state = EXPRESS_STATE_DICT.get(state_code, '未知状态')

    info = []
    express_base_info = '物流公司:{shipper_name}\n物流单号:{express_code}\n物流状态:{express_state}'.format(
        shipper_name=shipper_name,
        express_code=express_code,
        express_state=express_state)
    info.append(express_base_info)
    info.append('------物流详情------')
    traces = trace_data['Traces']
    for i, item in enumerate(traces[::-1]):
        bb = '{index}. {time} {station}'.format(
            index=str(i + 1),
            time=item['AcceptTime'],
            station=item['AcceptStation'])
        # print(bb)
        info.append(bb)
    return_info = {
        'express_code': express_code,
        'shipper_code': shipper_code,
        'shipper_name': shipper_name,
        'info': '\n'.join(info),
        'state': True if state_code == '3' else False
    }
    return return_info


if __name__ == '__main__':
    code = '78109182715352'
    code = '78109356970791'
    # code = '9860572561560'
    # code = 'JD0001855864185'
    cc = get_express_info(code)
    print(cc)
    if cc:
        print(cc['info'])


================================================
FILE: everyday_wechat/control/horoscope/__init__.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-

"""
    星座运势,基于 星座屋 爬取
"""


================================================
FILE: everyday_wechat/control/horoscope/xzw_horescope.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
"""
    爬取 星座屋 星座运势
    https://www.xzw.com/
"""
import re
from functools import reduce
import requests
from bs4 import BeautifulSoup
from everyday_wechat.utils.common import SPIDER_HEADERS

__all__ = ['get_xzw_horoscope', 'get_today_horoscope']

XZW_BASE_URL_TODAY = "https://www.xzw.com/fortune/{}"
XZW_BASE_URL_TOMORROW = "https://www.xzw.com/fortune/{}/1.html"
CONSTELLATION_DICT = {
    "白羊座": "aries",
    "金牛座": "taurus",
    "双子座": "gemini",
    "巨蟹座": "cancer",
    "狮子座": "leo",
    "处女座": "virgo",
    "天秤座": "libra",
    "天蝎座": "scorpio",
    "射手座": "sagittarius",
    "摩羯座": "capricorn",
    "水瓶座": "aquarius",
    "双鱼座": "pisces",
}


def get_xzw_horoscope(name, is_tomorrow=False):
    '''
    获取星座屋(https://www.xzw.com)的星座运势
    :param name: 星座名称
    :return:
    '''
    if not name in CONSTELLATION_DICT:
        print('星座输入有误')
        return
    try:
        const_code = CONSTELLATION_DICT[name]

        req_url = XZW_BASE_URL_TOMORROW.format(const_code) if is_tomorrow \
            else XZW_BASE_URL_TODAY.format(const_code)

        resp = requests.get(req_url, headers=SPIDER_HEADERS)
        if resp.status_code == 200:
            html = resp.text
            lucky_num = re.findall(r'<label>幸运数字:</label>(.*?)</li>', html)[0]
            lucky_color = re.findall(r'<label>幸运颜色:</label>(.*?)</li>', html)[0]
            detail_horoscope = re.findall(r'<p><strong class="p1">.*?</strong><span>(.*?)</span></p>', html)[0]
            if is_tomorrow:
                detail_horoscope = detail_horoscope.replace('今天', '明天')

            return_text = '{name}{_date}运势\n【幸运颜色】{color}\n【幸运数字】{num}\n【综合运势】{horoscope}'.format(
                _date='明日' if is_tomorrow else '今日',
                name=name,
                color=lucky_color,
                num=lucky_num,
                horoscope=detail_horoscope
            )
            return return_text
    except Exception as exception:
        print(str(exception))


get_today_horoscope = get_xzw_horoscope

if __name__ == '__main__':
    # print (get_constellation(3, 10))
    # print(get_xzw_text("03-18"))
    is_tomorrow = True
    print(get_xzw_horoscope("水瓶座", is_tomorrow))


================================================
FILE: everyday_wechat/control/moviebox/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-08-30 12:21
Introduction:
"""




================================================
FILE: everyday_wechat/control/moviebox/maoyan_movie_box.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-08-30 12:22
Introduction: 猫眼实时票房 地址:https://piaofang.maoyan.com/dashboard
接口地址:https://piaofang.maoyan.com/second-box?beginDate=20190924

"""
import requests

from datetime import datetime
from everyday_wechat.utils.common import SPIDER_HEADERS


def get_maoyan_movie_box(date='', is_expired=False):
    """
     获取特定日期的实时票房日期
     https://piaofang.maoyan.com/second-box?beginDate=20190830#指定日期的节假日及万年历信息
    :param date: str 日期 格式 yyyyMMdd
    :param is_expired
    :rtype str
    """
    date_ = date or datetime.now().strftime('%Y%m%d')

    print('获取 {} 的票房数据...'.format(date_))
    # try:
    url = 'https://piaofang.maoyan.com/second-box?beginDate={}'.format(date_)
    resp = requests.get(url, headers=SPIDER_HEADERS)
    # print(resp)
    if resp.status_code == 200:
        # print(resp.text)
        content_dict = resp.json()
        if content_dict['success']:
            data_dict = content_dict['data']
            total_box_info = data_dict['totalBoxInfo']
            box_list = data_dict['list']
            box_info_list = []

            for i, r in enumerate(box_list[:10]):
                movice_name = r['movieName']
                box_info = r['boxInfo']
                sumBoxInfo = r['sumBoxInfo']
                box_info_list.append('{}.《{}》({}万,累积:{})'.format(str(i + 1), movice_name, box_info, sumBoxInfo))

            cur_date = datetime.strptime(date_, '%Y%m%d').strftime('%Y{}%m{}%d{}').format('年', '月', '日')

            return_text = "{cur_date} {box_name}\n当日总票房:{total_box_info}万\n{box_info}".format(
                cur_date=cur_date,
                box_name="实时票房" if is_expired else "当日票房",
                total_box_info=total_box_info,
                box_info='\n'.join(box_info_list)
            )

            return return_text
        else:
            print('获取票房失败:{}'.format(content_dict['msg']))
            return None

    print('获取票房失败。')
    # except Exception as exception:
    #     print(str(exception))
    return None


# __date = '20190925'
# dd = get_maoyan_movie_box(__date, is_expired=False)
# print(dd)



================================================
FILE: everyday_wechat/control/onewords/__init__.py
================================================


================================================
FILE: everyday_wechat/control/onewords/acib.py
================================================
# coding=utf-8

"""
从词霸中获取每日一句,带英文。
"""

import requests
from everyday_wechat.utils.common import (
    is_json
)

__all__ = ['get_acib_info']


def get_acib_info():
    """
    从词霸中获取每日一句,带英文。
    :return:str ,返回每日一句(双语)
    """
    print('获取格言信息(双语)...')
    try:
        resp = requests.get('http://open.iciba.com/dsapi')
        if resp.status_code == 200 and is_json(resp):
            content_dict = resp.json()
            content = content_dict.get('content')
            note = content_dict.get('note')
            return '{}{}'.format(content, note)

        print('没有获取到格言数据。')
    except requests.exceptions.RequestException as exception:
        print(exception)
    return None


get_one_words = get_acib_info


================================================
FILE: everyday_wechat/control/onewords/caihongpi.py
================================================
# coding=utf-8
"""
https://chp.shadiao.app/?from_nmsl
彩虹屁生成器
 """
import requests

__all__ = ['get_caihongpi_info']


def get_caihongpi_info():
    """
    彩虹屁生成器
    :return: str,彩虹屁
    """
    print('获取彩虹屁信息...')
    try:
        resp = requests.get('https://chp.shadiao.app/api.php')
        if resp.status_code == 200:
            return resp.text
        print('彩虹屁获取失败。')
    except requests.exceptions.RequestException as exception:
        print(exception)
        # return None
    # return None


get_one_words = get_caihongpi_info

if __name__ == '__main__':
    ow = get_one_words()
    print(ow)
    pass


================================================
FILE: everyday_wechat/control/onewords/hitokoto.py
================================================
# coding=utf-8
"""
获取一言信息<https://hitokoto.cn/>
"""

import requests

__all__ = ['get_hitokoto_info']


def get_hitokoto_info():
    """
    从『一言』获取信息。(官网:https://hitokoto.cn/)
    :return: str,一言。
    """
    print('获取一言...')
    try:
        resp = requests.get('https://v1.hitokoto.cn/', params={'encode': 'text'})
        if resp.status_code == 200:
            return resp.text
        print('一言获取失败。')
    except requests.exceptions.RequestException as exception:
        print(exception)
        # return None
    # return None


get_one_words = get_hitokoto_info


================================================
FILE: everyday_wechat/control/onewords/juzimi.py
================================================
# coding=utf-8
"""
句子迷:(https://www.juzimi.com/)
民国情书:朱生豪先生的情话 && 爱你就像爱生命
Author: ClaireYiu(https://github.com/ClaireYiu)
"""
import random
import requests


# from requests_html import HTMLSession


def get_zsh_info():
    """
    句子迷:(https://www.juzimi.com/)
    朱生豪:https://www.juzimi.com/writer/朱生豪
    爱你就像爱生命(王小波):https://www.juzimi.com/article/爱你就像爱生命
    三行情书:https://www.juzimi.com/article/25637
    :return: str 情话
    """
    print('正在获取民国情话...')
    try:
        name = [
            ['writer/朱生豪', 38, ],
            ['article/爱你就像爱生命', 22],
            ['article/25637', 55],
        ]
        apdix = random.choice(name)
        # page 从零开始计数的。
        url = 'https://www.juzimi.com/{}?page={}'.format(
            apdix[0], random.randint(1, apdix[1]))
        # print(url)
        resp = requests.get(url)
        if resp.status_code == 200:
            # print(resp.html)
            # results = resp.find('a.xlistju')
            # if results:
            #     re_text = random.choice(results).text
            #     if re_text and '\n\n' in re_text:
            #         re_text = re_text.replace('\n\n','\n')
            #     return re_text
            return None
        print('获取民国情话失败..')
    except Exception as exception:
        print(exception)
    return None


get_one_words = get_zsh_info

if __name__ == '__main__':
    # for _ in range(15):
    #     ow = get_one_words()
    #     print(ow)
    pass


================================================
FILE: everyday_wechat/control/onewords/lovelive.py
================================================
# coding=utf-8
"""
从土味情话中获取每日一句。
 """
import requests

__all__ = ['get_lovelive_info']


def get_lovelive_info():
    """
    从土味情话中获取每日一句。
    :return: str,土味情话。
    """
    print('获取土味情话...')
    try:
        resp = requests.get('https://api.lovelive.tools/api/SweetNothings')
        if resp.status_code == 200:
            return resp.text
        print('土味情话获取失败。')
    except requests.exceptions.RequestException as exception:
        print(exception)
        # return None
    return None


get_one_words = get_lovelive_info


================================================
FILE: everyday_wechat/control/onewords/rtjokes.py
================================================
# coding=utf-8
"""
https://github.com/MZCretin/RollToolsApi#随机获取笑话段子列表
随机获取笑话段子列表
"""
import requests

__all__ = ['get_rtjokes_info']


def get_rtjokes_info():
    """
    随机获取笑话段子列表(https://github.com/MZCretin/RollToolsApi#随机获取笑话段子列表)
    :return: str,笑话。
    """
    print('获取随机笑话...')
    try:
        resp = requests.get('https://www.mxnzp.com/api/jokes/list/random')
        # print(resp.text)
        if resp.status_code == 200:
            content_dict = resp.json()
            if content_dict['code'] == 1:
                # 每次返回 10 条笑话信息,只取一次
                return_text = content_dict['data'][0]['content']
                # print(return_text)
                return return_text
            else:
                print(content_dict['msg'])
        print('获取笑话失败。')
    except Exception as exception:
        print(exception)
        return None
    return None


get_one_words = get_rtjokes_info

if __name__ == '__main__':
    get_rtjokes_info()


================================================
FILE: everyday_wechat/control/onewords/wufazhuce.py
================================================
# coding=utf-8
"""
从「一个」获取每日一言
"""
import requests
from bs4 import BeautifulSoup
from everyday_wechat.utils.common import SPIDER_HEADERS

__all__ = ['get_wufazhuce_info']


def get_wufazhuce_info():
    """
    获取格言信息(从『一个。one』获取信息 http://wufazhuce.com/)
    :return: str, 一句格言或者短语。
    """
    print('获取 ONE 信息...')
    user_url = 'http://wufazhuce.com/'
    try:
        resp = requests.get(user_url, headers=SPIDER_HEADERS)
        if resp.status_code == 200:
            soup_texts = BeautifulSoup(resp.text, 'lxml')
            # 『one -个』 中的每日一句
            every_msg = soup_texts.find('div', class_='fp-one-cita').text  # 只取当天的这句
            return every_msg
        print('获取 ONE 失败。')
    except Exception as exception:
        print(str(exception))
        return None
    return None


get_one_words = get_wufazhuce_info


================================================
FILE: everyday_wechat/control/rubbish/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-14 01:00
Introduction:
"""




================================================
FILE: everyday_wechat/control/rubbish/atoolbox_rubbish.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-14 01:02
Introduction: http://www.atoolbox.net/Tool.php?Id=804
"""

import requests
from everyday_wechat.utils.common import SPIDER_HEADERS

__all__ = ['get_atoolbox_rubbish']


def get_atoolbox_rubbish(key):
    """
    # http://www.atoolbox.net/Tool.php?Id=804
    :param key:
    :return:
    """
    params = {'key': key}
    resp = requests.get('http://www.atoolbox.net/api/GetRefuseClassification.php',
                        headers=SPIDER_HEADERS,
                        params=params)

    if resp.status_code == 200:
        # print(resp.text)
        content_dict = resp.json()
        if not content_dict:
            return None, None, None
        return_list = list(content_dict.values())
        _type = ''
        for rl in return_list:
            if key == rl['name']:
                _type = rl['type']
                break
        other = ''
        if not _type:
            other = ' '.join(i['name'] for i in return_list[:6])
        return _type, return_list, other
    return None, None, None


================================================
FILE: everyday_wechat/control/weather/__init__.py
================================================


================================================
FILE: everyday_wechat/control/weather/_city_sojson.json
================================================
{
   "北京": "101010100",
   "上海": "101020100",
   "天津": "101030100",
   "重庆": "101040100",
   "香港": "101320101",
   "澳门": "101330101",
   "安庆": "101220601",
   "蚌埠": "101220201",
   "巢湖市": "101220105",
   "池州": "101221701",
   "滁州": "101221101",
   "阜阳": "101220801",
   "淮北": "101221201",
   "淮南": "101220401",
   "黄山市": "101221001",
   "六安": "101221501",
   "马鞍山": "101220501",
   "宿州": "101220701",
   "铜陵": "101221301",
   "芜湖市": "101220301",
   "宣城": "101221401",
   "亳州": "101220901",
   "福州": "101230101",
   "龙岩": "101230701",
   "南平": "101230901",
   "宁德": "101230301",
   "莆田": "101230401",
   "泉州": "101230501",
   "三明": "101230801",
   "厦门": "101230201",
   "漳州": "101230601",
   "兰州": "101160101",
   "白银市": "101161301",
   "定西": "101160201",
   "嘉峪关": "101161401",
   "金昌": "101160601",
   "酒泉": "101160801",
   "临夏市": "101161101",
   "陇南市": "101161010",
   "平凉": "101160301",
   "庆阳": "101160401",
   "天水": "101160901",
   "武威": "101160501",
   "张掖": "101160701",
   "广州": "101280101",
   "深圳": "101280601",
   "潮州": "101281501",
   "东莞": "101281601",
   "佛山": "101280800",
   "河源": "101281201",
   "惠州": "101280301",
   "江门": "101281101",
   "揭阳": "101281901",
   "茂名": "101282001",
   "梅州": "101280401",
   "清远": "101281301",
   "汕头": "101280501",
   "汕尾": "101282101",
   "韶关": "101280201",
   "阳江": "101281801",
   "云浮": "101281401",
   "湛江": "101281001",
   "肇庆": "101280901",
   "中山市": "101281701",
   "珠海": "101280701",
   "南宁": "101300101",
   "桂林": "101300501",
   "百色": "101301001",
   "北海": "101301301",
   "崇左": "101300201",
   "防城港": "101301401",
   "贵港": "101300801",
   "河池": "101301201",
   "贺州": "101300701",
   "来宾": "101300401",
   "柳州": "101300301",
   "钦州": "101301101",
   "梧州": "101300601",
   "玉林": "101300901",
   "贵阳": "101260101",
   "安顺": "101260301",
   "毕节": "101260701",
   "六盘水": "101260803",
   "黔东南": "101260506",
   "黔南": "101260413",
   "黔西南": "101260906",
   "铜仁市": "101260601",
   "遵义": "101260201",
   "海口": "101310101",
   "三亚": "101310201",
   "白沙县": "101310207",
   "保亭县": "101310214",
   "昌江县": "101310206",
   "澄迈县": "101310204",
   "定安县": "101310209",
   "东方": "101310202",
   "乐东县": "101310221",
   "临高县": "101310203",
   "陵水县": "101310216",
   "琼海": "101310211",
   "琼中": "101310208",
   "屯昌县": "101310210",
   "万宁": "101310215",
   "文昌": "101310212",
   "五指山": "101310222",
   "儋州": "101310205",
   "石家庄": "101090101",
   "保定": "101090201",
   "沧州": "101090701",
   "承德市": "101090402",
   "邯郸市": "101091001",
   "衡水": "101090801",
   "廊坊": "101090601",
   "秦皇岛": "101091101",
   "唐山": "101090501",
   "邢台市": "101090901",
   "张家口": "101090301",
   "郑州": "101180101",
   "洛阳": "101180901",
   "开封市": "101180801",
   "安阳市": "101180201",
   "鹤壁": "101181201",
   "济源市": "101181801",
   "焦作": "101181101",
   "南阳": "101180701",
   "平顶山": "101180501",
   "三门峡": "101181701",
   "商丘": "101181001",
   "新乡市": "101180301",
   "信阳": "101180601",
   "许昌市": "101180401",
   "周口": "101181401",
   "驻马店": "101181601",
   "漯河": "101181501",
   "濮阳市": "101181301",
   "哈尔滨": "101050101",
   "大庆": "101050901",
   "大兴安岭": "101050701",
   "鹤岗": "101051201",
   "黑河": "101050601",
   "鸡西": "101051101",
   "佳木斯": "101050401",
   "牡丹江": "101050301",
   "七台河": "101051002",
   "齐齐哈尔": "101050201",
   "双鸭山": "101051301",
   "绥化": "101050501",
   "伊春市": "101050801",
   "武汉": "101200101",
   "仙桃": "101201601",
   "鄂州": "101200301",
   "黄冈": "101200501",
   "黄石": "101200601",
   "荆门": "101201401",
   "荆州市": "101200801",
   "潜江市": "101201701",
   "神农架": "101201201",
   "十堰": "101201101",
   "随州": "101201301",
   "天门市": "101201501",
   "咸宁": "101200701",
   "襄阳": "101200201",
   "孝感": "101200401",
   "宜昌": "101200901",
   "恩施市": "101201001",
   "长沙市": "101250101",
   "张家界": "101251101",
   "常德": "101250601",
   "郴州": "101250501",
   "衡阳市": "101250401",
   "怀化": "101251201",
   "娄底": "101250801",
   "邵阳市": "101250901",
   "湘潭市": "101250201",
   "湘西": "101251509",
   "益阳": "101250700",
   "永州": "101251401",
   "岳阳市": "101251001",
   "株洲": "101250301",
   "长春": "101060101",
   "吉林市": "101060201",
   "白城": "101060601",
   "白山": "101060901",
   "辽源": "101060701",
   "四平": "101060401",
   "松原": "101060801",
   "通化市": "101060501",
   "延边": "101060306",
   "南京": "101190101",
   "苏州": "101190401",
   "无锡": "101190201",
   "常州": "101191101",
   "淮安市": "101190901",
   "连云港": "101191001",
   "南通": "101190501",
   "宿迁": "101191301",
   "泰州": "101191201",
   "徐州": "101190801",
   "盐城": "101190701",
   "扬州": "101190601",
   "镇江": "101190301",
   "南昌市": "101240101",
   "抚州": "101240401",
   "赣州": "101240701",
   "吉安市": "101240601",
   "景德镇": "101240801",
   "九江市": "101240201",
   "萍乡": "101240901",
   "上饶市": "101240301",
   "新余": "101241001",
   "宜春": "101240501",
   "鹰潭": "101241101",
   "沈阳": "101070101",
   "大连市": "101070201",
   "鞍山市": "101070301",
   "本溪市": "101070501",
   "朝阳市": "101071201",
   "丹东": "101070601",
   "抚顺市": "101070401",
   "阜新": "101070901",
   "葫芦岛": "101071401",
   "锦州": "101070701",
   "辽阳市": "101071001",
   "盘锦": "101071301",
   "铁岭市": "101071101",
   "营口": "101070801",
   "呼和浩特": "101080101",
   "阿拉善盟": "101081213",
   "巴彦淖尔": "101080811",
   "包头": "101080201",
   "赤峰": "101080601",
   "鄂尔多斯": "101080701",
   "呼伦贝尔市": "101081001",
   "通辽": "101080501",
   "乌海": "101080301",
   "乌兰察布": "101080405",
   "锡林郭勒": "101080902",
   "兴安盟": "101081108",
   "银川": "101170101",
   "固原": "101170401",
   "石嘴山": "101170201",
   "吴忠": "101170301",
   "中卫": "101170501",
   "西宁": "101150101",
   "果洛": "101150507",
   "海北": "101150804",
   "海东": "101150207",
   "共和县": "101150401",
   "德令哈市": "101150701",
   "黄南": "101150305",
   "玉树": "101150601",
   "济南": "101120101",
   "青岛": "101120201",
   "滨州": "101121101",
   "德州": "101120401",
   "东营区": "101121201",
   "菏泽": "101121001",
   "济宁": "101120701",
   "莱芜": "101121601",
   "聊城": "101121701",
   "临沂": "101120901",
   "日照": "101121501",
   "泰安": "101120801",
   "威海": "101121301",
   "潍坊": "101120601",
   "烟台": "101120501",
   "枣庄": "101121401",
   "淄博": "101120301",
   "太原": "101100101",
   "长治市": "101100501",
   "大同市": "101100201",
   "晋城": "101100601",
   "晋中": "101100401",
   "临汾": "101100701",
   "吕梁": "101101100",
   "朔州": "101100901",
   "忻州": "101101001",
   "阳泉": "101100301",
   "运城": "101100801",
   "西安市": "101110101",
   "安康市": "101110701",
   "宝鸡": "101110901",
   "汉中": "101110801",
   "商洛": "101110601",
   "铜川": "101111001",
   "渭南": "101110501",
   "咸阳": "101110200",
   "延安": "101110300",
   "榆林": "101110401",
   "成都": "101270101",
   "绵阳": "101270401",
   "阿坝": "101271901",
   "巴中": "101270901",
   "达州": "101270601",
   "德阳": "101272001",
   "甘孜": "101271801",
   "广安市": "101270801",
   "广元": "101272101",
   "乐山": "101271401",
   "凉山": "101271601",
   "眉山市": "101271501",
   "南充": "101270501",
   "内江": "101271201",
   "攀枝花": "101270201",
   "遂宁": "101270701",
   "雅安": "101271701",
   "宜宾": "101271101",
   "资阳市": "101271301",
   "自贡": "101270301",
   "泸州": "101271001",
   "拉萨": "101140101",
   "阿里": "101140701",
   "昌都市": "101140501",
   "林芝市": "101140401",
   "那曲": "101140601",
   "日喀则市": "101140201",
   "山南": "101140301",
   "乌鲁木齐市": "101130101",
   "阿克苏市": "101130801",
   "阿拉尔市": "101130701",
   "巴音郭楞": "101130609",
   "博尔塔拉": "101131604",
   "昌吉市": "101130401",
   "哈密市": "101131201",
   "和田市": "101131301",
   "喀什市": "101130901",
   "克拉玛依市": "101130201",
   "石河子市": "101130301",
   "吐鲁番市": "101130501",
   "伊犁": "101131012",
   "昆明": "101290101",
   "怒江": "101291201",
   "普洱": "101290901",
   "丽江": "101291401",
   "保山": "101290501",
   "楚雄市": "101290801",
   "大理市": "101290201",
   "德宏": "101291501",
   "迪庆": "101291305",
   "红河县": "101290301",
   "临沧": "101291101",
   "曲靖": "101290401",
   "文山市": "101290601",
   "西双版纳": "101291602",
   "玉溪": "101290701",
   "昭通": "101291001",
   "杭州": "101210101",
   "湖州": "101210201",
   "嘉兴": "101210301",
   "金华": "101210901",
   "丽水": "101210801",
   "宁波": "101210401",
   "绍兴": "101210507",
   "台州": "101210601",
   "温州": "101210701",
   "舟山": "101211101",
   "衢州": "101211001",
   "桐城市": "101220609",
   "怀宁县": "101220605",
   "枞阳县": "101221305",
   "潜山县": "101220604",
   "太湖县": "101220603",
   "宿松县": "101220606",
   "望江县": "101220607",
   "岳西县": "101220608",
   "怀远县": "101220202",
   "五河县": "101220204",
   "固镇县": "101220203",
   "庐江县": "101220106",
   "无为县": "101220305",
   "含山县": "101220503",
   "和县": "101220504",
   "东至县": "101221702",
   "石台县": "101221705",
   "青阳县": "101221703",
   "天长市": "101221107",
   "明光市": "101221103",
   "来安县": "101221106",
   "全椒县": "101221105",
   "定远县": "101221104",
   "凤阳县": "101221102",
   "界首市": "101220805",
   "临泉县": "101220804",
   "太和县": "101220806",
   "阜南县": "101220802",
   "颍上县": "101220803",
   "濉溪县": "101221202",
   "潘集区": "101220403",
   "凤台县": "101220402",
   "屯溪区": "101221003",
   "黄山区": "101221002",
   "歙县": "101221006",
   "休宁县": "101221007",
   "黟县": "101221005",
   "祁门县": "101221004",
   "寿县": "101220408",
   "霍邱县": "101221502",
   "舒城县": "101221507",
   "金寨县": "101221505",
   "霍山县": "101221506",
   "当涂县": "101220502",
   "砀山县": "101220702",
   "萧县": "101220705",
   "灵璧县": "101220703",
   "泗县": "101220704",
   "义安区": "101221303",
   "芜湖县": "101220303",
   "繁昌县": "101220302",
   "南陵县": "101220304",
   "宁国市": "101221404",
   "郎溪县": "101221407",
   "广德县": "101221406",
   "泾县": "101221402",
   "绩溪县": "101221405",
   "旌德县": "101221403",
   "涡阳县": "101220902",
   "蒙城县": "101220904",
   "利辛县": "101220903",
   "海淀区": "101010200",
   "朝阳区": "101060110",
   "丰台区": "101010900",
   "石景山区": "101011000",
   "房山区": "101011200",
   "门头沟区": "101011400",
   "通州区": "101010600",
   "顺义区": "101010400",
   "昌平区": "101010700",
   "怀柔区": "101010500",
   "平谷区": "101011500",
   "大兴区": "101011100",
   "密云区": "101011300",
   "延庆区": "101010800",
   "福清市": "101230111",
   "长乐市": "101230110",
   "闽侯县": "101230103",
   "连江县": "101230105",
   "罗源县": "101230104",
   "闽清县": "101230102",
   "永泰县": "101230107",
   "平潭县": "101230108",
   "漳平市": "101230707",
   "长汀县": "101230702",
   "永定区": "101230706",
   "上杭县": "101230705",
   "武平县": "101230704",
   "连城县": "101230703",
   "邵武市": "101230904",
   "武夷山市": "101230905",
   "建瓯市": "101230910",
   "建阳市": "101230907",
   "顺昌县": "101230902",
   "浦城县": "101230906",
   "光泽县": "101230903",
   "松溪县": "101230908",
   "政和县": "101230909",
   "福安市": "101230306",
   "福鼎市": "101230308",
   "霞浦县": "101230303",
   "古田县": "101230302",
   "屏南县": "101230309",
   "寿宁县": "101230304",
   "周宁县": "101230305",
   "柘荣县": "101230307",
   "城厢区": "101230407",
   "涵江区": "101230404",
   "荔城区": "101230406",
   "秀屿区": "101230405",
   "仙游县": "101230402",
   "石狮市": "101230510",
   "晋江市": "101230509",
   "南安市": "101230506",
   "惠安县": "101230508",
   "安溪县": "101230502",
   "永春县": "101230504",
   "德化县": "101230505",
   "永安市": "101230810",
   "明溪县": "101230807",
   "清流县": "101230803",
   "宁化县": "101230802",
   "大田县": "101230811",
   "尤溪县": "101230809",
   "沙县": "101230808",
   "将乐县": "101230805",
   "泰宁县": "101230804",
   "建宁县": "101230806",
   "同安区": "101230202",
   "龙海市": "101230605",
   "云霄县": "101230609",
   "漳浦县": "101230606",
   "诏安县": "101230607",
   "长泰县": "101230602",
   "东山县": "101230608",
   "南靖县": "101230603",
   "平和县": "101230604",
   "华安县": "101230610",
   "皋兰县": "101160102",
   "永登县": "101160103",
   "榆中县": "101160104",
   "平川区": "101161304",
   "会宁县": "101161303",
   "景泰县": "101161305",
   "靖远县": "101161302",
   "临洮县": "101160205",
   "陇西县": "101160203",
   "通渭县": "101160202",
   "渭源县": "101160204",
   "漳县": "101160206",
   "岷县": "101160207",
   "合作市": "101161201",
   "临潭县": "101161202",
   "卓尼县": "101161203",
   "舟曲县": "101161204",
   "迭部县": "101161205",
   "玛曲县": "101161206",
   "碌曲县": "101161207",
   "夏河县": "101161208",
   "永昌县": "101160602",
   "玉门市": "101160807",
   "敦煌市": "101160808",
   "金塔县": "101160803",
   "瓜州县": "101160805",
   "肃北县": "101160806",
   "阿克塞": "101160804",
   "康乐县": "101161102",
   "永靖县": "101161103",
   "广河县": "101161104",
   "和政县": "101161105",
   "东乡族自治县": "101161106",
   "积石山": "101161107",
   "成县": "101161002",
   "徽县": "101161008",
   "康县": "101161005",
   "礼县": "101161007",
   "两当县": "101161009",
   "文县": "101161003",
   "西和县": "101161006",
   "宕昌县": "101161004",
   "武都区": "101161001",
   "崇信县": "101160304",
   "华亭县": "101160305",
   "静宁县": "101160307",
   "灵台县": "101160303",
   "崆峒区": "101160308",
   "庄浪县": "101160306",
   "泾川县": "101160302",
   "合水县": "101160405",
   "华池县": "101160404",
   "环县": "101160403",
   "宁县": "101160407",
   "庆城县": "101160409",
   "西峰区": "101160402",
   "镇原县": "101160408",
   "正宁县": "101160406",
   "甘谷县": "101160905",
   "秦安县": "101160904",
   "清水县": "101160903",
   "麦积区": "101160908",
   "武山县": "101160906",
   "张家川": "101160907",
   "古浪县": "101160503",
   "民勤县": "101160502",
   "天祝县": "101160505",
   "高台县": "101160705",
   "临泽县": "101160704",
   "民乐县": "101160703",
   "山丹县": "101160706",
   "肃南县": "101160702",
   "从化区": "101280103",
   "天河区": "101280109",
   "番禺区": "101280102",
   "花都区": "101280105",
   "增城区": "101280104",
   "南山区": "101280604",
   "潮安区": "101281503",
   "饶平县": "101281502",
   "南海区": "101280803",
   "顺德区": "101280801",
   "三水区": "101280802",
   "高明区": "101280804",
   "东源县": "101281206",
   "和平县": "101281204",
   "连平县": "101281203",
   "龙川县": "101281205",
   "紫金县": "101281202",
   "惠阳区": "101280303",
   "博罗县": "101280302",
   "惠东县": "101280304",
   "龙门县": "101280305",
   "江海区": "101281109",
   "蓬江区": "101281107",
   "新会区": "101281104",
   "台山市": "101281106",
   "开平市": "101281103",
   "鹤山市": "101281108",
   "恩平市": "101281105",
   "普宁市": "101281903",
   "揭东区": "101281905",
   "揭西县": "101281902",
   "惠来县": "101281904",
   "茂港": "101282006",
   "高州市": "101282002",
   "化州市": "101282003",
   "信宜市": "101282005",
   "电白区": "101282004",
   "梅县区": "101280409",
   "兴宁市": "101280402",
   "大埔县": "101280404",
   "丰顺县": "101280406",
   "五华县": "101280408",
   "平远县": "101280407",
   "蕉岭县": "101280403",
   "英德市": "101281307",
   "连州市": "101281303",
   "佛冈县": "101281306",
   "阳山县": "101281305",
   "清新区": "101281308",
   "连山县": "101281304",
   "连南县": "101281302",
   "南澳县": "101280504",
   "潮阳区": "101280502",
   "澄海区": "101280503",
   "陆丰市": "101282103",
   "海丰县": "101282102",
   "陆河县": "101282104",
   "曲江区": "101280209",
   "浈江区": "101280210",
   "武江区": "101280211",
   "乐昌市": "101280205",
   "南雄市": "101280207",
   "始兴县": "101280203",
   "仁化县": "101280206",
   "翁源县": "101280204",
   "新丰县": "101280208",
   "乳源县": "101280202",
   "阳春市": "101281802",
   "阳西县": "101281804",
   "阳东区": "101281803",
   "罗定市": "101281402",
   "新兴县": "101281403",
   "郁南县": "101281404",
   "云安区": "101281406",
   "赤坎区": "101281006",
   "霞山区": "101281009",
   "坡头区": "101281008",
   "麻章区": "101281010",
   "廉江市": "101281005",
   "雷州市": "101281003",
   "吴川市": "101281002",
   "遂溪县": "101281007",
   "徐闻县": "101281004",
   "高要区": "101280908",
   "四会市": "101280903",
   "广宁县": "101280902",
   "怀集县": "101280906",
   "封开县": "101280907",
   "德庆县": "101280905",
   "斗门区": "101280702",
   "金湾区": "101280703",
   "邕宁区": "101300103",
   "武鸣区": "101300108",
   "隆安县": "101300105",
   "马山县": "101300106",
   "上林县": "101300107",
   "宾阳县": "101300109",
   "横县": "101300104",
   "阳朔县": "101300510",
   "临桂区": "101300505",
   "灵川县": "101300507",
   "全州县": "101300508",
   "平乐县": "101300512",
   "兴安县": "101300506",
   "灌阳县": "101300509",
   "荔浦县": "101300513",
   "资源县": "101300514",
   "永福县": "101300504",
   "龙胜县": "101300503",
   "恭城县": "101300511",
   "凌云县": "101301011",
   "平果县": "101301007",
   "西林县": "101301009",
   "乐业县": "101301010",
   "德保县": "101301004",
   "田林县": "101301012",
   "田阳县": "101301003",
   "靖西市": "101301005",
   "田东县": "101301006",
   "那坡县": "101301002",
   "隆林县": "101301008",
   "合浦县": "101301302",
   "凭祥市": "101300204",
   "宁明县": "101300207",
   "扶绥县": "101300206",
   "龙州县": "101300203",
   "大新县": "101300205",
   "天等县": "101300202",
   "防城区": "101301405",
   "东兴市": "101301403",
   "上思县": "101301402",
   "桂平市": "101300802",
   "平南县": "101300803",
   "宜州市": "101301207",
   "天峨县": "101301202",
   "凤山县": "101301208",
   "南丹县": "101301209",
   "东兰县": "101301203",
   "都安县": "101301210",
   "罗城县": "101301206",
   "巴马县": "101301204",
   "环江县": "101301205",
   "大化县": "101301211",
   "钟山县": "101300704",
   "昭平县": "101300702",
   "富川县": "101300703",
   "合山市": "101300406",
   "象州县": "101300404",
   "武宣县": "101300405",
   "忻城县": "101300402",
   "金秀县": "101300403",
   "柳江区": "101300305",
   "柳城县": "101300302",
   "鹿寨县": "101300304",
   "融安县": "101300306",
   "融水县": "101300307",
   "三江县": "101300308",
   "灵山县": "101301103",
   "浦北县": "101301102",
   "长洲区": "101300607",
   "岑溪市": "101300606",
   "苍梧县": "101300604",
   "藤县": "101300602",
   "蒙山县": "101300605",
   "北流市": "101300903",
   "容县": "101300904",
   "陆川县": "101300905",
   "博白县": "101300902",
   "兴业县": "101300906",
   "南明区": "101260111",
   "云岩区": "101260110",
   "花溪区": "101260103",
   "乌当区": "101260104",
   "白云区": "101280110",
   "小河": "101260109",
   "清镇市": "101260108",
   "开阳县": "101260106",
   "修文县": "101260107",
   "息烽县": "101260105",
   "关岭县": "101260306",
   "紫云县": "101260305",
   "平坝区": "101260304",
   "普定县": "101260302",
   "大方县": "101260705",
   "黔西县": "101260708",
   "金沙县": "101260703",
   "织金县": "101260707",
   "纳雍县": "101260706",
   "赫章县": "101260702",
   "威宁县": "101260704",
   "水城县": "101260801",
   "盘县": "101260804",
   "凯里市": "101260501",
   "黄平县": "101260505",
   "施秉县": "101260503",
   "三穗县": "101260509",
   "镇远县": "101260504",
   "岑巩县": "101260502",
   "天柱县": "101260514",
   "锦屏县": "101260515",
   "剑河县": "101260511",
   "台江县": "101260510",
   "黎平县": "101260513",
   "榕江县": "101260516",
   "从江县": "101260517",
   "雷山县": "101260512",
   "麻江县": "101260507",
   "丹寨县": "101260508",
   "都匀市": "101260401",
   "福泉市": "101260405",
   "荔波县": "101260412",
   "贵定县": "101260402",
   "瓮安县": "101260403",
   "独山县": "101260410",
   "平塘县": "101260409",
   "罗甸县": "101260408",
   "长顺县": "101260404",
   "龙里县": "101260407",
   "惠水县": "101260406",
   "三都县": "101260411",
   "兴义市": "101260901",
   "兴仁县": "101260903",
   "普安县": "101260909",
   "晴隆县": "101260902",
   "贞丰县": "101260904",
   "望谟县": "101260905",
   "册亨县": "101260908",
   "安龙县": "101260907",
   "江口县": "101260602",
   "石阡县": "101260608",
   "思南县": "101260605",
   "德江县": "101260610",
   "玉屏县": "101260603",
   "印江县": "101260607",
   "沿河县": "101260609",
   "松桃县": "101260611",
   "红花岗区": "101260215",
   "务川县": "101260212",
   "道真县": "101260210",
   "汇川区": "101260214",
   "赤水市": "101260208",
   "仁怀市": "101260203",
   "遵义县": "101260202",
   "桐梓县": "101260207",
   "绥阳县": "101260204",
   "正安县": "101260211",
   "凤冈县": "101260206",
   "湄潭县": "101260205",
   "余庆县": "101260213",
   "习水县": "101260209",
   "琼山区": "101310104",
   "井陉矿区": "101090122",
   "辛集市": "101090114",
   "藁城市": "101090115",
   "晋州市": "101090116",
   "新乐市": "101090117",
   "鹿泉区": "101090118",
   "井陉县": "101090102",
   "正定县": "101090103",
   "行唐县": "101090104",
   "灵寿县": "101090106",
   "高邑县": "101090107",
   "深泽县": "101090108",
   "赞皇县": "101090109",
   "无极县": "101090110",
   "平山县": "101090111",
   "元氏县": "101090112",
   "赵县": "101090113",
   "涿州市": "101090218",
   "定州市": "101090219",
   "安国市": "101090220",
   "高碑店市": "101090221",
   "满城区": "101090202",
   "清苑区": "101090224",
   "涞水县": "101090222",
   "阜平县": "101090203",
   "徐水区": "101090204",
   "定兴县": "101090223",
   "唐县": "101090205",
   "高阳县": "101090206",
   "容城县": "101090207",
   "涞源县": "101090209",
   "望都县": "101090210",
   "安新县": "101090211",
   "易县": "101090212",
   "曲阳县": "101090214",
   "蠡县": "101090215",
   "顺平县": "101090216",
   "博野县": "101090225",
   "雄县": "101090217",
   "泊头市": "101090711",
   "任丘市": "101090712",
   "黄骅市": "101090713",
   "河间市": "101090714",
   "沧县": "101090716",
   "青县": "101090702",
   "东光县": "101090703",
   "海兴县": "101090704",
   "盐山县": "101090705",
   "肃宁县": "101090706",
   "南皮县": "101090707",
   "吴桥县": "101090708",
   "献县": "101090709",
   "孟村县": "101090710",
   "承德县": "101090403",
   "兴隆县": "101090404",
   "平泉市": "101090405",
   "滦平县": "101090406",
   "隆化县": "101090407",
   "丰宁县": "101090408",
   "宽城县": "101090409",
   "围场县": "101090410",
   "峰峰矿区": "101091002",
   "武安市": "101091016",
   "临漳县": "101091003",
   "成安县": "101091004",
   "大名县": "101091005",
   "涉县": "101091006",
   "磁县": "101091007",
   "肥乡县": "101091008",
   "永年县": "101091009",
   "邱县": "101091010",
   "鸡泽县": "101091011",
   "广平县": "101091012",
   "馆陶县": "101091013",
   "魏县": "101091014",
   "曲周县": "101091015",
   "冀州市": "101090810",
   "深州市": "101090811",
   "枣强县": "101090802",
   "武邑县": "101090803",
   "武强县": "101090804",
   "饶阳县": "101090805",
   "安平县": "101090806",
   "故城县": "101090807",
   "景县": "101090808",
   "阜城县": "101090809",
   "霸州市": "101090608",
   "三河市": "101090609",
   "固安县": "101090602",
   "永清县": "101090603",
   "香河县": "101090604",
   "大城县": "101090605",
   "文安县": "101090606",
   "大厂县": "101090607",
   "北戴河区": "101091106",
   "昌黎县": "101091103",
   "抚宁区": "101091104",
   "卢龙县": "101091105",
   "青龙县": "101091102",
   "丰南区": "101090502",
   "丰润区": "101090503",
   "遵化市": "101090510",
   "迁安市": "101090511",
   "滦县": "101090504",
   "滦南县": "101090505",
   "乐亭县": "101090506",
   "迁西县": "101090507",
   "玉田县": "101090508",
   "曹妃甸区": "101090509",
   "南宫市": "101090916",
   "沙河市": "101090917",
   "临城县": "101090902",
   "内丘县": "101090904",
   "柏乡县": "101090905",
   "隆尧县": "101090906",
   "任县": "101090918",
   "南和县": "101090907",
   "宁晋县": "101090908",
   "巨鹿县": "101090909",
   "新河县": "101090910",
   "广宗县": "101090911",
   "平乡县": "101090912",
   "威县": "101090913",
   "清河县": "101090914",
   "临西县": "101090915",
   "宣化区": "101090302",
   "张北县": "101090303",
   "康保县": "101090304",
   "沽源县": "101090305",
   "尚义县": "101090306",
   "蔚县": "101090307",
   "阳原县": "101090308",
   "怀安县": "101090309",
   "万全区": "101090310",
   "怀来县": "101090311",
   "涿鹿县": "101090312",
   "赤城县": "101090313",
   "崇礼区": "101090314",
   "上街区": "101180108",
   "巩义市": "101180102",
   "荥阳市": "101180103",
   "新密市": "101180105",
   "新郑市": "101180106",
   "登封市": "101180104",
   "中牟县": "101180107",
   "吉利区": "101180911",
   "偃师市": "101180908",
   "孟津县": "101180903",
   "新安县": "101180902",
   "栾川县": "101180909",
   "嵩县": "101180907",
   "汝阳县": "101180910",
   "宜阳县": "101180904",
   "洛宁县": "101180905",
   "伊川县": "101180906",
   "杞县": "101180802",
   "通许县": "101180804",
   "尉氏县": "101180803",
   "兰考县": "101180805",
   "林州市": "101180205",
   "汤阴县": "101180202",
   "滑县": "101180203",
   "内黄县": "101180204",
   "浚县": "101181202",
   "淇县": "101181203",
   "沁阳市": "101181104",
   "孟州市": "101181108",
   "修武县": "101181102",
   "博爱县": "101181106",
   "武陟县": "101181103",
   "温县": "101181107",
   "邓州市": "101180711",
   "南召县": "101180702",
   "方城县": "101180703",
   "西峡县": "101180705",
   "镇平县": "101180707",
   "内乡县": "101180706",
   "淅川县": "101180708",
   "社旗县": "101180704",
   "唐河县": "101180710",
   "新野县": "101180709",
   "桐柏县": "101180712",
   "石龙区": "101180508",
   "舞钢市": "101180506",
   "汝州市": "101180504",
   "宝丰县": "101180503",
   "叶县": "101180505",
   "鲁山县": "101180507",
   "郏县": "101180502",
   "义马市": "101181705",
   "灵宝市": "101181702",
   "渑池县": "101181703",
   "陕州区": "101181708",
   "卢氏县": "101181704",
   "睢阳区": "101181010",
   "永城市": "101181009",
   "民权县": "101181004",
   "睢县": "101181003",
   "宁陵县": "101181007",
   "虞城县": "101181005",
   "柘城县": "101181006",
   "夏邑县": "101181008",
   "卫辉市": "101180305",
   "辉县市": "101180304",
   "获嘉县": "101180302",
   "原阳县": "101180303",
   "延津县": "101180306",
   "封丘县": "101180307",
   "长垣县": "101180308",
   "罗山县": "101180603",
   "光山县": "101180604",
   "新县": "101180605",
   "商城县": "101180609",
   "固始县": "101180608",
   "潢川县": "101180607",
   "淮滨县": "101180606",
   "息县": "101180602",
   "禹州市": "101180405",
   "长葛市": "101180404",
   "鄢陵县": "101180402",
   "襄城县": "101180403",
   "项城市": "101181407",
   "扶沟县": "101181402",
   "西华县": "101181405",
   "商水县": "101181406",
   "沈丘县": "101181410",
   "郸城县": "101181408",
   "淮阳县": "101181404",
   "太康县": "101181403",
   "鹿邑县": "101181409",
   "西平县": "101181602",
   "上蔡县": "101181604",
   "平舆县": "101181607",
   "正阳县": "101181610",
   "确山县": "101181609",
   "泌阳县": "101181606",
   "汝南县": "101181605",
   "遂平县": "101181603",
   "新蔡县": "101181608",
   "舞阳县": "101181503",
   "临颍县": "101181502",
   "清丰县": "101181304",
   "南乐县": "101181303",
   "范县": "101181305",
   "台前县": "101181302",
   "阿城区": "101050104",
   "呼兰区": "101050103",
   "尚志市": "101050111",
   "双城市": "101050102",
   "五常市": "101050112",
   "方正县": "101050109",
   "宾县": "101050105",
   "依兰县": "101050106",
   "巴彦县": "101050107",
   "通河县": "101050108",
   "木兰县": "101050113",
   "延寿县": "101050110",
   "肇州县": "101050903",
   "肇源县": "101050904",
   "林甸县": "101050902",
   "杜尔伯特": "101050905",
   "呼玛县": "101050704",
   "漠河县": "101050703",
   "塔河县": "101050702",
   "萝北县": "101051203",
   "绥滨县": "101051202",
   "五大连池市": "101050605",
   "北安市": "101050606",
   "嫩江县": "101050602",
   "逊克县": "101050604",
   "孙吴县": "101050603",
   "虎林市": "101051102",
   "密山市": "101051103",
   "鸡东县": "101051104",
   "同江市": "101050406",
   "富锦市": "101050407",
   "桦南县": "101050405",
   "桦川县": "101050404",
   "汤原县": "101050402",
   "抚远市": "101050403",
   "绥芬河市": "101050305",
   "海林市": "101050302",
   "宁安市": "101050306",
   "穆棱市": "101050303",
   "东宁市": "101050307",
   "林口县": "101050304",
   "勃利县": "101051003",
   "讷河市": "101050202",
   "龙江县": "101050203",
   "依安县": "101050206",
   "泰来县": "101050210",
   "甘南县": "101050204",
   "富裕县": "101050205",
   "克山县": "101050208",
   "克东县": "101050209",
   "拜泉县": "101050207",
   "集贤县": "101051302",
   "友谊县": "101051305",
   "宝清县": "101051303",
   "饶河县": "101051304",
   "安达市": "101050503",
   "肇东市": "101050502",
   "海伦市": "101050504",
   "望奎县": "101050506",
   "兰西县": "101050507",
   "青冈县": "101050508",
   "庆安县": "101050509",
   "明水县": "101050505",
   "绥棱县": "101050510",
   "五营区": "101050803",
   "乌伊岭区": "101050802",
   "铁力市": "101050804",
   "嘉荫县": "101050805",
   "东西湖区": "101200106",
   "蔡甸区": "101200102",
   "江夏区": "101200105",
   "黄陂区": "101200103",
   "新洲区": "101200104",
   "梁子湖区": "101200302",
   "麻城市": "101200503",
   "武穴市": "101200509",
   "团风县": "101200510",
   "红安县": "101200502",
   "罗田县": "101200504",
   "英山县": "101200505",
   "浠水县": "101200506",
   "蕲春县": "101200507",
   "黄梅县": "101200508",
   "西塞山区": "101200606",
   "下陆区": "101200605",
   "铁山区": "101200604",
   "大冶市": "101200602",
   "阳新县": "101200603",
   "掇刀区": "101201404",
   "钟祥市": "101201402",
   "京山县": "101201403",
   "沙洋县": "101201405",
   "石首市": "101200804",
   "洪湖市": "101200806",
   "松滋市": "101200807",
   "公安县": "101200803",
   "监利县": "101200805",
   "江陵县": "101200802",
   "张湾区": "101201109",
   "茅箭区": "101201108",
   "丹江口市": "101201107",
   "郧阳区": "101201104",
   "郧西县": "101201103",
   "竹山县": "101201105",
   "竹溪县": "101201102",
   "房县": "101201106",
   "广水市": "101201302",
   "赤壁市": "101200702",
   "嘉鱼县": "101200703",
   "通城县": "101200705",
   "崇阳县": "101200704",
   "通山县": "101200706",
   "襄州区": "101200202",
   "老河口市": "101200206",
   "枣阳市": "101200208",
   "宜城市": "101200205",
   "南漳县": "101200204",
   "谷城县": "101200207",
   "保康县": "101200203",
   "应城市": "101200405",
   "安陆市": "101200402",
   "汉川市": "101200406",
   "孝昌县": "101200407",
   "大悟县": "101200404",
   "云梦县": "101200403",
   "长阳县": "101200908",
   "五峰县": "101200906",
   "夷陵区": "101200912",
   "宜都市": "101200909",
   "当阳市": "101200907",
   "枝江市": "101200910",
   "远安县": "101200902",
   "兴山县": "101200904",
   "秭归县": "101200903",
   "利川市": "101201002",
   "建始县": "101201003",
   "巴东县": "101201008",
   "宣恩县": "101201005",
   "咸丰县": "101201004",
   "来凤县": "101201007",
   "鹤峰县": "101201006",
   "浏阳市": "101250103",
   "长沙县": "101250106",
   "望城区": "101250105",
   "宁乡县": "101250102",
   "武陵源区": "101251104",
   "慈利县": "101251103",
   "桑植县": "101251102",
   "津市市": "101250608",
   "安乡县": "101250602",
   "汉寿县": "101250604",
   "澧县": "101250605",
   "临澧县": "101250606",
   "桃源县": "101250603",
   "石门县": "101250607",
   "苏仙区": "101250512",
   "资兴市": "101250507",
   "桂阳县": "101250502",
   "宜章县": "101250504",
   "永兴县": "101250510",
   "嘉禾县": "101250503",
   "临武县": "101250505",
   "汝城县": "101250508",
   "桂东县": "101250511",
   "安仁县": "101250509",
   "南岳区": "101250409",
   "耒阳市": "101250408",
   "常宁市": "101250406",
   "衡阳县": "101250405",
   "衡南县": "101250407",
   "衡山县": "101250402",
   "衡东县": "101250403",
   "祁东县": "101250404",
   "鹤城区": "101251202",
   "靖州县": "101251205",
   "麻阳县": "101251208",
   "通道县": "101251207",
   "新晃县": "101251209",
   "芷江治县": "101251210",
   "沅陵县": "101251203",
   "辰溪县": "101251204",
   "溆浦县": "101251211",
   "中方县": "101251212",
   "会同县": "101251206",
   "洪江市": "101251213",
   "冷水江市": "101250803",
   "涟源市": "101250806",
   "双峰县": "101250802",
   "新化县": "101250805",
   "城步县": "101250909",
   "武冈市": "101250908",
   "邵东县": "101250905",
   "新邵县": "101250904",
   "邵阳县": "101250910",
   "隆回县": "101250902",
   "洞口县": "101250903",
   "绥宁县": "101250906",
   "新宁县": "101250907",
   "湘乡市": "101250203",
   "韶山市": "101250202",
   "吉首市": "101251501",
   "泸溪县": "101251506",
   "凤凰县": "101251505",
   "花垣县": "101251508",
   "保靖县": "101251502",
   "古丈县": "101251504",
   "永顺县": "101251503",
   "龙山县": "101251507",
   "赫山区": "101250701",
   "沅江市": "101250705",
   "南县": "101250702",
   "桃江县": "101250703",
   "安化县": "101250704",
   "江华瑶族自治县": "101251410",
   "祁阳县": "101251402",
   "东安县": "101251403",
   "双牌县": "101251404",
   "道县": "101251405",
   "江永县": "101251407",
   "宁远县": "101251406",
   "蓝山县": "101251408",
   "新田县": "101251409",
   "汨罗市": "101251004",
   "临湘市": "101251006",
   "华容县": "101251002",
   "湘阴县": "101251003",
   "平江县": "101251005",
   "醴陵市": "101250303",
   "荷塘区": "101250304",
   "攸县": "101250302",
   "茶陵县": "101250305",
   "炎陵县": "101250306",
   "双阳区": "101060106",
   "德惠市": "101060103",
   "九台市": "101060104",
   "榆树市": "101060105",
   "农安县": "101060102",
   "蛟河市": "101060204",
   "桦甸市": "101060206",
   "舒兰市": "101060202",
   "磐石市": "101060205",
   "永吉县": "101060203",
   "洮南市": "101060602",
   "大安市": "101060603",
   "镇赉县": "101060604",
   "通榆县": "101060605",
   "江源区": "101060907",
   "长白县": "101060905",
   "临江市": "101060903",
   "抚松县": "101060906",
   "靖宇县": "101060902",
   "东丰县": "101060702",
   "东辽县": "101060703",
   "伊通满族自治县": "101060405",
   "公主岭市": "101060404",
   "双辽市": "101060402",
   "梨树县": "101060403",
   "前郭县": "101060803",
   "长岭县": "101060804",
   "乾安县": "101060802",
   "扶余市": "101060805",
   "梅河口市": "101060502",
   "集安市": "101060505",
   "通化县": "101060506",
   "辉南县": "101060504",
   "柳河县": "101060503",
   "延吉市": "101060301",
   "图们市": "101060309",
   "敦化市": "101060302",
   "珲春市": "101060308",
   "龙井市": "101060307",
   "和龙市": "101060305",
   "安图县": "101060303",
   "汪清县": "101060304",
   "浦口区": "101190107",
   "江宁区": "101190104",
   "六合区": "101190105",
   "溧水区": "101190102",
   "高淳区": "101190103",
   "吴中区": "101190405",
   "昆山市": "101190404",
   "常熟市": "101190402",
   "张家港市": "101190403",
   "塔城市": "101131101",
   "吴江区": "101190407",
   "太仓市": "101190408",
   "锡山区": "101190204",
   "江阴市": "101190202",
   "宜兴市": "101190203",
   "武进区": "101191104",
   "溧阳市": "101191102",
   "金坛区": "101191103",
   "淮安区": "101190908",
   "淮阴区": "101190906",
   "涟水县": "101190905",
   "洪泽区": "101190904",
   "盱眙县": "101190903",
   "金湖县": "101190902",
   "赣榆区": "101191003",
   "东海县": "101191002",
   "灌云县": "101191004",
   "灌南县": "101191005",
   "启东市": "101190507",
   "如皋市": "101190503",
   "海门市": "101190508",
   "海安县": "101190502",
   "如东县": "101190504",
   "宿豫区": "101191305",
   "沭阳县": "101191302",
   "泗阳县": "101191303",
   "泗洪县": "101191304",
   "兴化市": "101191202",
   "靖江市": "101191205",
   "泰兴市": "101191203",
   "姜堰区": "101191204",
   "新沂市": "101190807",
   "邳州市": "101190805",
   "丰县": "101190803",
   "沛县": "101190804",
   "铜山区": "101190802",
   "睢宁县": "101190806",
   "盐都区": "101190709",
   "东台市": "101190707",
   "大丰区": "101190708",
   "响水县": "101190702",
   "滨海县": "101190703",
   "阜宁县": "101190704",
   "射阳县": "101190705",
   "建湖县": "101190706",
   "邗江区": "101190606",
   "仪征市": "101190603",
   "高邮市": "101190604",
   "江都市": "101190605",
   "宝应县": "101190602",
   "丹徒区": "101190305",
   "丹阳市": "101190302",
   "扬中市": "101190303",
   "句容市": "101190304",
   "南昌县": "101240103",
   "新建区": "101240102",
   "安义县": "101240104",
   "进贤县": "101240105",
   "南城县": "101240408",
   "黎川县": "101240410",
   "南丰县": "101240409",
   "崇仁县": "101240404",
   "乐安县": "101240403",
   "宜黄县": "101240407",
   "金溪县": "101240405",
   "资溪县": "101240406",
   "东乡县": "101240411",
   "广昌县": "101240402",
   "于都县": "101240710",
   "瑞金市": "101240709",
   "南康市": "101240704",
   "赣县": "101240718",
   "信丰县": "101240706",
   "大余县": "101240705",
   "上犹县": "101240703",
   "崇义县": "101240702",
   "安远县": "101240712",
   "龙南县": "101240714",
   "定南县": "101240715",
   "全南县": "101240713",
   "宁都县": "101240707",
   "兴国县": "101240717",
   "会昌县": "101240711",
   "寻乌县": "101240716",
   "石城县": "101240708",
   "安福县": "101240612",
   "井冈山市": "101240608",
   "吉安县": "101240602",
   "吉水县": "101240603",
   "峡江县": "101240605",
   "新干县": "101240604",
   "永丰县": "101240606",
   "泰和县": "101240611",
   "遂川县": "101240610",
   "万安县": "101240609",
   "永新县": "101240607",
   "乐平市": "101240802",
   "浮梁县": "101240803",
   "庐山市": "101240203",
   "瑞昌市": "101240202",
   "武宁县": "101240204",
   "修水县": "101240212",
   "永修县": "101240206",
   "德安县": "101240205",
   "星子县": "101240209",
   "都昌县": "101240210",
   "湖口县": "101240207",
   "彭泽县": "101240208",
   "安源区": "101240904",
   "湘东区": "101240906",
   "莲花县": "101240902",
   "芦溪县": "101240905",
   "上栗县": "101240903",
   "德兴市": "101240307",
   "上饶县": "101240308",
   "广丰区": "101240313",
   "玉山县": "101240312",
   "铅山县": "101240311",
   "横峰县": "101240310",
   "弋阳县": "101240309",
   "余干县": "101240305",
   "鄱阳县": "101240302",
   "万年县": "101240306",
   "婺源县": "101240303",
   "分宜县": "101241002",
   "丰城市": "101240510",
   "樟树市": "101240509",
   "高安市": "101240508",
   "奉新县": "101240507",
   "万载县": "101240504",
   "上高县": "101240505",
   "宜丰县": "101240503",
   "靖安县": "101240506",
   "铜鼓县": "101240502",
   "贵溪市": "101241103",
   "余江县": "101241102",
   "苏家屯区": "101070112",
   "于洪区": "101070114",
   "新民市": "101070106",
   "辽中区": "101070103",
   "康平县": "101070104",
   "法库县": "101070105",
   "旅顺口区": "101070205",
   "金州区": "101070203",
   "瓦房店市": "101070202",
   "普兰店市": "101070204",
   "庄河市": "101070207",
   "长海县": "101070206",
   "岫岩县": "101070303",
   "海城市": "101070304",
   "台安县": "101070302",
   "本溪县": "101070502",
   "桓仁县": "101070504",
   "喀喇沁左翼蒙古族自治县": "101071204",
   "北票市": "101071205",
   "凌源市": "101071203",
   "建平县": "101071207",
   "宽甸县": "101070603",
   "东港市": "101070604",
   "凤城市": "101070602",
   "清原县": "101070403",
   "新宾县": "101070402",
   "彰武县": "101070902",
   "兴城市": "101071404",
   "绥中县": "101071403",
   "建昌县": "101071402",
   "凌海市": "101070702",
   "北镇市": "101070706",
   "黑山县": "101070705",
   "义县": "101070704",
   "弓长岭区": "101071004",
   "灯塔市": "101071003",
   "辽阳县": "101071002",
   "大洼区": "101071302",
   "盘山县": "101071303",
   "调兵山市": "101071105",
   "开原市": "101071102",
   "西丰县": "101071104",
   "昌图县": "101071103",
   "盖州市": "101070803",
   "大石桥市": "101070802",
   "清水河县": "101080105",
   "土默特左旗": "101080102",
   "托克托县": "101080103",
   "和林格尔县": "101080104",
   "武川县": "101080107",
   "阿拉善左旗": "101081201",
   "阿拉善右旗": "101081202",
   "额济纳旗": "101081203",
   "临河区": "101080801",
   "五原县": "101080802",
   "磴口县": "101080803",
   "乌拉特前旗": "101080804",
   "乌拉特中旗": "101080806",
   "乌拉特后旗": "101080807",
   "杭锦后旗": "101080810",
   "石拐区": "101080211",
   "白云鄂博": "101080202",
   "土默特右旗": "101080204",
   "固阳县": "101080205",
   "达茂旗": "101080206",
   "阿鲁科尔沁旗": "101080603",
   "巴林左旗": "101080605",
   "巴林右旗": "101080606",
   "林西县": "101080607",
   "克什克腾旗": "101080608",
   "翁牛特旗": "101080609",
   "喀喇沁旗": "101080611",
   "宁城县": "101080613",
   "敖汉旗": "101080614",
   "东胜区": "101080713",
   "达拉特旗": "101080703",
   "准格尔旗": "101080704",
   "鄂托克前旗": "101080705",
   "鄂托克旗": "101080708",
   "杭锦旗": "101080709",
   "乌审旗": "101080710",
   "伊金霍洛旗": "101080711",
   "莫力达瓦": "101081004",
   "满洲里市": "101081010",
   "牙克石市": "101081011",
   "扎兰屯市": "101081012",
   "额尔古纳市": "101081014",
   "根河市": "101081015",
   "阿荣旗": "101081003",
   "鄂伦春旗": "101081005",
   "鄂温克族旗": "101081006",
   "陈巴尔虎旗": "101081007",
   "新巴尔虎左旗": "101081008",
   "新巴尔虎右旗": "101081009",
   "霍林郭勒市": "101080512",
   "科尔沁左翼中旗": "101080503",
   "科尔沁左翼后旗": "101080504",
   "开鲁县": "101080506",
   "库伦旗": "101080507",
   "奈曼旗": "101080508",
   "扎鲁特旗": "101080509",
   "化德县": "101080403",
   "集宁区": "101080401",
   "丰镇市": "101080412",
   "卓资县": "101080402",
   "商都县": "101080404",
   "兴和县": "101080406",
   "凉城县": "101080407",
   "察哈尔右翼前旗": "101080408",
   "察哈尔右翼中旗": "101080409",
   "察哈尔右翼后旗": "101080410",
   "四子王旗": "101080411",
   "二连浩特市": "101080903",
   "锡林浩特市": "101080901",
   "阿巴嘎旗": "101080904",
   "苏尼特左旗": "101080906",
   "苏尼特右旗": "101080907",
   "东乌珠穆沁旗": "101080909",
   "西乌珠穆沁旗": "101080910",
   "太仆寺旗": "101080911",
   "镶黄旗": "101080912",
   "正镶白旗": "101080913",
   "多伦县": "101080915",
   "乌兰浩特市": "101081101",
   "阿尔山市": "101081102",
   "科尔沁右翼前旗": "101081109",
   "科尔沁右翼中旗": "101081103",
   "扎赉特旗": "101081105",
   "突泉县": "101081107",
   "灵武市": "101170103",
   "永宁县": "101170102",
   "贺兰县": "101170104",
   "西吉县": "101170402",
   "隆德县": "101170403",
   "泾源县": "101170404",
   "彭阳县": "101170406",
   "惠农区": "101170202",
   "大武口区": "101170205",
   "陶乐": "101170204",
   "平罗县": "101170203",
   "青铜峡市": "101170306",
   "盐池县": "101170303",
   "同心县": "101170302",
   "海原县": "101170504",
   "中宁县": "101170502",
   "湟中县": "101150104",
   "湟源县": "101150103",
   "大通县": "101150102",
   "玛沁县": "101150501",
   "班玛县": "101150502",
   "甘德县": "101150503",
   "达日县": "101150504",
   "久治县": "101150505",
   "玛多县": "101150506",
   "海晏县": "101150801",
   "祁连县": "101150803",
   "刚察县": "101150806",
   "门源县": "101150802",
   "平安县": "101150208",
   "乐都区": "101150202",
   "民和县": "101150203",
   "互助县": "101150204",
   "化隆县": "101150205",
   "循化县": "101150206",
   "同德县": "101150408",
   "贵德县": "101150404",
   "兴海县": "101150406",
   "贵南县": "101150407",
   "格尔木市": "101150714",
   "乌兰县": "101150709",
   "都兰县": "101150715",
   "天峻县": "101150708",
   "同仁县": "101150301",
   "尖扎县": "101150302",
   "泽库县": "101150303",
   "河南县": "101150304",
   "杂多县": "101150604",
   "称多县": "101150602",
   "治多县": "101150603",
   "囊谦县": "101150605",
   "曲麻莱县": "101150606",
   "长清区": "101120102",
   "章丘市": "101120104",
   "平阴县": "101120105",
   "济阳县": "101120106",
   "商河县": "101120103",
   "崂山区": "101120202",
   "胶州市": "101120205",
   "即墨市": "101120204",
   "平度市": "101120208",
   "黄岛区": "101120206",
   "莱西市": "101120207",
   "惠民县": "101121105",
   "阳信县": "101121104",
   "无棣县": "101121103",
   "沾化区": "101121106",
   "博兴县": "101121102",
   "邹平县": "101121107",
   "兰陵县": "101120404",
   "乐陵市": "101120406",
   "禹城市": "101120411",
   "宁津县": "101120409",
   "庆云县": "101120407",
   "临邑县": "101120403",
   "齐河县": "101120405",
   "平原县": "101120408",
   "夏津县": "101120410",
   "武城县": "101120402",
   "河口区": "101121202",
   "垦利区": "101121203",
   "利津县": "101121204",
   "广饶县": "101121205",
   "曹县": "101121007",
   "单县": "101121009",
   "成武县": "101121008",
   "巨野县": "101121006",
   "郓城县": "101121003",
   "鄄城县": "101121002",
   "定陶区": "101121005",
   "东明县": "101121004",
   "曲阜市": "101120710",
   "兖州市": "101120705",
   "邹城市": "101120711",
   "微山县": "101120703",
   "鱼台县": "101120704",
   "金乡县": "101120706",
   "嘉祥县": "101120702",
   "汶上县": "101120707",
   "泗水县": "101120708",
   "梁山县": "101120709",
   "临清市": "101121707",
   "阳谷县": "101121703",
   "莘县": "101121709",
   "茌平县": "101121705",
   "东阿县": "101121706",
   "冠县": "101121702",
   "高唐县": "101121704",
   "沂南县": "101120903",
   "郯城县": "101120906",
   "沂水县": "101120910",
   "费县": "101120909",
   "平邑县": "101120908",
   "莒南县": "101120902",
   "蒙阴县": "101120907",
   "临沭县": "101120905",
   "五莲县": "101121502",
   "莒县": "101121503",
   "泰山区": "101120803",
   "新泰市": "101120802",
   "肥城市": "101120804",
   "宁阳县": "101120806",
   "东平县": "101120805",
   "荣成市": "101121303",
   "乳山市": "101121304",
   "文登市": "101121302",
   "青州市": "101120602",
   "诸城市": "101120609",
   "寿光市": "101120603",
   "安丘市": "101120607",
   "高密市": "101120608",
   "昌邑市": "101120606",
   "临朐县": "101120604",
   "昌乐县": "101120605",
   "福山区": "101120508",
   "牟平区": "101120509",
   "龙口市": "101120505",
   "莱阳市": "101120510",
   "莱州市": "101120502",
   "蓬莱市": "101120504",
   "招远市": "101120506",
   "栖霞市": "101120507",
   "海阳市": "101120511",
   "长岛县": "101120503",
   "峄城区": "101121403",
   "台儿庄区": "101121404",
   "薛城区": "101121402",
   "滕州市": "101121405",
   "临淄区": "101120308",
   "淄川区": "101120302",
   "博山区": "101120303",
   "周村区": "101120305",
   "桓台县": "101120307",
   "高青县": "101120304",
   "沂源县": "101120306",
   "清徐县": "101100102",
   "阳曲县": "101100103",
   "娄烦县": "101100104",
   "古交市": "101100105",
   "沁县": "101100508",
   "潞城市": "101100504",
   "襄垣县": "101100505",
   "屯留县": "101100503",
   "平顺县": "101100506",
   "黎城县": "101100502",
   "壶关县": "101100511",
   "长子县": "101100509",
   "武乡县": "101100507",
   "沁源县": "101100510",
   "阳高县": "101100202",
   "天镇县": "101100204",
   "广灵县": "101100205",
   "灵丘县": "101100206",
   "浑源县": "101100207",
   "左云县": "101100208",
   "大同县": "101100203",
   "高平市": "101100605",
   "沁水县": "101100602",
   "阳城县": "101100603",
   "陵川县": "101100604",
   "泽州县": "101100606",
   "榆次区": "101100402",
   "介休市": "101100412",
   "榆社县": "101100403",
   "左权县": "101100404",
   "和顺县": "101100405",
   "昔阳县": "101100406",
   "寿阳县": "101100407",
   "太谷县": "101100408",
   "祁县": "101100409",
   "平遥县": "101100410",
   "灵石县": "101100411",
   "侯马市": "101100714",
   "霍州市": "101100711",
   "曲沃县": "101100702",
   "翼城县": "101100713",
   "襄汾县": "101100707",
   "洪洞县": "101100710",
   "吉县": "101100706",
   "安泽县": "101100716",
   "浮山县": "101100715",
   "古县": "101100717",
   "乡宁县": "101100712",
   "大宁县": "101100705",
   "隰县": "101100704",
   "永和县": "101100703",
   "蒲县": "101100708",
   "汾西县": "101100709",
   "离石区": "101101101",
   "孝义市": "101101110",
   "汾阳市": "101101111",
   "文水县": "101101112",
   "交城县": "101101113",
   "兴县": "101101103",
   "临县": "101101102",
   "柳林县": "101101105",
   "石楼县": "101101106",
   "岚县": "101101104",
   "方山县": "101101107",
   "中阳县": "101101109",
   "交口县": "101101108",
   "平鲁区": "101100902",
   "山阴县": "101100903",
   "应县": "101100905",
   "右玉县": "101100904",
   "怀仁县": "101100906",
   "原平市": "101101015",
   "定襄县": "101101002",
   "五台县": "101101003",
   "代县": "101101008",
   "繁峙县": "101101009",
   "宁武县": "101101007",
   "静乐县": "101101012",
   "神池县": "101101006",
   "五寨县": "101101014",
   "岢岚县": "101101013",
   "河曲县": "101101004",
   "保德县": "101101011",
   "偏关县": "101101005",
   "平定县": "101100303",
   "盂县": "101100302",
   "永济市": "101100810",
   "河津市": "101100805",
   "临猗县": "101100802",
   "万荣县": "101100804",
   "闻喜县": "101100808",
   "稷山县": "101100803",
   "新绛县": "101100806",
   "绛县": "101100807",
   "垣曲县": "101100809",
   "夏县": "101100812",
   "平陆县": "101100813",
   "芮城县": "101100811",
   "临潼区": "101110103",
   "长安区": "101090119",
   "蓝田县": "101110104",
   "周至县": "101110105",
   "户县": "101110106",
   "高陵区": "101110107",
   "汉阴县": "101110704",
   "石泉县": "101110703",
   "宁陕县": "101110710",
   "紫阳县": "101110702",
   "岚皋县": "101110706",
   "平利县": "101110707",
   "镇坪县": "101110709",
   "旬阳县": "101110705",
   "白河县": "101110708",
   "陈仓区": "101110912",
   "凤翔县": "101110906",
   "岐山县": "101110905",
   "扶风县": "101110907",
   "眉县": "101110908",
   "陇县": "101110911",
   "千阳县": "101110903",
   "麟游县": "101110904",
   "凤县": "101110910",
   "太白县": "101110909",
   "南郑县": "101110810",
   "城固县": "101110806",
   "洋县": "101110805",
   "西乡县": "101110807",
   "勉县": "101110803",
   "宁强县": "101110809",
   "略阳县": "101110802",
   "镇巴县": "101110811",
   "留坝县": "101110804",
   "佛坪县": "101110808",
   "商州区": "101110604",
   "洛南县": "101110602",
   "丹凤县": "101110606",
   "商南县": "101110607",
   "山阳县": "101110608",
   "镇安县": "101110605",
   "柞水县": "101110603",
   "耀州区": "101111004",
   "宜君县": "101111003",
   "韩城市": "101110510",
   "华阴市": "101110511",
   "华县": "101110502",
   "潼关县": "101110503",
   "大荔县": "101110504",
   "合阳县": "101110509",
   "澄城县": "101110508",
   "蒲城县": "101110507",
   "白水县": "101110505",
   "富平县": "101110506",
   "兴平市": "101110211",
   "三原县": "101110201",
   "泾阳县": "101110205",
   "乾县": "101110207",
   "礼泉县": "101110202",
   "永寿县": "101110203",
   "彬县": "101110208",
   "长武县": "101110209",
   "旬邑县": "101110210",
   "淳化县": "101110204",
   "武功县": "101110206",
   "吴起县": "101110312",
   "延长县": "101110301",
   "延川县": "101110302",
   "子长县": "101110303",
   "安塞区": "101110307",
   "志丹县": "101110306",
   "甘泉县": "101110308",
   "富县": "101110305",
   "洛川县": "101110309",
   "宜川县": "101110304",
   "黄龙县": "101110311",
   "黄陵县": "101110310",
   "榆阳区": "101110413",
   "神木县": "101110403",
   "府谷县": "101110402",
   "横山区": "101110407",
   "靖边县": "101110406",
   "定边县": "101110405",
   "绥德县": "101110410",
   "米脂县": "101110408",
   "佳县": "101110404",
   "吴堡县": "101110411",
   "清涧县": "101110412",
   "子洲县": "101110409",
   "闵行区": "101020200",
   "浦东新区": "101020600",
   "松江区": "101020900",
   "嘉定区": "101020500",
   "宝山区": "101020300",
   "青浦区": "101020800",
   "金山区": "101020700",
   "奉贤区": "101021000",
   "崇明区": "101021100",
   "龙泉驿区": "101270102",
   "青白江区": "101270115",
   "新都区": "101270103",
   "温江区": "101270104",
   "都江堰市": "101270111",
   "彭州市": "101270112",
   "邛崃市": "101270113",
   "崇州市": "101270114",
   "金堂县": "101270105",
   "双流区": "101270106",
   "郫县": "101270107",
   "大邑县": "101270108",
   "蒲江县": "101270109",
   "新津县": "101270110",
   "江油市": "101270408",
   "盐亭县": "101270403",
   "三台县": "101270402",
   "平武县": "101270407",
   "安县": "101270404",
   "梓潼县": "101270405",
   "北川县": "101270406",
   "马尔康市": "101271910",
   "汶川县": "101271902",
   "理县": "101271903",
   "茂县": "101271904",
   "松潘县": "101271905",
   "九寨沟县": "101271906",
   "金川县": "101271907",
   "小金县": "101271908",
   "黑水县": "101271909",
   "壤塘县": "101271911",
   "若尔盖县": "101271912",
   "红原县": "101271913",
   "通江县": "101270902",
   "南江县": "101270903",
   "平昌县": "101270904",
   "万源市": "101270606",
   "达川区": "101270608",
   "宣汉县": "101270602",
   "开江县": "101270603",
   "大竹县": "101270604",
   "渠县": "101270605",
   "广汉市": "101272003",
   "什邡市": "101272004",
   "绵竹市": "101272005",
   "罗江区": "101272006",
   "中江县": "101272002",
   "康定市": "101271802",
   "丹巴县": "101271804",
   "泸定县": "101271803",
   "炉霍县": "101271808",
   "九龙县": "101271805",
   "雅江县": "101271806",
   "新龙县": "101271809",
   "道孚县": "101271807",
   "白玉县": "101271811",
   "理塘县": "101271814",
   "德格县": "101271810",
   "乡城县": "101271816",
   "石渠县": "101271812",
   "稻城县": "101271817",
   "色达县": "101271813",
   "巴塘县": "101271815",
   "得荣县": "101271818",
   "华蓥市": "101270805",
   "岳池县": "101270802",
   "武胜县": "101270803",
   "邻水县": "101270804",
   "旺苍县": "101272102",
   "青川县": "101272103",
   "剑阁县": "101272104",
   "苍溪县": "101272105",
   "峨眉山市": "101271408",
   "犍为县": "101271402",
   "井研县": "101271403",
   "夹江县": "101271404",
   "沐川县": "101271405",
   "峨边县": "101271406",
   "马边县": "101271407",
   "西昌市": "101271610",
   "盐源县": "101271604",
   "德昌县": "101271605",
   "会理县": "101271606",
   "会东县": "101271607",
   "宁南县": "101271608",
   "普格县": "101271609",
   "布拖县": "101271619",
   "金阳县": "101271611",
   "昭觉县": "101271612",
   "喜德县": "101271613",
   "冕宁县": "101271614",
   "越西县": "101271615",
   "甘洛县": "101271616",
   "美姑县": "101271618",
   "雷波县": "101271617",
   "木里县": "101271603",
   "仁寿县": "101271502",
   "彭山区": "101271503",
   "洪雅县": "101271504",
   "丹棱县": "101271505",
   "青神县": "101271506",
   "阆中市": "101270507",
   "南部县": "101270502",
   "营山县": "101270503",
   "蓬安县": "101270504",
   "仪陇县": "101270505",
   "西充县": "101270506",
   "东兴区": "101271202",
   "威远县": "101271203",
   "资中县": "101271204",
   "隆昌县": "101271205",
   "仁和区": "101270202",
   "米易县": "101270203",
   "盐边县": "101270204",
   "蓬溪县": "101270702",
   "射洪县": "101270703",
   "名山区": "101271702",
   "荥经县": "101271703",
   "汉源县": "101271704",
   "石棉县": "101271705",
   "天全县": "101271706",
   "芦山县": "101271707",
   "宝兴县": "101271708",
   "叙州区": "101271103",
   "南溪区": "101271104",
   "江安县": "101271105",
   "长宁县": "101271106",
   "高县": "101271107",
   "珙县": "101271108",
   "筠连县": "101271109",
   "兴文县": "101271110",
   "屏山县": "101271111",
   "简阳市": "101270121",
   "安岳县": "101271302",
   "乐至县": "101271303",
   "荣县": "101270303",
   "富顺县": "101270302",
   "纳溪区": "101271007",
   "泸县": "101271003",
   "合江县": "101271004",
   "叙永县": "101271005",
   "古蔺县": "101271006",
   "东丽区": "101030400",
   "津南区": "101031000",
   "西青区": "101030500",
   "北辰区": "101030600",
   "滨海新区": "101031100",
   "和平区": "101030800",
   "河东区": "101031200",
   "武清区": "101030200",
   "宝坻区": "101030300",
   "宁河区": "101030700",
   "静海区": "101030900",
   "蓟州区": "101031400",
   "林周县": "101140104",
   "当雄县": "101140102",
   "尼木县": "101140103",
   "曲水县": "101140106",
   "堆龙德庆区": "101140105",
   "达孜县": "101140107",
   "墨竹工卡县": "101140108",
   "噶尔县": "101140707",
   "普兰县": "101140705",
   "札达县": "101140706",
   "日土县": "101140708",
   "革吉县": "101140709",
   "改则县": "101140702",
   "措勤县": "101140710",
   "江达县": "101140509",
   "贡觉县": "101140511",
   "类乌齐县": "101140507",
   "丁青县": "101140502",
   "察雅县": "101140510",
   "八宿县": "101140508",
   "左贡县": "101140505",
   "芒康县": "101140506",
   "洛隆县": "101140504",
   "边坝县": "101140503",
   "工布江达县": "101140405",
   "米林县": "101140403",
   "墨脱县": "101140407",
   "波密县": "101140402",
   "察隅县": "101140404",
   "朗县": "101140406",
   "嘉黎县": "101140603",
   "比如县": "101140609",
   "聂荣县": "101140607",
   "安多县": "101140605",
   "申扎县": "101140611",
   "索县": "101140606",
   "班戈县": "101140604",
   "巴青县": "101140608",
   "尼玛县": "101140602",
   "南木林县": "101140203",
   "江孜县": "101140206",
   "定日县": "101140205",
   "萨迦县": "101140213",
   "拉孜县": "101140202",
   "昂仁县": "101140211",
   "谢通门县": "101140214",
   "白朗县": "101140217",
   "仁布县": "101140220",
   "康马县": "101140219",
   "定结县": "101140212",
   "仲巴县": "101140208",
   "亚东县": "101140218",
   "吉隆县": "101140210",
   "聂拉木县": "101140204",
   "萨嘎县": "101140209",
   "岗巴县": "101140216",
   "乃东区": "101140309",
   "扎囊县": "101140303",
   "贡嘎县": "101140302",
   "桑日县": "101140310",
   "琼结县": "101140313",
   "曲松县": "101140314",
   "措美县": "101140312",
   "洛扎县": "101140311",
   "加查县": "101140304",
   "隆子县": "101140307",
   "错那县": "101140306",
   "浪卡子县": "101140305",
   "达坂城区": "101130105",
   "乌鲁木齐县": "101130113",
   "温宿县": "101130803",
   "库车县": "101130807",
   "沙雅县": "101130806",
   "新和县": "101130805",
   "拜城县": "101130804",
   "乌什县": "101130802",
   "阿瓦提县": "101130809",
   "柯坪县": "101130808",
   "库尔勒": "101130601",
   "轮台县": "101130602",
   "尉犁县": "101130603",
   "若羌县": "101130604",
   "且末县": "101130605",
   "焉耆县": "101130607",
   "和静县": "101130606",
   "和硕县": "101130608",
   "博湖县": "101130612",
   "博乐市": "101131601",
   "精河县": "101131603",
   "温泉县": "101131602",
   "呼图壁县": "101130402",
   "米泉": "101130403",
   "阜康市": "101130404",
   "玛纳斯县": "101130407",
   "奇台县": "101130406",
   "吉木萨尔县": "101130405",
   "木垒县": "101130408",
   "伊吾县": "101131204",
   "巴里坤": "101131203",
   "墨玉县": "101131304",
   "皮山县": "101131302",
   "洛浦县": "101131305",
   "策勒县": "101131303",
   "于田县": "101131307",
   "民丰县": "101131306",
   "疏附县": "101130911",
   "疏勒县": "101130912",
   "英吉沙县": "101130902",
   "泽普县": "101130907",
   "莎车县": "101130905",
   "叶城县": "101130906",
   "麦盖提县": "101130904",
   "岳普湖县": "101130909",
   "伽师县": "101130910",
   "巴楚县": "101130908",
   "塔什库尔干": "101130903",
   "阿图什市": "101131501",
   "阿克陶县": "101131503",
   "阿合奇县": "101131504",
   "乌恰县": "101131502",
   "鄯善县": "101130504",
   "托克逊县": "101130502",
   "阿勒泰": "101131401",
   "和布克赛尔": "101131104",
   "伊宁市": "101131001",
   "布尔津县": "101131406",
   "奎屯市": "101131011",
   "乌苏市": "101131106",
   "额敏县": "101131103",
   "富蕴县": "101131408",
   "伊宁县": "101131004",
   "福海县": "101131407",
   "霍城县": "101131009",
   "沙湾县": "101131107",
   "巩留县": "101131005",
   "哈巴河县": "101131402",
   "托里县": "101131105",
   "青河县": "101131409",
   "新源县": "101131006",
   "裕民县": "101131102",
   "吉木乃县": "101131405",
   "昭苏县": "101131007",
   "特克斯县": "101131008",
   "尼勒克县": "101131003",
   "察布查尔": "101131002",
   "东川区": "101290103",
   "安宁市": "101290112",
   "呈贡区": "101290108",
   "晋宁县": "101290105",
   "富民县": "101290109",
   "宜良县": "101290106",
   "嵩明县": "101290110",
   "石林县": "101290107",
   "禄劝县": "101290111",
   "寻甸县": "101290104",
   "兰坪县": "101291204",
   "泸水市": "101291205",
   "福贡县": "101291203",
   "贡山县": "101291207",
   "宁洱县": "101290912",
   "思茅区": "101290905",
   "墨江县": "101290906",
   "景东县": "101290903",
   "景谷县": "101290902",
   "镇沅县": "101290911",
   "江城县": "101290907",
   "孟连县": "101290908",
   "澜沧县": "101290904",
   "西盟县": "101290909",
   "宁蒗县": "101291404",
   "永胜县": "101291402",
   "华坪县": "101291403",
   "施甸县": "101290504",
   "腾冲市": "101290506",
   "龙陵县": "101290503",
   "昌宁县": "101290505",
   "双柏县": "101290809",
   "牟定县": "101290805",
   "南华县": "101290806",
   "姚安县": "101290804",
   "大姚县": "101290802",
   "永仁县": "101290810",
   "元谋县": "101290803",
   "武定县": "101290807",
   "禄丰县": "101290808",
   "祥云县": "101290207",
   "宾川县": "101290205",
   "弥渡县": "101290206",
   "永平县": "101290204",
   "云龙县": "101290202",
   "洱源县": "101290210",
   "剑川县": "101290209",
   "鹤庆县": "101290211",
   "漾濞县": "101290203",
   "南涧县": "101290212",
   "巍山县": "101290208",
   "芒市": "101291508",
   "瑞丽市": "101291506",
   "梁河县": "101291507",
   "盈江县": "101291504",
   "陇川县": "101291503",
   "香格里拉市": "101291301",
   "德钦县": "101291302",
   "维西县": "101291303",
   "泸西县": "101290311",
   "蒙自市": "101290309",
   "个旧市": "101290308",
   "开远市": "101290307",
   "绿春县": "101290306",
   "建水县": "101290303",
   "石屏县": "101290302",
   "弥勒市": "101290304",
   "元阳县": "101290305",
   "金平县": "101290312",
   "河口县": "101290313",
   "屏边县": "101290310",
   "凤庆县": "101291105",
   "云县": "101291107",
   "永德县": "101291106",
   "镇康县": "101291108",
   "双江县": "101291104",
   "耿马县": "101291103",
   "沧源县": "101291102",
   "宣威市": "101290409",
   "马龙县": "101290405",
   "陆良县": "101290403",
   "师宗县": "101290406",
   "罗平县": "101290407",
   "富源县": "101290404",
   "会泽县": "101290408",
   "沾益区": "101290402",
   "砚山县": "101290605",
   "西畴县": "101290602",
   "麻栗坡县": "101290604",
   "马关县": "101290603",
   "丘北县": "101290606",
   "广南县": "101290607",
   "富宁县": "101290608",
   "景洪市": "101291601",
   "勐海县": "101291603",
   "勐腊县": "101291605",
   "江川区": "101290703",
   "澄江县": "101290702",
   "通海县": "101290704",
   "华宁县": "101290705",
   "易门县": "101290707",
   "峨山县": "101290708",
   "新平县": "101290706",
   "元江县": "101290709",
   "鲁甸县": "101291002",
   "巧家县": "101291006",
   "盐津县": "101291009",
   "大关县": "101291010",
   "永善县": "101291008",
   "绥江县": "101291007",
   "镇雄县": "101291004",
   "彝良县": "101291003",
   "威信县": "101291005",
   "水富县": "101291011",
   "萧山区": "101210102",
   "余杭区": "101210106",
   "建德市": "101210105",
   "富阳区": "101210108",
   "临安市": "101210107",
   "桐庐县": "101210103",
   "淳安县": "101210104",
   "德清县": "101210204",
   "长兴县": "101210202",
   "安吉县": "101210203",
   "海宁市": "101210303",
   "嘉善县": "101210302",
   "平湖市": "101210305",
   "桐乡市": "101210304",
   "海盐县": "101210306",
   "兰溪市": "101210903",
   "义乌市": "101210904",
   "加格达奇": "101050708",
   "新林": "101050706",
   "呼中": "101050705",
   "东阳市": "101210905",
   "永康市": "101210907",
   "武义县": "101210906",
   "浦江县": "101210902",
   "磐安县": "101210908",
   "龙泉市": "101210803",
   "青田县": "101210805",
   "缙云县": "101210804",
   "遂昌县": "101210802",
   "松阳县": "101210808",
   "云和县": "101210806",
   "庆元县": "101210807",
   "景宁县": "101210809",
   "镇海区": "101210412",
   "北仑区": "101210410",
   "鄞州区": "101210411",
   "余姚市": "101210404",
   "慈溪市": "101210403",
   "奉化市": "101210405",
   "象山县": "101210406",
   "宁海县": "101210408",
   "上虞区": "101210503",
   "嵊州市": "101210505",
   "越城区": "101210501",
   "新昌县": "101210504",
   "诸暨市": "101210502",
   "椒江区": "101210611",
   "黄岩区": "101210612",
   "路桥区": "101210613",
   "温岭市": "101210607",
   "临海市": "101210610",
   "玉环县": "101210603",
   "三门县": "101210604",
   "天台县": "101210605",
   "仙居县": "101210606",
   "瑞安市": "101210705",
   "乐清市": "101210707",
   "洞头区": "101210706",
   "永嘉县": "101210708",
   "平阳县": "101210704",
   "苍南县": "101210709",
   "文成县": "101210703",
   "泰顺县": "101210702",
   "定海区": "101211106",
   "普陀区": "101021500",
   "岱山县": "101211104",
   "嵊泗县": "101211102",
   "衢江区": "101211006",
   "江山市": "101211005",
   "常山县": "101211002",
   "开化县": "101211003",
   "龙游县": "101211004",
   "合川区": "101040300",
   "江津区": "101040500",
   "南川区": "101040400",
   "永川区": "101040200",
   "渝北区": "101040700",
   "万盛": "101040600",
   "万州区": "101041300",
   "北碚区": "101040800",
   "沙坪坝区": "101043800",
   "巴南区": "101040900",
   "涪陵区": "101041400",
   "黔江区": "101041100",
   "长寿区": "101041000",
   "綦江区": "101043300",
   "潼南区": "101042100",
   "铜梁区": "101042800",
   "大足区": "101042600",
   "荣昌区": "101042700",
   "璧山区": "101042900",
   "垫江县": "101042200",
   "武隆县": "101043100",
   "丰都县": "101043000",
   "城口县": "101041600",
   "梁平县": "101042300",
   "开州区": "101044100",
   "巫溪县": "101041800",
   "巫山县": "101042000",
   "奉节县": "101041900",
   "云阳县": "101041700",
   "忠县": "101042400",
   "石柱县": "101042500",
   "彭水县": "101043200",
   "酉阳县": "101043400",
   "秀山县": "101043600",
   "九龙": "101320102",
   "台北": "101340101",
   "高雄": "101340201",
   "台中": "101340401",
   "台南": "101340203",
   "新竹": "101340103",
   "嘉义": "101340202",
   "桃园": "101340102",
   "苗栗": "101340402",
   "彰化": "101340403",
   "南投": "101340404",
   "云林": "101340406",
   "屏东": "101340205",
   "台东县": "101340204",
   "花莲": "101340405",
   "合肥": "101220101",
   "长丰县": "101220102",
   "肥东县": "101220103",
   "肥西县": "101220104"
}

================================================
FILE: everyday_wechat/control/weather/rtweather.py
================================================
# coding=utf-8
"""
https://github.com/MZCretin/RollToolsApi#获取特定城市今日天气
获取特定城市今日天气
"""
import requests

__all__ = ['get_rttodayweather']


# {"code":1,"msg":"数据返回成功","data":{"address":"广西壮族自治区 桂林市 全州县",
# "cityCode":"450324","temp":"26℃","weather":"晴","windDirection":"东北","windPower":"≤3级",
# "humidity":"58%","reportTime":"2019-06-14 10:49:37"}}

def get_rttodayweather(cityname):
    """
    获取特定城市今日天气
     https://github.com/MZCretin/RollToolsApi#获取特定城市今日天气
    :param cityname:str 传入你需要查询的城市,请尽量传入完整值,否则系统会自行匹配,可能会有误差
    :return:str 天气(2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情)
    """
    print('获取 {} 的天气...'.format(cityname))
    try:
        # forecast
        resp = requests.get('https://www.mxnzp.com/api/weather/forecast/{}'.format(cityname))
        print(resp.text)
        if resp.status_code == 200:
            content_dict = resp.json()
            if content_dict['code'] == 1:
                data_dict = content_dict['data']
                address = data_dict['address'].strip()

                report_time = data_dict['reportTime'].strip()
                report_time = report_time.split(' ')[0]
                return_text = ' '.join(
                    x for x in [
                        report_time, address, data_dict['weather'], data_dict['temp'],
                        data_dict['windDirection'] + '风', data_dict['windPower'],
                        '湿度:' + data_dict['humidity']] if x)
                # print(return_text)
                return return_text
            else:
                print('获取天气失败:{}'.format(content_dict['msg']))
                # return None
        print('获取天气失败。')
    except Exception as exception:
        print(str(exception))
        # return None
    # return None


get_today_weather = get_rttodayweather



if __name__ == '__main__':
    cityname = '香港'
    weather = get_today_weather(cityname)
    # print(weather)
    pass


================================================
FILE: everyday_wechat/control/weather/sojson.py
================================================
# coding=utf-8

import requests
import json
import os
from datetime import datetime
from datetime import timedelta

__all__ = ['get_sojson_weather', 'get_sojson_weather_tomorrow']

with open(os.path.join(os.path.dirname(__file__), '_city_sojson.json'), 'r', encoding='utf-8') as f:
    CITY_CODE_DICT = json.loads(f.read())

MSG_TOMORROW = '明日{city_name}天气\n{_date} {week}\n【明日天气】{_type}\n【明日气温】{low_temp} {high_temp}\n【明日风速】{speed}\n【出行提醒】{notice}'
MSG_TODAY = '今日{city_name}天气\n{_date},{week}\n【今日天气】{_type}\n【今日气温】{low_temp} {high_temp}\n【今日风速】{speed}\n【出行提醒】{notice}'


def get_sojson_weather(city_name, is_tomorrow=False):
    """
     获取天气信息。网址:https://www.sojson.com/blog/305.html .
    :param city_name: str,城市名
    :return: str ,例如:2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情
    """
    if is_tomorrow:
        return get_sojson_weather_tomorrow(city_name)
    if not city_name:
        return None
    city_code = CITY_CODE_DICT.get(city_name, None)
    if not city_code:
        print('没有此城市的消息...')
        return None
    print('获取天气信息...')

    weather_url = 'http://t.weather.sojson.com/api/weather/city/{}'.format(city_code)
    try:
        resp = requests.get(url=weather_url)
        if resp.status_code == 200:
            # print(resp.text)
            weather_dict = resp.json()
            # 今日天气
            # {
            # "sunrise": "04:45",
            # "high": "高温 34.0℃",
            # "low": "低温 25.0℃",
            # "sunset": "19:37",
            # "aqi": 145,
            # "ymd": "2019-06-12",
            # "week": "星期三",
            # "fx": "西南风",
            # "fl": "3-4级",
            # "type": "多云",
            # "notice": "阴晴之间,谨防紫外线侵扰"
            # }
            if weather_dict.get('status') == 200:

                today_weather = weather_dict.get('data').get('forecast')[0]

                today_date = datetime.now().strftime('%Y-%m-%d')
                # 这个天气的接口更新不及时,有时候当天1点的时候,还是昨天的天气信息,如果天气不一致,则取下一天(今天)的数据
                weather_today = today_weather['ymd']
                if today_date != weather_today:
                    today_weather = weather_dict.get('data').get('forecast')[1]

                weather_info = MSG_TODAY.format(
                    city_name=city_name,
                    _date=today_weather['ymd'],
                    week=today_weather['week'],
                    _type=today_weather['type'],
                    low_temp=today_weather['low'],
                    high_temp=today_weather['high'],
                    speed=today_weather['fx'] + today_weather['fl'],
                    notice=today_weather['notice'],
                )
                return weather_info
            else:
                print('天气请求出错:{}'.format(weather_dict.get('message')))

    except Exception as exception:
        print(str(exception))
        return None



def get_sojson_weather_tomorrow(city_name):
    """
     获取明日天气信息。网址:https://www.sojson.com/blog/305.html .
    :param city_name: str,城市名
    :return: str ,例如:2019-06-12 星期三 晴 南风 3-4级 高温 22.0℃ 低温 18.0℃ 愿你拥有比阳光明媚的心情
    """
    if not city_name:
        return None
    city_code = CITY_CODE_DICT.get(city_name, None)
    if not city_code:
        print('没有此城市的消息...')
        return None
    print('获取天气信息...')

    weather_url = 'http://t.weather.sojson.com/api/weather/city/{}'.format(city_code)
    try:
        resp = requests.get(url=weather_url)
        # print(resp.text)
        if resp.status_code == 200:
            weather_dict = resp.json()
            if weather_dict.get('status') == 200:

                today_weather = weather_dict.get('data').get('forecast')[1]
                today_date = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
                # 这个天气的接口更新不及时,有时候当天1点的时候,还是昨天的天气信息,如果天气不一致,则取下一天(今天)的数据
                weather_today = today_weather['ymd']
                if today_date != weather_today:
                    today_weather = weather_dict.get('data').get('forecast')[2]
                # MSG_TOMORROW = '明日天气预报\n{city_name},{_date},{week}\n【明日天气】{_type}\n
                # 【明日温度】{low_temp} {high_temp}\n【明日风速】{speed}\n【出行提醒】{notice}'

                weather_info = MSG_TOMORROW.format(
                    city_name=city_name,
                    _date=today_weather['ymd'],
                    week=today_weather['week'],
                    _type=today_weather['type'],
                    low_temp=today_weather['low'],
                    high_temp=today_weather['high'],
                    speed=today_weather['fx'] + today_weather['fl'],
                    notice=today_weather['notice'],
                )
                return weather_info
            else:
                print('天气请求出错:{}'.format(weather_dict.get('message')))

    except Exception as exception:
        print(str(exception))
        return None


get_today_weather = get_sojson_weather

if __name__ == '__main__':
    is_tomorrow = True
    we = get_sojson_weather('青岛', is_tomorrow)
    print(we)
    # pass


================================================
FILE: everyday_wechat/main.py
================================================
# coding=utf-8

"""
每天定时给多个女友发给微信暖心话
核心代码。
"""

import time
# import json
import platform
import os
# from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.schedulers.background import BackgroundScheduler
import itchat
from itchat.content import (
    TEXT
)

from everyday_wechat.utils.data_collection import (
    get_weather_info,
    get_dictum_info,
    get_diff_time,
    get_calendar_info,
    get_constellation_info
)
from everyday_wechat.control.airquality.air_quality_aqicn import (
    get_air_quality
)
from everyday_wechat.utils import config
from everyday_wechat.utils.itchat_helper import (
    init_wechat_config,
    set_system_notice,
)
from everyday_wechat.utils.group_helper import (
    handle_group_helper
)
from everyday_wechat.utils.friend_helper import (
    handle_friend
)

__all__ = ['run', 'delete_cache']


def run():
    """ 主运行入口 """
    # 判断是否登录,如果没有登录则自动登录,返回 False 表示登录失败
    print('开始登录...')
    if not is_online(auto_login=True):
        print('程序已退出...')
        return


def is_online(auto_login=False):
    """
    判断是否还在线。
    :param auto_login: bool,当为 Ture 则自动重连(默认为 False)。
    :return: bool,当返回为 True 时,在线;False 已断开连接。
    """

    def _online():
        """
        通过获取好友信息,判断用户是否还在线。
        :return: bool,当返回为 True 时,在线;False 已断开连接。
        """
        try:
            if itchat.search_friends():
                return True
        except IndexError:
            return False
        return True

    if _online(): return True  # 如果在线,则直接返回 True
    if not auto_login:  # 不自动登录,则直接返回 False
        print('微信已离线..')
        return False

    # hotReload = not config.get('is_forced_switch', False)  # 切换微信号,重新扫码。
    hotReload = False  # 2019年9月27日15:31:22 最近保存最近登录状态出错,所以先设置每次都得扫码登录
    loginCallback = init_data
    exitCallback = exit_msg
    try:
        for _ in range(2):  # 尝试登录 2 次。
            if platform.system() in ('Windows', 'Darwin'):
                itchat.auto_login(hotReload=hotReload,
                                  loginCallback=loginCallback, exitCallback=exitCallback)
                itchat.run(blockThread=True)
            else:
                # 命令行显示登录二维码。
                itchat.auto_login(enableCmdQR=2, hotReload=hotReload, loginCallback=loginCallback,
                                  exitCallback=exitCallback)
                itchat.run(blockThread=True)
            if _online():
                print('登录成功')
                return True
    except Exception as exception:  # 登录失败的错误处理。
        sex = str(exception)
        if sex == "'User'":
            print('此微信号不能登录网页版微信,不能运行此项目。没有任何其它解决办法!可以换个号再试试。')
        else:
            print(sex)

    delete_cache()  # 清理缓存数据
    print('登录失败。')
    return False


def delete_cache():
    """ 清除缓存数据,避免下次切换账号时出现 """
    file_names = ('QR.png', 'itchat.pkl')
    for file_name in file_names:
        if os.path.exists(file_name):
            os.remove(file_name)


def init_data():
    """ 初始化微信所需数据 """
    set_system_notice('登录成功')
    itchat.get_friends(update=True)  # 更新好友数据。
    itchat.get_chatrooms(update=True)  # 更新群聊数据。

    init_wechat_config()  # 初始化所有配置内容

    # 提醒内容不为空时,启动定时任务
    alarm_dict = config.get('alarm_info').get('alarm_dict')
    if alarm_dict:
        init_alarm(alarm_dict)  # 初始化定时任务

    print('初始化完成,开始正常工作。')


def init_alarm(alarm_dict):
    """
    初始化定时任务
    :param alarm_dict: 定时相关内容
    """
    # 定时任务
    scheduler = BackgroundScheduler()
    for key, value in alarm_dict.items():
        scheduler.add_job(send_alarm_msg, 'cron', [key], hour=value['hour'],
                          minute=value['minute'], id=key, misfire_grace_time=600, jitter=value.get("alarm_jitter",0))
    scheduler.start()

    # print('已开启定时发送提醒功能...')
    # print(scheduler.get_jobs())


def send_alarm_msg(key):
    """ 发送定时提醒 """
    print('\n启动定时自动提醒...')
    conf = config.get('alarm_info').get('alarm_dict')

    gf = conf.get(key)
    # print(gf)air_quality_city
    is_tomorrow = gf.get('is_tomorrow', False)
    calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow)
    weather = get_weather_info(gf.get('city_name'), is_tomorrow)
    horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow)
    dictum = get_dictum_info(gf.get('dictum_channel'))
    diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg'))
    air_quality = get_air_quality(gf.get('air_quality_city'))

    sweet_words = gf.get('sweet_words')
    send_msg = '\n'.join(
        x for x in [calendar_info, weather, air_quality, horoscope, dictum, diff_time, sweet_words] if x)
    # print('\n' + send_msg + '\n')
    if not send_msg or not is_online(): return
    uuid_list = gf.get('uuid_list')
    for uuid in uuid_list:
        time.sleep(1)
        itchat.send(send_msg, toUserName=uuid)
    print('\n定时内容:\n{}\n发送成功...\n\n'.format(send_msg))
    print('自动提醒消息发送完成...\n')


@itchat.msg_register([TEXT])
def text_reply(msg):
    """ 监听用户消息,用于自动回复 """
    handle_friend(msg)
    # 下面这段代码,可以很直观打印出返回的消息的数据结构。
    # 把打印的数据复制到  https://www.json.cn/ 可查看详细的内容。群消息同理
    # import json
    # print(json.dumps(msg, ensure_ascii=False))


@itchat.msg_register([TEXT], isGroupChat=True)
def text_group(msg):
    """ 监听用户消息,用于自动回复 """
    handle_group_helper(msg)


def exit_msg():
    """ 退出通知 """
    print('程序已退出')


if __name__ == '__main__':
    # run()
    pass
    # config.init()
    # init_wechat()


================================================
FILE: everyday_wechat/utils/__init__.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2019/6/23
# Author: snow




================================================
FILE: everyday_wechat/utils/common.py
================================================
# coding=utf-8
"""
工具类
"""
import re
import hashlib
import json

__all__ = [
    'FILEHELPER_MARK', 'FILEHELPER', 'SPIDER_HEADERS', 'WEEK_DICT',
    'BIRTHDAY_COMPILE', 'CONSTELLATION_NAME_LIST', 'CONSTELLATION_DATE_DICT',
    'is_json', 'md5_encode', 'get_constellation_name']

FILEHELPER_MARK = ['文件传输助手', 'filehelper']  # 文件传输助手标识
FILEHELPER = 'filehelper'

SPIDER_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; '
                  'WOW64; rv:60.0) Gecko/20100101 Firefox/60.0',
}

WEEK_DICT = {
    'Monday': '星期一', 'Tuesday': '星期二', 'Wednesday': '星期三',
    'Thursday': '星期四', 'Friday': '星期五', 'Saturday': '星期六',
    'Sunday': '星期日'
}

BIRTHDAY_COMPILE = re.compile(r'[\-\s]?(0?[1-9]|1[012])[\-\/\s]+(0?[1-9]|[12][0-9]|3[01])$')
CONSTELLATION_NAME_LIST = (
    "摩羯座", "水瓶座", "双鱼座", "白羊座",
    "金牛座", "双子座", "巨蟹座", "狮子座",
    "处女座", "天秤座", "天蝎座", "射手座")

CONSTELLATION_DATE_DICT = {
    (1, 20): '摩羯座',
    (2, 19): '水瓶座',
    (3, 21): '双鱼座',
    (4, 21): '白羊座',
    (5, 21): '金牛座',
    (6, 22): '双子座',
    (7, 23): '巨蟹座',
    (8, 23): '狮子座',
    (9, 23): '处女座',
    (10, 23): '天秤座',
    (11, 23): '天蝎座',
    (12, 23): '射手座',
    (12, 32): '摩羯座',
}


def is_json(resp):
    """
    判断数据是否能被 Json 化。 True 能,False 否。
    :param resp: request.
    :return: bool, True 数据可 Json 化;False 不能 JOSN 化。
    """
    try:
        json.loads(resp.text)
        return True
    except AttributeError as error:
        return False
    return False


def md5_encode(text):
    """ 把數據 md5 化 """
    if not isinstance(text, str):
        text = str(text)
    md5 = hashlib.md5()
    md5.update(text.encode('utf-8'))
    encodedStr = md5.hexdigest().upper()
    return encodedStr


def get_constellation_name(date):
    '''
    通过日期来返回星座名,或者檢查星座名是否正確。
    :param date: 指定日期或者星座名
    :return:rtype str
    '''
    if not date:
        return
    date = date.strip()
    if date in CONSTELLATION_NAME_LIST:
        return date

    times = BIRTHDAY_COMPILE.findall(date)
    if times:
        month, day = int(times[0][0]), int(times[0][1])
        for k, v in CONSTELLATION_DATE_DICT.items():
            if k > (month, day):
                return v
    return None


if __name__ == '__main__':
    print(md5_encode('aeryou'))
    pass


================================================
FILE: everyday_wechat/utils/config.py
================================================
# coding=utf-8
"""
用于管理缓存的配置数据
使用前必须先调用 init() 。
"""
import os
import copy as mycopy
import yaml

__all__ = ['set', 'get', 'copy', 'update', '_print']


# def init():
#     """
#     将 yaml 里的配置文件导入到 config.py 中
#     :return: bool ,true 表示数据导入成功。
#     """
#     global opts
#     opts = get_yaml()
#     if opts:
#         return True
#     return False

def get_yaml():
    """
    解析 yaml
    :return: s  字典
    """
    path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '_config.yaml')
    try:

        with open(path, 'r', encoding='utf-8') as file:
            config = yaml.safe_load(file)
            # config = yaml.load(file, Loader=yaml.Loader)
        return config
    except Exception as exception:
        print(str(exception))
        print('你的 _config.yaml 文件配置出错...')
    return None

opts = get_yaml()

def set(key, value):
    """ 通过 key 设置某一项值 """
    opts[key] = value


def get(key, default=None):
    """ 通过 key 获取值 """
    return opts.get(key, default)


def copy():
    """ 复制配置 """
    return mycopy.deepcopy(opts)


def update(new_opts):
    """ 全部替换配置 """
    opts.update(new_opts)


def _print():
    print(opts)


if __name__ == '__main__':
    you = get('is_forced_switch')
    print(you)


================================================
FILE: everyday_wechat/utils/data_collection.py
================================================
# coding=utf-8
"""
获取各种请求的调度管理中心
"""
import importlib
import re
from datetime import datetime
from datetime import timedelta

# from everyday_wechat.control.weather.rtweather import get_today_weather
from everyday_wechat.control.weather.sojson import get_sojson_weather
from everyday_wechat.utils.common import (
    get_constellation_name,
)
from everyday_wechat.utils import config
from everyday_wechat.control.horoscope.xzw_horescope import get_today_horoscope
# from everyday_wechat.control.calendar.sojson_calendar import get_sojson_calendar
from everyday_wechat.control.calendar.rt_calendar import get_rtcalendar

__all__ = [
    'get_dictum_info', 'get_weather_info', 'get_bot_info',
    'get_diff_time', 'get_constellation_info', 'get_calendar_info',
    'DICTUM_NAME_DICT', 'BOT_NAME_DICT'
]

DICTUM_NAME_DICT = {
    1: 'wufazhuce', 2: 'acib', 3: 'lovelive', 4: 'hitokoto',
    5: 'rtjokes', 6: 'juzimi', 7: 'caihongpi'
}
BOT_NAME_DICT = {
    1: 'tuling123', 2: 'yigeai', 3: 'qingyunke', 4: 'qq_nlpchat',
    5: 'tian_robot', 6: 'ruyiai', 7: 'ownthink_robot'
}
# 用于星座的正则表达式
BIRTHDAY_COMPILE = re.compile(r'\-?(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$')


def get_dictum_info(channel):
    """
    获取每日一句。
    :return:str
    """
    if not channel:
        return None
    source = DICTUM_NAME_DICT.get(channel, '')
    if source:
        addon = importlib.import_module('everyday_wechat.control.onewords.' + source, __package__)
        dictum = addon.get_one_words()
        # print(dictum)
        return dictum
    return None


def get_weather_info(cityname, is_tomorrow=False):
    """
    获取天气
    :param cityname:str,城市名称
    :return: str,天气情况
    """
    if not cityname:
        return
    # return get_today_weather(cityname)
    return get_sojson_weather(cityname, is_tomorrow)


def get_bot_info(message, userId=''):
    """
    跟机器人互动
    # 优先获取图灵机器人API的回复,但失效时,会使用青云客智能聊天机器人API(过时)
    :param message:str, 发送的话
    :param userId: str, 好友的uid,作为请求的唯一标识。
    :return:str, 机器人回复的话。
    """

    channel = config.get('auto_reply_info').get('bot_channel', 7)
    source = BOT_NAME_DICT.get(channel, 'ownthink_robot')
    # print(source)
    if source:
        addon = importlib.import_module('everyday_wechat.control.bot.' + source, __package__)
        reply_msg = addon.get_auto_reply(message, userId)
        return reply_msg
    # reply_msg = get_tuling123(message)
    # if not reply_msg:
    #     # reply_msg = get_qingyunke(message)
    #     reply_msg = get_yigeai(message)

    return None


def get_diff_time(start_date, start_msg=''):
    """
    # 在一起,一共多少天了。
    :param start_date:str,日期
    :return: str,eg(宝贝这是我们在一起的第 111 天。)
    """
    if not start_date:
        return None
    rdate = r'^[12]\d{3}[ \/\-](?:0?[1-9]|1[012])[ \/\-](?:0?[1-9]|[12][0-9]|3[01])$'
    start_date = start_date.strip()
    if not re.search(rdate, start_date):
        print('日期填写出错..')
        return
    start_datetime = datetime.strptime(start_date, '%Y-%m-%d')
    day_delta = (datetime.now() - start_datetime).days + 1
    if start_msg and start_msg.count('{}') == 1:
        delta_msg = start_msg.format(day_delta)
    else:
        delta_msg = '宝贝这是我们在一起的第 {} 天。'.format(day_delta)
    return delta_msg


def get_constellation_info(birthday_str, is_tomorrow=False):
    """
    获取星座运势
    :param birthday_str:  "10-12" 或  "1980-01-08" 或 星座名
    :return:
    """
    if not birthday_str:
        return
    const_name = get_constellation_name(birthday_str)
    if not const_name:
        print('星座名填写错误')
        return
    return get_today_horoscope(const_name, is_tomorrow)


def get_calendar_info(calendar=True, is_tomorrow=False, _date=''):
    """ 获取万年历 """
    if not calendar:
        return None
    if not is_tomorrow:
        date = datetime.now().strftime('%Y%m%d')
    else:
        date = (datetime.now() + timedelta(days=1)).strftime('%Y%m%d')
    return get_rtcalendar(date)

    # else:
    #     time_now = datetime.now()
    #     week = WEEK_DICT[time_now.strftime('%A')]
    #     date = time_now.strftime('%Y-%m-%d')
    #     return '{} {}'.format(date, week)


if __name__ == '__main__':
    config.init()
    text = 'are you ok'
    reply_msg = get_bot_info(text)
    print(reply_msg)
    pass


================================================
FILE: everyday_wechat/utils/db_helper.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-12 18:37
Introduction:
"""

import pymongo
from everyday_wechat.utils import config
from functools import wraps
from datetime import datetime

__all__ = [
    'is_open_db', 'udpate_weather', 'udpate_user_city', 'find_user_city',
    'find_weather', 'update_perpetual_calendar', 'find_perpetual_calendar',
    'find_rubbish', 'update_rubbish', 'find_movie_box', 'update_movie_box',
    'find_express', 'update_express', 'find_air_quality', 'udpate_air_quality'
]

cache_valid_time = 4 * 60 * 60  # 天气缓存有效时间
db_config = config.get('db_config')
if db_config and db_config.get('is_open_db') and db_config.get('mongodb_conf'):
    is_open_db = db_config.get('is_open_db')
    mongodb_conf = db_config.get('mongodb_conf')
    try:
        myclient = pymongo.MongoClient(
            host=mongodb_conf.get('host'),
            port=mongodb_conf.get('port'),
            serverSelectionTimeoutMS=10)
        myclient.server_info()  # 查看数据库信息,在这里用于是否连接数据的测试

        wechat_helper_db = myclient["wechat_helper"]
        weather_db = wechat_helper_db['weather']
        user_city_db = wechat_helper_db['user_city']
        perpetual_calendar_db = wechat_helper_db['perpetual_calendar']
        rubbish_db = wechat_helper_db['rubbish_assort']
        movie_box_db = wechat_helper_db['movie_box']  # 电影票房
        express_db = wechat_helper_db['express']  # 快递票房
        air_quality_db = wechat_helper_db['air_quality']  # 空气质量票房

    except pymongo.errors.ServerSelectionTimeoutError as err:
        # print(str(err))
        # print('数据库连接失败')
        is_open_db = False  # 把数据库设为不可用
else:
    is_open_db = False


def db_flag():
    """ 用于数据库操作的 flag 没开启就不进行数据库操作"""

    def _db_flag(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if is_open_db:
                return func(*args, **kwargs)
            else:
                return None

        return wrapper

    return _db_flag


@db_flag()
def udpate_weather(data):
    """
    更新天气数据
    :param data:
    """
    key = {'_date': data['_date'], 'city_name': data['city_name']}
    weather_db.update_one(key, {"$set": data}, upsert=True)


@db_flag()
def udpate_user_city(data):
    """
    更新用户城市信息,用户最后一次查询成功的城市名
    :param data:
    """
    key = {'userid': data['userid']}
    user_city_db.update_one(key, {"$set": data}, upsert=True)


@db_flag()
def find_user_city(uuid):
    """
    找到用户的城市,用户最后一次查询的城市名
    :param uuid:
    :return:
    """
    key = {'userid': uuid}
    data = user_city_db.find_one(key)
    if data:
        return data['city_name']


@db_flag()
def find_weather(date, cityname):
    """
    根据日期与城市名获取天气信息,天气信息有效期为 4 小时
    :param date: 日期(yyyy-mm-dd)
    :param cityname: 城市名
    :return: 天气信息
    """
    key = {'_date': date, 'city_name': cityname}
    data = weather_db.find_one(key)
    if data:
        diff_second = (datetime.now() - data['last_time']).seconds
        if diff_second <= cache_valid_time:
            return data['weather_info']
    return None


@db_flag()
def update_perpetual_calendar(_date, info):
    """
    更新日历信息
    :param _date: 日期(yyyy-mm-dd)
    :param info: 内容
    :return: None
    """
    key = {'_date': _date}
    data = {
        '_date': _date,
        'info': info,
        'last_time': datetime.now()
    }
    perpetual_calendar_db.update_one(key, {"$set": data}, upsert=True)


@db_flag()
def find_perpetual_calendar(_date):
    """
    查找日历内容
    :param _date: str 日期(yyyy-mm-dd)
    :return: str
    """
    key = {'_date': _date}
    data = perpetual_calendar_db.find_one(key)
    if data:
        return data['info']


@db_flag()
def find_rubbish(name):
    """
    从数据库里查询获取内容
    {'name': '爱群主', 'type': '什么垃圾'}
    """
    key = {'name': name}
    one = rubbish_db.find_one(key, {"_id": 0, "name": 1, "type": 1})
    if one:
        return one['type']
    return None


# 保存进数据库
# 如果有数据,则更新类别
@db_flag()
def update_rubbish(data):
    """
    将垃圾保存数据库
    :param data:
    :return:
    """
    if isinstance(data, str):
        data = [data]
    if isinstance(data, list):
        for d in data:
            key = {'name': d['name']}
            value = {"$set": {"type": d['type']}}
            rubbish_db.update_one(key, value, upsert=True)


@db_flag()
def find_movie_box(date):
    """
    查询电脑票房,
    如果是历史票房,则直接返回数据
    如果不是,保存时间在5分钟内,则直接返回数据。
    其他情况,返回为空
    :param date: 查询时间
    :return:
    """
    key = {'_date': date}
    data = movie_box_db.find_one(key)
    if data:
        is_expired = data['is_expired']
        if is_expired:
            return data['info']
        diff_second = (datetime.now() - data['last_time']).seconds
        if diff_second <= 5 * 60:
            return data['info']
    return None


@db_flag()
def update_movie_box(date, info, is_expired=False):
    """
    保存实时票房
    :param date: 日期 yyyyDDmm 格式
    :param info: 票房内容
    :param is_today: 是否是今日实时票房
    :return: None
    """
    key = {'_date': date}
    data = {
        '_date': date,
        'info': info,
        'last_time': datetime.now(),
        'is_expired': is_expired
    }
    movie_box_db.update_one(key, {"$set": data}, upsert=True)


@db_flag()
def update_express(data, uuid):
    """
    更新快递内容, 包括
    {'express_code': '78109182715352','shipper_code': 'ZTO',
    'shipper_name': '中通速递','info': '很多内容', 'state': True}
    :param data: dict 内容数据
    :param uuid: str 用户 uid
    :return:
    """
    key = {'express_code': data['express_code']}
    data['userid'] = uuid
    data['last_time'] = datetime.now()
    express_db.update_one(key, {"$set": data}, upsert=True)
    return None


@db_flag()
def find_express(express_code='', uuid=''):
    """
    获取缓存快递信息,express_code ,uuid 不可同时为空
    缓存时间:5 分钟
    :param express_code: str,快递单号
    :param uuid: str,用户 uid
    :return: dict ,快递信息
    """
    key = {}
    if express_code:
        key['express_code'] = express_code
    elif uuid:
        key['userid'] = uuid
    else:
        return None
    data = express_db.find_one(key)
    if data:
        data['is_forced_update'] = False  # 是否需要强制更新
        state = data['state']
        if state:  # 订单是否已完成所有流程
            return data
        diff_second = (datetime.now() - data['last_time']).seconds
        if diff_second <= 5 * 60:  # 有效缓存期 5分钟
            return data
        else:
            data['is_forced_update'] = True
            return data
    return None

@db_flag()
def find_air_quality(city):
    """
    根据日期与城市名获取空气信息,pm2.5 记录有效期为 1 小时
    :param city: 城市名
    :return: 空气信息
    """
    key = {'city': city}
    data = air_quality_db.find_one(key)
    if data:
        diff_second = (datetime.now() - data['last_time']).seconds
        if diff_second <= 1 * 60 * 60:
            return data['info']
    return None

@db_flag()
def udpate_air_quality(city, info):
    """
    :param city: 城市名
    :param info: 空气情况
    :return:
    """
    key = {'city': city}
    data = {
        'city': city,
        'info': info,
        'last_time': datetime.now()
    }
    air_quality_db.update_one(key, {"$set": data}, upsert=True)


# if __name__ == '__main__':
#     uuid = '123uuid'
#     y = find_user_city(uuid)
#     print(y)
#
#     _date = datetime.now().strftime('%Y-%m-%d')
#     cityname = '南京'
#     fw = find_weather(_date, cityname)
#     print(fw)


================================================
FILE: everyday_wechat/utils/friend_helper.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-12 23:07
Introduction: 处理好友消息内容
"""

import time
import random
import itchat
from everyday_wechat.utils import config
from everyday_wechat.utils.data_collection import (
    get_bot_info,
)
from everyday_wechat.utils.common import (
    FILEHELPER,
)

__all__ = ['handle_friend']


def handle_friend(msg):
    """ 处理好友信息 """
    try:

        # 自己通过手机微信发送给别人的消息(文件传输助手除外)不作处理。
        if msg['FromUserName'] == config.get('wechat_uuid') and msg['ToUserName'] != FILEHELPER:
            return

        conf = config.get('auto_reply_info')
        if not conf.get('is_auto_reply'):
            return
        # 获取发送者的用户id
        uuid = FILEHELPER if msg['ToUserName'] == FILEHELPER else msg['FromUserName']
        is_all = conf.get('is_auto_reply_all')
        auto_uuids = conf.get('auto_reply_black_uuids') if is_all else conf.get('auto_reply_white_uuids')
        # 开启回复所有人,当用户是黑名单,不回复消息
        if is_all and uuid in auto_uuids:
            return

        # 关闭回复所有人,当用户不是白名单,不回复消息
        if not is_all and uuid not in auto_uuids:
            return

        receive_text = msg.text  # 好友发送来的消息内容
        # 好友叫啥,用于打印
        nick_name = FILEHELPER if uuid == FILEHELPER else msg.user.nickName
        print('\n{}发来信息:{}'.format(nick_name, receive_text))
        reply_text = get_bot_info(receive_text, uuid)  # 获取自动回复
        if reply_text:  # 如内容不为空,回复消息
            time.sleep(random.randint(1, 2))  # 休眠一秒,保安全。想更快的,可以直接注释。

            prefix = conf.get('auto_reply_prefix', '')  # 前缀
            if prefix:
                reply_text = '{}{}'.format(prefix, reply_text)

            suffix = conf.get('auto_reply_suffix', '')  # 后缀
            if suffix:
                reply_text = '{}{}'.format(reply_text, suffix)

            itchat.send(reply_text, toUserName=uuid)
            print('回复{}:{}'.format(nick_name, reply_text))
        else:
            print('自动回复失败\n')
    except Exception as exception:
        print(str(exception))


================================================
FILE: everyday_wechat/utils/group_helper.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-11 12:55
Introduction: 群消息处理
"""

import re
from datetime import datetime
import itchat

from everyday_wechat.utils import config
from everyday_wechat.control.calendar.rt_calendar import get_rtcalendar
from everyday_wechat.utils.data_collection import (
    get_weather_info,
    get_bot_info,
    # get_calendar_info,
)
from everyday_wechat.control.rubbish.atoolbox_rubbish import (
    get_atoolbox_rubbish
)
from everyday_wechat.control.moviebox.maoyan_movie_box import (
    get_maoyan_movie_box
)
from everyday_wechat.control.express.kdniao_express import (
    get_express_info
)
from everyday_wechat.control.airquality.air_quality_aqicn import (
    get_air_quality
)

from everyday_wechat.utils.db_helper import (
    find_perpetual_calendar,
    find_user_city,
    find_weather,
    udpate_user_city,
    udpate_weather,
    update_perpetual_calendar,
    find_rubbish,
    update_rubbish,
    find_movie_box,
    update_movie_box,
    find_express,
    update_express,
    find_air_quality,
    udpate_air_quality
)

__all__ = ['handle_group_helper']

at_compile = r'(@.*?\s{1,}).*?'
tomorrow_compile = r'明[日天]'

punct_complie = r'[^a-zA-z0-9\u4e00-\u9fa5]+$'  # 去除句子最后面的标点
help_complie = r'^(?:0|帮忙|帮助|help)\s*$'

weather_compile = r'^(?:\s*(?:1|天气|weather)(?!\d).*?|.*?(?:天气|weather)\s*)$'
weather_clean_compile = r'1|天气|weather|\s'
calendar_complie = r'^\s*(?:2|日历|万年历|calendar)(?=19|2[01]\d{2}|\s|$)'
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日号]*$'
rubbish_complie = r'^\s*(?:3|垃圾|rubbish)(?!\d)'
moviebox_complie = r'^\s*(?:4|票房|moviebox)(?=19|2[01]\d{2}|\s|$)'
express_complie = r'^\s*(?:5|快递[单号]?|express)\s*([0-9a-zA-Z]+)'

air_compile = r'^(?:\s*(?:6|空气|pm\s?2\.?5)(?!\d).*?|.*?(?:空气|pm\s?2\.?5)\s*)$'
air_clean_compile = air_clean_compile = r'6|空气(?:质量)?|pm\s?2\.?5|\s'

common_msg = '@{ated_name}\u2005\n{text}'
weather_error_msg = '@{ated_name}\u2005\n未找到『{city}』城市的天气信息'
weather_null_msg = '@{ated_name}\u2005\n 请输入城市名'

calendar_error_msg = '@{ated_name}\u2005日期格式不对'
calendar_no_result_msg = '@{ated_name}\u2005未找到{_date}的日历数据'

rubbish_normal_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』属于{_type}'
rubbish_other_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』无记录\n【推荐查询】:{other}'
rubbish_nothing_msg = '@{ated_name}\u2005\n【查询结果】:『{name}』无记录'
rubbish_null_msg = '@{ated_name}\u2005 请输入垃圾名称'

moiebox_no_result_msg = '@{ated_name}\u2005未找到{_date}的票房数据'

air_city_null_msg = '@{ated_name}\u2005\n 请输入城市名'
air_error_msg = '@{ated_name}\u2005\n未找到『{city}』城市的空气质量信息'

help_group_content = """@{ated_name}
群助手功能:
1.输入:天气(weather)+城市名(可空)。例如:天气北京
2.输入:日历(calendar)+日期(格式:yyyy-MM-dd 可空)。例如:日历2019-07-03
3.输入:垃圾(rubbish)+名称。例如:3猫粮
4.输入:票房(moviebox)+日期。例如:票房
5.输入:快递(express)+ 快递订单号。例如: 快递 1231231231 
6.输入:空气(pm25)+城市名。例如:pm2.5 北京
更多功能:请输入 0|help|帮助,查看。
"""


# import pysnooper
# @pysnooper.snoop()
def handle_group_helper(msg):
    """
    处理群消息
    :param msg:
    :return:
    """
    uuid = msg.fromUserName  # 群 uid
    ated_uuid = msg.actualUserName  # 艾特你的用户的uuid
    ated_name = msg.actualNickName  # 艾特你的人的群里的名称
    text = msg['Text']  # 发送到群里的消息。

    # 自己通过手机端微信发出的消息不作处理
    if ated_uuid == config.get('wechat_uuid'):
        return

    conf = config.get('group_helper_conf')
    if not conf.get('is_open'):
        return

    # 如果开启了 『艾特才回复』,而群用户又没有艾特你。不处理消息
    if conf.get('is_at') and not msg.isAt:
        return

    is_all = conf.get('is_all', False)
    user_uuids = conf.get('group_black_uuids') if is_all else conf.get('group_white_uuids')
    # 开启回复所有群,而用户是黑名单,不处理消息
    if is_all and uuid in user_uuids:
        return

    # 未回复所有群,而用户不是白名单,不处理消息
    if not is_all and uuid not in user_uuids:
        return
    # 去掉 at 标记
    text = re.sub(at_compile, '', text)

    # 如果是帮助设置
    helps = re.findall(help_complie, text, re.I)
    if helps:
        retext = help_group_content.format(ated_name=ated_name)
        itchat.send(retext, uuid)
        return

    # 是否是明天,用于日历,天气,星座查询
    is_tomorrow = re.findall(tomorrow_compile, text)
    if is_tomorrow:
        is_tomorrow = True
        htext = re.sub(tomorrow_compile, '', text)
    else:
        is_tomorrow = False
        htext = text

    htext = re.sub(punct_complie, '', htext)  # 去句末的标点

    # 已开启天气查询,并包括天气关键词
    if conf.get('is_weather'):
        if re.findall(weather_compile, htext, re.I):
            city = re.sub(weather_clean_compile, '', text, flags=re.IGNORECASE).strip()

            if not city:  # 如果只是输入城市名
                # 从缓存数据库找最后一次查询的城市名
                city = find_user_city(ated_uuid)
            if not city:  # 缓存数据库没有保存,通过用户的资料查城市
                city = get_city_by_uuid(ated_uuid)
            if not city:
                retext = weather_null_msg.format(ated_name=ated_name)
                itchat.send(retext, uuid)
                return

            _date = datetime.now().strftime('%Y-%m-%d')
            weather_info = find_weather(_date, city)
            if weather_info:
                retext = common_msg.format(ated_name=ated_name, text=weather_info)
                itchat.send(retext, uuid)
                return

            weather_info = get_weather_info(city)
            if weather_info:
                # print(ated_name, city, retext)
                retext = common_msg.format(ated_name=ated_name, text=weather_info)
                itchat.send(retext, uuid)

                data = {
                    '_date': _date,
                    'city_name': city,
                    'weather_info': weather_info,
                    'userid': ated_uuid,
                    'last_time': datetime.now()
                }
                udpate_weather(data)
                # userid,city_name,last_time,group_name udpate_weather_city
                data2 = {
                    'userid': ated_uuid,
                    'city_name': city,
                    'last_time': datetime.now()
                }
                udpate_user_city(data2)
                return
            else:
                retext = weather_error_msg.format(ated_name=ated_name, city=city)
                itchat.send(retext, uuid)
                return
            return

    # 已开启日历,并包含日历
    if conf.get('is_calendar'):
        if re.findall(calendar_complie, htext, flags=re.IGNORECASE):

            calendar_text = re.sub(calendar_complie, '', htext).strip()
            if calendar_text:  # 日历后面填上日期了
                dates = re.findall(calendar_date_compile, calendar_text)
                if not dates:
                    retext = calendar_error_msg.format(ated_name=ated_name)
                    itchat.send(retext, uuid)
                    return

                _date = '{}-{:0>2}-{:0>2}'.format(*dates[0])  # 用于保存数据库
                rt_date = '{}{:0>2}{:0>2}'.format(*dates[0])  # 用于查询日历
            else:  # 日历 后面没有日期,则默认使用今日。
                _date = datetime.now().strftime('%Y-%m-%d')
                rt_date = datetime.now().strftime('%Y%m%d')

            # 从数据库缓存中记取内容
            cale_info = find_perpetual_calendar(_date)
            if cale_info:
                retext = common_msg.format(ated_name=ated_name, text=cale_info)
                itchat.send(retext, uuid)
                return

            # 取网络数据
            cale_info = get_rtcalendar(rt_date)
            if cale_info:
                retext = common_msg.format(ated_name=ated_name, text=cale_info)
                itchat.send(retext, uuid)
                update_perpetual_calendar(_date, cale_info)  # 保存数据到数据库
                return
            else:  # 查询无结果
                retext = calendar_no_result_msg.format(ated_name=ated_name, _date=_date)
                itchat.send(retext, uuid)
            return

    # 垃圾分类查询
    if conf.get('is_rubbish'):
        if re.findall(rubbish_complie, htext, re.I):
            key = re.sub(rubbish_complie, '', htext, flags=re.IGNORECASE).strip()
            if not key:
                retext = rubbish_null_msg.format(ated_name=ated_name)
                itchat.send(retext, uuid)
                return

            _type = find_rubbish(key)
            if _type:
                retext = rubbish_normal_msg.format(ated_name=ated_name, name=key, _type=_type)
                itchat.send(retext, uuid)
                return
            _type, return_list, other = get_atoolbox_rubbish(key)
            if _type:
                retext = rubbish_normal_msg.format(ated_name=ated_name, name=key, _type=_type)
                itchat.send_msg(retext, uuid)
            elif other:
                retext = rubbish_other_msg.format(ated_name=ated_name, name=key, other=other)
                itchat.send_msg(retext, uuid)
            else:
                retext = rubbish_nothing_msg.format(ated_name=ated_name, name=key)
                itchat.send_msg(retext, uuid)
            if return_list:
                update_rubbish(return_list)  # 保存数据库
            return

    if conf.get('is_moviebox'):
        if re.findall(moviebox_complie, htext, re.I):
            moviebox_text = re.sub(moviebox_complie, '', htext).strip()
            if moviebox_text:  # 日历后面填上日期了
                dates = re.findall(calendar_date_compile, moviebox_text)
                if not dates:
                    retext = calendar_error_msg.format(ated_name=ated_name)
                    itchat.send(retext, uuid)
                    return
                _date = '{}{:0>2}{:0>2}'.format(*dates[0])
            else:  # 日历 后面没有日期,则默认使用今日。
                _date = datetime.now().strftime('%Y%m%d')
            # 从数据库缓存中记取内容
            mb_info = find_movie_box(_date)
            if mb_info:
                retext = common_msg.format(ated_name=ated_name, text=mb_info)
                itchat.send(retext, uuid)
                return

            is_expired = False
            cur_date = datetime.now().date()
            query_date = datetime.strptime(_date, '%Y%m%d').date()

            if query_date < cur_date:
                is_expired = True

            # 取网络数据
            mb_info = get_maoyan_movie_box(_date, is_expired)
            if mb_info:
                retext = common_msg.format(ated_name=ated_name, text=mb_info)
                itchat.send(retext, uuid)
                update_movie_box(_date, mb_info, is_expired)  # 保存数据到数据库
                return
            else:  # 查询无结果
                retext = moiebox_no_result_msg.format(ated_name=ated_name, _date=_date)
                itchat.send(retext, uuid)
            return

    # 处理订单号
    if conf.get('is_express'):
        express_list = re.findall(express_complie, htext, re.I)
        if express_list:
            express_code = express_list[0]
            db_data = find_express(express_code, uuid)
            shipper_code, shipper_name = '', ''
            if db_data:
                if not db_data['is_forced_update']:
                    info = db_data['info']
                    retext = common_msg.format(ated_name=ated_name, text=info)
                    itchat.send(retext, uuid)
                    return
                shipper_code = db_data['shipper_code']
                shipper_name = db_data['shipper_name']

            data = get_express_info(
                express_code,
                shipper_name=shipper_name,
                shipper_code=shipper_code)
            if data:
                info = data['info']
                retext = common_msg.format(ated_name=ated_name, text=info)
                itchat.send(retext, uuid)
                update_express(data, uuid)
                return
            else:
                print('未查询到此订单号的快递物流轨迹。')
                return

    # 处理空气质量查询号
    if conf.get('is_air_quality'):
        if re.findall(air_compile, htext, re.I):
            city = re.sub(air_clean_compile, '', text, flags=re.IGNORECASE).strip()
            if not city:  # 如果只是输入城市名
                # 从缓存数据库找最后一次查询的城市名
                city = find_user_city(ated_uuid)
            if not city:  # 缓存数据库没有保存,通过用户的资料查城市
                city = get_city_by_uuid(ated_uuid)
            if not city:
                retext = air_city_null_msg.format(ated_name=ated_name)
                itchat.send(retext, uuid)
                return

            info = find_air_quality(city)
            if info:
                retext = common_msg.format(ated_name=ated_name, text=info)
                itchat.send(retext, uuid)
                return
            info = get_air_quality(city)
            if info:
                retext = common_msg.format(ated_name=ated_name, text=info)
                itchat.send(retext, uuid)

                udpate_air_quality(city, info)
                data2 = {
                    'userid': ated_uuid,
                    'city_name': city,
                    'last_time': datetime.now()
                }
                udpate_user_city(data2)
                return
            else:
                retext = air_error_msg.format(ated_name=ated_name, city=city)
                itchat.send(retext, uuid)
                return
            return

    # 其他结果都没有匹配到,走自动回复的路
    if conf.get('is_auto_reply'):
        reply_text = get_bot_info(text, ated_uuid)  # 获取自动回复
        if reply_text:  # 如内容不为空,回复消息
            reply_text = common_msg.format(ated_name=ated_name, text=reply_text)
            itchat.send(reply_text, uuid)
            print('回复{}:{}'.format(ated_name, reply_text))
        else:
            print('自动回复失败\n')


# 通过用户id找好友
def get_city_by_uuid(uid):
    """
    通过用户的uid得到用户的城市
    最好是与机器人是好友关系
    """
    itchat.get_friends(update=True)
    info = itchat.search_friends(userName=uid)
    # print('info:'+str(info))
    if not info:
        return None
    city = info.city
    # print('city:'+city)
    return city


================================================
FILE: everyday_wechat/utils/itchat_helper.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-11 14:56
Introduction:
"""

import itchat
import re
from datetime import datetime
from datetime import timedelta
from importlib import import_module
from everyday_wechat.utils import config
from everyday_wechat.utils.common import (
    md5_encode,
    FILEHELPER_MARK,
    FILEHELPER,
)
from everyday_wechat.utils.data_collection import (
    BOT_NAME_DICT
)

__all__ = ['init_wechat_config', 'set_system_notice', 'get_group', 'get_friend']

TIME_COMPILE = re.compile(r'^\s*([01]?[0-9]|2[0-3])\s*[::\-]\s*([0-5]?[0-9])\s*$')


def init_wechat_config():
    """ 初始化微信所需数据 """
    # print('初始化微信所需数据开始..')
    # 从config copy ,用于保存新的接口内容。
    myset = config.copy()
    print('=' * 80)

    base_wechat_info = itchat.search_friends()  # 获取此微信号的基础信息
    wechat_nick_name = base_wechat_info['NickName']  # 获取此微信号的昵称
    wechat_uuid = base_wechat_info['UserName']  # 获取此微信号的uuid
    myset['wechat_nick_name'] = wechat_nick_name
    myset['wechat_uuid'] = wechat_uuid

    # start---------------------------处理自动回复好友---------------------------start
    reply = myset.get('auto_reply_info')
    if reply is not None and reply.get('is_auto_reply'):
        if reply.get('is_auto_reply_all'):
            auto_reply_list_key = 'auto_reply_black_list'
            auto_reply_list_uuid_name = 'auto_reply_black_uuids'
        else:
            auto_reply_list_key = 'auto_reply_white_list'
            auto_reply_list_uuid_name = 'auto_reply_white_uuids'

        auto_reply_uuids_list = []
        for name in reply.get(auto_reply_list_key):
            if not name.strip():
                continue
            if name.lower() in FILEHELPER_MARK:  # 判断是否文件传输助手
                auto_reply_uuids_list.append(FILEHELPER)
                continue
            friend = get_friend(name)
            if friend:
                auto_reply_uuids_list.append(friend['UserName'])
            else:
                print('自动回复中的好友昵称『{}』有误。'.format(name))
        reply[auto_reply_list_uuid_name] = set(auto_reply_uuids_list)
        # print('已开启图灵自动回复...')

    # end---------------------------处理自动回复好友---------------------------end

    # start ----------------------------------- 群功能初始化 ----------------------------------- start
    helper = myset.get('group_helper_conf')
    if helper is not None and helper.get('is_open'):
        if helper.get('is_all', False):
            group_list_key = 'group_name_black_list'
            group_list_uuid_name = 'group_black_uuids'
        else:
            group_list_key = 'group_name_white_list'
            group_list_uuid_name = 'group_white_uuids'
        group_uuid_list = []
        for name in helper.get(group_list_key):
            if not name.strip():
                continue
            group = get_group(name)
            if group:
                group_uuid_list.append(group['UserName'])
            else:
                print('群助手中的群聊名称『{}』有误。'
                      '(注意:必须要把需要的群聊保存到通讯录)'.format(name))
        helper[group_list_uuid_name] = set(group_uuid_list)
    #   end ----------------------------------- 群功能初始化 ----------------------------------- end

    alarm = myset.get('alarm_info')
    alarm_dict = {}
    if alarm is not None and alarm.get('is_alarm'):
        for gi in alarm.get('girlfriend_infos'):
            ats = gi.get('alarm_timed')
            if not ats:
                continue
            uuid_list = []
            nickname_list = []
            # start---------------------------处理好友---------------------------start
            friends = gi.get('wechat_name')
            if isinstance(friends, str):
                friends = [friends]
            if isinstance(friends, list):
                for name in friends:
                    if name.lower() in FILEHELPER_MARK:  # 判断是否文件传输助手
                        uuid_list.append(FILEHELPER)
                        nickname_list.append(name)
                        continue
                    name_info = get_friend(name)
                    if not name_info:
                        print('定时提醒中的好友昵称『{}』无效'.format(name))
                    else:
                        uuid_list.append(name_info['UserName'])
                        nickname_list.append(name)
            # end---------------------------处理好友---------------------------end

            # start---------------------------群组处理---------------------------start
            group_names = gi.get('group_name')
            if isinstance(group_names, str):
                group_names = [group_names]
            if isinstance(group_names, list):
                for name in group_names:
                    name_info = get_group(name)
                    if not name_info:
                        print('定时任务中的群聊名称『{}』有误。'
                              '(注意:必须要把需要的群聊保存到通讯录)'.format(name))
                    else:
                        uuid_list.append(name_info['UserName'])
                        nickname_list.append(name)
            # end---------------------------群组处理---------------------------end

            # start---------------------------定时处理---------------------------start

            if isinstance(ats, str):
                ats = [ats]
            if isinstance(ats, list):
                for at in ats:
                    times = TIME_COMPILE.findall(at)
                    if not times:
                        print('时间{}格式出错'.format(at))
                        continue
                    hour, minute = int(times[0][0]), int(times[0][1])
                    temp_dict = {'hour': hour, 'minute': minute, 'uuid_list': uuid_list, 'nickname_list': nickname_list}
                    temp_dict.update(gi)
                    alarm_dict[md5_encode(str(temp_dict))] = temp_dict
        #   end---------------------------定时处理---------------------------end
        alarm['alarm_dict'] = alarm_dict

    # 将解析的数据保存于 config 中。
    config.update(myset)
    # print(json.dumps(alarm_dict, ensure_ascii=False))
    # print('初始化微信所需数据结束..')

    log_all_config()


def set_system_notice(text):
    """
    给文件传输助手发送系统日志。
    :param text:str 日志内容
    """
    if text:
        text = '系统通知:' + text
        itchat.send(text, toUserName=FILEHELPER)


def get_group(group_name, update=False):
    """
    根据群组名获取群组数据
    :param group_name:str, 群组名
    :param update: bool 强制更新群组数据
    :return: obj 单个群组信息
    """
    if update: itchat.get_chatrooms(update=True)
    if not group_name: return None
    groups = itchat.search_chatrooms(name=group_name)
    if not groups: return None
    return groups[0]


def get_friend(wechat_name, update=False):
    """
    根据用户名获取用户数据
    :param wechat_name: str 用户名
    :param update: bool 强制更新用户数据
    :return: obj 单个好友信息
    """
    if update: itchat.get_friends(update=True)
    if not wechat_name: return None
    friends = itchat.search_friends(name=wechat_name)
    if not friends: return None
    return friends[0]


def get_mps(mp_name, update=False):
    """
    根据公众号的名称获取用户数据
    :param mp_name: str 用户名
    :param update: bool 强制更新用户数据
    :return: obj 单个公众号信息
    """
    if update: itchat.get_mps(update=True)
    if not mp_name: return None
    mps = itchat.search_mps(name=mp_name)
    if not mps: return None
    # mpuuid = mps[0]['UserName'] 公众号的uuid
    return mps[0]


# import pysnooper
# @pysnooper.snoop()
def log_all_config():
    """
    用于打印设置日志
    :return:
    """
    print('=' * 80)
    channel = config.get('auto_reply_info').get('bot_channel', 7)
    source = BOT_NAME_DICT.get(channel, 'ownthink_robot')
    addon = import_module('everyday_wechat.control.bot.' + source, __package__)
    bot_name = addon.BOT_NAME
    print('自动回复机器人渠道:{}'.format(bot_name))

    # start ----------------------------------- 微信好友自动回复的功能日志 ----------------------------------- start
    reply = config.get('auto_reply_info', None)
    if not reply or not reply.get('is_auto_reply'):
        print('未开启微信好友自动回复。')
    else:
        if reply.get('is_auto_reply_all'):
            auto_uuids = reply.get('auto_reply_black_uuids')
            nicknames = []
            for auid in auto_uuids:
                if auid == 'filehelper':
                    nicknames.append(auid)
                else:
                    friends = itchat.search_friends(userName=auid)
                    nickname = friends.nickName
                    nicknames.append(nickname)
            nns = ','.join(nicknames)
            print('开启对全部微信好友全部回复,除了:{}'.format(nns))
        else:
            auto_uuids = reply.get('auto_reply_white_uuids')
            nicknames = []
            for auid in auto_uuids:
                if auid == 'filehelper':
                    nicknames.append(auid)
                else:
                    friends = itchat.search_friends(userName=auid)
                    nickname = friends.nickName
                    nicknames.append(nickname)
            nns = ','.join(nicknames)
            print('对微信好友 {},进行自动回复'.format(nns))

    print('=' * 80)

    # start ----------------------------------- 群功能日志说明 ----------------------------------- start
    helper = config.get('group_helper_conf')
    if not helper or not helper.get('is_open'):
        print('未开启群助手功能。')
    else:
        if helper.get('is_all'):
            auto_uuids = helper.get('group_black_uuids')
            nicknames = []
            for auid in auto_uuids:
                chatrooms = itchat.search_chatrooms(userName=auid)
                nickname = chatrooms['NickName']  # 群聊名称
                nicknames.append(nickname)
            nns = ','.join(nicknames)
            print('已开启对全部微信群的监听,除了群:{}。'.format(nns))
        else:
            auto_uuids = helper.get('group_white_uuids')
            nicknames = []
            for auid in auto_uuids:
                chatroom = itchat.search_chatrooms(userName=auid)
                nickname = chatroom['NickName']  # 群聊名称
                nicknames.append(nickname)
            nns = ','.join(nicknames)

            print('已对微信群:{},开启了群助手功能。'.format(nns))

            if helper.get('is_at'):
                print('只有群里用户@机器人,才会触发群助手功能。')
            if helper.get('is_auto_reply'):
                print('已开启对微信群内用户的自动回复。')
            if helper.get('is_weather'):
                print('已开启天气查询功能,具体使用方法请输入:“help” 查看。')
            if helper.get('is_calendar'):
                print('已开启日志查询功能,具体使用方法请输入:“help” 查看。')
            if helper.get('is_rubbish'):
                print('已开启垃圾分类查询功能,具体使用方法请输入:“help” 查看。')
            if helper.get('is_moviebox'):
                print('已开启票房查询功能,具体使用方法请输入:“help” 查看。')
            if helper.get('is_air_quality'):
                print('已开启空气质量查询功能,具体使用方法请输入:“help” 查看。')

    print('=' * 80)

    # start ----------------------------------- 提醒功能的日志说明 ----------------------------------- start
    alarm = config.get('alarm_info')
    if not alarm or not alarm.get('is_alarm'):
        print('未开启每日提醒功能。')
    else:
        print('已开启定时发送提醒功能。')
        alarm_dict = alarm.get('alarm_dict')
        for value in alarm_dict.values():
            nickname_list = value.get('nickname_list')
            nns = ','.join(nickname_list)
            # temp_dict = {'hour': hour, 'minute': minute, 'uuid_list': uuid_list, 'nickname_list': nickname_list}
            hour = value.get('hour')
            minute = value.get('minute')
            alarm_time = "{hour:0>2d}:{minute:0>2d}".format(hour=hour, minute=minute)

            # 计算在哪个区间给朋友发送信息
            jitter = value.get("alarm_jitter", 0)
            if jitter != 0:
                set_time = datetime.strptime(alarm_time, '%H:%M')
                jitter_time = timedelta(seconds=jitter)
                start_time = (set_time - jitter_time).strftime("%H:%M")
                end_time = (set_time + jitter_time).strftime("%H:%M")
                alarm_time = "{start_time}——{end_time} 期间".format(start_time=start_time, end_time=end_time)

            print('定时:{alarm_time},给:{nicknames},发送提醒内容一次。'.format(alarm_time=alarm_time, nicknames=nns))

    print('=' * 80)


================================================
FILE: history.md
================================================
2019年11月14日

    vesion: 0.3.27
    定时时间加了一个随时抖动。可以不再是固定时间内发送了

2019年10月1日

    vesion: 0.3.26
    新添加一个群助手功能:空气质量PM2.5查询
    也可以添加到每日提醒中。

2019年9月5日

    vesion: 0.3.20
    新添加一个群助手功能:快递物流信息查询

2019年8月27日

    vesion: 0.3.10
    新添加一个群助手功能:实时票房查询

2019年8月27日

    vesion: 0.3.07
    1.添加了一个新的机器人渠道:思知机器人

2019年8月14日 

    1. 更新天气更新不及时的 Bug。

2019年7月13日 

    1. 天气预报、星座运势、日历的提醒可以用明日。
    2. 自动回复可以回复所有人,添加不受影响的『白名单』。
    3. 新功能:群助手,可自动回复成员,查询天气,日历。
    4. 添加了 mongodb 数据库做缓存处理。

2019年7月2日 

    新添三个机器人渠道:「智能闲聊」、「天行机器人」 「海知智能机器人」

2019年6月30日  

    新添每日一言渠道:彩虹屁

2019年6月29日  

    1.新添内容:万年历。
    2.『在一起』文案可自定义。
    3.可添加多个定时提醒。
    4.更新非 windows 平台登录出现的 Bug.
    5.星座运势可直接填具体星座
    
2019年6月24日  

    重构代码结构。

2019年6月20日 

    新添内容:星座运势

2019年6月19日 

    新添每日一言渠道:民国情书

2019年6月16日 

    新添机器人渠道:一个 AI

2019年6月15日 

    1.好友可选『文件传输助手』
    2.定时发送消息可支持群聊组。
    
2019年6月15日 

    代码重构    

2019年6月12日 

    添加图灵机器人

更早,不知道了。

================================================
FILE: requirements.txt
================================================
itchat==1.3.10
requests
beautifulsoup4
apscheduler
pymongo
pyyaml
lxml

================================================
FILE: run.py
================================================
# coding=utf-8
"""
程序运行入口
"""

import sys
import re
from datetime import datetime

try:
    from everyday_wechat import __version__

    print('EverydayWechat 程序版本号:{}'.format(__version__))
    _date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print('当前时间:{}'.format(_date))
except Exception as exception:
    print(str(exception))
    print('请将脚本放在项目根目录中运行')
    print('请检查项目根目录中的 everyday_wechat 文件夹是否存在')
    exit(1)


def run():
    """ 主程序入口"""

    # 判断当前环境是否为 python 3
    if sys.version_info[0] == 2:
        print('此项目不支持 Python 2 版本!')
        return

    # 检查依赖库是否都已经安装上
    try:
        import itchat
        import apscheduler
        import requests
        from bs4 import BeautifulSoup
        if itchat.__version__ != '1.3.10':
            print('当前 itchat 版本为:{} ,本项目需要 itchat 的版本为 1.3.10。请升级至最新版本!\n'
                  '升级方法 1:pip install itchat --upgrade \n'
                  '或者方法 2: pip install -U itchat'.format(itchat.__version__))
            return

    except (ModuleNotFoundError, ImportError) as error:
        if isinstance(error, ModuleNotFoundError):
            no_modules = re.findall(r"named '(.*?)'$", str(error))
            if no_modules:
                print('当前运行环境缺少 {} 库'.format(no_modules[0]))
            print(str(error))
        elif isinstance(error, ImportError):
            print('当前运行环境引入库出错')
            print(str(error))
        return

    # 用于判断数据库功能是否开启
    try:
        from everyday_wechat.utils import config
        from everyday_wechat.utils.db_helper import is_open_db
        if not is_open_db:
            print('数据库未开启或启动失败!但数据库功能不会影响项目正常运行,主要用于群助手查询数据缓存。')
    except Exception as exception:
        print(str(exception))
        return

    print('所有环境配置 OK ..')
    from everyday_wechat import main
    main.run()


if __name__ == '__main__':
    run()

================================================
FILE: tests/__init__.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2019/6/23
# Author: snow


import os
from unittest import TestCase
from everyday_wechat.utils import config

here_dir = os.path.dirname(__file__)

class BaseTestCase(TestCase):
    def setUp(self):
        # config.init()
        pass

================================================
FILE: tests/test_01.py
================================================
#! usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2019/6/23
# Author: snow

import os



================================================
FILE: tests/test_alarm/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-11 12:01
Introduction:
"""




================================================
FILE: tests/test_alarm/_trial_temp/_trial_marker
================================================


================================================
FILE: tests/test_alarm/_trial_temp/test.log
================================================
2019-07-16 16:33:53+0800 [-] Log opened.


================================================
FILE: tests/test_alarm/_trial_temp-1/_trial_marker
================================================


================================================
FILE: tests/test_alarm/_trial_temp-1/test.log
================================================
2019-11-14 12:15:48+0800 [-] Log opened.


================================================
FILE: tests/test_alarm/test_info.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-11 12:03
Introduction:
"""
from tests import BaseTestCase
from everyday_wechat.utils import config
from everyday_wechat.utils.data_collection import *
from everyday_wechat.control.airquality.air_quality_aqicn import (
    get_air_quality
)

class TestJobModel(BaseTestCase):
    def test_all_info(self):
        """
        测试获取提醒的所有信息。
        :return:
        """
        girlfriend_infos = config.get('alarm_info').get('girlfriend_infos')
        for gf in girlfriend_infos:
            is_tomorrow = gf.get('is_tomorrow', False)
            calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow)
            weather = get_weather_info(gf.get('city_name'), is_tomorrow)
            horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow)
            dictum = get_dictum_info(gf.get('dictum_channel'))
            diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg'))
            air_quality = get_air_quality(gf.get('air_quality_city'))

            sweet_words = gf.get('sweet_words')
            send_msg = '\n'.join(
                x for x in [calendar_info, weather, air_quality, horoscope, dictum, diff_time, sweet_words] if x)
            print(send_msg)
            print('\n' + '-' * 50 + '\n')


================================================
FILE: tests/test_config/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-10-01 00:52
Introduction:
"""




================================================
FILE: tests/test_control/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-14 01:06
Introduction:
"""




================================================
FILE: tests/test_control/_trial_temp/_trial_marker
================================================


================================================
FILE: tests/test_control/_trial_temp/test.log
================================================
2019-08-27 13:27:03+0800 [-] Log opened.


================================================
FILE: tests/test_control/test_one_words.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-18 14:07
Introduction:
"""
from unittest import TestCase
import importlib
import path
import os

from everyday_wechat.control.onewords.wufazhuce import get_wufazhuce_info


class BaseTestCase(TestCase):
    def test_get_wufazhuce_(self):
        ok = get_wufazhuce_info()
        print(ok)

    def test_bot_name(self):
        _path = os.path.dirname(__file__)
        print(_path)
        source = 'ownthink_robot'

        addon = importlib.import_module('everyday_wechat.control.bot.' + source, __package__)
        name = addon.BOT_NAME
        print(name)

        loth = importlib.util.find_spec('everyday_wechat.control.bot')
        print(loth)

================================================
FILE: tests/test_control/test_rubbish.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-14 01:06
Introduction:
"""
from unittest import TestCase

from everyday_wechat.control.rubbish.atoolbox_rubbish import get_atoolbox_rubbish

class BaseTestCase(TestCase):
    def test_atoolbox_rubbish(self):
        key = '牛'
        ok = get_atoolbox_rubbish(key)
        print(ok)


================================================
FILE: tests/test_db/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-12 19:09
Introduction:
"""




================================================
FILE: tests/test_db/_trial_temp/_trial_marker
================================================


================================================
FILE: tests/test_db/_trial_temp/test.log
================================================
2019-10-01 00:18:51+0800 [-] Log opened.


================================================
FILE: tests/test_db/test_air.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019年9月4日12:41:33
Introduction:
"""

from tests import BaseTestCase

from everyday_wechat.utils.db_helper import *
from everyday_wechat.control.airquality.air_quality_aqicn import get_air_quality
import pysnooper


class TestDbAirModel(BaseTestCase):

    def test_db_get_data(self):

        city = '天津'
        cc = get_air_quality(city)
        if cc:
            print(cc)
            # print(cc['info'])

    def test_db_get_and_save_data(self):

        city = '天津'
        info = get_air_quality(city)
        if info:
            udpate_air_quality(city, info)

    def test_db_find_data(self):
        # uid = '05150520'
        city = '天津'

        # code = ''
        info = find_air_quality(city)
        if info:
            print(info)

    @pysnooper.snoop()
    def test_all_data(self):
        city = '宁波'
        info = find_air_quality(city)
        if info:
            print(info)
            return

        info = get_air_quality(city)
        if info:
            print(info)
            udpate_air_quality(city, info)


================================================
FILE: tests/test_db/test_db.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-12 19:15
Introduction:
"""

from tests import BaseTestCase
# from everyday_wechat.utils import config
from everyday_wechat.utils.db_helper import *
from everyday_wechat.control.moviebox.maoyan_movie_box import get_maoyan_movie_box
from datetime import datetime
from datetime import timedelta


class TestDbModel(BaseTestCase):

    def test_db_get_data(self):
        # yy = config.get('db_config')['mongodb_conf']
        # host = yy['host']+'dd'
        # port = yy['port']
        # hello = 'mongodb://{host}:{port}/'.format(host=host,port=port)
        #
        # myclient = pymongo.MongoClient(host=host,port=port)
        # dblist = myclient.list_database_names()
        # for db in dblist:
        #     print(db)
        # print('8' * 10, db_helper.is_open_db)
        uuid = '11'
        find_user_city(uuid)

    def test_db_movie(self):
        date_ = datetime.now().strftime('%Y%m%d')

        info = find_movie_box(date_)
        if info:
            print('数据库缓存')
            print(info)
        else:
            mb = get_maoyan_movie_box(date_)
            update_movie_box(date_, mb, is_expired=False)

    def test_db_yesterday_movice(self):
        date_ = (datetime.now() + timedelta(days=-1)).strftime('%Y%m%d')
        print(date_)


================================================
FILE: tests/test_db/test_express.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019年9月4日12:41:33
Introduction:
"""

from tests import BaseTestCase
# from everyday_wechat.utils import config
from everyday_wechat.utils.db_helper import *
from everyday_wechat.control.moviebox.maoyan_movie_box import get_maoyan_movie_box
from datetime import datetime
from datetime import timedelta
from everyday_wechat.control.express.kdniao_express import get_express_info
import pysnooper


class TestDbExpressModel(BaseTestCase):

    def test_db_get_data(self):

        code = '78109182715352'
        cc = get_express_info(code)
        if cc:
            print(cc)
            print(cc['info'])

    def test_db_get_and_save_data(self):
        uid = '05150520'
        code = '78109182715352'
        cc = get_express_info(code)
        if cc:
            update_express(cc, uid)
            print('保存数据')

    def test_db_find_data(self):
        # uid = '05150520'
        uid = ''
        code = '78109182715352'
        # code = ''
        info = find_express(code, uid)
        if info:
            print(info)

    @pysnooper.snoop()
    def test_all_data(self):
        uid = '05150520'
        code = '78109182715352'
        # code = '102276593571'
        # code = 'JD0001855864185'
        db_data = find_express(code, uid)
        shipper_code, shipper_name = '', ''
        if db_data:
            if not db_data['is_forced_update']:
                print(db_data['info'])
                return
            shipper_code = db_data['shipper_code']
            shipper_name = db_data['shipper_name']

        data = get_express_info(
            code,
            shipper_name=shipper_name,
            shipper_code=shipper_code)
        if data:
            print(data['info'])
            update_express(data, uid)
            return
        else:
            print('未查询到此订单号或者快递物流轨迹')
            return


================================================
FILE: tests/test_email_alarm/__init__.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-10-13 13:16
Introduction:
"""




================================================
FILE: tests/test_email_alarm/test_email.py
================================================
# -*- coding: utf-8 -*-
"""
Project: EverydayWechat-Github
Creator: DoubleThunder
Create time: 2019-07-11 12:03
Introduction:
"""
from tests import BaseTestCase
from everyday_wechat.utils import config
from everyday_wechat.utils.data_collection import *
from wechat_notice import EmailNotice
from everyday_wechat.control.airquality.air_quality_aqicn import (
    get_air_quality
)


class TestEmailModel(BaseTestCase):
    def test_all_info(self):
        """
        测试获取提醒的所有信息。
        :return:
        """
        girlfriend_infos = config.get('alarm_info').get('girlfriend_infos')
        for gf in girlfriend_infos:
            is_tomorrow = gf.get('is_tomorrow', False)
            calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow)
            weather = get_weather_info(gf.get('city_name'), is_tomorrow)
            horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow)
            dictum = get_dictum_info(gf.get('dictum_channel'))
            diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg'))
            sweet_words = gf.get('sweet_words')

            air_quality = get_air_quality(gf.get('air_quality_city'))

            send_msg = '\n'.join(
                x for x in [calendar_info, weather, horoscope, air_quality, dictum, diff_time, sweet_words] if x)
            print(send_msg)
            print('\n' + '-' * 50 + '\n')

    """
    other_alarm_conf:
      email_config:
        user: 'sfyc1314@163.com'
        password: 'pvQ8sgyCRTyq'
        host: 'smtp.163.com'
    """

    def test_send_email(self):
        ac = config.get('other_alarm_conf', None)
        # if ac:
        email_config = ac.get('email_config', None)
        user = email_config.get('user', None)
        password = email_config.get('password', None)
        host = email_config.get('host', None)
        email_notice = EmailNotice(user=user, password=password, host=host)

        # yy = email_notice.send('title', 'hello world', receivers='sfyc23@qq.com')
        # print(yy)

        girlfriend_infos = config.get('alarm_info').get('girlfriend_infos')
        for gf in girlfriend_infos[:1]:
            is_tomorrow = gf.get('is_tomorrow', False)
            calendar_info = get_calendar_info(gf.get('calendar'), is_tomorrow)
            weather = get_weather_info(gf.get('city_name'), is_tomorrow)
            horoscope = get_constellation_info(gf.get("horescope"), is_tomorrow)
            dictum = get_dictum_info(gf.get('dictum_channel'))
            diff_time = get_diff_time(gf.get('start_date'), gf.get('start_date_msg'))
            sweet_words = gf.get('sweet_words')
            send_msg = '\n'.join(x for x in [calendar_info, weather, horoscope, dictum, diff_time, sweet_words] if x)
            print(send_msg)
            print('\n' + '-' * 50 + '\n')
            # email_notice.send('title', send_msg, receivers='sfyc23@qq.com')

    def test_moviebox(self):
        pass
Download .txt
gitextract_2kqk_pde/

├── .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/
    │   │   ├── _trial_marker
    │   │   └── test.log
    │   ├── _trial_temp-1/
    │   │   ├── _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
Download .txt
SYMBOL INDEX (104 symbols across 40 files)

FILE: everyday_wechat/control/airquality/air_quality_aqicn.py
  function get_air_quality (line 26) | def get_air_quality(city):

FILE: everyday_wechat/control/bot/ownthink_robot.py
  function get_ownthink_robot (line 20) | def get_ownthink_robot(text, userid):

FILE: everyday_wechat/control/bot/qingyunke.py
  function get_qingyunke (line 17) | def get_qingyunke(text, userid=''):

FILE: everyday_wechat/control/bot/qq_nlpchat.py
  function get_nlp_textchat (line 29) | def get_nlp_textchat(text, userId):
  function getReqSign (line 74) | def getReqSign(parser, app_key):

FILE: everyday_wechat/control/bot/ruyiai.py
  function get_ruyiai_bot (line 21) | def get_ruyiai_bot(text, userId):

FILE: everyday_wechat/control/bot/tian_robot.py
  function get_tianapi_robot (line 19) | def get_tianapi_robot(text, userid):

FILE: everyday_wechat/control/bot/tuling123.py
  function get_tuling123 (line 29) | def get_tuling123(text, userId):

FILE: everyday_wechat/control/bot/yigeai.py
  function get_yigeai (line 22) | def get_yigeai(text, userid):

FILE: everyday_wechat/control/calendar/rt_calendar.py
  function get_rtcalendar (line 29) | def get_rtcalendar(date=''):

FILE: everyday_wechat/control/calendar/sojson_calendar.py
  function get_sojson_calendar (line 16) | def get_sojson_calendar(date=''):

FILE: everyday_wechat/control/express/kdniao_express.py
  function encrypt (line 28) | def encrypt(origin_data, app_key):
  function get_company_info (line 40) | def get_company_info(express_code, app_id, app_key):
  function get_logistic_info (line 84) | def get_logistic_info(logistic_code, shipper_code, app_id, app_key):
  function get_express_info (line 120) | def get_express_info(express_code, shipper_code='', shipper_name=''):

FILE: everyday_wechat/control/horoscope/xzw_horescope.py
  function get_xzw_horoscope (line 33) | def get_xzw_horoscope(name, is_tomorrow=False):

FILE: everyday_wechat/control/moviebox/maoyan_movie_box.py
  function get_maoyan_movie_box (line 16) | def get_maoyan_movie_box(date='', is_expired=False):

FILE: everyday_wechat/control/onewords/acib.py
  function get_acib_info (line 15) | def get_acib_info():

FILE: everyday_wechat/control/onewords/caihongpi.py
  function get_caihongpi_info (line 11) | def get_caihongpi_info():

FILE: everyday_wechat/control/onewords/hitokoto.py
  function get_hitokoto_info (line 11) | def get_hitokoto_info():

FILE: everyday_wechat/control/onewords/juzimi.py
  function get_zsh_info (line 14) | def get_zsh_info():

FILE: everyday_wechat/control/onewords/lovelive.py
  function get_lovelive_info (line 10) | def get_lovelive_info():

FILE: everyday_wechat/control/onewords/rtjokes.py
  function get_rtjokes_info (line 11) | def get_rtjokes_info():

FILE: everyday_wechat/control/onewords/wufazhuce.py
  function get_wufazhuce_info (line 12) | def get_wufazhuce_info():

FILE: everyday_wechat/control/rubbish/atoolbox_rubbish.py
  function get_atoolbox_rubbish (line 15) | def get_atoolbox_rubbish(key):

FILE: everyday_wechat/control/weather/rtweather.py
  function get_rttodayweather (line 15) | def get_rttodayweather(cityname):

FILE: everyday_wechat/control/weather/sojson.py
  function get_sojson_weather (line 18) | def get_sojson_weather(city_name, is_tomorrow=False):
  function get_sojson_weather_tomorrow (line 84) | def get_sojson_weather_tomorrow(city_name):

FILE: everyday_wechat/main.py
  function run (line 44) | def run():
  function is_online (line 53) | def is_online(auto_login=False):
  function delete_cache (line 107) | def delete_cache():
  function init_data (line 115) | def init_data():
  function init_alarm (line 131) | def init_alarm(alarm_dict):
  function send_alarm_msg (line 147) | def send_alarm_msg(key):
  function text_reply (line 176) | def text_reply(msg):
  function text_group (line 186) | def text_group(msg):
  function exit_msg (line 191) | def exit_msg():

FILE: everyday_wechat/utils/common.py
  function is_json (line 51) | def is_json(resp):
  function md5_encode (line 65) | def md5_encode(text):
  function get_constellation_name (line 75) | def get_constellation_name(date):

FILE: everyday_wechat/utils/config.py
  function get_yaml (line 24) | def get_yaml():
  function set (line 43) | def set(key, value):
  function get (line 48) | def get(key, default=None):
  function copy (line 53) | def copy():
  function update (line 58) | def update(new_opts):
  function _print (line 63) | def _print():

FILE: everyday_wechat/utils/data_collection.py
  function get_dictum_info (line 38) | def get_dictum_info(channel):
  function get_weather_info (line 54) | def get_weather_info(cityname, is_tomorrow=False):
  function get_bot_info (line 66) | def get_bot_info(message, userId=''):
  function get_diff_time (line 90) | def get_diff_time(start_date, start_msg=''):
  function get_constellation_info (line 112) | def get_constellation_info(birthday_str, is_tomorrow=False):
  function get_calendar_info (line 127) | def get_calendar_info(calendar=True, is_tomorrow=False, _date=''):

FILE: everyday_wechat/utils/db_helper.py
  function db_flag (line 50) | def db_flag():
  function udpate_weather (line 67) | def udpate_weather(data):
  function udpate_user_city (line 77) | def udpate_user_city(data):
  function find_user_city (line 87) | def find_user_city(uuid):
  function find_weather (line 100) | def find_weather(date, cityname):
  function update_perpetual_calendar (line 117) | def update_perpetual_calendar(_date, info):
  function find_perpetual_calendar (line 134) | def find_perpetual_calendar(_date):
  function find_rubbish (line 147) | def find_rubbish(name):
  function update_rubbish (line 162) | def update_rubbish(data):
  function find_movie_box (line 178) | def find_movie_box(date):
  function update_movie_box (line 200) | def update_movie_box(date, info, is_expired=False):
  function update_express (line 219) | def update_express(data, uuid):
  function find_express (line 236) | def find_express(express_code='', uuid=''):
  function find_air_quality (line 266) | def find_air_quality(city):
  function udpate_air_quality (line 281) | def udpate_air_quality(city, info):

FILE: everyday_wechat/utils/friend_helper.py
  function handle_friend (line 23) | def handle_friend(msg):

FILE: everyday_wechat/utils/group_helper.py
  function handle_group_helper (line 100) | def handle_group_helper(msg):
  function get_city_by_uuid (line 386) | def get_city_by_uuid(uid):

FILE: everyday_wechat/utils/itchat_helper.py
  function init_wechat_config (line 29) | def init_wechat_config():
  function set_system_notice (line 158) | def set_system_notice(text):
  function get_group (line 168) | def get_group(group_name, update=False):
  function get_friend (line 182) | def get_friend(wechat_name, update=False):
  function get_mps (line 196) | def get_mps(mp_name, update=False):
  function log_all_config (line 213) | def log_all_config():

FILE: run.py
  function run (line 23) | def run():

FILE: tests/__init__.py
  class BaseTestCase (line 13) | class BaseTestCase(TestCase):
    method setUp (line 14) | def setUp(self):

FILE: tests/test_alarm/test_info.py
  class TestJobModel (line 15) | class TestJobModel(BaseTestCase):
    method test_all_info (line 16) | def test_all_info(self):

FILE: tests/test_control/test_one_words.py
  class BaseTestCase (line 16) | class BaseTestCase(TestCase):
    method test_get_wufazhuce_ (line 17) | def test_get_wufazhuce_(self):
    method test_bot_name (line 21) | def test_bot_name(self):

FILE: tests/test_control/test_rubbish.py
  class BaseTestCase (line 12) | class BaseTestCase(TestCase):
    method test_atoolbox_rubbish (line 13) | def test_atoolbox_rubbish(self):

FILE: tests/test_db/test_air.py
  class TestDbAirModel (line 16) | class TestDbAirModel(BaseTestCase):
    method test_db_get_data (line 18) | def test_db_get_data(self):
    method test_db_get_and_save_data (line 26) | def test_db_get_and_save_data(self):
    method test_db_find_data (line 33) | def test_db_find_data(self):
    method test_all_data (line 43) | def test_all_data(self):

FILE: tests/test_db/test_db.py
  class TestDbModel (line 17) | class TestDbModel(BaseTestCase):
    method test_db_get_data (line 19) | def test_db_get_data(self):
    method test_db_movie (line 33) | def test_db_movie(self):
    method test_db_yesterday_movice (line 44) | def test_db_yesterday_movice(self):

FILE: tests/test_db/test_express.py
  class TestDbExpressModel (line 19) | class TestDbExpressModel(BaseTestCase):
    method test_db_get_data (line 21) | def test_db_get_data(self):
    method test_db_get_and_save_data (line 29) | def test_db_get_and_save_data(self):
    method test_db_find_data (line 37) | def test_db_find_data(self):
    method test_all_data (line 47) | def test_all_data(self):

FILE: tests/test_email_alarm/test_email.py
  class TestEmailModel (line 17) | class TestEmailModel(BaseTestCase):
    method test_all_info (line 18) | def test_all_info(self):
    method test_send_email (line 48) | def test_send_email(self):
    method test_moviebox (line 74) | def test_moviebox(self):
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (206K chars).
[
  {
    "path": ".dockerignore",
    "chars": 80,
    "preview": "# Git\n.git\n.gitignore\n\n# PyCharm\n.idea\n\n# Virtual environment\n.env/\n.venv/\nvenv/"
  },
  {
    "path": ".gitignore",
    "chars": 43,
    "preview": ".idea\n__pycache__\nitchat.pkl\nQR.png\n\nvenv/\n"
  },
  {
    "path": "Dockerfile",
    "chars": 262,
    "preview": "# 说明该镜像以哪个镜像为基础\nFROM python:3.7-slim\n\nRUN mkdir /app\nWORKDIR /app\n\nCOPY requirements.txt requirements.txt\n\nRUN pip insta"
  },
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "MIT License\n\nCopyright (c) 2019  Thunder Bouble\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 11834,
    "preview": "![python_vesion](https://img.shields.io/badge/Python-3.5%2B-green.svg)   [![itchat_vesion](https://img.shields.io/badge/"
  },
  {
    "path": "everyday_wechat/__init__.py",
    "chars": 177,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n# Date: 2019/6/23\n# Author: snow\n\nscript_name = 'EverydayWechat'\n__author_"
  },
  {
    "path": "everyday_wechat/_config.yaml",
    "chars": 4521,
    "preview": "# 配置文件请严格遵循 yaml 语法格式,yaml 学习地址:\n#  https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html\n#  http://einvern"
  },
  {
    "path": "everyday_wechat/control/__init__.py",
    "chars": 79,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n# Date: 2019/6/23\n# Author: snow\n"
  },
  {
    "path": "everyday_wechat/control/airquality/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-09-30 17:56\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/airquality/air_quality_aqicn.py",
    "chars": 1770,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-09-30 17:58\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/bot/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "everyday_wechat/control/bot/ownthink_robot.py",
    "chars": 1850,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-08-27 11:37\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/bot/qingyunke.py",
    "chars": 1114,
    "preview": "# coding=utf-8\n\n\"\"\"\nhttp://api.qingyunke.com/\n青云客智能聊天机器人API\n可直接使用\n\"\"\"\nimport requests\n\n__all__ = ['get_auto_reply', 'BOT"
  },
  {
    "path": "everyday_wechat/control/bot/qq_nlpchat.py",
    "chars": 2977,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: HelloWorldPython\nCreator: DoubleThunder\nCreate time: 2019-07-01 23:49\nIntroduction:"
  },
  {
    "path": "everyday_wechat/control/bot/ruyiai.py",
    "chars": 1771,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: HelloWorldPython\nCreator: DoubleThunder\nCreate time: 2019-07-02 02:46\nIntroduction:"
  },
  {
    "path": "everyday_wechat/control/bot/tian_robot.py",
    "chars": 2138,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-02 01:24\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/bot/tuling123.py",
    "chars": 2074,
    "preview": "# coding=utf-8\n\n'''\n图灵机器人自动回复\n官网:http://www.tuling123.com/\napiKey,userid 需要去官网申请。\n'''\n\nimport requests\nfrom everyday_wec"
  },
  {
    "path": "everyday_wechat/control/bot/yigeai.py",
    "chars": 1772,
    "preview": "#\n\"\"\"\n『一个AI』自动回复 (http://www.yige.ai/)\n\"\"\"\nimport requests\n\nfrom everyday_wechat.utils.common import (\n    is_json,\n    "
  },
  {
    "path": "everyday_wechat/control/calendar/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "everyday_wechat/control/calendar/rt_calendar.py",
    "chars": 2516,
    "preview": "# coding=utf-8\n\"\"\"\nhttps://github.com/MZCretin/RollToolsApi#指定日期的节假日及万年历信息\n指定日期的节假日及万年历信息\n\n{\"code\":1,\"msg\":\"数据返回成功\",\"dat"
  },
  {
    "path": "everyday_wechat/control/calendar/sojson_calendar.py",
    "chars": 2430,
    "preview": "# coding=utf-8\n\"\"\"\nhttps://www.sojson.com/api/lunar.html\n指定日期的节假日及万年历信息\n\"\"\"\nfrom datetime import datetime\nimport request"
  },
  {
    "path": "everyday_wechat/control/express/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-09-04 12:23\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/express/kdniao_express.py",
    "chars": 5589,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-09-04 12:24\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/horoscope/__init__.py",
    "chars": 74,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n\n\"\"\"\n    星座运势,基于 星座屋 爬取\n\"\"\"\n"
  },
  {
    "path": "everyday_wechat/control/horoscope/xzw_horescope.py",
    "chars": 2209,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\n    爬取 星座屋 星座运势\n    https://www.xzw.com/\n\"\"\"\nimport re\nfrom functools "
  },
  {
    "path": "everyday_wechat/control/moviebox/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-08-30 12:21\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/moviebox/maoyan_movie_box.py",
    "chars": 2173,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-08-30 12:22\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/onewords/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "everyday_wechat/control/onewords/acib.py",
    "chars": 724,
    "preview": "# coding=utf-8\n\n\"\"\"\n从词霸中获取每日一句,带英文。\n\"\"\"\n\nimport requests\nfrom everyday_wechat.utils.common import (\n    is_json\n)\n\n__all"
  },
  {
    "path": "everyday_wechat/control/onewords/caihongpi.py",
    "chars": 619,
    "preview": "# coding=utf-8\n\"\"\"\nhttps://chp.shadiao.app/?from_nmsl\n彩虹屁生成器\n \"\"\"\nimport requests\n\n__all__ = ['get_caihongpi_info']\n\n\nde"
  },
  {
    "path": "everyday_wechat/control/onewords/hitokoto.py",
    "chars": 571,
    "preview": "# coding=utf-8\n\"\"\"\n获取一言信息<https://hitokoto.cn/>\n\"\"\"\n\nimport requests\n\n__all__ = ['get_hitokoto_info']\n\n\ndef get_hitokoto"
  },
  {
    "path": "everyday_wechat/control/onewords/juzimi.py",
    "chars": 1439,
    "preview": "# coding=utf-8\n\"\"\"\n句子迷:(https://www.juzimi.com/)\n民国情书:朱生豪先生的情话 && 爱你就像爱生命\nAuthor: ClaireYiu(https://github.com/ClaireYiu"
  },
  {
    "path": "everyday_wechat/control/onewords/lovelive.py",
    "chars": 532,
    "preview": "# coding=utf-8\n\"\"\"\n从土味情话中获取每日一句。\n \"\"\"\nimport requests\n\n__all__ = ['get_lovelive_info']\n\n\ndef get_lovelive_info():\n    \"\""
  },
  {
    "path": "everyday_wechat/control/onewords/rtjokes.py",
    "chars": 958,
    "preview": "# coding=utf-8\n\"\"\"\nhttps://github.com/MZCretin/RollToolsApi#随机获取笑话段子列表\n随机获取笑话段子列表\n\"\"\"\nimport requests\n\n__all__ = ['get_r"
  },
  {
    "path": "everyday_wechat/control/onewords/wufazhuce.py",
    "chars": 831,
    "preview": "# coding=utf-8\n\"\"\"\n从「一个」获取每日一言\n\"\"\"\nimport requests\nfrom bs4 import BeautifulSoup\nfrom everyday_wechat.utils.common impor"
  },
  {
    "path": "everyday_wechat/control/rubbish/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-14 01:00\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/rubbish/atoolbox_rubbish.py",
    "chars": 1125,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-14 01:02\nIntroduc"
  },
  {
    "path": "everyday_wechat/control/weather/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "everyday_wechat/control/weather/_city_sojson.json",
    "chars": 57393,
    "preview": "{\n   \"北京\": \"101010100\",\n   \"上海\": \"101020100\",\n   \"天津\": \"101030100\",\n   \"重庆\": \"101040100\",\n   \"香港\": \"101320101\",\n   \"澳门\":"
  },
  {
    "path": "everyday_wechat/control/weather/rtweather.py",
    "chars": 1916,
    "preview": "# coding=utf-8\n\"\"\"\nhttps://github.com/MZCretin/RollToolsApi#获取特定城市今日天气\n获取特定城市今日天气\n\"\"\"\nimport requests\n\n__all__ = ['get_r"
  },
  {
    "path": "everyday_wechat/control/weather/sojson.py",
    "chars": 4995,
    "preview": "# coding=utf-8\n\nimport requests\nimport json\nimport os\nfrom datetime import datetime\nfrom datetime import timedelta\n\n__al"
  },
  {
    "path": "everyday_wechat/main.py",
    "chars": 5392,
    "preview": "# coding=utf-8\n\n\"\"\"\n每天定时给多个女友发给微信暖心话\n核心代码。\n\"\"\"\n\nimport time\n# import json\nimport platform\nimport os\n# from apscheduler.s"
  },
  {
    "path": "everyday_wechat/utils/__init__.py",
    "chars": 81,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n# Date: 2019/6/23\n# Author: snow\n\n\n"
  },
  {
    "path": "everyday_wechat/utils/common.py",
    "chars": 2236,
    "preview": "# coding=utf-8\n\"\"\"\n工具类\n\"\"\"\nimport re\nimport hashlib\nimport json\n\n__all__ = [\n    'FILEHELPER_MARK', 'FILEHELPER', 'SPIDE"
  },
  {
    "path": "everyday_wechat/utils/config.py",
    "chars": 1236,
    "preview": "# coding=utf-8\n\"\"\"\n用于管理缓存的配置数据\n使用前必须先调用 init() 。\n\"\"\"\nimport os\nimport copy as mycopy\nimport yaml\n\n__all__ = ['set', 'get"
  },
  {
    "path": "everyday_wechat/utils/data_collection.py",
    "chars": 4243,
    "preview": "# coding=utf-8\n\"\"\"\n获取各种请求的调度管理中心\n\"\"\"\nimport importlib\nimport re\nfrom datetime import datetime\nfrom datetime import timed"
  },
  {
    "path": "everyday_wechat/utils/db_helper.py",
    "chars": 7348,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-12 18:37\nIntroduc"
  },
  {
    "path": "everyday_wechat/utils/friend_helper.py",
    "chars": 2053,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-12 23:07\nIntroduc"
  },
  {
    "path": "everyday_wechat/utils/group_helper.py",
    "chars": 13812,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-11 12:55\nIntroduc"
  },
  {
    "path": "everyday_wechat/utils/itchat_helper.py",
    "chars": 12056,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-11 14:56\nIntroduc"
  },
  {
    "path": "history.md",
    "chars": 922,
    "preview": "2019年11月14日\n\n    vesion: 0.3.27\n    定时时间加了一个随时抖动。可以不再是固定时间内发送了\n\n2019年10月1日\n\n    vesion: 0.3.26\n    新添加一个群助手功能:空气质量PM2.5查"
  },
  {
    "path": "requirements.txt",
    "chars": 70,
    "preview": "itchat==1.3.10\nrequests\nbeautifulsoup4\napscheduler\npymongo\npyyaml\nlxml"
  },
  {
    "path": "run.py",
    "chars": 1830,
    "preview": "# coding=utf-8\n\"\"\"\n程序运行入口\n\"\"\"\n\nimport sys\nimport re\nfrom datetime import datetime\n\ntry:\n    from everyday_wechat import "
  },
  {
    "path": "tests/__init__.py",
    "chars": 288,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n# Date: 2019/6/23\n# Author: snow\n\n\nimport os\nfrom unittest import TestCase"
  },
  {
    "path": "tests/test_01.py",
    "chars": 91,
    "preview": "#! usr/bin/env python\n# -*- coding: utf-8 -*-\n# Date: 2019/6/23\n# Author: snow\n\nimport os\n\n"
  },
  {
    "path": "tests/test_alarm/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-11 12:01\nIntroduc"
  },
  {
    "path": "tests/test_alarm/_trial_temp/_trial_marker",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_alarm/_trial_temp/test.log",
    "chars": 41,
    "preview": "2019-07-16 16:33:53+0800 [-] Log opened.\n"
  },
  {
    "path": "tests/test_alarm/_trial_temp-1/_trial_marker",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_alarm/_trial_temp-1/test.log",
    "chars": 41,
    "preview": "2019-11-14 12:15:48+0800 [-] Log opened.\n"
  },
  {
    "path": "tests/test_alarm/test_info.py",
    "chars": 1355,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-11 12:03\nIntroduc"
  },
  {
    "path": "tests/test_config/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-10-01 00:52\nIntroduc"
  },
  {
    "path": "tests/test_control/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-14 01:06\nIntroduc"
  },
  {
    "path": "tests/test_control/_trial_temp/_trial_marker",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_control/_trial_temp/test.log",
    "chars": 41,
    "preview": "2019-08-27 13:27:03+0800 [-] Log opened.\n"
  },
  {
    "path": "tests/test_control/test_one_words.py",
    "chars": 756,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-18 14:07\nIntroduc"
  },
  {
    "path": "tests/test_control/test_rubbish.py",
    "chars": 386,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-14 01:06\nIntroduc"
  },
  {
    "path": "tests/test_db/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-12 19:09\nIntroduc"
  },
  {
    "path": "tests/test_db/_trial_temp/_trial_marker",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_db/_trial_temp/test.log",
    "chars": 41,
    "preview": "2019-10-01 00:18:51+0800 [-] Log opened.\n"
  },
  {
    "path": "tests/test_db/test_air.py",
    "chars": 1138,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019年9月4日12:41:33\nIntrodu"
  },
  {
    "path": "tests/test_db/test_db.py",
    "chars": 1361,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-12 19:15\nIntroduc"
  },
  {
    "path": "tests/test_db/test_express.py",
    "chars": 1924,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019年9月4日12:41:33\nIntrodu"
  },
  {
    "path": "tests/test_email_alarm/__init__.py",
    "chars": 132,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-10-13 13:16\nIntroduc"
  },
  {
    "path": "tests/test_email_alarm/test_email.py",
    "chars": 2939,
    "preview": "# -*- coding: utf-8 -*-\n\"\"\"\nProject: EverydayWechat-Github\nCreator: DoubleThunder\nCreate time: 2019-07-11 12:03\nIntroduc"
  }
]

About this extraction

This page contains the full source code of the sfyc23/EverydayWechat GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (178.2 KB), approximately 67.6k tokens, and a symbol index with 104 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!