├── test.py ├── data ├── 好友信息 ├── admin ├── cityjson ├── 201905232314 │ ├── 今日课程计划 │ └── 已完成课程 └── 9d04a_alldream.xlsx ├── start.bat ├── .run.py.swp ├── itchat.pkl ├── qinghua.txt ├── image ├── nomal.png ├── teacher.png ├── 2019-05-23-23_14_05.png └── 2019-05-23-23_14_051.png ├── __pycache__ ├── Find.cpython-36.pyc ├── Find.cpython-37.pyc ├── ctrip.cpython-36.pyc ├── run.cpython-36.pyc ├── run.cpython-37.pyc ├── turling.cpython-36.pyc └── turling.cpython-37.pyc ├── 运行截图 ├── Snipaste_2019-08-11_12-35-35.png ├── Snipaste_2019-08-11_12-37-29.png ├── Snipaste_2019-08-11_12-38-08.png ├── Snipaste_2019-08-11_12-40-26.png ├── Snipaste_2019-08-11_12-42-00.png ├── Snipaste_2019-08-11_12-44-30.png ├── Snipaste_2019-08-11_12-45-19.png ├── Snipaste_2019-08-11_12-46-50.png ├── Snipaste_2019-08-11_12-48-06.png ├── Snipaste_2019-08-11_12-48-58.png └── Snipaste_2019-08-11_12-50-04.png ├── start.py ├── wechatplus口令.md ├── turling.py ├── ctrip.py ├── FormyGfScript.py ├── nohup.out ├── formyGF.md ├── Find.py ├── run.py └── README.md /test.py: -------------------------------------------------------------------------------- 1 | print "hello world" -------------------------------------------------------------------------------- /data/好友信息: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/好友信息 -------------------------------------------------------------------------------- /start.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/start.bat -------------------------------------------------------------------------------- /.run.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/.run.py.swp -------------------------------------------------------------------------------- /data/admin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/admin -------------------------------------------------------------------------------- /itchat.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/itchat.pkl -------------------------------------------------------------------------------- /qinghua.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/qinghua.txt -------------------------------------------------------------------------------- /data/cityjson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/cityjson -------------------------------------------------------------------------------- /image/nomal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/image/nomal.png -------------------------------------------------------------------------------- /image/teacher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/image/teacher.png -------------------------------------------------------------------------------- /data/201905232314/今日课程计划: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/201905232314/今日课程计划 -------------------------------------------------------------------------------- /data/201905232314/已完成课程: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/201905232314/已完成课程 -------------------------------------------------------------------------------- /data/9d04a_alldream.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/data/9d04a_alldream.xlsx -------------------------------------------------------------------------------- /image/2019-05-23-23_14_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/image/2019-05-23-23_14_05.png -------------------------------------------------------------------------------- /__pycache__/Find.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/Find.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/Find.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/Find.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/ctrip.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/ctrip.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/run.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/run.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/run.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/run.cpython-37.pyc -------------------------------------------------------------------------------- /image/2019-05-23-23_14_051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/image/2019-05-23-23_14_051.png -------------------------------------------------------------------------------- /__pycache__/turling.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/turling.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/turling.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/__pycache__/turling.cpython-37.pyc -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-35-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-35-35.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-37-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-37-29.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-38-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-38-08.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-40-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-40-26.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-42-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-42-00.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-44-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-44-30.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-45-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-45-19.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-46-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-46-50.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-48-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-48-06.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-48-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-48-58.png -------------------------------------------------------------------------------- /运行截图/Snipaste_2019-08-11_12-50-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QiDaChen/personal-wechatplus/HEAD/运行截图/Snipaste_2019-08-11_12-50-04.png -------------------------------------------------------------------------------- /start.py: -------------------------------------------------------------------------------- 1 | #author:magic Chen py3.7.0 2019/3/25 chenphoun@outlook.com 2 | import itchat 3 | from run import * 4 | import pandas as pd 5 | 6 | 7 | def main(): 8 | itchat.auto_login(hotReload=True,enableCmdQR=2) 9 | friends = itchat.get_friends(update=True)[1:] 10 | dealData(friends) 11 | initset(friends) 12 | itchat.run() 13 | if __name__ == "__main__": 14 | main() 15 | 16 | 17 | -------------------------------------------------------------------------------- /wechatplus口令.md: -------------------------------------------------------------------------------- 1 | # wechatplus 2 | 3 | ## friends 4 | 5 | ### 聊天机器人 6 | 7 | #### 开始 8 | 9 | ##### 任何状态下输入[开始],便进入到聊天机器人状态 10 | 11 | #### 退出 12 | 13 | ##### 人工智能机器人状态下输入[退出],便退出聊天机器人状态 14 | 15 | #### 聊天 16 | 17 | ##### 在人工智能聊天机器人的状态下 输入任何聊天文本将会收到相应响应 18 | 19 | ### teacher 20 | 21 | #### 傲梦编程数据检索口令 22 | 23 | ##### 获取数据 24 | 25 | ###### 【获取数据】是下面所有傲梦编程数据检索的根本,必须要有 26 | 27 | ##### 输入验证码 28 | 29 | ###### 就是输入你看到图片的验证码 30 | 31 | ##### 今日课程计划 32 | 33 | ###### 【今日】 34 | 35 | ##### 近日课程计划 36 | 37 | ###### 【近日】 38 | 39 | ##### 生成备课表 40 | 41 | ###### 【备课表】 42 | 43 | ##### 某某学生课堂反馈 44 | 45 | ###### 例如【陈晓琪课堂反馈】 46 | 47 | ### 百度小能手 48 | 49 | #### 开启度娘模式 50 | 51 | ##### 【百度一下】 52 | 53 | #### 退出度娘模式 54 | 55 | ##### 【退出百度】 56 | 57 | #### 搜索关键词 58 | 59 | ##### 【四大发明都有啥】 60 | 61 | ### 新闻查看 62 | 63 | #### IT之家热点文章 64 | 65 | ##### 【热点】 66 | 67 | ### 普通用户升级成teacher权限 68 | 69 | #### 注册傲梦讲师 70 | 71 | 【注册傲梦讲师】直接输入(全匹配) 72 | 73 | #### 输入账号密码 74 | 75 | 【11位手机号 密码】手机号和密码之间要有空格(格式匹配) 76 | 77 | #### 确认信息录入 78 | 79 | 【确认信息录入】全匹配 80 | ## 获取90天低价机票 81 | [西安到上海的低价机票] 城市名只收录了国内的 82 | -------------------------------------------------------------------------------- /turling.py: -------------------------------------------------------------------------------- 1 | '''图灵机器人''' 2 | 3 | 4 | #coding=utf8 5 | import requests 6 | ''' 7 | 图灵机器人接口 8 | 函数的参数: 微信聊天的时候输入的内容 9 | 函数的返回值:图灵机器人的回应 10 | ''' 11 | headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'} 12 | def baidu(info): 13 | page = requests.get('https://zhidao.baidu.com/search?lm=0&rn=10&pn=0&fr=search&ie=gbk&word={}'.format(info),headers=headers) 14 | if page.ok: 15 | page.encoding = 'gbk' 16 | from lxml import etree 17 | tree = etree.HTML(page.text) 18 | answer = ''.join(tree.xpath('//*[@id="wgt-list"]/dl[1]/dd[1]//text()')) 19 | if '答:' not in answer: 20 | answer = ''.join(tree.xpath('//*[@id="wgt-list"]/dl[1]/dd[2]//text()')) 21 | return answer[2:] 22 | 23 | 24 | def jqr(info): 25 | apiUrl = 'http://www.tuling123.com/openapi/api' 26 | data = { 27 | 'key' : 'ad0c5d0594ce42f1b5c7a8547eb947e4','info' : info,'userid' : '陈小奇',# 28 | } 29 | # 我们通过如下命令发送一个post请求 30 | r = requests.post(apiUrl, data=data).json() 31 | # 让我们打印一下返回的值,看一下我们拿到了什么 32 | print(r) 33 | try: 34 | result = r['text']+r['url'] 35 | except KeyError: 36 | result = r['text'] 37 | try: 38 | ls = r['list'] 39 | for i in ls[:5]: 40 | result+=i['article'] 41 | result+='\n' 42 | result+=i['detailurl'] 43 | result+='\n' 44 | except KeyError: 45 | pass 46 | return result 47 | # print(jqr('qinaide')) 48 | -------------------------------------------------------------------------------- /ctrip.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import re 3 | import pickle 4 | import json 5 | 6 | def getCityTable(acity,dcity): 7 | with open("./data/cityjson",'rb') as file: 8 | cityDict = pickle.load(file) 9 | try: 10 | a = cityDict[acity] 11 | d = cityDict[dcity] 12 | return [a,d] 13 | except: 14 | return False 15 | 16 | def getaddr(words): 17 | adcity = False 18 | try : 19 | acity,dcity = re.findall("(.+)到(.+)",words)[0] 20 | print(acity,dcity) 21 | except: 22 | return adcity 23 | else: 24 | adcity = getCityTable(acity,dcity) 25 | finally: 26 | return adcity 27 | def getlowerprice(resultcity): 28 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} 29 | payload2 = {"flightWay": "Oneway", "dcity": resultcity[0], "acity": resultcity[1]} 30 | url2 = 'https://flights.ctrip.com/itinerary/api/12808/lowestPrice' 31 | resultjson = requests.post(url2, json=payload2, headers=headers) 32 | if resultjson.ok: 33 | jsons = json.loads(resultjson.text) 34 | print(jsons) 35 | if jsons['msg'] == 'success': 36 | res_list = jsons["data"]['oneWayPrice'] 37 | res_msg = '\n'.join(["时间{}:价格{}".format(k,v) for k,v in res_list[0].items()]) 38 | return res_msg 39 | else: 40 | return "这两地间您确定有航班?" 41 | else: 42 | return '网络环境差,获取失败' 43 | def getLowerAir(words): 44 | resultcity = getaddr(words) 45 | if resultcity: 46 | return getlowerprice(resultcity) 47 | else: 48 | return "您输入的城市太凶了,我都没有找到~" 49 | getLowerAir("西安到长沙") 50 | -------------------------------------------------------------------------------- /FormyGfScript.py: -------------------------------------------------------------------------------- 1 | import time 2 | from random import randint,choice 3 | import itchat 4 | import pandas as pd 5 | 6 | def dealFriendsData(friends): 7 | ''' 8 | 函数的参数是微信好友信息的字典 9 | 微信所有好友的信息抓取 10 | 好友信息中的网名 id 备注 个性签名 城市 性别 11 | 都被保存在了DataFrame数据帧里面 留作备用 12 | 转换好的df被作为返回值返回 13 | ''' 14 | fs = {} 15 | for i in friends: 16 | fs[i['NickName']] = {'UserName':i['UserName'],'Remark':i['RemarkName'],'Sex':i['Sex'],'qianming':i['Signature'],'city':i['City']} 17 | dfs = pd.DataFrame(fs).T 18 | return dfs 19 | def initConfig(): 20 | ''' 21 | 设置问候语和问候时间段的地方 22 | words 是问候语设置位置 23 | time 因为时间是随机的,但是有范围,[7,2]表示<7点之后两小时之内的随机时间> 24 | 25 | ''' 26 | config = {'morning':{'flag': True,'words':'早安','time':[7,2]}, 27 | 'afternoon':{'flag': True,'words':'晚安','time':[21,2]}, 28 | 'daily':{'flag': True,'words':qinghua(),'time':[11,7]}} 29 | for i,j in config.items(): 30 | config[i]['unix'] = today + j['time'][0]*3600 + randint(1,j['time'][1]*3600) 31 | return config 32 | def qinghua(): 33 | ''' 34 | 从qinghua.txt中随机取一句话出来 35 | 注意在文本中添加新的情话时候要换行 36 | 37 | ''' 38 | with open ('qinghua.txt','r') as file: 39 | word = file.read() 40 | word_list = word.split('\n') 41 | return choice(word_list) 42 | #登录微信脚本,获取女友的username 43 | itchat.auto_login() 44 | friends = itchat.get_friends(update=True)[1:] 45 | df = dealFriendsData(friends) 46 | she_username = df[df['Remark']=='傻逼兮兮'].iloc[0].UserName 47 | 48 | #定时发送信息 49 | today = 1558886400#北京时间2019-05-27 00:00:00 unix时间戳 50 | oneday = 24*60*60 51 | nextday = today + oneday 52 | set_ = initConfig() 53 | 54 | while 1: 55 | now = int(time.time())#获得当前的时间戳 56 | temp = now - nextday 57 | #一天过完之后 58 | if temp > 0: 59 | today = nextday 60 | nextday += oneday 61 | set_ = initConfig() 62 | #检测 时间 63 | else: 64 | for i,j in set_.items(): 65 | if now-j['unix'] > 0 and j['flag']: 66 | itchat.send_msg(j['words'],she_username) 67 | set_[i]['flag'] = False 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /nohup.out: -------------------------------------------------------------------------------- 1 | █ Getting uuid of QR code. 2 | Downloading QR code. 3 | ██████████████████████████████████████████████████████████████████████████████ 4 | ██ ████ ████████ ██████ ██ ██████ ██ 5 | ██ ██████████ ████ ██ ████████ ██████ ████████ ██████████ ██ 6 | ██ ██ ██ ██ ████ ██ ██ ████ ██ ██ ██ ██ ██ 7 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██ ██ 8 | ██ ██ ██ ████ ██████ ██ ██ ██ ██ ██ ██████ ██ ██ ██ 9 | ██ ██████████ ██████ ██████ ██ ████████ ████ ██████ ██████████ ██ 10 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 11 | ████████████████████ ████ ████ ██ ██ ██ ██████████████████ 12 | ████████ ██ ██ ██ ██ ████████ ██████████████████ ██████ 13 | ████ ██████ ██ ██████████ ████ ████ ████ ██ ██████ ████ ████ 14 | ████ ██ ██ ████ ██ ██ ████ ████ ██ ██████████ ██ 15 | ████ ████████ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ 16 | ██ ████ ██ ██████ ████████████ ██ ██ ██ ██ 17 | ██████ ██ ████ ██ ██ ██ ██ ████ ████ ██ ██████ 18 | ██████████ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ 19 | ██ ██ ██ ██████ ██████ ████ ██ ██ ██ ██████ ██ ████ ████ 20 | ██████ ████ ██████████ ██ ██████ ████ ████ ██ ████ ██ ██ 21 | ██ ██ ██████ ████ ██████████████ ██ ██ ██ ██████ ████ 22 | ██ ██ ██ ██ ██████ ██ ██ ██ ██ ████ ██████ ████ ██ ██ 23 | ████████ ████████ ██ ████ ██ ██ ██████ ██████ ██████ ████████ 24 | ████ ██ ██ ██ ██████ ████████ ██ ██ ██ ██ ████████ 25 | ██ ██████████████ ██████ ████ ██ ██ ██ ████ ██ ██████ 26 | ██ ██ ██ ████ ██ ██ ██████ ████ ██ ████ ████████ ██████ ██ 27 | ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ████ ██████ 28 | ██████ ████ ██████████ ██████ ██████ ██ ██ ██ ██ ██ 29 | ██ ██ ████████ ██ ████ ██████ ██ ██ ████ ████ 30 | ██ ██ ██ ██████ ████ ██ ████ ████ ████ ██ 31 | ██ ████ ██ ██████ ████ ██████ ████ ██ ██ ████ ██████ 32 | ██ ██ ██ ████ ████ ████████ ██ ██ ██ ████████ 33 | ██████████████████ ██ ████████████████ ██████ ████ ██████ ████ 34 | ██ ██ ██ ██ ████ ██████████ ██████ ██ ██ ██ ██ 35 | ██ ██████████ ████████████ ██ ██████ ██ ██ ██████ ██ ████ 36 | ██ ██ ██ ██ ██████ ██ ████████████ ████ ████ ████ 37 | ██ ██ ██ ██ ██ ██ ██████ ██ ██████████ ██ ████ ████████ 38 | ██ ██ ██ ████ ██ ██ ██ ██ ████████ ████ ████ ██ 39 | ██ ██████████ ██████ ████████ ██ ██████ ██████ ██ ██ ██ 40 | ██ ████ ████████████ ████ ██ ██ ██████ ██ ████ ████ ██ 41 | ██████████████████████████████████████████████████████████████████████████████ 42 | Please scan the QR code to log in. 43 | Please press confirm on your phone. 44 | Loading the contact, this may take a little while. 45 | Login successfully as 艺术家的猫 46 | Start auto replying. 47 | LOG OUT! 48 | -------------------------------------------------------------------------------- /formyGF.md: -------------------------------------------------------------------------------- 1 | # python让你的个人微信号像梦一样自由 2 | 3 | #### 起源 4 | 5 | 笔者是一个coder, 6 | 7 | 一个有女朋友的coder。 8 | 9 | 一个有女朋友但特别懒的coder, 10 | 11 | 一个有女朋友但特别懒可还是很想让女朋友如沐春风的coder, 12 | 13 | 一个有女朋友但特别懒可还是很想让女朋友如沐春风可记性不大好的coder, 14 | 15 | 16 | 17 | 18 | 19 | ​ 后来发现,呆板如笔者,实在难于兼容女朋友大人的需求版本,譬如,每天的早安晚安打卡总是因为一把游戏或者一个需求的影响忘得死死的,当想起来了的时候发现该到下一轮的打卡了。总是因为这样让人难以控制的原因需要解释安抚半天,这让笔者绝望并且懊恼。直到有一天看到这句话,**人工智能可以替代人类从事一部分工作,把人类*从繁杂*、*重复的劳动中解脱出来*,从事更加需要感性思维的工作,如艺术、科研、神学、哲学等工作。**一瞬间醍醐灌顶,繁杂、重复、解脱、解脱,一个可怕但是让笔者兴奋不已的想法开始在脑海中生根发芽。 20 | 21 | #### 干 22 | 23 | ​ 有了这个想法之后,笔者就迅速开始准备策划,千万不要等女朋友受不了我之后才做出来呀,眼看他起高楼,眼看他宴宾客,眼看他楼塌了,这是多么绝望的情景呀,毕竟,有女朋友是一件值得让程序员骄傲的事,可是有过女朋友,就要逊色太多了,想到这里,百度已经帮笔者找到了解决方案,itchat,迅速翻文档,测试代码, 24 | 25 | [](https://itchat.readthedocs.io/zh/latest/)经过简单的api研究,安装完模块,就开始了第一个版本的开发工作, 26 | 27 | 28 | 29 | 1:python 控制微信自动发送消息 30 | 31 | ```python 32 | import itchat 33 | 34 | itchat.auto_login() 35 | 36 | itchat.send('Hello, world', toUserName='filehelper') 37 | ``` 38 | 39 | 完工运行,文件助手收到了,我的第一条消息,可是来不及兴奋,笔者赶紧进行研究文档,看怎么去给特定好友好友发送信息,**toUserName**应该是每个好友都有的类似网名或者id的东西,想到这里,就决定得先把所有好友的信息拿下来研究一番, 40 | 41 | ```python 42 | friends = itchat.get_friends(update=True)[1:] 43 | ``` 44 | 45 | 拿到好友信息,进行简单的数据结构分析,便发现了其中的奥秘 46 | 47 | ```python 48 | def dealFriendsData(friends): 49 | ''' 50 | 函数的参数是微信好友信息的字典 51 | 微信所有好友的信息抓取 52 | 好友信息中的网名 id 备注 个性签名 城市 性别 53 | 都被保存在了DataFrame数据帧里面 留作备用 54 | 转换好的df被作为返回值返回 55 | ''' 56 | fs = {} 57 | for i in friends: 58 | fs[i['NickName']] = {'UserName':i['UserName'],'Remark':i['RemarkName'],'Sex':i['Sex'],'qianming':i['Signature'],'city':i['City']} 59 | dfs = pd.DataFrame(fs).T 60 | return dfs 61 | ``` 62 | 63 | 经过以上操作,好友的信息便被安排的明明白白,通过对信息中的命名的检查,一眼找到 **UserName**的信息, 64 | 65 | 想要找到女朋友的username手到擒来 66 | 67 | ```python 68 | she_username = df[df['Remark']=='女朋友的备注'].iloc[0].UserName 69 | ``` 70 | 71 | ok!至此,只剩下时间的问题了,要选在什么时间呢,不能太早,不能太晚,不能天天准点发,一个随机时间还不足以让笔者费脑筋 72 | 73 | ```python 74 | import time 75 | from random import randint 76 | 77 | def initConfig(): 78 | ''' 79 | 设置问候语和问候时间段的地方 80 | words 是问候语设置位置 81 | time 因为时间是随机的,但是有范围,[7,2]表示<7点之后两小时之内的随机时间> 82 | 83 | ''' 84 | config = {'morning':{'flag': True,'words':'早安','time':[7,2]}, 85 | 'afternoon':{'flag': True,'words':'晚安','time':[21,2]}, 86 | 'daily':{'flag': True,'words':qinghua(),'time':[11,7]}} 87 | for i,j in config.items(): 88 | config[i]['unix'] = today + j['time'][0]*3600 + randint(1,j['time'][1]*3600) 89 | return config 90 | 91 | #定时发送信息 92 | today = 1558886400#北京时间2019-05-27 00:00:00 unix时间戳 93 | oneday = 24*60*60 94 | nextday = today + oneday 95 | set_ = initConfig() 96 | 97 | while 1: 98 | now = int(time.time())#获得当前的时间戳 99 | temp = now - nextday 100 | #一天过完之后 101 | if temp > 0: 102 | today = nextday 103 | nextday += oneday 104 | set_ = initConfig() 105 | #检测 时间 106 | else: 107 | for i,j in set_.items(): 108 | if now-j['unix'] > 0 and j['flag']: 109 | itchat.send_msg(j['words'],she_username) 110 | set_[i]['flag'] = False 111 | 112 | 113 | 114 | ``` 115 | 116 | ​ 定时发送经过unix时间戳的灵活运用,实现了完美随机,接下来就是情话了,笔者是没有说情话的天分的,但是作为一个spider,从来都不怕,笔者准备了一个txt文本,把平常看到的听到的情话整理了起来,随机读取一下试试, 117 | 118 | ```python 119 | def qinghua(): 120 | ''' 121 | 从qinghua.txt中随机取一句话出来 122 | 注意在文本中添加新的情话时候要换行 123 | 124 | ''' 125 | with open ('qinghua.txt','r') as file: 126 | word = file.read() 127 | word_list = word.split('\n') 128 | return choice(word_list) 129 | ``` 130 | 131 | ![微信图片_20190527191248](C:\Users\Administrator\Desktop\微信图片_20190527191248.jpg) 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /Find.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pickle 3 | import time 4 | 5 | def readsth(): 6 | with open('./data/admin','rb') as file: 7 | return pickle.load(file) 8 | def aiYzm(filename): 9 | ''' 10 | :param filename: 表示图片的文件路径 11 | :return: 返回图片经过百度开发识别的结果,如识别失败的话直接返回false 12 | ''' 13 | from aip import AipOcr 14 | """ 你的 APPID AK SK """ 15 | APP_ID = '16190824' 16 | API_KEY = 'sW2uzXjyWqiyC5Lq2lNsdnig' 17 | SECRET_KEY = 'GVF2YX5cS7RZqfXMGgIpnuPDPQyfEyWq' 18 | client = AipOcr(APP_ID, API_KEY, SECRET_KEY) 19 | """ 读取图片 """ 20 | def get_file_content(filePath): 21 | with open(filePath, 'rb') as fp: 22 | return fp.read() 23 | image = get_file_content(filename) 24 | """ 调用数字识别 """ 25 | client.numbers(image); 26 | """ 如果有可选参数 """ 27 | options = {} 28 | options["recognize_granularity"] = "big" 29 | options["detect_direction"] = "true" 30 | """ 带参数调用数字识别 """ 31 | a = client.numbers(image, options) 32 | try: 33 | a = a['words_result'][0]['words'] 34 | print(a) 35 | except: 36 | return False 37 | else: 38 | if len(a) == 4: 39 | return a 40 | else: 41 | return False 42 | def uTime(stamp): 43 | ''' 44 | unix时间戳转化为正常显示的时间 45 | 参数是时间戳 46 | 返回值是转换好的时间 47 | ''' 48 | stamp = stamp/1000 49 | time_local = time.localtime(stamp) 50 | df = time.strftime("%Y-%m-%d %H:%M:%S",time_local) 51 | return df 52 | def bkb(user,timec): 53 | '''生成备课表''' 54 | filename = user.name 55 | with open('data/'+timec+'/'+'已完成课程', 'rb') as file: 56 | data = pickle.load(file) 57 | data = data[['courseTypeName', 'studentName', 'lessonStartTime', 'lessonEndTime', 'homework', 'recordUrl', 58 | 'teacherComment']] 59 | data = data[data['lessonStartTime'] >= int(time.time() - 604800) * 1000] 60 | data.columns = ['科目', '学生姓名', '课堂开始时间', '课堂结束时间', '课堂作业', '上课视频', '上课情况'] 61 | class_time = [] 62 | for i in data.index: 63 | time_1 = data.loc[i].课堂结束时间 - data.loc[i].课堂开始时间 64 | data.loc[i].课堂开始时间 = uTime(data.loc[i].课堂开始时间) 65 | data.loc[i].课堂结束时间 = uTime(data.loc[i].课堂结束时间) 66 | if time_1 >= 3600000: 67 | time_1 = 2 68 | else: 69 | time_1 = 1 70 | class_time.append(time_1) 71 | print(time_1) 72 | data.insert(4, '课时消耗', class_time) 73 | data.to_excel('./data/' + user.username[-5:] + '_alldream.xlsx', 'w+') 74 | 75 | def getToday(path,flag): 76 | '''参数是当前目录(今日学生信息的名称)下的文件名称 77 | 返回值是一个字符串 包含今日未完成课程信息 78 | 功能:获取当前日期内的上课内容 79 | ''' 80 | if flag: 81 | tm = '近日' 82 | else: 83 | tm = '今日' 84 | str1 = '' 85 | with open('./data/'+path+'/今日课程计划','rb') as file: 86 | data = pickle.load(file) 87 | stlist = data['list'] 88 | nowday = time.strftime("%Y-%m-%d",time.localtime(time.time())) 89 | times=0 90 | if not flag: 91 | for st in stlist: 92 | sttime = uTime(st['startTime']) 93 | if sttime[:10]!=nowday: 94 | continue 95 | times+=1 96 | edtime = uTime(st['endTime']) 97 | stname = st['studentName'] 98 | kemu = st['courseTypeName'] 99 | banji = st['courseHourName'] 100 | str1 += '\t学生:{} \n\t时间:\n\t{}\n\t{} \n\t科目:\t{} \n\t班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 101 | else: 102 | for st in stlist: 103 | sttime = uTime(st['startTime']) 104 | times+=1 105 | edtime = uTime(st['endTime']) 106 | stname = st['studentName'] 107 | kemu = st['courseTypeName'] 108 | banji = st['courseHourName'] 109 | str1 += '学生:{} \n时间:\n{}\n{} \n科目:{} \n班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 110 | 111 | if times >=1: 112 | return '老师您好,\n{}你总共有{}节课\n内容如下\n'.format(tm,times)+str1 113 | else: 114 | return'老师~今天真幸福呀,\n{}你已经完成了所有工作\n当然今天也可能是非常愉快的休息日,\n试试召唤智能机器人,\n \"小小奇\" '.format(tm) 115 | 116 | def getfk(name,timec): 117 | ''' 118 | 参数:查看反馈的学生姓名 以及保存本次数据的文件最内层路径 119 | 返回值:包含匹配到该学生的三条数据 如果先搞改变匹配数据的数量只需要改掉times里的值 120 | 功能实现原始数据的检索 可通过学生姓名直接检索 121 | ''' 122 | with open('./data/'+timec+'/已完成课程','rb') as file: 123 | df = pickle.load(file) 124 | student = df[df['studentName']==name] 125 | msg_list = [] 126 | for i in range(len(student)): 127 | st = student.iloc[i] 128 | remark = st['teacherComment'] 129 | videourl = st['recordUrl'] 130 | star = st['teacherCommentOne'] 131 | stTime = st['lessonStartTime'] 132 | msg = '这节课的开始时间是:\n{}\n这节课里你对孩子评价是:\n{}\n您为孩子打出惊人的{}颗星\n视频链接:\n{}\n--------------------------------------------' 133 | msg_one = msg.format(uTime(stTime),remark,star,videourl) 134 | msg_list.append(msg_one) 135 | return msg_list 136 | 137 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | import time 2 | import re 3 | from selenium import webdriver 4 | from PIL import Image 5 | import requests 6 | from lxml import etree 7 | import json 8 | import os 9 | import pickle 10 | import pandas as pd 11 | from Find import * 12 | from turling import * 13 | import itchat 14 | from Find import * 15 | from ctrip import * 16 | message = readsth() 17 | fsflag = {} 18 | msg_to_u = ['你好呀!现在开启微信机器人啦\n你可以获取数据','正在进入网页\n你可能需要根据图片输入验证码','正在获取cookies请稍等',' 已成功获取到cookies,\n接下来我要把所有的数据进行抓取','数据已经被我们完美的爬取下来\n接下来我们可以对数据进行一个查看或者操作\n今日课程计划\n某某同学的课堂反馈\n备课表的在线生成','\n 今日热点',' 今日热点\n',' 早安\n',' 晚安','很抱歉,未找到任何关于这个学生的历史课堂,请检查学生姓名是否输入错误'] 19 | driver = '' 20 | pic_xpth = '//*[@id="teacher_form"]/div[2]/div/img' 21 | us_xpath = '//*[@id="teacher_form"]/div[2]/input[1]' 22 | ps_xpath = '//*[@id="teacher_form"]/div[2]/input[3]' 23 | yzm_xpath = '//*[@id="teacher_form"]/div[2]/input[4]' 24 | dl_xpath = '//*[@id="teacher_form"]/input[2]' 25 | 26 | def initset(friends): 27 | global fsflag 28 | dealData(friends) 29 | for i in friends: 30 | fsflag[i['UserName']] = {'tuling':False,'duniang':False} 31 | return fsflag 32 | def getnews(): 33 | ''' 34 | 获取IT之家的热点新闻 35 | 36 | :return: 24h热点文章 168h热点文章 37 | ''' 38 | import requests 39 | from lxml import etree 40 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'} 41 | url = 'https://www.ithome.com/' 42 | page = requests.get(url,headers=headers) 43 | page.encoding = 'utf-8' 44 | tree = etree.HTML(page.text) 45 | result = '\n the hot news for 24h \n\n' 46 | week = '\n the top news for 168h \n\n' 47 | for i in range(12): 48 | try: 49 | a = tree.xpath('//*[@id="con"]/div[4]/div[2]/div[3]/div[3]/div[1]/ul/li[{}]/a//text()'.format(i+1))[0] 50 | b = tree.xpath('//*[@id="con"]/div[4]/div[2]/div[3]/div[3]/div[1]/ul/li[{}]/a/@href'.format(i+1))[0] 51 | c = tree.xpath('//*[@id="con"]/div[4]/div[2]/div[3]/div[3]/div[2]/ul/li[{}]/a//text()'.format(i+1))[0] 52 | d = tree.xpath('//*[@id="con"]/div[4]/div[2]/div[3]/div[3]/div[2]/ul/li[{}]/a/@href'.format(i+1))[0] 53 | week+='{}\n{}\n-------------------------\n'.format(c,d) 54 | result+='{}\n{}\n-------------------------\n'.format(a,b) 55 | except: 56 | break 57 | return result,week 58 | def getimg(img_time): 59 | '''得到网页登陆时候所需的验证码图片 60 | driver是全局变量 后面需要通过driver会的cookies 61 | 成功过得到会返回True 62 | ''' 63 | global driver 64 | driver = webdriver.Chrome() 65 | #driver.set_window_size() # 设置浏览器尺寸 66 | driver.maximize_window() 67 | driver.get('https://all-dream.com/front_login.jsp?param=teacher') 68 | time.sleep(5) # 要加载一段时间,留出时间 69 | if driver.title == '傲梦直播': 70 | driver.save_screenshot('.\image\{}.png'.format(img_time)) 71 | yzm_elmt = driver.find_element_by_xpath(pic_xpth) 72 | L = yzm_elmt.location['x'] 73 | T = yzm_elmt.location['y'] 74 | R = L+yzm_elmt.size['width'] 75 | B = T+yzm_elmt.size['height'] 76 | im = Image.open('.\image\{}.png'.format(img_time)) 77 | print(L,T,R,B) 78 | im = im.crop((L,T,R,B)) 79 | im.save('.\image\{}1.png'.format(img_time)) 80 | time.sleep(1) 81 | print(L,T,R,B) 82 | return True 83 | else: 84 | return False 85 | 86 | def dealData(friends): 87 | ''' 88 | 函数的参数是微信好友信息的字典 89 | 微信所有好友的信息抓取 90 | 好友信息中的网名 id 备注 个性签名 城市 性别 91 | 都被保存在了DataFrame数据帧里面 留作备用 92 | 转换好的df被作为返回值返回 93 | 94 | ''' 95 | fs = {} 96 | for i in friends: 97 | fs[i['NickName']] = {'UserName':i['UserName'],'Remark':i['RemarkName'],'Sex':i['Sex'],'qianming':i['Signature'],'city':i['City']} 98 | dfs = pd.DataFrame(fs).T 99 | save(dfs) 100 | def save(dfs): 101 | '''存储所有好友信息到本地''' 102 | with open('./data/好友信息','wb',) as file2: 103 | pickle.dump(dfs,file2) 104 | def log_web(ad,yzm): 105 | '''登陆我们的傲梦网站 106 | 参数是网站登陆所需的验证码 107 | 返回值是网页的driver 108 | ''' 109 | driver.find_element_by_xpath(us_xpath).send_keys(ad[0]) 110 | driver.find_element_by_xpath(ps_xpath).send_keys(ad[1]) 111 | driver.find_element_by_xpath(yzm_xpath).send_keys(yzm) 112 | driver.find_element_by_xpath(dl_xpath).click() 113 | time.sleep(3) 114 | if driver.title == '老师个人中心': 115 | print('网页成功登录') 116 | cook = driver.get_cookies() 117 | print(cook) 118 | return True,cwck(cook) 119 | else: 120 | print('网页登录失败请检查验证码是否识别正确 ') 121 | return False,0 122 | def cwck(cook): 123 | '''转换cookies成为爬虫所需的格式 124 | 列表转换为字典 125 | ''' 126 | cookies = {} 127 | for i in cook: 128 | cookies[i['name']] = i['value'] 129 | return cookies 130 | def getData(cookies): 131 | '''获取傲梦网站的学生信息以及课程信息 132 | 返回获取数据的文件所在目录 133 | 参数是网站所需的cookies 134 | 数据的精细化处理 是数据的检索更加简单 135 | ''' 136 | timec = time.strftime("%Y%m%d%H%M",time.localtime(time.time())) 137 | os.mkdir('./data/'+timec) 138 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} 139 | url = 'https://all-dream.com/rest/hour/queryMyCoursePlan4TeacherNew?free=0&limit=10&random=0.5043750329478451&page=1' 140 | today_class = requests.get(url,headers=headers,cookies=cookies) 141 | today_class = json.loads(today_class.text) 142 | print(today_class) 143 | with open('./data/'+timec+'/今日课程计划','wb') as file: 144 | pickle.dump(today_class,file) 145 | url_list = ['https://all-dream.com/rest/courseManage/queryMyOverCourse4Teacher?limit=10&page={}'.format(i+1) for i in range(10)] 146 | over_all_class = [] 147 | for url in url_list: 148 | over_class = requests.get(url,headers=headers,cookies=cookies) 149 | data_1 = json.loads(over_class.text)['list'] 150 | over_all_class.append(data_1) 151 | key = 1 152 | stOverClass = {} 153 | for ondPage in over_all_class: 154 | for oneClass in ondPage: 155 | stOverClass[key]=oneClass 156 | key+=1 157 | df = pd.DataFrame(stOverClass).T 158 | 159 | with open('./data/'+timec+'/已完成课程','wb',) as file2: 160 | pickle.dump(df,file2) 161 | return timec 162 | 163 | #生成了所有权限关闭的权限 164 | class Friends(): 165 | def __init__(self): 166 | with open('./data/好友信息','rb',) as file2: 167 | self.df =pickle.load(file2) 168 | def isvip(self,fromusername): 169 | '''对于主机微信的响应选择忽略 170 | 在admin中有备案的用户是vip权限《傲梦教师》 171 | 普通永用户都是nomal 172 | ''' 173 | flag = False 174 | try: 175 | name = self.df[self.df['UserName'] == fromusername].index[0] 176 | except: 177 | flag = '主机微信' 178 | name = '两岸猿声啼不住' 179 | if name in [x[:-3] for x in message]: 180 | flag = True 181 | return flag 182 | 183 | class Teacher(): 184 | def __init__(self,username): 185 | self.username = username 186 | self.df = pd.read_pickle('./data/好友信息') 187 | self.name = self.df[self.df['UserName']==self.username].index[0] 188 | for i in message: 189 | if self.name in i: 190 | self.admin = message[i] 191 | print(self.name) 192 | def getcookies(self): 193 | ''' 194 | 验证码图片的微信发送 195 | 验证码保存在本地 文件名由当前时间命名 196 | 时间作为发送信息的图片名 197 | ''' 198 | self.img_time = time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time())) 199 | if getimg(self.img_time): 200 | return self.img_time 201 | def svtime(self,timec): 202 | self.timec = timec 203 | 204 | class Nomal(): 205 | '''只要是主机微信的好友都是此类''' 206 | def __init__(self,username): 207 | self.flag = False 208 | self.username = username 209 | def logdata(user): 210 | driver.close() 211 | itchat.send_msg(msg_to_u[3], user.username) 212 | timec = getData(user.cookies) 213 | itchat.send_msg(msg_to_u[4], user.username) 214 | return timec 215 | 216 | class newTeacher(): 217 | def __init__(self,user): 218 | self.id = user.username 219 | self.name = self.getname() 220 | self.num = self.getnum() 221 | def getname(self): 222 | df = pd.read_pickle('./data/好友信息') 223 | return df[df['UserName']==self.id].index[0] 224 | def getnum(self): 225 | df = pd.read_pickle('./data/admin') 226 | if len(df)<10: 227 | result = '00'+str(len(df)) 228 | elif len(df)<100: 229 | result = '0'+str(len(df)) 230 | elif len(df) < 1000: 231 | result = str(len(df)) 232 | return result 233 | 234 | return len(df) 235 | def savemsg(self): 236 | a = pd.read_pickle('./data/admin') 237 | a[self.name+str(self.num)] = [self.admin,self.password] 238 | with open('./data/admin','wb') as file: 239 | pickle.dump(a,file) 240 | print('信息录入成功') 241 | @itchat.msg_register(itchat.content.TEXT) 242 | def text(msg): 243 | global fsflag,timec,message 244 | message = readsth() 245 | # print(message) 246 | friend = Friends() 247 | '''控制台的函数控制 248 | 信息的持续接收 249 | ''' 250 | #print(friend.df) 251 | fromusername = msg['FromUserName'] 252 | #此处可以增加管理员微信 253 | if msg['Text']=='初始化~': 254 | friends = itchat.get_friends(update=True)[1:] 255 | fsflag = initset(friends) 256 | return '初始化成功' 257 | elif '低价机票' in msg["Text"]: 258 | return getLowerAir(msg["Text"].replace('的低价机票','')) 259 | #图灵机器人模式 260 | elif msg['Text'] in ['开始','start']: 261 | fsflag[fromusername]['tuling'] = 'True' 262 | itchat.send_msg('ok~ next begin chat with Small~ Q from tu ling',fromusername) 263 | elif fromusername in fsflag: 264 | if fsflag[fromusername]['tuling']: 265 | if msg['Text'] in ['退出','exit']: 266 | fsflag[fromusername]['tuling'] = False 267 | return 'maybe! this the time leave u .Qqz' 268 | else: 269 | return jqr(msg['Text']) + "." 270 | elif fsflag[fromusername]['duniang']: 271 | if msg['Text'] == '退出百度': 272 | fsflag[fromusername]['duniang'] = False 273 | return 'see you my baby' 274 | else: 275 | return baidu(msg['Text']) + "." 276 | #度娘模式 277 | elif msg['Text'] in ['度娘','百度一下']: 278 | fsflag[fromusername]['duniang'] = 'True' 279 | itchat.send_msg('ok~ next begin chat with Small~ Q and baidu zhidao',fromusername) 280 | elif msg['Text'] == '热点': 281 | day,week = getnews() 282 | print(day,'\n',week) 283 | itchat.send_msg(day, fromusername) 284 | itchat.send_msg(week, fromusername) 285 | 286 | elif friend.isvip(fromusername): 287 | user = Teacher(fromusername) 288 | user.msg_1 = msg 289 | if user.msg_1['Text'] == '获取数据': 290 | itchat.send_msg('请耐心等候,小爬虫正在快吗加鞭获取数据', user.username) 291 | shot_tm = user.getcookies() 292 | itchat.send_msg(msg_to_u[1],user.username) 293 | itchat.send_image('.\image\{}1.png'.format(shot_tm),user.username) 294 | elif user.msg_1['Text'] in ['help', '帮助']: 295 | itchat.send_image('./image/teacher.png',user.username) 296 | elif re.findall('\d+',user.msg_1['Text']): 297 | if len(re.findall('\d+',user.msg_1['Text'])[0])==4: 298 | user.yzm = re.findall('\d+',user.msg_1['Text'])[0] 299 | suss,user.cookies = log_web(user.admin,user.yzm) 300 | if suss: 301 | timec = logdata(user) 302 | bkb(user, timec) 303 | else: 304 | itchat.send_msg('so sad~ 验证码输入错误,请重新获取数据', user.username) 305 | driver.close() 306 | elif user.msg_1['Text'] in '近日课程计划': 307 | print(timec) 308 | user.closetoday = getToday(timec,True) 309 | itchat.send_msg(user.name[:-4]+user.closetoday,user.username) 310 | 311 | elif user.msg_1['Text'] in '今日课程计划': 312 | print(timec) 313 | user.today = getToday(timec,False) 314 | itchat.send_msg(user.name[:-4]+user.today,user.username) 315 | elif user.msg_1['Text'][-4:]=='课堂反馈': 316 | ms = getfk(user.msg_1['Text'][:-4],timec) 317 | print(user.msg_1['Text'][:-4]) 318 | if len(ms)>=1: 319 | itchat.send_msg('已为您匹配到{}个结果'.format(len(ms)),user.username) 320 | for ms_1 in ms: 321 | itchat.send_msg(ms_1,user.username) 322 | else: 323 | itchat.send_msg(msg_to_u[-1],user.username) 324 | for msg in ms: 325 | itchat.send_msg(ms,user.username) 326 | 327 | elif '备课表' in user.msg_1['Text']: 328 | itchat.send_file('./data/' +user.username[-5:]+ '_alldream.xlsx',user.username) 329 | else: 330 | nomal = Nomal(msg['FromUserName']) 331 | print('创建聊天') 332 | nomal.msg = msg 333 | if nomal.msg['Text'] in ['help','帮助']: 334 | itchat.send_image('./image/nomal.png',nomal.username) 335 | if nomal.msg['Text'] == '注册傲梦讲师': 336 | global teacher 337 | teacher = newTeacher(nomal) 338 | itchat.send_msg('{}你好,现在需要录入你的傲梦网站的账号密码,请严格按照以下格式发送账号和密码(用一个空格隔开,前后不要加空格)如:”19091956102 12345“'.format(teacher.name),nomal.username) 339 | elif nomal.msg['Text'] == '初始化': 340 | initset() 341 | try: 342 | if nomal.username == teacher.id: 343 | print(nomal.msg['Text']) 344 | if len(nomal.msg['Text'].split(' '))==2 and len(nomal.msg['Text'].split(' ')[0])==11: 345 | print(nomal.msg['Text'].split(' ')[0]) 346 | teacher.admin = nomal.msg['Text'].split(' ')[0] 347 | teacher.password = nomal.msg['Text'].split(' ')[1] 348 | itchat.send_msg('你确认账号密码无误?有误的话请重新注册无误请回复:信息无误请录入',nomal.username) 349 | elif nomal.msg['Text'] == '信息无误请录入': 350 | teacher.savemsg() 351 | itchat.send_msg('录入成功',teacher.id) 352 | except: 353 | ... 354 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # personal-wechatplus 2 | 个人微信的功能集成(获取热点新闻,自动回复,爬虫控制,傲梦编程教师端数据的自动抓取和检索) 3 | 4 | #### 代码框架 5 | 6 | start.py:脚本的代码入口文件,运行时候需要进行微信的扫码 7 | 8 | run.py: 根据微信聊天信息的内容控制脚本的运行控制 9 | 10 | find.py:对数据(data中的已完成课程和未完成课程)进行清洗 11 | 12 | tuling.py :图灵机器人的接口调用,根据传入的数据返回的数据进行格式化整理返回 13 | 14 | data:存放爬虫爬取到的学生上课数据(已完成和未完成) 15 | 16 | img:存放爬虫过程中的二维码图片 17 | 18 | run.***.pyd对run 代码进行闭源处理的结果 19 | 20 | start.bat : 快捷开始的批处理文件,双击便能运行本系统 21 | 22 | 23 | 24 | #### 使用说明 25 | 26 | ##### 使用本人已经搭建好环境的使用说明 27 | 28 | ​ 1:添加本人的主机微信号(Chenphoun) 29 | 30 | ​ 2:普通权限添加后直接发送消息就可以使用 31 | 32 | ​ 3:傲梦的老师们需要进行以下操作录入个人信息 33 | 34 | 在与主机微信的聊天窗口直接发送指令<注册傲梦讲师>,接下来会收到账号和密码的输入格式说明,你只需要输入相应的个人账号和密码(**注意要一块输入,且账号和密码之间要用一个空格隔开**) 35 | 36 | 例如<**18091956102 zheshimima**>正确格式输入账号密码之后,还需要确认一下账号密码无误,回复<**信息无误请录入**> 出现录入成功的回复之后,就可以正常使用教师权限的功能了。 37 | 38 | ​ 4:微信端口令说明: 39 | 40 | ​ I:图灵机器人权限打 开始 or start 41 | 42 | ​ II:图灵机器人权限关闭 退出 or exit 43 | 44 | ​ III: 教师获取本日数据 获取数据 45 | 46 | ​ **注意:以下生成备课表等功能都需要先成功获取到数据之后才可以使用** 47 | 48 | ​ IV:获取未完成课时的信息检索 今日 or 近日 49 | 50 | ​ V:获取已完成课堂情况: 备课表 or 学生姓名+课堂反馈(如:陈奇课堂反馈) 51 | 52 | ​ VI: 获取IT之家本日和本周的hot文章 53 | 54 | 注意:**图灵机器人权限打开的时候是只能和进行聊天,新闻数据,笑话,天气等功能的使用,要想获取IT之家的热点和傲梦数据,需要退出图灵机器人权限才能使用,** 55 | 56 | #### 自行搭建环境说明 57 | 58 | ​ 1:clone本项目到本地,(最好是服务器环境,不然意义不大。我使用的是阿里云服务器,) 59 | 60 | ​ 2:改变bat批处理文件的路径(以编辑方式打开start,bat,把第二行python 之后 的文件路径换成你clone之后的start.py的文件路径) 61 | 62 | ​ 3:安装所需的模块和方法 63 | 64 | **itchat requests lxml pandas PIL selenium<需要配置chromedriver驱动> re baidu-aip** 65 | 66 | ​ 4:运行,双击批处理文件,**start.bat**之后会弹出微信登录二维码,让你的主机微信扫描登录,之后出现成功登录之后,就可以使用任何主机微信好友的账号进行功能的使用 67 | 68 | **欢迎完善功能,和提出建议** 69 | 70 | # 论文: 71 | 72 | 本课题研究的起因来源于现代人工作生活中的一些痛点,重复的手机软件使用以及工作数据被PC端的电脑所局限,抱着简化生活和工作内容的目的决定开发出一个简洁且不受使用限制的脚本,这一设计理念和Tim Peter 的 The Zen of Python不谋而合,而国内的应用软件中,微信无疑是和本脚本价值观及发展防线最为契合的一个。本脚本,适用于大多数的微信用户,并且对于本人公司的同事,脚本集成了更为方便的工作数据检索功能。本脚本采用python语言,因为python具有最为丰富的外接库,可以更容易解决大多数的项目功能难点。实现了网络爬虫的一些具体实例,并且把爬虫的功能封转在微信个人号之上,通过微信的聊天信息,控制爬虫流程的控制,极大的改善了网络的使用体验,改变了传统软件冗余的现状,具有极大的灵活性和实验价值 73 | 74 | 75 | 76 | 绪论 77 | 78 | 1.1编写目的 79 | 80 | ​ 处于信息时代的我们,每天接受这无数的信息轰炸,现代人的信息接受量达到了人类历史的新高度,但是,当我们接受信息的过程所花费时间并不是完全等同于我们使用电脑或手机设备的时间,这期间我们需要对互联网中的数据进行人为的筛选和检索,在这里,我们把获取筛选数据的时间称之为无助且必要时间。手机,作为现代人最常使用的移动设备,无疑便利了我们的生活,但同时,如果我们给他集成过多的软件,首先找到并打开软件的过程就需要很长的时间,并且一部手机的负载是有限的,过大的资源占用之下必将导致我们手机设备的卡顿,这严重影响我们的手机使用体验。例如当我们想知道今天某座城市的天气,我们需要打开固定的天气咨询类软件,通过时间和城市的选择获得我们想要的数据,这种繁琐的信息交互模式无疑不是最好的选择。而本系统的目的就是: 81 | 82 | 把每天被各种应用软件奴役的人从重复性的工作学习娱乐中解脱出来,使人们在信息同步的前提下有更多可以自由支配的时间。在不影响工作质量甚至会提高工作效率的前提下实现工作信息的同步和工作内容的完善。在功能不打折扣,时间陈本不增加的基础上完成手机使用软件的精简化,能够根据个人偏好实现信息的做针对性同步。例如,当我们想知道哪座城市的天气的时候,或者今日的热点新闻,热点话题,只需要简单的一句口令,我们需要的内容就可以铺陈眼前,功能的智能化和量身定做化变得史无前例的便捷,在最小程度上增加手机的资源占用下极大的压缩玩手机期间的无助且必要时间。 83 | 84 | 1.2系统应用背景 85 | 86 | 近年来,人们花费在电脑和手机上的时间越来越多,手机的软件更是层出不穷,据美通社2019年1月17号的报道显示,全球用户每天使用手机5.1小时,爱尔兰用户每天使用时长更是高达8.4小时,而人们花费如此多的时间都用来做了什么呢?工作,社交,新闻,短视频,游戏。但是根据对周围人群的统计我发现,在重复的浏览过程中,包含了很多重复且毫无价值的信息来源,于是,人们打开各式各样的软件浏览着千篇一律的内容,无意间消磨了大量的工作学习时间,于是,我打算开发一款可以自动帮我们检索信息的脚本,以微信个人号的方式为我们推送各种量身定做且经过处理的数据,这些同样适用于工作效率的提高,以在线教育讲师的工作为例,每日的课时信息,学生学习状况的整理,周期内的工作总结,都可以在这个脚本下集成。 87 | 88 | 在中国,微信的出现,无疑改变了我们的社交途径和方式,作为中国人最常用到的应用软件,它因为简洁,快捷,被人们所热爱,每天我们都会或多或少的通过微信和远方的朋友聊天,而我们的脚本正是集成在这个便捷的载体之上。就像正常的聊天一样,发送信息,微信机器人就像我们的私人助手一样,快速的给我们想要的内容反馈。 89 | 90 | 1.3研究内容 91 | 92 | ​ 本课题的主要研究内容在于多个脚本功能的集成及相互调用,功能主要包括基于itchat模块实现微信特定好友信息的持续获取和响应,基于reqursts模块实现异步加载数据的获取和基于pandas模块的数据清洗及检索,还有基于pygal模块的数据可视化模型的建立,以及基于pickle的文件数据的本地写入及读取,除此之外,我们需要积极研究的还有,如何管理不同权限的用户信息的功能分布,如何处理两种状态下的连天模式,即适用于普通用户的机器人聊天模式和只适用于高级权限的工作信息的聊天模式。 93 | 94 | 95 | 96 | 97 | 2需求分析 98 | 99 | 2.1功能需求 100 | 101 | 2.1.1用户体验 102 | 103 | ​ 用户能够在请求之后尽快时间得到响应,至少比用户正常打开软件时候的时间成本低,对于手机的资源占用要尽可能的少,至少要比正常使用手机获取信息的资源占用要小,使用本脚本的学习成本尽可能的低,对于容易出错的部分要实现简洁但清晰的说明指导,获取的信息要准确并明了,信息的获取需要符合使用者的信息需求偏好该脚本需要能在通常网络环境下随时响应, 104 | 105 | 2.1.2多功能协调 106 | 107 | ​ 微信个人号的聊天指令能够完成对各种功能的调用,相互之间的功能独立存在且相互联系, 108 | 109 | 2.1.3数据的格式及传递 110 | 111 | ​ 响应的数据简单明了。比如,课程计划,应包含学生姓名,上课时间,所属科目,学生的反馈,应包含学生姓名,课程进度,课程时间,教师评价,以及上课视频等内容。这里的大部分的内容在聊天过程中都是以文本格式传递的,学生的备课表需要以excel表格的形式返回。 112 | 113 | 2.1.4 功能 114 | 115 | ​ 聊天有两种状态,基于图灵机器人的闲聊状态和集成的工作数据同步以及实时热点新闻的同步状态。 116 | 117 | ​ 聊天机器人,实现微信聊天的自动回复,能够实时自动回复,可以接受并响应多种形式的微信消息,天气,火车信息等功能的调试及正常使用。 118 | 119 | ​ 集成爬虫,在线教育平台的数据抓取和检索,能够根据指令完成,当前工作日待完成课程,以及当前工作日近期课程计划,已完成课程中某位学生的课程进度以及课堂表现,以及根据爬虫的数据进行excel表格统计等功能,除此之外包括但不限于每日热点新闻,舆论热点等信息的爬取和检索 120 | 121 | ​ 支持多用户并发,能够微信账号对特定用户附加附加高级权限的功能,其他用户也能够通过指令对用户本人的数据进行爬取和检索。 122 | 123 | 2.2非功能需求 124 | 125 | 2.2.1安全性 126 | 127 | ​ 账号安全,用户的工作账号安全和信息安全必须得到保证。该项目的代码需要进行加密,以防止攻击代码被人利用。 128 | 129 | 130 | 131 | 2.2.2稳定性 132 | 133 | ​ 脚本需要在上线后实时响应,不能出现中途断线或者请求不响应的情况。对于各种异常可以扑捉,并做出处理。 134 | 135 | 2.2.3运行环境及设备准备 136 | 137 | 本操作脚本需要用到服务器,这里我们的实例是阿里云ecs云服务器,除此之外,我们需要一个用于信息整合和内容回复的微信个人号(下面称之为主机微信号),用户只需要是添加过主机个人号好友的微信个人号, 138 | 139 | 系统版本:Windows Server 2012 R2 数据中心版 64位 140 | 141 | 编辑器:pycharm 142 | 143 | 服务器运行:command命令行 144 | 145 | Python环境 python 3.7.0 146 | 147 | Lxml 4.2.5 148 | 149 | pandas 0.23.4 150 | 151 | Pillow 5.2.0 152 | 153 | selenium 3.141.0 154 | 155 | itchat 1.3.10 156 | 157 | pip 10.0.1 158 | 159 | 160 | 161 | 162 | 3概要设计 163 | 164 | 3.1基本模块 165 | 166 | ​ 本系统设计主要包含以下几个基本模块,自动获取数据,对获取到的大量数据进行数据清洗及处理,数据的传递,微信接口的架构, 167 | 168 | 3.1.1获取数据 169 | 170 | ​ 获取服务器运行的微信号的好友信息, 171 | 172 | ​ 获取傲梦教师端的课程数据数据,课程数据包含的内容有已完成课程,未完成课程,具体数据内容如下图所示, 173 | 174 | ​ 获取IT之家的高阅读量的文章标题及链接, 175 | 176 | ​ 根据接受信息获取图灵机器人的信息反馈 177 | 178 | 3.1.2数据清洗及处理 179 | 180 | ​ 通过对傲梦网站数据的分析研究,对爬取到的原始数据进行结构化的处理, 181 | 182 | ​ 通过对数据的筛选生成excel表格,和格式化的富文本 183 | 184 | 3.1.3微信接口的架构 185 | 186 | ​ 实时接受微信消息 187 | 188 | ​ 根据微信消息执行响应的模块, 189 | 190 | ​ 根据各个模块的响应精准返回模块中生成的数据结果 191 | 192 | ​ 根据不同的用户实现权限分级, 193 | 194 | ​ 对于不同的用户权限进行功能细化 195 | 196 | 3.1.4脚本实现预期效果 197 | 198 | ​ 因为本系统的用户在1000人以内且都是微信好友教师权限的用户也只有不到100人,所以对于用户身份验证的策略本系统拟采取本地初始设置,即对于普通权限的用户只需要是主机微信号的好友就可以使用,教师权限需要向管理员提交傲梦编程1对1少儿编程培训网站教师端的账号和密码经过管理员校验之后才能使用此权限的功能,普通用户只需要在和主机微信的聊天窗口下发送相应指令就可以得到响应,指令的帮助文档根据用户权限不同返回,如下图所示为普通用户的使用文档。普通用户以及教师的帮助文档如图 3.1 所示 199 | 200 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.gif) 201 | 202 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.gif) 203 | 204 | 图 3.1帮助文档 205 | 206 | 3.2流程图及说明 207 | 208 | ​ 如下图所示为本操作系统的模块设计流程图 209 | 210 | ​ 我们的脚本会持续监听微信消息的接收,当一条信息被接受,脚本会根据这个人的权限分流,以教师权限的用户为例,如果此时该用户直接使用了获取数据的指令,脚本会自动去该教师的傲梦编程教师端网站上获取该老师的数据,接下来该用户就可以直接通过口令检索出自己所需的数据。 211 | 212 | 脚本运行流程图3.2所示 213 | 214 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.gif) 215 | 216 | 图3.2 脚本运行流程示意图 217 | 218 | 3.3 关键技术介绍 219 | 220 | 3.3.1网络爬虫 221 | 222 | ​ 网络爬虫,也称为"网络蜘蛛",通过网页的链接地址搜索网页,从网站的某个页面开始,读取网页的内容,在网页中查找其他链接地址,然后通过链接地址找到下一个网页。这是一种继续循环的技术,直到根据某些策略爬网互联网上的所有网页。他可以快速捕获网站上可见的数据,是一种快速准确地获取数据的技术。目前不同的编程语言对爬虫都有相关的一些技术支持,如下表编程语言爬虫技术映射表编程语言主流爬虫框架(库)如表3.1所示 223 | 224 | 表3.1编程语言于主流爬虫库对照表 225 | 226 | | 编程语言 | 主流爬虫框架(库) | 227 | | ---------- | ------------------------------ | 228 | | C++ | open-source-search-engine | 229 | | Java | Request pyspiders Scrapy | 230 | | Python | Gecco WebMagic Spiderman | 231 | | JavaScript | x-ray js-crawler scraperjs、 | 232 | | C# | Abot | 233 | | PHP | php-spider | 234 | | Ruby | nokogiri | 235 | | Go | Go_spider,scrape | 236 | 237 | 238 | 239 | 3.3.2 python 240 | 241 | ​ Python是一种解释型面向对象的动态类型的开源的计算机程序设计语言,他因为语法简单功能强大以及且具有丰富的扩展库被人们所热爱,是轻量级的快速程序开发的不二之选 242 | 243 | 3.3.3 requests 244 | 245 | ​ Requests是一个以HTTP for Humans(给人用的http库)为宣言的网络编程库,他能够使用最为简洁明了的语法实现网络操作,提交请求获取响应,从来没有如此简单。在使用它的时候,你会惊叹,这才是python代码该有的样子。 246 | 247 | 3.3.4信息加密 248 | 249 | 信息加密技术是利用数学或物理手段,对电子信息在传输过程中和存储体内进行保护,以防止泄漏的技术。 250 | 251 | 3.3.5 pandas 252 | 253 | ​ pandas 是基于 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的[数据模型](https://baike.baidu.com/item/数据模型/1305623),提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。 254 | 255 | 3.3.6 xpath 256 | 257 | ​ XPath即为[XML](https://baike.baidu.com/item/XML)路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。 258 | 259 | XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于[XPointer](https://baike.baidu.com/item/XPointer)与[XSL](https://baike.baidu.com/item/XSL)间的语法模型。但是XPath很快的被开发者采用来当作小型[查询语言](https://baike.baidu.com/item/查询语言) 260 | 261 | 262 | 263 | 3.3.7 itchat 264 | 265 | itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单。使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人。当然,该api的使用远不止一个机器人,比如[这些](http://python.jobbole.com/86532/)。该接口与公众号接口[itchatmp](https://github.com/littlecodersh/itchatmp)共享类似的操作方式,学习一次掌握两个工具。 266 | 267 | 如今微信已经成为了个人社交的很大一部分,这个项目能够帮助你扩展你的个人的微信号、方便自己的生活。 268 | 269 | 3.3.9 webdriver 270 | 271 | WebDriver是一种用于自动化web应用程序测试的工具,特别是用于验证它们是否按预期工作。它的目标是提供一个友好的API,易于探索和理解,比Selenium-RC (1.0) API更容易使用,这将有助于使您的测试更容易阅读和维护。它不依赖于任何特定的测试框架,因此它可以在单元测试项目中或从简单的旧的“main”方法中使用,有了他,我们可以让我们的脚本模拟大多数的浏览器操作。 272 | 273 | 3.3.10图灵机器人 274 | 275 | 图灵机器人开放平台是北京光年无限科技旗下的智能聊天机器人开放平台。通过图灵机器人开放平台,用户可快速构建自己的专属聊天机器人并为其添加丰富的机器人云端技能 276 | 277 | 3.3.11 AJAX异步加载 278 | 279 | Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。 280 | 281 | 使用 JavaScript 向服务器提出请求并处理响应而不阻塞用户核心对象[XMLHttpRequest](https://baike.baidu.com/item/XMLHttpRequest)。通过这个对象,您的 JavaScript 可在不重载页面的情况与 Web 服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效 282 | 283 | 3.3.12 pickle 284 | 285 | ​ 在程序代码中中,我们常常需要把程序中的某些数据模型存储起来,这样在进行其他模块使用时直接将模型读出,而不需要去构建模型,这样就大大节约了时间。Python提供的pickle模块就很好地解决了这个问题,它可以序列化对象并保存到磁盘中,并在需要的时候读取出来,任何对象都可以执行序列化操作。 286 | 287 | 3.3.13 正则表达式 288 | 289 | 正则表达式是对[字符](https://baike.baidu.com/item/字符)串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。 290 | 291 | 3.3.14 cookies 292 | 293 | 基于 Internet的各种服务系统应运而生,建立商业站点或者功能比较完善的个人站点,常常需要记录访问者的一些信息;论坛作为 Internet发展的产物之一,在 Internet 中发挥着越来越重要的作用,是用户获取、交流、传递信息的主要场所之一,论坛常常也需要记录访问者的一些基本信息(如身份识别号码、密码、用户在 Web 站点购物的方式或用户访问该站点的次数)。目前公认的是,通过 Cookie 和 Session 技术来实现记录访问者的一些基本信息 294 | 295 | 3.3.15百度AI人工智能平台 296 | 297 | 提供全球领先的语音、图像、NLP等多项人工智能技术,开放对话式人工智能系统、智能驾驶系统两大行业生态,共享AI领域最新的应用场景和解决方案,提供了很多可供开发者免费使用的人工智能接口。 298 | 299 | 3.3.16 批处理文件 300 | 301 | 批处理文件(batch file)包含一系列 DOS命令,通常用于自动执行重复性任务。用户只需双击批处理文件便可执行任务,而无需重复输入相同指令。编写批处理文件非常简单,但难点在于确保一切按顺序执行。编写严谨的批处理文件可以极大程度地节省时间,在应对重复性工作时尤其有效。 302 | 303 | 304 | 305 | 306 | 4详细设计 307 | 308 | 4.1功能需求和程序的关系 309 | 310 | 再本操作系统中,微信聊天窗口作为我们的运行页面,所以微信消息数据的实时同步是保证代码正常运行的关键因素,获取到微信聊天信息的时候,这个数据包含了,信息的发送者,信息的内容(文本),以及该聊天信息的特定id。这个数据需要和我们程序本身的初始化数据进行判断,得出发送信息的身份对应用户权限,以及当前聊天模式,有了这个权限和模式,系统便可以根据用户的权限和信息内容明确用户的意向,聊天机器人模式下,系统根据用户的发送的内容去图灵机器人接口中获取响应,然后把这个响应返回给我们的用户,从而实现聊天机器人的功能,通常模式下,用户保持微信聊天正常状态,但是当用户身份为已经赋予权限的傲梦教师身份的时候,用户只需通过特定指令控制程序的走向,例如,当用户通过特定指令表示要获取当前时间的热点新闻,系统便会同过调用获取实时热点新闻的接口,获取到当前网站中的热点内容,本系统的设计模式采用,分布式扁平化设计理念,每一个新的指令进入,就对应新的脚本需要被执行,低内聚高耦合,模块之间只存在较少的联系,且模块之间互不干扰。 311 | 312 | 4.2接口设计 313 | 314 | 4.2.1微信信息的获取 315 | 316 | 在本脚本中,微信的聊天框可以说扮演了一个用户界面的角色,用户和服务器的一切交互都是通过微信信息的发送来完成的,所以脚本如何去获取微信好友的信息就成了本脚本第一个要解决的实际问题,itchat作为一个开源的微信个人号接口,让数据的传递变得空前的简洁,他可以完美模拟用户登录网页端的微信,实现代码如图4.1 所示 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg) 325 | 326 | 图4.1 微信消息实时获取示意图 327 | 328 | 运行结果如下图4.2所示: 329 | 330 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg) 331 | 332 | 图4.2 微信登录成功终端显示效果图 333 | 334 | 通过运行代码首先会出现微信登录所需的扫码,程序模拟登录了网页版的主机微信号。出现login successfully as 微信名字样表示登陆成功,msg_register函数实现了各种微信信息的实时获取,此处在text函数中可以把文本格式的信息内容获取到,经过对msg微信聊天信息研究发现,脚本所需的信息来源用户,信息内容,都可以直接在msg中获得。如下图代码和运行结果如图4.3所示 335 | 336 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg) 337 | 338 | 图4.3微信消息数据解析代码示意图 339 | 340 | 341 | 342 | 343 | 344 | 运行结果如图4.4所示 345 | 346 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg) 347 | 348 | 图4.4 微信聊天数据解析运行效果图 349 | 350 | 351 | 352 | 4.2.2新闻热点的爬取 353 | 354 | 对于舆论热点,本脚本拟获取IT之家版面中的如下图框选内容所示中的最热排行和周榜内容的网站示意图,如图4,5所示 355 | 356 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg) 357 | 358 | 图4.5 IT之家网站主页 359 | 360 | ​ 通过对数据的研究,发现本数据可以直接在网站的html代码中找到,如图4.6所示 361 | 362 | 363 | 364 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg) 365 | 366 | 图4.6 IT之家网站热点新闻网页代码示意图 367 | 368 | 369 | 370 | 通过数据比对,发现a标签中的文本就是文章的标题,而a标签的属性herf中保存着该热点新闻的url地址,要想抓取这个网页版的IT之家版面,需要模拟通过request模块向IT之家网站服务器发送请求,获取到该页面的内容并通过xpath把所属标签中的内容精确检索。且为防止被网站的反爬虫机制限制甚至拒绝响应,我们需要把爬虫程序伪装成浏览器,即提交请求的时候附加上请求头里面的关键内容,浏览器请求头内容如图4.8所示 371 | 372 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg) 373 | 374 | 图4.8 浏览器请求网页的请求头内容 375 | 376 | 在红框中的user-agent中,包含了浏览器兼容的内核版本,请求电脑的操作系统和位数。有了这些数据,我们的爬虫脚本就可以伪装成一个浏览器请求,从而避免了网站的反爬机制可能带来的问题,整体的实现思路如下,首先,用requests库的get方法发送请求,对于接受的的响应一个html网页代码进行树形结构的解析,然后通过xpath标签路径获取到指定内容的数据,这里需要通过网页代码结构的熟悉和研究找出多个标签之间的内在联系,使用xpath表达式快速检索到所需的数据, 377 | 378 | 请求代码如图4.9所示 379 | 380 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg) 381 | 382 | 图4.9 模拟请求IT之家官网获取响应的代码示意图 383 | 384 | Xpath获取特定标签的代码如图4.10所示 385 | 386 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image024.jpg) 387 | 388 | 图4.10 xpath获取特定标签内容的代码示意图 389 | 390 | 运行结果如图4.11所示: 391 | 392 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image026.jpg) 393 | 394 | 图4.11 IT之家数据获取运行结果终端效果图 395 | 396 | 4.2.3图灵机器人接口设计 397 | 398 | 图灵机器人的接口创建只需要登录网站, 399 | 400 | 创建一个机器人对象,这里的我们需要进行机器人的一个初始化设置,聊天机器人的初始化界面如图4.12所示 401 | 402 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image028.jpg) 403 | 404 | 图4.12 图灵机器人的应用创建网站示意图 405 | 406 | 机器人创建完毕之后,设置他的终端接入方式,图灵机器人的接口,需要根据不同的发送内容,得到相应的信息反馈,图灵机器人的接口是一个成熟并且完善的接口,这里的接口在本脚本中 拟选择使用api接入,因为在聊天机器人的基础上还有集成教师应用等有针对性的功能,如果选择直接个人号接入势必会造成接口的调用冲突,影响用户的使用体验。并且使用api接入,这里会让我们的脚本更加灵活,可以对图灵机器人做出更多针对性的调整。选择api接入如图4.13所示 407 | 408 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image030.jpg) 409 | 410 | 图4.13 图灵机器人接口选择示意图 411 | 412 | 接下来是代码实现,依旧使用requests模块对网页版的图灵机器人数据进行抓取,不同的是,这里我们需要通过提交聊天信息才能获取到图灵机器人的响应,所以此处的请求方式变成了post,代码实现如图4.14所示 413 | 414 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg) 415 | 416 | 图4.14 图灵机器人数据获取代码示意图 417 | 418 | 4.2.4 百度人工智能平台图片文字识别 419 | 420 | 百度人工智能平台的应用创建细节如图4.15所示 421 | 422 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image034.jpg) 423 | 424 | 图 4.15 百度人工智能平台图片文字识别接口设置截图 425 | 426 | 百度人工智能平台的图片识别相应代码如图4.16所示 427 | 428 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image036.jpg) 429 | 430 | 图4.16百度人工智能如图片文字识别接口实现代码 431 | 432 | 4.2.5傲梦官方网站教师端数据的获取 433 | 434 | ​ 网站数据的抓取是本脚本的难点,因为数据的复杂度远远要超过以上的两种数据,高复杂性带来了更多的处理数据的障碍,首先,我们获取到的数据是需要在登陆状态下的,所以在发送请求的时候除了反爬虫必须的useragent还需要验证身份信息的cookies,这里所以脚本必须要在登陆状态下获取到cookies才能成功请求到网页上的数据,这里就需要用到selenium库,他能够使用脚本对网页进行完全模拟人的操作,经过对傲梦编程网页的登录页面分析如下图所示,傲梦网页主页示意图如图4.17所示 435 | 436 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image038.jpg) 437 | 438 | 图4.17 傲梦编程网站登录页面 439 | 440 | 网址https://all-dream.com/front_login.jsp?param=tacher之后。本需要完成的工作分别是,输入账号和密码,输入验证码,点击登录,如果信息无误,登录成功后,就可以用selenium中的内置方法获取到登陆状态下的网页cookies,账号和密码基本不会改变,主要的问题此时出在了验证码的识别上,首先需要从页面拿到验证码的图片信息,因为验证码是每次请求都不同的,所以要保证webdriver操作页面的时刻的验证码图片信息获取到,此处可以采用webdriver的内建方法save_screenshot对验证码页面进行截图,并且还需要配合PIL的图片操作库,对截取的图片进行剪裁处理。实现代码如下所示: 441 | 442 | def getimg(img_time): 443 | '''得到网页登陆时候所需的验证码图片 444 | driver是全局变量 后面需要通过driver会的cookies 445 | 成功过得到会返回True 446 | ''' 447 | global driver 448 | driver = webdriver.Chrome() 449 | \#driver.set_window_size() # 设置浏览器尺寸 450 | driver.maximize_window() 451 | driver.get('https://all-dream.com/front_login.jsp?param=teacher') 452 | time.sleep(5) # 要加载一段时间,留出时间 453 | if driver.title == '傲梦直播': 454 | driver.save_screenshot('.\image\{}.png'.format(img_time)) 455 | yzm_elmt = driver.find_element_by_xpath(pic_xpth) 456 | L = yzm_elmt.location['x'] 457 | T = yzm_elmt.location['y'] 458 | R = L+yzm_elmt.size['width'] 459 | B = T+yzm_elmt.size['height'] 460 | im = Image.open('.\image\{}.png'.format(img_time)) 461 | print(L,T,R,B) 462 | im = im.crop((L,T,R,B)) 463 | im.save('.\image\{}1.png'.format(img_time)) 464 | time.sleep(1) 465 | print(L,T,R,B) 466 | return True 467 | else: 468 | return False 469 | 470 | 此时图片获取到之后识别成了又一个需要解决的问题,本系统采取两种识别方案交替进行,首先会使用百度的人工智能平台提供的图片文字识别策略,但是不可避免的问题是自动识别具有一定的误差,所以不能保证识别的百分之百成功率,所以这里拟采取图片通过主机微信发送给用户让用户来人工识别,这样图片的识别就能够迎刃而解。以下是两种解决方案状态下的代码线上运行效果。 471 | 472 | 使用百度ai人工智能开放平台的解决方案,通过调用接口实现验证码的基本识别,实现代码如下所示: 473 | 474 | def aiYzm(filename): 475 | ''':param filename: 表示图片的文件路径return: 返回图片经过百度开发识别的结果,如识别失败的话直接返回false ''' 476 | from aip import AipOcr 477 | """ 你的 APPID AK SK """ 478 | APP_ID = '16190824' 479 | API_KEY = 'sW2uzXjyWqiyC5Lq2lNsdnig' 480 | SECRET_KEY = 'GVF2YX5cS7RZqfXMGgIpnuPDPQyfEyWq' 481 | client = AipOcr(APP_ID, API_KEY, SECRET_KEY) 482 | """ 读取图片 """ 483 | def get_file_content(filePath): 484 | with open(filePath, 'rb') as fp: 485 | return fp.read() 486 | image = get_file_content(filename) 487 | """ 调用数字识别 """ 488 | client.numbers(image); 489 | """ 如果有可选参数 """ 490 | options = {} 491 | options["recognize_granularity"] = "big" 492 | options["detect_direction"] = "true" 493 | """ 带参数调用数字识别 """ 494 | a = client.numbers(image, options) 495 | try: 496 | a = a['words_result'][0]['words'] 497 | print(a) 498 | except: 499 | return False 500 | else: 501 | if len(a) == 4: 502 | return a 503 | else: 504 | return False 505 | 506 | 另外一种解决方案是直接把图片经过主机微信号发送给客户端微信,通过用户人工识别图片的结果,进行消息回复之后,实现验证码的人工识别。这里的实现代码如下 507 | 508 | imgnum = aiYzm('.\image\{}1.png'.format(shot_tm)) 509 | if imgnum: 510 | user.yzm = imgnum 511 | suss, user.cookies = log_web(user.admin, user.yzm) 512 | if suss: 513 | itchat.send_msg('网站登录成功,请稍等片刻数据马上抓取成功', user.username) 514 | timec = logdata(user) 515 | else: 516 | itchat.send_msg('so sad~ 验证码自动识别失败,请重新获取数据', user.username) 517 | driver.close() 518 | 519 | 成功识别图片的运行示意图如图4.18示 520 | 521 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image040.jpg) 522 | 523 | 图4.18 验证码图像识别成功运行示意图 524 | 525 | 失败识别验证码需要人工输入的运行示意图如图4.19所示 526 | 527 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image042.jpg) 528 | 529 | 图4.19 人工识别验证码运行效果 530 | 531 | 接下来依旧使用requests方案对傲梦编程官网的数据进行爬取,通过网站页面的结构分析,发现主要数据分成两部分,已完成课程数据和未完成课程的数据。对应页面的内容如下图所示, 532 | 533 | 已完成课程的内容网页效果图如图4.20 534 | 535 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image044.jpg) 536 | 537 | 图4.20 傲梦编程网站教师端已完成课程效果图 538 | 539 | 未完成课程的内容网页效果图如图4.21 540 | 541 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image046.jpg) 542 | 543 | 图4.21 傲梦编程教师端未完成课程效果图 544 | 545 | 通过对页面的html代码分析发现,本分关键代码人如图4.21所示: 546 | 547 | 548 | 549 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image048.jpg) 550 | 551 | 图4.22 傲梦编程网站关键代码截图 552 | 553 | 554 | 555 | 通过对网站后台代码的研究和探索性检查,网站的数据是异步加载的数据,通过谷歌浏览器的检查工具对网页中的异步加载数据排查(数据存在于检查接口下的NETWORK对应XHR里面) 556 | 557 | 网页异步加载数据总页面如图4.23 558 | 559 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image050.jpg) 560 | 561 | 图4.23 检查接口下异步加载数据列表示意图 562 | 563 | 该网页存在所需的加载数据,数据的格式是json格式,以已完成数据中的一页的一条记录为例,数据如下 564 | 565 | {"lessonId":"eec9348ceba84ef99e1d6d40edef2943","studentId":"4697f12fdf224456a4a26c417eadcea8","teacherId":"e4ccd1f328d84a76ab46e382d79af6a8","lessonName":"64510班级课程","studentName":"章圣歆","teacherName":"陈奇","lessonStartTime":1557055803000,"lessonEndTime":1557058654000,"teacherComment":"知识点内容:\n\t课程进度 pye21-1\n\t内容总结 贪吃蛇游戏的函数化\n孩子掌握情况:\n\t孩子具体完成情况 能在老师的引导下理解课堂代码的实现逻辑\n\t优点 学习兴趣高 理解能力强\n\t欠缺点 暂无\n需要家长配合:暂无\n上次课作业完成情况:完成 存在问题 已在课堂上解决","teacherCommentLevel":4,"studentComment":null,"lessonStatus":"2","studentCommentLevel":null,"studentCommentOne":null,"studentCommentTwo":null,"studentCommentThree":null,"studentCommentFour":null,"studentCommentFive":null,"teacherCommentOne":4,"teacherCommentTwo":4,"teacherCommentThree":4,"teacherCommentFour":4,"teacherCommentFive":4,"teacherLessonUrl":null,"lessonUrl":"http://timer.91veo.com/v1/meeting/join?id=1402562&value=fafc2c1c46bc952e524ca3c7bb42a1f9","recordUrl":"https://cdn.all-dream.com/user/e4ccd1f328d84a76ab46e382d79af6a8/20190505_202919_zoom_0.mp4","note":"","noteTeacher":"NOIP测试分数:","courseTypeName":"python程序设计","courseTypeId":"702dd6f4b95f418ebf5f54bd652e859f","studentSignNote":"","studentSignState":"1","online":"1","free":"0","homework":"https://cdn.all-dream.com/exercise/307f56ba15f84ce9b94e05ac0345ba4c/425.py"}, 566 | 567 | 文件中的json格式的数据可以继续用requests方式进行数据的爬取,这里因为数据是一部加载的数据,需要用到json模块对数据进行格式化处理,换而言之,只有json才能把网页中的结构体数据转换成python的字典格式,但是字典的数据课时处理起来不是非常的方便,在本系统中我们采用pandas的库对数据进行更加精细化的的直观处理。且网页中表示的实现是用unix时间戳来表示,这里本系统采用python的datatime的模块对时间进行格式化的处理。具体的实现代码如下所示: 568 | 569 | def getData(cookies): 570 | '''获取傲梦网站的学生信息以及课程信息 571 | 返回获取数据的文件所在目录 572 | 参数是网站所需的cookies 573 | 数据的精细化处理 是数据的检索更加简单 574 | ''' 575 | timec = time.strftime("%Y%m%d%H%M",time.localtime(time.time())) 576 | os.mkdir('./data/'+timec) 577 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} 578 | url = 'https://all-dream.com/rest/hour/queryMyCoursePlan4TeacherNew?free=0&limit=10&random=0.5043750329478451&page=1' 579 | today_class = requests.get(url,headers=headers,cookies=cookies) 580 | today_class = json.loads(today_class.text) 581 | print(today_class) 582 | with open('./data/'+timec+'/今日课程计划','wb') as file: 583 | pickle.dump(today_class,file) 584 | url_list = ['https://all-dream.com/rest/courseManage/queryMyOverCourse4Teacher?limit=10&page={}'.format(i+1) for i in range(10)] 585 | over_all_class = [] 586 | for url in url_list: 587 | over_class = requests.get(url,headers=headers,cookies=cookies) 588 | data_1 = json.loads(over_class.text)['list'] 589 | over_all_class.append(data_1) 590 | key = 1 591 | stOverClass = {} 592 | for ondPage in over_all_class: 593 | for oneClass in ondPage: 594 | stOverClass[key]=oneClass 595 | key+=1 596 | df = pd.DataFrame(stOverClass).T 597 | 598 | with open('./data/'+timec+'/已完成课程','wb',) as file2: 599 | pickle.dump(df,file2) 600 | return timec 601 | 602 | 603 | 604 | 605 | 这里为直观展示如图已完成课程数据中的一个数据结构图如图4.24 606 | 607 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image052.jpg) 608 | 609 | 图4.24 已完成课程数据结构图 610 | 611 | 其中满足我们需求的数据只需要学生姓名(studentName)上课时间(lessonStartTime)课程类别(courseTypeName)以及教师评价(teacherComment)其中课堂的上课时间是unix时间戳需要转换成正常显示的时间格式,评价中包含上课进度,学生课堂表现,知识点等内容。在这里我们首先要做的事情是吧数据西安进行存储,这里用到pickle模块,并且为了后期的容易清洗,数据格式用pandas模块中的dataframe数据表的格式保存,待完成课程的数据用以上相同的策略也可以抓取。功能中的今日课程计划和近日课程计划都是对待完成课程数据的检索,某某学生的课堂反馈则是对已完成课程 的数据检索。以及完成课程的excel表格也是对已完成课程的检索,实现代码如下所示: 612 | 613 | def getToday(path,flag): 614 | '''参数是当前目录(今日学生信息的名称)下的文件名称 615 | 返回值是一个字符串 包含今日未完成课程信息 616 | 功能:获取当前日期内的上课内容 617 | ''' 618 | if flag: 619 | tm = '近日' 620 | else: 621 | tm = '今日' 622 | str1 = '' 623 | with open('./data/'+path+'/今日课程计划','rb') as file: 624 | data = pickle.load(file) 625 | stlist = data['list'] 626 | nowday = time.strftime("%Y-%m-%d",time.localtime(time.time())) 627 | times=0 628 | if not flag: 629 | for st in stlist: 630 | sttime = uTime(st['startTime']) 631 | if sttime[:10]!=nowday: 632 | continue 633 | times+=1 634 | edtime = uTime(st['endTime']) 635 | stname = st['studentName'] 636 | kemu = st['courseTypeName'] 637 | banji = st['courseHourName'] 638 | str1 += '\t学生:{} \n\t时间:\n\t{}\n\t{} \n\t科目:\t{} \n\t班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 639 | else: 640 | for st in stlist: 641 | sttime = uTime(st['startTime']) 642 | times+=1 643 | edtime = uTime(st['endTime']) 644 | stname = st['studentName'] 645 | kemu = st['courseTypeName'] 646 | banji = st['courseHourName'] 647 | str1 += '学生:{} \n时间:\n{}\n{} \n科目:{} \n班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 648 | 649 | if times >=1: 650 | return '老师您好,\n{}你总共有{}节课\n内容如下\n'.format(tm,times)+str1 651 | else: 652 | return'老师~今天真幸福呀,\n{}你已经完成了所有工作\n当然今天也可能是非常愉快的休息日,\n试试召唤智能机器人,\n \"小小奇\" '.format(tm) 653 | 654 | 对于特定学生的课堂表现内容获取函数如下所示 655 | def getfk(name,timec): 656 | ''' 657 | 参数:查看反馈的学生姓名 以及保存本次数据的文件最内层路径 658 | 返回值:包含匹配到该学生的三条数据 如果先搞改变匹配数据的数量只需要改掉times里的值 659 | 功能实现原始数据的检索 可通过学生姓名直接检索 660 | ''' 661 | with open('./data/'+timec+'/已完成课程','rb') as file: 662 | df = pickle.load(file) 663 | student = df[df['studentName']==name] 664 | msg_list = [] 665 | for i in range(len(student)): 666 | st = student.iloc[i] 667 | remark = st['teacherComment'] 668 | videourl = st['recordUrl'] 669 | star = st['teacherCommentOne'] 670 | stTime = st['lessonStartTime'] 671 | msg = '这节课的开始时间是:\n{}\n这节课里你对孩子评价是:\n{}\n您为孩子打出惊人的{}颗星\n视频链接:\n{}\n--------------------------------------------' 672 | msg_one = msg.format(uTime(stTime),remark,star,videourl) 673 | msg_list.append(msg_one) 674 | return msg_list 675 | 676 | 对于备课表单自动生成,需要把网站爬取的相应数据转换成固定格式的excel格式,pandas的内置方法to_csv可以直接把格式为DataFrame的数据表直接转换成excel表格,实现代码如下所示: 677 | 678 | def savetoexcel(a): 679 | 680 | ​ for i in a: 681 | 682 | ​ with open('傲梦备课表.csv','a+',encoding = 'gbk',newline='')as csvfile: 683 | 684 | ​ writer = csv.writer(csvfile) 685 | 686 | ​ writer.writerow(list(i.values())) 687 | 688 | ​ with open("{}.csv".format('傲梦1')) as aaa: 689 | 690 | ​ lalal = pd.read_csv(aaa,header=None,skiprows=6) 691 | 692 | ​ lalal.columns = ['姓名', '课程类别', '课堂开始时间', '课堂结束时间', '课程进度', '内容总结'] 693 | 694 | lalal.to_excel("{}.xlsx".format('傲梦备课表') 695 | 696 | 4.2.5 程序脚本集成 697 | 698 | ​ 本系统的代码结构如图所示4.25所示 699 | 700 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image054.jpg) 701 | 702 | 图4.25 代码文件示意图 703 | 704 | 其中start.bat是本系统的快速运行脚本,双击它会自动使用python3版本环境运行代码start.py,而start.py会使用itchat自动登录微信,这里主机微信号需要使用扫描自动生成的微信二维码进行账号授权。经过这一步之后,微信的实时消息就可以被获取到,此时就可以在run.py根据帮助文档中的聊天信息做出相应的响应。其中响应分为傲梦官网学生信息的响应和图灵机器人的信息响应,以及附加功能中的接口调用,比如IT之家热点新闻。其中聊天的对象分为两个权限,对应程序代码中的两个类,代码如下所示 705 | 706 | class Friends(): 707 | def __init__(self): 708 | with open('./data/好友信息','rb',) as file2: 709 | self.df =pickle.load(file2) 710 | def isvip(self,fromusername): 711 | username = self.df[self.df['Remark'].isin(list(message.keys()))]['UserName'].values 712 | if fromusername in username: 713 | return True 714 | else: 715 | return False 716 | 717 | def readvip(): 718 | pass 719 | class Teacher(): 720 | def __init__(self,username): 721 | self.username = username 722 | with open('./data/好友信息','rb',) as file2: 723 | self.df =pickle.load(file2) 724 | self.name = self.df[self.df['UserName']==self.username].iloc[0].Remark 725 | self.admin = message[self.name] 726 | print(self.name) 727 | def getmessage(self,flag): 728 | if self.msg_1['Text'] =='小小奇': 729 | flag = True 730 | return flag 731 | def getcookies(self): 732 | ''' 733 | 验证码图片的微信发送 734 | 验证码保存在本地 文件名由当前时间命名 735 | 时间作为发送信息的图片名 736 | ''' 737 | self.img_time = time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time())) 738 | if getimg(self.img_time): 739 | return self.img_time 740 | def svtime(self,timec): 741 | self.timec = timec 742 | class Nomal(): 743 | def __init__(self,username): 744 | self.flag = False 745 | self.username = username 746 | 747 | 通过聊天信息Friends类中isvip方法对信息发送者的权限进行分类,确定是Teacher类还是Nomal类,对于不同权限的用户采取不同的信息响应策略,但是机器人的功能基本一致,机器人权限的开关和信息交互代码如下所示: 748 | 749 | nomal = Nomal(msg['FromUserName']) 750 | print('创建聊天') 751 | nomal.msg = msg 752 | if nomal.msg['Text'] in ['start','小小奇','开始']: 753 | itchat.send_msg('以下内容是自动回复,发送“exit”或者“退出”退出退出自动回复',nomal.username) 754 | nomalflag[nomal.username] = True 755 | elif nomal.msg['Text'] in ['help','帮助']: 756 | itchat.send_image('./image/nomal.png',nomal.username) 757 | elif nomal.msg['Text'] in ['end','exit','退出']: 758 | nomalflag[nomal.username] = False 759 | try: 760 | if nomalflag[nomal.username]: 761 | itchat.send_msg(jqr(nomal.msg['Text'])+".",nomal.username) 762 | except: 763 | pass 764 | 765 | 对于教师权限的用户的功能调用流程控制的代码实现策略如下所示: 766 | 767 | user = Teacher(fromusername) 768 | user.msg_1 = msg 769 | if user.msg_1['Text'] in ['start','小小奇','开始']: 770 | itchat.send_msg('以下内容是自动回复,发送“exit”或者“退出”退出退出自动回复',user.username) 771 | userflag[user.username] = True 772 | elif user.msg_1['Text'] in ['end','exit','退出']: 773 | userflag[user.username] = False 774 | if len(userflag): 775 | if userflag[user.username]: 776 | itchat.send_msg(jqr(user.msg_1['Text'])+".",user.username) 777 | 778 | if len(userflag)==0 or userflag[user.username]==False: 779 | if user.msg_1['Text'] == '获取数据': 780 | itchat.send_msg('请耐心等候,小爬虫正在快吗加鞭获取数据', user.username) 781 | shot_tm = user.getcookies() 782 | itchat.send_msg(msg_to_u[1],user.username) 783 | imgnum = aiYzm('.\image\{}1.png'.format(shot_tm)) 784 | if imgnum: 785 | user.yzm = imgnum 786 | suss, user.cookies = log_web(user.admin, user.yzm) 787 | if suss: 788 | itchat.send_msg('网站登录成功,请稍等片刻数据马上抓取成功', user.username) 789 | timec = logdata(user) 790 | else: 791 | itchat.send_msg('so sad~ 验证码自动识别失败,请重新获取数据', user.username) 792 | driver.close() 793 | 794 | else: 795 | itchat.send_image('.\image\{}1.png'.format(shot_tm),user.username) 796 | elif user.msg_1['Text'] in ['help', '帮助']: 797 | itchat.send_image('./image/teacher.png',user.username) 798 | elif re.findall('\d+',user.msg_1['Text']): 799 | if len(re.findall('\d+',user.msg_1['Text'])[0])==4: 800 | user.yzm = re.findall('\d+',user.msg_1['Text'])[0] 801 | suss,user.cookies = log_web(user.admin,user.yzm) 802 | if suss: 803 | timec = logdata(user) 804 | else: 805 | itchat.send_msg('so sad~ 验证码输入错误,请重新获取数据', user.username) 806 | driver.close() 807 | 808 | 809 | 810 | elif user.msg_1['Text'] in '近日课程计划': 811 | print(timec) 812 | user.closetoday = getToday(timec,True) 813 | itchat.send_msg(user.name[:-4]+user.closetoday,user.username) 814 | 815 | elif user.msg_1['Text'] in '今日课程计划': 816 | print(timec) 817 | user.today = getToday(timec,False) 818 | itchat.send_msg(user.name[:-4]+user.today,user.username) 819 | elif user.msg_1['Text'][-4:]=='课堂反馈': 820 | ms = getfk(user.msg_1['Text'][:-4],timec) 821 | print(user.msg_1['Text'][:-4]) 822 | if len(ms)>=1: 823 | itchat.send_msg('已为您匹配到{}个结果'.format(len(ms)),user.username) 824 | for ms_1 in ms: 825 | itchat.send_msg(ms_1,user.username) 826 | else: 827 | itchat.send_msg(msg_to_u[-1],user.username) 828 | for msg in ms: 829 | itchat.send_msg(ms,user.username) 830 | elif user.msg_1['Text'] == '热点': 831 | day,week = getnews() 832 | print(day,'\n',week) 833 | itchat.send_msg(day, user.username) 834 | itchat.send_msg(week, user.username) 835 | 836 | 4.3功能函数 837 | 838 | ​ 获取微信好友信息的函数如图4.26所示 839 | 840 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image056.jpg) 841 | 842 | 图4.26微信登录后好友信息身份信息的汇总获取代码实现 843 | 844 | ​ 获取网站cookies的函数如图4.27所示 845 | 846 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image058.jpg) 847 | 848 | 图4.27 模拟浏览器登录傲梦网站获取cookies代码截图 849 | 850 | 处理数据如图4.28所示 851 | 852 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image060.jpg) 853 | 854 | 图4.28 对爬取到的异步加载数据进行第一次数据筛选代码截图 855 | 856 | 857 | 858 | 859 | 860 | 861 | 4.4运行设计 862 | 863 | 批处理(Batch),也称为批处理脚本。顾名思义,批处理就是对某对象进行批量的处理。批处理文件的扩展名为bat。在本系统中,脚本的运行采用dos批处理运行python代码,严格遵守pep20的程序设计理念,以简约轻便为主旨,程序的运行指令为dos批处理文件,以下是文件的编码示意图如图4.19 864 | 865 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image062.jpg) 866 | 867 | 图4.19 脚本启动dos文件代码截图 868 | 869 | 870 | 871 | 4.5系统数据结构设计 872 | 873 | 4.5.1 用户傲梦网站的身份信息 874 | 875 | 教师的个人信息表设计如表4.1所示, 876 | 877 | 878 | 879 | 表4.1 教师个人信息表 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | | 姓名 | 账号 | 密码 | 894 | | ---- | ----------- | ------ | 895 | | 陈奇 | 18000000000 | 123456 | 896 | 897 | 教师的身份信息以上表中的格式存储,内容经过base64加密, 898 | 899 | 4.5.2 学生已完成课程数据 900 | 901 | ​ 学生的已完成课程数据格式如表4.2所示 902 | 903 | 表4.2 学生已完成课程数据表 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | | 学生姓名 | 上课时间 | 科目 | 教师评价 | 上课进度 | 926 | | -------- | -------------------------------------- | ---------------- | ------------------------------------ | ------------------ | 927 | | 李一一 | 2019-01-01 10:30 2019-01-01 11:20 | Python程序与设计 | 包含学生课堂表现,课堂知识点,等内容 | Python初级课第一课 | 928 | 929 | 930 | 931 | 4.5.3学生待完成课程数据 932 | 933 | ​ 学生的待完成课程数据表如表4.3所示 934 | 935 | 表4.3 学生未完成课程数据表 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | | 学生姓名 | 上课时间 | 科目 | 950 | | -------- | ---------------------------------- | ---------------- | 951 | | 李一一 | 2019-01-01-10:30至2019-01-01-11:20 | Python程序与设计 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 5 测试与结果分析 959 | 960 | 5.1 运行环境 961 | 962 | ​ 硬件:因为需要实时获取,所以需要运行在服务器环境中,本系统运行环境在阿里云的云服务器。 963 | 964 | ​ 软件:本脚本需要再python3.的环境下运行,webdriver需要在谷歌浏览器的安装目录下保存谷歌浏览器的webdriver驱动。 965 | 966 | 5.2运行界面及结果测试 967 | 968 | 5.2.1代码的运行 969 | 970 | ​ 测试环境: 971 | 972 | ​ 操作系统:Wingdows10企业版 64位 973 | 974 | ​ 运行方式:Dos批处理文件 975 | 976 | ​ Python版本:Python3.7.0 977 | 978 | ​ 浏览器版本:Goole Chrome版本 74.0.3729.131(正式版本) (64 位) 979 | 980 | 运行界面截图如下图5.1所示 981 | 982 | ​ ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image064.jpg) 983 | 984 | ​ 图5.1 程序运行启动成功终端效果图 985 | 986 | 5.2.2 爬取数据的展示 987 | 988 | 新闻热点的终端输出展示截图如图5.2所示 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image066.jpg) 999 | 1000 | 图5.2 热点数据的终端输出效果图 1001 | 1002 | 微信端新闻热点新闻的截图如图5.3所示 1003 | 1004 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image068.jpg) 1005 | 1006 | 图5.3 热点数据的微信端输出效果图 1007 | 1008 | 鉴于篇幅限制,以下为代码运行结果只展示微信端截图, 1009 | 1010 | 聊天机器人功能检测如图5.4所示 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image070.jpg) 1017 | 1018 | 图5.4聊天机器人微信端输出效果图 1019 | 1020 | 傲梦编程网站数据的检索测试示意图运行截图如图5.5所示 1021 | 1022 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image072.jpg) 1023 | 1024 | 图5.5获取傲梦数据微信端输出效果图 1025 | 1026 | 1027 | 1028 | 傲梦网站自动生成的备课表如图5.6所示 1029 | 1030 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image074.jpg) 1031 | 1032 | ​ 图5.6 脚本自动生成备课表的文件预览图 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 参考文献 1063 | 1064 | [1] Allen B. Downey.《Think Python: How to Think Like a Computer Scientist》Green Tea Press 1065 | 1066 | [2] Python程序设计 [An Introduction to Programming Using Python].[美] 戴维 I.施奈德(David I. Schneider)著;车万翔 译 1067 | 1068 | | [3]檀冬宇.基于Python的大众点评网数据抓取技术研究[J].计算机产品与流通,2019(05):116. | 1069 | | ------------------------------------------------------------ | 1070 | | [4]. Biophysical Society; Python hearts reveal mechanisms relevant to human heart health and disease[J]. NewsRx Health & Science,2019. | 1071 | | [5]Tomas Beuzen,Joshua Simmons. A variable selection package driving Netica with Python[J]. Environmental Modelling and Software,2019,115. | 1072 | | [6]Simon Olofsson,Lukas Hebing,Sebastian Niedenführ,Marc Peter Deisenroth,Ruth Misener. GPdoemd: A Python package for design of experiments for model discrimination[J]. Computers and Chemical Engineering,2019,125. | 1073 | | [7]Omid Haji Maghsoudi,Annie Vahedipour,Thomas Hallowell,Andrew Spence. Open-source Python software for analysis of 3D kinematics from quadrupedal animals[J]. Biomedical Signal Processing and Control,2019,51. | 1074 | | [8]Theo Steininger,Jait Dixit,Philipp Frank,Maksim Greiner,Sebastian Hutschenreuter,Jakob Knollmüller,Reimar Leike,Natalia Porqueres,Daniel Pumpe,Martin Reinecke,Matevž Šraml,Csongor Varady,Torsten Enßlin. NIFT y 3 – Numerical Information Field Theory: A Python Framework for Multicomponent Signal Inference on HPC Clusters[J]. Annalen der Physik,2019,531(3). | 1075 | 1076 | 1077 | 1078 | 1079 | 致 谢 1080 | 1081 | ​ 经过两个多月的努力,本脚本完美上线,在这里致谢同事罗煜,鲍得江等人的帮忙测试功能,提出了很多好的意见,感谢百度人工智能开放平台,解决了一部分验证码识别的问题,感谢图灵机器人的开发公司北京光年无限科技及开发人员。感谢我的毕业设计指导老师任强老师,为我的脚本完善提供了很好的建议和指导。 1082 | 1083 | ​ 除此之外,感激大学期间所有的老师们,他们带我走进了计算机这个神奇并且美丽的世界,感激车鹏飞老师,他用浅显易懂的方式让我理解了编程语言的内部机制,感激孙少波老师,他带我走进python的世界,并给我了很多学习和项目的经验,记得大一的时候,在张岗亭老师的引导下,当我用c语言完成99乘法表的时候,满心的激动,后来通过任强老师的网页设计,我搭建出了自己的第一个个人网页,所有的老师们带给我的知识,都让我在后来的学习中获益匪浅。 1084 | 1085 | ​ 最后,感谢我的舍友李尧,作为一个刚上大学时候连搜索引擎都不能熟练应用的电脑小白 ,在他的指导下,学会了科学的使用电脑,这让我的学习效率,事半功倍。绪论 1086 | 1087 | 1.1编写目的 1088 | 1089 | ​ 处于信息时代的我们,每天接受这无数的信息轰炸,现代人的信息接受量达到了人类历史的新高度,但是,当我们接受信息的过程所花费时间并不是完全等同于我们使用电脑或手机设备的时间,这期间我们需要对互联网中的数据进行人为的筛选和检索,在这里,我们把获取筛选数据的时间称之为无助且必要时间。手机,作为现代人最常使用的移动设备,无疑便利了我们的生活,但同时,如果我们给他集成过多的软件,首先找到并打开软件的过程就需要很长的时间,并且一部手机的负载是有限的,过大的资源占用之下必将导致我们手机设备的卡顿,这严重影响我们的手机使用体验。例如当我们想知道今天某座城市的天气,我们需要打开固定的天气咨询类软件,通过时间和城市的选择获得我们想要的数据,这种繁琐的信息交互模式无疑不是最好的选择。而本系统的目的就是: 1090 | 1091 | 把每天被各种应用软件奴役的人从重复性的工作学习娱乐中解脱出来,使人们在信息同步的前提下有更多可以自由支配的时间。在不影响工作质量甚至会提高工作效率的前提下实现工作信息的同步和工作内容的完善。在功能不打折扣,时间陈本不增加的基础上完成手机使用软件的精简化,能够根据个人偏好实现信息的做针对性同步。例如,当我们想知道哪座城市的天气的时候,或者今日的热点新闻,热点话题,只需要简单的一句口令,我们需要的内容就可以铺陈眼前,功能的智能化和量身定做化变得史无前例的便捷,在最小程度上增加手机的资源占用下极大的压缩玩手机期间的无助且必要时间。 1092 | 1093 | 1.2系统应用背景 1094 | 1095 | 近年来,人们花费在电脑和手机上的时间越来越多,手机的软件更是层出不穷,据美通社2019年1月17号的报道显示,全球用户每天使用手机5.1小时,爱尔兰用户每天使用时长更是高达8.4小时,而人们花费如此多的时间都用来做了什么呢?工作,社交,新闻,短视频,游戏。但是根据对周围人群的统计我发现,在重复的浏览过程中,包含了很多重复且毫无价值的信息来源,于是,人们打开各式各样的软件浏览着千篇一律的内容,无意间消磨了大量的工作学习时间,于是,我打算开发一款可以自动帮我们检索信息的脚本,以微信个人号的方式为我们推送各种量身定做且经过处理的数据,这些同样适用于工作效率的提高,以在线教育讲师的工作为例,每日的课时信息,学生学习状况的整理,周期内的工作总结,都可以在这个脚本下集成。 1096 | 1097 | 在中国,微信的出现,无疑改变了我们的社交途径和方式,作为中国人最常用到的应用软件,它因为简洁,快捷,被人们所热爱,每天我们都会或多或少的通过微信和远方的朋友聊天,而我们的脚本正是集成在这个便捷的载体之上。就像正常的聊天一样,发送信息,微信机器人就像我们的私人助手一样,快速的给我们想要的内容反馈。 1098 | 1099 | 1.3研究内容 1100 | 1101 | ​ 本课题的主要研究内容在于多个脚本功能的集成及相互调用,功能主要包括基于itchat模块实现微信特定好友信息的持续获取和响应,基于reqursts模块实现异步加载数据的获取和基于pandas模块的数据清洗及检索,还有基于pygal模块的数据可视化模型的建立,以及基于pickle的文件数据的本地写入及读取,除此之外,我们需要积极研究的还有,如何管理不同权限的用户信息的功能分布,如何处理两种状态下的连天模式,即适用于普通用户的机器人聊天模式和只适用于高级权限的工作信息的聊天模式。 1102 | 1103 | 1104 | 1105 | 1106 | 2需求分析 1107 | 1108 | 2.1功能需求 1109 | 1110 | 2.1.1用户体验 1111 | 1112 | ​ 用户能够在请求之后尽快时间得到响应,至少比用户正常打开软件时候的时间成本低,对于手机的资源占用要尽可能的少,至少要比正常使用手机获取信息的资源占用要小,使用本脚本的学习成本尽可能的低,对于容易出错的部分要实现简洁但清晰的说明指导,获取的信息要准确并明了,信息的获取需要符合使用者的信息需求偏好该脚本需要能在通常网络环境下随时响应, 1113 | 1114 | 2.1.2多功能协调 1115 | 1116 | ​ 微信个人号的聊天指令能够完成对各种功能的调用,相互之间的功能独立存在且相互联系, 1117 | 1118 | 2.1.3数据的格式及传递 1119 | 1120 | ​ 响应的数据简单明了。比如,课程计划,应包含学生姓名,上课时间,所属科目,学生的反馈,应包含学生姓名,课程进度,课程时间,教师评价,以及上课视频等内容。这里的大部分的内容在聊天过程中都是以文本格式传递的,学生的备课表需要以excel表格的形式返回。 1121 | 1122 | 2.1.4 功能 1123 | 1124 | ​ 聊天有两种状态,基于图灵机器人的闲聊状态和集成的工作数据同步以及实时热点新闻的同步状态。 1125 | 1126 | ​ 聊天机器人,实现微信聊天的自动回复,能够实时自动回复,可以接受并响应多种形式的微信消息,天气,火车信息等功能的调试及正常使用。 1127 | 1128 | ​ 集成爬虫,在线教育平台的数据抓取和检索,能够根据指令完成,当前工作日待完成课程,以及当前工作日近期课程计划,已完成课程中某位学生的课程进度以及课堂表现,以及根据爬虫的数据进行excel表格统计等功能,除此之外包括但不限于每日热点新闻,舆论热点等信息的爬取和检索 1129 | 1130 | ​ 支持多用户并发,能够微信账号对特定用户附加附加高级权限的功能,其他用户也能够通过指令对用户本人的数据进行爬取和检索。 1131 | 1132 | 2.2非功能需求 1133 | 1134 | 2.2.1安全性 1135 | 1136 | ​ 账号安全,用户的工作账号安全和信息安全必须得到保证。该项目的代码需要进行加密,以防止攻击代码被人利用。 1137 | 1138 | 1139 | 1140 | 2.2.2稳定性 1141 | 1142 | ​ 脚本需要在上线后实时响应,不能出现中途断线或者请求不响应的情况。对于各种异常可以扑捉,并做出处理。 1143 | 1144 | 2.2.3运行环境及设备准备 1145 | 1146 | 本操作脚本需要用到服务器,这里我们的实例是阿里云ecs云服务器,除此之外,我们需要一个用于信息整合和内容回复的微信个人号(下面称之为主机微信号),用户只需要是添加过主机个人号好友的微信个人号, 1147 | 1148 | 系统版本:Windows Server 2012 R2 数据中心版 64位 1149 | 1150 | 编辑器:pycharm 1151 | 1152 | 服务器运行:command命令行 1153 | 1154 | Python环境 python 3.7.0 1155 | 1156 | Lxml 4.2.5 1157 | 1158 | pandas 0.23.4 1159 | 1160 | Pillow 5.2.0 1161 | 1162 | selenium 3.141.0 1163 | 1164 | itchat 1.3.10 1165 | 1166 | pip 10.0.1 1167 | 1168 | 1169 | 1170 | 1171 | 3概要设计 1172 | 1173 | 3.1基本模块 1174 | 1175 | ​ 本系统设计主要包含以下几个基本模块,自动获取数据,对获取到的大量数据进行数据清洗及处理,数据的传递,微信接口的架构, 1176 | 1177 | 3.1.1获取数据 1178 | 1179 | ​ 获取服务器运行的微信号的好友信息, 1180 | 1181 | ​ 获取傲梦教师端的课程数据数据,课程数据包含的内容有已完成课程,未完成课程,具体数据内容如下图所示, 1182 | 1183 | ​ 获取IT之家的高阅读量的文章标题及链接, 1184 | 1185 | ​ 根据接受信息获取图灵机器人的信息反馈 1186 | 1187 | 3.1.2数据清洗及处理 1188 | 1189 | ​ 通过对傲梦网站数据的分析研究,对爬取到的原始数据进行结构化的处理, 1190 | 1191 | ​ 通过对数据的筛选生成excel表格,和格式化的富文本 1192 | 1193 | 3.1.3微信接口的架构 1194 | 1195 | ​ 实时接受微信消息 1196 | 1197 | ​ 根据微信消息执行响应的模块, 1198 | 1199 | ​ 根据各个模块的响应精准返回模块中生成的数据结果 1200 | 1201 | ​ 根据不同的用户实现权限分级, 1202 | 1203 | ​ 对于不同的用户权限进行功能细化 1204 | 1205 | 3.1.4脚本实现预期效果 1206 | 1207 | ​ 因为本系统的用户在1000人以内且都是微信好友教师权限的用户也只有不到100人,所以对于用户身份验证的策略本系统拟采取本地初始设置,即对于普通权限的用户只需要是主机微信号的好友就可以使用,教师权限需要向管理员提交傲梦编程1对1少儿编程培训网站教师端的账号和密码经过管理员校验之后才能使用此权限的功能,普通用户只需要在和主机微信的聊天窗口下发送相应指令就可以得到响应,指令的帮助文档根据用户权限不同返回,如下图所示为普通用户的使用文档。普通用户以及教师的帮助文档如图 3.1 所示 1208 | 1209 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.gif) 1210 | 1211 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.gif) 1212 | 1213 | 图 3.1帮助文档 1214 | 1215 | 3.2流程图及说明 1216 | 1217 | ​ 如下图所示为本操作系统的模块设计流程图 1218 | 1219 | ​ 我们的脚本会持续监听微信消息的接收,当一条信息被接受,脚本会根据这个人的权限分流,以教师权限的用户为例,如果此时该用户直接使用了获取数据的指令,脚本会自动去该教师的傲梦编程教师端网站上获取该老师的数据,接下来该用户就可以直接通过口令检索出自己所需的数据。 1220 | 1221 | 脚本运行流程图3.2所示 1222 | 1223 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.gif) 1224 | 1225 | 图3.2 脚本运行流程示意图 1226 | 1227 | 3.3 关键技术介绍 1228 | 1229 | 3.3.1网络爬虫 1230 | 1231 | ​ 网络爬虫,也称为"网络蜘蛛",通过网页的链接地址搜索网页,从网站的某个页面开始,读取网页的内容,在网页中查找其他链接地址,然后通过链接地址找到下一个网页。这是一种继续循环的技术,直到根据某些策略爬网互联网上的所有网页。他可以快速捕获网站上可见的数据,是一种快速准确地获取数据的技术。目前不同的编程语言对爬虫都有相关的一些技术支持,如下表编程语言爬虫技术映射表编程语言主流爬虫框架(库)如表3.1所示 1232 | 1233 | 表3.1编程语言于主流爬虫库对照表 1234 | 1235 | | 编程语言 | 主流爬虫框架(库) | 1236 | | ---------- | ------------------------------ | 1237 | | C++ | open-source-search-engine | 1238 | | Java | Request pyspiders Scrapy | 1239 | | Python | Gecco WebMagic Spiderman | 1240 | | JavaScript | x-ray js-crawler scraperjs、 | 1241 | | C# | Abot | 1242 | | PHP | php-spider | 1243 | | Ruby | nokogiri | 1244 | | Go | Go_spider,scrape | 1245 | 1246 | 1247 | 1248 | 3.3.2 python 1249 | 1250 | ​ Python是一种解释型面向对象的动态类型的开源的计算机程序设计语言,他因为语法简单功能强大以及且具有丰富的扩展库被人们所热爱,是轻量级的快速程序开发的不二之选 1251 | 1252 | 3.3.3 requests 1253 | 1254 | ​ Requests是一个以HTTP for Humans(给人用的http库)为宣言的网络编程库,他能够使用最为简洁明了的语法实现网络操作,提交请求获取响应,从来没有如此简单。在使用它的时候,你会惊叹,这才是python代码该有的样子。 1255 | 1256 | 3.3.4信息加密 1257 | 1258 | 信息加密技术是利用数学或物理手段,对电子信息在传输过程中和存储体内进行保护,以防止泄漏的技术。 1259 | 1260 | 3.3.5 pandas 1261 | 1262 | ​ pandas 是基于 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的[数据模型](https://baike.baidu.com/item/数据模型/1305623),提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。 1263 | 1264 | 3.3.6 xpath 1265 | 1266 | ​ XPath即为[XML](https://baike.baidu.com/item/XML)路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。 1267 | 1268 | XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于[XPointer](https://baike.baidu.com/item/XPointer)与[XSL](https://baike.baidu.com/item/XSL)间的语法模型。但是XPath很快的被开发者采用来当作小型[查询语言](https://baike.baidu.com/item/查询语言) 1269 | 1270 | 1271 | 1272 | 3.3.7 itchat 1273 | 1274 | itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单。使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人。当然,该api的使用远不止一个机器人,比如[这些](http://python.jobbole.com/86532/)。该接口与公众号接口[itchatmp](https://github.com/littlecodersh/itchatmp)共享类似的操作方式,学习一次掌握两个工具。 1275 | 1276 | 如今微信已经成为了个人社交的很大一部分,这个项目能够帮助你扩展你的个人的微信号、方便自己的生活。 1277 | 1278 | 3.3.9 webdriver 1279 | 1280 | WebDriver是一种用于自动化web应用程序测试的工具,特别是用于验证它们是否按预期工作。它的目标是提供一个友好的API,易于探索和理解,比Selenium-RC (1.0) API更容易使用,这将有助于使您的测试更容易阅读和维护。它不依赖于任何特定的测试框架,因此它可以在单元测试项目中或从简单的旧的“main”方法中使用,有了他,我们可以让我们的脚本模拟大多数的浏览器操作。 1281 | 1282 | 3.3.10图灵机器人 1283 | 1284 | 图灵机器人开放平台是北京光年无限科技旗下的智能聊天机器人开放平台。通过图灵机器人开放平台,用户可快速构建自己的专属聊天机器人并为其添加丰富的机器人云端技能 1285 | 1286 | 3.3.11 AJAX异步加载 1287 | 1288 | Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。 1289 | 1290 | 使用 JavaScript 向服务器提出请求并处理响应而不阻塞用户核心对象[XMLHttpRequest](https://baike.baidu.com/item/XMLHttpRequest)。通过这个对象,您的 JavaScript 可在不重载页面的情况与 Web 服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效 1291 | 1292 | 3.3.12 pickle 1293 | 1294 | ​ 在程序代码中中,我们常常需要把程序中的某些数据模型存储起来,这样在进行其他模块使用时直接将模型读出,而不需要去构建模型,这样就大大节约了时间。Python提供的pickle模块就很好地解决了这个问题,它可以序列化对象并保存到磁盘中,并在需要的时候读取出来,任何对象都可以执行序列化操作。 1295 | 1296 | 3.3.13 正则表达式 1297 | 1298 | 正则表达式是对[字符](https://baike.baidu.com/item/字符)串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。 1299 | 1300 | 3.3.14 cookies 1301 | 1302 | 基于 Internet的各种服务系统应运而生,建立商业站点或者功能比较完善的个人站点,常常需要记录访问者的一些信息;论坛作为 Internet发展的产物之一,在 Internet 中发挥着越来越重要的作用,是用户获取、交流、传递信息的主要场所之一,论坛常常也需要记录访问者的一些基本信息(如身份识别号码、密码、用户在 Web 站点购物的方式或用户访问该站点的次数)。目前公认的是,通过 Cookie 和 Session 技术来实现记录访问者的一些基本信息 1303 | 1304 | 3.3.15百度AI人工智能平台 1305 | 1306 | 提供全球领先的语音、图像、NLP等多项人工智能技术,开放对话式人工智能系统、智能驾驶系统两大行业生态,共享AI领域最新的应用场景和解决方案,提供了很多可供开发者免费使用的人工智能接口。 1307 | 1308 | 3.3.16 批处理文件 1309 | 1310 | 批处理文件(batch file)包含一系列 DOS命令,通常用于自动执行重复性任务。用户只需双击批处理文件便可执行任务,而无需重复输入相同指令。编写批处理文件非常简单,但难点在于确保一切按顺序执行。编写严谨的批处理文件可以极大程度地节省时间,在应对重复性工作时尤其有效。 1311 | 1312 | 1313 | 1314 | 1315 | 4详细设计 1316 | 1317 | 4.1功能需求和程序的关系 1318 | 1319 | 再本操作系统中,微信聊天窗口作为我们的运行页面,所以微信消息数据的实时同步是保证代码正常运行的关键因素,获取到微信聊天信息的时候,这个数据包含了,信息的发送者,信息的内容(文本),以及该聊天信息的特定id。这个数据需要和我们程序本身的初始化数据进行判断,得出发送信息的身份对应用户权限,以及当前聊天模式,有了这个权限和模式,系统便可以根据用户的权限和信息内容明确用户的意向,聊天机器人模式下,系统根据用户的发送的内容去图灵机器人接口中获取响应,然后把这个响应返回给我们的用户,从而实现聊天机器人的功能,通常模式下,用户保持微信聊天正常状态,但是当用户身份为已经赋予权限的傲梦教师身份的时候,用户只需通过特定指令控制程序的走向,例如,当用户通过特定指令表示要获取当前时间的热点新闻,系统便会同过调用获取实时热点新闻的接口,获取到当前网站中的热点内容,本系统的设计模式采用,分布式扁平化设计理念,每一个新的指令进入,就对应新的脚本需要被执行,低内聚高耦合,模块之间只存在较少的联系,且模块之间互不干扰。 1320 | 1321 | 4.2接口设计 1322 | 1323 | 4.2.1微信信息的获取 1324 | 1325 | 在本脚本中,微信的聊天框可以说扮演了一个用户界面的角色,用户和服务器的一切交互都是通过微信信息的发送来完成的,所以脚本如何去获取微信好友的信息就成了本脚本第一个要解决的实际问题,itchat作为一个开源的微信个人号接口,让数据的传递变得空前的简洁,他可以完美模拟用户登录网页端的微信,实现代码如图4.1 所示 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg) 1334 | 1335 | 图4.1 微信消息实时获取示意图 1336 | 1337 | 运行结果如下图4.2所示: 1338 | 1339 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg) 1340 | 1341 | 图4.2 微信登录成功终端显示效果图 1342 | 1343 | 通过运行代码首先会出现微信登录所需的扫码,程序模拟登录了网页版的主机微信号。出现login successfully as 微信名字样表示登陆成功,msg_register函数实现了各种微信信息的实时获取,此处在text函数中可以把文本格式的信息内容获取到,经过对msg微信聊天信息研究发现,脚本所需的信息来源用户,信息内容,都可以直接在msg中获得。如下图代码和运行结果如图4.3所示 1344 | 1345 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg) 1346 | 1347 | 图4.3微信消息数据解析代码示意图 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 运行结果如图4.4所示 1354 | 1355 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg) 1356 | 1357 | 图4.4 微信聊天数据解析运行效果图 1358 | 1359 | 1360 | 1361 | 4.2.2新闻热点的爬取 1362 | 1363 | 对于舆论热点,本脚本拟获取IT之家版面中的如下图框选内容所示中的最热排行和周榜内容的网站示意图,如图4,5所示 1364 | 1365 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg) 1366 | 1367 | 图4.5 IT之家网站主页 1368 | 1369 | ​ 通过对数据的研究,发现本数据可以直接在网站的html代码中找到,如图4.6所示 1370 | 1371 | 1372 | 1373 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg) 1374 | 1375 | 图4.6 IT之家网站热点新闻网页代码示意图 1376 | 1377 | 1378 | 1379 | 通过数据比对,发现a标签中的文本就是文章的标题,而a标签的属性herf中保存着该热点新闻的url地址,要想抓取这个网页版的IT之家版面,需要模拟通过request模块向IT之家网站服务器发送请求,获取到该页面的内容并通过xpath把所属标签中的内容精确检索。且为防止被网站的反爬虫机制限制甚至拒绝响应,我们需要把爬虫程序伪装成浏览器,即提交请求的时候附加上请求头里面的关键内容,浏览器请求头内容如图4.8所示 1380 | 1381 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg) 1382 | 1383 | 图4.8 浏览器请求网页的请求头内容 1384 | 1385 | 在红框中的user-agent中,包含了浏览器兼容的内核版本,请求电脑的操作系统和位数。有了这些数据,我们的爬虫脚本就可以伪装成一个浏览器请求,从而避免了网站的反爬机制可能带来的问题,整体的实现思路如下,首先,用requests库的get方法发送请求,对于接受的的响应一个html网页代码进行树形结构的解析,然后通过xpath标签路径获取到指定内容的数据,这里需要通过网页代码结构的熟悉和研究找出多个标签之间的内在联系,使用xpath表达式快速检索到所需的数据, 1386 | 1387 | 请求代码如图4.9所示 1388 | 1389 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg) 1390 | 1391 | 图4.9 模拟请求IT之家官网获取响应的代码示意图 1392 | 1393 | Xpath获取特定标签的代码如图4.10所示 1394 | 1395 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image024.jpg) 1396 | 1397 | 图4.10 xpath获取特定标签内容的代码示意图 1398 | 1399 | 运行结果如图4.11所示: 1400 | 1401 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image026.jpg) 1402 | 1403 | 图4.11 IT之家数据获取运行结果终端效果图 1404 | 1405 | 4.2.3图灵机器人接口设计 1406 | 1407 | 图灵机器人的接口创建只需要登录网站, 1408 | 1409 | 创建一个机器人对象,这里的我们需要进行机器人的一个初始化设置,聊天机器人的初始化界面如图4.12所示 1410 | 1411 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image028.jpg) 1412 | 1413 | 图4.12 图灵机器人的应用创建网站示意图 1414 | 1415 | 机器人创建完毕之后,设置他的终端接入方式,图灵机器人的接口,需要根据不同的发送内容,得到相应的信息反馈,图灵机器人的接口是一个成熟并且完善的接口,这里的接口在本脚本中 拟选择使用api接入,因为在聊天机器人的基础上还有集成教师应用等有针对性的功能,如果选择直接个人号接入势必会造成接口的调用冲突,影响用户的使用体验。并且使用api接入,这里会让我们的脚本更加灵活,可以对图灵机器人做出更多针对性的调整。选择api接入如图4.13所示 1416 | 1417 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image030.jpg) 1418 | 1419 | 图4.13 图灵机器人接口选择示意图 1420 | 1421 | 接下来是代码实现,依旧使用requests模块对网页版的图灵机器人数据进行抓取,不同的是,这里我们需要通过提交聊天信息才能获取到图灵机器人的响应,所以此处的请求方式变成了post,代码实现如图4.14所示 1422 | 1423 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg) 1424 | 1425 | 图4.14 图灵机器人数据获取代码示意图 1426 | 1427 | 4.2.4 百度人工智能平台图片文字识别 1428 | 1429 | 百度人工智能平台的应用创建细节如图4.15所示 1430 | 1431 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image034.jpg) 1432 | 1433 | 图 4.15 百度人工智能平台图片文字识别接口设置截图 1434 | 1435 | 百度人工智能平台的图片识别相应代码如图4.16所示 1436 | 1437 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image036.jpg) 1438 | 1439 | 图4.16百度人工智能如图片文字识别接口实现代码 1440 | 1441 | 4.2.5傲梦官方网站教师端数据的获取 1442 | 1443 | ​ 网站数据的抓取是本脚本的难点,因为数据的复杂度远远要超过以上的两种数据,高复杂性带来了更多的处理数据的障碍,首先,我们获取到的数据是需要在登陆状态下的,所以在发送请求的时候除了反爬虫必须的useragent还需要验证身份信息的cookies,这里所以脚本必须要在登陆状态下获取到cookies才能成功请求到网页上的数据,这里就需要用到selenium库,他能够使用脚本对网页进行完全模拟人的操作,经过对傲梦编程网页的登录页面分析如下图所示,傲梦网页主页示意图如图4.17所示 1444 | 1445 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image038.jpg) 1446 | 1447 | 图4.17 傲梦编程网站登录页面 1448 | 1449 | 网址https://all-dream.com/front_login.jsp?param=tacher之后。本需要完成的工作分别是,输入账号和密码,输入验证码,点击登录,如果信息无误,登录成功后,就可以用selenium中的内置方法获取到登陆状态下的网页cookies,账号和密码基本不会改变,主要的问题此时出在了验证码的识别上,首先需要从页面拿到验证码的图片信息,因为验证码是每次请求都不同的,所以要保证webdriver操作页面的时刻的验证码图片信息获取到,此处可以采用webdriver的内建方法save_screenshot对验证码页面进行截图,并且还需要配合PIL的图片操作库,对截取的图片进行剪裁处理。实现代码如下所示: 1450 | 1451 | def getimg(img_time): 1452 | '''得到网页登陆时候所需的验证码图片 1453 | driver是全局变量 后面需要通过driver会的cookies 1454 | 成功过得到会返回True 1455 | ''' 1456 | global driver 1457 | driver = webdriver.Chrome() 1458 | \#driver.set_window_size() # 设置浏览器尺寸 1459 | driver.maximize_window() 1460 | driver.get('https://all-dream.com/front_login.jsp?param=teacher') 1461 | time.sleep(5) # 要加载一段时间,留出时间 1462 | if driver.title == '傲梦直播': 1463 | driver.save_screenshot('.\image\{}.png'.format(img_time)) 1464 | yzm_elmt = driver.find_element_by_xpath(pic_xpth) 1465 | L = yzm_elmt.location['x'] 1466 | T = yzm_elmt.location['y'] 1467 | R = L+yzm_elmt.size['width'] 1468 | B = T+yzm_elmt.size['height'] 1469 | im = Image.open('.\image\{}.png'.format(img_time)) 1470 | print(L,T,R,B) 1471 | im = im.crop((L,T,R,B)) 1472 | im.save('.\image\{}1.png'.format(img_time)) 1473 | time.sleep(1) 1474 | print(L,T,R,B) 1475 | return True 1476 | else: 1477 | return False 1478 | 1479 | 此时图片获取到之后识别成了又一个需要解决的问题,本系统采取两种识别方案交替进行,首先会使用百度的人工智能平台提供的图片文字识别策略,但是不可避免的问题是自动识别具有一定的误差,所以不能保证识别的百分之百成功率,所以这里拟采取图片通过主机微信发送给用户让用户来人工识别,这样图片的识别就能够迎刃而解。以下是两种解决方案状态下的代码线上运行效果。 1480 | 1481 | 使用百度ai人工智能开放平台的解决方案,通过调用接口实现验证码的基本识别,实现代码如下所示: 1482 | 1483 | def aiYzm(filename): 1484 | ''':param filename: 表示图片的文件路径return: 返回图片经过百度开发识别的结果,如识别失败的话直接返回false ''' 1485 | from aip import AipOcr 1486 | """ 你的 APPID AK SK """ 1487 | APP_ID = '16190824' 1488 | API_KEY = 'sW2uzXjyWqiyC5Lq2lNsdnig' 1489 | SECRET_KEY = 'GVF2YX5cS7RZqfXMGgIpnuPDPQyfEyWq' 1490 | client = AipOcr(APP_ID, API_KEY, SECRET_KEY) 1491 | """ 读取图片 """ 1492 | def get_file_content(filePath): 1493 | with open(filePath, 'rb') as fp: 1494 | return fp.read() 1495 | image = get_file_content(filename) 1496 | """ 调用数字识别 """ 1497 | client.numbers(image); 1498 | """ 如果有可选参数 """ 1499 | options = {} 1500 | options["recognize_granularity"] = "big" 1501 | options["detect_direction"] = "true" 1502 | """ 带参数调用数字识别 """ 1503 | a = client.numbers(image, options) 1504 | try: 1505 | a = a['words_result'][0]['words'] 1506 | print(a) 1507 | except: 1508 | return False 1509 | else: 1510 | if len(a) == 4: 1511 | return a 1512 | else: 1513 | return False 1514 | 1515 | 另外一种解决方案是直接把图片经过主机微信号发送给客户端微信,通过用户人工识别图片的结果,进行消息回复之后,实现验证码的人工识别。这里的实现代码如下 1516 | 1517 | imgnum = aiYzm('.\image\{}1.png'.format(shot_tm)) 1518 | if imgnum: 1519 | user.yzm = imgnum 1520 | suss, user.cookies = log_web(user.admin, user.yzm) 1521 | if suss: 1522 | itchat.send_msg('网站登录成功,请稍等片刻数据马上抓取成功', user.username) 1523 | timec = logdata(user) 1524 | else: 1525 | itchat.send_msg('so sad~ 验证码自动识别失败,请重新获取数据', user.username) 1526 | driver.close() 1527 | 1528 | 成功识别图片的运行示意图如图4.18示 1529 | 1530 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image040.jpg) 1531 | 1532 | 图4.18 验证码图像识别成功运行示意图 1533 | 1534 | 失败识别验证码需要人工输入的运行示意图如图4.19所示 1535 | 1536 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image042.jpg) 1537 | 1538 | 图4.19 人工识别验证码运行效果 1539 | 1540 | 接下来依旧使用requests方案对傲梦编程官网的数据进行爬取,通过网站页面的结构分析,发现主要数据分成两部分,已完成课程数据和未完成课程的数据。对应页面的内容如下图所示, 1541 | 1542 | 已完成课程的内容网页效果图如图4.20 1543 | 1544 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image044.jpg) 1545 | 1546 | 图4.20 傲梦编程网站教师端已完成课程效果图 1547 | 1548 | 未完成课程的内容网页效果图如图4.21 1549 | 1550 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image046.jpg) 1551 | 1552 | 图4.21 傲梦编程教师端未完成课程效果图 1553 | 1554 | 通过对页面的html代码分析发现,本分关键代码人如图4.21所示: 1555 | 1556 | 1557 | 1558 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image048.jpg) 1559 | 1560 | 图4.22 傲梦编程网站关键代码截图 1561 | 1562 | 1563 | 1564 | 通过对网站后台代码的研究和探索性检查,网站的数据是异步加载的数据,通过谷歌浏览器的检查工具对网页中的异步加载数据排查(数据存在于检查接口下的NETWORK对应XHR里面) 1565 | 1566 | 网页异步加载数据总页面如图4.23 1567 | 1568 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image050.jpg) 1569 | 1570 | 图4.23 检查接口下异步加载数据列表示意图 1571 | 1572 | 该网页存在所需的加载数据,数据的格式是json格式,以已完成数据中的一页的一条记录为例,数据如下 1573 | 1574 | {"lessonId":"eec9348ceba84ef99e1d6d40edef2943","studentId":"4697f12fdf224456a4a26c417eadcea8","teacherId":"e4ccd1f328d84a76ab46e382d79af6a8","lessonName":"64510班级课程","studentName":"章圣歆","teacherName":"陈奇","lessonStartTime":1557055803000,"lessonEndTime":1557058654000,"teacherComment":"知识点内容:\n\t课程进度 pye21-1\n\t内容总结 贪吃蛇游戏的函数化\n孩子掌握情况:\n\t孩子具体完成情况 能在老师的引导下理解课堂代码的实现逻辑\n\t优点 学习兴趣高 理解能力强\n\t欠缺点 暂无\n需要家长配合:暂无\n上次课作业完成情况:完成 存在问题 已在课堂上解决","teacherCommentLevel":4,"studentComment":null,"lessonStatus":"2","studentCommentLevel":null,"studentCommentOne":null,"studentCommentTwo":null,"studentCommentThree":null,"studentCommentFour":null,"studentCommentFive":null,"teacherCommentOne":4,"teacherCommentTwo":4,"teacherCommentThree":4,"teacherCommentFour":4,"teacherCommentFive":4,"teacherLessonUrl":null,"lessonUrl":"http://timer.91veo.com/v1/meeting/join?id=1402562&value=fafc2c1c46bc952e524ca3c7bb42a1f9","recordUrl":"https://cdn.all-dream.com/user/e4ccd1f328d84a76ab46e382d79af6a8/20190505_202919_zoom_0.mp4","note":"","noteTeacher":"NOIP测试分数:","courseTypeName":"python程序设计","courseTypeId":"702dd6f4b95f418ebf5f54bd652e859f","studentSignNote":"","studentSignState":"1","online":"1","free":"0","homework":"https://cdn.all-dream.com/exercise/307f56ba15f84ce9b94e05ac0345ba4c/425.py"}, 1575 | 1576 | 文件中的json格式的数据可以继续用requests方式进行数据的爬取,这里因为数据是一部加载的数据,需要用到json模块对数据进行格式化处理,换而言之,只有json才能把网页中的结构体数据转换成python的字典格式,但是字典的数据课时处理起来不是非常的方便,在本系统中我们采用pandas的库对数据进行更加精细化的的直观处理。且网页中表示的实现是用unix时间戳来表示,这里本系统采用python的datatime的模块对时间进行格式化的处理。具体的实现代码如下所示: 1577 | 1578 | def getData(cookies): 1579 | '''获取傲梦网站的学生信息以及课程信息 1580 | 返回获取数据的文件所在目录 1581 | 参数是网站所需的cookies 1582 | 数据的精细化处理 是数据的检索更加简单 1583 | ''' 1584 | timec = time.strftime("%Y%m%d%H%M",time.localtime(time.time())) 1585 | os.mkdir('./data/'+timec) 1586 | headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} 1587 | url = 'https://all-dream.com/rest/hour/queryMyCoursePlan4TeacherNew?free=0&limit=10&random=0.5043750329478451&page=1' 1588 | today_class = requests.get(url,headers=headers,cookies=cookies) 1589 | today_class = json.loads(today_class.text) 1590 | print(today_class) 1591 | with open('./data/'+timec+'/今日课程计划','wb') as file: 1592 | pickle.dump(today_class,file) 1593 | url_list = ['https://all-dream.com/rest/courseManage/queryMyOverCourse4Teacher?limit=10&page={}'.format(i+1) for i in range(10)] 1594 | over_all_class = [] 1595 | for url in url_list: 1596 | over_class = requests.get(url,headers=headers,cookies=cookies) 1597 | data_1 = json.loads(over_class.text)['list'] 1598 | over_all_class.append(data_1) 1599 | key = 1 1600 | stOverClass = {} 1601 | for ondPage in over_all_class: 1602 | for oneClass in ondPage: 1603 | stOverClass[key]=oneClass 1604 | key+=1 1605 | df = pd.DataFrame(stOverClass).T 1606 | 1607 | with open('./data/'+timec+'/已完成课程','wb',) as file2: 1608 | pickle.dump(df,file2) 1609 | return timec 1610 | 1611 | 1612 | 1613 | 1614 | 这里为直观展示如图已完成课程数据中的一个数据结构图如图4.24 1615 | 1616 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image052.jpg) 1617 | 1618 | 图4.24 已完成课程数据结构图 1619 | 1620 | 其中满足我们需求的数据只需要学生姓名(studentName)上课时间(lessonStartTime)课程类别(courseTypeName)以及教师评价(teacherComment)其中课堂的上课时间是unix时间戳需要转换成正常显示的时间格式,评价中包含上课进度,学生课堂表现,知识点等内容。在这里我们首先要做的事情是吧数据西安进行存储,这里用到pickle模块,并且为了后期的容易清洗,数据格式用pandas模块中的dataframe数据表的格式保存,待完成课程的数据用以上相同的策略也可以抓取。功能中的今日课程计划和近日课程计划都是对待完成课程数据的检索,某某学生的课堂反馈则是对已完成课程 的数据检索。以及完成课程的excel表格也是对已完成课程的检索,实现代码如下所示: 1621 | 1622 | def getToday(path,flag): 1623 | '''参数是当前目录(今日学生信息的名称)下的文件名称 1624 | 返回值是一个字符串 包含今日未完成课程信息 1625 | 功能:获取当前日期内的上课内容 1626 | ''' 1627 | if flag: 1628 | tm = '近日' 1629 | else: 1630 | tm = '今日' 1631 | str1 = '' 1632 | with open('./data/'+path+'/今日课程计划','rb') as file: 1633 | data = pickle.load(file) 1634 | stlist = data['list'] 1635 | nowday = time.strftime("%Y-%m-%d",time.localtime(time.time())) 1636 | times=0 1637 | if not flag: 1638 | for st in stlist: 1639 | sttime = uTime(st['startTime']) 1640 | if sttime[:10]!=nowday: 1641 | continue 1642 | times+=1 1643 | edtime = uTime(st['endTime']) 1644 | stname = st['studentName'] 1645 | kemu = st['courseTypeName'] 1646 | banji = st['courseHourName'] 1647 | str1 += '\t学生:{} \n\t时间:\n\t{}\n\t{} \n\t科目:\t{} \n\t班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 1648 | else: 1649 | for st in stlist: 1650 | sttime = uTime(st['startTime']) 1651 | times+=1 1652 | edtime = uTime(st['endTime']) 1653 | stname = st['studentName'] 1654 | kemu = st['courseTypeName'] 1655 | banji = st['courseHourName'] 1656 | str1 += '学生:{} \n时间:\n{}\n{} \n科目:{} \n班级:{}\n'.format(stname,sttime,edtime,kemu,banji) 1657 | 1658 | if times >=1: 1659 | return '老师您好,\n{}你总共有{}节课\n内容如下\n'.format(tm,times)+str1 1660 | else: 1661 | return'老师~今天真幸福呀,\n{}你已经完成了所有工作\n当然今天也可能是非常愉快的休息日,\n试试召唤智能机器人,\n \"小小奇\" '.format(tm) 1662 | 1663 | 对于特定学生的课堂表现内容获取函数如下所示 1664 | def getfk(name,timec): 1665 | ''' 1666 | 参数:查看反馈的学生姓名 以及保存本次数据的文件最内层路径 1667 | 返回值:包含匹配到该学生的三条数据 如果先搞改变匹配数据的数量只需要改掉times里的值 1668 | 功能实现原始数据的检索 可通过学生姓名直接检索 1669 | ''' 1670 | with open('./data/'+timec+'/已完成课程','rb') as file: 1671 | df = pickle.load(file) 1672 | student = df[df['studentName']==name] 1673 | msg_list = [] 1674 | for i in range(len(student)): 1675 | st = student.iloc[i] 1676 | remark = st['teacherComment'] 1677 | videourl = st['recordUrl'] 1678 | star = st['teacherCommentOne'] 1679 | stTime = st['lessonStartTime'] 1680 | msg = '这节课的开始时间是:\n{}\n这节课里你对孩子评价是:\n{}\n您为孩子打出惊人的{}颗星\n视频链接:\n{}\n--------------------------------------------' 1681 | msg_one = msg.format(uTime(stTime),remark,star,videourl) 1682 | msg_list.append(msg_one) 1683 | return msg_list 1684 | 1685 | 对于备课表单自动生成,需要把网站爬取的相应数据转换成固定格式的excel格式,pandas的内置方法to_csv可以直接把格式为DataFrame的数据表直接转换成excel表格,实现代码如下所示: 1686 | 1687 | def savetoexcel(a): 1688 | 1689 | ​ for i in a: 1690 | 1691 | ​ with open('傲梦备课表.csv','a+',encoding = 'gbk',newline='')as csvfile: 1692 | 1693 | ​ writer = csv.writer(csvfile) 1694 | 1695 | ​ writer.writerow(list(i.values())) 1696 | 1697 | ​ with open("{}.csv".format('傲梦1')) as aaa: 1698 | 1699 | ​ lalal = pd.read_csv(aaa,header=None,skiprows=6) 1700 | 1701 | ​ lalal.columns = ['姓名', '课程类别', '课堂开始时间', '课堂结束时间', '课程进度', '内容总结'] 1702 | 1703 | lalal.to_excel("{}.xlsx".format('傲梦备课表') 1704 | 1705 | 4.2.5 程序脚本集成 1706 | 1707 | ​ 本系统的代码结构如图所示4.25所示 1708 | 1709 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image054.jpg) 1710 | 1711 | 图4.25 代码文件示意图 1712 | 1713 | 其中start.bat是本系统的快速运行脚本,双击它会自动使用python3版本环境运行代码start.py,而start.py会使用itchat自动登录微信,这里主机微信号需要使用扫描自动生成的微信二维码进行账号授权。经过这一步之后,微信的实时消息就可以被获取到,此时就可以在run.py根据帮助文档中的聊天信息做出相应的响应。其中响应分为傲梦官网学生信息的响应和图灵机器人的信息响应,以及附加功能中的接口调用,比如IT之家热点新闻。其中聊天的对象分为两个权限,对应程序代码中的两个类,代码如下所示 1714 | 1715 | class Friends(): 1716 | def __init__(self): 1717 | with open('./data/好友信息','rb',) as file2: 1718 | self.df =pickle.load(file2) 1719 | def isvip(self,fromusername): 1720 | username = self.df[self.df['Remark'].isin(list(message.keys()))]['UserName'].values 1721 | if fromusername in username: 1722 | return True 1723 | else: 1724 | return False 1725 | 1726 | def readvip(): 1727 | pass 1728 | class Teacher(): 1729 | def __init__(self,username): 1730 | self.username = username 1731 | with open('./data/好友信息','rb',) as file2: 1732 | self.df =pickle.load(file2) 1733 | self.name = self.df[self.df['UserName']==self.username].iloc[0].Remark 1734 | self.admin = message[self.name] 1735 | print(self.name) 1736 | def getmessage(self,flag): 1737 | if self.msg_1['Text'] =='小小奇': 1738 | flag = True 1739 | return flag 1740 | def getcookies(self): 1741 | ''' 1742 | 验证码图片的微信发送 1743 | 验证码保存在本地 文件名由当前时间命名 1744 | 时间作为发送信息的图片名 1745 | ''' 1746 | self.img_time = time.strftime("%Y-%m-%d-%H_%M_%S",time.localtime(time.time())) 1747 | if getimg(self.img_time): 1748 | return self.img_time 1749 | def svtime(self,timec): 1750 | self.timec = timec 1751 | class Nomal(): 1752 | def __init__(self,username): 1753 | self.flag = False 1754 | self.username = username 1755 | 1756 | 通过聊天信息Friends类中isvip方法对信息发送者的权限进行分类,确定是Teacher类还是Nomal类,对于不同权限的用户采取不同的信息响应策略,但是机器人的功能基本一致,机器人权限的开关和信息交互代码如下所示: 1757 | 1758 | nomal = Nomal(msg['FromUserName']) 1759 | print('创建聊天') 1760 | nomal.msg = msg 1761 | if nomal.msg['Text'] in ['start','小小奇','开始']: 1762 | itchat.send_msg('以下内容是自动回复,发送“exit”或者“退出”退出退出自动回复',nomal.username) 1763 | nomalflag[nomal.username] = True 1764 | elif nomal.msg['Text'] in ['help','帮助']: 1765 | itchat.send_image('./image/nomal.png',nomal.username) 1766 | elif nomal.msg['Text'] in ['end','exit','退出']: 1767 | nomalflag[nomal.username] = False 1768 | try: 1769 | if nomalflag[nomal.username]: 1770 | itchat.send_msg(jqr(nomal.msg['Text'])+".",nomal.username) 1771 | except: 1772 | pass 1773 | 1774 | 对于教师权限的用户的功能调用流程控制的代码实现策略如下所示: 1775 | 1776 | user = Teacher(fromusername) 1777 | user.msg_1 = msg 1778 | if user.msg_1['Text'] in ['start','小小奇','开始']: 1779 | itchat.send_msg('以下内容是自动回复,发送“exit”或者“退出”退出退出自动回复',user.username) 1780 | userflag[user.username] = True 1781 | elif user.msg_1['Text'] in ['end','exit','退出']: 1782 | userflag[user.username] = False 1783 | if len(userflag): 1784 | if userflag[user.username]: 1785 | itchat.send_msg(jqr(user.msg_1['Text'])+".",user.username) 1786 | 1787 | if len(userflag)==0 or userflag[user.username]==False: 1788 | if user.msg_1['Text'] == '获取数据': 1789 | itchat.send_msg('请耐心等候,小爬虫正在快吗加鞭获取数据', user.username) 1790 | shot_tm = user.getcookies() 1791 | itchat.send_msg(msg_to_u[1],user.username) 1792 | imgnum = aiYzm('.\image\{}1.png'.format(shot_tm)) 1793 | if imgnum: 1794 | user.yzm = imgnum 1795 | suss, user.cookies = log_web(user.admin, user.yzm) 1796 | if suss: 1797 | itchat.send_msg('网站登录成功,请稍等片刻数据马上抓取成功', user.username) 1798 | timec = logdata(user) 1799 | else: 1800 | itchat.send_msg('so sad~ 验证码自动识别失败,请重新获取数据', user.username) 1801 | driver.close() 1802 | 1803 | else: 1804 | itchat.send_image('.\image\{}1.png'.format(shot_tm),user.username) 1805 | elif user.msg_1['Text'] in ['help', '帮助']: 1806 | itchat.send_image('./image/teacher.png',user.username) 1807 | elif re.findall('\d+',user.msg_1['Text']): 1808 | if len(re.findall('\d+',user.msg_1['Text'])[0])==4: 1809 | user.yzm = re.findall('\d+',user.msg_1['Text'])[0] 1810 | suss,user.cookies = log_web(user.admin,user.yzm) 1811 | if suss: 1812 | timec = logdata(user) 1813 | else: 1814 | itchat.send_msg('so sad~ 验证码输入错误,请重新获取数据', user.username) 1815 | driver.close() 1816 | 1817 | 1818 | 1819 | elif user.msg_1['Text'] in '近日课程计划': 1820 | print(timec) 1821 | user.closetoday = getToday(timec,True) 1822 | itchat.send_msg(user.name[:-4]+user.closetoday,user.username) 1823 | 1824 | elif user.msg_1['Text'] in '今日课程计划': 1825 | print(timec) 1826 | user.today = getToday(timec,False) 1827 | itchat.send_msg(user.name[:-4]+user.today,user.username) 1828 | elif user.msg_1['Text'][-4:]=='课堂反馈': 1829 | ms = getfk(user.msg_1['Text'][:-4],timec) 1830 | print(user.msg_1['Text'][:-4]) 1831 | if len(ms)>=1: 1832 | itchat.send_msg('已为您匹配到{}个结果'.format(len(ms)),user.username) 1833 | for ms_1 in ms: 1834 | itchat.send_msg(ms_1,user.username) 1835 | else: 1836 | itchat.send_msg(msg_to_u[-1],user.username) 1837 | for msg in ms: 1838 | itchat.send_msg(ms,user.username) 1839 | elif user.msg_1['Text'] == '热点': 1840 | day,week = getnews() 1841 | print(day,'\n',week) 1842 | itchat.send_msg(day, user.username) 1843 | itchat.send_msg(week, user.username) 1844 | 1845 | 4.3功能函数 1846 | 1847 | ​ 获取微信好友信息的函数如图4.26所示 1848 | 1849 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image056.jpg) 1850 | 1851 | 图4.26微信登录后好友信息身份信息的汇总获取代码实现 1852 | 1853 | ​ 获取网站cookies的函数如图4.27所示 1854 | 1855 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image058.jpg) 1856 | 1857 | 图4.27 模拟浏览器登录傲梦网站获取cookies代码截图 1858 | 1859 | 处理数据如图4.28所示 1860 | 1861 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image060.jpg) 1862 | 1863 | 图4.28 对爬取到的异步加载数据进行第一次数据筛选代码截图 1864 | 1865 | 1866 | 1867 | 1868 | 1869 | 1870 | 4.4运行设计 1871 | 1872 | 批处理(Batch),也称为批处理脚本。顾名思义,批处理就是对某对象进行批量的处理。批处理文件的扩展名为bat。在本系统中,脚本的运行采用dos批处理运行python代码,严格遵守pep20的程序设计理念,以简约轻便为主旨,程序的运行指令为dos批处理文件,以下是文件的编码示意图如图4.19 1873 | 1874 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image062.jpg) 1875 | 1876 | 图4.19 脚本启动dos文件代码截图 1877 | 1878 | 1879 | 1880 | 4.5系统数据结构设计 1881 | 1882 | 4.5.1 用户傲梦网站的身份信息 1883 | 1884 | 教师的个人信息表设计如表4.1所示, 1885 | 1886 | 1887 | 1888 | 表4.1 教师个人信息表 1889 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | | 姓名 | 账号 | 密码 | 1903 | | ---- | ----------- | ------ | 1904 | | 陈奇 | 18000000000 | 123456 | 1905 | 1906 | 教师的身份信息以上表中的格式存储,内容经过base64加密, 1907 | 1908 | 4.5.2 学生已完成课程数据 1909 | 1910 | ​ 学生的已完成课程数据格式如表4.2所示 1911 | 1912 | 表4.2 学生已完成课程数据表 1913 | 1914 | 1915 | 1916 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | 1927 | 1928 | 1929 | 1930 | 1931 | 1932 | 1933 | 1934 | | 学生姓名 | 上课时间 | 科目 | 教师评价 | 上课进度 | 1935 | | -------- | -------------------------------------- | ---------------- | ------------------------------------ | ------------------ | 1936 | | 李一一 | 2019-01-01 10:30 2019-01-01 11:20 | Python程序与设计 | 包含学生课堂表现,课堂知识点,等内容 | Python初级课第一课 | 1937 | 1938 | 1939 | 1940 | 4.5.3学生待完成课程数据 1941 | 1942 | ​ 学生的待完成课程数据表如表4.3所示 1943 | 1944 | 表4.3 学生未完成课程数据表 1945 | 1946 | 1947 | 1948 | 1949 | 1950 | 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1958 | | 学生姓名 | 上课时间 | 科目 | 1959 | | -------- | ---------------------------------- | ---------------- | 1960 | | 李一一 | 2019-01-01-10:30至2019-01-01-11:20 | Python程序与设计 | 1961 | 1962 | 1963 | 1964 | 1965 | 1966 | 1967 | 5 测试与结果分析 1968 | 1969 | 5.1 运行环境 1970 | 1971 | ​ 硬件:因为需要实时获取,所以需要运行在服务器环境中,本系统运行环境在阿里云的云服务器。 1972 | 1973 | ​ 软件:本脚本需要再python3.的环境下运行,webdriver需要在谷歌浏览器的安装目录下保存谷歌浏览器的webdriver驱动。 1974 | 1975 | 5.2运行界面及结果测试 1976 | 1977 | 5.2.1代码的运行 1978 | 1979 | ​ 测试环境: 1980 | 1981 | ​ 操作系统:Wingdows10企业版 64位 1982 | 1983 | ​ 运行方式:Dos批处理文件 1984 | 1985 | ​ Python版本:Python3.7.0 1986 | 1987 | ​ 浏览器版本:Goole Chrome版本 74.0.3729.131(正式版本) (64 位) 1988 | 1989 | 运行界面截图如下图5.1所示 1990 | 1991 | ​ ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image064.jpg) 1992 | 1993 | ​ 图5.1 程序运行启动成功终端效果图 1994 | 1995 | 5.2.2 爬取数据的展示 1996 | 1997 | 新闻热点的终端输出展示截图如图5.2所示 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image066.jpg) 2008 | 2009 | 图5.2 热点数据的终端输出效果图 2010 | 2011 | 微信端新闻热点新闻的截图如图5.3所示 2012 | 2013 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image068.jpg) 2014 | 2015 | 图5.3 热点数据的微信端输出效果图 2016 | 2017 | 鉴于篇幅限制,以下为代码运行结果只展示微信端截图, 2018 | 2019 | 聊天机器人功能检测如图5.4所示 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image070.jpg) 2026 | 2027 | 图5.4聊天机器人微信端输出效果图 2028 | 2029 | 傲梦编程网站数据的检索测试示意图运行截图如图5.5所示 2030 | 2031 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image072.jpg) 2032 | 2033 | 图5.5获取傲梦数据微信端输出效果图 2034 | 2035 | 2036 | 2037 | 傲梦网站自动生成的备课表如图5.6所示 2038 | 2039 | ![img](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image074.jpg) 2040 | 2041 | ​ 图5.6 脚本自动生成备课表的文件预览图 2042 | 2043 | 2044 | 2045 | 2046 | 2047 | 2048 | 2049 | 2050 | 2051 | 2052 | 2053 | 2054 | 2055 | 2056 | 2057 | 2058 | 2059 | 2060 | 2061 | 2062 | 2063 | 2064 | 2065 | 2066 | 2067 | 2068 | 2069 | 2070 | 2071 | 参考文献 2072 | 2073 | [1] Allen B. Downey.《Think Python: How to Think Like a Computer Scientist》Green Tea Press 2074 | 2075 | [2] Python程序设计 [An Introduction to Programming Using Python].[美] 戴维 I.施奈德(David I. Schneider)著;车万翔 译 2076 | 2077 | | [3]檀冬宇.基于Python的大众点评网数据抓取技术研究[J].计算机产品与流通,2019(05):116. | 2078 | | ------------------------------------------------------------ | 2079 | | [4]. Biophysical Society; Python hearts reveal mechanisms relevant to human heart health and disease[J]. NewsRx Health & Science,2019. | 2080 | | [5]Tomas Beuzen,Joshua Simmons. A variable selection package driving Netica with Python[J]. Environmental Modelling and Software,2019,115. | 2081 | | [6]Simon Olofsson,Lukas Hebing,Sebastian Niedenführ,Marc Peter Deisenroth,Ruth Misener. GPdoemd: A Python package for design of experiments for model discrimination[J]. Computers and Chemical Engineering,2019,125. | 2082 | | [7]Omid Haji Maghsoudi,Annie Vahedipour,Thomas Hallowell,Andrew Spence. Open-source Python software for analysis of 3D kinematics from quadrupedal animals[J]. Biomedical Signal Processing and Control,2019,51. | 2083 | | [8]Theo Steininger,Jait Dixit,Philipp Frank,Maksim Greiner,Sebastian Hutschenreuter,Jakob Knollmüller,Reimar Leike,Natalia Porqueres,Daniel Pumpe,Martin Reinecke,Matevž Šraml,Csongor Varady,Torsten Enßlin. NIFT y 3 – Numerical Information Field Theory: A Python Framework for Multicomponent Signal Inference on HPC Clusters[J]. Annalen der Physik,2019,531(3). | 2084 | 2085 | 2086 | 2087 | 2088 | 致 谢 2089 | 2090 | ​ 经过两个多月的努力,本脚本完美上线,在这里致谢同事罗煜,鲍得江等人的帮忙测试功能,提出了很多好的意见,感谢百度人工智能开放平台,解决了一部分验证码识别的问题,感谢图灵机器人的开发公司北京光年无限科技及开发人员。感谢我的毕业设计指导老师任强老师,为我的脚本完善提供了很好的建议和指导。 2091 | 2092 | ​ 除此之外,感激大学期间所有的老师们,他们带我走进了计算机这个神奇并且美丽的世界,感激车鹏飞老师,他用浅显易懂的方式让我理解了编程语言的内部机制,感激孙少波老师,他带我走进python的世界,并给我了很多学习和项目的经验,记得大一的时候,在张岗亭老师的引导下,当我用c语言完成99乘法表的时候,满心的激动,后来通过任强老师的网页设计,我搭建出了自己的第一个个人网页,所有的老师们带给我的知识,都让我在后来的学习中获益匪浅。 2093 | 2094 | ​ 最后,感谢我的舍友李尧,作为一个刚上大学时候连搜索引擎都不能熟练应用的电脑小白 ,在他的指导下,学会了科学的使用电脑,这让我的学习效率,事半功倍。 --------------------------------------------------------------------------------