xhtdtk 发表于 2021-12-19 15:50

利用公众号自动回复制作查询学时(Requests)

本帖最后由 xhtdtk 于 2021-12-22 17:59 编辑

前因:小型的教育机构想弄一个查询学时的工具,但是又不想搞的太麻烦怎么办呢,突发奇想利用公众号自动回复的功能不就OK了吗,还能让家长关注公众号。

制作流程:先尝试实现功能,后获取学时数据

尝试实现功能:
一、查看提交的表单数据
对表单里的数据进行分析,我一般采用两个步骤。
第一个步骤:表单数据比较,查看表单数据变化的规律
第一次提交:

第二次提交(同一关键字增加回复消息):

第三次提交(新的关键词回复):

分析:
第一次提交和第二次提交比较:ruleid不同,猜测第一次提交ruleid为0,提交后生成ruleid,说明在同一关键字下增加消息要先获取ruleid;多了一组type,field,content,是新增的回复消息。
第一次提交和第三次提交比较:仅新增的规则不同,没有变化的暂时视为常量。

第二个步骤:查找需要获取的数据
我们每一次点击到实现了最终效果,可能都是在向服务器发送请求,所以我们需要查找的数据更有可能出现在最终效果的某一次点击上。
如果是静态的数据,可以直接查找;如果是动态的,可能涉及一些JS逆向。

在开发者模式下直接查找ruleid的值,直接获取

问题1:即使表单数据准备完整,发送POST请求还是失败了
在查看请求头时发现
{’Content-Type‘: 'application/x-www-form-urlencoded; charset=UTF-8'}
说明表单数据要进行url编码再进行请求
data=urllib.parse.urlencode(data)

问题2:一共可以添加200个关键词回复,每个回复只能添加5个文本,每个文本只能限制300字
写代码时注意,每当文本超过270字左右(误差计算在内270字刚刚好),表单数据就要添加第二个文本

二、根据上课记录表,提取收据
表格格式:

获取数据代码:
def data():
      wb=openpyxl.load_workbook('学期上课记录表.xlsx',data_only=True)
      dict_student_sign={}
      for each_wsname in wb.sheetnames:
                if each_wsname=='课时':
                        continue
                ws=wb
                for wsrow in range(4,ws.max_row):
                        if not ws.cell(wsrow,2).value in and not ws.cell(wsrow,2).value in list(dict_student_sign.keys()):
                              dict_student_sign={}
                              dict_student_sign['考勤']=[]
      for each_wsname in wb.sheetnames:
                ws=wb
                if each_wsname=='课时':
                        for wsrow in range(2,ws.max_row+1):
                              dict_student_sign['课时']=ws.cell(wsrow,2).value
                              wscolumn=3
                              str_=''
                              while True:
                                        if ws.cell(wsrow,wscolumn).value==None:
                                                break
                                        else:
                                                str_=str_+str(ws.cell(wsrow,wscolumn).value)+'+'
                                        wscolumn=wscolumn+1
                              dict_student_sign['考勤'].append('总课时:'+str_[:-1])
                        continue
                for wsrow in range(4,ws.max_row+1):
                        if ws.cell(wsrow,2).value in list(dict_student_sign.keys()):
                              for wscolumn in range(3,33):
                                        if ws.cell(wsrow,wscolumn).value in ['出勤','未出勤','补课']:
                                                x=3
                                                while True:
                                                      if wsrow-x>7:
                                                                x=x+7
                                                      else:
                                                                break
                                                if ws.cell(wsrow-(wsrow-x),wscolumn).value in :
                                                      title=''
                                                else:
                                                      title=ws.cell(wsrow-(wsrow-x),wscolumn).value
                                                if ws.cell(wsrow,wscolumn).value in ['未出勤']:
                                                      dict_student_sign['考勤'].append(each_wsname+str(ws.cell(1,wscolumn).value)+'日\n'+ws.cell(wsrow,wscolumn).value+title+'☆余'+str(dict_student_sign['课时']-0)+'课时')
                                                else:
                                                      dict_student_sign['考勤'].append(each_wsname+str(ws.cell(1,wscolumn).value)+'日\n'+ws.cell(wsrow,wscolumn).value+title+'★余'+str(dict_student_sign['课时']-2)+'课时')
                                                      dict_student_sign['课时']=dict_student_sign['课时']-2
      #print(dict_student_sign)
      return dict_student_sign

效果:

返回了字典

三、完善功能
查询已发信息(token,cookie需要手动修改):
def chat(token):
      header={
                'Host': 'mp.weixin.qq.com',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
                'Cookie': '自己添加'
      }
      url='https://mp.weixin.qq.com/advanced/autoreply'
      param={
                'action': 'smartreply',
                'token': token,
                'lang': 'zh_CN',
                'count': 200,
                'offset': 0
      }
      rep=requests.get(url,headers=header,params=param)
      soup=BeautifulSoup(rep.text)
      for each_script in soup.find_all('script',type='text/javascript'):
                if '// 开启了关键词回复' in str(each_script):
                        text=re.sub('\n|\r| |<.*?>|//.*,//','',str(each_script))
                        text=re.sub(',func_ban_info:\\[//能力封禁\\]|\\.replace.*?\\)|//用数组是为了兼容appmsg_gray|\\*1','',text)
                        text=re.findall('list:(\\[.*\\])',text)
                        text=re.sub(',}','}',text)
                        text=json.loads(text)
      #print(text)
      dict_content={}
      for each_student in text:
                list_content=[]
                student_name=each_student['keyword_list']['content']
                ruleid=each_student['rule_id']
                dict_content={}
                dict_content['rule_id']=ruleid
                if each_student['keyword_list']['content']!=None:
                        for each_reply_list in each_student['reply_list']:
                              for each_content in each_reply_list['content'].split('时\n'):
                                        if each_content!='':
                                                list_content.append(each_content+'时')
                        dict_content['content']=list_content
      #print(dict_content)
      return dict_content

效果:


更新自动回复(token,cookie需要手动修改):
def function(excel_data,web_chat,token):
      header={
                'Referer': 'https://mp.weixin.qq.com/advanced/autoreply?action=smartreply&t=ivr/keywords&token='+str(token)+'&lang=zh_CN',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
                'Cookie': '自己添加'
      }
      url='https://mp.weixin.qq.com/advanced/setreplyrule'
      param={
                'lang': 'zh_CN',
                'cgi': 'setreplyrule',
                'fun': 'save',
                't': 'ajax-response',
                'token': token
      }
      for each_data in excel_data.keys():
                data={'token': token,'lang': 'zh_CN','f': 'json','ajax': 1,'replytype': 'smartreply','allreply': 1,'replycnt': 1,'keywordcnt': 1,'matchmode0': 1}
                if not each_data in list(web_chat.keys()):
                        data['ruleid']=0
                else:
                        data['ruleid']=web_chat['rule_id']
                        if excel_data['考勤']==web_chat['content']:
                              continue
                data['rulename']=each_data+'剩余课时'
                data['keyword0']=each_data
                num_content=0
                str_content=''
                for each_content in excel_data['考勤']:
                        if len(str_content)<=270:
                              str_content=str_content+each_content+'\n'
                              data['content'+str(num_content)]=str_content
                              data['type'+str(num_content)]=1
                              data['fileid'+str(num_content)]='undefined'
                        else:
                              num_content=num_content+1
                              str_content=''
                all_content=0
                for content_content in data.keys():
                        if 'content' in content_content:
                              all_content=all_content+1
                data['replycnt']=all_content
                data=urllib.parse.urlencode(data)
                print(each_data+'更新成功')
                rep=requests.post(url,headers=header,params=param,data=data)
                time.sleep(2)

token和cookie在哪里:


最终效果:
只要更新了上课记录的表格,就能更新到公众号


使用建议:
获取学时返回的是字典,无论是哪种记录表,只要返回的字典格式和我的一样,就能使用我的代码了

ZVesper 发表于 2021-12-19 16:06

验证一句话,有需求才有动力

lanzhe00 发表于 2021-12-19 16:16

学习了!这个应用挺好。

geryjun 发表于 2021-12-19 16:26

学习了!看起来不错

我来了老大 发表于 2021-12-19 16:41

不错不错!楼主的行动力太强了{:301_975:}我也想给我的公众号搞一个

1wang 发表于 2021-12-19 16:45

这样查方便

guide 发表于 2021-12-19 17:25

不错学习了

归隐小赵 发表于 2021-12-19 18:47

emm,微信有对外的api的,直接把微信回复接入过来,用py开个flask不是更适合吗

wangxd 发表于 2021-12-19 20:00

验证一句话,有需求才有动力

kuixu 发表于 2021-12-19 21:40

学习了~很有帮助
页: [1] 2
查看完整版本: 利用公众号自动回复制作查询学时(Requests)