one
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
*.mp3
|
||||
*.mp4
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/4 下午8:02
|
||||
# @Author : cmk
|
||||
# @File : movie——bilibili.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import requests
|
||||
#视频合并
|
||||
from moviepy.editor import *
|
||||
|
||||
|
||||
vidor_url= 'https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/50/03/1628270350/1628270350-1-30032.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1722780365&gen=playurlv2&os=cosbv&oi=2029323983&trid=7cefdb0e26b3415f91afce6fdaa1bda3u&mid=0&platform=pc&og=cos&upsig=a1b7708bfc4500ba3655eef7f6526fc6&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&bvc=vod&nettype=0&orderid=0,3&buvid=18B09F3B-6AB6-4569-ABBA-98D50EE4645F34003infoc&build=0&f=u_0_0&agrr=0&bw=12942&logo=80000000'
|
||||
audio_url = 'https://upos-sz-mirrorcos.bilivideo.com/upgcxcode/50/03/1628270350/1628270350-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1722780365&gen=playurlv2&os=cosbv&oi=2029323983&trid=7cefdb0e26b3415f91afce6fdaa1bda3u&mid=0&platform=pc&og=cos&upsig=8109b2753456551bb0bb919f9a64c898&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform,og&bvc=vod&nettype=0&orderid=0,3&buvid=18B09F3B-6AB6-4569-ABBA-98D50EE4645F34003infoc&build=0&f=u_0_0&agrr=0&bw=9052&logo=80000000'
|
||||
|
||||
headers = {
|
||||
'referer':'https://search.bilibili.com/all?vt=73072246&keyword=docker%E6%95%99%E7%A8%8B&from_source=webtop_search&spm_id_from=333.1073&search_source=2',
|
||||
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
||||
}
|
||||
|
||||
# vidor_data = requests.get(vidor_url, headers=headers).content
|
||||
# audio_data = requests.get(audio_url, headers=headers).content
|
||||
#
|
||||
# with open('bilibili.mp4','wb') as f:
|
||||
# f.write(vidor_data)
|
||||
# with open('bilibili.mp3','wb') as f:
|
||||
# f.write(audio_data)
|
||||
|
||||
ffmpeg_tools.ffmpeg_merge_video_audio('bilibili.mp4','bilibili.mp3','all.mp4')
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/4 下午9:21
|
||||
# @Author : cmk
|
||||
# @File : vip_muisc.py
|
||||
# @Email : 15726649712@163.com
|
||||
import os
|
||||
|
||||
import requests
|
||||
from moviepy.editor import AudioFileClip
|
||||
from lxml import etree
|
||||
|
||||
|
||||
headers = {
|
||||
'referer':'https://music.163.com',
|
||||
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
||||
}
|
||||
url = 'https://music.163.com/artist/mv?id=222871'
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
#print(response.text)
|
||||
html = etree.HTML(response.text)
|
||||
name_list = html.xpath('//*[@id="m-mv-module"]/li[*]/p/a/text()')
|
||||
url_list = html.xpath('//*[@id="m-mv-module"]/li[*]/p/a/@href')
|
||||
|
||||
data = {name:url for name,url in zip(name_list,url_list)}
|
||||
print(data)
|
||||
|
||||
for name in data:
|
||||
url = f'https://music.163.com/#/{data[name]}'
|
||||
response = requests.get(url, headers=headers)
|
||||
with open(f'{name}.mp4', 'wb') as f:
|
||||
f.write(response.content)
|
||||
name = AudioFileClip(f"{name}.mp4")
|
||||
name.write_audiofile(f'{name}.mp3')
|
||||
os.remove(f'{name}.mp4')
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/5 下午9:48
|
||||
# @Author : cmk
|
||||
# @File : bilibili-laomo.py
|
||||
# @Email : 15726649712@163.com
|
||||
import re
|
||||
|
||||
import requests
|
||||
from lxml import etree
|
||||
import json
|
||||
import jsonpath
|
||||
from moviepy.editor import VideoFileClip
|
||||
|
||||
'''
|
||||
video_url
|
||||
audio_url
|
||||
'''
|
||||
|
||||
|
||||
url = 'https://www.bilibili.com/video/BV1gb4y1P7mV/?spm_id_from=333.788&vd_source=74f0d233d72bf26491f5540af160ff76'
|
||||
headers = {
|
||||
'Referer':'https://space.bilibili.com/3493290691266862/?spm_id_from=333.999.0.0',
|
||||
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
||||
}
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
html = etree.HTML(response.text)
|
||||
html.xpath('')
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/28 下午3:15
|
||||
# @Author : cmk
|
||||
# @File : 001-reuquest使用.py
|
||||
# @Email : 15726649712@163.com
|
||||
import random
|
||||
|
||||
import requests
|
||||
|
||||
user_agents = [
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
|
||||
'Opera/8.0 (Windows NT 5.1; U; en)',
|
||||
'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
|
||||
'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2 ',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
|
||||
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
|
||||
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
|
||||
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
|
||||
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
|
||||
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
|
||||
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0) ',
|
||||
]
|
||||
print(random.choices(user_agents))
|
||||
# url = 'https://www.baidu.com'
|
||||
# #url = 'http://www.jinrizulan.top/login'
|
||||
# header = {
|
||||
# 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
|
||||
# }
|
||||
|
||||
# respones = requests.get(url, headers=header)
|
||||
# print(respones.text)
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/28 下午5:47
|
||||
# @Author : cmk
|
||||
# @File : 002问问.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import requests
|
||||
import random
|
||||
|
||||
# url = 'https://www.sogou.com/sogou'
|
||||
# user_agents = [
|
||||
# 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
|
||||
# 'Opera/8.0 (Windows NT 5.1; U; en)',
|
||||
# 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
|
||||
# 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50'
|
||||
# ]
|
||||
# UA = random.choice(user_agents)
|
||||
# headers = {
|
||||
# 'user_agents': UA
|
||||
# }
|
||||
# input_out = input('输入你要问的内容')
|
||||
# #https://www.sogou.com/sogou?query=%E5%8C%97%E4%BA%AC&page=3
|
||||
# for i in range(1,10):
|
||||
# query = {
|
||||
# 'query': input_out,
|
||||
# 'page': i,
|
||||
# }
|
||||
# response = requests.get(url, headers=headers, params=query)
|
||||
# if response.status_code == 200:
|
||||
# with open(f'./shougou/{input_out}_{i}.html', 'w') as f:
|
||||
# f.write(response.content.decode(response.encoding))
|
||||
|
||||
class Wenwen:
|
||||
def __init__(self,url,headers):
|
||||
self.url = url
|
||||
self.headers = headers
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/28 下午10:17
|
||||
# @Author : cmk
|
||||
# @File : 003post_requrest.py
|
||||
# @Email : 15726649712@163.com
|
||||
import requests
|
||||
|
||||
url = 'http://www.abcbiquge.com/login.htm'
|
||||
headers = {
|
||||
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
|
||||
'Referer':'http://www.abcbiquge.com/login.htm'
|
||||
}
|
||||
|
||||
from_data = {
|
||||
'name': 'acctv111',
|
||||
'password': '0E7517141FB53F21EE439B355B5A1D0A',
|
||||
'autoLogin': 1,
|
||||
'autologin': 1
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, data=from_data)
|
||||
print(response.text)
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/29 下午9:54
|
||||
# @Author : cmk
|
||||
# @File : ip代理.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import requests
|
||||
from retrying import retry
|
||||
|
||||
|
||||
class aa():
|
||||
def __init__(self):
|
||||
self.url = 'https://myip.ipip.net'
|
||||
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
|
||||
}
|
||||
self.num_ = 0
|
||||
self.ip = {'https':'http://115.239.0.204:40018'}
|
||||
@retry(stop_max_attempt_number=10)
|
||||
def get_ip(self):
|
||||
self.num_ += 1
|
||||
print(self.num_)
|
||||
response = requests.get(url=self.url, headers=self.headers,proxies=self.ip,timeout=3)
|
||||
return response.text
|
||||
def run(self):
|
||||
|
||||
try:
|
||||
self.get_ip()
|
||||
return self.get_ip()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
aa = aa()
|
||||
while True:
|
||||
bb = aa.run()
|
||||
if 'IP' not in bb:
|
||||
break
|
||||
else:
|
||||
print(bb)
|
||||
|
||||
|
||||
|
||||
# proxies = {"https":"http://119.41.206.35:40015"}
|
||||
# response = requests.get(url, headers=headers,proxies=proxies,timeout=5)
|
||||
# print(response.text)
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="shortcut icon" href="//www.sogou.com/images/logo/new/favicon.ico?v=4" type="image/x-icon">
|
||||
|
||||
<title>搜狗搜索</title>
|
||||
|
||||
<script>
|
||||
|
||||
(function () {
|
||||
|
||||
if (!window.Promise) {
|
||||
|
||||
document.writeln('<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"><' + '/' + 'script>');
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="static/css/anti.min.css?v=1"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="newstatic/css/verify.css">
|
||||
|
||||
<script src="//dlweb.sogoucdn.com/common/lib/jquery/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script src="static/js/antispider.min.js?v=3"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var domain = getDomain();
|
||||
|
||||
window.imgCode = -1;
|
||||
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
function checkSNUID() {
|
||||
|
||||
var cookieArr = document.cookie.split('; '),
|
||||
|
||||
count = 0;
|
||||
|
||||
|
||||
|
||||
for(var i = 0, len = cookieArr.length; i < len; i++) {
|
||||
|
||||
if (cookieArr[i].indexOf('SNUID=') > -1) {
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return count > 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(checkSNUID()) {
|
||||
|
||||
var date = new Date(), expires;
|
||||
|
||||
date.setTime(date.getTime() -100000);
|
||||
|
||||
expires = date.toGMTString();
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires;
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogo.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.www.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.weixin.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.sogou.com';
|
||||
|
||||
document.cookie = 'SNUID=1;path=/;expires=' + expires + ';domain=.snapshot.sogoucdn.com';
|
||||
|
||||
sendLog('delSNUID');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(getCookie('seccodeRight') === 'success') {
|
||||
|
||||
sendLog('verifyLoop');
|
||||
|
||||
|
||||
|
||||
setCookie('seccodeRight', 1, getUTCString(-1), location.hostname, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2026/5/8 10:37
|
||||
# @Author : cmk
|
||||
# @File : WY-music.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
'''
|
||||
简单暴力获取网易云音乐照片或者mv
|
||||
简单测试,无法大批量下载,vip歌曲无法下载
|
||||
'''
|
||||
|
||||
import requests
|
||||
from fake_useragent import UserAgent
|
||||
|
||||
class music():
|
||||
def __init__(self):
|
||||
self.headers = {
|
||||
'User-Agent': UserAgent().random,
|
||||
}
|
||||
def get_data(self,name,url):
|
||||
res = requests.get(url, headers=self.headers)
|
||||
with open(name, 'wb') as f:
|
||||
f.write(res.content)
|
||||
|
||||
if __name__ == '__main__':
|
||||
music_ = music()
|
||||
name = input("输入音乐 or mv or 照片的名称以及格式.mp3,jpg,mp4:")
|
||||
url = input('输入F12抓包的url:')
|
||||
music_.get_data(name,url)
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/3 下午4:14
|
||||
# @Author : cmk
|
||||
# @File : test_xapth.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import requests
|
||||
from lxml import etree
|
||||
|
||||
url ='https://movie.douban.com/top250'
|
||||
|
||||
headers = {
|
||||
'User_Agents': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
|
||||
'Referer':'https://movie.douban.com/subject/1292052/'
|
||||
}
|
||||
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
print(response.status_code)
|
||||
|
||||
print(response.content.decode(response.encoding))
|
||||
|
||||
# str类型无法直接被xpath语法处理,需要转换成html对象
|
||||
# HTML_data = etree.HTML(response.text)
|
||||
#
|
||||
# HTML_data.xpath('//*[@id="root"]/div[2]/div[1]/div[1]/div[1]/a/text()')
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/18
|
||||
# File : 1.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/18 上午9:47
|
||||
# File : js加密.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
import hashlib
|
||||
# import base64
|
||||
#
|
||||
# data = '程明坤'
|
||||
#
|
||||
# base64_data = base64.b64encode(data.encode()).decode('GBK')
|
||||
# '56iL5piO5Z2k'
|
||||
# print(base64_data)
|
||||
# base64_d1 = base64.b64decode(base64_data).decode()
|
||||
# print(base64_d1)
|
||||
|
||||
#md5不可逆
|
||||
# import hashlib
|
||||
# data = '程明坤'
|
||||
# #hexdigest()获取加密后的密文
|
||||
# hash = hashlib.md5(data.encode()).hexdigest()
|
||||
# print(hash)
|
||||
|
||||
import hmac
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/31 下午8:54
|
||||
# @Author : cmk
|
||||
# @File : 豆瓣.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import requests
|
||||
import pymongo
|
||||
import time
|
||||
import jsonpath
|
||||
|
||||
'''
|
||||
要求:取产地和排名
|
||||
'''
|
||||
mongo_client = pymongo.MongoClient('mongodb://localhost:27017/')
|
||||
mongo_db = mongo_client['movie']
|
||||
mongo_collection = mongo_db['movie']
|
||||
|
||||
nums = input('请输入你要获取的页数:')
|
||||
for num in range(int(nums)):
|
||||
url = f'https://movie.douban.com/j/chart/top_list?type=13&interval_id=100%3A90&action=&start={num * 20}&limit=20'
|
||||
|
||||
heraders = {
|
||||
'Host': 'movie.douban.com',
|
||||
'Origin': 'http://movie.douban.com',
|
||||
'Referer': 'http://movie.douban.com/j/chart/top_list',
|
||||
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'
|
||||
}
|
||||
response = requests.get(url, headers=heraders)
|
||||
json_data = response.json()
|
||||
mongo_collection.insert_many(json_data)
|
||||
time.sleep(3)
|
||||
|
||||
for i in mongo_collection.find():
|
||||
print(i)
|
||||
# for i in range(len(json_data)):
|
||||
# mongo_collection.insert_many(json_data[i])
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/4 下午7:01
|
||||
# @Author : cmk
|
||||
# @File : db_mongodb.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import pymongo
|
||||
|
||||
|
||||
cline = pymongo.MongoClient('localhost', 27017)
|
||||
# 安全验证
|
||||
#cline.authenticate('admin', 'admin')
|
||||
|
||||
db = cline['cmk']
|
||||
|
||||
c1 = db['cmk']
|
||||
|
||||
#需要用循环提取
|
||||
# a = c1.find()
|
||||
# for i in a:
|
||||
# print(i)
|
||||
|
||||
# 只能查看一条数据,不用转换
|
||||
c1.find_one()
|
||||
|
||||
# 添加一条数据
|
||||
#c1.insert_one({'_id': 11, 'age': 18.0, 'name': 'cctv11'})
|
||||
|
||||
#修改数据
|
||||
#c1.update_one({'name': 'cctv11'},{'$set':{'name': 'cmk'}})
|
||||
|
||||
c1.delete_one({'name': 'cmk'})
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2025/1/2
|
||||
# File : 4k.py
|
||||
# 脚本作用 : 批量下载https://pic.netbian.com图片
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
|
||||
import requests
|
||||
|
||||
def my_headers(url):
|
||||
headers = {
|
||||
'Referer': 'https://pic.netbian.com',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-arch': '"x86"',
|
||||
'sec-ch-ua-bitness': '"64"',
|
||||
'sec-ch-ua-full-version': '"131.0.6778.205"',
|
||||
'sec-ch-ua-full-version-list': '"Google Chrome";v="131.0.6778.205", "Chromium";v="131.0.6778.205", "Not_A Brand";v="24.0.0.0"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-model': '""',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-ch-ua-platform-version': '"15.0.0"',
|
||||
}
|
||||
response = requests.get(url, headers=headers)
|
||||
return response
|
||||
|
||||
if __name__ == '__main__':
|
||||
url = 'https://pic.netbian.com'
|
||||
a = input('输入你要获取的内容"4kfengjing":')
|
||||
print(my_headers(url).text)
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2025/1/1
|
||||
# File : 百度.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
import requests
|
||||
import re
|
||||
import json
|
||||
headers = {
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'Accept-Language': 'zh,zh-CN;q=0.9',
|
||||
'Cache-Control': 'max-age=0',
|
||||
'Connection': 'keep-alive',
|
||||
# 'Cookie': 'BIDUPSID=D972F42DA92BDE42EE76DC23E23EF94D; PSTM=1732951044; BAIDUID=D972F42DA92BDE425BD1E54B14510FFE:FG=1; BD_UPN=12314753; BAIDUID_BFESS=D972F42DA92BDE425BD1E54B14510FFE:FG=1; MAWEBCUID=web_uMpwvXBHFXRmTYmsjlzyiMoLsZiFOKOBmGcXUlfDyoEwqNWQpq; __bid_n=193f9404ffd3728f638fc8; ZFY=8ygVtyGYPKpdeQvvwWRkEK0Sj:BrcvpoB3fhY1QjSVz8:C; RT="z=1&dm=baidu.com&si=9d655702-d58a-47db-b1da-aefcaab93deb&ss=m58rm2qx&sl=2&tt=2i4&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=hnmw"; newlogin=1; B64_BOT=1; H_WISE_SIDS=61027_61390_61445_60853_61491_61430_61494_61530_61521_61613; H_WISE_SIDS_BFESS=61027_61390_61445_60853_61491_61430_61494_61530_61521_61613; BDRCVFR[77Ms7oRaB-6]=mk3SLVN4HKm; H_PS_PSSID=61027_61390_61445_60853_61491_61494_61530_61521_61613; delPer=0; BD_CK_SAM=1; PSINO=1; BA_HECTOR=a080a0a00g8l8h2g042524ak0e77un1jn9dl01v; baikeVisitId=1d8b54e9-6dba-4cec-8ae1-1ad59b8c2303; COOKIE_SESSION=45_0_7_4_5_7_0_0_7_3_0_3_47_0_8_0_1735702499_0_1735702491%7C9%230_0_1735702491%7C1; BD_HOME=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; ppfuid=FOCoIC3q5fKa8fgJnwzbE67EJ49BGJeplOzf+4l4EOvDuu2RXBRv6R3A1AZMa49I27C0gDDLrJyxcIIeAeEhD8JYsoLTpBiaCXhLqvzbzmvy3SeAW17tKgNq/Xx+RgOdb8TWCFe62MVrDTY6lMf2GrfqL8c87KLF2qFER3obJGlcv8RcA1xQKfriWJVc7a+LGEimjy3MrXEpSuItnI4KDw0lcp9gYlNeIi8lCW52aQjdXPm3tCosQ5WOQK5BipRU/MX8cKJjK8bCUsEqWG541oOswVAInEL977Gkc4LGHFurc6cZOQiWpdWZFfM9cCLuTBuECl+tiP++NCHKpXEMdWH1SPBXDyoMbf9Ga3EX3JChPqbqXCynz2/zX5KTmKXkQbeCqJ91LNPfk1CUv8oZVqpjmQL+qAV8IsF/o1nhFAyZ9KUZywDhnDu1Pi1I0y9kFgpvN5wsxOF4OWHNx5obqb9HgVrRCzW8F/grF+qG2/fHZFO3SaB4GS7zlBrG2cLm8lTRl19JYcYcqvy3P/50mxpWDwUUC4pvKOF9e+pwNq7l6HzKEZyCMUDd+W6AiaksYiu+4AAz72OnMQfgAyNUbW3IyzL5c+UBht87WUigOY9alcIuR+n1gwn+Dmf3unATYGtv0zKmAog3Ny9wFYiQ/gdKSrR9D25HSwrLQyIe5QKTkKSlY6nVev8MhaT3AUPwNqYIvWCQZXWkhuuU0ZXLMYAKJSeHY7mTrwwSSKC3ZaJ1ws01+N7+ZYRSV0hfkzrW2tjIBQevKFs86lIavrkFVLBPKHcPBGk0StntFSLi18x91rSPWb2eeCt263/A+EJVR/A8+3BQ92SIDoXabq8Wb8ZGN9BAsC9g5OdjE6lhwzTadptHqT7mZN901gDzA4lMYEG/kekC+0J5/N5yVy+ei7UKhQHejRjxCO2+98Bn9oZFiDSnLA6b6enRLnlcjd/V5Lrc1iQJ5vVqzr55rpErNdd7jPkj5hbBFquQKM4S+tDJ34jmplOTrqqKT7PPVfrdgd4OkK13pEy86BsJ8M0gKXgtivUgM8Bjl1m/pkg0SuDyntWLdrmMxcZYvgySvSSwQ2Qtm8EkKHIMyR/XgfHnpX5vadGpRMro2qaE8u+x8w1gJHIRKib2u6Q1JtQiZE1Rde/vRx8xKfg6uYR37n0BvfgJE5+KbeuwCyAvJRGUA2fpt0VClIfV0m2PRG7bvH00OODKY6cFi7NgWAK6Jc1G4bJvJ++n215hSNvqitQjGGwIBF37aBhyiPWPAOeYXBqA; BDUSS=FdZSVd6allRNmpyVXVzWnZjSXYxNWhTQm5oLTdkc1V0TnJ4bndYTWhhcnZTWnhuRVFBQUFBJCQAAAAAAAAAAAEAAAAG38eed2luZHnM9NW9yMvJ-gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO-8dGfvvHRnc; BDUSS_BFESS=FdZSVd6allRNmpyVXVzWnZjSXYxNWhTQm5oLTdkc1V0TnJ4bndYTWhhcnZTWnhuRVFBQUFBJCQAAAAAAAAAAAEAAAAG38eed2luZHnM9NW9yMvJ-gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO-8dGfvvHRnc',
|
||||
'Sec-Fetch-Dest': 'document',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'none',
|
||||
'Sec-Fetch-User': '?1',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
}
|
||||
|
||||
response = requests.get('https://www.baidu.com/',headers=headers)
|
||||
html = response.text
|
||||
print(html)
|
||||
data = re.findall(r'<script type="application/json" id="placeholder-data" data-for="result-data">(.*?)</script>', html)
|
||||
print(data)
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/8/14 上午9:56
|
||||
# @Author : cmk
|
||||
# @File : 自动化测试.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
from selenium import webdriver
|
||||
|
||||
wd = webdriver.Chrome()
|
||||
wd.get('http://tieba.baidu.com')
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2025/4/6
|
||||
# File : 002-Blibli.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
|
||||
'''
|
||||
#闭包
|
||||
def outer(n):
|
||||
m = 10
|
||||
def a(e):
|
||||
nonlocal m # 告诉解释器,此处使用的是外部变量M
|
||||
m = 100 # 修改m值,如果没有nonlocal 无法修改
|
||||
data = f'我是a:{n * m *e}'
|
||||
return data
|
||||
def b(e):
|
||||
m = 100
|
||||
data = f'我是b:{n * m *e}'
|
||||
return data
|
||||
def c(e):
|
||||
data = f'我是c:{n * m *e}'
|
||||
return data
|
||||
if n < 5:
|
||||
return a
|
||||
elif 5<= n < 10:
|
||||
return b
|
||||
elif 10<= n < 20:
|
||||
return c
|
||||
|
||||
|
||||
print(outer(4)(6))
|
||||
'''
|
||||
|
||||
'''
|
||||
装饰器
|
||||
'''
|
||||
##没有参数
|
||||
# def outer(fn):
|
||||
# def a():
|
||||
# print('你好11111')
|
||||
# fn()
|
||||
# return a
|
||||
#
|
||||
#
|
||||
# def c():
|
||||
# print('aaaa')
|
||||
#
|
||||
#
|
||||
# outer(c)()
|
||||
#
|
||||
# #语法糖
|
||||
# @outer
|
||||
# def b():
|
||||
# print('哈哈哈')
|
||||
# b()
|
||||
|
||||
#有参数
|
||||
def outer(fn1):
|
||||
def inner(*args, **kwargs):
|
||||
print('我是outer')
|
||||
fn1(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
def outer2(fn1):
|
||||
def inner(*args, **kwargs):
|
||||
print(f'我是outer2')
|
||||
fn1(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
|
||||
@outer2
|
||||
@outer
|
||||
def c1(a,b):
|
||||
print(a+b)
|
||||
|
||||
c1(1,2,3)
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2025/4/1
|
||||
# File : 01课堂作业.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 :
|
||||
# ------------------------------------
|
||||
|
||||
'''
|
||||
课堂作业:https://www.sogou.com/sogou?query=%E7%BE%8E%E9%A3%9F&ie=utf8&insite=wenwen.sogou.com 保存页面内容
|
||||
'''
|
||||
|
||||
import requests
|
||||
from fake_useragent import FakeUserAgent
|
||||
|
||||
url_ = 'https://www.sogou.com/'
|
||||
|
||||
headers = {
|
||||
'User-Agent': FakeUserAgent().random,
|
||||
}
|
||||
data = {
|
||||
'query': '美食',
|
||||
'ie': 'utf8',
|
||||
'insite': 'wenwen.sogou.com',
|
||||
}
|
||||
res = requests.get(url_, headers=headers,data=data)
|
||||
print(res.text)
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/25 下午1:42
|
||||
# @Author : cmk
|
||||
# @File : DingDing_tools.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import requests
|
||||
import json
|
||||
import urllib.parse
|
||||
|
||||
class DingDingTools:
|
||||
def __init__(self, webhook, secret=None):
|
||||
self.webhook = webhook
|
||||
self.secret = secret
|
||||
|
||||
def timestamp_sign(self):
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
if self.secret:
|
||||
secret_enc = self.secret.encode('utf-8')
|
||||
string_to_sign = '{}\n{}'.format(timestamp, self.secret)
|
||||
string_to_sign_enc = string_to_sign.encode('utf-8')
|
||||
hmac_code = hmac.new(secret_enc, string_to_sign_enc, hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code)
|
||||
sign = urllib.parse.quote_plus(sign)
|
||||
return timestamp, sign
|
||||
else:
|
||||
return timestamp, None
|
||||
#消息类型https://open.dingtalk.com/document/orgapp/custom-bot-send-message-type#66407430cd5xr
|
||||
def text(self,memages):
|
||||
timestamp,sign = self.timestamp_sign()
|
||||
if 'https://oapi.dingtalk.com/robot/send?access_token=' in self.webhook:
|
||||
url = self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
else:
|
||||
url = 'https://oapi.dingtalk.com/robot/send?access_token=' + self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
headers = {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
}
|
||||
data = {
|
||||
#消息类型
|
||||
"msgtype": "text",
|
||||
"text":{
|
||||
#消息内容
|
||||
"content": memages
|
||||
},
|
||||
#被圈的人,非必填项
|
||||
"at": {
|
||||
#被@人的手机号
|
||||
"atMobile": ['15726649712'],
|
||||
#被@人的用户userId
|
||||
"atUserIds":['程明坤'],
|
||||
#是否@所有人。
|
||||
"isAtAll": True
|
||||
}
|
||||
}
|
||||
respones = requests.post(url,headers=headers,data=json.dumps(data))
|
||||
return respones.text
|
||||
|
||||
def link(self,title,text,messageUrl,picUrl=None):
|
||||
data = {
|
||||
"msgtype": "link",
|
||||
"link": {
|
||||
"title": title,
|
||||
"text": text,
|
||||
"messageUrl": messageUrl,
|
||||
"picUrl": picUrl
|
||||
}
|
||||
}
|
||||
timestamp,sign = self.timestamp_sign()
|
||||
if 'https://oapi.dingtalk.com/robot/send?access_token=' in self.webhook:
|
||||
url = self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
else:
|
||||
url = 'https://oapi.dingtalk.com/robot/send?access_token=' + self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
headers = {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
}
|
||||
respones = requests.post(url,headers=headers,data=json.dumps(data))
|
||||
return respones.text
|
||||
|
||||
def Marddown(self,title,mesage):
|
||||
data = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title": title,
|
||||
"text": mesage
|
||||
},
|
||||
"at": {
|
||||
"atMobiles": [],
|
||||
"isAtAll": False
|
||||
}
|
||||
}
|
||||
timestamp, sign = self.timestamp_sign()
|
||||
if 'https://oapi.dingtalk.com/robot/send?access_token=' in self.webhook:
|
||||
url = self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
else:
|
||||
url = 'https://oapi.dingtalk.com/robot/send?access_token=' + self.webhook + '×tamp=' + timestamp + '&sign=' + sign
|
||||
headers = {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
}
|
||||
respones = requests.post(url, headers=headers, data=json.dumps(data))
|
||||
return respones.text
|
||||
# if __name__ == '__main__':
|
||||
# webhook = '3922b5bec47e2e34c9cd965e9088902826b4a0abd71212ae2feb17df09aabb38'
|
||||
# secret = 'SEC58bfd29aab7dab71eae40558e1b41306e58e63b9974f5eff7bd4b518f47c6189'
|
||||
# Ding_reboot = DingDingTools(webhook,secret)
|
||||
@@ -0,0 +1,333 @@
|
||||
ChatbotMessage(message_type=text, text=TextContent(content=验证码), sender_nick=程明坤, conversation_title=None)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=程明坤, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 哇哦这尼玛), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= ), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= ), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=南涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证吗), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=程明坤, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
ChatbotMessage(message_type=text, text=TextContent(content= 验证码), sender_nick=岳振涛, conversation_title=萝卜头)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/5/9 9:33
|
||||
# @Author : cmk
|
||||
# @File : Class_Dingding.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import requests
|
||||
import json
|
||||
import urllib.parse
|
||||
|
||||
|
||||
class DingTalkRobot:
|
||||
def __init__(self, webhook, secret=None):
|
||||
self.webhook = webhook
|
||||
self.secret = secret
|
||||
|
||||
def _generate_timestamp_and_sign(self):
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
if self.secret:
|
||||
secret_enc = self.secret.encode('utf-8')
|
||||
string_to_sign = '{}\n{}'.format(timestamp, self.secret)
|
||||
string_to_sign_enc = string_to_sign.encode('utf-8')
|
||||
hmac_code = hmac.new(secret_enc, string_to_sign_enc, hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code)
|
||||
sign = urllib.parse.quote_plus(sign)
|
||||
return timestamp, sign
|
||||
else:
|
||||
return timestamp, None
|
||||
|
||||
def _send_request(self, data):
|
||||
headers = {'Content-Type': 'application/json;charset=utf-8'}
|
||||
response = requests.post(self.webhook, headers=headers, data=json.dumps(data))
|
||||
return response.json()
|
||||
|
||||
def send_text(self, content, at_mobiles=None, is_at_all=False):
|
||||
timestamp, sign = self._generate_timestamp_and_sign()
|
||||
data = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": content
|
||||
},
|
||||
"at": {
|
||||
"atMobiles": at_mobiles if at_mobiles else [],
|
||||
"isAtAll": is_at_all
|
||||
}
|
||||
}
|
||||
if sign:
|
||||
data['timestamp'] = timestamp
|
||||
data['sign'] = sign
|
||||
return self._send_request(data)
|
||||
|
||||
def send_markdown(self, title, text, at_mobiles=None, is_at_all=False):
|
||||
timestamp, sign = self._generate_timestamp_and_sign()
|
||||
data = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title": title,
|
||||
"text": text
|
||||
},
|
||||
"at": {
|
||||
"atMobiles": at_mobiles if at_mobiles else [],
|
||||
"isAtAll": is_at_all
|
||||
}
|
||||
}
|
||||
if sign:
|
||||
data['timestamp'] = timestamp
|
||||
data['sign'] = sign
|
||||
return self._send_request(data)
|
||||
|
||||
# Add more message types as needed...
|
||||
'''
|
||||
使用案例
|
||||
# 创建机器人实例
|
||||
webhook_url = "https://oapi.dingtalk.com/robot/send?access_token=your_access_token"
|
||||
secret = "your_secret" # 如果没有加签验证,可以设为None
|
||||
robot = DingTalkRobot(webhook_url, secret)
|
||||
|
||||
# 发送文本消息
|
||||
response = robot.send_text("Hello, this is a 00test message!")
|
||||
print(response)
|
||||
|
||||
# 发送带@的文本消息
|
||||
response = robot.send_text("Hello, this is a 00test message with @!", at_mobiles=["18888888888"], is_at_all=False)
|
||||
print(response)
|
||||
|
||||
# 发送Markdown消息
|
||||
markdown_title = "Test Markdown Message"
|
||||
markdown_text = "# This is a 00test Markdown message\n- Item 1\n- Item 2\n[Link](https://www.example.com)"
|
||||
response = robot.send_markdown(markdown_title, markdown_text)
|
||||
print(response)
|
||||
|
||||
'''
|
||||
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2023/7/16 22:32
|
||||
# @Author : cmk
|
||||
# @File : reboot_dingding.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import socket
|
||||
from multiprocessing import Process
|
||||
import os
|
||||
|
||||
#from conversation.info import *
|
||||
|
||||
|
||||
def handle_client(client_socket):
|
||||
# 获取socket
|
||||
request_data = client_socket.recv(20000)
|
||||
post_userid, post_sign, post_timestamp, post_mes = getPost(request_data)
|
||||
# 回应socket
|
||||
initKey(post_userid, post_sign, post_timestamp, post_mes)
|
||||
# 关闭socket
|
||||
client_socket.close()
|
||||
|
||||
|
||||
def getPost(request_data):
|
||||
request_data = str(request_data, encoding="utf8").split('\r\n')
|
||||
items = []
|
||||
for item in request_data[1:-2]:
|
||||
items.append(item.split(':'))
|
||||
post_useful = {}
|
||||
for i in items:
|
||||
post_useful.update({i[0]: i[1]})
|
||||
if post_useful.get('sign') == None:
|
||||
print('other connect')
|
||||
return 0
|
||||
else:
|
||||
post_sign = post_useful.get('sign').strip()
|
||||
post_timestamp = post_useful.get('timestamp').strip()
|
||||
|
||||
post_mes = json.loads(request_data[-1])
|
||||
post_userid = post_mes.get('senderId').strip()
|
||||
post_mes = post_mes.get('text').get('content').strip()
|
||||
|
||||
return post_userid, post_sign, post_timestamp, post_mes
|
||||
|
||||
def initKey(post_userid, post_sign, post_timestamp, post_mes):
|
||||
# 配置token
|
||||
# 得到当前时间戳
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
# 计算签名
|
||||
#app_secret = '_XhYNZ45qor2DsnNRqXyCGINypH669XzN2jK0hvtfem-1rfziLuafeq82xbmmj53'
|
||||
app_secret = 'X1s04VcwlxhO7JLEUkCFYbxAW9aTvuWUQrUeyDTqkLbr9GQ_tJ6jG0732S87ayvY'
|
||||
app_secret_enc = app_secret.encode('utf-8')
|
||||
string_to_sign = '{}\n{}'.format(post_timestamp, app_secret)
|
||||
string_to_sign_enc = string_to_sign.encode('utf-8')
|
||||
hmac_code = hmac.new(app_secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code).decode('utf-8')
|
||||
# 验证是否来自钉钉的合法请求
|
||||
if (abs(int(post_timestamp) - int(timestamp)) < 3600000 and post_sign == sign):
|
||||
#webhook="https://oapi.dingtalk.com/robot/send?access_token=88327cd1bfcb3fb9d3186fcf1bf8b15a82ac3475c271a8c74600b6431e9e6929"
|
||||
#webhook='https://oapi.dingtalk.com/robot/send?access_token=caaca475c58e8789d85826130271c9e9da7d3837cc65504ef2534fee0b134506'
|
||||
#webhook='https://oapi.dingtalk.com/robot/send?access_token=00f64174519e59edc9a274f5f3792c3b24c16486bad2031ce80a54baf30840ed'
|
||||
webhook='https://oapi.dingtalk.com/robot/send?access_token=78c04c1b2254083a9c90f12a191170499ee274f92aa551a00abd9349db85cc05'
|
||||
header = {
|
||||
"Content-Type": "application/json",
|
||||
"Charset": "UTF-8"
|
||||
}
|
||||
# 发送消息
|
||||
message_json = json.dumps(selectMes(post_userid, post_mes))
|
||||
# 返回发送状态
|
||||
info = requests.post(url=webhook, data=message_json, headers=header)
|
||||
print(info.text)
|
||||
else:
|
||||
print("Warning:Not DingDing's post")
|
||||
|
||||
|
||||
def selectMes(post_userid, post_mes):
|
||||
print(post_userid)
|
||||
# 判断指令选择对应回复
|
||||
if (post_mes == '值班'):
|
||||
mes = os.popen('python zhiban_dingding_robot_api.py').read()
|
||||
send_mes = '@{} \n\n {}'.format(post_userid,mes)
|
||||
return sendMarkdown(post_userid, send_mes)
|
||||
else:
|
||||
#cmd = 'python tongyiqianwen.py {}'.forman(post_mes)
|
||||
mes = os.popen('python tongyiqianwen.py {}'.format(post_mes)).read()
|
||||
send_mes = '@{} \n\n {}'.format(post_userid,mes)
|
||||
return sendText(post_userid, send_mes)
|
||||
|
||||
def sendText(post_userid, send_mes):
|
||||
# 发送文本形式
|
||||
message = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": send_mes
|
||||
},
|
||||
"at": {
|
||||
"atDingtalkIds": [post_userid],
|
||||
"isAtAll": False
|
||||
}
|
||||
}
|
||||
return message
|
||||
|
||||
|
||||
def sendMarkdown(post_userid, send_mes):
|
||||
# 发送Markdown形式
|
||||
message = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title": "智能运维信息",
|
||||
"text": send_mes
|
||||
},
|
||||
"at": {
|
||||
"atDingtalkIds": [post_userid],
|
||||
"isAtAll": False
|
||||
}
|
||||
}
|
||||
return message
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 启动服务,端口9000
|
||||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_socket.bind(("", 8090))
|
||||
server_socket.listen(120)
|
||||
while True:
|
||||
print("已启动")
|
||||
client_socket, client_address = server_socket.accept()
|
||||
print(f"{client_address},用户连接上了")
|
||||
handle_client_process = Process(target=handle_client, args=(client_socket,))
|
||||
handle_client_process.start()
|
||||
client_socket.close()
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/5/11 9:54
|
||||
# @Author : cmk
|
||||
# @File : 00test.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
|
||||
import Class_Dingding
|
||||
|
||||
# 创建机器人实例
|
||||
webhook_url = "https://oapi.dingtalk.com/robot/send?access_token=3922b5bec47e2e34c9cd965e9088902826b4a0abd71212ae2feb17df09aabb38"
|
||||
secret = "SEC58bfd29aab7dab71eae40558e1b41306e58e63b9974f5eff7bd4b518f47c6189" # 如果没有加签验证,可以设为None
|
||||
robot = Class_Dingding.DingTalkRobot(webhook_url, secret)
|
||||
|
||||
# 发送文本消息
|
||||
# response = robot.send_text("Hello, this is a 00test message!")
|
||||
# print(response)
|
||||
#
|
||||
# # 发送带@的文本消息
|
||||
# response = robot.send_text("Hello, this is a 00test message with @!", at_mobiles=["18888888888"], is_at_all=False)
|
||||
# print(response)
|
||||
|
||||
# 发送Markdown消息
|
||||
markdown_title = "Test Markdown Message"
|
||||
markdown_text = "# This is a 00test Markdown message\n- Item 1\n- Item 2\n[Link](https://github.com/chengmingkun/images/blob/master/infinity-1349967.jpg)"
|
||||
response = robot.send_markdown(markdown_title, markdown_text)
|
||||
print(response)
|
||||
@@ -0,0 +1,132 @@
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import socket
|
||||
from multiprocessing import Process
|
||||
|
||||
# from conversation.info import *
|
||||
|
||||
|
||||
def handle_client(client_socket):
|
||||
# 获取socket
|
||||
request_data = client_socket.recv(20000)
|
||||
post_userid, post_sign, post_timestamp, post_mes = getPost(request_data)
|
||||
# 回应socket
|
||||
initKey(post_userid, post_sign, post_timestamp, post_mes)
|
||||
# 关闭socket
|
||||
client_socket.close()
|
||||
|
||||
|
||||
def getPost(request_data):
|
||||
request_data = str(request_data, encoding="utf8").split('\r\n')
|
||||
items = []
|
||||
for item in request_data[1:-2]:
|
||||
items.append(item.split(':'))
|
||||
post_useful = {}
|
||||
for i in items:
|
||||
post_useful.update({i[0]: i[1]})
|
||||
if post_useful.get('sign') == None:
|
||||
print('other connect')
|
||||
return 0
|
||||
else:
|
||||
post_sign = post_useful.get('sign').strip()
|
||||
post_timestamp = post_useful.get('timestamp').strip()
|
||||
|
||||
post_mes = json.loads(request_data[-1])
|
||||
post_userid = post_mes.get('senderId').strip()
|
||||
post_mes = post_mes.get('text').get('content').strip()
|
||||
|
||||
return post_userid, post_sign, post_timestamp, post_mes
|
||||
|
||||
def initKey(post_userid, post_sign, post_timestamp, post_mes):
|
||||
# 配置token
|
||||
# 得到当前时间戳
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
# 计算签名
|
||||
app_secret = ''
|
||||
app_secret_enc = app_secret.encode('utf-8')
|
||||
string_to_sign = '{}\n{}'.format(post_timestamp, app_secret)
|
||||
string_to_sign_enc = string_to_sign.encode('utf-8')
|
||||
hmac_code = hmac.new(app_secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code).decode('utf-8')
|
||||
# 验证是否来自钉钉的合法请求
|
||||
if (abs(int(post_timestamp) - int(timestamp)) < 3600000 and post_sign == sign):
|
||||
webhook="https://oapi.dingtalk.com/robot/send?access_token="
|
||||
header = {
|
||||
"Content-Type": "application/json",
|
||||
"Charset": "UTF-8"
|
||||
}
|
||||
# 发送消息
|
||||
message_json = json.dumps(selectMes(post_userid, post_mes))
|
||||
# 返回发送状态
|
||||
info = requests.post(url=webhook, data=message_json, headers=header)
|
||||
print(info.text)
|
||||
else:
|
||||
print("Warning:Not DingDing's post")
|
||||
|
||||
|
||||
def selectMes(post_userid, post_mes):
|
||||
print(post_userid)
|
||||
# 判断指令选择对应回复
|
||||
if (post_mes == '你好'):
|
||||
send_mes = '@{} \n\n 哈喽,你好啊!'.format(post_userid)
|
||||
return sendText(post_userid, send_mes)
|
||||
if (post_mes == '你的名字'):
|
||||
send_mes = '@{} \n\n 您好,我是智能运维助手~,目前正在学习中~'.format(post_userid)
|
||||
return sendMarkdown(post_userid, send_mes)
|
||||
try:
|
||||
if eval(post_mes):
|
||||
send_mes = "@{} \n\n > {}中文名称为: {}".format(post_userid, post_mes, eval(post_mes))
|
||||
return sendMarkdown(post_userid, send_mes)
|
||||
except:
|
||||
return sendMarkdown(post_userid, '@{} \n\n 感谢您的反馈,正在学习新知识中~'.format(post_userid))
|
||||
else:
|
||||
return sendMarkdown(post_userid, '@{} \n\n 感谢您的反馈,正在学习新知识中~'.format(post_userid))
|
||||
|
||||
|
||||
def sendText(post_userid, send_mes):
|
||||
# 发送文本形式
|
||||
message = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": send_mes
|
||||
},
|
||||
"at": {
|
||||
"atDingtalkIds": [post_userid],
|
||||
"isAtAll": False
|
||||
}
|
||||
}
|
||||
return message
|
||||
|
||||
|
||||
def sendMarkdown(post_userid, send_mes):
|
||||
# 发送Markdown形式
|
||||
message = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title": "智能运维信息",
|
||||
"text": send_mes
|
||||
},
|
||||
"at": {
|
||||
"atDingtalkIds": [post_userid],
|
||||
"isAtAll": False
|
||||
}
|
||||
}
|
||||
return message
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 启动服务,端口9000
|
||||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_socket.bind(("", 9000))
|
||||
server_socket.listen(120)
|
||||
while True:
|
||||
print("已启动")
|
||||
client_socket, client_address = server_socket.accept()
|
||||
print(f"{client_address},用户连接上了")
|
||||
handle_client_process = Process(target=handle_client, args=(client_socket,))
|
||||
handle_client_process.start()
|
||||
client_socket.close()
|
||||
@@ -0,0 +1,230 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/23 上午11:08
|
||||
# File : dingding_rebot.py
|
||||
# 脚本作用 : 使用钉钉机器人发送消息
|
||||
# ------------------------------------
|
||||
|
||||
'''
|
||||
测试使用机器人
|
||||
https://oapi.dingtalk.com/robot/send?access_token=d7e8be9866a981d899e38aa27005e264f47d1f913816caa1001f9d5229f7d074
|
||||
SEC6872ee8ddf8e72bf97f4b5f641f1cdbaf28185013d52e45b6b2a2b8c8675b959
|
||||
'''
|
||||
|
||||
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import requests
|
||||
import json
|
||||
|
||||
def signs(secret):
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
string_to_sign = '{}\n{}'.format(timestamp, secret)
|
||||
hmac_code = hmac.new(secret.encode('utf-8'), string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code).decode('utf-8')
|
||||
return timestamp,sign
|
||||
def req(tokin,secret,data):
|
||||
timestamp,sign = signs(secret)
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={tokin}×tamp={timestamp}&sign={sign}'
|
||||
response = requests.post(url=url,data=json.dumps(data),headers={'Content-Type': 'application/json'})
|
||||
if response.status_code == 200:
|
||||
mes = "消息发送成功"
|
||||
else:
|
||||
mes = f"消息发送失败,状态码:{response.status_code}"
|
||||
print(mes)
|
||||
class mes_type():
|
||||
|
||||
def text(self,mes):
|
||||
'''
|
||||
文本类型
|
||||
"text": {
|
||||
"content":"我就是我, @014728255240768602 是不一样的烟火"
|
||||
},
|
||||
"msgtype":"text"
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": mes
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
def link(self,mes):
|
||||
'''
|
||||
{
|
||||
"msgtype": "link",
|
||||
"link": {
|
||||
"text": "这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林",
|
||||
"title": "时代的火车向前开",
|
||||
"picUrl": "",
|
||||
"messageUrl": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI"
|
||||
}
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "link",
|
||||
"link": mes
|
||||
}
|
||||
return data
|
||||
|
||||
def marddown(self,mes):
|
||||
'''
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"杭州天气",
|
||||
"text": "#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > \n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n"
|
||||
}}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": mes
|
||||
}
|
||||
return data
|
||||
|
||||
def ActionCard(self,mes):
|
||||
'''
|
||||
整体调整
|
||||
{
|
||||
"actionCard": {
|
||||
"title": "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
|
||||
"text": "
|
||||
### 乔布斯 20 年前想打造的苹果咖啡厅
|
||||
Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
|
||||
"btnOrientation": "0",
|
||||
"singleTitle" : "阅读全文",
|
||||
"singleURL" : "https://www.dingtalk.com/"
|
||||
},
|
||||
"msgtype": "actionCard"
|
||||
}
|
||||
单独跳转
|
||||
{
|
||||
"msgtype": "actionCard",
|
||||
"actionCard": {
|
||||
"title": "我 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
|
||||
"text": " \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
|
||||
"btnOrientation": "0",
|
||||
"btns": [
|
||||
{
|
||||
"title": "内容不错",
|
||||
"actionURL": "https://www.dingtalk.com/"
|
||||
},
|
||||
{
|
||||
"title": "不感兴趣",
|
||||
"actionURL": "https://www.dingtalk.com/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"actionCard": mes,
|
||||
"msgtype": "actionCard"
|
||||
}
|
||||
return data
|
||||
def FeedCard(self,mes):
|
||||
'''
|
||||
{
|
||||
"msgtype":"feedCard",
|
||||
"feedCard": {
|
||||
"links": [
|
||||
{
|
||||
"title": "时代的火车向前开1",
|
||||
"messageURL": "https://www.dingtalk.com/",
|
||||
"picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
},
|
||||
{
|
||||
"title": "时代的火车向前开2",
|
||||
"messageURL": "https://www.dingtalk.com/",
|
||||
"picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "feedCard",
|
||||
"feedCard": {
|
||||
"links": mes
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
if __name__ == '__main__':
|
||||
token = '5c2777357a4aa5960799d01a02588c19fa90c3f498783376075dafda7d5d706a'
|
||||
secret = 'SEC058dab30c973edc0dd70b2a7e97eddfd33f20b45a5117b7c5d55c8f2d0dec474'
|
||||
mes = mes_type()
|
||||
# text_data = '文本类型消息测试'
|
||||
# req(token,secret,mes.text(text_data))
|
||||
# link_data = {
|
||||
# "title": "链接类型消息测试标题",
|
||||
# "text": "链接类型消息测试消息内容",
|
||||
# "messageUrl": "https://www.baidu.com",
|
||||
# "picUrl": "https://iknow-pic.cdn.bcebos.com/a71ea8d3fd1f4134a1175ce3371f95cad1c85e0e"
|
||||
# }
|
||||
# req(token,secret,mes.link(link_data))
|
||||
# markdown_data = {
|
||||
# "title": "Marddown类型消息测试",
|
||||
# "text": "[百度](https://www.baidu.com) \n\t **文本加粗**\n\t *文字倾斜*\n\t***加粗倾斜***\n\t\n- item1\n- item2\n 1. item1\n 2. item2"
|
||||
# }
|
||||
# req(token,secret,mes.marddown(markdown_data))
|
||||
# ActionCard_data_all = {
|
||||
# "title": "ActionCard整体跳转消息",
|
||||
# "text": """
|
||||
# 乔布斯 20 年前想打造的苹果咖啡厅Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到20年前苹果一个建立咖啡馆的计划
|
||||
# 
|
||||
# """,
|
||||
# "btnOrientation": "0",
|
||||
# "singleTitle": "阅读全文",
|
||||
# "singleURL": "https://www.dingtalk.com/"
|
||||
# }
|
||||
# req(token, secret, mes.ActionCard(ActionCard_data_all))
|
||||
# ActionCard_data = {
|
||||
# "title": "ActionCard独立跳转消息",
|
||||
# "text": " \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
|
||||
# "btnOrientation": "0",
|
||||
# "btns": [
|
||||
# {
|
||||
# "title": "内容不错",
|
||||
# "actionURL": "https://www.dingtalk.com/"
|
||||
# },
|
||||
# {
|
||||
# "title": "不感兴趣",
|
||||
# "actionURL": "https://www.dingtalk.com/"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# req(token, secret, mes.ActionCard(ActionCard_data))
|
||||
# FeedCard_data = [
|
||||
# {
|
||||
# "title": "时代的火车向前开1",
|
||||
# "messageURL": "https://www.dingtalk.com/",
|
||||
# "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
# },
|
||||
# {
|
||||
# "title": "时代的火车向前开2",
|
||||
# "messageURL": "https://www.dingtalk.com/",
|
||||
# "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
# },
|
||||
# {
|
||||
# "title": "时代的火车向前开2",
|
||||
# "messageURL": "https://www.dingtalk.com/",
|
||||
# "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
# },
|
||||
# {
|
||||
# "title": "时代的火车向前开2",
|
||||
# "messageURL": "https://www.dingtalk.com/",
|
||||
# "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
# },
|
||||
# {
|
||||
# "title": "时代的火车向前开2",
|
||||
# "messageURL": "https://www.dingtalk.com/",
|
||||
# "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
|
||||
# }
|
||||
# ]
|
||||
# req(token,secret,mes.FeedCard(FeedCard_data))
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/10/18 上午10:41
|
||||
# File : echo_text.py.py
|
||||
# 脚本作用 : 钉钉消息自动回复
|
||||
# 项目名称 : 测试
|
||||
# ------------------------------------
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
from dingtalk_stream import AckMessage
|
||||
import dingtalk_stream
|
||||
import MFA
|
||||
|
||||
|
||||
def setup_logger():
|
||||
logger = logging.getLogger()
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(
|
||||
logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
return logger
|
||||
|
||||
|
||||
def define_options():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--client_id', dest='client_id', required=True,
|
||||
help='app_key or suite_key from https://open-dev.digntalk.com'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--client_secret', dest='client_secret', required=True,
|
||||
help='app_secret or suite_secret from https://open-dev.digntalk.com'
|
||||
)
|
||||
options = parser.parse_args()
|
||||
return options
|
||||
|
||||
|
||||
class EchoTextHandler(dingtalk_stream.ChatbotHandler):
|
||||
def __init__(self, logger: logging.Logger = None):
|
||||
super(dingtalk_stream.ChatbotHandler, self).__init__()
|
||||
if logger:
|
||||
self.logger = logger
|
||||
|
||||
async def process(self, callback: dingtalk_stream.CallbackMessage):
|
||||
#消息发送人
|
||||
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
|
||||
print(incoming_message)
|
||||
#接收到的消息
|
||||
text = incoming_message.text.content.strip()
|
||||
if text == '验证码':
|
||||
data = MFA.calGoogleCode('2FO6PJ4O7S67RXHH')
|
||||
self.reply_text(f'验证码:\t {data}', incoming_message)
|
||||
else:
|
||||
self.reply_text('不好意思,我还没有学会',incoming_message)
|
||||
#消息返回
|
||||
|
||||
return AckMessage.STATUS_OK, 'OK'
|
||||
|
||||
def main():
|
||||
logger = setup_logger()
|
||||
options = define_options()
|
||||
credential = dingtalk_stream.Credential(options.client_id, options.client_secret)
|
||||
client = dingtalk_stream.DingTalkStreamClient(credential)
|
||||
client.register_callback_handler(dingtalk_stream.chatbot.ChatbotMessage.TOPIC, EchoTextHandler(logger))
|
||||
client.start_forever()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/10/18 上午10:41
|
||||
# File : mfa.py
|
||||
# 脚本作用 : 钉钉消息自动回复(支持设备验证码、账号信息及帮助查询)
|
||||
# 项目名称 : 测试
|
||||
# ------------------------------------
|
||||
|
||||
import logging
|
||||
from dingtalk_stream import AckMessage
|
||||
import dingtalk_stream
|
||||
import time
|
||||
import base64
|
||||
import struct
|
||||
import hmac
|
||||
import sys
|
||||
import hashlib
|
||||
from logging.handlers import RotatingFileHandler # 用于日志轮转
|
||||
|
||||
|
||||
def calGoogleCode(secretKey):
|
||||
"""生成Google验证码的工具函数"""
|
||||
input = int(time.time()) // 30
|
||||
key = base64.b32decode(secretKey)
|
||||
msg = struct.pack(">Q", input)
|
||||
googleCode = hmac.new(key, msg, hashlib.sha1).digest()
|
||||
# 版本兼容判断
|
||||
o = googleCode[19] & 15 if (sys.version_info > (2, 7)) else ord(googleCode[19]) & 15
|
||||
googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000)
|
||||
# 补全6位验证码(若首位为0会被省略,需补全)
|
||||
return googleCode.zfill(6)
|
||||
|
||||
|
||||
class EchoTextHandler(dingtalk_stream.ChatbotHandler):
|
||||
def __init__(self, logger: logging.Logger = None):
|
||||
super(dingtalk_stream.ChatbotHandler, self).__init__()
|
||||
self.logger = logger
|
||||
# 定义支持的指令与对应配置
|
||||
self.command_config = {
|
||||
"堡垒机": {
|
||||
"secret_key": "2FO6PJ4O7S67RXHH",
|
||||
"user": None,
|
||||
"pwd": None,
|
||||
"desc": "仅返回堡垒机验证码"
|
||||
},
|
||||
"笔记本": {
|
||||
"secret_key": "IVWRJD2IYB3OUIXU7X7ZK7WEKWOVNQEQTB3MBJ2S2KDG6UP2AYHMLELXCAVIHLG6",
|
||||
"user": "B_tongyi@1411305101097388.onaliyun.com",
|
||||
"pwd": "Admin@123",
|
||||
"desc": "返回笔记本登录账号、密码及验证码"
|
||||
},
|
||||
"台式机": {
|
||||
"secret_key": "72RVB6TBNP35D674H45MGDXKQD6HML4DZ7WJLR3NXDGQYAY2DMDIKWOPTKZINIXB",
|
||||
"user": "T_tongyi@1411305101097388.onaliyun.com",
|
||||
"pwd": "Admin@123",
|
||||
"desc": "返回台式机登录账号、密码及验证码"
|
||||
},
|
||||
"工单": {
|
||||
"secret_key": "2D3IRWIFK63PCTLQ5IK4X7JOVESELCHQGCBGBLAI5OFCJSNWC72XK463I44DIFJC",
|
||||
"user": "gwL2-sub02@1759775427129703.onaliyun.com",
|
||||
"pwd": "Yun@sgit2023",
|
||||
"desc": "返回工单系统登录账号、密码及验证码"
|
||||
},
|
||||
"帮助": {
|
||||
"desc": "查看所有支持的指令及说明"
|
||||
}
|
||||
}
|
||||
|
||||
async def process(self, callback: dingtalk_stream.CallbackMessage):
|
||||
# 打印完整消息结构(便于调试,稳定后可注释)
|
||||
if self.logger:
|
||||
self.logger.info(f"完整消息结构:{callback.data}")
|
||||
|
||||
# 解析消息内容
|
||||
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
|
||||
user_command = incoming_message.text.content.strip()
|
||||
|
||||
# 修复:从日志中发现用户名称在'senderNick'字段
|
||||
sender_nick = callback.data.get("senderNick", "未知用户")
|
||||
|
||||
# 日志记录收到的消息
|
||||
if self.logger:
|
||||
self.logger.info(f"收到[{sender_nick}]的消息:{user_command}")
|
||||
|
||||
# 生成并发送回复
|
||||
reply_content = await self.get_reply_content(user_command)
|
||||
self.reply_text(reply_content, incoming_message)
|
||||
|
||||
return AckMessage.STATUS_OK, 'OK'
|
||||
|
||||
async def get_reply_content(self, command):
|
||||
"""根据用户指令生成对应回复内容"""
|
||||
if command == "帮助":
|
||||
return self.generate_help_text()
|
||||
|
||||
config = self.command_config.get(command)
|
||||
if config:
|
||||
mfa = calGoogleCode(config["secret_key"])
|
||||
if config["user"] and config["pwd"]:
|
||||
return (f"【{command}】登录信息\n"
|
||||
f"账号:{config['user']}\n"
|
||||
f"密码:{config['pwd']}\n"
|
||||
f"验证码:{mfa}")
|
||||
else:
|
||||
return f"【{command}】验证码:{mfa}"
|
||||
|
||||
return "不好意思,我还未支持该指令~\n发送「帮助」可查看所有可用功能"
|
||||
|
||||
def generate_help_text(self):
|
||||
"""生成帮助文本"""
|
||||
help_text = "目前支持以下指令,直接发送指令即可获取对应信息:\n"
|
||||
for cmd, info in self.command_config.items():
|
||||
help_text += f"• 「{cmd}」:{info['desc']}\n"
|
||||
help_text += "\n提示:验证码有效期为30秒,获取后请尽快使用~"
|
||||
return help_text
|
||||
|
||||
|
||||
def setup_logger():
|
||||
"""配置日志:仅写入文件,不输出到控制台,支持日志轮转"""
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO) # 设置日志级别
|
||||
|
||||
# 移除已有的处理器(防止默认控制台输出)
|
||||
if logger.hasHandlers():
|
||||
logger.handlers.clear()
|
||||
|
||||
# 配置日志文件轮转
|
||||
# 文件名:mfa.log,最大5MB,保留3个备份
|
||||
file_handler = RotatingFileHandler(
|
||||
'mfa.log',
|
||||
maxBytes=5*1024*1024, # 5MB
|
||||
backupCount=3,
|
||||
encoding='utf-8' # 确保中文正常写入
|
||||
)
|
||||
|
||||
# 设置日志格式
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# 添加文件处理器
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
def main():
|
||||
# 初始化日志(仅写入文件)
|
||||
logger = setup_logger()
|
||||
|
||||
# 钉钉客户端配置
|
||||
client_id = 'dinge1p7abma50df9uh7'
|
||||
client_secret = '63p0_GNh1mrfXK7pxUkpIWrzX6gyT1Ot_adwgAxyo27qpbcR2h9l6YYG2DbA4yoK'
|
||||
credential = dingtalk_stream.Credential(client_id, client_secret)
|
||||
client = dingtalk_stream.DingTalkStreamClient(credential)
|
||||
|
||||
# 注册消息处理器并启动
|
||||
client.register_callback_handler(
|
||||
dingtalk_stream.chatbot.ChatbotMessage.TOPIC,
|
||||
EchoTextHandler(logger)
|
||||
)
|
||||
logger.info("钉钉机器人已启动,等待接收消息...")
|
||||
client.start_forever()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/27 下午4:40
|
||||
# File : MFA.py
|
||||
# 脚本作用 : MFS动态验证码
|
||||
# 项目名称 : 工具
|
||||
# ------------------------------------
|
||||
|
||||
|
||||
import time
|
||||
import base64
|
||||
import struct
|
||||
import hmac
|
||||
import sys
|
||||
import hashlib
|
||||
|
||||
|
||||
|
||||
def calGoogleCode(secretKey):
|
||||
input = int(time.time()) // 30
|
||||
key = base64.b32decode(secretKey)
|
||||
msg = struct.pack(">Q", input)
|
||||
googleCode = hmac.new(key, msg, hashlib.sha1).digest()
|
||||
# 版本判断
|
||||
if (sys.version_info > (2, 7)):
|
||||
o = googleCode[19] & 15
|
||||
else:
|
||||
o = ord(googleCode[19]) & 15
|
||||
googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000)
|
||||
if len(googleCode) == 5: # 如果验证码的第一位是0,则不会显示。此处判断若是5位码,则在第一位补上0
|
||||
googleCode = '0' + googleCode
|
||||
return googleCode
|
||||
|
||||
if __name__ == "__main__":
|
||||
#阿里云工单maf密钥
|
||||
FortressSecret = '2D3IRWIFK63PCTLQ5IK4X7JOVESELCHQGCBGBLAI5OFCJSNWC72XK463I44DIFJC'
|
||||
#国网内网堡垒机动态码---王维
|
||||
#FortressSecret = '2FO6PJ4O7S67RXHH'
|
||||
data = calGoogleCode(FortressSecret)
|
||||
print(f'阿里云工单MFA验证码:{data}')
|
||||
i = 0
|
||||
while i < 5:
|
||||
if data != calGoogleCode(FortressSecret):
|
||||
print(f'阿里云工单MFA验证码:{calGoogleCode(FortressSecret)}')
|
||||
data = calGoogleCode(FortressSecret)
|
||||
i+=1
|
||||
else:
|
||||
pass
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/10/18 上午10:41
|
||||
# File : echo_text.py.py
|
||||
# 脚本作用 : 钉钉消息自动回复
|
||||
# 项目名称 : 测试
|
||||
# ------------------------------------
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
from dingtalk_stream import AckMessage
|
||||
import dingtalk_stream
|
||||
import MFA
|
||||
|
||||
|
||||
def setup_logger():
|
||||
logger = logging.getLogger()
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(
|
||||
logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
return logger
|
||||
|
||||
|
||||
def define_options():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--client_id', dest='client_id', required=True,
|
||||
help='app_key or suite_key from https://open-dev.digntalk.com'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--client_secret', dest='client_secret', required=True,
|
||||
help='app_secret or suite_secret from https://open-dev.digntalk.com'
|
||||
)
|
||||
options = parser.parse_args()
|
||||
return options
|
||||
|
||||
|
||||
class EchoTextHandler(dingtalk_stream.ChatbotHandler):
|
||||
def __init__(self, logger: logging.Logger = None):
|
||||
super(dingtalk_stream.ChatbotHandler, self).__init__()
|
||||
if logger:
|
||||
self.logger = logger
|
||||
|
||||
async def process(self, callback: dingtalk_stream.CallbackMessage):
|
||||
#消息发送人
|
||||
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
|
||||
print(incoming_message)
|
||||
#接收到的消息
|
||||
text = incoming_message.text.content.strip()
|
||||
if text == '验证码':
|
||||
data = MFA.calGoogleCode('2FO6PJ4O7S67RXHH')
|
||||
self.reply_text(f'验证码{data}', incoming_message)
|
||||
else:
|
||||
self.reply_text('不好意思,我还没有学会',incoming_message)
|
||||
#消息返回
|
||||
|
||||
return AckMessage.STATUS_OK, 'OK'
|
||||
|
||||
def main():
|
||||
logger = setup_logger()
|
||||
options = define_options()
|
||||
credential = dingtalk_stream.Credential(options.client_id, options.client_secret)
|
||||
client = dingtalk_stream.DingTalkStreamClient(credential)
|
||||
client.register_callback_handler(dingtalk_stream.chatbot.ChatbotMessage.TOPIC, EchoTextHandler(logger))
|
||||
client.start_forever()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
/usr/local/bin/python3.9 /opt/dingding/echo_text.py --client_id="dinge5z8v7iufyknqiow" --client_secret="NstaxHjjSJK2ZPX5bIQf4qhNlaeh6vrYXu71K04xs9lJ1axKk6WzeyVRlynyaYXA" >>/opt/dingding/dingding.sh&
|
||||
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/1/10 下午4:14
|
||||
# @Author : cmk
|
||||
# @File : 钉钉发送消息.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
'''
|
||||
测试使用机器人
|
||||
https://oapi.dingtalk.com/robot/send?access_token=d7e8be9866a981d899e38aa27005e264f47d1f913816caa1001f9d5229f7d074
|
||||
SEC6872ee8ddf8e72bf97f4b5f641f1cdbaf28185013d52e45b6b2a2b8c8675b959
|
||||
'''
|
||||
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import requests
|
||||
import json
|
||||
import pymysql
|
||||
|
||||
|
||||
# 消息发送
|
||||
class res_dingding():
|
||||
def __init__(self, tokin, secret=None, ip=None, guanjianchi=None):
|
||||
self.tokin = tokin
|
||||
self.secret = secret
|
||||
self.ip = ip
|
||||
self.guanjianchi = guanjianchi
|
||||
|
||||
def sign(self):
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
string_to_sign = '{}\n{}'.format(timestamp, self.secret)
|
||||
hmac_code = hmac.new(self.secret.encode('utf-8'), string_to_sign.encode('utf-8'),
|
||||
digestmod=hashlib.sha256).digest()
|
||||
sign = base64.b64encode(hmac_code).decode('utf-8')
|
||||
return timestamp, sign
|
||||
|
||||
def req(self, data):
|
||||
timestamp, sign = self.sign()
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={self.tokin}×tamp={timestamp}&sign={sign}'
|
||||
response = requests.post(url=url, data=json.dumps(data), headers={'Content-Type': 'application/json'})
|
||||
print(response.text)
|
||||
if response.status_code == 200:
|
||||
mes = "消息发送成功"
|
||||
else:
|
||||
mes = f"消息发送失败,状态码:{response.status_code}"
|
||||
print(mes)
|
||||
|
||||
class mes_type():
|
||||
|
||||
def text(self, mes):
|
||||
'''
|
||||
文本类型
|
||||
"text": {
|
||||
"content":"我就是我, @014728255240768602 是不一样的烟火"
|
||||
},
|
||||
"msgtype":"text"
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": mes
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
def link(self, mes,title,messageUrl):
|
||||
'''
|
||||
{
|
||||
"msgtype": "link",
|
||||
"link": {
|
||||
"text": "这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林",
|
||||
"title": "时代的火车向前开",
|
||||
"picUrl": "",
|
||||
"messageUrl": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI"
|
||||
}
|
||||
}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "link",
|
||||
"link": {
|
||||
"text": mes,
|
||||
"title": title,
|
||||
"picUrl": "",
|
||||
"messageUrl": messageUrl
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
def marddown(self, title,mes):
|
||||
'''
|
||||
{
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":"杭州天气",
|
||||
"text": "#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > \n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n"
|
||||
}}
|
||||
'''
|
||||
data = {
|
||||
"msgtype": "markdown",
|
||||
"markdown": {
|
||||
"title":title,
|
||||
'text': mes
|
||||
}
|
||||
}
|
||||
return data
|
||||
|
||||
class MySql():
|
||||
def __init__(self, host, port, user, passwd, db):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = passwd
|
||||
self.db = db
|
||||
self.conn = pymysql.connect(host=self.host, port=self.port, user=self.user, password=self.password,
|
||||
database=self.db)
|
||||
self.cursor = self.conn.cursor()
|
||||
|
||||
def select(self, sql):
|
||||
self.cursor.execute(sql)
|
||||
return self.cursor.fetchall()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
db = MySql('127.0.0.1', 3306, 'root', 'password', 'zucai')
|
||||
sql= '''
|
||||
SELECT
|
||||
A.new AS '数据写入时间',
|
||||
A.changci AS '比赛场次',
|
||||
A.bisai_date AS '比赛时间',
|
||||
A.bisai_type AS '比赛类型',
|
||||
A.master AS '主队',
|
||||
A.slave AS '客队',
|
||||
A.jieguo AS '平均赔率',
|
||||
B.jieguo AS '立博',
|
||||
C.jieguo AS 'Bet365',
|
||||
D.jieguo AS '澳门',
|
||||
E.jieguo AS '韦德',
|
||||
F.jieguo AS 'snai',
|
||||
G.jieguo AS '威廉',
|
||||
H.jieguo AS '平博'
|
||||
FROM
|
||||
-- 以平均赔率对应的子查询结果作为主表(这里用左连接举例,你可以根据实际需求调整连接方式)
|
||||
(SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '平均赔率' ORDER BY `new` DESC LIMIT 14) A
|
||||
-- 通过左连接关联立博对应的子查询结果,关联条件基于相同的new、master、slave字段值,同时按照时间排序取最新的一条记录
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '立博' ORDER BY `new` DESC LIMIT 14) B
|
||||
ON A.new = B.new AND A.master = B.master AND A.slave = B.slave
|
||||
-- 继续通过左连接关联Bet365对应的子查询结果,关联条件同上,且按时间排序取最新记录
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = 'Bet365' ORDER BY `new` DESC LIMIT 14) C
|
||||
ON A.new = C.new AND A.master = C.master AND A.slave = C.slave
|
||||
-- 依次按照这样的方式连接其他公司对应的子查询结果,并按时间取最新记录
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '澳门' ORDER BY `new` DESC LIMIT 14) D
|
||||
ON A.new = D.new AND A.master = D.master AND A.slave = D.slave
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '韦德' ORDER BY `new` DESC LIMIT 14) E
|
||||
ON A.new = E.new AND A.master = E.master AND A.slave = E.slave
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = 'snai' ORDER BY `new` DESC LIMIT 14) F
|
||||
ON A.new = F.new AND A.master = F.master AND A.slave = F.slave
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '威廉' ORDER BY `new` DESC LIMIT 14) G
|
||||
ON A.new = G.new AND A.master = G.master AND A.slave = G.slave
|
||||
LEFT JOIN (SELECT `new`, `changci`, `bisai_type`, `bisai_date`, `master`, `slave`, `data_s`, `data_p`, `data_f`, `jieguo`, `gongshi` FROM o_pei WHERE gongshi = '平博' ORDER BY `new` DESC LIMIT 14) H
|
||||
ON A.new = H.new AND A.master = H.master AND A.slave = H.slave;
|
||||
'''
|
||||
data_list = db.select(sql)
|
||||
data = ''
|
||||
c = "==" * 10
|
||||
print(c)
|
||||
for i in data_list:
|
||||
a = f'''{c}\n## 场次:{i[1]} {i[4]} vs {i[5]} \n## 数据获取时间: {i[0]}\n### 购买推荐:{list(i[6:14])}\n'''
|
||||
print(a)
|
||||
data +=a
|
||||
token = '5c2777357a4aa5960799d01a02588c19fa90c3f498783376075dafda7d5d706a'
|
||||
secret = 'SEC058dab30c973edc0dd70b2a7e97eddfd33f20b45a5117b7c5d55c8f2d0dec474'
|
||||
Ding = res_dingding(token, secret)
|
||||
Mes = mes_type()
|
||||
Ding.req(Mes.marddown('足彩',data))
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/6/16 11:42
|
||||
# @Author : cmk
|
||||
# @File : 动态验证码.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import time
|
||||
import base64
|
||||
import struct
|
||||
import hmac
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
def calGoogleCode(secretKey):
|
||||
input = int(time.time()) // 30
|
||||
key = base64.b32decode(secretKey)
|
||||
msg = struct.pack(">Q", input)
|
||||
googleCode = hmac.new(key, msg, hashlib.sha1).digest()
|
||||
# 版本判断
|
||||
if (sys.version_info > (2, 7)):
|
||||
o = googleCode[19] & 15
|
||||
else:
|
||||
o = ord(googleCode[19]) & 15
|
||||
googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000)
|
||||
if len(googleCode) == 5: # 如果验证码的第一位是0,则不会显示。此处判断若是5位码,则在第一位补上0
|
||||
googleCode = '0' + googleCode
|
||||
return googleCode
|
||||
|
||||
if __name__ == '__main__':
|
||||
FortressSecret = "HZKUXZZNEJX35JUVKVU7OF6F33CSV5LU"
|
||||
print(calGoogleCode(FortressSecret))
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/7/24 下午10:32
|
||||
# @Author : cmk
|
||||
# @File : 生成密钥.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import pyotp
|
||||
import time
|
||||
|
||||
totp = pyotp.random_base32()
|
||||
print(totp)
|
||||
|
||||
totp = pyotp.TOTP('HZKUXZZNEJX35JUVKVU7OF6F33CSV5LU').now()
|
||||
|
||||
print(totp)
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/27 下午4:40
|
||||
# File : MFA.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
|
||||
import time
|
||||
import base64
|
||||
import struct
|
||||
import hmac
|
||||
import sys
|
||||
import hashlib
|
||||
|
||||
|
||||
|
||||
def calGoogleCode(secretKey):
|
||||
input = int(time.time()) // 30
|
||||
key = base64.b32decode(secretKey)
|
||||
msg = struct.pack(">Q", input)
|
||||
googleCode = hmac.new(key, msg, hashlib.sha1).digest()
|
||||
# 版本判断
|
||||
if (sys.version_info > (2, 7)):
|
||||
o = googleCode[19] & 15
|
||||
else:
|
||||
o = ord(googleCode[19]) & 15
|
||||
googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000)
|
||||
if len(googleCode) == 5: # 如果验证码的第一位是0,则不会显示。此处判断若是5位码,则在第一位补上0
|
||||
googleCode = '0' + googleCode
|
||||
return googleCode
|
||||
|
||||
if __name__ == "__main__":
|
||||
#阿里云工单maf密钥
|
||||
FortressSecret = '2D3IRWIFK63PCTLQ5IK4X7JOVESELCHQGCBGBLAI5OFCJSNWC72XK463I44DIFJC'
|
||||
#国网内网堡垒机动态码---王维
|
||||
#FortressSecret = '2FO6PJ4O7S67RXHH'
|
||||
data = calGoogleCode(FortressSecret)
|
||||
print(f'阿里云工单MFA验证码:{data}')
|
||||
i = 0
|
||||
while i < 5:
|
||||
if data != calGoogleCode(FortressSecret):
|
||||
print(f'阿里云工单MFA验证码:{calGoogleCode(FortressSecret)}')
|
||||
data = calGoogleCode(FortressSecret)
|
||||
i+=1
|
||||
else:
|
||||
pass
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import pandas as pd
|
||||
|
||||
df = pd.read_excel('国网内网云版本2605.xlsx',sheet_name='部署情况')
|
||||
|
||||
print(df.head())
|
||||
Binary file not shown.
@@ -0,0 +1,497 @@
|
||||
"""
|
||||
图形化自动处理:
|
||||
1. Word -> PDF -> 图片版PDF
|
||||
2. PDF -> 图片版PDF
|
||||
|
||||
依赖:
|
||||
pip install pymupdf pywin32
|
||||
|
||||
说明:
|
||||
- 支持 .doc / .docx / .pdf
|
||||
- 支持一次选择多个文件
|
||||
- 输出图片版 PDF
|
||||
- 自动清理临时文件
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
import threading
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, messagebox, scrolledtext
|
||||
import fitz
|
||||
import win32com.client
|
||||
|
||||
|
||||
# =========================
|
||||
# 核心转换函数
|
||||
# =========================
|
||||
|
||||
def word_to_pdf_by_wps(word_path, pdf_path, log_func=print):
|
||||
"""
|
||||
WPS 转 PDF
|
||||
"""
|
||||
|
||||
wps = None
|
||||
doc = None
|
||||
|
||||
try:
|
||||
try:
|
||||
wps = win32com.client.Dispatch("KWPS.Application")
|
||||
except Exception:
|
||||
wps = win32com.client.Dispatch("wps.Application")
|
||||
|
||||
wps.Visible = False
|
||||
|
||||
doc = wps.Documents.Open(os.path.abspath(word_path))
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# 17 = PDF
|
||||
doc.ExportAsFixedFormat(os.path.abspath(pdf_path), 17)
|
||||
|
||||
log_func(f"[OK] Word 转 PDF 完成: {pdf_path}")
|
||||
|
||||
finally:
|
||||
try:
|
||||
if doc:
|
||||
doc.Close(False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
if wps:
|
||||
wps.Quit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def pdf_to_images(pdf_path, image_dir, zoom=2, log_func=print):
|
||||
"""
|
||||
PDF 每页转图片
|
||||
"""
|
||||
|
||||
os.makedirs(image_dir, exist_ok=True)
|
||||
|
||||
doc = fitz.open(pdf_path)
|
||||
|
||||
image_paths = []
|
||||
|
||||
try:
|
||||
for i in range(len(doc)):
|
||||
page = doc.load_page(i)
|
||||
|
||||
pix = page.get_pixmap(
|
||||
matrix=fitz.Matrix(zoom, zoom),
|
||||
alpha=False
|
||||
)
|
||||
|
||||
img_path = os.path.join(
|
||||
image_dir,
|
||||
f"page_{i + 1}.png"
|
||||
)
|
||||
|
||||
pix.save(img_path)
|
||||
|
||||
image_paths.append(img_path)
|
||||
|
||||
log_func(f"[OK] 截图完成: {img_path}")
|
||||
|
||||
finally:
|
||||
doc.close()
|
||||
|
||||
return image_paths
|
||||
|
||||
|
||||
def images_to_pdf(image_paths, output_pdf_path, log_func=print):
|
||||
"""
|
||||
图片重新合成 PDF
|
||||
"""
|
||||
|
||||
pdf = fitz.open()
|
||||
|
||||
try:
|
||||
for img_path in image_paths:
|
||||
img = fitz.open(img_path)
|
||||
|
||||
try:
|
||||
rect = img[0].rect
|
||||
|
||||
page = pdf.new_page(
|
||||
width=rect.width,
|
||||
height=rect.height
|
||||
)
|
||||
|
||||
page.insert_image(rect, filename=img_path)
|
||||
|
||||
finally:
|
||||
img.close()
|
||||
|
||||
pdf.save(output_pdf_path, deflate=True)
|
||||
|
||||
finally:
|
||||
pdf.close()
|
||||
|
||||
log_func(f"[OK] 图片版 PDF 已生成: {output_pdf_path}")
|
||||
|
||||
|
||||
def safe_delete(path, log_func=print):
|
||||
"""
|
||||
删除文件或目录
|
||||
"""
|
||||
|
||||
if not os.path.exists(path):
|
||||
return
|
||||
|
||||
try:
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
log_func(f"[OK] 文件已删除: {path}")
|
||||
|
||||
elif os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
log_func(f"[OK] 文件夹已删除: {path}")
|
||||
|
||||
except Exception as e:
|
||||
log_func(f"[警告] 删除失败: {path}")
|
||||
log_func(f"原因: {e}")
|
||||
|
||||
|
||||
def convert_one_file(input_path, output_dir, zoom=2, log_func=print):
|
||||
"""
|
||||
处理单个文件
|
||||
"""
|
||||
|
||||
input_path = os.path.abspath(input_path)
|
||||
|
||||
if not os.path.exists(input_path):
|
||||
raise FileNotFoundError(f"文件不存在: {input_path}")
|
||||
|
||||
ext = os.path.splitext(input_path)[1].lower()
|
||||
|
||||
base_name = os.path.splitext(os.path.basename(input_path))[0]
|
||||
|
||||
work_dir = output_dir if output_dir else os.path.dirname(input_path)
|
||||
os.makedirs(work_dir, exist_ok=True)
|
||||
|
||||
image_dir = os.path.join(
|
||||
work_dir,
|
||||
base_name + "_images"
|
||||
)
|
||||
|
||||
output_pdf_path = os.path.join(
|
||||
work_dir,
|
||||
base_name + "_图片版.pdf"
|
||||
)
|
||||
|
||||
temp_pdf_path = os.path.join(
|
||||
work_dir,
|
||||
base_name + "_temp.pdf"
|
||||
)
|
||||
|
||||
generated_temp_pdf = False
|
||||
|
||||
try:
|
||||
if ext in [".doc", ".docx"]:
|
||||
log_func("=" * 80)
|
||||
log_func(f"[1] 检测到 Word 文档: {input_path}")
|
||||
|
||||
word_to_pdf_by_wps(
|
||||
input_path,
|
||||
temp_pdf_path,
|
||||
log_func
|
||||
)
|
||||
|
||||
pdf_path = temp_pdf_path
|
||||
generated_temp_pdf = True
|
||||
|
||||
elif ext == ".pdf":
|
||||
log_func("=" * 80)
|
||||
log_func(f"[1] 检测到 PDF 文件: {input_path}")
|
||||
|
||||
pdf_path = input_path
|
||||
|
||||
else:
|
||||
raise ValueError(f"不支持的文件类型: {ext}")
|
||||
|
||||
log_func("[2] 正在按页截图...")
|
||||
|
||||
image_paths = pdf_to_images(
|
||||
pdf_path,
|
||||
image_dir,
|
||||
zoom=zoom,
|
||||
log_func=log_func
|
||||
)
|
||||
|
||||
if not image_paths:
|
||||
raise RuntimeError("PDF 没有成功生成任何图片")
|
||||
|
||||
log_func("[3] 正在生成图片版 PDF...")
|
||||
|
||||
images_to_pdf(
|
||||
image_paths,
|
||||
output_pdf_path,
|
||||
log_func=log_func
|
||||
)
|
||||
|
||||
log_func("[4] 清理临时文件...")
|
||||
|
||||
safe_delete(image_dir, log_func)
|
||||
|
||||
if generated_temp_pdf:
|
||||
safe_delete(temp_pdf_path, log_func)
|
||||
|
||||
log_func(f"[完成] 最终文件: {output_pdf_path}")
|
||||
|
||||
return output_pdf_path
|
||||
|
||||
except Exception as e:
|
||||
log_func(f"[失败] {input_path}")
|
||||
log_func(f"原因: {e}")
|
||||
raise
|
||||
|
||||
|
||||
# =========================
|
||||
# 图形化界面
|
||||
# =========================
|
||||
|
||||
class PdfImageApp:
|
||||
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Word / PDF 转图片版 PDF 工具")
|
||||
self.root.geometry("900x600")
|
||||
|
||||
self.selected_files = []
|
||||
self.output_dir = ""
|
||||
|
||||
self.build_ui()
|
||||
|
||||
def build_ui(self):
|
||||
title_label = tk.Label(
|
||||
self.root,
|
||||
text="需要本地有wps \nWord / PDF 转图片版 PDF 工具",
|
||||
font=("微软雅黑", 18, "bold")
|
||||
)
|
||||
title_label.pack(pady=10)
|
||||
|
||||
desc_label = tk.Label(
|
||||
self.root,
|
||||
text="支持 .doc / .docx / .pdf,可一次选择多个文件,自动生成图片版 PDF",
|
||||
font=("微软雅黑", 10)
|
||||
)
|
||||
desc_label.pack()
|
||||
|
||||
button_frame = tk.Frame(self.root)
|
||||
button_frame.pack(pady=10)
|
||||
|
||||
select_file_btn = tk.Button(
|
||||
button_frame,
|
||||
text="选择文件",
|
||||
width=18,
|
||||
command=self.select_files
|
||||
)
|
||||
select_file_btn.grid(row=0, column=0, padx=10)
|
||||
|
||||
select_output_btn = tk.Button(
|
||||
button_frame,
|
||||
text="选择输出目录",
|
||||
width=18,
|
||||
command=self.select_output_dir
|
||||
)
|
||||
select_output_btn.grid(row=0, column=1, padx=10)
|
||||
|
||||
start_btn = tk.Button(
|
||||
button_frame,
|
||||
text="开始转换",
|
||||
width=18,
|
||||
bg="#4CAF50",
|
||||
fg="white",
|
||||
command=self.start_convert
|
||||
)
|
||||
start_btn.grid(row=0, column=2, padx=10)
|
||||
|
||||
clear_btn = tk.Button(
|
||||
button_frame,
|
||||
text="清空日志",
|
||||
width=18,
|
||||
command=self.clear_log
|
||||
)
|
||||
clear_btn.grid(row=0, column=3, padx=10)
|
||||
|
||||
self.file_label = tk.Label(
|
||||
self.root,
|
||||
text="当前未选择文件",
|
||||
fg="blue",
|
||||
wraplength=850,
|
||||
justify="left"
|
||||
)
|
||||
self.file_label.pack(pady=5)
|
||||
|
||||
self.output_label = tk.Label(
|
||||
self.root,
|
||||
text="输出目录:默认输出到原文件所在目录",
|
||||
fg="purple",
|
||||
wraplength=850,
|
||||
justify="left"
|
||||
)
|
||||
self.output_label.pack(pady=5)
|
||||
|
||||
zoom_frame = tk.Frame(self.root)
|
||||
zoom_frame.pack(pady=5)
|
||||
|
||||
# tk.Label(
|
||||
# zoom_frame,
|
||||
# text="清晰度 zoom:"
|
||||
# ).pack(side=tk.LEFT)
|
||||
#
|
||||
# self.zoom_var = tk.StringVar(value="2")
|
||||
#
|
||||
# zoom_entry = tk.Entry(
|
||||
# zoom_frame,
|
||||
# textvariable=self.zoom_var,
|
||||
# width=8
|
||||
# )
|
||||
# zoom_entry.pack(side=tk.LEFT)
|
||||
#
|
||||
# tk.Label(
|
||||
# zoom_frame,
|
||||
# text="建议:2 正常,3 更清晰但文件更大"
|
||||
# ).pack(side=tk.LEFT, padx=10)
|
||||
|
||||
self.log_box = scrolledtext.ScrolledText(
|
||||
self.root,
|
||||
width=110,
|
||||
height=25,
|
||||
font=("Consolas", 10)
|
||||
)
|
||||
self.log_box.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
|
||||
|
||||
def log(self, msg):
|
||||
self.log_box.insert(tk.END, msg + "\n")
|
||||
self.log_box.see(tk.END)
|
||||
self.root.update_idletasks()
|
||||
|
||||
def clear_log(self):
|
||||
self.log_box.delete("1.0", tk.END)
|
||||
|
||||
def select_files(self):
|
||||
files = filedialog.askopenfilenames(
|
||||
title="请选择 Word 或 PDF 文件",
|
||||
filetypes=[
|
||||
("支持的文件", "*.doc *.docx *.pdf"),
|
||||
("Word 文件", "*.doc *.docx"),
|
||||
("PDF 文件", "*.pdf"),
|
||||
("所有文件", "*.*")
|
||||
]
|
||||
)
|
||||
|
||||
if files:
|
||||
self.selected_files = list(files)
|
||||
|
||||
self.file_label.config(
|
||||
text=f"已选择 {len(self.selected_files)} 个文件:\n" +
|
||||
"\n".join(self.selected_files)
|
||||
)
|
||||
|
||||
self.log(f"[选择文件] 共选择 {len(self.selected_files)} 个文件")
|
||||
|
||||
def select_output_dir(self):
|
||||
output_dir = filedialog.askdirectory(
|
||||
title="请选择输出目录"
|
||||
)
|
||||
|
||||
if output_dir:
|
||||
self.output_dir = output_dir
|
||||
self.output_label.config(
|
||||
text=f"输出目录:{self.output_dir}"
|
||||
)
|
||||
self.log(f"[输出目录] {self.output_dir}")
|
||||
|
||||
def start_convert(self):
|
||||
if not self.selected_files:
|
||||
messagebox.showwarning(
|
||||
"提示",
|
||||
"请先选择一个或多个 Word / PDF 文件"
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
zoom = float(self.zoom_var.get())
|
||||
if zoom <= 0:
|
||||
raise ValueError
|
||||
except Exception:
|
||||
messagebox.showwarning(
|
||||
"提示",
|
||||
"zoom 必须是大于 0 的数字,例如 2 或 3"
|
||||
)
|
||||
return
|
||||
|
||||
t = threading.Thread(
|
||||
target=self.convert_files_thread,
|
||||
args=(zoom,),
|
||||
daemon=True
|
||||
)
|
||||
t.start()
|
||||
|
||||
def convert_files_thread(self, zoom):
|
||||
success_files = []
|
||||
failed_files = []
|
||||
|
||||
self.log("")
|
||||
self.log("========== 开始批量转换 ==========")
|
||||
|
||||
for index, file_path in enumerate(self.selected_files, start=1):
|
||||
self.log("")
|
||||
self.log(f"[任务 {index}/{len(self.selected_files)}] {file_path}")
|
||||
|
||||
try:
|
||||
output_pdf = convert_one_file(
|
||||
input_path=file_path,
|
||||
output_dir=self.output_dir,
|
||||
zoom=zoom,
|
||||
log_func=self.log
|
||||
)
|
||||
|
||||
success_files.append(output_pdf)
|
||||
|
||||
except Exception as e:
|
||||
failed_files.append((file_path, str(e)))
|
||||
|
||||
self.log("")
|
||||
self.log("========== 批量转换结束 ==========")
|
||||
self.log(f"[成功] {len(success_files)} 个")
|
||||
self.log(f"[失败] {len(failed_files)} 个")
|
||||
|
||||
if success_files:
|
||||
self.log("")
|
||||
self.log("生成的图片版 PDF:")
|
||||
for f in success_files:
|
||||
self.log(f)
|
||||
|
||||
if failed_files:
|
||||
self.log("")
|
||||
self.log("失败文件:")
|
||||
for f, reason in failed_files:
|
||||
self.log(f"{f} -> {reason}")
|
||||
|
||||
if failed_files:
|
||||
messagebox.showwarning(
|
||||
"转换完成",
|
||||
f"处理完成。\n\n成功:{len(success_files)} 个\n失败:{len(failed_files)} 个\n\n请查看日志。\n\n请使用生成的“图片版 PDF”文件。"
|
||||
)
|
||||
else:
|
||||
messagebox.showinfo(
|
||||
"转换完成",
|
||||
f"全部处理完成。\n\n成功生成 {len(success_files)} 个图片版 PDF。\n\n请使用生成的“图片版 PDF”文件。"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
root = tk.Tk()
|
||||
app = PdfImageApp(root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,248 @@
|
||||
"""
|
||||
自动处理:
|
||||
1. Word -> PDF -> 图片版PDF
|
||||
2. PDF -> 图片版PDF
|
||||
|
||||
依赖:
|
||||
pip install pymupdf pywin32
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import shutil
|
||||
import fitz
|
||||
import win32com.client
|
||||
|
||||
|
||||
def word_to_pdf_by_wps(word_path, pdf_path):
|
||||
"""
|
||||
WPS 转 PDF
|
||||
"""
|
||||
|
||||
try:
|
||||
wps = win32com.client.Dispatch("KWPS.Application")
|
||||
except Exception:
|
||||
wps = win32com.client.Dispatch("wps.Application")
|
||||
|
||||
wps.Visible = False
|
||||
|
||||
doc = wps.Documents.Open(os.path.abspath(word_path))
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# 17 = PDF
|
||||
doc.ExportAsFixedFormat(os.path.abspath(pdf_path), 17)
|
||||
|
||||
doc.Close(False)
|
||||
wps.Quit()
|
||||
|
||||
print(f"[OK] Word 转 PDF 完成: {pdf_path}")
|
||||
|
||||
|
||||
def pdf_to_images(pdf_path, image_dir, zoom=2):
|
||||
"""
|
||||
PDF 每页转图片
|
||||
"""
|
||||
|
||||
os.makedirs(image_dir, exist_ok=True)
|
||||
|
||||
doc = fitz.open(pdf_path)
|
||||
|
||||
image_paths = []
|
||||
|
||||
for i in range(len(doc)):
|
||||
page = doc.load_page(i)
|
||||
|
||||
pix = page.get_pixmap(
|
||||
matrix=fitz.Matrix(zoom, zoom),
|
||||
alpha=False
|
||||
)
|
||||
|
||||
img_path = os.path.join(
|
||||
image_dir,
|
||||
f"page_{i + 1}.png"
|
||||
)
|
||||
|
||||
pix.save(img_path)
|
||||
|
||||
image_paths.append(img_path)
|
||||
|
||||
print(f"[OK] 截图完成: {img_path}")
|
||||
|
||||
doc.close()
|
||||
|
||||
return image_paths
|
||||
|
||||
|
||||
def images_to_pdf(image_paths, output_pdf_path):
|
||||
"""
|
||||
图片重新合成 PDF
|
||||
"""
|
||||
|
||||
pdf = fitz.open()
|
||||
|
||||
for img_path in image_paths:
|
||||
img = fitz.open(img_path)
|
||||
|
||||
rect = img[0].rect
|
||||
|
||||
page = pdf.new_page(
|
||||
width=rect.width,
|
||||
height=rect.height
|
||||
)
|
||||
|
||||
page.insert_image(rect, filename=img_path)
|
||||
|
||||
img.close()
|
||||
|
||||
pdf.save(output_pdf_path, deflate=True)
|
||||
pdf.close()
|
||||
|
||||
print(f"[OK] 图片版 PDF 已生成: {output_pdf_path}")
|
||||
|
||||
|
||||
def safe_delete(path):
|
||||
"""
|
||||
自动删除:
|
||||
- 文件
|
||||
- 空目录
|
||||
- 非空目录
|
||||
"""
|
||||
|
||||
if not os.path.exists(path):
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
print(f"[OK] 文件已删除: {path}")
|
||||
|
||||
elif os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
print(f"[OK] 文件夹已删除: {path}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[警告] 删除失败: {path}")
|
||||
print(f"原因: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("用法:")
|
||||
print("python auto_pdf_image.py 文件")
|
||||
return
|
||||
|
||||
input_path = os.path.abspath(sys.argv[1])
|
||||
|
||||
if not os.path.exists(input_path):
|
||||
print("文件不存在:", input_path)
|
||||
return
|
||||
|
||||
ext = os.path.splitext(input_path)[1].lower()
|
||||
|
||||
base_dir = os.path.dirname(input_path)
|
||||
base_name = os.path.splitext(os.path.basename(input_path))[0]
|
||||
|
||||
image_dir = os.path.join(
|
||||
base_dir,
|
||||
base_name + "_images"
|
||||
)
|
||||
|
||||
output_pdf_path = os.path.join(
|
||||
base_dir,
|
||||
base_name + "_图片版.pdf"
|
||||
)
|
||||
|
||||
temp_pdf_path = os.path.join(
|
||||
base_dir,
|
||||
base_name + "_temp.pdf"
|
||||
)
|
||||
|
||||
generated_temp_pdf = False
|
||||
|
||||
try:
|
||||
|
||||
# =========================
|
||||
# Word 文档
|
||||
# =========================
|
||||
if ext in [".doc", ".docx"]:
|
||||
|
||||
print("[1] 检测到 Word 文档")
|
||||
|
||||
word_to_pdf_by_wps(
|
||||
input_path,
|
||||
temp_pdf_path
|
||||
)
|
||||
|
||||
pdf_path = temp_pdf_path
|
||||
|
||||
generated_temp_pdf = True
|
||||
|
||||
# =========================
|
||||
# PDF 文件
|
||||
# =========================
|
||||
elif ext == ".pdf":
|
||||
|
||||
print("[1] 检测到 PDF 文件")
|
||||
|
||||
pdf_path = input_path
|
||||
|
||||
else:
|
||||
print("仅支持:")
|
||||
print(".doc")
|
||||
print(".docx")
|
||||
print(".pdf")
|
||||
return
|
||||
|
||||
# =========================
|
||||
# PDF -> 图片
|
||||
# =========================
|
||||
print("[2] 正在按页截图...")
|
||||
|
||||
image_paths = pdf_to_images(
|
||||
pdf_path,
|
||||
image_dir,
|
||||
zoom=2
|
||||
)
|
||||
|
||||
# =========================
|
||||
# 图片 -> PDF
|
||||
# =========================
|
||||
print("[3] 正在生成图片版 PDF...")
|
||||
|
||||
images_to_pdf(
|
||||
image_paths,
|
||||
output_pdf_path
|
||||
)
|
||||
|
||||
# =========================
|
||||
# 删除临时文件
|
||||
# =========================
|
||||
print("[4] 清理临时文件...")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
safe_delete(image_dir)
|
||||
|
||||
# 删除临时 PDF
|
||||
if generated_temp_pdf:
|
||||
safe_delete(temp_pdf_path)
|
||||
|
||||
print()
|
||||
print("[完成]")
|
||||
print("最终文件:", output_pdf_path)
|
||||
|
||||
except Exception as e:
|
||||
print("[失败]", e)
|
||||
print()
|
||||
print("请确认:")
|
||||
print("1. WPS 已安装")
|
||||
print("2. 文档能正常打开")
|
||||
print("3. 文件未被占用")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/4/22 17:05
|
||||
# @Author : cmk
|
||||
# @File : check_perf_jiankong.py
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
|
||||
def get_vm_name(sr):
|
||||
url = 'http://localhost:7070/api/v3/column/m.ip?m.sr.id={}%23'.format(sr)
|
||||
data = requests.get(url=url).text
|
||||
data = json.loads(data) # 列表
|
||||
sr_ip_list = []
|
||||
for i in range(len(data)):
|
||||
sr_ip_list.append(data[i]['m.ip'])
|
||||
return sr_ip_list
|
||||
|
||||
|
||||
def get_vm_docker_id(sr):
|
||||
vm_docker_list = []
|
||||
for ip in get_vm_name(sr):
|
||||
cmd = '''ssh %s -o ConnectTimeout=5 -o ConnectionAttempts=3 -o PasswordAuthentication=no -o StrictHostKeyChecking=no docker ps |grep %s |awk '{print $1}' ''' % (
|
||||
ip, sr)
|
||||
docker_id = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
vm_docker_dise = []
|
||||
vm_docker_dise.append(ip)
|
||||
vm_docker_dise.append(docker_id)
|
||||
vm_docker_list.append(vm_docker_dise)
|
||||
return vm_docker_list
|
||||
|
||||
if __name__ == '__main__':
|
||||
sr = 'redline-perf.PerfWorker'
|
||||
rds_id = sys.argv[1]
|
||||
for docker_id in get_vm_docker_id(sr):
|
||||
cmd = '''ssh %s docker exec -i %s ifconfig|grep inet|grep broadcast|awk '{print $2}' ''' % (docker_id[0],docker_id[1])
|
||||
ip = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
#curl -L "http://127.0.0.1:8080/v1/api/timeSeries/mysql_perf?insName=rm-sj55xtw8hapf4848x&targetMetrics=avg.cpu_usage"
|
||||
url = "http://{}:8080/v1/api/timeSeries/mysql_perf?insName={}&targetMetrics=avg.cpu_usage".format(ip,rds_id)
|
||||
data = json.loads(requests.get(url).text)
|
||||
keys = data[0].keys()
|
||||
key_list = list(keys)
|
||||
if 'success' in key_list:
|
||||
print '\033[91m服务:{},ip信息:{},性能监控异常,服务异常,需要排查app.log日志\033[0m'.format(sr,docker_id[0])
|
||||
else:
|
||||
print '\033[92m服务:{},ip信息:{},性能监控正常\033[0m'.format(sr,docker_id[0])
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
# @Time : 2024/4/18 19:25
|
||||
# @Author : cmk
|
||||
# @File : check_perf_jiya.py
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
'''
|
||||
date &&
|
||||
curl "http://localhost:7070/api/v3/column/m.ip?m.sr.id=redline-perf.PerfMaster%23"| grep ip | awk -F '"' '{print $(NF-1)}' > masterhosts
|
||||
curl "http://localhost:7070/api/v3/column/m.ip?m.sr.id=redline-perf.PerfWorker%23" | grep ip | awk -F '"' '{print $(NF-1)}' > perfworkerhosts
|
||||
curl "http://localhost:7070/api/v3/column/m.ip?m.sr.id=redline-perf.LogWorker%23"| grep ip | awk -F '"' '{print $(NF-1)}' > logworkerhosts
|
||||
&& cat perfworkerhosts > allhosts && cat logworkerhosts >> allhosts && cat masterhosts >> allhosts && sort allhosts | uniq > allhosts2
|
||||
pssh -P -i -p 10 -h perfworkerhosts "cd /cloud/data/redline-perf/PerfWorker#/perf-worker/home/admin/redline-perf;tail -n 300 ./log/app.log | grep processing | tail -n 10 "
|
||||
pssh -P -i -p 10 -h logworkerhosts "cd /cloud/data/redline-perf/LogWorker#/log-worker/home/admin/redline-perf; tail -n 300 ./log/app.log | grep processing | tail -n 10 "
|
||||
grep processing /home/admin/redline-perf/log/app.log | tail -n 10
|
||||
'''
|
||||
|
||||
|
||||
def get_vm_name(sr):
|
||||
url = 'http://localhost:7070/api/v3/column/m.ip?m.sr.id={}%23'.format(sr)
|
||||
data = requests.get(url=url).text
|
||||
data = json.loads(data) # 列表
|
||||
sr_ip_list = []
|
||||
for i in range(len(data)):
|
||||
sr_ip_list.append(data[i]['m.ip'])
|
||||
return sr_ip_list
|
||||
|
||||
|
||||
def get_vm_docker_id(sr):
|
||||
vm_docker_list = []
|
||||
for ip in get_vm_name(sr):
|
||||
cmd = '''ssh %s -o ConnectTimeout=5 -o ConnectionAttempts=3 -o PasswordAuthentication=no -o StrictHostKeyChecking=no docker ps |grep %s |awk '{print $1}' ''' % (
|
||||
ip, sr)
|
||||
docker_id = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
vm_docker_dise = []
|
||||
vm_docker_dise.append(ip)
|
||||
vm_docker_dise.append(docker_id)
|
||||
vm_docker_list.append(vm_docker_dise)
|
||||
return vm_docker_list
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sr_list = ['redline-perf.PerfWorker', 'redline-perf.PerfMaster', 'redline-perf.LogWorker']
|
||||
for sr in sr_list:
|
||||
vm_docker_id = get_vm_docker_id(sr)
|
||||
for i in range(len(vm_docker_id)):
|
||||
ip = vm_docker_id[i][0]
|
||||
docker_id = vm_docker_id[i][1]
|
||||
# 需要添加判断,可能存在多个异常
|
||||
cmd = '''ssh %s docker exec -i %s 'grep processed-received /home/admin/redline-perf/log/app.log | tail -n 1' ''' % (
|
||||
ip, docker_id)
|
||||
#data_list = os.popen(cmd).readlines()
|
||||
#for data in data_list:
|
||||
data = os.popen(cmd).readline()
|
||||
data = data.rsplit(':')
|
||||
data_int = int(data[-1])
|
||||
mes_list = []
|
||||
if data_int < int(-100):
|
||||
print "\033[91m 服务是:{},ip是:{},服务当前值是:{},当前服务存在积压,需要重启异常sr\033[0m".format(sr, ip, data_int)
|
||||
# data = raw_input('当前节点存在积压影响管控使用,是否重启,重启输入:Y,不重启输入N,其他默认不重启:\n')
|
||||
# if data.lower() == 'y':
|
||||
# os.system('ssh {} docker restart {}'.format(ip,docker_id))
|
||||
# else:
|
||||
# pass
|
||||
else:
|
||||
print "\033[92m 服务是:{},ip是:{},服务当前值是:{},当前服务正常\033[0m".format(sr, ip, data_int)
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/4/22 17:05
|
||||
# @Author : cmk
|
||||
# @File : check_perf_jiankong.py
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import random
|
||||
|
||||
import requests
|
||||
|
||||
def get_vm_name(sr):
|
||||
url = 'http://localhost:7070/api/v3/column/m.ip?m.sr.id={}%23'.format(sr)
|
||||
data = requests.get(url=url).text
|
||||
data = json.loads(data) # 列表
|
||||
sr_ip_list = []
|
||||
for i in range(len(data)):
|
||||
sr_ip_list.append(data[i]['m.ip'])
|
||||
return sr_ip_list
|
||||
|
||||
|
||||
def get_vm_docker_id(sr):
|
||||
vm_docker_list = []
|
||||
for ip in get_vm_name(sr):
|
||||
cmd = '''ssh %s -o ConnectTimeout=5 -o ConnectionAttempts=3 -o PasswordAuthentication=no -o StrictHostKeyChecking=no docker ps |grep %s |awk '{print $1}' ''' % (
|
||||
ip, sr)
|
||||
docker_id = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
vm_docker_dise = []
|
||||
vm_docker_dise.append(ip)
|
||||
vm_docker_dise.append(docker_id)
|
||||
vm_docker_list.append(vm_docker_dise)
|
||||
return vm_docker_list
|
||||
|
||||
if __name__ == '__main__':
|
||||
sr = 'redline-perf.LogWorker'
|
||||
rds_id = sys.argv[1]
|
||||
number = random.randint(0,len(get_vm_docker_id(sr))-1)
|
||||
docker_id = get_vm_docker_id(sr)[number]
|
||||
cmd = '''ssh %s docker exec -i %s ifconfig|grep inet|grep broadcast|awk '{print $2}' ''' % (docker_id[0],docker_id[1])
|
||||
ip = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
# 慢sql信息(一个节点)
|
||||
#curl - L "http://127.0.0.1:8080/v2/api/log/slowlog/detail?dbType=mysql&insName=rm-9uryw9o566n148lc4&pageCount=1&pageSize=30&reverseOrderQuery=true¤tPage=1"
|
||||
url = "http://{}:8080/v2/api/log/slowlog/detail?dbType=mysql&insName={}&pageCount=1&pageSize=30&reverseOrderQuery=true¤tPage=1".format(ip,rds_id)
|
||||
data = json.loads(requests.get(url).text)
|
||||
keys = data.keys()
|
||||
key_list = list(keys)
|
||||
if 'success' in key_list:
|
||||
if data.get('success') == True:
|
||||
print '\033[92m服务:{},ip信息:{},慢sql审计功能正常\033[0m'.format(sr, docker_id[0])
|
||||
print data
|
||||
else:
|
||||
print '\033[91m服务:{},ip信息:{},慢sql审计功能异常,需要排查app.log日志\033[0m'.format(sr, docker_id[0])
|
||||
print data
|
||||
else:
|
||||
print '\033[91m服务:{},ip信息:{},慢sql审计功能异常,需要排查app.log日志\033[0m'.format(sr, docker_id[0])
|
||||
print data
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/4/22 17:05
|
||||
# @Author : cmk
|
||||
# @File : check_perf_jiankong.py
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
|
||||
def get_vm_name(sr):
|
||||
url = 'http://localhost:7070/api/v3/column/m.ip?m.sr.id={}%23'.format(sr)
|
||||
data = requests.get(url=url).text
|
||||
data = json.loads(data) # 列表
|
||||
sr_ip_list = []
|
||||
for i in range(len(data)):
|
||||
sr_ip_list.append(data[i]['m.ip'])
|
||||
return sr_ip_list
|
||||
|
||||
|
||||
def get_vm_docker_id(sr):
|
||||
vm_docker_list = []
|
||||
for ip in get_vm_name(sr):
|
||||
cmd = '''ssh %s -o ConnectTimeout=5 -o ConnectionAttempts=3 -o PasswordAuthentication=no -o StrictHostKeyChecking=no docker ps |grep %s |awk '{print $1}' ''' % (
|
||||
ip, sr)
|
||||
docker_id = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
vm_docker_dise = []
|
||||
vm_docker_dise.append(ip)
|
||||
vm_docker_dise.append(docker_id)
|
||||
vm_docker_list.append(vm_docker_dise)
|
||||
return vm_docker_list
|
||||
|
||||
if __name__ == '__main__':
|
||||
sr = 'redline-perf.LogWorker'
|
||||
rds_id = sys.argv[1]
|
||||
for docker_id in get_vm_docker_id(sr):
|
||||
cmd = '''ssh %s docker exec -i %s ifconfig|grep inet|grep broadcast|awk '{print $2}' ''' % (docker_id[0],docker_id[1])
|
||||
ip = os.popen(cmd).readlines()[0].replace('\n', '')
|
||||
#curl -L "http://127.0.0.1:8080/v1/api/log/auditlog/detail?dbType=mysql&identityLogGroup=rm-9uryw9o566n148lc4&pageCount=1&pageSize=30&reverseOrderQuery=true"
|
||||
url = "http://{}:8080/v1/api/log/auditlog/detail?dbType=mysql&identityLogGroup={}&pageCount=1&pageSize=30&reverseOrderQuery=true".format(ip,rds_id)
|
||||
data = json.loads(requests.get(url).text)
|
||||
keys = data[0].keys()
|
||||
key_list = list(keys)
|
||||
if 'success' in key_list:
|
||||
print '\033[91m服务:{},ip信息:{},sql审计功能服务异常,需要排查app.log日志\033[0m'.format(sr,docker_id[0])
|
||||
else:
|
||||
print '\033[92m服务:{},ip信息:{},sql审计功能服务正常\033[0m'.format(sr,docker_id[0])
|
||||
@@ -0,0 +1,10 @@
|
||||
perf链路积压巡检
|
||||
/home/tops/bin/python /apsarapangu/shujuku/001_zongbu_jiaoben_shell_python/check_perf/check_perf_jiya.py
|
||||
perf性能监控巡检,rds需要随机写一个
|
||||
/home/tops/bin/python /apsarapangu/shujuku/001_zongbu_jiaoben_shell_python/check_perf/check_perf_jiankong.py rm-9uryw9o566n148lc4
|
||||
# 查看每个logwork节点处理sql数据量
|
||||
go_sr exec redline-perf.PerfMaster "grep -E 'MASTER_INFO_LOG|TOTAL_DATASIZE_PER_TICK_TOK' /home/admin/redline-perf/log/master.log"
|
||||
#log审计(全部节点)
|
||||
curl -L "http://127.0.0.1:8080/v1/api/log/auditlog/detail?dbType=mysql&identityLogGroup=rm-9uryw9o566n148lc4&pageCount=1&pageSize=30&reverseOrderQuery=true"
|
||||
#慢sql信息(一个节点)
|
||||
curl -L "http://127.0.0.1:8080/v2/api/log/slowlog/detail?dbType=mysql&insName=rm-9uryw9o566n148lc4&pageCount=1&pageSize=30&reverseOrderQuery=true¤tPage=1"
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/5/28 14:12
|
||||
# @Author : cmk
|
||||
# @File : Class_db.py
|
||||
|
||||
|
||||
|
||||
import MySQLdb
|
||||
|
||||
class MySQL:
|
||||
def __init__(self, host,port, user, password, database):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.database = database
|
||||
self.conn = None
|
||||
self.cursor = None
|
||||
|
||||
def connect(self):
|
||||
self.conn = MySQLdb.connect(host=self.host,port=self.port,user=self.user,passwd=self.password,db=self.database)
|
||||
self.cursor = self.conn.cursor()
|
||||
print "Login %s successful!"%self.database
|
||||
|
||||
def commit(self): #提交事务
|
||||
self.conn.commit()
|
||||
|
||||
|
||||
def rollback(self): #回滚事务
|
||||
self.conn.rollback()
|
||||
|
||||
def close(self): # 关闭数据库连接和游标
|
||||
if self.conn:
|
||||
self.conn.close()
|
||||
print "Connection closed."
|
||||
|
||||
#简单的sql,不存在传参,直接查询
|
||||
def select(self,sql):
|
||||
self.connect()
|
||||
print sql
|
||||
self.cursor.execute(sql)
|
||||
self.close()
|
||||
return self.cursor.fetchall()
|
||||
|
||||
# insert
|
||||
def add_delete_inster(self,sql):
|
||||
self.connect()
|
||||
print sql
|
||||
self.cursor.execute(sql)
|
||||
self.commit()
|
||||
print 'Execution insert successful!'
|
||||
self.close()
|
||||
|
||||
# insert表的列比较长的
|
||||
def insert_json(self,table,data):
|
||||
self.connect()
|
||||
keys = ', '.join(data.keys())
|
||||
values = ', '.join(['"{}"'.format(k) for k in data.values()])
|
||||
sql = 'insert into %s(%s) values(%s)' %(table,keys,values)
|
||||
print sql
|
||||
self.cursor.execute(sql)
|
||||
self.commit()
|
||||
print 'Execution insert_json successful!'
|
||||
self.close()
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/6/12 10:32
|
||||
# @Author : cmk
|
||||
# @File : db_dwphoenix.py
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import requests
|
||||
import Class_db
|
||||
from time import sleep
|
||||
import put_sms
|
||||
|
||||
url = "http://localhost:7070/api/v3/column/service.res.result,service.res.serverrole?service.res.type=db&service.res.name={}".format('dwphoenix');
|
||||
data = requests.get(url=url).text
|
||||
data_all = json.loads(data)[0].get('service.res.result')
|
||||
data_all = json.loads(data_all)
|
||||
host = data_all.get('db_host')
|
||||
port = int(data_all.get('db_port'))
|
||||
user = data_all.get('db_user')
|
||||
password = data_all.get('db_password')
|
||||
database = data_all.get('dbName')
|
||||
|
||||
|
||||
now = datetime.datetime.now()
|
||||
date = now.strftime('%Y-%m-%d')
|
||||
db = Class_db.MySQL(host=host,port=port,user=user,password=password,database=database)
|
||||
#sql_phoenix_task_transfer_flow = 'select gmt_create,stage from phoenix_task_transfer_flow where gmt_create like "2024-06-11%" order by id desc limit 1'
|
||||
sql_phoenix_task_transfer_flow = 'select gmt_create,stage from phoenix_task_transfer_flow where gmt_create like "{}%" order by id desc limit 1'.format(date)
|
||||
sql_phoenix_task_inst = 'select bizdate,count(1) from phoenix_task_inst where dag_type = 0 and bizdate > current_date - 2 group by bizdate'
|
||||
|
||||
count = 0
|
||||
while count < 60:
|
||||
data_phoenix_task_transfer_flow = db.select(sql_phoenix_task_transfer_flow)
|
||||
#if len(data_phoenix_task_transfer_flow[0]) >=2:
|
||||
if data_phoenix_task_transfer_flow[0][1] == 70:
|
||||
data_phoenix_task_inst = db.select(sql_phoenix_task_inst)
|
||||
mes = '转实例stage时间:{}\n转实例stage状态:{}\n昨日转实例数量:{}-{}\n今日转实例数量:{}-{}'.format(data_phoenix_task_transfer_flow[0][0],data_phoenix_task_transfer_flow[0][1],data_phoenix_task_inst[0][0],data_phoenix_task_inst[0][1],data_phoenix_task_inst[1][0],data_phoenix_task_inst[1][1])
|
||||
print mes
|
||||
put_sms.SLS_PORT('13552923180',mes).sms()
|
||||
break
|
||||
count+=1
|
||||
sleep(60)
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2024/6/12 9:19
|
||||
# @Author : cmk
|
||||
# @File : put_sms.py
|
||||
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
class SLS_PORT:
|
||||
def __init__(self,phone,manages):
|
||||
self.phone = phone
|
||||
self.manages = manages
|
||||
|
||||
def sms(self):
|
||||
headers = {
|
||||
'User-Agent': 'Apipost client Runtime/+https://www.apipost.cn/',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
params = (
|
||||
('token', 'DiEmKwjle8ZXI3V4zAn1cyRq0s2CdbhN'),
|
||||
)
|
||||
data = {"flag": "test", "text": self.manages, "phone": self.phone}
|
||||
# ecs接口
|
||||
#res = requests.post('http://26.0.3.55:15000/app/slsNotify/', headers=headers, params=params,data=json.dumps(data))
|
||||
# 物理机接口http:20.1.60.195:34982
|
||||
res = requests.post('http://20.1.60.195:34982/app/slsNotify/', headers=headers, params=params,data=json.dumps(data))
|
||||
return res.text
|
||||
@@ -0,0 +1,168 @@
|
||||
import sys,time,os,base64
|
||||
from pywinauto.application import Application
|
||||
import ddddocr
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
import hmac, base64, struct, hashlib
|
||||
from PIL import Image
|
||||
|
||||
url = 'https://bastionhost.res.sgmc.sgcc.com.cn/index.php/login'
|
||||
username = "chengmingkun"#设置堡垒机账号
|
||||
|
||||
#password = 'AliOS%1688' #上一次 2
|
||||
#password = '1234sheng!WSS' #最近一次 3
|
||||
#password = '123sheng!WSS' 1
|
||||
|
||||
#FortressSecret = "C4L2SFCFLSCPQPEC6LVN6D3PTTCUZKMB" #堡垒机口令秘钥
|
||||
|
||||
password = 'Admin@123'
|
||||
FortressSecret = "YHETDNUGNRO323Z6XQDQVJMQ4JMEYYS5"
|
||||
|
||||
search_host = "20.1.216.139" #设置主机运维中搜素ip,如果为空则跳过搜索
|
||||
#"20.1.216.139"
|
||||
|
||||
SHUTDOWN_TIME = 600 #设置堡垒机页面保留时间
|
||||
|
||||
#设置chromedriver路径
|
||||
if os.path.exists(os.path.join(os.path.join(os.environ["HOMEPATH"],"Desktop"),"chromedriver.exe")):
|
||||
webdriverpath = os.path.join(os.path.join(os.environ["HOMEPATH"],"Desktop"),"chromedriver.exe")
|
||||
else:
|
||||
webdriverpath = os.path.join(sys.exec_prefix + '\\lib','chromedriver.exe')
|
||||
|
||||
def calGoogleCode(secretKey):
|
||||
input = int(time.time()) // 30
|
||||
key = base64.b32decode(secretKey)
|
||||
msg = struct.pack(">Q", input)
|
||||
googleCode = hmac.new(key, msg, hashlib.sha1).digest()
|
||||
# 版本判断
|
||||
if (sys.version_info > (2, 7)):
|
||||
o = googleCode[19] & 15
|
||||
else:
|
||||
o = ord(googleCode[19]) & 15
|
||||
googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000)
|
||||
if len(googleCode) == 5: # 如果验证码的第一位是0,则不会显示。此处判断若是5位码,则在第一位补上0
|
||||
googleCode = '0' + googleCode
|
||||
return googleCode
|
||||
class Login_Agent():
|
||||
def __init__(self,url,username,password):
|
||||
self.url = url
|
||||
self.username = username
|
||||
self.password = password
|
||||
opt = webdriver.ChromeOptions() # 创建浏览
|
||||
opt.add_argument('--ignore-certificate-errors')
|
||||
opt.add_argument('--disable-extensions')
|
||||
opt.add_argument('--disable-web-security')
|
||||
opt.add_argument('--all-running-insecure-content')
|
||||
opt.add_experimental_option("excludeSwitches", ["enable-automation"]) # 隐藏浏览器会有“Chrome提示受到自动软件控制”的提示
|
||||
opt.add_experimental_option('useAutomationExtension', False)
|
||||
opt.add_experimental_option('detach', True)
|
||||
caps = opt.to_capabilities()
|
||||
caps['goog:chromeOptions'] = {'agrs': ['--disable-features=CrossSiteDocumentNlockingIfIsolating']}
|
||||
# 不自动关闭浏览器
|
||||
self.driver = webdriver.Chrome(webdriverpath, options=opt) # 创建浏览器对象
|
||||
def login_run(self):
|
||||
self.driver.get(self.url) # 打开网页0
|
||||
self.driver.maximize_window()#最大化浏览器页面
|
||||
if "密码" in self.driver.find_element(By.XPATH, r'//*[@id="sign-box"]/ul').text:
|
||||
self.driver.find_element(By.ID, "pwd_username").send_keys(self.username)#输入账号
|
||||
self.driver.find_element(By.ID, "pwd_pwd").send_keys(self.password)#输入密码
|
||||
self.img_path = r'//*[@id="sign-box"]/form[1]/div[3]/div/div/img'
|
||||
self.yzm = 'pwd_captcha'
|
||||
self.login = r'//*[@id="sign-box"]/form[1]/div[4]/button'
|
||||
else:
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="sign-box"]/ul/li[2]').click()#切换为手机口令页面
|
||||
self.driver.find_element(By.LINK_TEXT, '手机APP口令').click()#切换为手机口令页面
|
||||
self.driver.find_element(By.ID, "ga_username").send_keys(self.username)#输入账号
|
||||
self.driver.find_element(By.ID, "ga_pwd").send_keys(self.password)#输入密码
|
||||
self.driver.find_element(By.ID, "ga_totp").send_keys(calGoogleCode(FortressSecret))#输入口令
|
||||
self.img_path = r'//*[@id="sign-box"]/form[5]/div[4]/div/div/img'
|
||||
self.yzm = 'ga_captcha'
|
||||
self.login = r'//*[@id="sign-box"]/form[5]/div[5]/button'
|
||||
#刷新一下验证码,第一次获取验证码无法登录
|
||||
self.driver.find_element(By.XPATH, self.img_path).click()
|
||||
self.image_code()#解析图片验证码
|
||||
for i in range(6):#循环5次,判断验证码是否正确,如果验证码错误,重新调用image_code()
|
||||
time.sleep(0.1)
|
||||
try:
|
||||
if self.driver.find_element(By.XPATH, r'//*[@id="sign-box"]/div[2]/span').text == "验证码错误":
|
||||
self.image_code()
|
||||
elif self.driver.find_element(By.XPATH, r'//*[@id="sign-box"]/div[2]/span').text == "动态口令错误":
|
||||
self.driver.find_element(By.ID, "ga_pwd").send_keys(self.password)#输入密码
|
||||
self.driver.find_element(By.ID, "ga_totp").send_keys(calGoogleCode(FortressSecret))#输入口令
|
||||
self.image_code()
|
||||
else:
|
||||
break
|
||||
except Exception as e:
|
||||
pass
|
||||
time.sleep(0.2)
|
||||
try:#防止遇到登录成功,但是需要强制修改密码
|
||||
self.driver.find_element(By.XPATH, r'/html/body/div/div[2]/div[1]/ul/li[3]/a/i').click()#点击运维菜单
|
||||
os.remove("web_screen.png")
|
||||
os.remove("checkcode.png")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(1)#//*[@id="table-om-asset"]/tbody/tr[1]/td[5]/select
|
||||
#//*[@id="table-om-asset"]/tbody/tr[1]/td[5]/select
|
||||
|
||||
self.driver.find_element(By.XPATH, r'/html/body/div/div[2]/div[1]/ul/li[3]/ul/li[1]/a').click()#点击运维下主机运维菜单
|
||||
if search_host: # 如果存在ip则搜索列表
|
||||
time.sleep(0.5)
|
||||
self.search_host()
|
||||
user_root = self.driver.find_element(By.XPATH, r'//*[@id="table-om-asset"]/tbody/tr[1]/td[5]/select')
|
||||
if "opsae" not in user_root.text.splitlines()[0]:#判断账号是否是root
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="table-om-asset"]/tbody/tr[1]/td[5]/select').click() #如果不是root,点击切换为root
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="table-om-asset"]/tbody/tr[1]/td[5]/select/option[2]').click()
|
||||
#self.driver.find_element(By.XPATH, r'//*[@id="table-om-asset"]/tbody/tr[1]/td[6]/div/i').click() #点击登录xshell
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="table-om-asset"]/tbody/tr[1]/td[6]/div/i').click() #点击登录xshell
|
||||
xshell_auto()
|
||||
time.sleep(SHUTDOWN_TIME)
|
||||
self.driver.quit()
|
||||
def image_code(self):
|
||||
time.sleep(0.18)
|
||||
self.driver.save_screenshot("web_screen.png")
|
||||
page_snap_obj = Image.open("web_screen.png")
|
||||
img = self.driver.find_element(By.XPATH, self.img_path)
|
||||
location = img.location
|
||||
size = img.size
|
||||
left = location['x']
|
||||
top = location['y']
|
||||
right = left + size['width']
|
||||
bottom = top + size['height']
|
||||
image_obj = page_snap_obj.crop((left,top,right,bottom))
|
||||
img_code = image_obj.save('checkcode.png')
|
||||
with open("checkcode.png","rb") as file_jpg:
|
||||
f_res = file_jpg.read()
|
||||
ocr = ddddocr.DdddOcr(show_ad=False)
|
||||
res = ocr.classification(f_res)
|
||||
if len(res) != 4:
|
||||
self.driver.find_element(By.XPATH, self.img_path).click() #如果识别验证码不足4位,则重新刷新验证码
|
||||
self.image_code()
|
||||
#time.sleep(0.1)
|
||||
else:
|
||||
self.driver.find_element(By.ID, self.yzm).send_keys(res) #输入验证码
|
||||
#self.driver.find_element(By.LINK_TEXT, '验证码').send_keys(res) #输入验证码
|
||||
#time.sleep(0.1)
|
||||
self.driver.find_element(By.XPATH, self.login).click() #登录按钮
|
||||
def search_host(self):
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="filter-search"]/form/div/div[2]/input').send_keys(search_host) #搜索列表
|
||||
print(search_host)
|
||||
#time.sleep(0.5)
|
||||
self.driver.find_element(By.XPATH, r'//*[@id="filter-search"]/form/div/div[2]/button/i').click() #点击搜索
|
||||
def xshell_auto():#except测试时使用,正常走的是try
|
||||
try:
|
||||
app = Application('uia').connect(title = r'要打开 USM Single Sign-On Plugin 吗?')
|
||||
dig = app[r'要打开 USM Single Sign-On Plugin 吗?'].window(title="打开 USM Single Sign-On Plugin", control_type="Button")
|
||||
except:
|
||||
app = Application('uia').connect(title = r'主机运维 - Google Chrome')#连接浏览器
|
||||
dig = app[r'主机运维 - Google Chrome'] #定位到浏览器页面
|
||||
time.sleep(1.8)
|
||||
dig.wait("visible").click()
|
||||
try:#有时候可能会卡住,导致wait无法点击,此方法兜底
|
||||
time.sleep(1.8)
|
||||
app = Application('uia').connect(title = r'要打开 USM Single Sign-On Plugin 吗?')
|
||||
dig = app[r'要打开 USM Single Sign-On Plugin 吗?']
|
||||
dig.child_window(title="打开 USM Single Sign-On Plugin", control_type="Button").click()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if __name__ == "__main__":
|
||||
Login_Agent(url,username,password).login_run()
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2023/7/29 23:27
|
||||
# @Author : cmk
|
||||
# @File : __init__.py.py
|
||||
# @Email : 15726649712@163.com
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2023/7/28 13:21
|
||||
# @Author : cmk
|
||||
# @File : check_db_host.py
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import random
|
||||
|
||||
now = datetime.datetime.now()
|
||||
date = now.strftime("%Y%m%d")
|
||||
|
||||
os.system('chattr -a /u01/shenjilog/Command_history.log')
|
||||
os.system('mv /u01/shenjilog/Command_history.log /u01/shenjilog/Command_history.log_{}'.format(date))
|
||||
os.system('touch /u01/shenjilog/Command_history.log')
|
||||
os.system('chmod 777 /u01/shenjilog/Command_history.log&&chattr +a /u01/shenjilog/Command_history.log')
|
||||
os.system('find /u01/shenjilog/ -name "Command_history" -mtime +1 -exec rm -rf {} \;')
|
||||
file = '/u01/shenjilog/Command_history.log_{}'.format(date)
|
||||
host = '127.0.0.1'
|
||||
with open(file, 'r') as f:
|
||||
data = f.readlines()
|
||||
for i in range(len(data)):
|
||||
data_list = data[i].split('#')
|
||||
if int(len(data_list)) < 2:
|
||||
continue
|
||||
else:
|
||||
print(data_list)
|
||||
date = data_list[0]
|
||||
user = data_list[1].split(':')[-1]
|
||||
ip = data_list[2].split(':')[-1].split(' ')[0]
|
||||
cmd = data_list[3].split(']')[-1]
|
||||
sql = "insert into check_minirds_host VALUES ('{}','{}','{}','{}','{}')".format(host,date,user,ip,cmd)
|
||||
os.system('mysql -h152.136.143.185 -ucmk -P3306 -pAdmin@123 -Dzhiban -e "{}"'.format(sql))
|
||||
@@ -0,0 +1,7 @@
|
||||
date=`date +"%Y%m%d"`
|
||||
chattr -a /u01/shenjilog/Command_history.log
|
||||
mv /u01/shenjilog/Command_history.log /u01/shenjilog/Command_history.log_$date
|
||||
touch /u01/shenjilog/Command_history.log
|
||||
chmod 777 /u01/shenjilog/Command_history.log
|
||||
chattr +a /u01/shenjilog/Command_history.log
|
||||
find /u01/shenjilog/ -name 'Command_history' -mtime +1 -exec rm -rf {} \;
|
||||
@@ -0,0 +1,3 @@
|
||||
#记录历史命令
|
||||
export HISTORY_FILE="/u01/shenjilog/Command_history.log"
|
||||
export PROMPT_COMMAND='{ date "+%Y-%m-%d %T # USER:$USER # IP:$SSH_CLIENT # $(history 1 | { read x cmd;echo "$cmd"; })";} >>$HISTORY_FILE'
|
||||
@@ -0,0 +1,6 @@
|
||||
# 脚本目录说明
|
||||
|
||||
- check_minirds_bak.py :minirds备份巡检,连续5天没有备份集提示异常
|
||||
- check_minirds_instance_performance.py : minirds性能巡检,cpu,内存,连接数,iops,磁盘
|
||||
- utils: 公共模块,主要存放一些公共模块。
|
||||
- get_db: 获取云平台数据库连接信息
|
||||
@@ -0,0 +1,211 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/10/29 下午12:08
|
||||
# File : check_bakowner_status.py
|
||||
# 脚本作用 : 风险-检查服务状态
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_bakowner_bak')
|
||||
type_list = [
|
||||
{
|
||||
"name": "ftp",
|
||||
"type": 23
|
||||
},
|
||||
{
|
||||
"name": "aurora-cluster",
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"name": "task-dispatcher",
|
||||
"type": 6
|
||||
},
|
||||
{
|
||||
"name": "stat-jobworker",
|
||||
"type": 7
|
||||
},
|
||||
{
|
||||
"name": "stat-jobworker",
|
||||
"type": 59
|
||||
},
|
||||
{
|
||||
"name": "stat-jobworker",
|
||||
"type": 60
|
||||
},
|
||||
{
|
||||
"name": "api",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"name": "redis",
|
||||
"type": 24
|
||||
},
|
||||
{
|
||||
"name": "redis",
|
||||
"type": 61
|
||||
},
|
||||
{
|
||||
"name": "stat-jobschedule",
|
||||
"type": 35
|
||||
},
|
||||
{
|
||||
"name": "bak-master",
|
||||
"type": 37
|
||||
},
|
||||
{
|
||||
"name": "bak-master",
|
||||
"type": 28
|
||||
},
|
||||
{
|
||||
"name": "message-center",
|
||||
"type": 39
|
||||
},
|
||||
{
|
||||
"name": "tengine",
|
||||
"type": 57
|
||||
},
|
||||
{
|
||||
"name": "resmanager",
|
||||
"type": 96
|
||||
},
|
||||
{
|
||||
"name": "check-ins",
|
||||
"type": 101
|
||||
},
|
||||
{
|
||||
"name": "secgroup",
|
||||
"type": 115
|
||||
},
|
||||
{
|
||||
"name": "bifrost",
|
||||
"type": 117
|
||||
},
|
||||
{
|
||||
"name": "bifrost",
|
||||
"type": 118
|
||||
},
|
||||
{
|
||||
"name": "robot",
|
||||
"type": 128
|
||||
},
|
||||
{
|
||||
"name": "dboss",
|
||||
"type": 187
|
||||
},
|
||||
{
|
||||
"name": "pengine-master",
|
||||
"type": 200
|
||||
},
|
||||
{
|
||||
"name": "pengine-mysql",
|
||||
"type": 260
|
||||
},
|
||||
{
|
||||
"name": "pengine-tsdb",
|
||||
"type": 261
|
||||
},
|
||||
{
|
||||
"name": "pengine-mongodb",
|
||||
"type": 3717
|
||||
},
|
||||
{
|
||||
"name": "pengine-redis",
|
||||
"type": 6379
|
||||
},
|
||||
{
|
||||
"name": "bakapi",
|
||||
"type": 222
|
||||
},
|
||||
{
|
||||
"name": "backend_location",
|
||||
"type": 126
|
||||
},
|
||||
{
|
||||
"name": "tender-api",
|
||||
"type": 306
|
||||
},
|
||||
{
|
||||
"name": "name-service",
|
||||
"type": 999
|
||||
}
|
||||
]
|
||||
|
||||
# 获取集群和服务
|
||||
def get_project_clusterlist():
|
||||
'''
|
||||
{
|
||||
u'integrator-B-20220325-2c26': {'services': set([u'minirds-integrator']), 'idc': u'am28'},
|
||||
u'maotai_7u-A-20191123-1ecc': {'services': set([u'minirds-maotai', u'minirds-portal', u'srs-client']), 'idc': u'am779'},
|
||||
u'maotai_7u-B-20220325-2c25': {'services': set([u'minirds-maotai', u'minirds-portal', u'srs-client']), 'idc': u'am28'},
|
||||
u'integrator-A-20191123-1ecd': {'services': set([u'minirds-integrator']), 'idc': u'am779'}
|
||||
}
|
||||
'''
|
||||
url= 'http://127.0.0.1:7070/api/v3/column/m.cluster,m.sr.id,m.idc?m.project=minirds-mt'
|
||||
res = requests.get(url)
|
||||
c_map = {}
|
||||
for c in res.json():
|
||||
if not c.get("m.sr.id") or c['m.sr.id'].startswith("tianji") or c['m.sr.id'].startswith('hids-client'):
|
||||
continue
|
||||
service_name = c['m.sr.id'].split('.')[0]
|
||||
c_map.setdefault(c['m.cluster'], {}).setdefault("idc", c['m.idc'])
|
||||
c_map.setdefault(c['m.cluster'], {}).setdefault("services", set()).add(service_name)
|
||||
return c_map
|
||||
|
||||
# 获取集群服务和服务实际ip
|
||||
def get_service_res_info(cluster_name, service_name):
|
||||
res_map = {}
|
||||
url = 'http://localhost:7070/api/v5/GetClusterSRInfo?cluster=%s&serverrole=%s&attr=service_registration' % (cluster_name, service_name)
|
||||
res = requests.get(url)
|
||||
data = res.json()
|
||||
|
||||
if data and 'data' in data.keys() and 'service_registration' in data['data']:
|
||||
for name, value in json.loads(data['data']['service_registration']).iteritems():
|
||||
if name.endswith("_iplist") and 'iplist' in name:
|
||||
res_map.setdefault(name, value)
|
||||
return res_map
|
||||
|
||||
#
|
||||
def bakowner_status():
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
all_sr_info = {}
|
||||
sql_db = db('dbaas_db')
|
||||
clusterlist = get_project_clusterlist()
|
||||
for cluster, service in clusterlist.items():
|
||||
a = get_service_res_info(cluster, list(service.get("services"))[0])
|
||||
all_sr_info.update(a)
|
||||
for sr in type_list:
|
||||
for sr_info in all_sr_info:
|
||||
if sr.get("name") in sr_info:
|
||||
ip_tmp = all_sr_info.get(sr_info).split(",")
|
||||
ip_list = ['"{}"'.format(ip) for ip in ip_tmp]
|
||||
ip_addr = ",".join(ip_list)
|
||||
sql = "select ip,status from bakowner where type=%s and ip in (%s)" % (sr.get("type"), ip_addr)
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_list = [data.strip().split('\t') for data in datas]
|
||||
for data in data_list:
|
||||
if data[1] == '1':
|
||||
check_state = False
|
||||
print(sr.get('name'),sr.get('type'),data[0],data[1])
|
||||
log.error('\033[31m服务:{},ip地址:{},类型:{},状态:{},异常\033[0m'.format(sr.get('name'),data[0],sr.get('type'),data[1]))
|
||||
err_tip += '服务:{},ip地址:{},类型:{},状态:{}\n'.format(sr.get('name'),data[0],sr.get('type'),data[1])
|
||||
else:
|
||||
log.info('\033[42m服务:{},ip地址:{},类型:{},状态:{},正常\033[0m'.format(sr.get('name'),data[0],sr.get('type'),data[1]))
|
||||
str_separator()
|
||||
return check_state, err_tip
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(bakowner_status())
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午2:28
|
||||
# File : check_minirds_bak.py
|
||||
# 脚本作用 : 检查minirds实例备份是否存在异常:连续5天没有备份的情况
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_minirds_bak')
|
||||
|
||||
#获取实例备份异常
|
||||
def get_bak_data(DB):
|
||||
log.info('开始实例备份异常巡检...........')
|
||||
sql_db = db(DB)
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''select * from m_baknotice_custins'''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.info('开始执行sql命令获取数据.....')
|
||||
data = os.popen(cmd).readlines()
|
||||
check_state = True
|
||||
err_tip = []
|
||||
if len(data) == 0:
|
||||
log.info('平台没有实例超过5天没有备份的')
|
||||
else:
|
||||
check_state = False
|
||||
err_tip = ""
|
||||
for line in data:
|
||||
files = line.strip().split('\t')
|
||||
log.error('实例:{}备份异常,最后一次备份失败时间是{},连续5天没有备份'.format(files[2],files[4]))
|
||||
err_tip += '实例:{}备份异常\n'.format(files[2])
|
||||
log.info('实例备份异常巡检完成,开始分析...........')
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查备份异常
|
||||
main(get_bak_data('dukang_db'))
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/6 下午5:58
|
||||
# File : check_minirds_cluster.py
|
||||
# 脚本作用 : 检查minirds集群信息,判断集群内存分配率小于80%
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_minirds_cluster')
|
||||
'''
|
||||
集群实例全是空的情况下资源使用率报错
|
||||
'''
|
||||
#获取集群信息
|
||||
def get_cluster_name(DB):
|
||||
sql_db = db(DB)
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''
|
||||
select hi.cluster_name,hi.db_type,count(hi.ip) as host_num,sum(hp.cpu_cores-4) as cpu_total,
|
||||
sum(round(hp.mem_size/1024,2)-30) as 'mem_total',sum(round(hp.data_space_total/1024,2)) as 'disk_data_total'
|
||||
from hostinfo hi,host_perf hp where hi.status=1 and hi.id = hp.host_id group by cluster_name
|
||||
'''
|
||||
cmd = '{} -Ne "{}"'.format(sql_db, sql)
|
||||
log.debug('需要执行的sql命令:{}'.format(sql))
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_list = [data.strip().split('\t') for data in datas]
|
||||
log.info('获取集群总量资源,预留cpu4核,内存30G:{}'.format(data_list))
|
||||
return data_list
|
||||
|
||||
#通过集群名称获取计算集群资源
|
||||
def get_cluster_data(DB):
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
cluster_name_lines = get_cluster_name(DB)
|
||||
for cluster in cluster_name_lines:
|
||||
log.info('开始获取{}集群集群资源使用量'.format(cluster[0]))
|
||||
sql = '''
|
||||
select sum(ins_num),sum(cpu_sold_num),round(sum(mem_sold)),round(sum(disk_sold)) from (
|
||||
SELECT COUNT(hi.id) AS ins_num,SUM(ist.cpu_cores) AS cpu_sold_num,SUM(ist.mem_size) / 1024 AS 'mem_sold',
|
||||
SUM(ci.disk_size) / 1024 AS 'disk_sold' FROM instance i,instance_stat ist,cust_instance ci,custins_hostins_rel chr,hostinfo hi WHERE
|
||||
ist.ins_id = i.id AND i.is_deleted = 0 AND ci.is_deleted = 0 AND i.id = chr.hostins_id AND ci.id = chr.custins_id
|
||||
AND i.host_id = hi.id AND hi.cluster_name = '{}' GROUP BY hi.id) t
|
||||
'''.format(cluster[0])
|
||||
sql_db = db(DB)
|
||||
cmd = '{} -Ne "{}"'.format(sql_db, sql)
|
||||
datas = os.popen(cmd).readlines()
|
||||
log.info('开始分析{}集群信息'.format(cluster[0]))
|
||||
data_list = [data.strip().split('\t') for data in datas][0]
|
||||
cluster_data = cluster + data_list
|
||||
mes = '''数据库集群:{},数据库类型:{},集群机器数量:{},集群实例节点数据:{},集群cpu总量:{},集群cpu售卖量:{},集群内存总量:{}G,集群内存售卖量:{}G,集群磁盘总量:{}G,集群磁盘售卖量:{}G
|
||||
'''.format(cluster_data[0],cluster_data[1],cluster_data[2],cluster_data[6],cluster_data[3],cluster_data[7],cluster_data[4],cluster_data[8],cluster_data[5],cluster_data[9])
|
||||
if cluster_data[8] != 'NULL':
|
||||
f_num = round(float(cluster_data[8]) / float(cluster_data[4]), 2)
|
||||
if f_num > 0.8:
|
||||
check_state = False
|
||||
log.info(mes)
|
||||
log.error("集群资源紧张,当前分配率是{},内存分配率大于80%".format(f_num))
|
||||
err_tip += '集群:{},当前分配率是{},内存使用率大于80%\n'.format(cluster_data[0], f_num)
|
||||
else:
|
||||
log.info(mes)
|
||||
else:
|
||||
log.info('集群:{},当前机器上面没有实例'.format(cluster[0]))
|
||||
str_separator()
|
||||
return check_state, err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
if __name__ == '__main__':
|
||||
main(get_cluster_data('dbaas_db'))
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/6 下午6:01
|
||||
# File : check_minirds_host.py
|
||||
# 脚本作用 : 检查minirds物理机分配情况,物理机内存分配率小于80%,磁盘不允许超卖
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_minirds_host')
|
||||
def get_hosts_data(DB):
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
sql_db = db(DB)
|
||||
'''
|
||||
cluster_name:集群,db_type:数据库类型,
|
||||
isolate_host:主机支持数据库类型(0 查共享1 查独占2 查独享3 查空机器),total:总量,sold:售卖量
|
||||
instance:主机实例列表,instance_stat:实例状态,cust_instance:实例列表
|
||||
custins_hostins_rel:用户实例,与主机实例 关系表 (一般1:2)
|
||||
hostinfo:主机列表,host_perf:主机资源和性能报表
|
||||
'''
|
||||
sql = '''
|
||||
select hi.cluster_name,hi.db_type,hi.ip,hi.host_name,i.isolate_host,count(hi.id) as ins_num,
|
||||
(hp.cpu_cores-4) as cpu_total,sum(ist.cpu_cores) as cpu_sold,
|
||||
(round(hp.mem_size/1024,2) - 30) as 'mem_total',round(sum(ist.mem_size)/1024,2) as 'mem_sold',
|
||||
round(hp.data_space_total/1024,2) as 'disk_data_total',round(sum(ci.disk_size)/1024,2) as 'disk_sold'
|
||||
from instance i,instance_stat ist,cust_instance ci,custins_hostins_rel chr,hostinfo hi,host_perf hp
|
||||
where ist.ins_id=i.id and i.is_deleted=0 and ci.is_deleted=0 and i.id =chr.hostins_id
|
||||
and ci.id=chr.custins_id and i.host_id =hi.id and hi.id=hp.host_id group by hi.id
|
||||
'''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.info('开始获取机器资源数据......')
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_lists = [data.strip().split('\t') for data in datas]
|
||||
for data_list in data_lists:
|
||||
#cpu售卖率
|
||||
cpu = round(float(data_list[7])/float(data_list[6]),2)
|
||||
#内存售卖率
|
||||
mem = round(float(data_list[9])/float(data_list[8]),2)
|
||||
#磁盘售卖率
|
||||
disk = round(float(data_list[11])/float(data_list[10]),2)
|
||||
if data_list[4] == '2':
|
||||
if cpu >0.8:
|
||||
log.error('主机:{}是独享型机器,cpu分配率是{}%,大于资源总量的80%'.format(data_list[3],cpu*100))
|
||||
err_tip += '主机:{},cpu分配率大于80%\n'.format(data_list[3])
|
||||
if mem > 0.8:
|
||||
log.error('主机:{}是独享型机器,内存分配率是{}%,大于资源总量的80%'.format(data_list[3],mem*100))
|
||||
err_tip += '主机:{},内存分配率大于80%\n'.format(data_list[3])
|
||||
if disk > 1:
|
||||
log.error('主机:{}是独享型机器,磁盘分配率是{},超卖了'.format(data_list[3],disk*100))
|
||||
err_tip += '主机:{},磁盘超卖了\n'.format(data_list[3])
|
||||
elif data_list[4] == '0':
|
||||
if mem > 0.8:
|
||||
log.error('主机:{}是共享型机器,内存分配率是{}%,大于资源总量的80%'.format(data_list[3],mem*100))
|
||||
err_tip += '主机:{},内存分配率大于80%\n'.format(data_list[3])
|
||||
if disk > 1:
|
||||
log.error('主机:{}是共享型机器,磁盘分配率是{}%,超卖了'.format(data_list[3],disk*100))
|
||||
err_tip += '主机:{},磁盘超卖了\n'.format(data_list[3])
|
||||
str_separator()
|
||||
if len(err_tip):
|
||||
check_state = False
|
||||
return check_state,err_tip
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(get_hosts_data('dbaas_db'))
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/27 下午3:07
|
||||
# File : check_minirds_ins_dr.py
|
||||
# 脚本作用 : 检查环境是否是容灾环境,数据库是否符合容灾逻辑(主备实例在不通的机房)
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_ins_dr')
|
||||
|
||||
#检查容灾环境主备实例是否在同一机房
|
||||
def get_bak_data(DB):
|
||||
sql_db = db(DB)
|
||||
sql = '''select ins_name,master_site_name from dr_service_instance_check where single_site = 1 and custins_id in (select id from cust_instance where cluster_name in (select clustername from clusters where is_multi_site = 1));
|
||||
'''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.info('开始执行sql命令获取数据.....')
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
data = os.popen(cmd).readlines()
|
||||
if len(data) >0:
|
||||
check_state = False
|
||||
for lines in data:
|
||||
line = lines.strip().split('\t')
|
||||
log.debug('{}:实例不符合容灾逻辑,主备实例都在{}机房'.format(line[0],line[1]))
|
||||
err_tip += '{}实例主备节点都在{}机房\n'.format(line[0],line[1])
|
||||
else:
|
||||
log.info('环境里面的容灾实例主备节点符合容灾要求')
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查备份异常
|
||||
main(get_bak_data('dbaas_db'))
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/21 下午4:05
|
||||
# File : check_minirds_instance_performance.py
|
||||
# 脚本作用 : minirds实例性能巡检
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
import os
|
||||
from get_db import main
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_minirds_instance_performance')
|
||||
|
||||
|
||||
#获取数据
|
||||
def get_minirds_data(file):
|
||||
sql = '''select ins_name,cpu_ratio,mem_ratio,iops_ratio,conn_ratio,slave_lag,disk_ratio from instance_list_page'''
|
||||
log.info("需要执行的sql:{}".format(sql))
|
||||
sql_db = main('dukang_db')
|
||||
log.info("开始获取数据....")
|
||||
cmd = "{} -Ne '{}' >{}".format(sql_db, sql,file)
|
||||
log.info("数据获取完成,保存到当前目录{}文件中".format(file))
|
||||
os.system(cmd)
|
||||
cpu_list = []
|
||||
mem_list = []
|
||||
iops_list = []
|
||||
conn_list = []
|
||||
slave_list = []
|
||||
disk_list = []
|
||||
with open(file,'r') as f:
|
||||
lines = f.readlines()
|
||||
log.info('开始分析数据......')
|
||||
for line in lines:
|
||||
pages = line.strip().split()
|
||||
if float(pages[1]) > float(80):
|
||||
cpu_list.append({pages[0]:pages[1]})
|
||||
if float(pages[2]) > float(80):
|
||||
mem_list.append({pages[0]:pages[2]})
|
||||
if float(pages[3]) > float(90):
|
||||
iops_list.append({pages[0]:pages[3]})
|
||||
if float(pages[4]) > float(80):
|
||||
conn_list.append({pages[0]:pages[4]})
|
||||
if float(pages[5]) > float(100):
|
||||
slave_list.append({pages[0]:pages[5]})
|
||||
if float(pages[6]) > float(100):
|
||||
disk_list.append({pages[0]:pages[6]})
|
||||
data = {
|
||||
'cpu':cpu_list,
|
||||
'mem':mem_list,
|
||||
'iops':iops_list,
|
||||
'conn':conn_list,
|
||||
'slave':slave_list,
|
||||
'disk':disk_list
|
||||
}
|
||||
str_separator()
|
||||
return data
|
||||
|
||||
#判断列表长度,确认巡检结果
|
||||
def return_data():
|
||||
data = get_minirds_data('check_minirds.txt')
|
||||
for i in data:
|
||||
if len(data.get(i)) == 0:
|
||||
print('minirds性能巡检{}通过'.format(i))
|
||||
json_print(success_msg())
|
||||
else:
|
||||
mes = 'minirds性能巡检{}不通过,异常实例和当前的性能数据如下:{}'.format(i,data.get(i))
|
||||
json_print(error_msg(mes))
|
||||
str_separator()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
return_data()
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/6 下午5:55
|
||||
# File : check_minirds_task.py
|
||||
# 脚本作用 : 检查minirds是否存在中断任务
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
|
||||
log = logger('check_rds')
|
||||
#获取rds任务运行失败的数据
|
||||
def get_task_data(DB):
|
||||
sql_db = db(DB)
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''select id,target_id,task_begin,task_end,task_key,action from task_queue where status = '8' '''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.debug('需要执行的sql命令:{}'.format(sql))
|
||||
log.info('开始执行sql命令获取数据.....')
|
||||
data = os.popen(cmd).readlines()
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
if len(data) == 0:
|
||||
log.info('当前平台没有中断任务')
|
||||
else:
|
||||
check_state = False
|
||||
for lines in data:
|
||||
line = lines.strip().split('\t')
|
||||
log.error('平台存在中断任务,中断任务id:{},实例id:{},任务开始时间:{},任务中断时间:{},任务类型:{},任务名称:{}'.format(line[0],line[1],line[2],line[3],line[4],line[5]))
|
||||
err_tip += '平台存在中断任务,实例id:{},任务类型:{},任务名称:{}'.format(line[1],line[4],line[5])
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查任务异常
|
||||
main(get_task_data('dbaas_db'))
|
||||
@@ -0,0 +1,231 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午3:02
|
||||
# File : get_db.py
|
||||
# 脚本作用 : 获取数据库连接信息
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import sys
|
||||
import json
|
||||
import yaml
|
||||
import base64
|
||||
import traceback
|
||||
import subprocess
|
||||
|
||||
|
||||
minirds_db_list = ["bak_db", "dbaas_db", "drds_metadata_db", "dukang_db", "perf_db", "rds_perf_db", "robot_db"]
|
||||
|
||||
|
||||
def exec_client(cmd, ip=None):
|
||||
if ip:
|
||||
cmd = """ssh -t {} {} """.format(ip, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
code, out, err = p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
out.replace("Connection to {} closed.".format(ip), "") # 去除退出提示信息
|
||||
if code != 0:
|
||||
raise ValueError(str(err))
|
||||
return out.strip()
|
||||
|
||||
|
||||
def fuzzy_search_dict(key, data):
|
||||
""" 模糊搜索字典值 """
|
||||
return [d for d in data if any(key in v for v in d.values())]
|
||||
|
||||
|
||||
def base64_to_str(bs64):
|
||||
return base64.b64decode(bs64)
|
||||
|
||||
|
||||
def search_minirds(db_name, data):
|
||||
_data = json.loads(data)
|
||||
_db_name = db_name.replace("_db", "")
|
||||
original_db_name = db_name
|
||||
db_host = ""
|
||||
db_port = ""
|
||||
db_password = ""
|
||||
db_user = ""
|
||||
db_name = ""
|
||||
instance_name = ""
|
||||
if original_db_name == "drds_metadata_db":
|
||||
db_host = _data["db_drds_db_host"]
|
||||
db_port = _data["db_drds_db_port"]
|
||||
db_password = _data["db_drds_db_password"]
|
||||
db_user = _data["db_drds_db_user"]
|
||||
db_name = _data["db_drds_db_name"]
|
||||
elif original_db_name == "rds_perf_db":
|
||||
db_host = _data["db_rdsperf_db_host"]
|
||||
db_port = _data["db_rdsperf_db_port"]
|
||||
db_password = _data["db_rdsperf_db_password"]
|
||||
db_user = _data["db_rdsperf_db_user"]
|
||||
db_name = _data["db_rdsperf_db_name"]
|
||||
else:
|
||||
for key, value in _data.items():
|
||||
if "db_{}_db_host".format(_db_name) == key:
|
||||
db_host = value
|
||||
elif "db_{}_db_port".format(_db_name) == key:
|
||||
db_port = value
|
||||
elif "db_{}_db_password".format(_db_name) == key:
|
||||
db_password = value
|
||||
elif "db_{}_db_user".format(_db_name) == key:
|
||||
db_user = value
|
||||
elif "db_{}_db_name".format(_db_name) == key:
|
||||
db_name = value
|
||||
elif "db_{}_instance_name".format(_db_name) == key:
|
||||
instance_name = value
|
||||
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_tianji(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["minirds.host"]
|
||||
db_port = _data["minirds.port"]
|
||||
db_password = _data["minirds.password"]
|
||||
db_user = _data["minirds.username"]
|
||||
db_name = _data["minirds.database"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_ark(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["db.aiops.host"]
|
||||
db_port = _data["db.aiops.port"]
|
||||
db_password = _data["db.aiops.password"]
|
||||
db_user = _data["db.aiops.user"]
|
||||
db_name = _data["db.aiops.name"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def print_db_connect(data):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
sql_str = "mysql -h{db_host} -u{db_user} -p{db_port} -P{db_passwd} -D{db_name}".format(
|
||||
db_host=data["db_host"],
|
||||
db_user=data["db_user"],
|
||||
db_port=data["db_passwd"],
|
||||
db_passwd=data["db_port"],
|
||||
db_name=data["db_name"]
|
||||
)
|
||||
#print ("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
except Exception as error:
|
||||
msg = traceback.format_exc()
|
||||
print(msg)
|
||||
|
||||
|
||||
def db_resource_api():
|
||||
api = "http://localhost:7070/api/v3/column/service.res.result,service.res.serverrole?service.res.type=db"
|
||||
cmd = "curl -s {}".format(api)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = json.loads(out)
|
||||
return data
|
||||
|
||||
|
||||
def get_minirds_db_resource(db_name):
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=minirds-maotai"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_minirds(db_name, register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_tianji_db_resource():
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=tianjimon"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_tianji(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_ark_db_resource():
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=ark-aiops-datacollector"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_ark(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_paas_db_resource(db_name):
|
||||
result = []
|
||||
if "_" in db_name:
|
||||
db_name = db_name.replace("_", "-")
|
||||
cmd = "kubectl get secret -A |grep minirds |grep {} |awk '{{print $1,$2}}' ".format(db_name)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = out.split("\n")
|
||||
if len(data) < 1:
|
||||
# print("没有找到对应的paas侧元数据库,请确认是否输入正确")
|
||||
exit(1)
|
||||
for i in data:
|
||||
_data = i.split()
|
||||
result.append({"namespace": _data[0], "name": _data[1]})
|
||||
return result
|
||||
|
||||
|
||||
def get_paas_db_info(name):
|
||||
paas_db_resource = get_paas_db_resource(name)
|
||||
for paas in paas_db_resource:
|
||||
cmd = "kubectl get secret {} -n {} -oyaml".format(paas["name"], paas["namespace"])
|
||||
out = exec_client(cmd=cmd)
|
||||
data = yaml.safe_load(out)
|
||||
db_host = base64_to_str(data["data"]["db_host"])
|
||||
db_name = base64_to_str(data["data"]["db_name"])
|
||||
db_password = base64_to_str(data["data"]["db_password"])
|
||||
db_port = base64_to_str(data["data"]["db_port"])
|
||||
db_user = base64_to_str(data["data"]["db_user"])
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n', ' ')
|
||||
|
||||
|
||||
def new_db_resource():
|
||||
db_resource = []
|
||||
resource = db_resource_api()
|
||||
for db in resource:
|
||||
db_res = json.loads(db["service.res.result"])
|
||||
db_data = {
|
||||
"db_user": db_res["db_user"],
|
||||
"db_host": db_res["db_host"],
|
||||
"db_port": db_res["db_port"],
|
||||
"db_name": db_res["db_name"],
|
||||
"db_passwd": db_res["db_password"]
|
||||
}
|
||||
db_resource.append({"db_res": json.dumps(db_data)})
|
||||
return db_resource
|
||||
|
||||
|
||||
def main(db_name):
|
||||
db_info = ""
|
||||
if db_name in minirds_db_list:
|
||||
db_info = get_minirds_db_resource(db_name)
|
||||
return db_info
|
||||
if db_name == "tianjimon0":
|
||||
db_info = get_tianji_db_resource()
|
||||
return db_info
|
||||
if db_name == "aiops":
|
||||
db_info = get_ark_db_resource()
|
||||
return db_info
|
||||
db_data = fuzzy_search_dict(db_name, new_db_resource())
|
||||
|
||||
if len(db_data) < 1 and not db_info:
|
||||
db_info = get_paas_db_info(db_name)
|
||||
return db_info
|
||||
for db in db_data:
|
||||
|
||||
db_info = print_db_connect(json.loads(db["db_res"]))
|
||||
return db_info
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# main()
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/10/29 下午4:41
|
||||
# File : 00test.py
|
||||
# 脚本作用 :
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
# @Project: inspectioncode
|
||||
# @Time: 2024/7/29 16:48
|
||||
# @File: utils.py
|
||||
# @Describe:
|
||||
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def exec_client(cmd, hostname=None, log=None):
|
||||
if hostname:
|
||||
cmd = """ssh -t {} {} """.format(hostname, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
code, out, err = p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
log.debug("cmd: [{}], out: [{}], err: [{}], code: {}".format(cmd, out.strip(), err, code))
|
||||
# if code != 0:
|
||||
# logging.error("[error: {}, out: {}, code: {}]".format(err, out, code))
|
||||
# exit(code)
|
||||
return out.strip(), err, code
|
||||
|
||||
|
||||
def logger(name):
|
||||
"""
|
||||
所有场景,公共日志入口
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
# 根据场景,区分日志
|
||||
|
||||
log = logging.getLogger(name)
|
||||
log.setLevel(logging.DEBUG)
|
||||
fmt_str = '%(asctime)s [%(levelname)2s] [%(filename)s:%(lineno)d:%(funcName)s] %(message)s'
|
||||
fmt = logging.Formatter(fmt_str)
|
||||
stream_h = logging.StreamHandler()
|
||||
stream_h.setFormatter(fmt)
|
||||
stream_h.setLevel(logging.DEBUG)
|
||||
log.addHandler(stream_h)
|
||||
return log
|
||||
|
||||
|
||||
def success_msg():
|
||||
return {
|
||||
"message": "success",
|
||||
"details": {
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"code": "200",
|
||||
"message": "巡检通过"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def error_msg(msg):
|
||||
return {
|
||||
"message": "failed",
|
||||
"details": {
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"code": "500",
|
||||
"message": msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def str_separator():
|
||||
print("=" * 30)
|
||||
|
||||
|
||||
def json_print(data):
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
@@ -0,0 +1,48 @@
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/check_rds_bak.py
|
||||
脚本作用: 检查rds实例备份是否存在异常:连续5天没有备份的情况
|
||||
==============================
|
||||
{
|
||||
"message": "failed",
|
||||
"details": {
|
||||
"timestamp": "2025-08-01 09:38:41",
|
||||
"message": "实例:rm-9urk7o461mu83350l备份异常\n实例:rm-9ur951u1ilsy3wqsp备份异常\n实例:rm-9urv0jm29a6ex5u62备份异常\n实例:rm-9ur7164re689awq52备份异常\n实例:rm-9ur95td400406x134备份异常\n实例:rm-9ur9u77v4i73375z2备份异常\n实例:rm-9ure9279601942823备份异常\n实例:rm-9ur0r6kxctwhgk6fp备份异常\n实例:rm-9ur0d3rj7504f2j1p备份异常\n实例:rm-9ur5s851960k552xy备份异常\n实例:rm-9ur4ip58r0f263u4u备份异常\n实例:rm-9ur61h23wazm78l62备份异常\n实例:rm-9urb5o4u4n93mn3b9备份异常\n实例:rm-9ur5y9ep1l65k7jsk备份异常\n实例:rm-9ur3dq9vq0620j31s备份异常\n",
|
||||
"code": "500"
|
||||
}
|
||||
}
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/check_rds_cluster.py
|
||||
脚本作用: 获取rds集群信息,判断集群内存分配率小于80%
|
||||
==============================
|
||||
{
|
||||
"message": "failed",
|
||||
"details": {
|
||||
"timestamp": "2025-08-01 09:38:46",
|
||||
"message": "集群:cluster-analyticdb30-xk3r8d,当前分配率是0.91,内存使用率大于80%\n集群:cluster-maxscale-xi4rz7,当前分配率是0.89,内存使用率大于80%\n",
|
||||
"code": "500"
|
||||
}
|
||||
}
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/check_rds_host.py
|
||||
脚本作用: 检查rds物理机分配情况,物理机内存分配率小于80%,磁盘不允许超卖
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/check_rds_ins_disk.py
|
||||
脚本作用: 检查数据库实例磁盘大小,磁盘使用量小于总量的80%
|
||||
==============================
|
||||
{
|
||||
"message": "failed",
|
||||
"details": {
|
||||
"timestamp": "2025-08-01 09:38:47",
|
||||
"message": "实例id:rm-9ur53114w79grgtkh,实例磁盘使用率80.03\n实例id:rm-9urgnbdeu8og71f2q,实例磁盘使用率80.17\n实例id:rr-9uru3o52w7yrfpbs5,实例磁盘使用率80.36\n实例id:rr-9ure45hk1v1e0d869,实例磁盘使用率81.32\n实例id:rm-9ur46gxx4fs0frc4w,实例磁盘使用率81.70\n实例id:rr-9ur6l3a5kyjhr0qs1,实例磁盘使用率81.86\n实例id:rm-9urb5o4u4n93mn3b9,实例磁盘使用率82.00\n实例id:rr-9urql03m7303yl3u7,实例磁盘使用率82.41\n实例id:rr-9urmm8w58li62sziu,实例磁盘使用率82.71\n实例id:rr-9ur97z6110cczv7o9,实例磁盘使用率82.74\n实例id:rm-9urv6wp8t8i53gezl,实例磁盘使用率82.86\n实例id:rm-9urw0zfa4v41v5if5,实例磁盘使用率82.89\n实例id:rm-9ur1687t7k7789ehj,实例磁盘使用率83.18\n实例id:rm-9urcm2w4l6r9ereqk,实例磁盘使用率83.63\n实例id:rm-9ur04d7yl13e7imhs,实例磁盘使用率83.68\n实例id:rm-9ur9695u1f45i9z0p,实例磁盘使用率83.98\n实例id:rm-9uru5m57vuev517z4,实例磁盘使用率84.04\n实例id:rm-9urqxb52u884s1uyq,实例磁盘使用率84.09\n实例id:rm-9urkm7h98580l7u7k,实例磁盘使用率84.12\n实例id:rm-9ur5y9ep1l65k7jsk,实例磁盘使用率84.45\n实例id:rm-9urbjw4yz324k5l3q,实例磁盘使用率84.46\n实例id:rm-9urqi5dt5h6876u2u,实例磁盘使用率85.07\n实例id:rm-9urji72eo21hr8rb1,实例磁盘使用率85.35\n实例id:rm-9urpb726e6v1gpk9k,实例磁盘使用率85.59\n实例id:rm-9urrgbe12kp6w1d8w,实例磁盘使用率86.82\n实例id:rm-9urrau77a8fwd77vv,实例磁盘使用率87.07\n实例id:rm-9url7zi3nswd8gk2m,实例磁盘使用率88.12\n实例id:rm-9ur888m949y09x935,实例磁盘使用率88.17\n实例id:rm-9ur4l1hktqen8wm76,实例磁盘使用率89.90\n实例id:rm-9ur53guln849ny2z4,实例磁盘使用率89.99\n实例id:rm-9ur386yw8b61ri6ez,实例磁盘使用率90.17\n实例id:rm-9urye4yz7t83as84p,实例磁盘使用率91.96\n实例id:rm-9ury2i0da2m13277y,实例磁盘使用率93.83\n实例id:rm-9urrgelzqxzhr57pe,实例磁盘使用率93.95\n实例id:rm-9ur9x3h625u5a0efr,实例磁盘使用率95.22\n实例id:rm-9ur5s851960k552xy,实例磁盘使用率96.04\n实例id:rm-9ur3316f4hyy20u4s,实例磁盘使用率97.06\n实例id:rm-9ur17h00iy41x2vyb,实例磁盘使用率102.02\n实例id:rm-9urtebuzro7abcwgn,实例磁盘使用率102.36\n",
|
||||
"code": "500"
|
||||
}
|
||||
}
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/check_rds_task.py
|
||||
脚本作用: 检查rds是否存在中断任务
|
||||
==============================
|
||||
{
|
||||
"message": "success",
|
||||
"details": {
|
||||
"timestamp": "2025-08-01 09:38:49",
|
||||
"message": "巡检通过",
|
||||
"code": "200"
|
||||
}
|
||||
}
|
||||
脚本路径: /home/mysql/backup/data/cmk/work/cmk/work_python/rds/utils.py
|
||||
No script description found in /home/mysql/backup/data/cmk/work/cmk/work_python/rds/utils.py.
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午2:59
|
||||
# File : check_rds_bak.py
|
||||
# 脚本作用 : 检查rds实例备份是否存在异常:连续5天没有备份的情况
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_rds_bak')
|
||||
|
||||
#获取实例备份异常
|
||||
def get_bak_data():
|
||||
log.info('开始实例备份异常巡检...........')
|
||||
sql_db = db('dukang')
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''select * from m_baknotice_custins'''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.debug('需要执行的sql命令:{}'.format(sql))
|
||||
log.info('开始执行sql命令获取数据.....')
|
||||
data = os.popen(cmd).readlines()
|
||||
check_state = True
|
||||
err_tip = []
|
||||
if len(data) == 0:
|
||||
log.info('平台没有实例超过5天没有备份的')
|
||||
else:
|
||||
check_state = False
|
||||
err_tip = ""
|
||||
for line in data:
|
||||
files = line.strip().split('\t')
|
||||
log.error('实例:{}备份异常,最后一次备份失败时间是{},连续5天没有备份'.format(files[2],files[4]))
|
||||
err_tip += '实例:{}备份异常\n'.format(files[2])
|
||||
log.info('实例备份异常巡检完成,开始分析...........')
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查备份异常
|
||||
main(get_bak_data())
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/3 上午10:39
|
||||
# File : check_rds_cluster.py
|
||||
# 脚本作用 : 获取rds集群信息,判断集群内存分配率小于80%
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_rds_cluster')
|
||||
|
||||
#获取集群信息
|
||||
def get_cluster_name(DB):
|
||||
sql_db = db(DB)
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''
|
||||
select hi.cluster_name,hi.db_type,count(hi.ip) as host_num,sum(hp.cpu_cores-4) as cpu_total,
|
||||
sum(round(hp.mem_size/1024,2)-30) as 'mem_total',sum(round(hp.data_space_total/1024,2)) as 'disk_data_total'
|
||||
from hostinfo hi,host_perf hp where hi.status=1 and hi.id = hp.host_id group by cluster_name
|
||||
'''
|
||||
cmd = '{} -Ne "{}"'.format(sql_db, sql)
|
||||
log.debug('需要执行的sql命令:{}'.format(sql))
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_list = [data.strip().split('\t') for data in datas]
|
||||
log.info('获取集群总量资源,预留cpu4核,内存30G:{}'.format(data_list))
|
||||
return data_list
|
||||
|
||||
#通过集群名称获取计算集群资源
|
||||
def get_cluster_data(DB):
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
cluster_name_lines = get_cluster_name(DB)
|
||||
for cluster in cluster_name_lines:
|
||||
log.info('开始获取{}集群集群资源使用量'.format(cluster[0]))
|
||||
sql = '''
|
||||
select sum(ins_num),sum(cpu_sold_num),round(sum(mem_sold)),round(sum(disk_sold)) from (
|
||||
SELECT COUNT(hi.id) AS ins_num,SUM(ist.cpu_cores) AS cpu_sold_num,SUM(ist.mem_size) / 1024 AS 'mem_sold',
|
||||
SUM(ci.disk_size) / 1024 AS 'disk_sold' FROM instance i,instance_stat ist,cust_instance ci,custins_hostins_rel chr,hostinfo hi WHERE
|
||||
ist.ins_id = i.id AND i.is_deleted = 0 AND ci.is_deleted = 0 AND i.id = chr.hostins_id AND ci.id = chr.custins_id
|
||||
AND i.host_id = hi.id AND hi.cluster_name = '{}' GROUP BY hi.id) t
|
||||
'''.format(cluster[0])
|
||||
sql_db = db(DB)
|
||||
cmd = '{} -Ne "{}"'.format(sql_db, sql)
|
||||
datas = os.popen(cmd).readlines()
|
||||
log.info('开始分析{}集群信息'.format(cluster[0]))
|
||||
data_list = [data.strip().split('\t') for data in datas][0]
|
||||
cluster_data = cluster + data_list
|
||||
mes = '''数据库集群:{},数据库类型:{},集群机器数量:{},集群实例节点数据:{},集群cpu总量:{},集群cpu售卖量:{},集群内存总量:{}G,集群内存售卖量:{}G,集群磁盘总量:{}G,集群磁盘售卖量:{}G
|
||||
'''.format(cluster_data[0],cluster_data[1],cluster_data[2],cluster_data[6],cluster_data[3],cluster_data[7],cluster_data[4],cluster_data[8],cluster_data[5],cluster_data[9])
|
||||
|
||||
if cluster_data[8] != 'NULL':
|
||||
f_num = round(float(cluster_data[8]) / float(cluster_data[4]), 2)
|
||||
if f_num > 0.8:
|
||||
check_state = False
|
||||
log.info(mes)
|
||||
log.error("集群资源紧张,当前分配率是{},内存分配率大于80%".format(f_num))
|
||||
err_tip += '集群:{},当前分配率是{},内存使用率大于80%\n'.format(cluster_data[0], f_num)
|
||||
else:
|
||||
log.info(mes)
|
||||
str_separator()
|
||||
return check_state, err_tip
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
if __name__ == '__main__':
|
||||
main(get_cluster_data('dbaas'))
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/4 下午2:43
|
||||
# File : check_rds_host.py
|
||||
# 脚本作用 : 检查rds物理机分配情况,物理机内存分配率小于80%,磁盘不允许超卖
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_rds_host')
|
||||
|
||||
def get_hosts_data(DB):
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
sql_db = db(DB)
|
||||
'''
|
||||
cluster_name:集群,db_type:数据库类型,
|
||||
isolate_host:主机支持数据库类型(0 查共享1 查独占2 查独享3 查空机器),total:总量,sold:售卖量
|
||||
instance:主机实例列表,instance_stat:实例状态,cust_instance:实例列表
|
||||
custins_hostins_rel:用户实例,与主机实例 关系表 (一般1:2)
|
||||
hostinfo:主机列表,host_perf:主机资源和性能报表
|
||||
'''
|
||||
sql = '''
|
||||
select hi.cluster_name,hi.db_type,hi.ip,hi.host_name,i.isolate_host,count(hi.id) as ins_num,
|
||||
(hp.cpu_cores-4) as cpu_total,sum(ist.cpu_cores) as cpu_sold,
|
||||
(round(hp.mem_size/1024,2) - 30) as 'mem_total',round(sum(ist.mem_size)/1024,2) as 'mem_sold',
|
||||
round(hp.data_space_total/1024,2) as 'disk_data_total',round(sum(ci.disk_size)/1024,2) as 'disk_sold'
|
||||
from instance i,instance_stat ist,cust_instance ci,custins_hostins_rel chr,hostinfo hi,host_perf hp
|
||||
where ist.ins_id=i.id and i.is_deleted=0 and ci.is_deleted=0 and i.id =chr.hostins_id
|
||||
and ci.id=chr.custins_id and i.host_id =hi.id and hi.id=hp.host_id group by hi.id
|
||||
'''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.info('开始获取机器资源数据......')
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_lists = [data.strip().split('\t') for data in datas]
|
||||
for data_list in data_lists:
|
||||
#cpu售卖率
|
||||
cpu = round(float(data_list[7])/float(data_list[6]),2)
|
||||
#内存售卖率
|
||||
mem = round(float(data_list[9])/float(data_list[8]),2)
|
||||
#磁盘售卖率
|
||||
disk = round(float(data_list[11])/float(data_list[10]),2)
|
||||
if data_list[4] == '2':
|
||||
if cpu >0.8:
|
||||
log.error('主机:{}是独享型机器,cpu分配率是{}%,大于资源总量的80%'.format(data_list[3],cpu*100))
|
||||
err_tip += '主机:{},cpu分配率大于80%\n'.format(data_list[3])
|
||||
if mem > 0.8:
|
||||
log.error('主机:{}是独享型机器,内存分配率是{}%,大于资源总量的80%'.format(data_list[3],mem*100))
|
||||
err_tip += '主机:{},内存分配率大于80%\n'.format(data_list[3])
|
||||
if disk > 1:
|
||||
log.error('主机:{}是独享型机器,磁盘分配率是{},超卖了'.format(data_list[3],disk))
|
||||
err_tip += '主机:{},磁盘超卖了\n'.format(data_list[3])
|
||||
elif data_list[4] == '0':
|
||||
if mem > 0.8:
|
||||
log.error('主机:{}是共享型机器,内存分配率是{}%,大于资源总量的80%'.format(data_list[3],mem*100))
|
||||
err_tip += '主机:{},内存分配率大于80%\n'.format(data_list[3])
|
||||
if disk > 1:
|
||||
log.error('主机:{}是共享型机器,磁盘分配率是{}%,超卖了'.format(data_list[3],disk))
|
||||
err_tip += '主机:{},磁盘超卖了\n'.format(data_list[3])
|
||||
str_separator()
|
||||
if len(err_tip):
|
||||
check_state = False
|
||||
return check_state,err_tip
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(get_hosts_data('dbaas'))
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/9/6 上午10:14
|
||||
# File : check_rds_ins_disk.py
|
||||
# 脚本作用 : 检查数据库实例磁盘大小,磁盘使用量小于总量的80%
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
import os
|
||||
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
log = logger('check_rds_ins_disk')
|
||||
|
||||
|
||||
def get_ins_disk_data(DB):
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
sql_db = db(DB)
|
||||
sql = '''select ins_name,disk_ratio from instance_list_page where ins_name not like 'bak%' and db_type='mysql' and disk_ratio >'80';'''
|
||||
cmd = '{} -Ne "{}"'.format(sql_db, sql)
|
||||
log.info('开始获取磁盘使用率大于80%的实例......')
|
||||
datas = os.popen(cmd).readlines()
|
||||
data_lists = [data.strip().split('\t') for data in datas]
|
||||
if len(data_lists) > 0:
|
||||
check_state = False
|
||||
for data_list in data_lists:
|
||||
log.error('实例id:{},实例磁盘使用率{},磁盘使用率大于80%'.format(data_list[0], data_list[1]))
|
||||
err_tip += '实例id:{},实例磁盘使用率{}\n'.format(data_list[0], data_list[1])
|
||||
str_separator()
|
||||
return check_state, err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(get_ins_disk_data('dukang'))
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午2:59
|
||||
# File : check_rds_task.py
|
||||
# 脚本作用 : 检查rds是否存在中断任务
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
|
||||
log = logger('check_rds')
|
||||
#获取rds任务运行失败的数据
|
||||
def get_task_data():
|
||||
sql_db = db('dbaas')
|
||||
log.debug('数据库的连接:{}'.format(sql_db))
|
||||
sql = '''select id,target_id,task_begin,task_end,task_key,action from task_queue where status = '8' '''
|
||||
cmd = "{} -Ne '{}'".format(sql_db, sql)
|
||||
log.debug('需要执行的sql命令:{}'.format(sql))
|
||||
log.info('开始执行sql命令获取数据.....')
|
||||
data = os.popen(cmd).readlines()
|
||||
check_state = True
|
||||
err_tip = ""
|
||||
if len(data) == 0:
|
||||
log.info('当前平台没有中断任务')
|
||||
else:
|
||||
check_state = False
|
||||
for lines in data:
|
||||
line = lines.strip().split('\t')
|
||||
log.error('平台存在中断任务,中断任务id:{},实例id:{},任务开始时间:{},任务中断时间:{},任务类型:{},任务名称:{}'.format(line[0],line[1],line[2],line[3],line[4],line[5]))
|
||||
err_tip += '平台存在中断任务,实例id:{},任务类型:{},任务名称:{}'.format(line[1],line[4],line[5])
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查任务异常
|
||||
main(get_task_data())
|
||||
@@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午3:02
|
||||
# File : get_db.py
|
||||
# 脚本作用 : 获取数据库连接信息
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import sys
|
||||
import json
|
||||
import yaml
|
||||
import base64
|
||||
import traceback
|
||||
import subprocess
|
||||
|
||||
|
||||
minirds_db_list = ["bak_db", "dbaas_db", "drds_metadata_db", "dukang_db", "perf_db", "rds_perf_db", "robot_db"]
|
||||
|
||||
|
||||
def exec_client(cmd, ip=None):
|
||||
if ip:
|
||||
cmd = """ssh -t {} {} """.format(ip, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
code, out, err = p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
out.replace("Connection to {} closed.".format(ip), "") # 去除退出提示信息
|
||||
if code != 0:
|
||||
raise ValueError(str(err))
|
||||
return out.strip()
|
||||
|
||||
|
||||
def fuzzy_search_dict(key, data):
|
||||
""" 模糊搜索字典值 """
|
||||
return [d for d in data if any(key in v for v in d.values())]
|
||||
|
||||
|
||||
def base64_to_str(bs64):
|
||||
return base64.b64decode(bs64)
|
||||
|
||||
|
||||
def search_minirds(db_name, data):
|
||||
_data = json.loads(data)
|
||||
_db_name = db_name.replace("_db", "")
|
||||
original_db_name = db_name
|
||||
db_host = ""
|
||||
db_port = ""
|
||||
db_password = ""
|
||||
db_user = ""
|
||||
db_name = ""
|
||||
instance_name = ""
|
||||
if original_db_name == "drds_metadata_db":
|
||||
db_host = _data["db_drds_db_host"]
|
||||
db_port = _data["db_drds_db_port"]
|
||||
db_password = _data["db_drds_db_password"]
|
||||
db_user = _data["db_drds_db_user"]
|
||||
db_name = _data["db_drds_db_name"]
|
||||
elif original_db_name == "rds_perf_db":
|
||||
db_host = _data["db_rdsperf_db_host"]
|
||||
db_port = _data["db_rdsperf_db_port"]
|
||||
db_password = _data["db_rdsperf_db_password"]
|
||||
db_user = _data["db_rdsperf_db_user"]
|
||||
db_name = _data["db_rdsperf_db_name"]
|
||||
else:
|
||||
for key, value in _data.items():
|
||||
if "db_{}_db_host".format(_db_name) == key:
|
||||
db_host = value
|
||||
elif "db_{}_db_port".format(_db_name) == key:
|
||||
db_port = value
|
||||
elif "db_{}_db_password".format(_db_name) == key:
|
||||
db_password = value
|
||||
elif "db_{}_db_user".format(_db_name) == key:
|
||||
db_user = value
|
||||
elif "db_{}_db_name".format(_db_name) == key:
|
||||
db_name = value
|
||||
elif "db_{}_instance_name".format(_db_name) == key:
|
||||
instance_name = value
|
||||
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_tianji(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["minirds.host"]
|
||||
db_port = _data["minirds.port"]
|
||||
db_password = _data["minirds.password"]
|
||||
db_user = _data["minirds.username"]
|
||||
db_name = _data["minirds.database"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_ark(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["db.aiops.host"]
|
||||
db_port = _data["db.aiops.port"]
|
||||
db_password = _data["db.aiops.password"]
|
||||
db_user = _data["db.aiops.user"]
|
||||
db_name = _data["db.aiops.name"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def print_db_connect(data):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
sql_str = "mysql -h{db_host} -u{db_user} -p{db_port} -P{db_passwd} -D{db_name}".format(
|
||||
db_host=data["db_host"],
|
||||
db_user=data["db_user"],
|
||||
db_port=data["db_passwd"],
|
||||
db_passwd=data["db_port"],
|
||||
db_name=data["db_name"]
|
||||
)
|
||||
#print ("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
except Exception as error:
|
||||
msg = traceback.format_exc()
|
||||
print(msg)
|
||||
|
||||
|
||||
def db_resource_api():
|
||||
'''获取tianji接口上面所有db信息'''
|
||||
api = "http://localhost:7070/api/v3/column/service.res.result,service.res.serverrole?service.res.type=db"
|
||||
cmd = "curl -s {}".format(api)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = json.loads(out)
|
||||
return data
|
||||
|
||||
|
||||
def get_minirds_db_resource(db_name):
|
||||
'''获取minirds源数据库数据'''
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=minirds-maotai"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_minirds(db_name, register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_tianji_db_resource():
|
||||
'''获取tianjimon数据'''
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=tianjimon"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_tianji(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_ark_db_resource():
|
||||
'''获取ark-aiops-datacollector数据库'''
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=ark-aiops-datacollector"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_ark(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_paas_db_resource(db_name):
|
||||
'''获取passsecret服务'''
|
||||
result = []
|
||||
if "_" in db_name:
|
||||
db_name = db_name.replace("_", "-")
|
||||
cmd = "kubectl get secret -A |grep minirds |grep {} |awk '{{print $1,$2}}' ".format(db_name)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = out.split("\n")
|
||||
if len(data) < 1:
|
||||
# print("没有找到对应的paas侧元数据库,请确认是否输入正确")
|
||||
exit(1)
|
||||
for i in data:
|
||||
_data = i.split()
|
||||
result.append({"namespace": _data[0], "name": _data[1]})
|
||||
return result
|
||||
|
||||
|
||||
def get_paas_db_info(name):
|
||||
'''获取pass侧数据库信息'''
|
||||
paas_db_resource = get_paas_db_resource(name)
|
||||
for paas in paas_db_resource:
|
||||
cmd = "kubectl get secret {} -n {} -oyaml".format(paas["name"], paas["namespace"])
|
||||
out = exec_client(cmd=cmd)
|
||||
data = yaml.safe_load(out)
|
||||
db_host = base64_to_str(data["data"]["db_host"])
|
||||
db_name = base64_to_str(data["data"]["db_name"])
|
||||
db_password = base64_to_str(data["data"]["db_password"])
|
||||
db_port = base64_to_str(data["data"]["db_port"])
|
||||
db_user = base64_to_str(data["data"]["db_user"])
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
if name == db_name:
|
||||
return sql_str.replace('\n', ' ')
|
||||
else:
|
||||
print(sql_str)
|
||||
return "没有找到一样的数据库名称,上面可能是你需要的"
|
||||
|
||||
|
||||
def new_db_resource():
|
||||
db_resource = []
|
||||
resource = db_resource_api()
|
||||
for db in resource:
|
||||
db_res = json.loads(db["service.res.result"])
|
||||
db_data = {
|
||||
"db_user": db_res["db_user"],
|
||||
"db_host": db_res["db_host"],
|
||||
"db_port": db_res["db_port"],
|
||||
"db_name": db_res["db_name"],
|
||||
"db_passwd": db_res["db_password"]
|
||||
}
|
||||
db_resource.append({"db_res": json.dumps(db_data)})
|
||||
return db_resource
|
||||
|
||||
|
||||
def main():
|
||||
db_name = sys.argv[1]
|
||||
# def main(db_name):
|
||||
db_info = ""
|
||||
if db_name in minirds_db_list:
|
||||
db_info = get_minirds_db_resource(db_name)
|
||||
return db_info
|
||||
if db_name == "tianjimon0":
|
||||
db_info = get_tianji_db_resource()
|
||||
return db_info
|
||||
if db_name == "aiops":
|
||||
db_info = get_ark_db_resource()
|
||||
return db_info
|
||||
db_data = fuzzy_search_dict(db_name, new_db_resource())
|
||||
|
||||
if len(db_data) < 1 and not db_info:
|
||||
db_info = get_paas_db_info(db_name)
|
||||
return db_info
|
||||
for db in db_data:
|
||||
db_info = print_db_connect(json.loads(db["db_res"]))
|
||||
return db_info
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(main())
|
||||
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午3:02
|
||||
# File : get_db.py
|
||||
# 脚本作用 : 获取数据库连接信息
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import sys
|
||||
import json
|
||||
import yaml
|
||||
import base64
|
||||
import traceback
|
||||
import subprocess
|
||||
|
||||
|
||||
# config = ConfigParser.ConfigParser()
|
||||
# config.read("/apsarapangu/disk2/lei/cron/conf/app.ini")
|
||||
# ops_ip = config.get("sys_config", "ops1_ip")
|
||||
|
||||
minirds_db_list = ["bak_db", "dbaas_db", "drds_metadata_db", "dukang_db", "perf_db", "rds_perf_db", "robot_db"]
|
||||
|
||||
|
||||
def exec_client(cmd, ip=None):
|
||||
if ip:
|
||||
cmd = """ssh -t {} {} """.format(ip, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
code, out, err = p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
out.replace("Connection to {} closed.".format(ip), "") # 去除退出提示信息
|
||||
if code != 0:
|
||||
raise ValueError(str(err))
|
||||
return out.strip()
|
||||
|
||||
|
||||
def fuzzy_search_dict(key, data):
|
||||
""" 模糊搜索字典值 """
|
||||
return [d for d in data if any(key in v for v in d.values())]
|
||||
|
||||
|
||||
def base64_to_str(bs64):
|
||||
return base64.b64decode(bs64)
|
||||
|
||||
|
||||
def search_minirds(db_name, data):
|
||||
_data = json.loads(data)
|
||||
_db_name = db_name.replace("_db", "")
|
||||
original_db_name = db_name
|
||||
db_host = ""
|
||||
db_port = ""
|
||||
db_password = ""
|
||||
db_user = ""
|
||||
db_name = ""
|
||||
instance_name = ""
|
||||
if original_db_name == "drds_metadata_db":
|
||||
db_host = _data["db_drds_db_host"]
|
||||
db_port = _data["db_drds_db_port"]
|
||||
db_password = _data["db_drds_db_password"]
|
||||
db_user = _data["db_drds_db_user"]
|
||||
db_name = _data["db_drds_db_name"]
|
||||
elif original_db_name == "rds_perf_db":
|
||||
db_host = _data["db_rdsperf_db_host"]
|
||||
db_port = _data["db_rdsperf_db_port"]
|
||||
db_password = _data["db_rdsperf_db_password"]
|
||||
db_user = _data["db_rdsperf_db_user"]
|
||||
db_name = _data["db_rdsperf_db_name"]
|
||||
else:
|
||||
for key, value in _data.items():
|
||||
if "db_{}_db_host".format(_db_name) == key:
|
||||
db_host = value
|
||||
elif "db_{}_db_port".format(_db_name) == key:
|
||||
db_port = value
|
||||
elif "db_{}_db_password".format(_db_name) == key:
|
||||
db_password = value
|
||||
elif "db_{}_db_user".format(_db_name) == key:
|
||||
db_user = value
|
||||
elif "db_{}_db_name".format(_db_name) == key:
|
||||
db_name = value
|
||||
elif "db_{}_instance_name".format(_db_name) == key:
|
||||
instance_name = value
|
||||
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_tianji(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["minirds.host"]
|
||||
db_port = _data["minirds.port"]
|
||||
db_password = _data["minirds.password"]
|
||||
db_user = _data["minirds.username"]
|
||||
db_name = _data["minirds.database"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def search_ark(data):
|
||||
_data = json.loads(data)
|
||||
db_host = _data["db.aiops.host"]
|
||||
db_port = _data["db.aiops.port"]
|
||||
db_password = _data["db.aiops.password"]
|
||||
db_user = _data["db.aiops.user"]
|
||||
db_name = _data["db.aiops.name"]
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
|
||||
|
||||
def print_db_connect(data):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
sql_str = "mysql -h{db_host} -u{db_user} -p{db_port} -P{db_passwd} -D{db_name}".format(
|
||||
db_host=data["db_host"],
|
||||
db_user=data["db_user"],
|
||||
db_port=data["db_passwd"],
|
||||
db_passwd=data["db_port"],
|
||||
db_name=data["db_name"]
|
||||
)
|
||||
#print ("{}".format(sql_str))
|
||||
return sql_str.replace('\n',' ')
|
||||
except Exception as error:
|
||||
msg = traceback.format_exc()
|
||||
print(msg)
|
||||
|
||||
|
||||
def db_resource_api():
|
||||
api = "http://localhost:7070/api/v3/column/service.res.result,service.res.serverrole?service.res.type=db"
|
||||
cmd = "curl -s {}".format(api)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = json.loads(out)
|
||||
return data
|
||||
|
||||
|
||||
def get_minirds_db_resource(db_name):
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=minirds-maotai"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_minirds(db_name, register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_tianji_db_resource():
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=tianjimon"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_tianji(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_ark_db_resource():
|
||||
api = "http://localhost:7070/api/v3/column/c.sr.service_registration?c.sr.id=ark-aiops-datacollector"
|
||||
out = exec_client(cmd="curl -s {}".format(api))
|
||||
data = json.loads(out)
|
||||
register_data = data[0]["c.sr.service_registration"]
|
||||
_data = search_ark(register_data)
|
||||
return _data
|
||||
|
||||
|
||||
def get_paas_db_resource(db_name):
|
||||
result = []
|
||||
if "_" in db_name:
|
||||
db_name = db_name.replace("_", "-")
|
||||
cmd = "kubectl get secret -A |grep minirds |grep {} |awk '{{print $1,$2}}' ".format(db_name)
|
||||
out = exec_client(cmd=cmd)
|
||||
data = out.split("\n")
|
||||
if len(data) < 1:
|
||||
# print("没有找到对应的paas侧元数据库,请确认是否输入正确")
|
||||
exit(1)
|
||||
for i in data:
|
||||
_data = i.split()
|
||||
result.append({"namespace": _data[0], "name": _data[1]})
|
||||
return result
|
||||
|
||||
|
||||
def get_paas_db_info(name):
|
||||
paas_db_resource = get_paas_db_resource(name)
|
||||
for paas in paas_db_resource:
|
||||
cmd = "kubectl get secret {} -n {} -oyaml".format(paas["name"], paas["namespace"])
|
||||
out = exec_client(cmd=cmd)
|
||||
data = yaml.safe_load(out)
|
||||
db_host = base64_to_str(data["data"]["db_host"])
|
||||
db_name = base64_to_str(data["data"]["db_name"])
|
||||
db_password = base64_to_str(data["data"]["db_password"])
|
||||
db_port = base64_to_str(data["data"]["db_port"])
|
||||
db_user = base64_to_str(data["data"]["db_user"])
|
||||
sql_str = "mysql -h{} -u{} -P{} -p{} -D{}".format(db_host, db_user, db_port, db_password, db_name)
|
||||
#print("{}".format(sql_str))
|
||||
return sql_str.replace('\n', ' ')
|
||||
|
||||
|
||||
def new_db_resource():
|
||||
db_resource = []
|
||||
resource = db_resource_api()
|
||||
for db in resource:
|
||||
db_res = json.loads(db["service.res.result"])
|
||||
db_data = {
|
||||
"db_user": db_res["db_user"],
|
||||
"db_host": db_res["db_host"],
|
||||
"db_port": db_res["db_port"],
|
||||
"db_name": db_res["db_name"],
|
||||
"db_passwd": db_res["db_password"]
|
||||
}
|
||||
db_resource.append({"db_res": json.dumps(db_data)})
|
||||
return db_resource
|
||||
|
||||
|
||||
# def main():
|
||||
# db_name = sys.argv[1]
|
||||
def main(db_name):
|
||||
db_info = ""
|
||||
if db_name in minirds_db_list:
|
||||
db_info = get_minirds_db_resource(db_name)
|
||||
return db_info
|
||||
if db_name == "tianjimon0":
|
||||
db_info = get_tianji_db_resource()
|
||||
return db_info
|
||||
if db_name == "aiops":
|
||||
db_info = get_ark_db_resource()
|
||||
return db_info
|
||||
db_data = fuzzy_search_dict(db_name, new_db_resource())
|
||||
|
||||
if len(db_data) < 1 and not db_info:
|
||||
db_info = get_paas_db_info(db_name)
|
||||
return db_info
|
||||
for db in db_data:
|
||||
db_info = print_db_connect(json.loads(db["db_res"]))
|
||||
return db_info
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# main()
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------
|
||||
# Time : 2024/8/28 下午2:59
|
||||
# File : RDS_P1_BAK.py
|
||||
# 脚本作用 : 检查rds实例备份是否存在异常:连续5天没有备份的情况
|
||||
# 项目名称 : 阿里云平台
|
||||
# ------------------------------------
|
||||
|
||||
import os
|
||||
from get_db import main as db
|
||||
from utils import logger, success_msg, error_msg, str_separator, json_print
|
||||
|
||||
LOG = logger('check_rds_bak') #日志记录器
|
||||
def get_bak_data():
|
||||
"""
|
||||
获取RDS实例备份异常情况
|
||||
作用: 查询数据库获取RDS实例备份信息,并检查是否存在连续5天无备份的情况。
|
||||
结果格式:
|
||||
(CHECK_STATE,ERR_TIP)
|
||||
结果作用:
|
||||
CHECK_STATE: 定义的bool值,判断是否存在异常
|
||||
ERR_TIP: list,异常实例列表
|
||||
"""
|
||||
LOG.info('开始实例备份异常巡检...........')
|
||||
SQL_DB = db('dukang') #获取数据库连接
|
||||
LOG.debug('数据库的连接:{}'.format(SQL_DB))
|
||||
GET_BAK_SQL = '''select ins_name from m_baknotice_custins'''
|
||||
GET_INS_SQL = '''select ins_name from instance_list_page'''
|
||||
GET_BAK_CMD = "{} -Ne '{}'".format(SQL_DB, GET_BAK_SQL) #需要执行的SQL命令
|
||||
GET_INS_CMD = "{} -Ne '{}'".format(SQL_DB, GET_INS_SQL) #需要执行的SQL命令
|
||||
LOG.debug('需要执行的sql命令:{}'.format(GET_BAK_SQL))
|
||||
LOG.info('开始执行sql命令获取数据.....')
|
||||
BAK_RES = os.popen(GET_BAK_CMD).readlines() #执行SQL命令并读取结果
|
||||
INS_RES = os.popen(GET_INS_CMD).readlines() #执行SQL命令并读取结果
|
||||
RM_INS = [ INS for INS in INS_RES if INS.startswith('rm-')]
|
||||
RESULT = []
|
||||
for LINE in RM_INS:
|
||||
CLEANED_LINE = LINE.strip()
|
||||
CONTENT = {
|
||||
"ins": CLEANED_LINE,
|
||||
"result": "true"
|
||||
}
|
||||
RESULT.append(CONTENT)
|
||||
if BAK_RES:
|
||||
for INS in BAK_RES:
|
||||
INS_NAME = INS.strip()
|
||||
for K in RESULT:
|
||||
if name == k['ins']:
|
||||
k['result'] = 'false'
|
||||
print(RESULT)
|
||||
get_bak_data()
|
||||
"""
|
||||
check_state = True #检查状态,默认为True
|
||||
RDS_BAK_RESULT = [] #定义保存检查结果的列表
|
||||
if len(data) == 0:
|
||||
log.info('平台没有实例超过5天没有备份的')
|
||||
else:
|
||||
check_state = False
|
||||
err_tip = ""
|
||||
for line in data:
|
||||
files = line.strip().split('\t')
|
||||
log.error('实例:{}备份异常,最后一次备份失败时间是{},连续5天没有备份'.format(files[2],files[4]))
|
||||
err_tip += '实例:{}备份异常\n'.format(files[2])
|
||||
log.info('实例备份异常巡检完成,开始分析...........')
|
||||
str_separator()
|
||||
return check_state,err_tip
|
||||
|
||||
|
||||
def main(data):
|
||||
if data[0]:
|
||||
json_print(success_msg())
|
||||
else:
|
||||
json_print(error_msg(data[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#检查备份异常
|
||||
main(get_bak_data())
|
||||
"""
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#****************************************************************#
|
||||
# ScriptName: rds.sh
|
||||
# Author: $SHTERM_REAL_USER@alibaba-inc.com
|
||||
# Create Date: 2024-09-06 16:02
|
||||
# Modify Author: $SHTERM_REAL_USER@alibaba-inc.com
|
||||
# Modify Date: 2024-09-06 16:02
|
||||
# Function:
|
||||
#***************************************************************#
|
||||
|
||||
/home/tops/bin/python check_rds_bak.py
|
||||
/home/tops/bin/python check_rds_cluster.py
|
||||
/home/tops/bin/python check_rds_host.py
|
||||
/home/tops/bin/python check_rds_ins_disk.py
|
||||
/home/tops/bin/python check_rds_task.py
|
||||
@@ -0,0 +1,16 @@
|
||||
formatted_time=$(date +"%Y-%m-%d")
|
||||
log_file="$PWD/check_$formatted_time.log"
|
||||
for file in $PWD/*; do
|
||||
if [ -f "$file" ] && [[ "$file" == *.py ]]; then
|
||||
echo "脚本路径: $file" >> $log_file
|
||||
# 获取文件内容中的'脚本作用'注释并输出,假设注释格式为 '# 脚本作用:描述内容'
|
||||
description=$(grep "^# 脚本作用" "$file" | cut -d ':' -f2-)
|
||||
if [ -n "$description" ]; then
|
||||
echo "脚本作用:$description" >> $log_file
|
||||
else
|
||||
echo "No script description found in $file." >> $log_file
|
||||
fi
|
||||
# 执行 Python 文件
|
||||
/home/tops/bin/python "$file" >>$log_file
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
# @Project: inspectioncode
|
||||
# @Time: 2024/7/29 16:48
|
||||
# @File: utils.py
|
||||
# @Describe:
|
||||
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def exec_client(cmd, hostname=None, log=None):
|
||||
if hostname:
|
||||
cmd = """ssh -t {} {} """.format(hostname, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
code, out, err = p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')
|
||||
log.debug("cmd: [{}], out: [{}], err: [{}], code: {}".format(cmd, out.strip(), err, code))
|
||||
# if code != 0:
|
||||
# logging.error("[error: {}, out: {}, code: {}]".format(err, out, code))
|
||||
# exit(code)
|
||||
return out.strip(), err, code
|
||||
|
||||
|
||||
def logger(name):
|
||||
"""
|
||||
所有场景,公共日志入口
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
# 根据场景,区分日志
|
||||
|
||||
log = logging.getLogger(name)
|
||||
log.setLevel(logging.DEBUG)
|
||||
fmt_str = '%(asctime)s [%(levelname)2s] [%(filename)s:%(lineno)d:%(funcName)s] %(message)s'
|
||||
fmt = logging.Formatter(fmt_str)
|
||||
stream_h = logging.StreamHandler()
|
||||
stream_h.setFormatter(fmt)
|
||||
stream_h.setLevel(logging.DEBUG)
|
||||
log.addHandler(stream_h)
|
||||
return log
|
||||
|
||||
|
||||
def success_msg():
|
||||
return {
|
||||
"message": "success",
|
||||
"details": {
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"code": "200",
|
||||
"message": "巡检通过"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def error_msg(msg):
|
||||
return {
|
||||
"message": "failed",
|
||||
"details": {
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"code": "500",
|
||||
"message": msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def str_separator():
|
||||
print("=" * 30)
|
||||
|
||||
|
||||
def json_print(data):
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/6/27 下午11:05
|
||||
# @Author : cmk
|
||||
# @File : test-v2.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import datetime
|
||||
import concurrent.futures
|
||||
from pathlib import Path
|
||||
#from tools.SMS_PUT import sms
|
||||
from tools.Logger import setup_logger
|
||||
|
||||
|
||||
# ---------------------- 配置配置 ----------------------
|
||||
script_dir = Path(__file__).parent.resolve()
|
||||
log_path = (script_dir / "logs" / "nc_disk.log").resolve()
|
||||
project_list = ['minirds-mt', 'rds', 'drds', 'dts']
|
||||
# 告警阈值配置
|
||||
DISK_THRESHOLD = 80 # 磁盘使用率阈值(%)
|
||||
CPU_USAGE_THRESHOLD = 80 # CPU使用率阈值(%)
|
||||
MEM_USAGE_THRESHOLD = 80 # 内存使用率阈值(%)
|
||||
LOAD_AVG_THRESHOLD = 1.5 # 系统负载阈值(CPU核心数倍数)
|
||||
|
||||
# SSH配置
|
||||
SSH_CONNECT_TIMEOUT = 3 # SSH连接超时时间(秒)
|
||||
SSH_RETRIES = 3 # SSH连接重试次数
|
||||
SSH_RETRY_DELAY = 2 # SSH重试间隔时间(秒)
|
||||
|
||||
# ---------------------- 日志配置 ----------------------
|
||||
log = setup_logger(
|
||||
logger_name="daily_logger",
|
||||
log_file=log_path,
|
||||
backup_count=7
|
||||
)
|
||||
|
||||
# 确保日志目录存在
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# ---------------------- 工具函数 ----------------------
|
||||
def mask_ip(real_ip: str) -> str:
|
||||
"""IP脱敏处理"""
|
||||
parts = real_ip.split('.')
|
||||
return f"**.**.{parts[2]}.{parts[3]}" if len(parts) == 4 else real_ip
|
||||
|
||||
|
||||
def get_system_info(host):
|
||||
"""获取本地系统信息(CPU、内存、负载、磁盘)"""
|
||||
try:
|
||||
# 1. 获取磁盘使用率(通过df命令)
|
||||
df_cmd = "df -h | awk 'NR>1{print $1,$2,$3,$4,$5,$6}'"
|
||||
disk_cmd = f'ssh {host} {df_cmd}'
|
||||
disk_output = os.popen(disk_cmd).read().split('\n')
|
||||
|
||||
disks = []
|
||||
for line in disk_output:
|
||||
if line.strip():
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 6:
|
||||
disk = {
|
||||
'filesystem': parts[0],
|
||||
'size': parts[1],
|
||||
'used': parts[2],
|
||||
'available': parts[3],
|
||||
'percent_used': int(parts[4].replace('%', '')),
|
||||
'mount_point': parts[5]
|
||||
}
|
||||
disks.append(disk)
|
||||
|
||||
# 2. 获取CPU使用率(通过top命令)
|
||||
_top_cmd = "top -bn1 | grep 'Cpu(s)'"
|
||||
top_cmd = f'ssh {host} {_top_cmd}'
|
||||
top_output = os.popen(top_cmd).read().strip()
|
||||
cpu_match = re.search(r'(\d+\.\d+)\%* us', top_output)
|
||||
cpu_usage = float(cpu_match.group(1)) if cpu_match else 0
|
||||
|
||||
# 3. 获取内存使用率(通过free命令)
|
||||
free_cmd = "free -m | grep Mem"
|
||||
free_output = os.popen(free_cmd).read().strip()
|
||||
mem_match = re.search(r'Mem:\s+(\d+)\s+(\d+)\s+(\d+)', free_output)
|
||||
if mem_match:
|
||||
total_mem = int(mem_match.group(1))
|
||||
used_mem = int(mem_match.group(2))
|
||||
mem_usage = round((used_mem / total_mem) * 100, 2)
|
||||
else:
|
||||
mem_usage = 0
|
||||
|
||||
# 4. 获取系统负载(通过uptime命令)
|
||||
uptime_cmd = "uptime"
|
||||
uptime_output = os.popen(uptime_cmd).read().strip()
|
||||
load_match = re.search(r'load average:\s+([\d.]+),\s+([\d.]+),\s+([\d.]+)', uptime_output)
|
||||
load_avg = float(load_match.group(1)) if load_match else 0
|
||||
|
||||
# 5. 获取CPU核心数
|
||||
cpu_cores = 1
|
||||
try:
|
||||
cpu_cores_cmd = "grep -c 'processor' /proc/cpuinfo"
|
||||
cpu_cores_output = os.popen(cpu_cores_cmd).read().strip()
|
||||
|
||||
if cpu_cores_output:
|
||||
match = re.search(r'\d+', cpu_cores_output)
|
||||
if match:
|
||||
cpu_cores = int(match.group(0))
|
||||
log.debug(f"获取到本地CPU核心数: {cpu_cores}")
|
||||
else:
|
||||
log.warning(f"无法从输出中提取CPU核心数: {cpu_cores_output}")
|
||||
# 备选方案:使用nproc命令
|
||||
nproc_cmd = "nproc || echo 1"
|
||||
nproc_output = os.popen(nproc_cmd).read().strip()
|
||||
match = re.search(r'\d+', nproc_output)
|
||||
if match:
|
||||
cpu_cores = int(match.group(0))
|
||||
log.info(f"通过nproc获取到本地CPU核心数: {cpu_cores}")
|
||||
else:
|
||||
log.warning(f"获取本地CPU核心数失败,命令无输出")
|
||||
except Exception as e:
|
||||
log.error(f"获取本地CPU核心数异常: {str(e)}")
|
||||
|
||||
return {
|
||||
"disks": disks,
|
||||
"cpu_usage": cpu_usage,
|
||||
"mem_usage": mem_usage,
|
||||
"load_avg": load_avg,
|
||||
"load_avg_compare": load_avg / cpu_cores,
|
||||
"cpu_cores": cpu_cores
|
||||
}
|
||||
except Exception as e:
|
||||
log.error(f"获取本地系统信息失败: {str(e)}")
|
||||
raise e
|
||||
@@ -0,0 +1,396 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/6/9 上午10:27
|
||||
# @Author : cmk
|
||||
# @File : test.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import datetime
|
||||
import concurrent.futures
|
||||
from pathlib import Path
|
||||
#from tools.SMS_PUT import sms
|
||||
from tools.Logger import setup_logger
|
||||
|
||||
|
||||
# ---------------------- 配置配置 ----------------------
|
||||
script_dir = Path(__file__).parent.resolve()
|
||||
log_path = (script_dir / "logs" / "nc_disk.log").resolve()
|
||||
project_list = ['minirds-mt', 'rds', 'drds', 'dts']
|
||||
# 告警阈值配置
|
||||
DISK_THRESHOLD = 80 # 磁盘使用率阈值(%)
|
||||
CPU_USAGE_THRESHOLD = 80 # CPU使用率阈值(%)
|
||||
MEM_USAGE_THRESHOLD = 80 # 内存使用率阈值(%)
|
||||
LOAD_AVG_THRESHOLD = 1.5 # 系统负载阈值(CPU核心数倍数)
|
||||
|
||||
# SSH配置
|
||||
SSH_CONNECT_TIMEOUT = 3 # SSH连接超时时间(秒)
|
||||
SSH_RETRIES = 3 # SSH连接重试次数
|
||||
SSH_RETRY_DELAY = 2 # SSH重试间隔时间(秒)
|
||||
|
||||
# ---------------------- 日志配置 ----------------------
|
||||
log = setup_logger(
|
||||
logger_name="daily_logger",
|
||||
log_file=log_path,
|
||||
backup_count=7
|
||||
)
|
||||
|
||||
# 确保日志目录存在
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# ---------------------- 工具函数 ----------------------
|
||||
def mask_ip(real_ip: str) -> str:
|
||||
"""IP脱敏处理"""
|
||||
parts = real_ip.split('.')
|
||||
return f"**.**.{parts[2]}.{parts[3]}" if len(parts) == 4 else real_ip
|
||||
|
||||
|
||||
def retry(func):
|
||||
"""重试装饰器,用于SSH连接"""
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
max_retries = kwargs.pop('max_retries', SSH_RETRIES)
|
||||
delay = kwargs.pop('delay', SSH_RETRY_DELAY)
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
if attempt < max_retries - 1:
|
||||
log.warning(f"操作失败,尝试重试 ({attempt + 1}/{max_retries}): {str(e)}")
|
||||
import time
|
||||
time.sleep(delay)
|
||||
else:
|
||||
raise e
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@retry
|
||||
def get_system_info(host, ssh_cmd_prefix=""):
|
||||
"""获取主机系统信息(CPU、内存、负载)"""
|
||||
try:
|
||||
# 1.获取磁盘使用率(通过df命令)
|
||||
disk_cmd = "df -h | awk 'NR>1{print $1,$2,$3,$4,$5,$6}'"
|
||||
top_disk = f"{ssh_cmd_prefix} {disk_cmd}"
|
||||
disk_output = os.popen(f"{top_disk}").read().split('\n')
|
||||
|
||||
#for line_num, line in enumerate(disk_output.split('\n'), 1):
|
||||
# 1. 获取CPU使用率(通过top命令)
|
||||
top_cmd = f"{ssh_cmd_prefix} top -bn1 | grep 'Cpu(s)'"
|
||||
top_output = os.popen(top_cmd).read().strip()
|
||||
cpu_match = re.search(r'(\d+\.\d+)\%* us', top_output)
|
||||
cpu_usage = float(cpu_match.group(1)) if cpu_match else 0
|
||||
|
||||
# 2. 获取内存使用率(通过free命令)
|
||||
free_cmd = f"{ssh_cmd_prefix} free -m | grep Mem"
|
||||
free_output = os.popen(free_cmd).read().strip()
|
||||
mem_match = re.search(r'Mem:\s+(\d+)\s+(\d+)\s+(\d+)', free_output)
|
||||
if mem_match:
|
||||
total_mem = int(mem_match.group(1))
|
||||
used_mem = int(mem_match.group(2))
|
||||
mem_usage = round((used_mem / total_mem) * 100, 2)
|
||||
else:
|
||||
mem_usage = 0
|
||||
|
||||
# 3. 获取系统负载(通过uptime命令)
|
||||
uptime_cmd = f"{ssh_cmd_prefix} uptime"
|
||||
uptime_output = os.popen(uptime_cmd).read().strip()
|
||||
load_match = re.search(r'load average:\s+([\d.]+),\s+([\d.]+),\s+([\d.]+)', uptime_output)
|
||||
load_avg = float(load_match.group(1)) if load_match else 0
|
||||
|
||||
# 4. 获取CPU核心数(优化版)
|
||||
cpu_cores = 1
|
||||
try:
|
||||
cpu_cores_cmd = f"{ssh_cmd_prefix} grep -c 'processor' /proc/cpuinfo"
|
||||
cpu_cores_output = os.popen(cpu_cores_cmd).read().strip()
|
||||
|
||||
if cpu_cores_output:
|
||||
match = re.search(r'\d+', cpu_cores_output)
|
||||
if match:
|
||||
cpu_cores = int(match.group(0))
|
||||
log.debug(f"获取到主机 {host} 的CPU核心数: {cpu_cores}")
|
||||
else:
|
||||
log.warning(f"无法从输出中提取CPU核心数: {cpu_cores_output}")
|
||||
# 备选方案:使用nproc命令
|
||||
nproc_cmd = f"{ssh_cmd_prefix} nproc || echo 1"
|
||||
nproc_output = os.popen(nproc_cmd).read().strip()
|
||||
match = re.search(r'\d+', nproc_output)
|
||||
if match:
|
||||
cpu_cores = int(match.group(0))
|
||||
log.info(f"通过nproc获取到主机 {host} 的CPU核心数: {cpu_cores}")
|
||||
else:
|
||||
log.warning(f"获取主机 {host} 的CPU核心数失败,命令无输出")
|
||||
except Exception as e:
|
||||
log.error(f"获取主机 {host} 的CPU核心数异常: {str(e)}")
|
||||
|
||||
return {
|
||||
"cpu_usage": cpu_usage,
|
||||
"mem_usage": mem_usage,
|
||||
"load_avg": load_avg,
|
||||
"load_avg_compare": load_avg / cpu_cores,
|
||||
"cpu_cores": cpu_cores
|
||||
}
|
||||
except Exception as e:
|
||||
log.error(f"获取主机 {host} 系统信息失败: {str(e)}")
|
||||
raise e # 让重试机制处理异常
|
||||
|
||||
|
||||
# ---------------------- 核心逻辑 ----------------------
|
||||
def get_nc_hostname(project, get_time):
|
||||
"""获取平台机器信息(带缓存)"""
|
||||
url = f'http://127.0.0.1:7070/api/v3/column/m.project,m.ip,m.id'
|
||||
data = requests.get(url).json()
|
||||
if not data:
|
||||
return []
|
||||
|
||||
data_list = [i for i in data if 'cloud' in i.get('m.id', '') and i.get('m.project') == project]
|
||||
log.info(f"[项目:{project}] 获取到 {len(data_list)} 台机器")
|
||||
return data_list
|
||||
|
||||
|
||||
@retry
|
||||
def get_disk_info(host_info, get_time, ssh_key_path=None):
|
||||
"""获取单台主机的磁盘、CPU、内存及负载信息"""
|
||||
host = host_info['m.id']
|
||||
project = host_info['m.project']
|
||||
ip = host_info['m.ip']
|
||||
cmd_prefix = f"ssh -i {ssh_key_path} -o ConnectTimeout={SSH_CONNECT_TIMEOUT} {host} " if ssh_key_path else f"ssh -o ConnectTimeout={SSH_CONNECT_TIMEOUT} {host} "
|
||||
|
||||
try:
|
||||
# 1. 获取磁盘信息
|
||||
disk_cmd = "df -h | awk 'NR>1{print $1,$2,$3,$4,$5,$6}'"
|
||||
disk_output = os.popen(f"{cmd_prefix}{disk_cmd}").read()
|
||||
disk_info_list = []
|
||||
|
||||
for line_num, line in enumerate(disk_output.split('\n'), 1):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
parts = line.split()
|
||||
if len(parts) < 6:
|
||||
log.warning(f"[项目:{project}, 主机:{host}] 无效磁盘信息行(行号:{line_num}): {line}")
|
||||
continue
|
||||
|
||||
try:
|
||||
percent_used = parts[4].strip('%')
|
||||
if not percent_used.isdigit():
|
||||
log.warning(f"[项目:{project}, 主机:{host}] 无效使用率: {percent_used}, 行: {line}")
|
||||
continue
|
||||
|
||||
disk_info = {
|
||||
"project": project,
|
||||
"host": host,
|
||||
"ip": mask_ip(ip),
|
||||
"device": parts[0],
|
||||
"total": parts[1],
|
||||
"used": parts[2],
|
||||
"available": parts[3],
|
||||
"percent_used": int(percent_used),
|
||||
"mount_point": parts[5],
|
||||
"get_time": get_time
|
||||
}
|
||||
disk_info_list.append(disk_info)
|
||||
except Exception as e:
|
||||
log.error(f"[项目:{project}, 主机:{host}] 解析磁盘信息失败: {str(e)}, 行: {line}")
|
||||
|
||||
# 2. 获取系统信息
|
||||
system_info = get_system_info(host, cmd_prefix)
|
||||
|
||||
log.debug(f"[项目:{project}, 主机:{host}] 成功获取 {len(disk_info_list)} 条磁盘信息及系统信息")
|
||||
return {
|
||||
"disk_info": disk_info_list,
|
||||
"system_info": system_info,
|
||||
"project": project,
|
||||
"host": host,
|
||||
"ip": mask_ip(ip)
|
||||
}
|
||||
except Exception as e:
|
||||
# 明确处理SSH连接异常
|
||||
if "Connection timed out" in str(e) or "connect to host" in str(e):
|
||||
log.warning(f"[项目:{project}, 主机:{host}] SSH连接超时,跳过该主机")
|
||||
else:
|
||||
log.error(f"[项目:{project}, 主机:{host}] 获取信息失败: {str(e)}")
|
||||
raise e # 让重试机制处理异常
|
||||
|
||||
|
||||
def check_disk(project, get_time, ssh_key_path=None, all_hosts=None):
|
||||
"""获取指定项目的所有主机信息(支持传入全局主机列表)"""
|
||||
log.info(f"[项目:{project}] 开始处理主机信息")
|
||||
# 使用全局主机列表,避免重复获取
|
||||
hosts = [host for host in all_hosts if host.get('m.project') == project] if all_hosts else []
|
||||
all_info = []
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
||||
future_to_host = {
|
||||
executor.submit(get_disk_info, host, get_time, ssh_key_path): host
|
||||
for host in hosts
|
||||
}
|
||||
for future in concurrent.futures.as_completed(future_to_host):
|
||||
try:
|
||||
info = future.result()
|
||||
all_info.append(info)
|
||||
except Exception as e:
|
||||
host = future_to_host[future]
|
||||
log.error(f"[项目:{project}, 主机:{host['m.id']}] 处理异常: {str(e)}")
|
||||
|
||||
log.info(f"[项目:{project}] 共获取到 {len(all_info)} 台主机的信息")
|
||||
return all_info
|
||||
|
||||
|
||||
def send_alert(alert_type, data, system_info=None):
|
||||
"""统一发送告警信息"""
|
||||
if alert_type == "disk":
|
||||
alert_title = "-----数据库告警-----\n磁盘高使用率告警"
|
||||
alert_content = (
|
||||
f"\n{alert_title}\n"
|
||||
f"产品:{data['project']}\n"
|
||||
f" - 主机:{data['host']}\n"
|
||||
f" ip: {data['ip']}\n"
|
||||
f" 设备:{data['device']}\n"
|
||||
f" 总量:{data['total']}\n"
|
||||
f" 已用:{data['used']}\n"
|
||||
f" 剩余:{data['available']}\n"
|
||||
f" 使用率:{data['percent_used']}%\n"
|
||||
f" 挂载点:{data['mount_point']}\n"
|
||||
f" 时间:{data['get_time']}\n"
|
||||
)
|
||||
elif alert_type == "cpu":
|
||||
alert_title = "-----数据库告警-----\nCPU高使用率告警"
|
||||
alert_content = (
|
||||
f"\n{alert_title}\n"
|
||||
f"产品:{data['project']}\n"
|
||||
f" - 主机:{data['host']}\n"
|
||||
f" ip: {data['ip']}\n"
|
||||
f" CPU使用率:{system_info['cpu_usage']}%\n"
|
||||
f" 阈值:{CPU_USAGE_THRESHOLD}%\n"
|
||||
f" 时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||
)
|
||||
elif alert_type == "memory":
|
||||
alert_title = "-----数据库告警----\n内存高使用率告警-"
|
||||
alert_content = (
|
||||
f"\n{alert_title}\n"
|
||||
f"产品:{data['project']}\n"
|
||||
f" - 主机:{data['host']}\n"
|
||||
f" ip: {data['ip']}\n"
|
||||
f" 内存使用率:{system_info['mem_usage']}%\n"
|
||||
f" 阈值:{MEM_USAGE_THRESHOLD}%\n"
|
||||
f" 时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||
)
|
||||
elif alert_type == "load":
|
||||
alert_title = "-----数据库告警-----\n系统高负载告警"
|
||||
alert_content = (
|
||||
f"\n{alert_title}\n"
|
||||
f"产品:{data['project']}\n"
|
||||
f" - 主机:{data['host']}\n"
|
||||
f" ip: {data['ip']}\n"
|
||||
f" 系统负载:{system_info['load_avg']}\n"
|
||||
f" CPU核心数:{system_info['cpu_cores']}\n"
|
||||
f" 负载/核心数:{system_info['load_avg_compare']:.2f}\n"
|
||||
f" 阈值:{LOAD_AVG_THRESHOLD}\n"
|
||||
f" 时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
|
||||
)
|
||||
else:
|
||||
log.warning(f"未知告警类型: {alert_type}")
|
||||
return False, alert_content
|
||||
|
||||
log.info(f"[告警类型:{alert_type}] {alert_content}")
|
||||
try:
|
||||
#result = sms(alert_content)
|
||||
result = ''
|
||||
if result:
|
||||
log.info(f"[告警类型:{alert_type}] 告警发送成功")
|
||||
return True, alert_content
|
||||
else:
|
||||
log.error(f"[告警类型:{alert_type}] 告警发送失败")
|
||||
return False, alert_content
|
||||
except Exception as e:
|
||||
log.error(f"[告警类型:{alert_type}] 发送告警异常: {str(e)}")
|
||||
return False, alert_content
|
||||
|
||||
|
||||
def get_all_data(ssh_key_path=None):
|
||||
"""获取所有项目的硬件信息并处理告警"""
|
||||
get_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
alert_count = {"disk": 0, "cpu": 0, "memory": 0, "load": 0}
|
||||
|
||||
# 1. 统一获取所有项目的主机列表(仅请求一次API)
|
||||
log.info("开始获取所有项目的主机列表...")
|
||||
all_hosts = []
|
||||
for project in project_list:
|
||||
hosts = get_nc_hostname(project, get_time)
|
||||
all_hosts.extend(hosts)
|
||||
log.info(f"共获取到 {len(all_hosts)} 台主机的基础信息")
|
||||
|
||||
# 2. 并发处理每个项目的主机信息
|
||||
all_info = []
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
|
||||
future_to_project = {
|
||||
executor.submit(check_disk, project, get_time, ssh_key_path, all_hosts): project
|
||||
for project in project_list
|
||||
}
|
||||
for future in concurrent.futures.as_completed(future_to_project):
|
||||
try:
|
||||
project = future_to_project[future]
|
||||
project_info = future.result()
|
||||
all_info.extend(project_info)
|
||||
log.info(f"[项目:{project}] 处理完成,获取到 {len(project_info)} 台主机信息")
|
||||
except Exception as e:
|
||||
log.error(f"[项目:{project}] 处理异常: {str(e)}")
|
||||
|
||||
log.info(f"所有项目处理完成,共获取到 {len(all_info)} 台主机的详细信息")
|
||||
|
||||
# 3. 处理告警
|
||||
for host_info in all_info:
|
||||
# 提取基本信息
|
||||
base_data = {
|
||||
"project": host_info["project"],
|
||||
"host": host_info["host"],
|
||||
"ip": host_info["ip"]
|
||||
}
|
||||
|
||||
# 处理磁盘告警
|
||||
for disk in host_info['disk_info']:
|
||||
if disk['percent_used'] > CPU_USAGE_THRESHOLD:
|
||||
success, _ = send_alert("disk", disk)
|
||||
if success:
|
||||
alert_count["disk"] += 1
|
||||
|
||||
# 处理系统告警
|
||||
system_info = host_info['system_info']
|
||||
if not system_info:
|
||||
continue
|
||||
|
||||
# CPU告警
|
||||
if system_info['cpu_usage'] > CPU_USAGE_THRESHOLD:
|
||||
success, _ = send_alert("cpu", base_data, system_info)
|
||||
if success:
|
||||
alert_count["cpu"] += 1
|
||||
|
||||
# 内存告警
|
||||
if system_info['mem_usage'] > MEM_USAGE_THRESHOLD:
|
||||
success, _ = send_alert("memory", base_data, system_info)
|
||||
if success:
|
||||
alert_count["memory"] += 1
|
||||
|
||||
# 系统负载告警
|
||||
if system_info['load_avg_compare'] > LOAD_AVG_THRESHOLD:
|
||||
success, _ = send_alert("load", base_data, system_info)
|
||||
if success:
|
||||
alert_count["load"] += 1
|
||||
|
||||
log.info(
|
||||
f"本次检查共触发告警: 磁盘[{alert_count['disk']}]、CPU[{alert_count['cpu']}]、内存[{alert_count['memory']}]、负载[{alert_count['load']}]")
|
||||
return all_info
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
log.info("+++++++++++++ 开始检查物理机硬件信息 +++++++++++++++++++++++")
|
||||
SSH_KEY_PATH = "/root/.ssh/id_rsa"
|
||||
get_all_data(SSH_KEY_PATH)
|
||||
log.info("+++++++++++++ 物理机硬件信息检查完成 +++++++++++++++++++++++")
|
||||
except Exception as e:
|
||||
log.critical(f"脚本执行异常: {str(e)}", exc_info=True)
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/5/28 上午9:25
|
||||
# @Author : cmk
|
||||
# @File : Logger.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from typing import Optional
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
|
||||
|
||||
def setup_logger(
|
||||
logger_name: str = "app_logger",
|
||||
log_file: Optional[str] = None,
|
||||
level: int = logging.INFO,
|
||||
console_output: bool = True,
|
||||
log_format: str = "%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s",
|
||||
backup_count: int = 7, # 保留的历史日志文件数量
|
||||
when: str = 'midnight', # 切割时间点,默认为午夜
|
||||
interval: int = 1, # 切割间隔
|
||||
) -> logging.Logger:
|
||||
"""
|
||||
配置并返回一个自定义logger实例
|
||||
|
||||
参数:
|
||||
logger_name: 日志器名称,用于区分不同的日志实例
|
||||
log_file: 日志文件路径,若为None则不输出到文件
|
||||
level: 日志级别,默认INFO
|
||||
console_output: 是否输出到控制台
|
||||
log_format: 日志格式字符串
|
||||
backup_count: 保留的历史日志文件数量
|
||||
when: 日志切割时间单位 ('S'/'M'/'H'/'D'/'midnight'等)
|
||||
interval: 日志切割间隔
|
||||
|
||||
返回:
|
||||
配置好的logger实例
|
||||
"""
|
||||
# 获取或创建logger实例(避免重复配置)
|
||||
logger = logging.getLogger(logger_name)
|
||||
|
||||
# 防止重复添加处理器
|
||||
if logger.handlers:
|
||||
return logger
|
||||
|
||||
# 设置日志级别
|
||||
logger.setLevel(level)
|
||||
|
||||
# 创建格式化器
|
||||
formatter = logging.Formatter(log_format)
|
||||
|
||||
# 添加文件处理器(如果指定了文件名)
|
||||
if log_file:
|
||||
try:
|
||||
# 确保日志目录存在
|
||||
log_dir = os.path.dirname(log_file)
|
||||
if log_dir and not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir)
|
||||
|
||||
# 使用TimedRotatingFileHandler按天切割日志
|
||||
file_handler = TimedRotatingFileHandler(
|
||||
log_file,
|
||||
when=when,
|
||||
interval=interval,
|
||||
backupCount=backup_count,
|
||||
encoding='utf-8'
|
||||
)
|
||||
file_handler.setLevel(level)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# 添加日志切割提示
|
||||
file_handler.suffix = "%Y-%m-%d.log" # 设置历史日志文件后缀
|
||||
file_handler.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}\.log$") # 设置匹配模式
|
||||
|
||||
except Exception as e:
|
||||
print(f"无法创建日志文件 {log_file}: {e}")
|
||||
|
||||
# 添加控制台处理器
|
||||
# if console_output:
|
||||
# console_handler = logging.StreamHandler()
|
||||
# console_handler.setLevel(level)
|
||||
# console_handler.setFormatter(formatter)
|
||||
# logger.addHandler(console_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
# 示例使用
|
||||
if __name__ == "__main__":
|
||||
# 配置按天切割的文件日志
|
||||
daily_logger = setup_logger(
|
||||
logger_name="daily_logger",
|
||||
log_file="logs/app.log", # 日志将按天切割到logs目录
|
||||
level=logging.DEBUG,
|
||||
backup_count=30 # 保留30天的历史日志
|
||||
)
|
||||
|
||||
# 测试日志记录
|
||||
daily_logger.info("这是一条测试日志")
|
||||
daily_logger.debug("这是一条测试日志")
|
||||
daily_logger.warning("这是一条测试日志")
|
||||
daily_logger.error("这是一条测试日志")
|
||||
daily_logger.critical("这是一条测试日志")
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/6/27 下午10:58
|
||||
# @Author : cmk
|
||||
# @File : __init__.py.py
|
||||
# @Email : 15726649712@163.com
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/6/5 上午9:47
|
||||
# @Author : cmk
|
||||
# @File : database.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import pymysql
|
||||
|
||||
class DBHelper:
|
||||
def __init__(self, host, user, password, database, port=3306, charset='utf8mb4'):
|
||||
self.conn = pymysql.connect(
|
||||
host=host,
|
||||
user=user,
|
||||
password=password,
|
||||
database=database,
|
||||
port=port,
|
||||
charset=charset
|
||||
)
|
||||
self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)
|
||||
|
||||
def execute(self, sql, params=None):
|
||||
"""执行非查询操作(insert, update, delete)"""
|
||||
try:
|
||||
self.cursor.execute(sql, params or ())
|
||||
self.conn.commit()
|
||||
return self.cursor.rowcount
|
||||
except Exception as e:
|
||||
self.conn.rollback()
|
||||
print("执行失败:", e)
|
||||
return -1
|
||||
|
||||
def fetchall(self, sql, params=None):
|
||||
"""执行查询,返回所有结果"""
|
||||
self.cursor.execute(sql, params or ())
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def fetchone(self, sql, params=None):
|
||||
"""执行查询,返回单条结果"""
|
||||
self.cursor.execute(sql, params or ())
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def insert(self, table, data):
|
||||
"""插入数据"""
|
||||
keys = ', '.join(data.keys())
|
||||
values = ', '.join(['%s'] * len(data))
|
||||
sql = f"INSERT INTO {table} ({keys}) VALUES ({values})"
|
||||
return self.execute(sql, tuple(data.values()))
|
||||
|
||||
def update(self, table, data, where):
|
||||
"""更新数据"""
|
||||
set_clause = ', '.join([f"{k}=%s" for k in data.keys()])
|
||||
where_clause = ' AND '.join([f"{k}=%s" for k in where.keys()])
|
||||
sql = f"UPDATE {table} SET {set_clause} WHERE {where_clause}"
|
||||
return self.execute(sql, tuple(data.values()) + tuple(where.values()))
|
||||
|
||||
def delete(self, table, where):
|
||||
"""删除数据"""
|
||||
where_clause = ' AND '.join([f"{k}=%s" for k in where.keys()])
|
||||
sql = f"DELETE FROM {table} WHERE {where_clause}"
|
||||
return self.execute(sql, tuple(where.values()))
|
||||
|
||||
def close(self):
|
||||
"""关闭连接"""
|
||||
self.cursor.close()
|
||||
self.conn.close()
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2025/2/13 下午2:07
|
||||
# @Author : cmk
|
||||
# @File : tianji_json.py
|
||||
# @Email : 15726649712@163.com
|
||||
|
||||
import json
|
||||
import pandas as pd
|
||||
import os
|
||||
import pprint
|
||||
|
||||
with open('zhuque_0213.json','r',encoding='utf-8') as f:
|
||||
data =f.readlines()
|
||||
json_data=json.loads(''.join(data))
|
||||
|
||||
list_data = json_data['productList']
|
||||
for i in range(0,int(len(list_data))):
|
||||
print(list_data[i]['productName'])
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
[{
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"user": "root",
|
||||
"password": "password",
|
||||
"database": "ticai"
|
||||
}]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user