├── Images
├── change.png
├── changedetails.png
├── cloud.png
├── reigon.png
└── sex.png
├── README.md
├── activityRate.py
├── analyzeData.py
├── autoDownload.py
├── bot.py
├── getLatestData.py
├── groupBot.py
├── provinceMap.py
├── sex.py
├── signUp.py
├── transfer_single.py
└── wordCloud.py
/Images/change.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenkeyseven/wechatGroupAnalyzer/161159d4c6e32a6f3d25b9152b49749b7f7cfeb0/Images/change.png
--------------------------------------------------------------------------------
/Images/changedetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenkeyseven/wechatGroupAnalyzer/161159d4c6e32a6f3d25b9152b49749b7f7cfeb0/Images/changedetails.png
--------------------------------------------------------------------------------
/Images/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenkeyseven/wechatGroupAnalyzer/161159d4c6e32a6f3d25b9152b49749b7f7cfeb0/Images/cloud.png
--------------------------------------------------------------------------------
/Images/reigon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenkeyseven/wechatGroupAnalyzer/161159d4c6e32a6f3d25b9152b49749b7f7cfeb0/Images/reigon.png
--------------------------------------------------------------------------------
/Images/sex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tenkeyseven/wechatGroupAnalyzer/161159d4c6e32a6f3d25b9152b49749b7f7cfeb0/Images/sex.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 微信群分析器
2 |
3 | `python 3.6` `itchat` `pyecharts` `jieba`
4 |
5 | ## Update
6 | - 「2019/11/6」由于微信网页版登陆出现限制,此项目可能出现**无法登录**问题,相关问题移步 [littlecodersh/ItChat](https://github.com/littlecodersh/ItChat) Issue 区域查看
7 |
8 | ## 实现功能
9 |
10 | ### 1.群聊人员增减分析
11 |
12 | #### 增减数量图
13 |
14 | 
15 |
16 | #### 具体情况输出
17 |
18 |
19 |

20 |
21 |
22 | ### 2.生成群成员三图(地区分布图、签名词云图、性别比例图)
23 |
24 | #### 地区分布图
25 |
26 |
27 |
28 | 
29 |
30 | #### 群成员签名词云图
31 |
32 |
33 |
34 | 
35 |
36 | #### 群成员性别比例图
37 |
38 |
39 |
40 | 
41 |
42 | ## 使用说明
43 |
44 | 基于`python3.6`环境开发,使用了微信端第三方 Api 库`itchat`,echarts 的 python 接口库`pyecharts`, 分词库`jieba`,以及其他一些在程序工作中要用到了编解码、存储等库。
45 |
46 | 安装方法:
47 |
48 | ```
49 | pip install itchat
50 | pip install pyecharts
51 | pip install jieba
52 | ```
53 |
54 | 此分析器包含两个 python 程序,分别为 getLatestData.py 和 analyzeData.py 。
55 |
56 | getLatestData.py 用于对指定的群列表获取最新的群成员信息,并写入文件保存。
57 |
58 | analyzeData.py 用于对指定的群列表进行分析,输出群成员变化细则、群成员人数增减图和三图(群成员分布图、群成员签名云图和群成员性别比例图)
59 |
60 | ### 使用流程
61 |
62 | 1. 在手机上确定要分析的群聊,点开设置,将群聊保存至通讯录(Save to Contacts)。
63 | 2. 运行 getLatestData.py,第一次登陆,会弹出二维码,使用手机扫码登陆微信网页版,并确认,之后登陆只需要在手机确认即可。
64 | 3. 程序将会自动生成文件夹result,并将原始数据保存至此。
65 | 4. 运行 analyzeData.py,程序将会对数据进行分析,输出分许结果以及生成相应的图。
66 |
67 | ### 参数说明
68 |
69 | 在 getLatestData.py 中,参数设置如下
70 |
71 | ```python
72 | #getLatestData.py
73 | if __name__ == '__main__':
74 | '''在GroupList中输入想要分析的群聊名称,输入login的参数
75 | login = 'auto',会调用itchat的自动缓存登陆模式,第二次登陆无需扫码
76 | 适用于持续使用者
77 | logn = 'single',会调用itchat单次扫码登陆模式,适合于一次使用。
78 | '''
79 | GroupList = ['测试','计算机网络2018']
80 | introduce()
81 | init()
82 | mainWork(
83 | GroupList,
84 | login = 'auto'
85 | )
86 | ```
87 |
88 |
89 |
90 | 在 analyzeData.py 中,参数设置应如下
91 |
92 | ```python
93 | #analyzeData.py
94 | if __name__ == '__main__':
95 | '''在GroupList中添加需要分析的群名
96 | 在main函数中相应添加True/False值来确定是否要进行绘制 地理分布图、词云图和性别饼图
97 | 三个值默认都为True
98 | 对群成员的分析默认进行绘图。
99 | '''
100 | GrouppList = ['测试','计算机网络2018']
101 | main(
102 | GrouppList,
103 | Map = True, #True 或 默认 为开启画图,False为不开启
104 | Cloud = True,
105 | Pie = True
106 | )
107 | ```
108 |
109 | ### 其他
110 |
111 | 对群成员人数增减进行分析依赖于多次采集的数据,而绘制三图相对不受人员变化影响,所以可以在第一次三图绘制好之后,将其设置为False,每次分析数据只分析人员变化。
112 |
113 | ### 参考内容
114 |
115 | + [pyecharts](https://github.com/pyecharts/pyecharts)
116 | + [itchat](https://github.com/littlecodersh/ItChat)
117 | + [CSDN:利用itchat接口进行微信好友数据分析](https://blog.csdn.net/alicelmx/article/details/80862340)
118 |
119 | ### 其他内容
120 |
121 | ---
122 |
123 | %E2%9C%A7-green.svg)一些小例子
124 |
125 | #### 1.微信好友的词云图
126 |
127 | **依赖库安装**
128 |
129 | `pip install itchat`
130 |
131 | `pip install pyecharts`
132 |
133 | **运行代码**
134 |
135 | [有注释的代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/wordCloud.py)
136 |
137 |
138 |
139 | #### 2.微信好友性别比
140 |
141 | **依赖库安装**
142 |
143 | `pip install itchat`
144 |
145 | `pip install pyecharts`
146 |
147 | **运行代码**
148 |
149 | [有注释的代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/sex.py)
150 |
151 |
152 |
153 | #### 3.微信好友地区分布图
154 |
155 | **使用**
156 |
157 | 和以上两种一样,运行后会自动在程序根目录生成.html电子图
158 |
159 | **依赖库安装**
160 |
161 | `pip install itchat`
162 |
163 | `pip install pyecharts`
164 |
165 | `pip install echarts-countries-pypkg `(安装必要的地图
166 |
167 | **运行代码**
168 |
169 | [代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/provinceMap.py)
170 |
171 |
172 |
173 |
174 |
175 | #### 4.图灵小机器人私戳版(不是很图灵...)
176 | **依赖库安装**
177 |
178 | `pip install itchat`
179 |
180 | **运行代码**
181 |
182 | [bot.py的代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/bot.py)
183 |
184 |
185 |
186 | #### 5.图灵小机器人群聊版(不是那么图灵+1)
187 |
188 | **使用**
189 |
190 | 运行程序,在群里@机器人并且带消息,然后机器人就会在群里自动回复你了~
191 |
192 | **依赖库安装**
193 |
194 | `pip install itchat`
195 |
196 | **运行代码**
197 |
198 | [群聊版代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/groupBot.py)
199 |
200 |
201 |
202 | #### 6.非常简单的群聊文件自动下载工具
203 |
204 | **使用**
205 |
206 | 运行程序,然后此程序自动下载微信群中别人发的文件。
207 |
208 | **依赖库安装**
209 |
210 | `pip install itchat`
211 |
212 | **运行代码**
213 |
214 | [代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/autoDownload.py)
215 |
216 |
217 |
218 | #### 7.微信消息转发器v1
219 |
220 | **使用**
221 |
222 | 【例】微信转发消息工具,转发指定群个人消息至另外一群
223 |
224 | 例如:
225 |
226 | --在群聊A中,小T发消息:你好
227 |
228 | --在群聊B中有转发消息:及时收到来自群聊【A】,@小T的消息:你好
229 |
230 | 使用:
231 |
232 | --运行本程序即可,关闭退出即可
233 |
234 | 说明:
235 |
236 | --目前仅限于接收和转化文本消息,图片、语音、视频、文件暂时未添加功能。
237 |
238 | **依赖库安装**
239 |
240 | `pip install itchat`
241 |
242 | **运行代码**
243 |
244 | [有注释的代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/transfer_single.py)
245 |
246 |
247 |
248 | #### 8.微信群报名小助手
249 |
250 | **使用**
251 |
252 | 【例子】微信报名签到小工具
253 |
254 | 使用:
255 |
256 | 在微信群中,@<签到管理器>报名,即时返回签到信息
257 |
258 | 例子:
259 |
260 | > 小A:@小T 报名
261 |
262 | > 小T:收到,目前报名人有
263 |
264 | > 1.小A
265 |
266 | **依赖库安装**
267 |
268 | `pip install itchat`
269 |
270 | **运行代码**
271 |
272 | [有注释的代码](https://github.com/tenkeyseven/wechatGroupAnalyzer/blob/master/signUp.py)
273 |
--------------------------------------------------------------------------------
/activityRate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | 【例子】发言热度
6 |
7 | """
8 |
9 | import itchat
10 | from itchat.content import TEXT
11 |
12 | from collections import Counter
13 |
14 | from pyecharts import Bar
15 |
16 | import time
17 |
18 | @itchat.msg_register(TEXT, isGroupChat=True)
19 | def statistics(msg):
20 | if msg['FromUserName'] == groupID:
21 | print('{}发言了:{}'.format(msg['ActualNickName'], msg['Text']))
22 | talkCounter[msg['ActualNickName']] += 1
23 | print(talkCounter)
24 |
25 | if __name__ == '__main__':s
26 | itchat.auto_login(hotReload=True)
27 | groupName = '啊哈'
28 | groupID = itchat.search_chatrooms(name=groupName)[0]['UserName']
29 |
30 | talkCounter = Counter()
31 | beginTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
32 | itchat.run()
33 | endTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
34 |
35 | duration = '统计自 {} 到 {} 时间段内'.format(beginTime, endTime)
36 |
37 | bar = Bar(title='{}群活跃度表'.format(groupName), subtitle=duration, width=1200, height=600, title_pos='left')
38 | attr, value = bar.cast(talkCounter.most_common(100))
39 | bar.add(
40 | '', attr, value,
41 | xaxis_name='昵称',
42 | yaxis_name='发言活跃度',
43 | is_label_show = True,
44 | is_datazoom_show = True,
45 | datazoom_type = 'both',
46 | xaxis_name_pos = 'end'
47 | )
48 | bar.render('./{}发言活跃度.html'.format(groupName))
--------------------------------------------------------------------------------
/analyzeData.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | import codecs
5 | import datetime
6 | import json
7 | from pyecharts import Bar
8 | from collections import Counter
9 | from pyecharts import Bar,Pie,Map,WordCloud
10 | import jieba.analyse
11 | import re
12 | import os
13 |
14 | def getFiles(inputFile):
15 | with codecs.open(inputFile,encoding='utf-8') as f:
16 | friendsList = json.load(f)
17 | return friendsList
18 |
19 | def get_var(var,mlist):
20 | variable = []
21 | for i in mlist:
22 | value = i[var]
23 | variable.append(value)
24 | return variable
25 |
26 | def peopledic(add,quit):
27 | dict_temp = {
28 | 'add' : [],
29 | 'quit' : []
30 | }
31 | dict_temp['add'] = add
32 | dict_temp['quit'] = quit
33 | return dict_temp
34 |
35 | def getSelectedList(mlist,groupName):
36 | selectedList = []
37 | for rawGroup in mlist:
38 | if rawGroup['name'] == groupName:
39 | selectedList.append(rawGroup)
40 | return selectedList
41 |
42 | def getAddQuitList(mlist):
43 | addlist = [[]]
44 | quitlist =[[]]
45 | lens = len(mlist)
46 | for i in range(lens):
47 | addlist.append(mlist[i]['add'])
48 | quitlist.append(mlist[i]['quit'])
49 | return addlist,quitlist
50 |
51 | def getLenofList(addlist,quitlist):
52 | lenaddlist = []
53 | lenquitlist = []
54 |
55 | for i in addlist:
56 | lenaddlist.append(len(i))
57 |
58 | for i in quitlist:
59 | lenquitlist.append(len(i))
60 | return lenaddlist,lenquitlist
61 |
62 | def drawBar(timeList,amountList,markdictList,name):
63 | outputFile='./result/{}_群人员变化表.html'.format(name)
64 | addlist,quitlist = getAddQuitList(markdictList)
65 | lenaddlist,lenquitlist = getLenofList(addlist,quitlist)
66 |
67 | bar = Bar('{} 群人员变化表'.format(name),width = 1200, height = 600, title_pos = 'left')
68 | bar.add(
69 | '群总人数',
70 | timeList,amountList,
71 | tooltip_tragger = 'item',
72 | tooltip_tragger_on ='mousemove|click',
73 | is_label_show = True,
74 | )
75 | bar.add(
76 | '较前一时间入群人数',
77 | timeList,lenaddlist,
78 | is_label_show = True,
79 |
80 | )
81 | bar.add(
82 | '较前一时间退群人数',
83 | timeList,lenquitlist,
84 | xaxis_name = '检测群时间',
85 | yaxis_name = '群人数',
86 | label_color = ['#8A2BE2','#EE2C2C','#7CFC00'],
87 | is_label_show = True,
88 | is_datazoom_show = True,
89 | datazoom_type = 'both',
90 | xaxis_label_textsize = '10',
91 | xaxis_type = 'category'
92 | )
93 |
94 | bar.render(outputFile)
95 |
96 | def analyseProvince(mlist):
97 | '''use this function to get provinceinfo'''
98 | provinceCounter = Counter()
99 | for province in mlist:
100 | if province != '':
101 | provinceCounter[province] += 1
102 | return provinceCounter
103 |
104 | def extractTag(text,tagsList):
105 | if text:
106 | tags = jieba.analyse.extract_tags(text)
107 |
108 | for tag in tags:
109 | tagsList[tag] += 1
110 |
111 | def analyseSignature(mlist):
112 | signatureCounter = Counter()
113 | for signature in mlist:
114 | signature = signature.strip().replace("emoji", "").replace("span", "").replace("class", "")
115 | rec = re.compile("1f\d+\w*|[<>/=]")
116 | signature = rec.sub("", signature)
117 | extractTag(signature,signatureCounter)
118 | return signatureCounter
119 |
120 | def analyseSexInfo(mlist):
121 | '''This function accepet an sex list and return the statistics in tuple'''
122 | male = 0
123 | female = 0
124 | unknownsex = 0
125 | for sex in mlist:
126 | if sex == 1:
127 | male += 1
128 | elif sex == 2:
129 | female += 1
130 | else:
131 | unknownsex += 1
132 | return (male,female,unknownsex)
133 |
134 | def counter2list(_counter):
135 | nameList,countList = [],[]
136 | for counter in _counter:
137 | nameList.append(counter[0])
138 | countList.append(counter[1])
139 | return (nameList,countList)
140 |
141 | def drawMap(name,rank,chatroomname):
142 | outputFile = './result/{}_群成员区域分布图.html'.format(chatroomname)
143 | map = Map(title='{} 群成员区域分布图'.format(chatroomname), width=1200, height=600, title_pos='center')
144 | map.add(
145 | '',name,rank,
146 | maptype = 'china', # 地图范围
147 | is_visualmap = True, # 是否开启鼠标缩放漫游等
148 | is_label_show = True, # 是否显示地图标记
149 | )
150 | map.render(outputFile)
151 |
152 | def drawWorldCloud(name,rank,chatroomname):
153 | outputFile = './result/{}_群成员签名词云图.html'.format(chatroomname)
154 | cloud = WordCloud('{} 群成员签名词云图'.format(chatroomname), width=1200, height=600, title_pos='center')
155 | cloud.add(
156 | ' ',name,rank,
157 | shape='star',
158 | background_color='white',
159 | max_words=200
160 | )
161 | cloud.render(outputFile)
162 |
163 | def drawPie(name,rank,chatroomname):
164 | outputFile = './result/{}_群性别比例图.html'.format(chatroomname)
165 | pie = Pie('{} 群性别比例图'.format(chatroomname), width=1200, height=600, title_pos='center')
166 | pie.add(
167 | '',
168 | name,rank,
169 | is_label_show = True, # 是否显示标签
170 | label_text_color = None, # 标签颜色
171 | legend_orient = 'vertical', # 图例是否垂直
172 | legend_pos = 'left'
173 | )
174 | pie.render(outputFile)
175 |
176 | def analyseGroupByName(selectedList,name):
177 | nickNameListSet = []
178 | remarkNameListSet = []
179 | amountList = []
180 | timeList = []
181 | markdictList = []
182 |
183 | for x in selectedList:
184 | nickNameListSet.append(get_var(var = 'NickName', mlist = x['record']))
185 | remarkNameListSet.append(get_var(var = 'RemarkName', mlist = x['record']))
186 |
187 | lenofSelectedList = len(selectedList) #this is the len of the name corresponding GrouppList
188 |
189 | for x in range(lenofSelectedList):
190 | timeList.append(selectedList[x]['time'])
191 | amountList.append(len(nickNameListSet[x]))
192 |
193 | ''' this loop are use to generate a list containing dictionary of the add/quit info
194 | '''
195 | for i in range(lenofSelectedList-1): # the amount of stored groups' all data block
196 | quitlist = []
197 | addlist =[]
198 | for j in range(amountList[i]):
199 | if nickNameListSet[i][j] in nickNameListSet[i+1]:
200 | pass
201 | else:
202 | quitlist.append(nickNameListSet[i][j])
203 |
204 | for j in range(amountList[i+1]):
205 | if nickNameListSet[i+1][j] in nickNameListSet[i]:
206 | pass
207 | else:
208 | addlist.append(nickNameListSet[i+1][j])
209 |
210 | markdictList.append(peopledic(add = addlist,quit = quitlist))
211 |
212 | print('------------------------分析开始------------------------\n')
213 | drawBar(timeList,amountList,markdictList,name)
214 | print("{} 群分析完成!".format(name))
215 | info = '截至目前一共采集了{}组数据'.format(lenofSelectedList)
216 | print(info)
217 | info2 = '人员增减变化、地区分布、词云图、性别比的图表已经生成了,在本文件目录result文件夹下可以找到,接下来给出具体增减成员信息\n'
218 | print(info2)
219 |
220 | addlist,quitlist = getAddQuitList(markdictList)
221 | lenaddlist,lenquitlist = getLenofList(addlist,quitlist)
222 |
223 | for i in range(lenofSelectedList):
224 | print("时间:{}\n群总人数 {}".format(timeList[i],amountList[i]))
225 | if lenaddlist[i] != 0:
226 | print("群成员相较于前一次增加了{}人,分别为: ".format(lenaddlist[i]))
227 | for j in range(len(addlist[i])):
228 | print(addlist[i][j], end = ' ')
229 | else:
230 | print("群成员相较于前一次没有增加")
231 | if lenquitlist[i] != 0:
232 | print("\n群成员相较于前一次减少了{}人,分别为: ".format(lenquitlist[i]))
233 | for j in range(len(quitlist[i])):
234 | print(quitlist[i][j], end = ' ')
235 | else:
236 | print("\n群成员相较于前一次没有减少")
237 | print('\n')
238 | print('------------------------分析结束------------------------\n')
239 |
240 | def drawThreeGraphies(selectedList, name, Map, Cloud, Pie):
241 |
242 | lenofSelectedList = len(selectedList)
243 | LatestIndex = lenofSelectedList - 1
244 |
245 | nickNameList = get_var(var = 'NickName', mlist = selectedList[LatestIndex]['record'])
246 | # remarkNameList = get_var(var = 'RemarkName', mlist = selectedList[LatestIndex]['record'])
247 | provinceList = get_var(var = 'Province', mlist = selectedList[LatestIndex]['record'])
248 | # cityList = get_var(var = 'City', mlist = selectedList[LatestIndex]['record'])
249 | sexList = get_var(var = 'Sex', mlist = selectedList[LatestIndex]['record'])
250 | signatureList = get_var(var = 'Signature', mlist = selectedList[LatestIndex]['record'])
251 |
252 | total = len(nickNameList)
253 |
254 | # for i in range(total):
255 | # print("{}({}) {} {}{} {}".format(nickNameList[i],remarkNameList[i],provinceList[i],cityList[i],sexList[i],signatureList[i]))
256 |
257 | if Map :
258 | provinceCounter = analyseProvince(provinceList)
259 | nameList,ranklist = counter2list(provinceCounter.most_common(15))
260 | drawMap(nameList,ranklist,name)
261 | else:
262 | pass
263 |
264 | if Cloud :
265 | signatureCounter = analyseSignature(signatureList)
266 | nameList,ranklist = counter2list(signatureCounter.most_common(200))
267 | drawWorldCloud(nameList,ranklist,name)
268 | else:
269 | pass
270 |
271 | if Pie:
272 | sextuple = analyseSexInfo(sexList)
273 | nameList = ['男','女','未标记']
274 | ranklist = []
275 | for i in sextuple:
276 | ranklist.append(i)
277 | drawPie(nameList,ranklist,name)
278 | else:
279 | pass
280 |
281 | def main(GrouppList, Map = True, Cloud = True, Pie = True):
282 | print("analysing...Please wait a little while")
283 | inputfiles = './result/records.json'
284 | if os.path.exists(inputfiles) != True:
285 | print("Program has stopped, Please make sure data file exists and be in right path")
286 | return
287 | dataList = getFiles(inputfiles)
288 | searchGroupList = GrouppList
289 |
290 | for group in searchGroupList:
291 | selectedList = getSelectedList(mlist = dataList, groupName = group)
292 | drawThreeGraphies(selectedList = selectedList, name = group, Map = Map, Cloud = Cloud, Pie = Pie)
293 | analyseGroupByName(selectedList = selectedList, name = group)
294 |
295 | if __name__ == '__main__':
296 | '''在GroupList中添加需要分析的群名
297 | 在main函数中相应添加True/False值来确定是否要进行绘制 地理分布图、词云图和性别饼图
298 | 三个值默认都为True
299 | 对群成员的分析默认进行绘图。
300 | '''
301 | GrouppList = ['pyecharts 可视化交流群','测试','计算机网络2018']
302 | main(
303 | GrouppList,
304 | Map = True, #True 或 默认 为开启画图,False为不开启
305 | Cloud = True,
306 | Pie = True
307 | )
--------------------------------------------------------------------------------
/autoDownload.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import itchat
5 |
6 | @itchat.msg_register([itchat.content.ATTACHMENT], isGroupChat=True)
7 | def auto_download(msg):
8 | print(msg)
9 | msg.download(msg.fileName)
10 | sender = itchat.search_friends(userName=msg.fromUserName)
11 | print('get {} from {} sucessfully'.format(msg.fileName, sender.nickName))
12 | return
13 |
14 | itchat.auto_login(hotReload=True)
15 | itchat.run()
16 |
--------------------------------------------------------------------------------
/bot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import itchat
5 | import requests
6 |
7 | KEY = 'd6adf489248347428178a7bbff5502a7'
8 |
9 | def get_response(msg):
10 | apiUrl = 'http://www.tuling123.com/openapi/api'
11 | data = {
12 | 'key' : KEY,
13 | 'info' : msg,
14 | 'userid' : 'wechat-robot',
15 | }
16 |
17 | try:
18 | r = requests.post(apiUrl, data=data).json()
19 | return r.get('text')
20 | except:
21 | return
22 |
23 | @itchat.msg_register(itchat.content.TEXT)
24 | def tuling_reply(msg):
25 | defaultReply = '我收到你的消息啦,让我想想~'
26 | reply = get_response(msg['Text'])
27 | return reply or defaultReply
28 |
29 | itchat.auto_login(hotReload=True)
30 | itchat.run()
31 |
--------------------------------------------------------------------------------
/getLatestData.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 |
4 | import itchat
5 | import codecs
6 | import json
7 | import datetime
8 | import os
9 |
10 | def introduce():
11 | intro = '''
12 | welcome to use this program to know your wechat groups
13 | we can use this program to
14 | 1.Know how many people are in this group and who are they.
15 | 2.Get visible data in sex ratio, local distribution and signature wordcloud.
16 | 3.if run full time, maybe it can get the real time monitoring on group members.
17 | PLEASE MAKE SURE THAT YOU SAVE THIS GROUPCHAT TO YOUR CONTACT
18 | '''
19 | print(intro)
20 | intro_begin = 'OK, program is ready to work, this may take a little while.\n'
21 | print(intro_begin)
22 |
23 |
24 | def saveFiles(friendsList):
25 | outputFile = './result/records.json'
26 | with codecs.open(outputFile,'w',encoding='utf-8') as jsonFile:
27 | # 默认使用ascii,为了输出中文将参数ensure_ascii设置成False
28 | jsonFile.write(json.dumps(friendsList,ensure_ascii=False))
29 |
30 | def getFiles(inputFile):
31 | with codecs.open(inputFile,encoding='utf-8') as f:
32 | friendsList = json.load(f)
33 | return friendsList
34 |
35 | def get_var(var,mlist):
36 | variable = []
37 | for i in mlist:
38 | value = i[var]
39 | variable.append(value)
40 | return variable
41 |
42 | def getTime():
43 | return datetime.datetime.now().strftime('%Y-%m-%d|%H:%M:%S')
44 |
45 | def generateDict(mlist,name):
46 | currentTime = getTime()
47 |
48 | currentDict ={
49 | 'time' : currentTime,
50 | 'name' : name,
51 | 'record' : mlist
52 | }
53 |
54 | return currentDict
55 |
56 | def saveData(saveddict):
57 | filesAddress = './result/records.json'
58 | data = getFiles(filesAddress)
59 | data.append(saveddict)
60 | print("Save data sucessfully!")
61 | print("we have already saved {} data block\n".format(len(data)))
62 | saveFiles(data)
63 |
64 | def makedir(folderAddress):
65 | if os.path.exists(folderAddress):
66 | pass
67 | else:
68 | os.makedirs(folderAddress)
69 |
70 | def init():
71 | makedir('./result')
72 |
73 | init_list = []
74 |
75 | if os.path.exists('./result/records.json'):
76 | pass
77 | else:
78 | saveFiles(init_list)
79 |
80 | def mainWork(chatRoomList,login):
81 |
82 | if login == 'auto':
83 | itchat.auto_login(hotReload = True)
84 | elif login == 'single':
85 | ichat.login()
86 | else:
87 | print("[Stopped] plz input correct login command")
88 | return
89 |
90 | for chatRoomName in chatRoomList:
91 | searchedChatRoomList = itchat.search_chatrooms(chatRoomName)
92 | ''' Try to search the matched chatrooms '''
93 | ''' '''
94 | if searchedChatRoomList is None:
95 | print("{} is not founded".format(chatRoomName))
96 | elif len(searchedChatRoomList) is 0:
97 | print("Oh No, We got nothing, ** Make sure that you save this groupchat to contact **")
98 | else:
99 | ''' get the chatroom '''
100 | # print(searchedChatRoomList)
101 | thisUserName = searchedChatRoomList[0]["UserName"]
102 | # print(thisUserName) #get the "id" UserName
103 |
104 | chatRoom = itchat.update_chatroom(thisUserName, detailedMember=True) #update the group message,and then return the chatroom
105 | # print(chatRoom['MemberList'])
106 | total = len(chatRoom['MemberList']) #get the len of chatroom memberlist
107 |
108 | currentSavedDict = generateDict(chatRoom['MemberList'], chatRoomName)
109 |
110 | saveData(currentSavedDict)
111 | itchat.logout()
112 |
113 | if __name__ == '__main__':
114 | '''在GroupList中输入想要分析的群聊名称,输入login的参数
115 | login = 'auto',会调用itchat的自动缓存登陆模式,第二次登陆无需扫码
116 | 适用于持续使用者
117 | logn = 'single',会调用itchat单次扫码登陆模式,适合于一次使用。
118 | '''
119 | GroupList = ['测试','计算机网络2018']
120 | introduce()
121 | init()
122 | mainWork(
123 | GroupList,
124 | login = 'auto'
125 | )
--------------------------------------------------------------------------------
/groupBot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | 【例】图灵小机器人的群聊版
6 | 功能:
7 | 开启后,在群里@机器人并带上消息,机器人会在群聊里@提问者并回复
8 | 机器人回复内容来自 http://www.tuling123.com/openapi/api,
9 | KEY值是使用api的通行证,可以自己申请。
10 |
11 | """
12 |
13 | import itchat
14 | import requests
15 |
16 | def get_response(info):
17 | '''
18 | 此函数用于调用API获取回复,若出现问题时,将会返回一个空值
19 | '''
20 | apiUrl = 'http://www.tuling123.com/openapi/api'
21 | data = {
22 | 'key' : KEY,
23 | 'info' : info,
24 | 'userid' : 'wechat-robot',
25 | }
26 |
27 | try:
28 | r = requests.post(apiUrl, data=data).json()
29 | return r.get('text')
30 | except:
31 | return
32 | def getReply(text):
33 | '''
34 | 此函数用于群里@机器人后消息的处理,处理除去@<机器人名>后的文本消息
35 | '''
36 | if text == '':
37 | return '@机器人的同时说些什么吧~'
38 | defalutReply = '机器人开小差了等会儿再试试吧'
39 | reply = get_response(text)
40 | return reply or defalutReply
41 |
42 | @itchat.msg_register(itchat.content.TEXT, isGroupChat=True)
43 | def group_reply(msg):
44 | '''
45 | 此函数用于接收群聊消息和回复消息,只有机器人被@之后,才做出回复
46 | 例:
47 | (在某群中)
48 | 群成员小k : @robot 你好啊
49 | robot自动回复 : @小k: 你也好呀
50 | '''
51 | textMsg = msg['Text']
52 | print('收到群消息:{}'.format(textMsg))
53 | if msg.isAt:
54 | robotHostName = '@' + myself['NickName']
55 | rawMessage = textMsg.replace(robotHostName, '') #对获取的消息做处理,将@<机器人名>从文本中去除
56 | # print('{}'.format(rawMessage))
57 | itchat.send(u'@{}\u2005: {}'.format(msg['ActualNickName'], getReply(rawMessage)),msg['FromUserName'])
58 |
59 | if __name__ == '__main__':
60 | KEY = 'd6adf489248347428178a7bbff5502a7'
61 | itchat.auto_login(hotReload=True) #登陆微信
62 | myself = itchat.search_friends() #获取机器人账号自己的消息
63 | itchat.run()
64 |
--------------------------------------------------------------------------------
/provinceMap.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import itchat
5 | from pyecharts import Map
6 | from collections import Counter
7 |
8 | itchat.auto_login(hotReload=True)
9 | myFriendList = itchat.get_friends()
10 |
11 | provinceCounter = Counter()
12 |
13 | for friend in myFriendList:
14 | province = friend['Province']
15 | if province != '':
16 | provinceCounter[province] += 1
17 |
18 | myMap = Map('你的微信好友地区分布图',width=1200, height=600, title_pos='center')
19 | attr, value = myMap.cast(provinceCounter)
20 | myMap.add(
21 | '', attr, value,
22 | maptype = 'china',
23 | is_visualmap = True,
24 | is_label_show = True,
25 | visual_range = [0,80]
26 | )
27 | myMap.render('./你的微信好友地区分布图.html')
28 |
29 |
30 |
--------------------------------------------------------------------------------
/sex.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | 【例子】分析微信好友性别比例
6 | 引入库
7 | `itchat` 模拟登陆网页版微信
8 | `pyecharts` 用于绘图
9 | 功能
10 | 迷你登陆微信网页版,获取好友列表性别比例
11 | """
12 |
13 | import itchat
14 | from pyecharts import Pie
15 |
16 | itchat.auto_login(hotReload=True) #登陆微信
17 |
18 | myFriendList = itchat.get_friends() #获取微信中的好友列表
19 |
20 | sexCounter = {'男' : 0, '女' : 0, '未标注' : 0}
21 |
22 | for friend in myFriendList:
23 | if friend['Sex'] == 1:
24 | sexCounter['男'] += 1
25 | elif friend['Sex'] == 2:
26 | sexCounter['女'] += 1
27 | else:
28 | sexCounter['未标注'] += 1
29 |
30 | pie = Pie('你的微信好友性别比例图',width=1200, height=600, title_pos='center')
31 | attr, value = pie.cast(sexCounter)
32 | '''利用pyecharts的cast方法将字典列表转换成两个列表用于绘图
33 | 例:
34 | tagsList = [{'周一':3},{'周二':2},{'周三':1}]
35 | 用cast方法获得
36 | attr = ['周一','周二','周三']
37 | value = [3,2,1]
38 | '''
39 | pie.add(
40 | '', attr, value,
41 | is_label_show = True,
42 | legend_orient = 'vertical', # 图例是否垂直
43 | legend_pos = 'left'
44 | )
45 |
46 | pie.render('./你的微信好友性别比例图.html') # 绘图渲染
47 |
--------------------------------------------------------------------------------
/signUp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | 【例子】微信报名签到小工具
6 | 使用:
7 | 在微信群中,@<签到管理器>报名,即时返回签到信息
8 | 例子:
9 | 小A:@小T 报名
10 | 小T:收到,目前报名人有
11 | 1.小A
12 | """
13 |
14 | import itchat
15 | from collections import Counter
16 |
17 | @itchat.msg_register(itchat.content.TEXT, isGroupChat=True)
18 | def signUp(msg):
19 | textMsg = msg['Text']
20 | # 获取信息的文本信息
21 | robotHostName = '@' + myself['NickName']
22 | rawMessage = textMsg.replace(robotHostName, '').strip()
23 | # 去除掉@<机器人名>之后的文本
24 | groupID = msg['FromUserName']
25 | # 群ID
26 | if msg.isAt and rawMessage == '报名':
27 | if signCounter[groupID] == 0 :
28 | sendMsg[groupID] = '收到,目前报名人有:'
29 | # 若第一次@,则创建该群下的计数和信息记录
30 |
31 | signCounter[groupID] += 1
32 | signUser = msg['ActualNickName']
33 | sendMsg[groupID] = sendMsg[groupID] + '\n' + str(signCounter[groupID]) + '.' + signUser
34 | # 将报名计数迭代,且将报名信息更新
35 | # 每一次添加字符串 <迭代次数>.<报名人ID>
36 |
37 | print(sendMsg[groupID])
38 | # 控制台输出
39 | itchat.send(sendMsg[groupID], groupID)
40 | # 将内容发送到群里
41 |
42 | if __name__ == '__main__':
43 | signCounter = Counter()
44 | sendMsg = {}
45 |
46 | itchat.auto_login(hotReload=True)
47 | myself = itchat.search_friends()
48 | # 获取自身账号信息
49 | itchat.run()
--------------------------------------------------------------------------------
/transfer_single.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | 【例】微信转发消息工具,转发指定群个人消息至另外一群
6 | 例如:
7 | --在群聊A中,小T发消息:你好
8 | --在群聊B中有转发消息:及时收到来自群聊【A】,@小T的消息:你好
9 | 使用:
10 | --运行本程序即可,关闭退出即可
11 | 说明:
12 | --目前仅限于接收和转化文本消息,图片、语音、视频、文件暂时未添加功能。
13 | """
14 |
15 | import itchat
16 |
17 | @itchat.msg_register([itchat.content.TEXT], isGroupChat=True)
18 | def transfer(msg):
19 | print('有群聊消息')
20 |
21 | if msg['ToUserName'] == groupID and msg['FromUserName'] == userID:
22 | '''
23 | 此处注意:
24 | 如果是转化自己发出的消息到其他群应设置判断条件为
25 | msg['ToUserName'] == groupID and msg['FromUserName'] == userID
26 | 转化发别人消息到其他群则为
27 | msg['ToUserName'] == userID and msg['FromUserName'] == groupID
28 | '''
29 | print('收到关注消息')
30 |
31 | for toGroup in toGroupList:
32 | toGroupIDList = itchat.search_chatrooms(name=toGroup)
33 | toGroupID = toGroupIDList[0]['UserName']
34 | itchat.send('及时转发来自群【{}】,@{}的消息:{}'.format(groupName,userName,msg['Content']),toGroupID)
35 |
36 | print('已转发完成')
37 |
38 | def main(userName,groupName,toGroupList):
39 | global groupID
40 | global userID
41 |
42 | itchat.auto_login(hotReload=True)
43 | # 登陆微信
44 | searchedGroupList = itchat.search_chatrooms(name=groupName)
45 | groupID = searchedGroupList[0]['UserName']
46 | chatRoom = itchat.update_chatroom(groupID, detailedMember=True)
47 | # 搜索指定群聊的id
48 | for member in chatRoom['MemberList']:
49 | if member['NickName'] == userName:
50 | userID = member['UserName']
51 | # 在指定群聊中搜索指定人员的id
52 |
53 | # print('userID = {}\ngroupID = {}\n'.format(userID,groupID))
54 |
55 | itchat.run()
56 | # 开始搜索
57 |
58 | if __name__ == '__main__':
59 | '''以下可修改为
60 | '''
61 | userName = 'Tenkey'
62 | groupName = '新时代文化交流群'
63 | toGroupList = ['啊哈']
64 | main(userName,groupName,toGroupList)
65 |
--------------------------------------------------------------------------------
/wordCloud.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 |
6 | 【例子】:对微信好友的个性签名生成词云图
7 | 引入库说明
8 | `itchat` 模拟登陆网页版微信
9 | `jieba` 用于分词
10 | `pyecharts` 用于绘图
11 | `collections` 使用Counter经行计数
12 | 功能
13 | 模拟登陆微信网页版,获取好友列表签名生成词云图
14 | 在本文件目录下生成词云图的 .html 文件
15 |
16 | """
17 |
18 | import itchat
19 | import jieba.analyse
20 | from pyecharts import WordCloud
21 | from collections import Counter
22 |
23 | itchat.auto_login(hotReload=True) #登陆微信
24 |
25 | myFriendsList = itchat.get_friends() #获取微信中的好友列表
26 |
27 | signatureCounter = Counter() #生成一个Counter对象,后续用于词频的计数
28 | for friend in myFriendsList:
29 | signature = friend['Signature']
30 | signature = signature.strip().replace('emoji','').replace('class','').replace('span','') #替换好友签名中表情的代码文本
31 | tags = jieba.analyse.extract_tags(signature) #利用jieba分词,统计词频
32 | for tag in tags:
33 | signatureCounter[tag] += 1
34 | tagsList = signatureCounter.most_common(200) #选出分词后词频最高的200个词
35 |
36 | wordCloud = WordCloud('你的微信好友签名云图',width=1200, height=600, title_pos='center') #生成一个词云图对象,用于绘制词云图,在这里设置标题、高度宽度和位置
37 | attr, value = wordCloud.cast(tagsList)
38 | '''利用pyecharts的cast方法将字典列表转换成两个列表用于绘图
39 | 例:
40 | tagsList = [{'周一':3},{'周二':2},{'周三':1}]
41 | 用cast方法获得
42 | attr = ['周一','周二','周三']
43 | value = [3,2,1]
44 | '''
45 | wordCloud.add(
46 | '',attr,value,
47 | shape = 'star',
48 | )
49 | '''设置词云图属性,将分词列列表和词频列表添加进入
50 | 设置词云图形状为'start'
51 | 还有的图形 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star'
52 |
53 | '''
54 | wordCloud.render('./你的微信好友签名云图.html') #渲染,在本程序目录下生成.html文件
--------------------------------------------------------------------------------