python发送微信
申请企业微信
使用python发送信息到企业微信,同时支持python2与python3环境,需要先申请一个企业微信,然后创建应用,获取以下三个信息
企业IP、Agentid、Secret
网信为创建的应用名称
脚本描述
将以上三个信息替换到脚本中,主要是
class WeiXin(object):部分,其他的辅助性工具类,收集的一些常用脚本可不用关注
#!/usr/bin/env python
#coding=utf-
'''
Created on 2018年2月8日 @author: root
''' from datetime import datetime
import sys, os, re, json,socket,time
from subprocess import Popen, PIPE
from sys import version_info
if version_info.major == and version_info.minor >=:
import urllib.request as urllib2
pyversion =
elif version_info.major == :
pyversion =
else:
import urllib2
pyversion = try:
if version_info.major and version_info.major == :
pyversion=
elif version_info.major and version_info.major == :
pyversion=
else:
pyversion=
except Exception as e:
pyversion = localpath = os.path.split(os.path.realpath(__file__))[] class OSCmd():
'''
OS Command:直接可调用执行命令的方法,不包括业务逻辑
本脚本为分好层次的项目中抽出出来的方法,归为3个类,一个是命令类OSCmd,一个是系统检查类;
为保持代码统计,命令类OSCmd是项目是调试好的代码复制过来的,不在此脚本中修改,每次都去项目中取相应的方法
系统检查逻辑类可以修改
''' def __init__(self):
'''
Constructor
''' def exes(self, cmd_shell):
'''
call shell command
'''
s = Popen(cmd_shell, shell=True, stdout=PIPE);
if pyversion == :
s = s.encode(encoding="utf-8")
return (s.communicate()[]).strip('\n') def getexesfstval(self, cmd_shell):
'''
call shell command
比如在通过ps -ef过滤进程号的时候,在eclipse中执行可以返回正确的结果,然后在shell在测试脚本时却多返回一个数字(比如13742),这里取第一个数字,舍弃多返回的数字
'''
s = Popen(cmd_shell, shell=True, stdout=PIPE);
res = (s.communicate()[]).strip('\n')
ress = res.split('\n')
return ress[] def exef(self, filename, args):
'''
filename : the file is needed to exec as the way like "./filename args"
args: list []
for exp: oscmd.exef('/scripts/test/t2.py', ['a','b'])
'''
args.insert(, '')
if os.path.exists(filename):
os.execv(filename, args)
else:
print('The {0} is not exist'.format(filename)) def getLineFromFile(self, targetFile, *param):
'''
文件中,返回某行记录,适合小文件
f:返回首行
l:返回末行
n:返回第n行,n为正整数
默认返回最后一行数据
'''
global f
try:
f = open(targetFile);
pnum = len(param);
with open(targetFile, 'r') as f: # 打开文件,适合小文件
lines = f.readlines() # 读取所有行
first_line = lines[] # 取第一行
last_line = lines[-] # 取最后一行 if pnum > :
if type(param[]) == type('a') and param[].lower() == 'f':
return first_line
elif type(param[]) == type('a') and param[].lower() == 'l':
return last_line
else:
return lines[int(param[]) - ]
return last_line
finally:
f.close(); def timeminustoS(self, t1, t2):
t1 = time.localtime(t1)
t1 = time.strftime("%Y-%m-%d %H:%M:%S", t1)
t1 = datetime.strptime(t1, "%Y-%m-%d %H:%M:%S") # t2=time.localtime(t2)
t2 = time.strftime("%Y-%m-%d %H:%M:%S", t2)
t2 = datetime.strptime(t2, "%Y-%m-%d %H:%M:%S")
return self.total_seconds(t2 - t1) def total_seconds(self, time_delta):
'''
python 2.6 has not total_seconds method
'''
return 1.0 * (time_delta.microseconds + (time_delta.seconds + time_delta.days * * ) * ** ) / ** def rmfileFrmNow(self,p_savenum, targetDir, mins, *contain):
'''
删除指定目录下指定分钟之前的文件,不删除目录,也不递归目录 删除/backup/rman/backdb目录下超过30个小时的文件
rmfileFrmNow('/backup/rman/backdb', *) 删除/backup/rman/backdb目录下超过30个小时,包含_MEMDB_20字符的文件
rmfileFrmNow('/backup/rman/backdb', *,'_MEMDB_20') 删除/backup/rman/backdb目录下超过30个小时,同时包含back_full_、_MEMDB_20字符的文件
rmfileFrmNow('/backup/rman/backdb', *,'back_full','_MEMDB_20')
'''
clen = len(contain)
defilist = []
if os.path.isdir(targetDir):
for fil in os.listdir(targetDir):
if clen > :
for c in contain:
if c in str(fil):
defilist.append(fil)
#排序
defilist = self.get_filist_bytime(defilist)
lsz = len(defilist)
if lsz > p_savenum:
defilist = defilist[,lsz - p_savenum] if os.path.isdir(targetDir):
for fil in os.listdir(targetDir):
flag = True
if clen > :
for c in contain:
if not c in str(fil):
flag = False
if flag:
fil = os.path.join(targetDir, fil)
if os.path.isfile(fil):
if self.isBeforeMins(fil, mins):
os.remove(fil) def isBeforeMins(self, fil, mins):
'''
判断一个文件的最后修改时间距离当前时间,是否超过指定的分钟数
'''
if os.path.isfile(fil):
mtfile = os.path.getmtime(fil)
tnow = time.localtime()
sec = self.timeminustoS(mtfile, tnow)
mms = round(sec / )
mins = eval(mins)
if mms - mins > :
return True
return False def isMorthanSize(self, fil, siz):
'''
判断一个文件是否超过指定的大小,单位为M
'''
if os.path.isfile(fil):
filsiz = os.path.getsize(fil)
fsiz = eval(siz)**
if filsiz - fsiz > :
return True
return False def rmfilMorthanSize(self, targetDir, siz, *contain):
'''
删除指定目录下超过指定大小的文件,不删除目录,也不递归目录 删除/backup/rman/backdb目录下超过2G大小的文件
rmfileFrmNow('/backup/rman/backdb', *) 删除/backup/rman/backdb目录下超过10G大小,包含_MEMDB_20字符的文件
rmfileFrmNow('/backup/rman/backdb', *,'_MEMDB_20') 删除/backup/rman/backdb目录下超过3G大小,同时包含back_full_、_MEMDB_20字符的文件
rmfileFrmNow('/backup/rman/backdb', *,'back_full','_MEMDB_20')
'''
clen = len(contain)
if os.path.isdir(targetDir):
for fil in os.listdir(targetDir):
flag = True
if clen > :
for c in contain:
if not c in str(fil):
flag = False
if flag:
fil = os.path.join(targetDir, fil)
if os.path.isfile(fil):
if self.isMorthanSize(fil, siz):
os.remove(fil) def mkdir(self, dr, *mod):
# import stat
s1 = str(dr)
if s1.startswith("~/"):
s1 = s1[:]
homedir = os.environ['HOME']
s1 = '%s%s' % (homedir, s1)
if not os.path.exists(s1):
cmd_shell = 'mkdir -p %s' % (s1)
# os.mkdir(dir) 这个命令不识别linux 用户home目录“~”符号
self.exes(cmd_shell)
p_num = len(mod)
chmod = 'chmod -R 755 %s' % (s1)
if p_num == :
chmod = 'chmod -R %s %s' % (mod[], s1)
self.exes(chmod)
# os.chmod(dir, mod)
else:
# os.chmod(dir, stat.S_IRWXU|stat.S_IRGRP|stat.S_IROTH) 该行会抛出异常 TypeError: coercing to Unicode: need string or buffer, builtin_function_or_method found
self.exes(chmod)
return s1 def mknod(self, filename, *mod):
s1 = str(filename)
if s1.startswith("~/"):
s1 = s1[:]
homedir = os.environ['HOME']
s1 = '%s%s' % (homedir, s1)
if not os.path.exists(s1):
cmd_shell = 'touch %s' % (s1)
self.exes(cmd_shell)
p_num = len(mod)
chmod = 'chmod -R 644 %s' % (s1)
if p_num == :
chmod = 'chmod -R %s %s' % (mod[], s1)
self.exes(chmod)
else:
self.exes(chmod)
return s1 def get_filist_bytime(self,file_path):
dir_list = os.listdir(file_path)
if not dir_list:
return
else:
# 注意,这里使用lambda表达式,将文件按照最后修改时间顺序升序排列
# os.path.getmtime() 函数是获取文件最后修改时间
# os.path.getctime() 函数是获取文件最后创建时间
dir_list = sorted(dir_list, key=lambda x: os.path.getmtime(os.path.join(file_path, x)))
return dir_list def shichaByMin(self, t1, t2):
'''
计算以下三种类型之间的时间差
time.time()-浮点型,time.localtime()-struct_time型、datetime.now()-datetime型
'''
t1 = datetime.strptime(t1, "%Y-%m-%d %H:%M:%S")
t2 = datetime.strptime(t2, "%Y-%m-%d %H:%M:%S")
return round(self.total_seconds(t2 - t1) / ) def total_seconds(self, time_delta):
'''
python 2.6 has not total_seconds method
'''
return 1.0 * (time_delta.microseconds + (time_delta.seconds + time_delta.days * * ) * ** ) / ** class Properties:
# 脚本默认配置路径
oscheck_properties = '/tmp/.python-eggs/.oscheck.properties'
file_name = ''
oscmd = OSCmd() def __init__(self, file_name='.oscheck.properties'):
'''
将配置文件转化为列表,以列表的读取方式进行值的替换
'''
dr = '/tmp/.python-eggs/'
if not os.path.exists(dr): # 当目录以~开头时该行永为True,但下面的语句会自判断
self.oscmd.mkdir(dr,'') if not os.path.exists(file_name): # 当目录以~开头时该行永为True,但下面的语句会自判断
file_name = self.oscmd.mknod(file_name,'')
# os.mknod(file_name) ~ self.file_name = file_name
self.properties = {}
try:
fopen = open(self.file_name, 'r')
for line in fopen:
line = line.strip()
if line.find('=') > and not line.startswith('#'):
strs = line.split('=')
self.properties[strs[].strip()] = strs[].strip()
except Exception as e:
raise e
else:
fopen.close() def has_key(self, key):
return key in self.properties def keys(self, key):
return self.properties.keys(); def get(self, key, default_value=''):
if key in self.properties:
return self.properties[key]
return default_value def put(self, key, value):
self.properties[key] = value
self.replace_property(self.file_name, key + '=.*', key + '=' + str(value), True) def putjson(self, key, values):
'''
以json的形式存储prop中的value,可以处理一些特殊字符,比如=
'''
pj = {key: values}
value = json.dumps(pj)
self.put(key, value) def getjsonvalue(self, key, default_value=''):
'''
以json的形式存储prop中的value,可以处理一些特殊字符,比如=
'''
if key in self.properties:
value = self.get(key)
valuedict = json.loads(value)
return valuedict[key]
return default_value def toasc(self, ss):
asclst = []
for em in bytearray(ss):
asclst.append(em)
return asclst def asctostr(self, asclst):
ss = ''
for em in asclst:
ss += str(chr(em))
return ss def putpwd(self, key, value):
'''
字符串以ASCII码存储
'''
asclst = self.toasc(value)
self.putjson(key, asclst) def getpwd(self, key):
asclst = self.getjsonvalue(key)
pwd = self.asctostr(asclst)
return pwd def replace_property(self, file_name, from_regex, to_str, append_on_not_exists=True):
'''
新写入数据后,替换文件以永久保存
:param file_name:
:param from_regex:
:param to_str:
:param append_on_not_exists:
:return:
'''
import tempfile
tmpfile = tempfile.TemporaryFile() if os.path.exists(file_name):
r_open = open(file_name, 'r')
pattern = re.compile(r'' + from_regex)
found = None
for line in r_open:
if pattern.search(line) and not line.strip().startswith('#'):
found = True
line = re.sub(from_regex, to_str, line)
if pyversion == :
line = line.encode(encoding="utf-8")
tmpfile.write(line)
if not found and append_on_not_exists:
to_str = '\n' + to_str
if pyversion == :
to_str = to_str.encode(encoding="utf-8")
tmpfile.write(to_str)
r_open.close()
tmpfile.seek() content = tmpfile.read() if os.path.exists(file_name):
os.remove(file_name) w_open = open(file_name, 'w')
if pyversion == :
content = content.decode('utf-8')
w_open.write(content)
w_open.close()
tmpfile.close()
else:
print("file %s not found" % (file_name)) def parsePro(file_name='/tmp/.python-eggs/.oscheck.properties'):
return Properties(file_name) class Log:
def __init__(self):
'''
Constructor
''' logfile = os.path.join(localpath, 'scheck.log') def setlog(self, logfile):
self.logfile = logfile def log(self, strs, sp='a'):
open(self.logfile, sp).write('%s\n' % (strs)) def inserttime(self, sp='a'):
now = datetime.now()
strs = now.strftime('%Y-%m-%d %H:%M:%S')
oscmd = OSCmd()
oscmd.mknod(self.logfile, '')
open(self.logfile, sp).write('%s\n' % (strs)) def frmMsg(self,content):
'''
格式化信息输出
:param content:
:return:
'''
curtime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
hname = socket.gethostname()
IPADDR = socket.gethostbyname(hname)
cnt = "内容:{0} <br/>时间:{1} <br/>信息来自 {2} {3}".format(content,curtime,hname,IPADDR)
return cnt class WeiXin(object):
'''
发送微信
'''
token_url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'
cropmsg ={
'corpid' : 'wwe***2ed*********',
'corpsecret' : 'Mgyi*****ahx3O-******HkLfg'
}
sendmsg = {}
access_token_key="weixin_access_token"
time_token_key="weixin_tokenkey_gettime"
oscmd = OSCmd()
prop = parsePro()
log = Log() def __init__(self):
'''
Constructor
''' def formatContent(self,content):
cnt=self.log.frmMsg(content)
return cnt def setMsg(self,param):
arg_num=len(param)
content = param[]
content = self.formatContent(content)
if pyversion == :
content = content.decode('utf-8') if arg_num == :
touser="@all"
agentid=""
elif arg_num == :
touser=param[]
agentid=""
elif arg_num == :
touser=param[]
agentid=param[] self.sendmsg = {
"touser":touser,
"agentid":agentid,
"msgtype": "text",
"text":{
"content":content
}
} def updateToken(self):
access_token_response = self.geturl(self.token_url, self.cropmsg)
access_token = (json.loads(access_token_response)['access_token']).encode('utf-8')
self.prop.put(self.access_token_key, access_token)
self.prop.put(self.time_token_key, datetime.now().strftime('%Y-%m-%d %H:%M:%S')) def get_access_token(self):
'''
获取访问凭证,经过编码的一串字符串数据
每两个小时取一次即可
'''
if not self.prop.has_key(self.time_token_key):
self.updateToken()
else:
curtime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
oldtime = self.prop.get(self.time_token_key)
shicha = self.oscmd.shichaByMin(oldtime,curtime)
if shicha > :
self.updateToken() return self.prop.get(self.access_token_key) def encodeurl(self,dic):
'''
将字典转换为url参数传值方式,key1=value1&key2=value2
'''
data = ''
for k,v in dic.items():
data += '%s=%s%s' % (k,v,'&')
return data def geturl(self,url,data):
'''
data为字典类型的参数,
返回类型<type 'unicode'>,json
'''
data = self.encodeurl(data)
response = urllib2.urlopen('%s?%s' % (url,data))
return response.read().decode('utf-8') def posturl(self,url,data,isjson = True):
'''
发送json数据
返回类型<type 'unicode'>,json
'''
if isjson:
data = json.dumps(data) #dict
if pyversion == :
data = data.encode(encoding="utf-8")
response = urllib2.urlopen(url,data)
return response.read().decode('utf-8') def sampleSend(self,content):
self.setMsg(content)
# 获取企业访问凭证
access_token = self.get_access_token()
sendmsg_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s' % access_token
print (self.posturl(sendmsg_url,self.sendmsg)) def showExample(self):
if len(sys.argv) == :
touser,notuse,content = sys.argv[:]
else:
print ('error segments, now exit')
sys.exit() def send(self,param):
ll = Log()
arg_num=len(param)
if arg_num >=:
self.sampleSend(param)
#ll.log('%s'%(param)) return '' def showUsing(self):
print ('There must be more than 1 params. For example:')
print ('python sendweixin.py "微信发送信息调试 " ')
print ('python sendweixin.py "微信发送信息调试 " "微信用户ID" ')
print ('注意事项,该脚本尚存在一个问题,首次发送微信时会报access_token missing,第二次无此问题')
print ('python sendweixin.py "微信发送信息调试 " "微信用户ID" "企业微信号"')
print ('error segments, now exit') if __name__ == '__main__': inp = sys.argv
arg_num = len(inp)
wxmsg = WeiXin() if arg_num > :
res = wxmsg.send(sys.argv[:])
else:
wxmsg.showUsing()
sys.exit()
重点为以下两段代码,企业与应用的标识
cropmsg ={
'corpid' : 'wwe***2ed*********',
'corpsecret' : 'Mgyi*****ahx3O-******HkLfg'
}
如果输入一个参数,则默认发送给企业微信中可以访问该应用的所有用户;第二个参数指定具体的微信号
if arg_num == :
touser="@all"
agentid=""
elif arg_num == :
touser=param[]
agentid=""
elif arg_num == :
touser=param[]
agentid=param[]
示例
$ python sendwx.py "阳光、沙滩、海浪、老船长……"
{"errcode":,"errmsg":"ok","invaliduser":""}
python发送微信的更多相关文章
- python发送微信及企业微信消息
1.发送微信消息 直接使用第三方库 itchat,其文档中有详细使用方式:https://itchat.readthedocs.io/zh/latest/ 如下实例为 发送群聊信息 # -*- cod ...
- Python 发送微信小程序的模板消息
在小程序的开发过程中,会存在模板消息的发送,具体文档见 这里,模板消息的发送是和语言无关的,这里将简要写一下怎么用 Python 给用户发送模板消息. 通过文档可以知道,发送的时候,需要使用小 ...
- Python发送微信消息
针对此 需要安装itchat第三方模块 采用pip安装就可以了 pip install itchat import itchatimport time#引入时间函数进行测试time_format= ...
- python使用itchat发送微信消息提醒
最近在学习一点python,先找了找有趣的应用,实际修改跑了一下提高兴趣程度. 找到itchat,它的简介是这样的: “itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单. ...
- 用python自制微信机器人,定时发送天气预报
0 引言 前段时间找到了一个免费的天气预报API,费了好段时间把这个API解析并组装成自己想用的格式了,就想着如何实现每天发送天气信息给自己.最近无意中发现了wxpy库,用它来做再合适不过了.以下是w ...
- 全网最全的Windows下Anaconda2 / Anaconda3里Python语言实现定时发送微信消息给好友或群里(图文详解)
不多说,直接上干货! 缘由: (1)最近看到情侣零点送祝福,感觉还是很浪漫的事情,相信有很多人熬夜为了给爱的人送上零点祝福,但是有时等着等着就睡着了或者时间并不是卡的那么准就有点强迫症了,这是也许程序 ...
- 【玩具】使用Python自动化发送微信消息进行订水
事情是这样的,我知道淘宝上有卖一种USB接口的大按钮,估计是给工厂或者医院之类的场景设计的,样子长这样: 然后我就一直挺想搞一个的,不为别的,就是玩,但是想来想去也没想到这玩意儿对我而言能有啥用途,就 ...
- python实现微信接口(itchat)
python实现微信接口(itchat) 安装 sudo pip install itchat 登录 itchat.auto_login() 这种方法将会通过微信扫描二维码登录,但是这种登录的方式确实 ...
- 登录以及发送微信消息itchat 库
项目地址点这里 itchat itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单. 使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人. 当然,该api的 ...
随机推荐
- LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
reinterpret_cast代表强制转化,即把pNMHDR强制转化成LPNMITEMACTIVATE类型的. reinterpret_cast<type-id> (expression ...
- Sublime Text3注册码供研究使用
文章介绍 看到文章时候感觉不错,一直用的Notepad++.文章属于转载,文末有文章来源,转载注明出处. 一. Sublime 下载地址: Sublime 3: http://www.sublimet ...
- Boot Option Menu
SATA HDD:TOSHIBA MQ02ABF100 1000G SATA HDD:SAMSUNG MZVLW512HMJP-000L2 => Invalid Partition T ...
- Arcgis android10.2测试版中android.view.InflateException
最近2天总是有时出现 下面这个错误 android.view.InflateException: Binary XML file line #15: Error inflating class co ...
- C#校验算法列举
以下是工作中常用的几种校验算法,后期将不断更新 和校验 /// <summary> /// CS和校验 /// </summary> /// <param name=&q ...
- 最大k乘积
思路:看到这道题,第一思路就要是动态规划,不要想着用啥暴力或者排列组合,只会搞得很复杂. 动态规划的思路是对这个整数,我们从后向前进行划分k个数字,我们知道对于划分后的最后一个整数,它的位数要保证前面 ...
- ASP SQLDATASOURCE
原文链接:http://blog.csdn.net/dodream/article/details/4887076
- 微信Dat文件解码
最近在整理磁盘文件,因为经过一段时间的蹂躏后,磁盘实在是太多东西了,不整理一下,简直对不住我的SSD好嘛.偶然发现磁盘中某公司的文件夹占用空间简直不能再大,那可是我的C盘啊,合计才119GB的SSD空 ...
- 【洛谷2324】[SCOI2005]骑士精神 IDA*
[SCOI2005]骑士精神 描述 在一个\(5×5\)的棋盘上有\(12\)个白色的骑士和\(12\)个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为 ...
- 使用js实现水波效果
使用到的工具:jQuery Ripples Plugin 下载安装 git clone https://github.com/sirxemic/jquery.ripples.git 引入jquery, ...