├── .gitignore ├── LICENSE ├── README.md ├── blockchain ├── README.md └── money.py ├── bug_notify ├── README.md ├── avd.py └── wecom.py ├── check_pic ├── .gitignore ├── 1.jpg ├── LICENSE ├── README.md ├── TencentYoutuyun │ ├── __init__.py │ ├── auth.py │ ├── conf.py │ └── youtu.py ├── check.py └── requirements.txt ├── etcd2consul ├── 333.csv ├── README.md ├── consulkv2service.py ├── csv_base_service2consul_service.py ├── etcd2consul_kv.py ├── etcd2consul_service.py └── salt2consul_service.py ├── google-authenticator ├── LICENSE ├── README.md └── google-authenticator.py ├── how-to-look-the-plate ├── README.md ├── capture.jpg └── rise.py ├── hwpy ├── 3rd │ ├── SSU.exe │ ├── disk.sh │ ├── hwinfo.sh │ └── ssu.sh ├── README.md ├── deploy.sh ├── hwpy │ ├── __init__.py │ ├── __main__.py │ ├── _dmide.py │ ├── _hwdisk.py │ ├── _hwnet.py │ ├── _hwpart.py │ └── info.py └── setup.py ├── rabbitmq-test ├── README.md ├── send.py ├── work.py ├── work.py.bak ├── work.py.false └── work.py.new ├── short-url ├── README.md └── short-url.py ├── wechatbot ├── README.md ├── bot.png └── wechatbot.py └── ws-test ├── .gevent.py ├── README.md ├── iws.sh └── wsc.py /.gitignore: -------------------------------------------------------------------------------- 1 | check_pic/config 2 | __pycache__/ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 StarsL.cn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tools 2 | Python写的小工具集合 3 | -------------------------------------------------------------------------------- /blockchain/README.md: -------------------------------------------------------------------------------- 1 | ## 注意:火币的sdk不支持python3.9,请使用3.9以下的版本,3.6测试正常。 2 | 3 | # 运维同学,如何优雅的炒币? 4 | 5 | ## 痛点分析: 6 | 1. 在币安和火币都有交易,需要经常切换APP来查看资产涨跌情况。 7 | 2. 目前币安和火币都无法查看持有币种的收益与收益率,只有当前币值。 8 | 3. 当同一币种多次调整仓位后,无法清楚了解自己的成本价是多少。 9 | 10 | ## 使用前提: 11 | 1. 需要创建调用币安和火币API的只读API Key。 12 | 2. 必须使用中国大陆以外的服务器来调用币安和火币的API。 13 | 3. 使用python3.6开发。 14 | 15 | ## API文档 16 | ``` 17 | # 火币 18 | https://huobiapi.github.io/docs/spot/v1/cn/ 19 | # 币安 20 | https://binance-docs.github.io/apidocs/spot/cn/ 21 | ``` 22 | 23 | ## 实现功能: 24 | 1. 把币安和火币所持有币种的信息聚合到一起展示。 25 | 2. 能展示所持有币种的数量、总价、最新价、成本价、收益、收益率。 26 | 3. 以文本和图片的方式输出表格信息。 27 | 4. 币安可开启展示所持有币种的历史交易收益与收益率。 28 | 5. 火币信息采集是使用官方的python sdk,币安无现货sdk,直接调用API。 29 | 30 | ## 扩展功能: 31 | 1. 定时推送微信群或者钉钉群。 32 | 2. 发消息来触发推送微信群或者钉钉群。 33 | 3. 微信群报价机器人。 34 | 35 | ### 火币Python SDK安装 36 | ``` 37 | git clone https://github.com/HuobiRDCenter/huobi_Python.git 38 | cd huobi_Python 39 | pip3 install-r requirements.txt 40 | python3 setup.py build 41 | python3 setup.py install 42 | ``` 43 | 44 | ### 完整代码请参考github或点击阅读原文 45 | https://github.com/starsliao/tools/tree/master/blockchain 46 | 47 | 48 | ## 部分代码解析: 49 | 50 | ### 币安私有接口鉴权签名代码 51 | ``` 52 | import requests,json,time 53 | import hashlib 54 | import hmac 55 | 56 | ab_apikey = '' 57 | ab_apisecret = '' 58 | ab_url = 'https://api.binance.com' 59 | 60 | def getjson(api,params=''): 61 | ts = round(time.time()*1000) 62 | query = f'{params}×tamp={ts}' if params != '' else f'timestamp={ts}' 63 | signature = hmac.new(ab_apisecret.encode(), msg=query.encode(), digestmod=hashlib.sha256).hexdigest() 64 | queryurl = f'{ab_url}{api}?{query}&signature={signature}' 65 | headers = {'Content-Type': 'application/json','X-MBX-APIKEY': ab_apikey} 66 | resjson = requests.request("GET", queryurl, headers=headers).json() 67 | return resjson 68 | 69 | ab_listjson = getjson('/api/v3/account') 70 | borderjson = getjson('/api/v3/allOrders',f"symbol={i['asset']}USDT") 71 | ``` 72 | 73 | ### 把最终数据以文本表格方式输出 74 | ``` 75 | from prettytable import PrettyTable 76 | table_list.sort(key=lambda x:float(x[-1].replace('%','')),reverse = True) 77 | tab = PrettyTable() 78 | tab.field_names = ['币种','数量','总价','最新价','成本价','收益','收益率'] 79 | tab.align['币种'] = "l" 80 | tab.align['数量'] = "r" 81 | tab.align['总价'] = "r" 82 | tab.align['最新价'] = "r" 83 | tab.align['成本价'] = "r" 84 | tab.align['收益'] = "r" 85 | tab.align['收益率'] = "r" 86 | for x in table_list: 87 | tab.add_row(x) 88 | tab_info = str(tab) 89 | space = 5 90 | print(tab) 91 | ``` 92 | 93 | ### 把文本表格转换成图片 94 | ``` 95 | from PIL import Image, ImageDraw, ImageFont 96 | import uuid 97 | font = ImageFont.truetype('/opt/yahei_mono.ttf', 20,encoding="utf-8") 98 | im = Image.new('RGB',(10, 10),(0,0,0,0)) 99 | draw = ImageDraw.Draw(im, "RGB") 100 | img_size = draw.multiline_textsize(tab_info, font=font) 101 | im_new = im.resize((img_size[0]+space*2, img_size[1]+space*6)) 102 | draw = ImageDraw.Draw(im_new, 'RGB') 103 | draw.multiline_text((space,space), tab_info, spacing=6, fill=(255,255,255), font=font) 104 | filename = str(uuid.uuid1()) 105 | im_new.save(f'/tmp/b/b-{filename}.png', "PNG") 106 | print(f'img_path:/tmp/b/b-{filename}.png') 107 | ``` 108 | 109 | ### 图片推送钉钉群,需要图床支持,上传到阿里云OSS例子 110 | ``` 111 | # 上传OSS 112 | import oss2,os 113 | auth = oss2.Auth(Key, Secret) 114 | bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'oss_bucket') 115 | bucket.put_object_from_file(目标路径/文件名, 源文件) 116 | os.remove(源文件) 117 | 118 | # 推送消息 119 | from dingtalkchatbot.chatbot import DingtalkChatbot 120 | webhook = 'https://oapi.dingtalk.com/robot/send?access_token=' 121 | msg = DingtalkChatbot(webhook) 122 | send = msg.send_markdown(title='xxxx', text='### xxxx:\n' 123 | '![5XX](https://oss_bucket.oss-cn-shenzhen.aliyuncs.com/oss.png)\n\n' 124 | '[点击查看明细](http://xxx.com)\n', is_at_all=True) 125 | print(send) 126 | ``` 127 | -------------------------------------------------------------------------------- /blockchain/money.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import requests,json,time 3 | import hashlib 4 | import hmac 5 | from huobi.client.account import AccountClient 6 | from huobi.constant import * 7 | from huobi.client.trade import TradeClient 8 | from huobi.utils import * 9 | from huobi.client.market import MarketClient 10 | from datetime import datetime, timedelta 11 | from prettytable import PrettyTable 12 | 13 | ab_apikey = '' 14 | ab_apisecret = '' 15 | ab_url = 'https://api.binance.com' 16 | 17 | hb_api_key='' 18 | hb_secret_key='' 19 | hb_iglist = ['hbpoint','meetone','add','eon','eop','iq','usdt'] 20 | 21 | def getjson(api,params=''): 22 | ts = round(time.time()*1000) 23 | query = f'{params}×tamp={ts}' if params != '' else f'timestamp={ts}' 24 | signature = hmac.new(ab_apisecret.encode(), msg=query.encode(), digestmod=hashlib.sha256).hexdigest() 25 | queryurl = f'{ab_url}{api}?{query}&signature={signature}' 26 | headers = {'Content-Type': 'application/json','X-MBX-APIKEY': ab_apikey} 27 | resjson = requests.request("GET", queryurl, headers=headers).json() 28 | return resjson 29 | 30 | def getlastprice(buss,symbol): 31 | if buss == '安': 32 | return requests.request("GET",f'{ab_url}/api/v3/ticker/price?symbol={symbol}USDT').json()['price'] 33 | else: 34 | market_client = MarketClient() 35 | return market_client.get_market_trade(symbol=f"{symbol}usdt")[0].price 36 | def showmethemoney(buss,asset,border): 37 | #print("**********************************************") 38 | count = [float(i['executedQty']) if i['side'] == 'BUY' else -float(i['executedQty']) for i in border] 39 | amount = [float(i['cummulativeQuoteQty']) if i['side'] == 'BUY' else -float(i['cummulativeQuoteQty']) for i in border] 40 | avgprice = round(sum(amount)/sum(count),8) 41 | #print(f"========={i['asset']}========{sum(amount)}/{sum(count)}={avgprice}") 42 | #print(json.dumps(border,indent=4)) 43 | buy_count,buy_amount,sell_count,sell_amount = 0,0,0,0 44 | last_order = border[-1]['orderId'] 45 | for j in border: 46 | if j['side'] == 'BUY': 47 | buy_count = buy_count + float(j['executedQty']) 48 | buy_amount = buy_amount + float(j['cummulativeQuoteQty']) 49 | else: 50 | sell_count = sell_count + float(j['executedQty']) 51 | sell_amount = sell_amount + float(j['cummulativeQuoteQty']) 52 | 53 | last_count = buy_count - sell_count 54 | if round(last_count,8) == 0 or j['orderId'] == last_order: 55 | if j['orderId'] == last_order and round(last_count,8) != 0: 56 | last_price = float(getlastprice(buss,asset)) 57 | ccost_price = (buy_amount - sell_amount)/last_count 58 | u_price = last_count * last_price 59 | sell_amount = sell_amount + (last_price * last_count) 60 | 61 | p = f'{round(last_count,2)}个,币值:{round(u_price,2)}u,最新:{round(last_price,6)}u,成本:{round(ccost_price,6)}u,' 62 | 63 | profit = sell_amount - buy_amount 64 | rate = round((sell_amount - buy_amount)*100/buy_amount,2) 65 | #print(f"{buss}:{asset.upper()}:{p}收益:{round(profit,2)}u,收益率:{rate}%") 66 | table_list.append([f'{buss}:{asset.upper()}',round(last_count,2),'%.2fu' % u_price,f'{round(last_price,6)}u',f'{round(ccost_price,6)}u',f'{round(profit,2)}u',f'{rate}%']) 67 | else: 68 | ptime = time.strftime("%y-%m-%d_%H:%M", time.localtime(j['updateTime']/1000)) 69 | p = f'成交时间:{ptime},' 70 | 71 | #profit = sell_amount - buy_amount 72 | #rate = round((sell_amount - buy_amount)*100/buy_amount,2) 73 | #print(f"{i['asset']}:{p}收益:{round(profit,6)}u,收益率:{rate}%") 74 | buy_count,buy_amount,sell_count,sell_amount = 0,0,0,0 75 | 76 | 77 | if __name__ == "__main__": 78 | table_list = [] 79 | 80 | #币安处理 81 | ab_listjson = getjson('/api/v3/account') 82 | ab_list = [i for i in ab_listjson['balances'] if float(i['free']) != 0 or float(i['locked']) != 0] 83 | #print(ab_list) 84 | for i in ab_list: 85 | if i['asset'] != 'BNB' and i['asset'] != 'USDT': 86 | borderjson = getjson('/api/v3/allOrders',f"symbol={i['asset']}USDT") 87 | 88 | #单个币的交易订单记录,格式为列表内每个订单为一个字典:订单id,单价,成交量,成交金额,类型,成交时间。 89 | ab_border = [{"orderId":i['orderId'], 90 | "price":i['price'], 91 | "executedQty":i['executedQty'], 92 | "cummulativeQuoteQty":i['cummulativeQuoteQty'], 93 | "side":i['side'], 94 | "updateTime":i['updateTime']} 95 | for i in borderjson if float(i['executedQty']) != 0 and i['orderId'] != 8472222] 96 | 97 | showmethemoney('安',i['asset'],ab_border) 98 | 99 | #火币处理 100 | hb_balance = {} 101 | account_client = AccountClient(api_key=hb_api_key,secret_key=hb_secret_key) 102 | account_balance_list = account_client.get_account_balance() 103 | for account_balance_obj in account_balance_list: 104 | for balance_obj in account_balance_obj.list: 105 | if float(balance_obj.balance) > 0.01 and balance_obj.currency not in hb_iglist: 106 | hb_balance[balance_obj.currency] = float(balance_obj.balance) if balance_obj.currency not in hb_balance else hb_balance[balance_obj.currency] + float(balance_obj.balance) 107 | 108 | trade_client = TradeClient(api_key=hb_api_key,secret_key=hb_secret_key) 109 | for symbol,bcount in hb_balance.items(): 110 | x,order_bcount = 0,0 111 | hb_border = [] 112 | while abs(order_bcount - bcount) >0.1 and x < 30: 113 | list_obj = trade_client.get_orders(symbol=f'{symbol}usdt', 114 | start_date=(datetime.now() - timedelta(days=2*x+1)).strftime('%Y-%m-%d'), 115 | end_date=(datetime.now() - timedelta(days=2*x)).strftime('%Y-%m-%d'), 116 | order_state="partial-filled,filled,partial-canceled") 117 | if len(list_obj) != 0: 118 | for order in list_obj: 119 | hb_border.append({"orderId":order.id, "price":order.price, 120 | "executedQty":order.filled_amount, 121 | "cummulativeQuoteQty":order.filled_cash_amount, 122 | "side":'BUY' if order.type.startswith("buy-") else 'SELL', 123 | "updateTime":order.finished_at}) 124 | order_bcount = order_bcount + (float(order.filled_amount) if order.type.startswith("buy-") else -float(order.filled_amount)) 125 | if abs(abs(order_bcount) - bcount) <0.1: 126 | break 127 | x=x+1 128 | showmethemoney('火',symbol,hb_border) 129 | 130 | table_list.sort(key=lambda x:float(x[-1].replace('%','')),reverse = True) 131 | tab = PrettyTable() 132 | tab.field_names = ['币种','数量','总价','最新价','成本价','收益','收益率'] 133 | tab.align['币种'] = "l" 134 | tab.align['数量'] = "r" 135 | tab.align['总价'] = "r" 136 | tab.align['最新价'] = "r" 137 | tab.align['成本价'] = "r" 138 | tab.align['收益'] = "r" 139 | tab.align['收益率'] = "r" 140 | for x in table_list: 141 | tab.add_row(x) 142 | tab_info = str(tab) 143 | space = 5 144 | print(tab) 145 | 146 | from PIL import Image, ImageDraw, ImageFont 147 | import uuid 148 | font = ImageFont.truetype('/opt/yahei_mono.ttf', 20,encoding="utf-8") 149 | im = Image.new('RGB',(10, 10),(0,0,0,0)) 150 | draw = ImageDraw.Draw(im, "RGB") 151 | img_size = draw.multiline_textsize(tab_info, font=font) 152 | im_new = im.resize((img_size[0]+space*2, img_size[1]+space*6)) 153 | draw = ImageDraw.Draw(im_new, 'RGB') 154 | draw.multiline_text((space,space), tab_info, spacing=6, fill=(255,255,255), font=font) 155 | filename = str(uuid.uuid1()) 156 | im_new.save(f'/tmp/b/b-{filename}.png', "PNG") 157 | print(f'img_path:/tmp/b/b-{filename}.png') 158 | -------------------------------------------------------------------------------- /bug_notify/README.md: -------------------------------------------------------------------------------- 1 | ### 从阿里云漏洞库采集最新漏洞推送到企业微信 2 | -------------------------------------------------------------------------------- /bug_notify/avd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from bs4 import BeautifulSoup 3 | import requests,sys,os,pickle 4 | from datetime import datetime 5 | import wecom,hashlib 6 | weixin = wecom.WXQY() 7 | 8 | avd_url = 'https://avd.aliyun.com' 9 | avd_file = './last_avd_id.pkl' 10 | wxkey = 'xxxxx-xxxxx-xxxxx-xxx' 11 | res = requests.get(avd_url + '/high-risk/list') 12 | res.encoding = 'utf-8' 13 | soup = BeautifulSoup(res.text, 'html.parser') 14 | bugs = soup.select('tr') 15 | ''' 16 | 17 | AVD编号 18 | 漏洞名称 19 | 漏洞类型 20 | 披露时间 21 | 漏洞状态 22 | 23 | ''' 24 | bug_info = bugs[1].select('td') 25 | bug_info_md5 = hashlib.md5(f'{bug_info}'.encode(encoding='UTF-8')).hexdigest() 26 | avd_id = bug_info[0].getText(strip=True) 27 | print(avd_id) 28 | if os.path.exists(avd_file): 29 | with open(avd_file, 'rb') as f: 30 | last_avd_md5 = pickle.load(f) 31 | if last_avd_md5 == bug_info_md5: 32 | print('avd_id 存在') 33 | sys.exit() 34 | if os.path.exists(avd_file) == False or last_avd_md5 != bug_info_md5: 35 | with open(avd_file, 'wb') as f: 36 | pickle.dump(bug_info_md5,f) 37 | 38 | avd_id_url = avd_url + bug_info[0].a.attrs['href'] 39 | avd_name = bug_info[1].getText(strip=True) 40 | avd_type = bug_info[2].button.attrs.get('title',bug_info[2].getText(strip=True)) 41 | avd_time = bug_info[3].getText(strip=True) 42 | avd_stat = bug_info[4].select('button')[1].attrs['title'] 43 | now = datetime.now().strftime('%Y-%m-%d') 44 | print(avd_id,avd_id_url,avd_name,avd_type,avd_time,avd_stat) 45 | md = f'# {avd_name}\n' \ 46 | f'- 编号:{avd_id}[【详情】]({avd_id_url})\n' \ 47 | f'- 类型:{avd_type}\n' \ 48 | f'- 披露:{avd_time}\n' \ 49 | f'- 状态:{avd_stat}({now})\n' 50 | sendwx = weixin.send_message_group(wxkey, 'markdown', md, '@xxxxx') 51 | print(sendwx) 52 | -------------------------------------------------------------------------------- /bug_notify/wecom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import time,datetime 4 | import requests 5 | import json 6 | import sys 7 | 8 | class WXQY: 9 | apiurl = "https://qyapi.weixin.qq.com/cgi-bin/" 10 | def send_message_group(self, key, type, data, at): 11 | at = '<@'+'><@'.join(at.split('@')[1:])+'>' 12 | if not key or not data: 13 | return 14 | params = {'msgtype' : type} 15 | if len(data.encode('utf-8')) > 4000: 16 | data = data[0:1000] 17 | if type == "text": 18 | params[type] = {'content' : data,'mentioned_list':['@all']} 19 | elif type == "markdown": 20 | params[type] = {'content' : f'{data}\n{at}'} 21 | elif type == "news": 22 | params[type] = {'articles' : data,'mentioned_mobile_list':[at]} 23 | else: 24 | params["msgtype"] = "text" 25 | params["text"] = {'content' : "不支持的消息类型 " + type} 26 | 27 | url = self.apiurl + 'webhook/send?key=%s'%(key) 28 | return self.http_request_v2(url, "POST", params=params) 29 | 30 | def http_request_v2(self, url, method="GET", headers={}, params=None): 31 | if method == "GET": 32 | response = requests.get(url) 33 | elif method == "POST": 34 | data = bytes(json.dumps(params), 'utf-8') 35 | response = requests.post(url, data= data) 36 | elif method == "DELETE": 37 | response = requests.delete(url, data= data) 38 | result = response.json() 39 | return result 40 | 41 | if __name__ == "__main__": 42 | key = sys.argv[1] 43 | info = sys.argv[2] 44 | weixin = WXQY() 45 | md = '# 实时新增用户反馈132例\n \ 46 | ## 类型:用户反馈\n \ 47 | ### 普通用户反馈:117例\n \ 48 | #### VIP用户反馈:15例\n' 49 | result = weixin.send_message_group(key, "text", info, '@all'); 50 | 51 | print(result) 52 | -------------------------------------------------------------------------------- /check_pic/.gitignore: -------------------------------------------------------------------------------- 1 | config 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | db.sqlite3 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # pyenv 78 | .python-version 79 | 80 | # celery beat schedule file 81 | celerybeat-schedule 82 | 83 | # SageMath parsed files 84 | *.sage.py 85 | 86 | # Environments 87 | .env 88 | .venv 89 | env/ 90 | venv/ 91 | ENV/ 92 | env.bak/ 93 | venv.bak/ 94 | 95 | # Spyder project settings 96 | .spyderproject 97 | .spyproject 98 | 99 | # Rope project settings 100 | .ropeproject 101 | 102 | # mkdocs documentation 103 | /site 104 | 105 | # mypy 106 | .mypy_cache/ 107 | -------------------------------------------------------------------------------- /check_pic/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/check_pic/1.jpg -------------------------------------------------------------------------------- /check_pic/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 StarsL.cn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /check_pic/README.md: -------------------------------------------------------------------------------- 1 | # check_pic 2 | ![](https://img.shields.io/pypi/pyversions/django.svg) 3 | > 图片检测、照片评分、人脸识别、鉴黄 4 | 5 | 基于腾讯优图接口,[https://open.youtu.qq.com](https://open.youtu.qq.com),请注册账号并添加应用获取AppID等信息填写到check.py中。 6 | 7 | ### install 8 | ``` 9 | pip install -U requests 10 | 11 | vim check.py 12 | 13 | appid = 'xxxxx' 14 | secret_id = 'xxxxx' 15 | secret_key = 'xxxxx' 16 | userid = 'xxxxx' 17 | ``` 18 | ### Usage 19 | ``` 20 | [root@i check_pic]#./check.py 1.jpg 21 | checking img... 22 | 图像标签识别: 23 | ['60%:女孩', '15%:写真照', '12%:头发'] 24 | 人脸分析: 25 | ['性别:女', '年龄:26', '魅力:94', '笑容:20', '不戴眼镜'] 26 | 性感检测: 27 | ['99%:性感', '100%:女性胸部', '34%:色情综合值'] 28 | ``` 29 | -------------------------------------------------------------------------------- /check_pic/TencentYoutuyun/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .youtu import YouTu 4 | from .auth import Auth 5 | 6 | 7 | -------------------------------------------------------------------------------- /check_pic/TencentYoutuyun/auth.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import time 4 | import random 5 | import hmac, hashlib 6 | import binascii 7 | import base64 8 | from TencentYoutuyun import conf 9 | 10 | class Auth(object): 11 | 12 | def __init__(self, secret_id, secret_key, appid, userid): 13 | self.AUTH_URL_FORMAT_ERROR = -1 14 | self.AUTH_SECRET_ID_KEY_ERROR = -2 15 | 16 | self._secret_id = secret_id 17 | self._secret_key = secret_key 18 | self._appid = appid 19 | self._userid = userid 20 | 21 | def app_sign(self, expired=0): 22 | if not self._secret_id or not self._secret_key: 23 | return self.AUTH_SECRET_ID_KEY_ERROR 24 | 25 | puserid = '' 26 | if self._userid != '': 27 | if len(self._userid) > 64: 28 | return self.AUTH_URL_FORMAT_ERROR 29 | puserid = self._userid 30 | 31 | now = int(time.time()) 32 | rdm = random.randint(0, 999999999) 33 | plain_text = 'a=' + self._appid + '&k=' + self._secret_id + '&e=' + str(expired) + '&t=' + str(now) + '&r=' + str(rdm) + '&u=' + puserid + '&f=' 34 | bin = hmac.new(self._secret_key.encode(), plain_text.encode(), hashlib.sha1) 35 | s = bin.hexdigest() 36 | s = binascii.unhexlify(s) 37 | s = s + plain_text.encode('ascii') 38 | signature = base64.b64encode(s).rstrip() #生成签名 39 | return signature 40 | 41 | -------------------------------------------------------------------------------- /check_pic/TencentYoutuyun/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import pkg_resources 3 | import platform 4 | 5 | API_YOUTU_END_POINT = 'http://api.youtu.qq.com/' 6 | API_YOUTU_VIP_END_POINT = 'https://vip-api.youtu.qq.com/' 7 | 8 | APPID = 'xxx' 9 | SECRET_ID = 'xxx' 10 | SECRET_KEY = 'xx' 11 | USER_ID = 'xx' 12 | 13 | _config = { 14 | 'end_point':API_YOUTU_END_POINT, 15 | 'appid':APPID, 16 | 'secret_id':SECRET_ID, 17 | 'secret_key':SECRET_KEY, 18 | 'userid':USER_ID, 19 | } 20 | 21 | def get_app_info(): 22 | return _config 23 | 24 | def set_app_info(appid=None, secret_id=None, secret_key=None, userid=None, end_point=None): 25 | if appid: 26 | _config['appid'] = appid 27 | if secret_id: 28 | _config['secret_id'] = secret_id 29 | if secret_key: 30 | _config['secret_key'] = secret_key 31 | if userid: 32 | _config['userid'] = userid 33 | if end_point: 34 | _config['end_point'] = end_point 35 | 36 | 37 | -------------------------------------------------------------------------------- /check_pic/TencentYoutuyun/youtu.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os.path 4 | import time 5 | import requests 6 | import base64 7 | import json 8 | from TencentYoutuyun import conf 9 | from .auth import Auth 10 | 11 | class YouTu(object): 12 | 13 | def __init__(self, appid, secret_id, secret_key, userid='0', end_point=conf.API_YOUTU_END_POINT): 14 | self.IMAGE_FILE_NOT_EXISTS = -1 15 | self.IMAGE_NETWORK_ERROR = -2 16 | self.IMAGE_PARAMS_ERROR = -3 17 | self.PERSON_ID_EMPTY = -4 18 | self.GROUP_ID_EMPTY = -5 19 | self.GROUP_IDS_EMPTY = -6 20 | self.IMAGES_EMPTY = -7 21 | self.FACE_IDS_EMPTY = -8 22 | self.FACE_ID_EMPTY = -9 23 | self.LIST_TYPE_INVALID = -10 24 | self.IMAGE_PATH_EMPTY = -11 25 | 26 | self.VALIDATE_DATA_EMPTY = -12 27 | self.VIDEO_PATH_EMPTY = -13 28 | self.CARD_PATH_EMPTY = -14 29 | self.IDCARD_NAME_OR_ID_EMPTY = -15 30 | 31 | self.VIDEO_FILE_NOT_EXISTS = -16 32 | self.CARD_FILE_NOT_EXISTS = -17 33 | 34 | self.UNKNOW_CARD_TYPE = -18 35 | 36 | self.EXPIRED_SECONDS = 2592000 37 | self._secret_id = secret_id 38 | self._secret_key = secret_key 39 | self._appid = appid 40 | self._userid = userid 41 | self._end_point = end_point 42 | conf.set_app_info(appid, secret_id, secret_key, userid, end_point) 43 | 44 | def get_headers(self, req_type): 45 | 46 | expired = int(time.time()) + self.EXPIRED_SECONDS 47 | auth = Auth(self._secret_id, self._secret_key, self._appid, self._userid) 48 | 49 | sign = auth.app_sign(expired) 50 | headers = { 51 | 'Authorization':sign, 52 | 'Content-Type':'text/json' 53 | } 54 | 55 | return headers 56 | 57 | def generate_res_url(self, req_type, url_type = 0): 58 | 59 | app_info = conf.get_app_info() 60 | url_api_str = '' 61 | if url_type == 4: 62 | url_api_str = 'youtu/carapi' 63 | elif url_type == 3: 64 | url_api_str = 'youtu/openliveapi' 65 | elif url_type == 2: 66 | url_api_str = 'youtu/ocrapi' 67 | elif url_type == 1: 68 | url_api_str = 'youtu/imageapi' 69 | else : 70 | url_api_str = 'youtu/api' 71 | 72 | return app_info['end_point'] + url_api_str + '/' + str(req_type) 73 | 74 | def FaceCompare(self, image_pathA, image_pathB, data_type = 0): 75 | 76 | req_type = 'facecompare' 77 | headers = self.get_headers(req_type) 78 | url = self.generate_res_url(req_type) 79 | 80 | data = { 81 | "app_id": self._appid 82 | } 83 | 84 | if len(image_pathA) == 0 or len(image_pathB) == 0: 85 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', 'session_id':'', 'similarity':0} 86 | 87 | if data_type == 0: 88 | filepathA = os.path.abspath(image_pathA) 89 | filepathB = os.path.abspath(image_pathB) 90 | 91 | if not os.path.exists(filepathA): 92 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', 'session_id':'', 'similarity':0} 93 | if not os.path.exists(filepathB): 94 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', 'session_id':'', 'similarity':0} 95 | 96 | data["imageA"] = base64.b64encode(open(filepathA, 'rb').read()).rstrip().decode('utf-8') 97 | data["imageB"] = base64.b64encode(open(filepathB, 'rb').read()).rstrip().decode('utf-8') 98 | else : 99 | data["urlA"] = image_pathA 100 | data["urlB"] = image_pathB 101 | 102 | r = {} 103 | try: 104 | r = requests.post(url, headers=headers, data = json.dumps(data)) 105 | if r.status_code != 200: 106 | return {'httpcode':r.status_code, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':'', 'session_id':'', 'similarity':0} 107 | ret = r.json() 108 | 109 | except Exception as e: 110 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'session_id':'', 'similarity':0} 111 | 112 | return ret 113 | 114 | def FaceVerify(self, person_id, image_path, data_type = 0): 115 | 116 | req_type='faceverify' 117 | headers = self.get_headers(req_type) 118 | url = self.generate_res_url(req_type) 119 | 120 | data = { 121 | "app_id": self._appid, 122 | "person_id": person_id 123 | } 124 | 125 | if len(image_path) == 0: 126 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "confidence":0, "ismatch":0, "session_id":''} 127 | 128 | if data_type == 0: 129 | filepath = os.path.abspath(image_path) 130 | if not os.path.exists(filepath): 131 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "confidence":0, "ismatch":0, "session_id":''} 132 | if len(person_id) == 0: 133 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "confidence":0, "ismatch":0, "session_id":''} 134 | 135 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 136 | else : 137 | data["url"] = image_path 138 | 139 | r = {} 140 | try: 141 | r = requests.post(url, headers=headers, data = json.dumps(data)) 142 | if r.status_code != 200: 143 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "confidence":0, "ismatch":0, "session_id":''} 144 | ret = r.json() 145 | 146 | except Exception as e: 147 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "confidence":0, "ismatch":0, "session_id":''} 148 | 149 | return ret 150 | 151 | def FaceIdentify(self, group_id, image_path, data_type = 0): 152 | 153 | req_type='faceidentify' 154 | headers = self.get_headers(req_type) 155 | url = self.generate_res_url(req_type) 156 | 157 | data = { 158 | "app_id": self._appid 159 | } 160 | 161 | if len(image_path) == 0: 162 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "session_id":'', "candidates":[{}]} 163 | 164 | if data_type == 0: 165 | filepath = os.path.abspath(image_path) 166 | if not os.path.exists(filepath): 167 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "session_id":'', "candidates":[{}]} 168 | 169 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 170 | else : 171 | data["url"] = image_path 172 | 173 | if len(group_id) == 0: 174 | return {'httpcode':0, 'errorcode':self.GROUP_ID_EMPTY, 'errormsg':'GROUP_ID_EMPTY', "session_id":'', "candidates":[{}]} 175 | else : 176 | data["group_id"] = group_id 177 | 178 | r = {} 179 | try: 180 | r = requests.post(url, headers=headers, data = json.dumps(data)) 181 | if r.status_code != 200: 182 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "session_id":'', "candidates":[{}]} 183 | ret = r.json() 184 | 185 | except Exception as e: 186 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "session_id":'', "candidates":[{}]} 187 | 188 | return ret 189 | 190 | def MultiFaceIdentify(self, group_id, group_ids, image_path, data_type = 0, topn = 5, min_size = 40): 191 | 192 | req_type='multifaceidentify' 193 | headers = self.get_headers(req_type) 194 | url = self.generate_res_url(req_type) 195 | 196 | data = { 197 | "app_id": self._appid, 198 | "topn": topn, 199 | "min_size": min_size 200 | } 201 | 202 | if len(image_path) == 0: 203 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "session_id":'', "candidates":[{}]} 204 | 205 | if data_type == 0: 206 | filepath = os.path.abspath(image_path) 207 | if not os.path.exists(filepath): 208 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "session_id":'', "candidates":[{}]} 209 | 210 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 211 | else : 212 | data["url"] = image_path 213 | 214 | if len(group_id) == 0 and len(group_ids) == 0: 215 | return {'httpcode':0, 'errorcode':self.ERROR_PARAMETER_EMPTY, 'errormsg':'ERROR_PARAMETER_EMPTY', "session_id":'', "candidates":[{}]} 216 | elif len(group_id) != 0: 217 | data["group_id"] = group_id 218 | else : 219 | data["group_ids"] = group_ids 220 | 221 | r = {} 222 | try: 223 | r = requests.post(url, headers=headers, data = json.dumps(data)) 224 | if r.status_code != 200: 225 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "session_id":'', "candidates":[{}]} 226 | ret = r.json() 227 | 228 | except Exception as e: 229 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "session_id":'', "candidates":[{}]} 230 | 231 | return ret 232 | 233 | def DetectFace(self, image_path, mode = 0, data_type = 0): 234 | 235 | req_type='detectface' 236 | headers = self.get_headers(req_type) 237 | url = self.generate_res_url(req_type) 238 | 239 | data = { 240 | "app_id": self._appid, 241 | "mode": mode 242 | } 243 | 244 | if len(image_path) == 0: 245 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "session_id":'', "image_id":'', "image_height":0, "image_width":0, "face":[{}]} 246 | 247 | if data_type == 0: 248 | filepath = os.path.abspath(image_path) 249 | if not os.path.exists(filepath): 250 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "session_id":'', "image_id":'', "image_height":0, "image_width":0, "face":[{}]} 251 | 252 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 253 | else : 254 | data["url"] = image_path 255 | 256 | r = {} 257 | try: 258 | r = requests.post(url, headers=headers, data = json.dumps(data)) 259 | if r.status_code != 200: 260 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "session_id":'', "image_id":'', "image_height":0, "image_width":0, "face":[{}]} 261 | ret = r.json() 262 | 263 | except Exception as e: 264 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "session_id":'', "image_id":'', "image_height":0, "image_width":0, "face":[{}]} 265 | 266 | return ret 267 | 268 | 269 | def NewPerson(self, person_id, image_path, group_ids, person_name= '', tag='', data_type = 0): 270 | 271 | req_type='newperson' 272 | headers = self.get_headers(req_type) 273 | url = self.generate_res_url(req_type) 274 | 275 | if len(person_id) == 0: 276 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 277 | 278 | if len(group_ids) == 0: 279 | return {'httpcode':0, 'errorcode':self.GROUP_IDS_EMPTY, 'errormsg':'GROUP_IDS_EMPTY', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 280 | 281 | if type(group_ids) != list: 282 | return {'httpcode':0, 'errorcode': self.LIST_TYPE_INVALID, 'errormsg':'LIST_TYPE_INVALID', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 283 | 284 | data = { 285 | "app_id": self._appid, 286 | "person_id" : person_id, 287 | "person_name": person_name, 288 | "group_ids": group_ids, 289 | "tag": tag 290 | } 291 | 292 | if len(image_path) == 0: 293 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 294 | 295 | if data_type == 0: 296 | filepath = os.path.abspath(image_path) 297 | if not os.path.exists(filepath): 298 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 299 | 300 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 301 | else: 302 | data["url"] = image_path 303 | 304 | r = {} 305 | try: 306 | r = requests.post(url, headers=headers, data = json.dumps(data)) 307 | if r.status_code != 200: 308 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 309 | 310 | ret = r.json() 311 | except Exception as e: 312 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "person_id":'', "suc_group":'', "suc_face":0, "session_id":0, "face_id":'', "group_ids":''} 313 | 314 | return ret 315 | 316 | def DelPerson(self, person_id) : 317 | 318 | req_type='delperson' 319 | headers = self.get_headers(req_type) 320 | url = self.generate_res_url(req_type) 321 | 322 | if len(person_id) == 0: 323 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "deleted":0, "session_id":''} 324 | 325 | data = { 326 | "app_id": self._appid, 327 | "person_id" : person_id 328 | } 329 | 330 | r = {} 331 | try: 332 | r = requests.post(url, headers=headers, data = json.dumps(data)) 333 | if r.status_code != 200: 334 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "deleted":0, "session_id":''} 335 | 336 | ret = r.json() 337 | except Exception as e: 338 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "deleted":0, "session_id":''} 339 | 340 | return ret 341 | 342 | def AddFace(self, person_id, images, tag='', data_type = 0): 343 | 344 | req_type='addface' 345 | headers = self.get_headers(req_type) 346 | url = self.generate_res_url(req_type) 347 | 348 | if len(person_id) == 0: 349 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 350 | 351 | data = { 352 | "app_id": self._appid, 353 | "person_id" : person_id, 354 | "tag" : tag 355 | } 356 | 357 | if len(images) == 0: 358 | return {'httpcode':0, 'errorcode':self.IMAGES_EMPTY, 'errormsg':'IMAGES_EMPTY', "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 359 | 360 | if type(images) != list: 361 | return {'httpcode':0, 'errorcode':self.LIST_TYPE_INVALID, 'errormsg':'LIST_TYPE_INVALID', "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 362 | 363 | if data_type == 0: 364 | images_content = [] 365 | for image in images: 366 | filepath = os.path.abspath(image) 367 | if not os.path.exists(filepath): 368 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 369 | 370 | images_content.append(base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8')) 371 | data["images"] = images_content 372 | else : 373 | data["urls"] = images 374 | 375 | r = {} 376 | try: 377 | r = requests.post(url, headers=headers, data = json.dumps(data)) 378 | if r.status_code != 200: 379 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 380 | 381 | ret = r.json() 382 | except Exception as e: 383 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "face_ids":[], "session_id":'', "added": 0, "ret_codes":[]} 384 | 385 | return ret 386 | 387 | def DelFace(self, person_id, face_ids): 388 | 389 | req_type='delface' 390 | headers = self.get_headers(req_type) 391 | url = self.generate_res_url(req_type) 392 | 393 | if len(person_id) == 0: 394 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "session_id":'', "deleted ": 0} 395 | 396 | if len(face_ids) == 0: 397 | return {'httpcode':0, 'errorcode':self.FACE_IDS_IMPTY, 'errormsg':'FACE_IDS_IMPTY', "session_id":'', "deleted ": 0} 398 | 399 | if type(face_ids) != list: 400 | return {'httpcode':0, 'errorcode':self.LIST_TYPE_INVALID, 'errormsg':'LIST_TYPE_INVALID', "session_id":'', "deleted ": 0} 401 | 402 | data = { 403 | "app_id": self._appid, 404 | "person_id":person_id, 405 | "face_ids":face_ids 406 | } 407 | 408 | r = {} 409 | try: 410 | r = requests.post(url, headers=headers, data = json.dumps(data)) 411 | if r.status_code != 200: 412 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "session_id":'', "deleted ": 0} 413 | 414 | ret = r.json() 415 | except Exception as e: 416 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "session_id":'', "deleted ": 0} 417 | 418 | return ret 419 | 420 | 421 | def SetInfo(self, person_id, person_name='', tag=''): 422 | 423 | req_type='setinfo' 424 | headers = self.get_headers(req_type) 425 | url = self.generate_res_url(req_type) 426 | url_type 427 | if len(person_id) == 0: 428 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "person_id":'', "session_id ": ''} 429 | 430 | data = { 431 | "app_id": self._appid, 432 | "person_id": person_id, 433 | "person_name": person_name, 434 | "tag":tag 435 | } 436 | 437 | r = {} 438 | try: 439 | r = requests.post(url, headers=headers, data = json.dumps(data)) 440 | if r.status_code != 200: 441 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "person_id":'', "session_id ": ''} 442 | 443 | ret = r.json() 444 | except Exception as e: 445 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "person_id":'', "session_id ": ''} 446 | 447 | return ret 448 | 449 | def GetInfo(self, person_id): 450 | 451 | req_type='getinfo' 452 | headers = self.get_headers(req_type) 453 | url = self.generate_res_url(req_type) 454 | 455 | if len(person_id) == 0: 456 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "person_id":'', "person_name ": '', "face_ids":[], "tag":'', "secret_id":''} 457 | 458 | data = { 459 | "app_id": self._appid, 460 | "person_id": person_id 461 | } 462 | 463 | r = {} 464 | try: 465 | r = requests.post(url, headers=headers, data = json.dumps(data)) 466 | if r.status_code != 200: 467 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "person_id":'', "person_name ": '', "face_ids":[], "tag":'', "secret_id":''} 468 | ret = r.json() 469 | 470 | except Exception as e: 471 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "person_id":'', "person_name ": '', "face_ids":[], "tag":'', "secret_id":''} 472 | 473 | return ret 474 | 475 | def GetGroupIds(self): 476 | 477 | req_type='getgroupids' 478 | headers = self.get_headers(req_type) 479 | url = self.generate_res_url(req_type) 480 | 481 | data = { 482 | "app_id": self._appid 483 | } 484 | 485 | r = {} 486 | try: 487 | r = requests.post(url, headers=headers, data = json.dumps(data)) 488 | if r.status_code != 200: 489 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "group_ids":[]} 490 | 491 | ret = r.json() 492 | except Exception as e: 493 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "group_ids":[]} 494 | 495 | return ret 496 | 497 | def GetPersonIds(self, group_id) : 498 | 499 | req_type='getpersonids' 500 | headers = self.get_headers(req_type) 501 | url = self.generate_res_url(req_type) 502 | 503 | if len(group_id) == 0: 504 | return {'httpcode':0, 'errorcode':self.GROUP_ID_EMPTY, 'errormsg':'GROUP_ID_EMPTY', "person_ids":[]} 505 | 506 | data = { 507 | "app_id": self._appid, 508 | "group_id": group_id 509 | } 510 | 511 | r = {} 512 | try: 513 | r = requests.post(url, headers=headers, data = json.dumps(data)) 514 | if r.status_code != 200: 515 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "person_ids":[]} 516 | 517 | ret = r.json() 518 | except Exception as e: 519 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "person_ids":[]} 520 | 521 | return ret 522 | 523 | def GetFaceIds(self, person_id): 524 | 525 | req_type='getfaceids' 526 | headers = self.get_headers(req_type) 527 | url = self.generate_res_url(req_type) 528 | 529 | if len(person_id) == 0: 530 | return {'httpcode':0, 'errorcode':self.PERSON_ID_EMPTY, 'errormsg':'PERSON_ID_EMPTY', "face_ids":[]} 531 | 532 | data = { 533 | "app_id": self._appid, 534 | "person_id": person_id 535 | } 536 | 537 | r = {} 538 | try: 539 | r = requests.post(url, headers=headers, data = json.dumps(data)) 540 | if r.status_code != 200: 541 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "face_ids":[]} 542 | 543 | ret = r.json() 544 | except Exception as e: 545 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "face_ids":[]} 546 | 547 | return ret 548 | 549 | def GetFaceInfo(self, face_id): 550 | 551 | req_type='getfaceinfo' 552 | headers = self.get_headers(req_type) 553 | url = self.generate_res_url(req_type) 554 | 555 | if len(face_id) == 0: 556 | return {'httpcode':0, 'errorcode':self.FACE_ID_EMPTY, 'errormsg':'FACE_ID_EMPTY', "face_info":[]} 557 | 558 | data = { 559 | "app_id": self._appid, 560 | "face_id": face_id 561 | } 562 | 563 | r = {} 564 | try: 565 | r = requests.post(url, headers=headers, data = json.dumps(data)) 566 | if r.status_code != 200: 567 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "face_info":[]} 568 | 569 | ret = r.json() 570 | except Exception as e: 571 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "face_info":[]} 572 | 573 | return ret 574 | 575 | def FaceShape(self, image_path, mode = 0, data_type = 0): 576 | 577 | req_type='faceshape' 578 | headers = self.get_headers(req_type) 579 | url = self.generate_res_url(req_type) 580 | 581 | data = { 582 | "app_id": self._appid, 583 | "mode": mode 584 | } 585 | 586 | if len(image_path) == 0: 587 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', "face_shape":[{}], "image_height":0, "image_width":0, "session_id":''} 588 | 589 | if data_type == 0: 590 | filepath = os.path.abspath(image_path) 591 | if not os.path.exists(filepath): 592 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS', "face_shape":[{}], "image_height":0, "image_width":0, "session_id":''} 593 | 594 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 595 | else: 596 | data["url"] = image_path 597 | 598 | r = {} 599 | try: 600 | r = requests.post(url, headers=headers, data = json.dumps(data)) 601 | if r.status_code != 200: 602 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':'', "face_shape":[{}], "image_height":0, "image_width":0, "session_id":''} 603 | 604 | ret = r.json() 605 | except Exception as e: 606 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), "face_shape":[{}], "image_height":0, "image_width":0, "session_id":''} 607 | 608 | return ret 609 | 610 | def fuzzydetect(self, image_path, data_type = 0, seq = ''): 611 | 612 | req_type='fuzzydetect' 613 | headers = self.get_headers(req_type) 614 | url = self.generate_res_url(req_type, 1) 615 | 616 | data = { 617 | "app_id": self._appid, 618 | "seq": seq 619 | } 620 | 621 | if len(image_path) == 0: 622 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 623 | 624 | if data_type == 0: 625 | filepath = os.path.abspath(image_path) 626 | if not os.path.exists(filepath): 627 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 628 | 629 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 630 | else: 631 | data["url"] = image_path 632 | 633 | r = {} 634 | try: 635 | r = requests.post(url, headers=headers, data = json.dumps(data)) 636 | if r.status_code != 200: 637 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 638 | 639 | ret = r.json() 640 | except Exception as e: 641 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 642 | 643 | return ret 644 | 645 | def fooddetect(self, image_path, data_type = 0, seq = ''): 646 | 647 | req_type='fooddetect' 648 | headers = self.get_headers(req_type) 649 | url = self.generate_res_url(req_type, 1) 650 | 651 | data = { 652 | "app_id": self._appid, 653 | "seq": seq 654 | } 655 | 656 | if len(image_path) == 0: 657 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 658 | 659 | if data_type == 0: 660 | filepath = os.path.abspath(image_path) 661 | if not os.path.exists(filepath): 662 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 663 | 664 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 665 | else: 666 | data["url"] = image_path 667 | 668 | r = {} 669 | try: 670 | r = requests.post(url, headers=headers, data = json.dumps(data)) 671 | if r.status_code != 200: 672 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 673 | 674 | ret = r.json() 675 | except Exception as e: 676 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 677 | 678 | return ret 679 | 680 | 681 | 682 | def imagetag(self, image_path, data_type = 0, seq = ''): 683 | 684 | req_type='imagetag' 685 | headers = self.get_headers(req_type) 686 | url = self.generate_res_url(req_type, 1) 687 | 688 | data = { 689 | "app_id": self._appid, 690 | "seq": seq 691 | } 692 | 693 | if len(image_path) == 0: 694 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 695 | 696 | if data_type == 0: 697 | filepath = os.path.abspath(image_path) 698 | if not os.path.exists(filepath): 699 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 700 | 701 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 702 | else: 703 | data["url"] = image_path 704 | 705 | r = {} 706 | try: 707 | r = requests.post(url, headers=headers, data = json.dumps(data)) 708 | if r.status_code != 200: 709 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 710 | 711 | ret = r.json() 712 | except Exception as e: 713 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 714 | 715 | return ret 716 | 717 | def imageporn(self, image_path, data_type = 0, seq = ''): 718 | 719 | req_type='imageporn' 720 | headers = self.get_headers(req_type) 721 | url = self.generate_res_url(req_type, 1) 722 | 723 | data = { 724 | "app_id": self._appid, 725 | "seq": seq 726 | } 727 | 728 | if len(image_path) == 0: 729 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 730 | 731 | if data_type == 0: 732 | filepath = os.path.abspath(image_path) 733 | if not os.path.exists(filepath): 734 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 735 | 736 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 737 | else: 738 | data["url"] = image_path 739 | 740 | r = {} 741 | try: 742 | r = requests.post(url, headers=headers, data = json.dumps(data)) 743 | if r.status_code != 200: 744 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 745 | 746 | ret = r.json() 747 | except Exception as e: 748 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 749 | 750 | return ret 751 | 752 | def imageterrorism(self, image_path, data_type = 0, seq = ''): 753 | 754 | req_type='imageterrorism' 755 | headers = self.get_headers(req_type) 756 | url = self.generate_res_url(req_type, 1) 757 | 758 | data = { 759 | "app_id": self._appid, 760 | "seq": seq 761 | } 762 | 763 | if len(image_path) == 0: 764 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 765 | 766 | if data_type == 0: 767 | filepath = os.path.abspath(image_path) 768 | if not os.path.exists(filepath): 769 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 770 | 771 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 772 | else: 773 | data["url"] = image_path 774 | 775 | r = {} 776 | try: 777 | r = requests.post(url, headers=headers, data = json.dumps(data)) 778 | if r.status_code != 200: 779 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 780 | 781 | ret = r.json() 782 | except Exception as e: 783 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 784 | 785 | return ret 786 | 787 | def carclassify(self, image_path, data_type = 0, seq = ''): 788 | 789 | req_type='carclassify' 790 | headers = self.get_headers(req_type) 791 | url = self.generate_res_url(req_type, 4) 792 | 793 | data = { 794 | "app_id": self._appid, 795 | "seq": seq 796 | } 797 | 798 | if len(image_path) == 0: 799 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 800 | 801 | if data_type == 0: 802 | filepath = os.path.abspath(image_path) 803 | if not os.path.exists(filepath): 804 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 805 | 806 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 807 | else: 808 | data["url"] = image_path 809 | 810 | r = {} 811 | try: 812 | r = requests.post(url, headers=headers, data = json.dumps(data)) 813 | if r.status_code != 200: 814 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 815 | 816 | ret = r.json() 817 | except Exception as e: 818 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 819 | 820 | return ret 821 | 822 | def idcardocr(self, image_path, data_type = 0, card_type = 1 ,seq = ''): 823 | 824 | req_type='idcardocr' 825 | headers = self.get_headers(req_type) 826 | url = self.generate_res_url(req_type, 2) 827 | 828 | data = { 829 | "app_id": self._appid, 830 | "seq": seq, 831 | "card_type":card_type 832 | } 833 | 834 | if len(image_path) == 0: 835 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 836 | 837 | if data_type == 0: 838 | filepath = os.path.abspath(image_path) 839 | if not os.path.exists(filepath): 840 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 841 | 842 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 843 | else: 844 | data["url"] = image_path 845 | r = {} 846 | try: 847 | r = requests.post(url, headers=headers, data = json.dumps(data)) 848 | if r.status_code != 200: 849 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 850 | 851 | ret = r.json() 852 | except Exception as e: 853 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 854 | 855 | return ret 856 | 857 | def driverlicenseocr(self, image_path, data_type = 0, proc_type = 0, seq = ''): 858 | 859 | req_type='driverlicenseocr' 860 | headers = self.get_headers(req_type) 861 | url = self.generate_res_url(req_type, 2) 862 | data = { 863 | "app_id": self._appid, 864 | "session_id": seq, 865 | "type": proc_type 866 | } 867 | 868 | if len(image_path) == 0: 869 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 870 | 871 | if data_type == 0: 872 | filepath = os.path.abspath(image_path) 873 | if not os.path.exists(filepath): 874 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 875 | 876 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 877 | else: 878 | data["url"] = image_path 879 | 880 | r = {} 881 | try: 882 | r = requests.post(url, headers=headers, data = json.dumps(data)) 883 | if r.status_code != 200: 884 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 885 | 886 | ret = r.json() 887 | except Exception as e: 888 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 889 | 890 | return ret 891 | 892 | def bcocr(self, image_path, data_type = 0, seq = ''): 893 | 894 | req_type='bcocr' 895 | headers = self.get_headers(req_type) 896 | url = self.generate_res_url(req_type, 2) 897 | data = { 898 | "app_id": self._appid, 899 | "session_id": seq, 900 | } 901 | 902 | if len(image_path) == 0: 903 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 904 | 905 | if data_type == 0: 906 | filepath = os.path.abspath(image_path) 907 | if not os.path.exists(filepath): 908 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 909 | 910 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 911 | else: 912 | data["url"] = image_path 913 | 914 | r = {} 915 | try: 916 | r = requests.post(url, headers=headers, data = json.dumps(data)) 917 | if r.status_code != 200: 918 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 919 | 920 | ret = r.json() 921 | except Exception as e: 922 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 923 | 924 | return ret 925 | 926 | def generalocr(self, image_path, data_type = 0, seq = ''): 927 | 928 | req_type='generalocr' 929 | headers = self.get_headers(req_type) 930 | url = self.generate_res_url(req_type, 2) 931 | data = { 932 | "app_id": self._appid, 933 | "session_id": seq, 934 | } 935 | 936 | if len(image_path) == 0: 937 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 938 | 939 | if data_type == 0: 940 | filepath = os.path.abspath(image_path) 941 | if not os.path.exists(filepath): 942 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 943 | 944 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 945 | else: 946 | data["url"] = image_path 947 | 948 | r = {} 949 | try: 950 | r = requests.post(url, headers=headers, data = json.dumps(data)) 951 | if r.status_code != 200: 952 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 953 | 954 | ret = r.json() 955 | except Exception as e: 956 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 957 | 958 | return ret 959 | 960 | def creditcardocr(self, image_path, data_type = 0, seq = ''): 961 | 962 | req_type='creditcardocr' 963 | headers = self.get_headers(req_type) 964 | url = self.generate_res_url(req_type, 2) 965 | data = { 966 | "app_id": self._appid, 967 | "session_id": seq, 968 | } 969 | 970 | if len(image_path) == 0: 971 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 972 | 973 | if data_type == 0: 974 | filepath = os.path.abspath(image_path) 975 | if not os.path.exists(filepath): 976 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 977 | 978 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 979 | else: 980 | data["url"] = image_path 981 | 982 | r = {} 983 | try: 984 | r = requests.post(url, headers=headers, data = json.dumps(data)) 985 | if r.status_code != 200: 986 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 987 | 988 | ret = r.json() 989 | except Exception as e: 990 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 991 | 992 | return ret 993 | 994 | def bizlicenseocr(self, image_path, data_type = 0, seq = ''): 995 | 996 | req_type='bizlicenseocr' 997 | headers = self.get_headers(req_type) 998 | url = self.generate_res_url(req_type, 2) 999 | data = { 1000 | "app_id": self._appid, 1001 | "session_id": seq, 1002 | } 1003 | 1004 | if len(image_path) == 0: 1005 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 1006 | 1007 | if data_type == 0: 1008 | filepath = os.path.abspath(image_path) 1009 | if not os.path.exists(filepath): 1010 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 1011 | 1012 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 1013 | else: 1014 | data["url"] = image_path 1015 | 1016 | r = {} 1017 | try: 1018 | r = requests.post(url, headers=headers, data = json.dumps(data)) 1019 | if r.status_code != 200: 1020 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 1021 | 1022 | ret = r.json() 1023 | except Exception as e: 1024 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 1025 | 1026 | return ret 1027 | 1028 | def plateocr(self, image_path, data_type = 0, seq = ''): 1029 | 1030 | req_type='plateocr' 1031 | headers = self.get_headers(req_type) 1032 | url = self.generate_res_url(req_type, 2) 1033 | data = { 1034 | "app_id": self._appid, 1035 | "session_id": seq, 1036 | } 1037 | 1038 | if len(image_path) == 0: 1039 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY'} 1040 | 1041 | if data_type == 0: 1042 | filepath = os.path.abspath(image_path) 1043 | if not os.path.exists(filepath): 1044 | return {'httpcode':0, 'errorcode':self.IMAGE_FILE_NOT_EXISTS, 'errormsg':'IMAGE_FILE_NOT_EXISTS'} 1045 | 1046 | data["image"] = base64.b64encode(open(filepath, 'rb').read()).rstrip().decode('utf-8') 1047 | else: 1048 | data["url"] = image_path 1049 | 1050 | r = {} 1051 | try: 1052 | r = requests.post(url, headers=headers, data = json.dumps(data)) 1053 | if r.status_code != 200: 1054 | return {'httpcode':r.status_code, 'errorcode':'', 'errormsg':''} 1055 | 1056 | ret = r.json() 1057 | except Exception as e: 1058 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e)} 1059 | 1060 | return ret 1061 | 1062 | def livegetfour(self, seq = ''): 1063 | 1064 | req_type = 'livegetfour' 1065 | headers = self.get_headers(req_type) 1066 | url = self.generate_res_url(req_type, 3) 1067 | 1068 | data = { 1069 | 'app_id' : self._appid, 1070 | 'seq' : seq 1071 | } 1072 | 1073 | r = {} 1074 | try: 1075 | r = requests.post(url, headers = headers, data = json.dumps(data)) 1076 | if r.status_code != 200: 1077 | return {'httpcode' : r.status_code, 'errorcode' : '', 'errormsg' : '', 'validate_data' : ''} 1078 | ret = r.json() 1079 | except Exception as e: 1080 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'validate_data' : ''} 1081 | 1082 | return ret 1083 | 1084 | def livedetectfour(self, validate_data, video_path, seq = '', card_path = '', compare_flag = False): 1085 | 1086 | req_type = 'livedetectfour' 1087 | headers = self.get_headers(req_type) 1088 | url = self.generate_res_url(req_type, 3) 1089 | 1090 | data = { 1091 | 'app_id' : self._appid, 1092 | 'seq' : seq 1093 | } 1094 | 1095 | if len(validate_data) == 0: 1096 | return {'httpcode' : 0, 'errorcode' : self.VALIDATE_DATA_EMPTY, 'errormsg' : 'VALIDATE_DATA_EMPTY', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1097 | 1098 | if len(video_path) == 0: 1099 | return {'httpcode' : 0, 'errorcode' : self.VIDEO_PATH_EMPTY, 'errormsg' : 'VIDEO_PATH_EMPTY,', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1100 | 1101 | if compare_flag == True and len(card_path) == 0: 1102 | return {'httpcode' : 0, 'errorcode' : self.CARD_PATH_EMPTY, 'errormsg' : 'CARD_PATH_EMPTY', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1103 | 1104 | videofile = os.path.abspath(video_path) 1105 | if not os.path.exists(videofile): 1106 | return {'httpcode' : 0, 'errorcode' : self.VIDEO_FILE_NOT_EXISTS, 'errormsg' : 'VIDEO_FILE_NOT_EXISTS', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1107 | else: 1108 | data["video"] = base64.b64encode(open(videofile, 'rb').read()).rstrip() 1109 | 1110 | 1111 | cardfile = os.path.abspath(card_path) 1112 | if compare_flag == True : 1113 | if not os.path.exists(cardfile): 1114 | return {'httpcode' : 0, 'errorcode' : self.CARD_FILE_NOT_EXISTS, 'errormsg' : 'CARD_FILE_NOT_EXISTS', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1115 | else: 1116 | data["card"] = base64.b64encode(open(cardfile, 'rb').read()).rstrip() 1117 | 1118 | data['validate_data'] = validate_data 1119 | data['compare_flag'] = compare_flag 1120 | 1121 | r = {} 1122 | try: 1123 | r = requests.post(url, headers = headers, data = json.dumps(data)) 1124 | if r.status_code != 200: 1125 | return {'httpcode' : r.status_code, 'errorcode' : '', 'errormsg' : '', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1126 | ret = r.json() 1127 | except Exception as e: 1128 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'photo' : ''} 1129 | 1130 | return ret 1131 | 1132 | def idcardlivedetectfour(self, idcard_number, idcard_name, validate_data, video_path, seq = ''): 1133 | 1134 | req_type = 'idcardlivedetectfour' 1135 | headers = self.get_headers(req_type) 1136 | url = self.generate_res_url(req_type, 3) 1137 | 1138 | data = { 1139 | 'app_id' : self._appid, 1140 | 'seq' : seq 1141 | } 1142 | 1143 | if len(idcard_name) == 0 or len(idcard_number) == 0: 1144 | return {'httpcode' : 0, 'errorcode' : self.IDCARD_NAME_OR_ID_EMPTY , 'errormsg' : 'IDCARD_NAME_OR_ID_EMPTY ', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1145 | 1146 | if len(validate_data) == 0: 1147 | return {'httpcode' : 0, 'errorcode' : self.VALIDATE_DATA_EMPTY, 'errormsg' : 'VALIDATE_DATA_EMPTY', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1148 | 1149 | if len(video_path) == 0: 1150 | return {'httpcode' : 0, 'errorcode' : self.VIDEO_PATH_EMPTY, 'errormsg' : 'VIDEO_PATH_EMPTY', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1151 | 1152 | videofile = os.path.abspath(video_path) 1153 | if not os.path.exists(videofile): 1154 | return {'httpcode' : 0, 'errorcode' : self.VIDEO_FILE_NOT_EXISTS, 'errormsg' : 'VIDEO_FILE_NOT_EXISTS', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1155 | else: 1156 | data["video"] = base64.b64encode(open(videofile, 'rb').read()).rstrip() 1157 | 1158 | data['idcard_number'] = idcard_number 1159 | data['idcard_name'] = idcard_name 1160 | data['validate_data'] = validate_data 1161 | 1162 | r = {} 1163 | try: 1164 | r = requests.post(url, headers = headers, data = json.dumps(data)) 1165 | if r.status_code != 200 : 1166 | return {'httpcode' : r.status_code, 'errorcode' : '', 'errormsg' : '', 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1167 | ret = r.json() 1168 | except Exception as e: 1169 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'live_status' : '', 'live_msg' : '', 'compare_status' : '', 'compare_msg' : '', 'sim' : 0, 'video_photo' : ''} 1170 | 1171 | return ret 1172 | 1173 | def idcardfacecompare(self, idcard_number, idcard_name, image_path, data_type = 0 , session_id = ''): 1174 | 1175 | req_type = 'idcardfacecompare' 1176 | headers = self.get_headers(req_type) 1177 | url = self.generate_res_url(req_type, 3) 1178 | 1179 | data = { 1180 | 'app_id' : self._appid, 1181 | 'session_id' : session_id 1182 | } 1183 | 1184 | if len(idcard_name) == 0 or len(idcard_number) == 0 : 1185 | return {'httpcode' : 0, 'errorcode' : self.IDCARD_NAME_OR_ID_EMPTY , 'errormsg' : 'IDCARD_NAME_OR_ID_EMPTY ', 'similarity' : '', 'session_id' : session_id} 1186 | 1187 | if len(image_path) == 0 : 1188 | return {'httpcode':0, 'errorcode':self.IMAGE_PATH_EMPTY, 'errormsg':'IMAGE_PATH_EMPTY', 'similarity' : '', 'session_id' : session_id} 1189 | 1190 | if data_type == 0: 1191 | imagefile = os.path.abspath(image_path) 1192 | if not os.path.exists(imagefile): 1193 | return {'httpcode' : 0, 'errorcode' : self.IMAGE_FILE_NOT_EXISTS, 'errormsg' : 'IMAGE_FILE_NOT_EXISTS', 'similarity' : '', 'session_id' : session_id} 1194 | else: 1195 | data['image'] = base64.b64encode(open(imagefile, 'rb').read()).rstrip() 1196 | else: 1197 | data['url'] = image_path 1198 | data['idcard_number'] = idcard_number 1199 | data['idcard_name'] = idcard_name 1200 | 1201 | r = {} 1202 | try: 1203 | r = requests.post(url, headers = headers, data = json.dumps(data)) 1204 | if r.status_code != 200: 1205 | return {'httpcode' : r.status_code, 'errorcode' : '', 'errormsg' : '', 'similarity' : '', 'session_id' : session_id} 1206 | ret = r.json() 1207 | except Exception as e: 1208 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'similarity' : '', 'session_id' : session_id} 1209 | 1210 | return ret 1211 | 1212 | def ValidateIdcard(self, idcard_number, idcard_name, seq = "default"): 1213 | 1214 | req_type = 'validateidcard' 1215 | headers = self.get_headers(req_type) 1216 | url = self.generate_res_url(req_type, 3) 1217 | 1218 | data = { 1219 | "app_id": self._appid, 1220 | "idcard_number": idcard_number, 1221 | "idcard_name": idcard_name, 1222 | "seq": seq 1223 | } 1224 | 1225 | r = {} 1226 | try: 1227 | r = requests.post(url, headers=headers, data = json.dumps(data)) 1228 | if r.status_code != 200: 1229 | return {'httpcode':r.status_code, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':'', 'session_id':''} 1230 | ret = r.json() 1231 | 1232 | except Exception as e: 1233 | return {'httpcode':0, 'errorcode':self.IMAGE_NETWORK_ERROR, 'errormsg':str(e), 'session_id':''} 1234 | 1235 | return ret 1236 | 1237 | 1238 | -------------------------------------------------------------------------------- /check_pic/check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #-*- coding: utf-8 -*- 3 | import sys,os 4 | import configparser 5 | import TencentYoutuyun 6 | 7 | if len(sys.argv) == 2 : 8 | print ("checking img...") 9 | img = sys.argv[1] 10 | if os.access(img, os.R_OK) == False: 11 | print ("指定的路径不存在") 12 | sys.exit() 13 | else: 14 | print ("请指定一张图片文件路径") 15 | sys.exit() 16 | 17 | def getConfig(section, key): 18 | config = configparser.ConfigParser() 19 | path = os.path.split(os.path.realpath(__file__))[0] + '/config' 20 | config.read(path) 21 | return config.get(section, key) 22 | 23 | appid = getConfig("appinfo","appid") 24 | secret_id = getConfig("appinfo","secret_id") 25 | secret_key = getConfig("appinfo","secret_key") 26 | userid = getConfig("appinfo","userid") 27 | end_point = TencentYoutuyun.conf.API_YOUTU_END_POINT 28 | youtu = TencentYoutuyun.YouTu(appid, secret_id, secret_key, userid, end_point) 29 | 30 | print("图像标签识别:") 31 | tag_list=youtu.imagetag(img)['tags'] 32 | new_tag=[] 33 | for i in tag_list: 34 | new_tag.append("{}%:{}".format(i['tag_confidence'],i['tag_name'].encode('iso8859-1').decode('utf-8'))) 35 | 36 | new_tag.sort(reverse=True) 37 | print(new_tag) 38 | 39 | print("人脸分析:") 40 | face=youtu.DetectFace(img) 41 | if len(face['face']) == 0: 42 | print("非人脸图片") 43 | else: 44 | # sex = {0:"女",100:"男"} 45 | glass = {0:"不戴眼镜",1:"戴眼镜",2:"戴墨镜"} 46 | face_dict=face['face'][0] 47 | if face_dict['gender'] <= 50: 48 | sex = "女" 49 | else: 50 | sex = "男" 51 | face_info = ("性别:{},年龄:{},魅力:{},笑容:{},{}".format \ 52 | (sex,face_dict['age'],face_dict['beauty'],face_dict['expression'],glass[face_dict['glasses']])).split(",") 53 | print(face_info) 54 | 55 | print("性感检测:") 56 | hsex = {"normal":"正常","hot":"性感","porn":"色情图像","normal_level":"正常级别","breast":"胸","female-breast":"女性胸部","ass":"屁股","bare-body":"裸露身体","unreal-hot-people":"非真实的性感人物","porn-level":"色情级别","normal_hot_porn":"色情综合值"} 57 | sexp=youtu.imageporn(img)['tags'] 58 | sex_info = ["{}%:{}".format(i['tag_confidence'],hsex[i['tag_name']]) for i in sexp if i['tag_confidence'] > 9] 59 | print(sex_info) 60 | -------------------------------------------------------------------------------- /check_pic/requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.21.0 2 | configparser==3.5.0 3 | -------------------------------------------------------------------------------- /etcd2consul/333.csv: -------------------------------------------------------------------------------- 1 | service,env,ip,domain,port,usr,passwd 2 | mysql,sit,192.168.200.227,mysql.sit.server,3306,wluser,dyei1@SW 3 | redis,sit,192.168.200.227,redis.sit.server,6379,,sje1gDK 4 | rabbitmq,sit,192.168.200.227,mq.sit.server,5672,cg,d9a1kqb 5 | riak-http,sit,192.168.200.227,riak-kv.sit.server,8098,, 6 | riak-tcp,sit,192.168.200.227,riak-kv.sit.server,8087,, 7 | mysql,uat,10.200.124.181,mysql.uat.server,3306,wluser,dhs611DE 8 | redis,uat,10.200.124.181,redis.uat.server,6379,,38shiav4 9 | rabbitmq,uat,10.200.124.181,mq.uat.server,5672,wl,sjh1y26d 10 | riak-http,uat,10.200.124.181,riak-kv.uat.server,8098,, 11 | riak-tcp,uat,10.200.124.181,riak-kv.uat.server,8087,, 12 | api,pro,10.200.78.34,api.cg.server,9090,, 13 | mysql-m,pro,10.200.78.100,mysql-m.cg.server,3306,usr_wladmin,ios0DaC1f9yj5 14 | mysql-s,pro,10.200.78.101,mysql-s.cg.server,3306,usr_wladmin,ios0DaC1f9yj5 15 | rabbitmq,pro,10.200.78.90,mq.cg.server,5672,cg,s7ay147qo 16 | redis,pro,10.200.78.40,redis.cg.server,6379,,ye2i1ab0f 17 | riak-http,pro,10.200.78.50,riak-kv.cg.server,8098,, 18 | riak-tcp,pro,10.200.78.50,riak-kv.cg.server,8087,, 19 | -------------------------------------------------------------------------------- /etcd2consul/README.md: -------------------------------------------------------------------------------- 1 | #### 项目中使用的把etcd数据导入到consul的KV和SERVICE,仅供参考。 2 | ``` 3 | #add 4 | svc导入consul service 5 | salt导入consul service 6 | consul kv导入consul service 7 | ``` 8 | -------------------------------------------------------------------------------- /etcd2consul/consulkv2service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | # -*- coding:utf-8 -*- 3 | import requests,json,base64 4 | service_list = [] 5 | headers = {"X-Consul-Token": "xxxxxxxx"} 6 | req = requests.get("http://192.168.200.60:8500/v1/kv/nginx?recurse=ture", headers=headers).json() 7 | for i in req: 8 | k=i['Key'] 9 | name = f"SV_{k.split('/')[2]}" 10 | if name not in ['SV_fg_dev','SV_fg_pdev','SV_fg_sit','SV_wl_sit']: 11 | continue 12 | v=json.loads(base64.b64decode(i['Value'])) 13 | id = k.split('/')[4] 14 | tags = [k.split('/')[3], f'{v["ndomain"]}:{v["nport"]}'] 15 | address = v['sip'] 16 | port = int(v['sport']) 17 | data = { 18 | "id": id, 19 | "name": name, 20 | "tags": tags, 21 | "address": address, 22 | "port": port, 23 | "check": { 24 | "name": id, 25 | "tcp": f"{address}:{port}", 26 | "interval": "10s" 27 | } 28 | } 29 | reg = requests.put("http://192.168.200.60:8500/v1/agent/service/register", headers=headers, data=json.dumps(data)) 30 | print(name,reg.status_code,reg.text) 31 | -------------------------------------------------------------------------------- /etcd2consul/csv_base_service2consul_service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | # -*- coding:utf-8 -*- 3 | import requests,json,csv 4 | csvFile = open("333.csv", "r") 5 | dict_reader = csv.DictReader(csvFile) 6 | service_list = [] 7 | headers = {"X-Consul-Token": "xxxxxxxx"} 8 | for i in dict_reader: 9 | service_list.append(i) 10 | for i in service_list: 11 | meta_dict = {} 12 | for k,v in i.items(): 13 | meta_dict[k] = v 14 | 15 | data = { 16 | "id": f"{i['env']}/{i['service']}", 17 | "name": i['env'], 18 | "tags": [i['service']], 19 | "address": i['ip'], 20 | "port": int(i['port']), 21 | "Meta": meta_dict, 22 | "check": { 23 | "name": f"{i['env']} {i['service']}", 24 | "tcp": f"{i['ip']}:{i['port']}", 25 | "interval": "10s" 26 | } 27 | } 28 | reg = requests.put("http://192.168.200.60:8500/v1/agent/service/register", headers=headers, data=json.dumps(data)) 29 | print(f"{i['env']}/{i['service']}",reg.status_code,reg.text) 30 | reg = requests.put(f"http://192.168.200.60:8500/v1/kv/hosts/{i['env']}/{i['domain']}", headers=headers,data=i['ip']) 31 | print(f"{i['domain']}={i['ip']}",reg.status_code,reg.text) 32 | 33 | """ 34 | 注册 35 | curl --request PUT --data @playload.json http://192.168.200.60:8500/v1/agent/service/register 36 | 37 | 删除 38 | curl --request PUT http://192.168.200.60:8500/v1/agent/service/deregister/DEVtest 39 | 40 | 查询所有服务详情 41 | curl http://192.168.200.60:8500/v1/agent/services|python -m json.tool 42 | 43 | 查询单个服务(精简) 44 | curl http://192.168.200.60:8500/v1/agent/service/dev/redis|python -m json.tool 45 | ------ 46 | 查询所有服务列表(精简) 47 | curl http://192.168.200.60:8500/v1/catalog/services|python -m json.tool 48 | 49 | 查询指定环境的所有服务(详细) 50 | curl http://192.168.200.60:8500/v1/catalog/service/dev|python -m json.tool 51 | 52 | 查询指定环境的单个服务(详细) 53 | curl http://192.168.200.60:8500/v1/catalog/service/dev?tag=redis|python -m json.tool 54 | 55 | K/V 56 | curl -H "X-Consul-Token: xxxxxxxxxxxxx" -X PUT -d 'test' http://192.168.200.60:8500/v1/kv/web/key1 57 | curl -H "X-Consul-Token: xxxxxxxxxxxxx" --request DELETE http://192.168.200.60:8500/v1/kv/web/?recurse=ture 58 | """ 59 | -------------------------------------------------------------------------------- /etcd2consul/etcd2consul_kv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os,linecache 3 | import requests,json,csv 4 | conf = os.system("etcdctl get --prefix /nginx/>/tmp/php.etcd") 5 | count = len(open('/tmp/php.etcd').readlines()) 6 | php = {} 7 | for i in range(1,count+1,2): 8 | fst_line=linecache.getline('/tmp/php.etcd',i).strip('\n') 9 | sec_line=linecache.getline('/tmp/php.etcd',i+1).strip('\n') 10 | php[fst_line] = sec_line 11 | 12 | headers = {"X-Consul-Token": "xxxxxxxx"} 13 | for k,v in php.items(): 14 | reg = requests.put(f"http://192.168.200.60:8500/v1/kv{k}", headers=headers,data=v) 15 | print(k,v,reg.status_code,reg.text) 16 | -------------------------------------------------------------------------------- /etcd2consul/etcd2consul_service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os,linecache 3 | import requests,json,csv 4 | conf = os.system("etcdctl get --prefix /nginx/|grep -A1 -E 'fg_sit|fg_dev|fg_pdev|wl_sit'|grep -v '\-\-' >/tmp/sgame") 5 | count = len(open('/tmp/sgame').readlines()) 6 | game = {} 7 | for i in range(1,count+1,2): 8 | fst_line=linecache.getline('/tmp/sgame',i).strip('\n') 9 | sec_line=linecache.getline('/tmp/sgame',i+1).strip('\n') 10 | game[fst_line] = sec_line 11 | 12 | headers = {"X-Consul-Token": "xxxxxxxx"} 13 | for k,v in game.items(): 14 | gameinfo = json.loads(v) 15 | name = f"game_{k.split('/')[3]}" 16 | id = k.split('/')[5] 17 | tags = [k.split('/')[4], f'{gameinfo["ndomain"]}:{gameinfo["nport"]}'] 18 | address = gameinfo['sip'] 19 | port = int(gameinfo['sport']) 20 | 21 | data = { 22 | "id": id, 23 | "name": name, 24 | "tags": tags, 25 | "address": address, 26 | "port": port, 27 | "check": { 28 | "name": name, 29 | "tcp": f"{address}:{port}", 30 | "interval": "10s" 31 | } 32 | } 33 | reg = requests.put("http://192.168.200.60:8500/v1/agent/service/register", headers=headers, data=json.dumps(data)) 34 | print(name,reg.status_code,reg.text) 35 | -------------------------------------------------------------------------------- /etcd2consul/salt2consul_service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | # -*- coding:utf-8 -*- 3 | import os,re,requests,json 4 | headers = {"X-Consul-Token": "xxxxxxxx"} 5 | iplist=os.popen('salt \* grains.item ipv4 --out=txt').readlines() 6 | host_dict = {} 7 | for i in iplist: 8 | hostname = i.split(':')[0] 9 | ips = re.sub('[u\'\ ]','',re.split('.*\[(.*)\].*',i)[1]).split(",") 10 | ip = [j for j in ips if j.startswith('192.168.2') or j.startswith('192.168.10.')][0] 11 | host_dict[hostname] = ip 12 | print(host_dict) 13 | del host_dict['openshift.201-all01'] 14 | del host_dict['openshift.203-all02'] 15 | del host_dict['openshift.202-all03'] 16 | #host_dict = {} 17 | #host_dict = {'openshift.201-all01':'192.168.200.201','openshift.203-all02':'192.168.200.203','openshift.202-all03':'192.168.200.202'} 18 | for k,v in host_dict.items(): 19 | if '-test-' in k: 20 | env = 'HW-SIT' 21 | elif '-dev-' in k: 22 | env = 'HW-DEV' 23 | elif '-pdev-' in k: 24 | env = 'HW-FGPDEV' 25 | elif '-wlsit-' in k: 26 | env = 'HW-WLSIT' 27 | else: 28 | env = 'HW-BASE' 29 | 30 | data = { 31 | "id": k, 32 | "name": env, 33 | "tags": ["node_exporter",env,k,v], 34 | "address": v, 35 | "port": 9100, 36 | "check": { 37 | "tcp": f"{v}:9100", 38 | "interval": "10s" 39 | } 40 | } 41 | reg = requests.put("http://192.168.200.60:8500/v1/agent/service/register", headers=headers, data=json.dumps(data)) 42 | print(env,k,v,reg.status_code) 43 | -------------------------------------------------------------------------------- /google-authenticator/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 StarsL.cn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /google-authenticator/README.md: -------------------------------------------------------------------------------- 1 | # google-authenticator 2 | 谷歌验证器的python3实现,根据明文字符串即可生成二维码、秘钥串、验证码 3 | -------------------------------------------------------------------------------- /google-authenticator/google-authenticator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding:utf-8 -*- 3 | import hmac, base64, struct, hashlib, time 4 | import sys 5 | import qrcode,qrcode_terminal 6 | class google(object): 7 | def SecretKey(self, pubKey): 8 | return base64.b32encode(pubKey.encode('utf-8')).decode('utf-8') 9 | 10 | def QR(self, name, secretKey): 11 | qr = qrcode.QRCode( 12 | version=1, 13 | error_correction=qrcode.constants.ERROR_CORRECT_H, 14 | box_size=7, 15 | border=4 16 | ) 17 | qrdata = f'otpauth://totp/{name}?secret={secretKey}' 18 | qr.add_data(qrdata) 19 | qr.make(fit=True) 20 | img = qr.make_image() 21 | img.save("/tmp/test.png") 22 | return qrcode_terminal.draw(qrdata) 23 | 24 | def GoogleCode(self, secretKey): 25 | input = int(time.time()) // 30 26 | key = base64.b32decode(secretKey) 27 | msg = struct.pack(">Q", input) 28 | googleCode = hmac.new(key, msg, hashlib.sha1).digest() 29 | if (sys.version_info> (2, 7)): 30 | o = googleCode[19] & 15 31 | else: 32 | o = ord(googleCode[19]) & 15 33 | googleCode = str((struct.unpack(">I", googleCode[o:o + 4])[0] & 0x7fffffff) % 1000000) 34 | if len(googleCode) == 5: 35 | googleCode = '0' + googleCode 36 | return googleCode 37 | 38 | if __name__ == "__main__": 39 | new = google() 40 | key = new.SecretKey('starsliao') 41 | print ('\n谷歌验证器导入二维码:\n') 42 | qr = new.QR('StarsL.cn',key) 43 | gc = new.GoogleCode(key) 44 | print (f'\n秘钥串:{key}\n验证码:{gc}') 45 | -------------------------------------------------------------------------------- /how-to-look-the-plate/README.md: -------------------------------------------------------------------------------- 1 | 2 | # 如何使用钉钉优雅的看盘 3 | ### 实现功能 4 | - 基于python3 + DingtalkChatbot 实现消息推送。 5 | 6 | - 交易期间,每10分钟推送一次关注的股票涨幅与价格。(红涨绿跌) 7 | 8 | - 当关注股票涨跌幅达到每个百分点,会实时推送消息和分时图。 9 | 10 | - 点击任意股票右侧的【分时】,即可在钉钉侧边栏展示当前股票的分时图。 11 | 12 | - 无后台服务,通过系统定时任务运行。 13 | 14 | ### 如何使用 15 | 16 | 安装依赖: 17 | ``` 18 | pip3 install requests DingtalkChatbot==1.5.1 19 | ``` 20 | 21 | 编辑脚本加入股票,钉钉@手机号,钉钉自定义机器人Token 22 | ``` 23 | # 增加需要展示的股票代码 24 | stock_list = ['600869','601118','600682','600546','002223'] 25 | # @到钉钉手机号 26 | at = '170xxx' 27 | # 钉钉群自定义webhook机器人地址,自定义关键字:股票 28 | webhook = 'https://oapi.dingtalk.com/robot/send?access_token=xxx' 29 | ``` 30 | 增加crontab: 31 | ``` 32 | * 9-15 * * 1-5 /opt/rise.py 33 | 0 8 * * 1-5 rm -rvf /tmp/.rise.json 34 | ``` 35 | ### 关注公众号【**全栈运维开发**】加入运维群交流,获取更多... 36 | ![](https://github.com/starsliao/Prometheus/blob/master/qr.jpg) 37 | 38 | 39 | ### 截图 40 | ![](https://github.com/starsliao/tools/raw/master/how-to-look-the-plate/capture.jpg) 41 | -------------------------------------------------------------------------------- /how-to-look-the-plate/capture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/how-to-look-the-plate/capture.jpg -------------------------------------------------------------------------------- /how-to-look-the-plate/rise.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | # @Author : StarsL.cn 4 | # @Email : starsliao@163.com 5 | # @describe: 如何使用钉钉优雅的看盘 6 | 7 | ''' 8 | 安装依赖: 9 | pip install DingtalkChatbot==1.5.1 10 | 11 | 增加crontab: 12 | * 9-15 * * 1-5 /opt/rise.py 13 | 0 8 * * 1-5 rm -rvf /tmp/.rise.json 14 | 15 | 参考接口: 16 | http://api.money.163.com/data/feed/0000001,0601998,0600734,0600006,money.api 17 | http://hq.sinajs.cn/list=sh000001,sh601998,sh600734,sh600006 18 | http://hq.sinajs.cn/list=s_sh000001,s_sh601998,s_sh600734,s_sh600006,s_sz002505 19 | http://image.sinajs.cn/newchart/min/n/sh600006.gif 20 | ''' 21 | 22 | import requests,datetime,os,json 23 | from dingtalkchatbot.chatbot import DingtalkChatbot 24 | now = datetime.datetime.now() 25 | time930 = datetime.datetime.strptime(str(now.date())+'09:30', '%Y-%m-%d%H:%M') 26 | time1132 = datetime.datetime.strptime(str(now.date())+'11:32', '%Y-%m-%d%H:%M') 27 | time1300 = datetime.datetime.strptime(str(now.date())+'13:00', '%Y-%m-%d%H:%M') 28 | time1502 = datetime.datetime.strptime(str(now.date())+'15:02', '%Y-%m-%d%H:%M') 29 | stock = '' 30 | 31 | # 增加需要展示的股票代码 32 | stock_list = ['600869','601118','600682','600546','002223'] 33 | # @到钉钉手机号 34 | at = '170xxx' 35 | # 钉钉群自定义webhook机器人地址,自定义关键字:股票 36 | webhook = 'https://oapi.dingtalk.com/robot/send?access_token=xxx' 37 | 38 | for i in stock_list: 39 | i = 's_sh' + i if int(i) >= 600000 else 's_sz' + i 40 | stock = stock + i + ',' 41 | if (now > time930 and now < time1132) or (now > time1300 and now < time1502): 42 | response = requests.get(f'http://hq.sinajs.cn/list=s_sh000001,{stock}',stream=True) 43 | md='' 44 | if os.path.exists('/tmp/.rise.json'): 45 | with open('/tmp/.rise.json', 'r') as fr: 46 | info_dict = json.load(fr) 47 | else: 48 | info_dict = {} 49 | for j in [(i.split('"')[1] + ',' + i.split('=')[0].split('_')[-1]).split(',') for i in response.iter_lines(decode_unicode=True)]: 50 | info = f'{j[0]}:{j[3]}%,{round(float(j[1]),2)}' 51 | imgurl = f'http://image.sinajs.cn/newchart/min/n/{j[-1]}.gif?{now.timestamp()}' 52 | if j[-1] not in info_dict: 53 | info_dict[j[-1]] = [] 54 | if '-' in info: 55 | info = f'{info}[【分时】](dingtalk://dingtalkclient/page/link?url={imgurl}&pc_slide=true)' 56 | else: 57 | info = f'{info}[【分时】](dingtalk://dingtalkclient/page/link?url={imgurl}&pc_slide=true)' 58 | if abs(float(j[3])) >= 1 and int(float(j[3])) not in info_dict[j[-1]]: 59 | info = info + '\n' + f'![{j[3]}分时图]({imgurl})\n\n' 60 | info_dict[j[-1]].append(int(float(j[3]))) 61 | md = md + f'- {info}\n' 62 | with open(f'/tmp/.rise.json', 'w') as f: 63 | json.dump(info_dict,f) 64 | 65 | if "分时图" in md: 66 | msg = DingtalkChatbot(webhook) 67 | send = msg.send_markdown(title='股票波动推图',text=f'{md}\n',at_mobiles=[at]) 68 | 69 | elif now.minute in [1,11,21,31,41,51]: 70 | msg = DingtalkChatbot(webhook) 71 | send = msg.send_markdown(title='股票定时推送',text=f'{md}\n',at_mobiles=[at]) 72 | else: 73 | print('time not match') 74 | -------------------------------------------------------------------------------- /hwpy/3rd/SSU.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/hwpy/3rd/SSU.exe -------------------------------------------------------------------------------- /hwpy/3rd/disk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in $(lsblk -s | grep disk | awk '{print $1}' | sed "s#└─##");do 3 | hdinfo=`sudo -S smartctl -a /dev/$i | grep -E "Device Model|Serial Number|test result|Power_On_Hours|SATA Version"` 4 | dm=`echo "$hdinfo"|grep "Device Model"|awk '{print $NF}'` 5 | sn=`echo "$hdinfo"|grep "Serial Number"|awk '{print $NF}'` 6 | tr=`echo "$hdinfo"|grep "test result"|awk '{print $NF}'` 7 | ph=`echo "$hdinfo"|grep "Power_On_Hours"|awk '{print $NF}'` 8 | ph=`echo "$hdinfo"|grep "SATA Version"|awk -F 'SATA Version is:' '{print $NF}'|xargs` 9 | echo "$i 型号:$dm 序列号:$sn 状态:$tr 通电(时):$ph 速度:$sv" 10 | done 11 | -------------------------------------------------------------------------------- /hwpy/3rd/hwinfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo -e '\e[31;1m#############\e[0m' 3 | echo -e '\e[31;1m#\e[0m服务器信息:\e[31;1m#\e[0m' 4 | echo -e '\e[31;1m#############\e[0m' 5 | echo "服务器型号:`dmidecode -t system|grep -A1 Manufacturer|awk -F: '{print $2}'|xargs`,服务器类型/高度:`dmidecode -t chassis|grep -E 'Type|Height'|awk -F:\ '{print $2}'|xargs -i printf {}.`" 6 | echo -e '\n' 7 | echo -e '\e[31;1m##########\e[0m' 8 | echo -e '\e[31;1m#\e[0mCPU信息:\e[31;1m#\e[0m' 9 | echo -e '\e[31;1m##########\e[0m' 10 | x=`dmidecode -t processor|grep 'Status: Populated'|wc -l` 11 | y=1 12 | if [ `grep 'model name' /proc/cpuinfo|sort|uniq|wc -l` == 1 ]; 13 | then 14 | cpu=`grep 'model name' /proc/cpuinfo|awk -F:\ '{print $2}'|sed 's/[[:space:]][[:space:]]*/ /g'|sed -n 1p` 15 | while [ $y -le $x ]; do 16 | echo "物理CPU:`dmidecode -t processor|grep 'Socket Designation'|awk -F:\ '{print $2}'|sed -n $y\p`:型号:$cpu,核心数:`dmidecode -t processor|grep 'Core Count'|awk -F:\ '{print $2}'|sed -n $y\p`,共`dmidecode -t processor|grep 'Thread Count'|awk -F:\ '{print $2}'|sed -n $y\p`个线程,当前频率:`dmidecode -t processor|grep 'Current Speed'|awk -F:\ '{print $2}'|sed -n $y\p`." 17 | y=`expr $y + 1` 18 | done 19 | else 20 | while [ $y -le $x ]; do 21 | cpu=`grep 'model name' /proc/cpuinfo|sort|uniq|awk -F:\ '{print $2}'|sed 's/[[:space:]][[:space:]]*/ /g'|sed -n $y\p` 22 | echo "物理CPU:`dmidecode -t processor|grep 'Socket Designation'|awk -F:\ '{print $2}'|sed -n $y\p`:型号:$cpu,核心数:`dmidecode -t processor|grep 'Core Count'|awk -F:\ '{print $2}'|sed -n $y\p`,共`dmidecode -t processor|grep 'Thread Count'|awk -F:\ '{print $2}'|sed -n $y\p`个线程,当前频率:`dmidecode -t processor|grep 'Current Speed'|awk -F:\ '{print $2}'|sed -n $y\p`." 23 | y=`expr $y + 1` 24 | done 25 | fi 26 | echo "支持的物理CPU数:`dmidecode -t processor|grep Version|wc -l`个,已安装的CPU数:$x个,支持的CPU插槽接口:`dmidecode -t processor|grep 'Upgrade'|awk -F:\ '{print $2}'|sed -n 1p`,所支持的最大CPU频率:`dmidecode -t processor|grep 'Max Speed'|awk -F:\ '{print $2}'|sed -n 1p`." 27 | echo -e '\n' 28 | echo -e '\e[31;1m###########\e[0m' 29 | echo -e '\e[31;1m#\e[0m内存信息:\e[31;1m#\e[0m' 30 | echo -e '\e[31;1m###########\e[0m' 31 | x=`dmidecode -t memory|grep 'Size'|wc -l` 32 | y=1 33 | s=`echo -e '\e[31;1m该插槽未安装内存\e[0m'` 34 | while [ $y -le $x ]; do 35 | echo "内存`dmidecode -t memory|grep 'Locator:'|grep -v 'Bank'|awk -F:\ '{print $2}'|sed 's/ *$//g'|sed -n $y\p`:容量为:`dmidecode -t memory|grep 'Size:'|awk -F:\ '{print $2}'|sed -n $y\p`,类型为:`dmidecode -t memory|grep 'Type:'|grep -v 'Error Correction Type'|awk -F:\ '{print $2}'|sed -n $y\p`,频率为:`dmidecode -t memory|grep 'Speed:'|awk -F:\ '{print $2}'|sed -n $y\p`,生产厂商为:`dmidecode -t memory|grep 'Manufacturer:'|awk -F:\ '{print $2}'|sed 's/ *$//g'|sed -n $y\p`."|sed "s/No\ Module\ Installed.*/$s/g" 36 | y=`expr $y + 1` 37 | done 38 | echo "支持的最大总内存容量:`dmidecode -t memory|grep 'Maximum Capacity'|awk -F:\ '{print $2}'`,支持的总内存数量:`dmidecode -t memory|grep 'Number Of Devices'|awk -F:\ '{print $2}'`根,支持的纠错类型:`dmidecode -t memory|grep 'Error Correction Type'|awk -F:\ '{print $2}'`." 39 | echo -e '\n' 40 | echo -e '\e[31;1m###########\e[0m' 41 | echo -e '\e[31;1m#\e[0m硬盘信息:\e[31;1m#\e[0m' 42 | echo -e '\e[31;1m###########\e[0m' 43 | fdisk -l &>/tmp/tmp.disk && grep -E 'Disk /dev/sd|Disk /dev/hd|Disk /dev/cciss' /tmp/tmp.disk|awk -F, '{print $1}' && rm -rf /tmp/tmp.disk 44 | if [ -f /usr/sbin/smartctl ]; 45 | then 46 | if [ -b /dev/sda ] || [ -b /dev/hda ]; 47 | then 48 | ls -1 /dev/?d[a-z]|while read line ; 49 | do 50 | smartctl -i $line>/tmp/disk.1 51 | if [ "`grep 'SMART support is: Enabled' /tmp/disk.1`" = "SMART support is: Enabled" ] ; 52 | then 53 | smartctl -A $line>/tmp/disk.2 54 | echo "硬盘$line:型号:`grep 'Device Model' /tmp/disk.1|awk -F: '{print $2}'|xargs`,ATA标准:`grep 'ATA Standard is' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:已开启,使用时间:`grep -E 'Power_On_Hours' /tmp/disk.2|awk -F\ '{print $10}'`小时,当前硬盘温度:`grep -E 'Temperature_Celsius' /tmp/disk.2|awk -F\ '{print $10}'`度." 55 | # elif [ "`grep 'Device does not support SMART' /tmp/disk.1`" = "Device does not support SMART" ]; 56 | # then 57 | # echo "硬盘$line:型号:`grep -E 'Vendor|Product' /tmp/disk.1|awk -F: '{print $2}'|xargs`,传输协议:`grep 'Transport protocol' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:不支持." 58 | # else 59 | # echo "硬盘$line:型号:`grep -E 'Vendor|Product' /tmp/disk.1|awk -F: '{print $2}'|xargs`,传输协议:`grep 'Transport protocol' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:支持,未开启." 60 | else 61 | echo "硬盘$line:型号:`grep -E 'Vendor|Product' /tmp/disk.1|awk -F: '{print $2}'|xargs`,传输协议:`grep 'Transport protocol' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:`tail -1 /tmp/disk.1`." 62 | fi; 63 | done 64 | fi 65 | if [ -d /dev/cciss ]; 66 | then 67 | ls -1 /dev/cciss/????|while read line ; 68 | do 69 | smartctl -i -d cciss,0 $line>/tmp/disk.1 70 | if [ "`grep 'Device supports SMART and is Enabled' /tmp/disk.1`" = "Device supports SMART and is Enabled" ]; 71 | then 72 | smartctl -A -d cciss,0 $line>/tmp/disk.2 73 | echo "硬盘$line:型号:`grep -E 'Vendor|Product' /tmp/disk.1|awk -F: '{print $2}'|xargs`,传输协议:`grep 'Transport protocol' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:已开启,使用时间:`grep 'number of hours powered up' /tmp/disk.2|awk -F= '{print $2}'|xargs`小时,当前硬盘温度:`grep 'Current Drive Temperature' /tmp/disk.2|awk -F\ '{print $4}'|xargs`度,极限温度:`grep 'Drive Trip Temperature' /tmp/disk.2|awk -F\ '{print $4}'|xargs`度." 74 | else 75 | echo "硬盘$line:型号:`grep -E 'Vendor|Product' /tmp/disk.1|awk -F: '{print $2}'|xargs`,传输协议:`grep 'Transport protocol' /tmp/disk.1|awk -F: '{print $2}'|xargs`, SMART模式:`tail -1 /tmp/disk.1`." 76 | fi; 77 | done 78 | fi 79 | rm -rf /tmp/disk.1 /tmp/disk.2 80 | else 81 | echo "smartmontools未安装,硬盘部分信息无法检测,请根据系统使用yum或者apt-get等来进行安装." 82 | fi 83 | echo -e '\n' 84 | echo -e '\e[31;1m###########\e[0m' 85 | echo -e '\e[31;1m#\e[0m网卡信息:\e[31;1m#\e[0m' 86 | echo -e '\e[31;1m###########\e[0m' 87 | echo "共检测到`lspci|grep 'Ethernet controller'|wc -l`块网卡,型号如下:" 88 | echo "`lspci|grep 'Ethernet controller'|awk -F:\ '{print $2}'|awk -F\( '{print $1}'|awk '{print NR,$0}'`" 89 | if [ -f /sbin/ethtool ] || [ -f /usr/sbin/ethtool ]; 90 | then 91 | x=`lspci|grep 'Ethernet controller'|wc -l` 92 | y=0 93 | while [ $y -lt $x ]; 94 | do 95 | echo "网卡eth$y:支持最大速度:`ethtool eth$y|grep -B1 'Supports auto-negotiation'|sed -n 1p|xargs`,当前连接速度:`ethtool eth$y|grep -E 'Speed|Duplex'|awk -F:\ '{print $2}'|xargs`,当前链路状态:`ethtool eth$y|grep -E 'Link detected'|awk -F:\ '{print $2}'`." 96 | y=`expr $y + 1` 97 | done 98 | else 99 | echo "ethtool未安装,网卡部分信息无法检测,请根据系统使用yum或者apt-get等来进行安装." 100 | fi 101 | echo -e '\n' 102 | echo -e '\e[31;1m###########\e[0m' 103 | echo -e '\e[31;1m#\e[0m系统版本:\e[31;1m#\e[0m' 104 | echo -e '\e[31;1m###########\e[0m' 105 | if [ -f /usr/bin/lsb_release ]; 106 | then 107 | lsb=`lsb_release -d|awk -F: '{ print $2 }'|xargs` 108 | else 109 | lsb=`sed -n 1p /etc/issue` 110 | fi 111 | echo "发行版本:$lsb `getconf LONG_BIT`位,内核版本:`uname -r`" 112 | echo -e '\n' 113 | echo -e '\e[31;1m###########\e[0m' 114 | echo -e '\e[31;1m#\e[0m网络信息:\e[31;1m#\e[0m' 115 | echo -e '\e[31;1m###########\e[0m' 116 | /sbin/ifconfig|grep -B1 "inet addr"|xargs|sed s/\ --\ /\\n/g|grep -v 'lo'|awk -F\ '{print "网卡""\033[31;1m"$1"\033[0m"":IP地址:"$7",MAC地址:"$5}'|sed s/addr://g 117 | echo "默认网关:`route -n|awk '{if($1=="0.0.0.0")print $2 }'`,DNS:`grep 'nameserver' /etc/resolv.conf|awk -F\ '{print $2}'|sed ':a;N;s/\n/,/;ta'`" 118 | echo -e '\n' 119 | echo -e '\e[31;1m###########\e[0m' 120 | echo -e '\e[31;1m#\e[0m已开端口:\e[31;1m#\e[0m' 121 | echo -e '\e[31;1m###########\e[0m' 122 | netstat -nlptu|sed -n '3,$p'>/tmp/net.1 123 | grep tcp /tmp/net.1|awk -F\ '{print $4"\t"$7}'|sed s/:::/0.0.0.0:/g|sed s/::ffff://g|awk -F: '{print $2}'|sed '/^$/d'|sed 's/^/TCP\t/'>/tmp/net.2 124 | udp=`echo -e '\e[31;1mUDP\e[0m'` 125 | grep udp /tmp/net.1|awk -F\ '{print $4"\t"$6}'|sed s/:::/0.0.0.0:/g|sed s/::ffff://g|awk -F: '{print $2}'|sed '/^$/d'|sed "s/^/$udp\t/">>/tmp/net.2 126 | echo -e "协议\t端口\t进程号/进程名" 127 | sort -k2n /tmp/net.2|uniq 128 | rm -rf /tmp/net.1 /tmp/net.2 129 | echo -e '\n' 130 | echo -e '\e[31;1m#############检测完成#############\e[0m' 131 | echo -e '\n' -------------------------------------------------------------------------------- /hwpy/3rd/ssu.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/hwpy/3rd/ssu.sh -------------------------------------------------------------------------------- /hwpy/README.md: -------------------------------------------------------------------------------- 1 | # 获取Linux服务器硬件明细。Get linux server hardware information. 2 | 3 | # install(python2.7 and python3.6) 4 | 5 | #### lastest psutil maybe required 6 | ``` 7 | # yum install -y gcc python-devel dmidecode pciutils 8 | # pip install -U setuptools 9 | # pip install -U psutil 10 | ``` 11 | 12 | ``` 13 | # pip install hwpy 14 | ``` 15 | 16 | # usage 17 | ``` 18 | # python -m hwpy 19 | ``` 20 | ``` 21 | from hwpy import info 22 | info.main() 23 | info.hwlist 24 | ``` 25 | ``` 26 | info.cpu 27 | info.net 28 | info.disk 29 | info.part 30 | info.host 31 | info.mem 32 | ``` 33 | -------------------------------------------------------------------------------- /hwpy/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$1" ] 3 | then 4 | msg=$1 5 | else 6 | msg="update" 7 | fi 8 | rm -rvf hwpy.egg-info dist hwpy/*.pyc 9 | python setup.py sdist 10 | twine upload dist/hwpy*.tar.gz && \ 11 | rm -rvf hwpy.egg-info dist && \ 12 | git add --all && \ 13 | git commit -m "$msg" && \ 14 | git push 15 | -------------------------------------------------------------------------------- /hwpy/hwpy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/hwpy/hwpy/__init__.py -------------------------------------------------------------------------------- /hwpy/hwpy/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from . import info as _info 3 | if __name__ == '__main__': 4 | _info.main() 5 | -------------------------------------------------------------------------------- /hwpy/hwpy/_dmide.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import subprocess,sys 3 | 4 | def parse_dmi(content,hwtype): 5 | info = [] 6 | lines = iter(content) 7 | # lines = iter(content.strip().splitlines()) 8 | while True: 9 | try: 10 | line = next(lines) 11 | except StopIteration: 12 | break 13 | if line.startswith('Handle 0x'): 14 | info.append((hwtype, _parse_handle_section(lines))) 15 | return info 16 | 17 | def _parse_handle_section(lines): 18 | data = { 19 | '_title': next(lines).rstrip(), 20 | } 21 | 22 | for line in lines: 23 | line = line.rstrip() 24 | if line.startswith('\t\t'): 25 | if isinstance(data[k], list): 26 | data[k].append(line.lstrip()) 27 | elif line.startswith('\t'): 28 | k, v = [i.strip() for i in line.lstrip().split(':', 1)] 29 | if v: 30 | data[k] = v 31 | else: 32 | data[k] = [] 33 | else: 34 | break 35 | return data 36 | 37 | def info(shell): 38 | try: 39 | output = subprocess.check_output( 40 | 'PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin ' 41 | 'sudo ' + shell, shell=True) 42 | except Exception as e: 43 | print(e) 44 | if str(e).find("command not found") == -1: 45 | print("please install dmidecode") 46 | print("e.g. sudo yum install dmidecode") 47 | 48 | sys.exit(1) 49 | return output.decode('utf-8').strip().splitlines() 50 | # return output.decode('utf-8').strip().split('\n') 51 | 52 | 53 | def getserver(): 54 | hwvendor = info("dmidecode -t system|grep -C2 Version|awk -F:\ '{print $2}'") 55 | hwclass = info("dmidecode -t chassis|grep -E 'Type|Height'|awk -F:\ '{print $2}'") 56 | serverdict = {'Server':{'Vendor':hwvendor[0],'Type':hwvendor[1],'Version':hwvendor[2],'SN':hwvendor[3],'UUID':hwvendor[4]},'Class':{'Server Type':hwclass[0],'Height':hwclass[1]}} 57 | return serverdict 58 | 59 | 60 | def getcpu(): 61 | hwcpu = parse_dmi(info("dmidecode -t processor"),"cpu") 62 | cpudict = {} 63 | hascpu = 0 64 | disbyb = 0 65 | for i in hwcpu: 66 | cnum = i[1]['Socket Designation'] 67 | if i[1]['Status'] == 'Populated, Enabled': 68 | hascpu += 1 69 | ctype = i[1].get('Version', False) 70 | ccc = i[1].get('Core Count', False) 71 | ctc = i[1].get('Thread Count', False) 72 | ccspeed = i[1].get('Current Speed', False) 73 | cpudict[cnum] = {'Type':ctype,'Core Count':ccc,'Thread Count':ctc,'Current Speed':ccspeed} 74 | elif i[1]['Status'] == 'Populated, Disabled By BIOS': 75 | disbyb += 1 76 | cpudict['CPU #Populated, Disabled By BIOS'] = {'Count':str(disbyb)} 77 | else: 78 | cpudict[cnum] = {'Status':i[1]['Status']} 79 | 80 | hwctotal = str(len(hwcpu)) 81 | hwcsocket = hwcpu[0][1].get('Upgrade', False) 82 | hwcmspeed = hwcpu[0][1].get('Max Speed', False) 83 | cpudict['CpuSocket'] = {'Socket Count':hwctotal,'CPU Count':str(hascpu),'Socket Type':hwcsocket,'Max Speed':hwcmspeed} 84 | return cpudict 85 | 86 | 87 | def getmem(): 88 | hwmem = parse_dmi(info("dmidecode -t memory"),"memory") 89 | memdict = {} 90 | hasmem = 0 91 | for i in hwmem: 92 | if i[1]['_title'] == 'Memory Device': 93 | memnum = 'MEM-' + i[1]['Locator'] 94 | if i[1]['Size'] != 'No Module Installed': 95 | hasmem +=1 96 | msize = i[1].get('Size', False) 97 | mtype = i[1].get('Type', False) 98 | mmspeed = i[1].get('Speed', False) 99 | mcspeed = i[1].get('Configured Clock Speed', False) 100 | mfac = i[1].get('Manufacturer', False) 101 | mpn = i[1].get('Part Number', False) 102 | memdict[memnum] = {'Size':msize,'Type':mtype,'Speed':mmspeed,'Current Speed':mcspeed,'Vendor':mfac,'Model':mpn} 103 | # else: 104 | # memdict[memnum] = {'Status':"No Module Installed"} 105 | elif i[1]['_title'] == 'Physical Memory Array': 106 | hwmtotalnum = i[1].get('Number Of Devices', False) 107 | hwmtotalsize = i[1].get('Maximum Capacity', False) 108 | hwmerr = i[1].get('Error Correction Type', False) 109 | memdict['Memsocket'] = {'Mem Socket Count':hwmtotalnum,'Max Size':hwmtotalsize,'Error Correction Type':hwmerr} 110 | memdict['Memsocket']['Current Mem Count'] = str(hasmem) 111 | return memdict 112 | -------------------------------------------------------------------------------- /hwpy/hwpy/_hwdisk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from __future__ import print_function 3 | import os 4 | import re 5 | import sys 6 | import errno 7 | from subprocess import Popen,PIPE 8 | 9 | def find_device(data, pciid): 10 | id = re.escape(pciid) 11 | m = re.search("^" + id + "\s(.*)$", data, re.MULTILINE) 12 | return m.group(1) 13 | 14 | def pretty_size(size): 15 | size_strs = ['B', 'KiB', 'MiB', 'GiB', 'TiB'] 16 | last_size = size 17 | fract_size = size 18 | num_divs = 0 19 | 20 | while size > 1: 21 | fract_size = last_size 22 | last_size = size 23 | size /= 1024 24 | num_divs += 1 25 | 26 | num_divs -= 1 27 | fraction = fract_size / 1024 28 | pretty = "%.2f" % fraction 29 | pretty = pretty + size_strs[num_divs] 30 | return pretty 31 | 32 | def virtual_device(path): 33 | for dir in os.listdir(path): 34 | if re.search("device", dir): 35 | return 0 36 | return 1 37 | 38 | class Device: 39 | def __init__(self): 40 | self.sectorsize = "" 41 | self.sectors = "" 42 | self.rotational = "" 43 | self.sysdir = "" 44 | self.host = "" 45 | self.model = "" 46 | self.vendor = "" 47 | self.holders = [] 48 | self.diskname = "" 49 | self.partitions = [] 50 | self.removable = "" 51 | self.start = "" 52 | self.discard = "" 53 | self.sysfs_no_links = 0 54 | 55 | def populate_model(self): 56 | try: 57 | f = open(self.sysdir + "/device/model") 58 | self.model = f.read().rstrip() 59 | f.close() 60 | except IOError: 61 | # do nothing 62 | pass 63 | 64 | def populate_vendor(self): 65 | try: 66 | f = open(self.sysdir + "/device/vendor") 67 | self.vendor = f.read().rstrip() 68 | f.close() 69 | except IOError: 70 | #do nothing 71 | pass 72 | 73 | def populate_sectors(self): 74 | try: 75 | f = open(self.sysdir + "/size") 76 | self.sectors = f.read().rstrip() 77 | f.close() 78 | except IOError: 79 | self.sectors = 0 80 | 81 | def populate_sector_size(self): 82 | try: 83 | f = open(self.sysdir + "/queue/hw_sector_size") 84 | self.sectorsize = f.read().rstrip() 85 | f.close() 86 | except IOError: 87 | # if this sysfs doesnt show us sectorsize then just assume 512 88 | self.sectorsize = "512" 89 | 90 | def populate_rotational(self): 91 | try: 92 | f = open(self.sysdir + "/queue/rotational") 93 | rotation = f.read().rstrip() 94 | f.close() 95 | except IOError: 96 | self.rotational = "Could not determine rotational" 97 | return 98 | if rotation == "1": 99 | self.rotational = "Spinning disk" 100 | else: 101 | self.rotational = "SSD" 102 | 103 | def populate_host(self, pcidata): 104 | if self.sysfs_no_links == 1: 105 | try: 106 | sysdir = os.readlink(os.path.join(self.sysdir, "device")) 107 | except: 108 | pass 109 | else: 110 | sysdir = self.sysdir 111 | # m = re.match(".+/\d+:(\w+:\w+\.\w)/host\d+/\s*", sysdir) 112 | m = re.match(".+/\d+:(\w+:\w+\.\w)/[a-z]+\d+/\s*", sysdir) 113 | if m: 114 | pciid = m.group(1) 115 | self.host = find_device(pcidata, pciid) 116 | else: 117 | self.host = "" 118 | 119 | def populate_diskname(self): 120 | m = re.match(".*/(.+)$", self.sysdir) 121 | self.diskname = m.group(1) 122 | 123 | def populate_holders(self): 124 | for dir in os.listdir(self.sysdir + "/holders"): 125 | if re.search("^dm-.*", dir): 126 | try: 127 | f = open(self.sysdir + "/holders/" + dir + "/dm/name") 128 | name = f.read().rstrip() 129 | f.close() 130 | self.holders.append(name) 131 | except IOError: 132 | self.holders.append(dir) 133 | else: 134 | self.holders.append(dir) 135 | 136 | def populate_discard(self): 137 | try: 138 | f = open(self.sysdir + "/queue/discard_granularity") 139 | discard = f.read().rstrip() 140 | f.close() 141 | if discard == "0": 142 | self.discard = "No" 143 | else: 144 | self.discard = "Yes" 145 | except IOError: 146 | self.discard = "No" 147 | 148 | def populate_start(self): 149 | try: 150 | f = open(self.sysdir + "/start") 151 | self.start = f.read().rstrip() 152 | f.close() 153 | except IOError: 154 | pass 155 | 156 | def populate_partitions(self): 157 | for dir in os.listdir(self.sysdir): 158 | m = re.search("(" + self.diskname + "\d+)", dir) 159 | if m: 160 | partname = m.group(1) 161 | part = Device() 162 | part.sysdir = self.sysdir + "/" + partname 163 | part.populate_part_info() 164 | self.partitions.append(part) 165 | 166 | def populate_part_info(self): 167 | """ Only call this if we are a partition """ 168 | self.populate_diskname() 169 | self.populate_holders() 170 | self.populate_sectors() 171 | self.populate_start() 172 | 173 | def populate_removable(self): 174 | try: 175 | f = open(self.sysdir + "/removable") 176 | remove = f.read().rstrip() 177 | f.close() 178 | if remove == "1": 179 | self.removable = "Yes" 180 | else: 181 | self.removable = "No" 182 | except IOError: 183 | self.removable = "No" 184 | 185 | def populate_all(self, pcidata): 186 | self.populate_diskname() 187 | self.populate_holders() 188 | self.populate_partitions() 189 | self.populate_removable() 190 | self.populate_model() 191 | self.populate_vendor() 192 | self.populate_sectors() 193 | self.populate_sector_size() 194 | self.populate_rotational() 195 | self.populate_discard() 196 | self.populate_host(pcidata) 197 | 198 | def getdisk(): 199 | p = Popen(["lspci"], stdout=PIPE) 200 | err = p.wait() 201 | if err: 202 | print ("Error running lspci") 203 | sys.exit() 204 | pcidata = p.stdout.read().decode('utf-8') 205 | 206 | sysfs_no_links = 0 207 | devices = [] 208 | 209 | if len(sys.argv) > 1: 210 | m = re.match("/dev/(\D+)\d*", sys.argv[1]) 211 | if m: 212 | block = m.group(1) 213 | else: 214 | block = sys.argv[1] 215 | 216 | try: 217 | path = os.readlink(os.path.join("/sys/block/", block)) 218 | except OSError as e: 219 | if e.errno == errno.EINVAL: 220 | path = block 221 | else: 222 | print ("Invalid device name " + block) 223 | sys.exit() 224 | d = Device() 225 | d.sysdir = os.path.join("/sys/block", path) 226 | d.populate_all(pcidata) 227 | devices.append(d) 228 | else: 229 | for block in os.listdir("/sys/block"): 230 | try: 231 | if sysfs_no_links == 0: 232 | path = os.readlink(os.path.join("/sys/block/", block)) 233 | else: 234 | path = block 235 | except OSError as e: 236 | if e.errno == errno.EINVAL: 237 | path = block 238 | sysfs_no_links = 1 239 | else: 240 | continue 241 | if re.search("virtual", path): 242 | continue 243 | if sysfs_no_links == 1: 244 | sysdir = os.path.join("/sys/block", path) 245 | if virtual_device(sysdir) == 1: 246 | continue 247 | d = Device() 248 | d.sysdir = os.path.join("/sys/block", path) 249 | d.sysfs_no_links = sysfs_no_links 250 | d.populate_all(pcidata) 251 | devices.append(d) 252 | diskdict = {} 253 | devices.sort() 254 | for d in devices: 255 | diskdict[d.diskname] = [] 256 | size = float(d.sectors) * float(d.sectorsize) 257 | allpretty = pretty_size(size) 258 | diskdict[d.diskname] = {'host':d.host,'vendor':d.vendor,'model':d.model,'size':allpretty,'type':d.rotational} 259 | return diskdict 260 | -------------------------------------------------------------------------------- /hwpy/hwpy/_hwnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from __future__ import print_function 3 | from psutil import net_if_addrs,net_if_stats 4 | import os 5 | import re 6 | import sys 7 | import errno 8 | from subprocess import Popen,PIPE 9 | p = Popen(["lspci"], stdout=PIPE) 10 | err = p.wait() 11 | if err: 12 | print ("Error running lspci") 13 | sys.exit() 14 | pcidata = p.stdout.read().decode('utf-8') 15 | 16 | def _find_device(data, pciid): 17 | id = re.escape(pciid) 18 | m = re.search("^" + id + "\s(.*)$", data, re.MULTILINE) 19 | return m.group(1) 20 | def getnet(): 21 | netdict = {} 22 | for k, v in net_if_addrs().items(): 23 | if not (k.startswith('tap') or k.startswith('vir') or k.startswith('br') or k.startswith('lo') or k.startswith('docker')): 24 | for item in v: 25 | mac = item[1] 26 | if ':' in mac and len(mac)==17: 27 | netdir = os.readlink(os.path.join("/sys/class/net", k)) 28 | m = re.match(".+/\d+:(\w+:\w+\.\w)/[a-z]+\w*/\s*", netdir) 29 | if m: 30 | pciid = m.group(1) 31 | host = _find_device(pcidata, pciid) 32 | else: 33 | host = "" 34 | eth = Popen("sudo ethtool {}|grep 'Link detected'|awk -F:\ '{{print $2}}'".format(k), stdout=PIPE,shell=True) 35 | err = eth.wait() 36 | if err: 37 | print ("Error running ethtool") 38 | sys.exit() 39 | isup = eth.stdout.read().decode('utf-8').strip("\n") 40 | if isup == "yes" and net_if_stats()[k].speed != 65535: 41 | speed = str(net_if_stats()[k].speed) + 'Mbps' 42 | elif isup == "no": 43 | speed = False 44 | else: 45 | speed = 'Unknown' 46 | netdict[k] = {'host':host,'mac':mac,'isup':isup,'speed':speed} 47 | return netdict 48 | -------------------------------------------------------------------------------- /hwpy/hwpy/_hwpart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from psutil import disk_partitions as _disk_partitions, disk_usage as _disk_usage 3 | 4 | def _pretty_size(size): 5 | size_strs = ['B', 'KiB', 'MiB', 'GiB', 'TiB'] 6 | last_size = size 7 | fract_size = size 8 | num_divs = 0 9 | 10 | while size > 1: 11 | fract_size = last_size 12 | last_size = size 13 | size /= 1024.0 14 | num_divs += 1 15 | 16 | num_divs -= 1 17 | fraction = fract_size / 1024.0 18 | pretty = "%.2f" % fraction 19 | pretty = pretty + size_strs[num_divs] 20 | return pretty 21 | 22 | def getpart(): 23 | partlist = _disk_partitions() 24 | partlist.sort() 25 | partdict={} 26 | for i in partlist: 27 | dev = i.device 28 | mount = i.mountpoint 29 | fstype = i.fstype 30 | total = _pretty_size(_disk_usage(mount).total) 31 | partdict[i.device]={'mount':mount,'fstype':fstype,'total':total} 32 | return partdict 33 | -------------------------------------------------------------------------------- /hwpy/hwpy/info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from . import _hwnet, _hwpart, _hwdisk, _dmide 3 | net = _hwnet.getnet() 4 | part = _hwpart.getpart() 5 | disk = _hwdisk.getdisk() 6 | cpu = _dmide.getcpu() 7 | host = _dmide.getserver() 8 | mem = _dmide.getmem() 9 | hwlist = [host,cpu,mem,disk,part,net] 10 | def main(): 11 | for i in hwlist: 12 | items = i.keys() 13 | itemslist = sorted(items) 14 | for m in itemslist: 15 | print (m + ':') 16 | for ik,iv in i[m].items(): 17 | print ("\t" + ik + ':' + str(iv)) 18 | -------------------------------------------------------------------------------- /hwpy/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | ############################################# 5 | # File Name: hwpy 6 | # Author: Stars Liao 7 | # Mail: starsliaop@163.com 8 | # Created Time: 2018-12-24 19:17:34 9 | ############################################# 10 | 11 | from setuptools import setup, find_packages 12 | with open("README.md", "r") as fh: 13 | long_description = fh.read() 14 | 15 | setup( 16 | name = "hwpy", 17 | version = "0.3.8", 18 | keywords = ("pip", "hwpy","Hardware","硬件检测"), 19 | description = "Get linux server hardware information. 获取Linux服务器硬件明细。", 20 | long_description = long_description, 21 | long_description_content_type="text/markdown", 22 | license = "MIT Licence", 23 | 24 | url = "https://github.com/starsliao/PythonTools", 25 | author = "Stars Liao", 26 | author_email = "starsliao@163.com", 27 | 28 | packages = find_packages(), 29 | include_package_data = True, 30 | platforms = "any", 31 | install_requires = ["psutil==5.9.5"], 32 | classifiers=[ 33 | 'Intended Audience :: System Administrators', 34 | 'Operating System :: POSIX :: Linux', 35 | 'Programming Language :: Python :: 2.7', 36 | 'Programming Language :: Python :: 3.6', 37 | 'Topic :: Utilities', 38 | ], 39 | ) 40 | -------------------------------------------------------------------------------- /rabbitmq-test/README.md: -------------------------------------------------------------------------------- 1 | ### obsolete 2 | -------------------------------------------------------------------------------- /rabbitmq-test/send.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import pika 3 | import sys,datetime,time 4 | import multiprocessing,logging 5 | 6 | logger = logging.getLogger("MQ_SENDER") 7 | logger.setLevel(logging.DEBUG) 8 | fh = logging.FileHandler("/var/log/mq_sender.log") 9 | fh.setLevel(logging.DEBUG) 10 | #ch = logging.StreamHandler() 11 | #ch.setLevel(logging.INFO) 12 | formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] [%(process)d] %(message)s") 13 | #ch.setFormatter(formatter) 14 | fh.setFormatter(formatter) 15 | #logger.addHandler(ch) 16 | logger.addHandler(fh) 17 | 18 | def sender(): 19 | credentials = pika.PlainCredentials('admin','app') 20 | connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.200.201',5672,'test',credentials)) 21 | channel = connection.channel() 22 | channel.queue_declare(queue='deploy', durable=True) 23 | try: 24 | for i in range(1,100001): 25 | #message = datetime.datetime.now().strftime('%Y_%m_%d_%H:%M:%S.%f') 26 | channel.basic_publish(exchange='',routing_key='deploy',body=str(i),properties=pika.BasicProperties(delivery_mode=2)) 27 | logger.info(f'[sender]{i}') 28 | time.sleep(1) 29 | connection.close() 30 | except KeyboardInterrupt: 31 | connection.close() 32 | print('EXIT!') 33 | for i in range(600): 34 | p = multiprocessing.Process(target=sender) 35 | p.start() 36 | -------------------------------------------------------------------------------- /rabbitmq-test/work.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import multiprocessing 3 | import threading 4 | import pika 5 | import os,sys,time,logging,random 6 | class Worker: 7 | def __init__(self, username, password, host, vhost, queue_name): 8 | self.username = username 9 | self.password = password 10 | self.host = host 11 | self.vhost = vhost 12 | self.queue_name = queue_name 13 | self.connection = None 14 | self.channel = None 15 | 16 | logger = logging.getLogger("MQ_WORKER") 17 | logger.setLevel(logging.DEBUG) 18 | fh = logging.FileHandler("/var/log/mq_worker.log") 19 | fh.setLevel(logging.DEBUG) 20 | ch = logging.StreamHandler() 21 | ch.setLevel(logging.INFO) 22 | formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] [%(process)d] %(message)s") 23 | ch.setFormatter(formatter) 24 | fh.setFormatter(formatter) 25 | logger.addHandler(ch) 26 | logger.addHandler(fh) 27 | 28 | self.logger = logger 29 | 30 | def conn(self): 31 | if self.connection and not self.connection.is_closed: 32 | self.connection.close() 33 | credentials = pika.PlainCredentials(self.username, self.password) 34 | is_closed = True 35 | while is_closed: 36 | try: 37 | self.connection = pika.BlockingConnection(pika.ConnectionParameters(self.host,5672,self.vhost,credentials,heartbeat=60)) 38 | is_closed = False 39 | except: 40 | self.logger.error('[main] AMQP_Connection_Error') 41 | time.sleep(2) 42 | self.channel = self.connection.channel() 43 | self.channel.basic_qos(prefetch_count=1) 44 | self.channel.queue_declare(queue=self.queue_name, durable=True) 45 | self.channel.basic_consume(queue=self.queue_name, on_message_callback=self.task) 46 | self.logger.info('[Connect Successfully] Waiting for messages. To exit press CTRL+C') 47 | self.channel.start_consuming() 48 | 49 | def heart(self): 50 | while True: 51 | time.sleep(20) 52 | try: 53 | self.connection.process_data_events() 54 | self.logger.debug(f'[heartbeat] Heartbeat check succeeded') 55 | except Exception as err: 56 | self.logger.error(f'[heartbeat] {err}') 57 | t = threading.Thread(target=self.conn) 58 | t.daemon = True 59 | t.start() 60 | k = True 61 | while k: 62 | if self.connection.is_open: 63 | k = False 64 | 65 | def task(self, ch, method, properties, body): 66 | num = random.uniform(0,1) 67 | self.logger.info(f'Received: {body},{num}') 68 | time.sleep(num) 69 | self.logger.info(f'Done: {body}') 70 | ch.basic_ack(delivery_tag=method.delivery_tag) 71 | self.logger.info(f'ACK: {body}') 72 | 73 | # def doit(self) 74 | # t = threading.Thread(target=self.task, args=(ch, method, properties, body,)) 75 | # t.daemon = True 76 | # t.start() 77 | 78 | def main(self): 79 | t = threading.Thread(target=self.conn) 80 | t.daemon = True 81 | t.start() 82 | while True: 83 | if self.connection and not self.connection.is_closed: 84 | self.heart() 85 | 86 | if __name__ == '__main__': 87 | w = Worker('admin','app','192.168.200.201','test','deploy') 88 | for i in range(400): 89 | p = multiprocessing.Process(target=w.main) 90 | p.start() 91 | -------------------------------------------------------------------------------- /rabbitmq-test/work.py.bak: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import multiprocessing 3 | import threading 4 | import pika 5 | import sys,time,logging 6 | class Worker: 7 | def __init__(self, username, password, host, vhost, queue_name): 8 | self.username = username 9 | self.password = password 10 | self.host = host 11 | self.vhost = vhost 12 | self.queue_name = queue_name 13 | self.connection = None 14 | self.channel = None 15 | self.credentials = None 16 | 17 | logger = logging.getLogger("MQ_WORKER") 18 | logger.setLevel(logging.DEBUG) 19 | fh = logging.FileHandler("/var/log/mq_worker.log") 20 | fh.setLevel(logging.DEBUG) 21 | ch = logging.StreamHandler() 22 | ch.setLevel(logging.INFO) 23 | formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s") 24 | ch.setFormatter(formatter) 25 | fh.setFormatter(formatter) 26 | logger.addHandler(ch) 27 | logger.addHandler(fh) 28 | 29 | self.logger = logger 30 | 31 | def conn(self): 32 | if self.connection and not self.connection.is_closed: 33 | self.connection.close() 34 | self.credentials = pika.PlainCredentials(self.username, self.password) 35 | is_closed = True 36 | while is_closed: 37 | try: 38 | self.connection = pika.BlockingConnection(pika.ConnectionParameters(self.host,5672,self.vhost,self.credentials,heartbeat=60)) 39 | is_closed = False 40 | except: 41 | self.logger.error('[main] AMQPConnectionError') 42 | time.sleep(2) 43 | self.channel = self.connection.channel() 44 | self.channel.basic_qos(prefetch_count=1) 45 | self.channel.queue_declare(queue=self.queue_name, durable=True) 46 | self.logger.info('[Connect Successfully] Waiting for messages. To exit press CTRL+C') 47 | 48 | def task(self,body,ch,method): 49 | self.logger.info(f'Received: {body}') 50 | time.sleep(3) 51 | self.logger.info(f'Done: {body}') 52 | ch.basic_ack(delivery_tag=method.delivery_tag) 53 | self.logger.info(f'ACK: {body}\n') 54 | 55 | def receive(self,callback): 56 | def cb(ch, method, properties, body): 57 | t = threading.Thread(target=callback, args=(body,ch,method,)) 58 | t.daemon = True 59 | t.start() 60 | while t.is_alive(): 61 | time.sleep(5) 62 | self.logger.info(f'[heartbeat] Heart beating...') 63 | #print(f'[INFO] [{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] heart beating') 64 | try: 65 | self.connection.process_data_events() 66 | except Exception as err: 67 | self.logger.error(f'[heartbeat] {err}') 68 | self.conn() 69 | self.channel.basic_consume(queue=self.queue_name, on_message_callback=cb) 70 | self.channel.start_consuming() 71 | self.conn() 72 | self.channel.basic_consume(queue=self.queue_name, on_message_callback=cb) 73 | self.channel.start_consuming() 74 | 75 | if __name__ == '__main__': 76 | w = Worker('app','app','192.168.200.201','app','deploy') 77 | w.receive(w.task) 78 | #p = multiprocessing.Process(target=w.receive, args=(w.task,)) 79 | #p.start() 80 | -------------------------------------------------------------------------------- /rabbitmq-test/work.py.false: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import multiprocessing 3 | import threading 4 | import pika 5 | import sys,time,logging,random 6 | class Worker: 7 | def __init__(self, username, password, host, vhost, queue_name): 8 | self.username = username 9 | self.password = password 10 | self.host = host 11 | self.vhost = vhost 12 | self.queue_name = queue_name 13 | self.connection = None 14 | self.channel = None 15 | self.credentials = None 16 | 17 | logger = logging.getLogger("MQ_WORKER") 18 | logger.setLevel(logging.DEBUG) 19 | fh = logging.FileHandler("/var/log/mq_worker.log") 20 | fh.setLevel(logging.DEBUG) 21 | ch = logging.StreamHandler() 22 | ch.setLevel(logging.INFO) 23 | formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s") 24 | ch.setFormatter(formatter) 25 | fh.setFormatter(formatter) 26 | logger.addHandler(ch) 27 | logger.addHandler(fh) 28 | 29 | self.logger = logger 30 | 31 | def conn(self): 32 | if self.connection and not self.connection.is_closed: 33 | self.connection.close() 34 | self.credentials = pika.PlainCredentials(self.username, self.password) 35 | is_closed = True 36 | while is_closed: 37 | try: 38 | self.connection = pika.BlockingConnection(pika.ConnectionParameters(self.host,5672,self.vhost,self.credentials,heartbeat=10)) 39 | is_closed = False 40 | except: 41 | self.logger.error('[main] AMQPConnectionError') 42 | time.sleep(2) 43 | self.channel = self.connection.channel() 44 | self.channel.basic_qos(prefetch_count=1) 45 | self.channel.queue_declare(queue=self.queue_name, durable=True) 46 | self.channel.basic_consume(queue=self.queue_name, on_message_callback=self.task) 47 | t = threading.Thread(target=self.heart) 48 | t.daemon = True 49 | t.start() 50 | self.logger.info('[Connect Successfully] Waiting for messages. To exit press CTRL+C') 51 | self.channel.start_consuming() 52 | 53 | def heart(self): 54 | while True: 55 | time.sleep(3) 56 | try: 57 | self.connection.process_data_events() 58 | self.logger.info(f'[heartbeat] Heartbeat check succeeded') 59 | except Exception as err: 60 | self.logger.error(f'[heartbeat] {err}') 61 | self.conn() 62 | 63 | def task(self, ch, method, properties, body): 64 | num = random.uniform(200,300) 65 | self.logger.info(f'Received: {body},{num}') 66 | time.sleep(3600) 67 | self.logger.info(f'Done: {body}') 68 | ch.basic_ack(delivery_tag=method.delivery_tag) 69 | self.logger.info(f'ACK: {body}\n') 70 | 71 | if __name__ == '__main__': 72 | w = Worker('app','app','192.168.200.201','app','deploy') 73 | w.conn() 74 | # for i in range(1): 75 | # p = multiprocessing.Process(target=w.conn) 76 | # p.start() 77 | -------------------------------------------------------------------------------- /rabbitmq-test/work.py.new: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | import multiprocessing 3 | import threading 4 | import pika 5 | import sys,time,logging,random 6 | class Worker: 7 | def __init__(self, username, password, host, vhost, queue_name): 8 | self.username = username 9 | self.password = password 10 | self.host = host 11 | self.vhost = vhost 12 | self.queue_name = queue_name 13 | self.connection = None 14 | self.channel = None 15 | self.credentials = None 16 | 17 | logger = logging.getLogger("MQ_WORKER") 18 | logger.setLevel(logging.DEBUG) 19 | fh = logging.FileHandler("/var/log/mq_worker.log") 20 | fh.setLevel(logging.DEBUG) 21 | ch = logging.StreamHandler() 22 | ch.setLevel(logging.INFO) 23 | formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s") 24 | ch.setFormatter(formatter) 25 | fh.setFormatter(formatter) 26 | logger.addHandler(ch) 27 | logger.addHandler(fh) 28 | 29 | self.logger = logger 30 | 31 | def conn(self): 32 | if self.connection and not self.connection.is_closed: 33 | self.connection.close() 34 | self.credentials = pika.PlainCredentials(self.username, self.password) 35 | is_closed = True 36 | while is_closed: 37 | try: 38 | self.connection = pika.BlockingConnection(pika.ConnectionParameters(self.host,5672,self.vhost,self.credentials,heartbeat=60)) 39 | is_closed = False 40 | except: 41 | self.logger.error('[main] AMQPConnectionError') 42 | time.sleep(2) 43 | self.channel = self.connection.channel() 44 | self.channel.basic_qos(prefetch_count=1) 45 | self.channel.queue_declare(queue=self.queue_name, durable=True) 46 | self.channel.basic_consume(queue=self.queue_name, on_message_callback=self.cb) 47 | self.logger.info('[Connect Successfully] Waiting for messages. To exit press CTRL+C') 48 | self.channel.start_consuming() 49 | 50 | def cb(self, ch, method, properties, body): 51 | t = threading.Thread(target=self.task, args=(body,ch,method,)) 52 | t.daemon = True 53 | t.start() 54 | while t.is_alive(): 55 | time.sleep(0.2) 56 | self.logger.info(f'[heartbeat] Heart beating...') 57 | #print(f'[INFO] [{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}] heart beating') 58 | try: 59 | self.connection.process_data_events() 60 | except Exception as err: 61 | self.logger.error(f'[heartbeat] {err}') 62 | self.conn() 63 | 64 | def task(self,body,ch,method): 65 | self.logger.info(f'Received: {body}') 66 | num = random.uniform(0,2) 67 | time.sleep(0.5) 68 | self.logger.info(f'Done: {body}') 69 | ch.basic_ack(delivery_tag=method.delivery_tag) 70 | self.logger.info(f'ACK: {body}\n') 71 | 72 | if __name__ == '__main__': 73 | w = Worker('app','app','192.168.200.201','app','deploy') 74 | w.conn() 75 | # for i in range(1): 76 | # p = multiprocessing.Process(target=w.conn) 77 | # p.start() 78 | -------------------------------------------------------------------------------- /short-url/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | import requests 3 | url = "http://yourServerIp:888/shorturl" 4 | payload={'url': "https://baidu.com"} 5 | response = requests.post(url, data=payload) 6 | response.json()['surl'] 7 | ``` 8 | -------------------------------------------------------------------------------- /short-url/short-url.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | ''' 3 | import requests 4 | url = "http://yourServerIp:888/shorturl" 5 | payload={'url': "https://baidu.com"} 6 | response = requests.post(url, data=payload) 7 | response.json()['surl'] 8 | ''' 9 | 10 | import redis 11 | from flask import Flask, request, Response, jsonify, redirect 12 | 13 | base62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | len_base62 = len(base62) 15 | base_url = 'http://s.openiops.com/' 16 | r = redis.StrictRedis(host='127.0.0.1', port=6379, db=6, password='xxxxxxxxxx') 17 | 18 | def base62_encode(num): 19 | string = '' 20 | while num: 21 | string = base62[num % len_base62] + string 22 | num //= len_base62 23 | return string 24 | 25 | app = Flask(__name__) 26 | @app.route("/shorturl", methods=['POST']) 27 | def shorturl(): 28 | if request.method == 'POST': 29 | url = request.form['url'] 30 | sid = base62_encode(r.incr('SID')) 31 | r.hset('URL', sid, url) 32 | surl = base_url + sid 33 | return jsonify({'surl': surl}) 34 | 35 | @app.route('/') 36 | def longurl(token): 37 | long_url = r.hget('URL', token).decode(encoding='utf-8') 38 | return redirect(long_url, 301) 39 | 40 | if __name__ == "__main__": 41 | app.run(host="0.0.0.0", port=888) 42 | -------------------------------------------------------------------------------- /wechatbot/README.md: -------------------------------------------------------------------------------- 1 | 使用UOS微信协议,web版接口复活!实现一个微信群报价机器人 2 | 3 | 如果之前你的微信提示不能登录web端,使得itchat等基于微信网页版模拟操作的库无法使用,那么这个更新将会是你的福音。因为这个修改版的itchat已经支持使用UOS微信桌面版协议实现登录! 4 | 5 | ## 如何使用: 6 | 安装修改版的ItChat即可: 7 | 8 | ``` 9 | yum install xdg-utils -y 10 | pip3 uninstall itchat 11 | pip3 install git+https://github.com/StarsL-cn/ItChat-UOS.git 12 | ``` 13 | 14 | 对itchat不熟悉的同学可以参考该项目说明 15 | 16 | ## 原理说明: 17 | 18 | 原理很简单:UOS下的微信只是网页版套了个electron。所以目前采用的绕过web端的限制方式,其实是使用了UOS的桌面版微信请求头,只要在请求的地址上首先加一个?target=t 就是这样:https://wx.qq.com/?target=t 然后在扫码登陆后拦截 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage 这个请求,并在请求头上添加两个固定的参数: 19 | ``` 20 | extspam ='Gp8ICJkIEpkICggwMDAwMDAwMRAGGoAI1GiJSIpeO1RZTq9QBKsRbPJdi84ropi16EYI10WB6g74sGmRwSNXjPQnYUKYotKkvLGpshucCaeWZMOylnc6o2AgDX9grhQQx7fm2DJRTyuNhUlwmEoWhjoG3F0ySAWUsEbH3bJMsEBwoB//0qmFJob74ffdaslqL+IrSy7LJ76/G5TkvNC+J0VQkpH1u3iJJs0uUYyLDzdBIQ6Ogd8LDQ3VKnJLm4g/uDLe+G7zzzkOPzCjXL+70naaQ9medzqmh+/SmaQ6uFWLDQLcRln++wBwoEibNpG4uOJvqXy+ql50DjlNchSuqLmeadFoo9/mDT0q3G7o/80P15ostktjb7h9bfNc+nZVSnUEJXbCjTeqS5UYuxn+HTS5nZsPVxJA2O5GdKCYK4x8lTTKShRstqPfbQpplfllx2fwXcSljuYi3YipPyS3GCAqf5A7aYYwJ7AvGqUiR2SsVQ9Nbp8MGHET1GxhifC692APj6SJxZD3i1drSYZPMMsS9rKAJTGz2FEupohtpf2tgXm6c16nDk/cw+C7K7me5j5PLHv55DFCS84b06AytZPdkFZLj7FHOkcFGJXitHkX5cgww7vuf6F3p0yM/W73SoXTx6GX4G6Hg2rYx3O/9VU2Uq8lvURB4qIbD9XQpzmyiFMaytMnqxcZJcoXCtfkTJ6pI7a92JpRUvdSitg967VUDUAQnCXCM/m0snRkR9LtoXAO1FUGpwlp1EfIdCZFPKNnXMeqev0j9W9ZrkEs9ZWcUEexSj5z+dKYQBhIICviYUQHVqBTZSNy22PlUIeDeIs11j7q4t8rD8LPvzAKWVqXE+5lS1JPZkjg4y5hfX1Dod3t96clFfwsvDP6xBSe1NBcoKbkyGxYK0UvPGtKQEE0Se2zAymYDv41klYE9s+rxp8e94/H8XhrL9oGm8KWb2RmYnAE7ry9gd6e8ZuBRIsISlJAE/e8y8xFmP031S6Lnaet6YXPsFpuFsdQs535IjcFd75hh6DNMBYhSfjv456cvhsb99+fRw/KVZLC3yzNSCbLSyo9d9BI45Plma6V8akURQA/qsaAzU0VyTIqZJkPDTzhuCl92vD2AD/QOhx6iwRSVPAxcRFZcWjgc2wCKh+uCYkTVbNQpB9B90YlNmI3fWTuUOUjwOzQRxJZj11NsimjOJ50qQwTTFj6qQvQ1a/I+MkTx5UO+yNHl718JWcR3AXGmv/aa9rD1eNP8ioTGlOZwPgmr2sor2iBpKTOrB83QgZXP+xRYkb4zVC+LoAXEoIa1+zArywlgREer7DLePukkU6wHTkuSaF+ge5Of1bXuU4i938WJHj0t3D8uQxkJvoFi/EYN/7u2P1zGRLV4dHVUsZMGCCtnO6BBigFMAA=' 21 | client-version' = '2.0.0' 22 | ``` 23 | 这样就可以完美使用桌面版协议了。 24 | 25 | # 开发一个微信群数字货币报价机器人: 26 | 27 | ## 实现功能: 28 | 1. 基于itchat库实现微信群机器人,只需要把该微信号加入到对应的群,群成员发送币种名称消息即可触发机器人报价。 29 | 2. 目前接入了币安,火币,抹茶3个交易所的行情数据。 30 | 3. 这些都是开放的接口不需要认证。 31 | 4. 记得使用非国内的服务器来请求这些接口。 32 | 5. 另外基于apscheduler写了个简单的定时任务,可定时推送消息到微信群。 33 | 34 | ## 截图: 35 | ![](https://raw.githubusercontent.com/starsliao/PyTools/master/wechatbot/bot.png) 36 | 37 | ## 完整代码请参考gitlab: 38 | https://github.com/starsliao/tools/blob/master/wechatbot/wechatbot.py 39 | -------------------------------------------------------------------------------- /wechatbot/bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/starsliao/PythonTools/3bdd7fc988529ea75e927f4a3f1ed9b10424eaba/wechatbot/bot.png -------------------------------------------------------------------------------- /wechatbot/wechatbot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import itchat,os,threading,requests 3 | from apscheduler.schedulers.blocking import BlockingScheduler 4 | def kline(symbol): 5 | queryurl = f"https://api.huobi.pro/market/history/kline?period=1day&size=1&symbol={symbol}usdt" 6 | res_dict = requests.request("GET", queryurl).json() 7 | if 'status' in res_dict and res_dict['status'] == 'ok': 8 | return res_dict['data'][0] 9 | else: 10 | queryurl = f"https://api.binance.com/api/v3/klines?limit=1&interval=1d&symbol={symbol.upper()}USDT" 11 | res_list = requests.request("GET", queryurl).json() 12 | if isinstance(res_list,list): 13 | return res_list[0] 14 | else: 15 | queryurl = f"https://www.mxc.com/open/api/v2/market/kline?limit=1&interval=1d&symbol={symbol.upper()}_USDT" 16 | res_dict = requests.request("GET", queryurl).json() 17 | if 'data' in res_dict and res_dict['data'] != []: 18 | return res_dict 19 | else: 20 | return 'error' 21 | def str_of_num(num): 22 | num = float(num) 23 | def strofsize(num, level): 24 | if level >= 2: 25 | return num, level 26 | elif num >= 10000: 27 | num /= 10000 28 | level += 1 29 | return strofsize(num, level) 30 | else: 31 | return num, level 32 | units = ['', '万', '亿'] 33 | num, level = strofsize(num, 0) 34 | if level > len(units): 35 | level -= 1 36 | return '{}{}'.format(round(num, 3), units[level]) 37 | 38 | def inquiry(symbol): 39 | binfo = kline(symbol) 40 | print(binfo) 41 | if 'data' in binfo and binfo['data'] != []: 42 | id,open,close,high,low,vol,amount = binfo['data'][0] 43 | b,t,count,open,close = '抹茶',8,-1,float(open),float(close) 44 | elif isinstance(binfo,dict): 45 | id,open,close,low,high,vol,amount,count = binfo.values() 46 | b,t = '火币',0 47 | elif isinstance(binfo,list): 48 | id,open,high,low,close,vol,x1,amount,count,x2,x3,x4 = binfo 49 | b,t,open,close = '币安',8,float(open),float(close) 50 | else: 51 | return binfo 52 | #return '火币、币安找不到该币种' 53 | quote = round((close - open)/open * 100,2) 54 | return f"今日【{b}】报价\n价格:{close}u\n涨幅:{quote}%\n开盘:{open}u\n最高:{high}u\n最低:{low}u\n成交量:{str_of_num(vol)}\n成交额:{str_of_num(amount)}u\n交易笔数:{str_of_num(count)}\n----------\n以每日{t}时为基准开始计算" 55 | 56 | @itchat.msg_register(itchat.content.TEXT, isGroupChat=True) 57 | def group_reply(msg): 58 | symbol = msg.text.strip() 59 | #print(symbol) 60 | if symbol.encode('UTF-8').isalpha() and len(symbol) < 10: 61 | output = inquiry(symbol.lower()) 62 | if output != 'error': 63 | return f"【{symbol.upper()}】{output}" 64 | 65 | elif msg.actualNickName == '你的微信昵称' and msg.text == "查收益": 66 | stdout = os.popen("/opt/money.py").read() 67 | path = stdout.split('img_path:')[-1] 68 | print(stdout) 69 | itchat.send_image(path.strip(),toUserName=msg.FromUserName) 70 | #return "@"+msg.actualNickName+" 已接收消息:"+msg.text 71 | 72 | @itchat.msg_register(itchat.content.TEXT, isFriendChat=True) 73 | def friend_reply(msg): 74 | if msg.text == "查收益": 75 | stdout = os.popen("/opt/containerd/bin/b/money.py").read() 76 | path = stdout.split('img_path:')[-1] 77 | print(stdout) 78 | itchat.send_image(path.strip(),toUserName=msg.FromUserName) 79 | #return "@"+msg.actualNickName+" 已接收消息:"+msg.text 80 | 81 | def send_job(): 82 | stdout = os.popen("/opt/containerd/bin/b/money.py").read() 83 | path = stdout.split('img_path:')[-1] 84 | print(stdout) 85 | itchat.send_image(path.strip(),toUserName='@@群ID') 86 | def start_job(): 87 | sched = BlockingScheduler() 88 | sched.add_job(send_job, 'interval', seconds=120) 89 | sched.start() 90 | itchat.auto_login(hotReload=True,enableCmdQR=2)#登入 91 | thread = threading.Thread(target=start_job) 92 | thread.start() 93 | itchat.run() 94 | -------------------------------------------------------------------------------- /ws-test/.gevent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | import sys 3 | port = int(sys.argv[1]) 4 | from gevent import monkey; monkey.patch_all() 5 | from ws4py.websocket import EchoWebSocket 6 | from ws4py.server.geventserver import WSGIServer 7 | from ws4py.server.wsgiutils import WebSocketWSGIApplication 8 | import logging 9 | from ws4py import configure_logger 10 | try: 11 | 12 | logger = logging.getLogger('ws4py') 13 | configure_logger(level=10) 14 | server = WSGIServer(('0.0.0.0', port), WebSocketWSGIApplication(handler_cls=EchoWebSocket)) 15 | print("=====START 0.0.0.0:{}=====".format(port)) 16 | server.serve_forever() 17 | except KeyboardInterrupt: 18 | print ("=====STOP 0.0.0.0:{}=====".format(port)) 19 | -------------------------------------------------------------------------------- /ws-test/README.md: -------------------------------------------------------------------------------- 1 | # ws-test 2 | ## ws服务端连接测试 3 | #### `iws.sh`为一键安装ws服务端脚本,运行后,输入端口号即可监听(已存在的端口会被杀掉)。 4 | #### `wsc.py`为ws客户端,运行后会发送message到服务端,客户端能看服务器会不停的返回当前时间,服务端能看到请求的连接信息。 5 | 6 | ``` 7 | # example 8 | 9 | wsc.py wss://xxx.com:999 10 | wsc.py ws://xxx.com:777 11 | ``` 12 | -------------------------------------------------------------------------------- /ws-test/iws.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | read -p "=====INPUT SERVER PORT:" port 3 | pid=`netstat -nlpt|grep $port|awk '{print $NF}'|awk -F / '{print $1}'` 4 | kill -9 $pid 5 | if [ ! -f "/usr/bin/pip2" ];then 6 | yum install epel-release -y --disablerepo=* --enablerepo=extras 7 | yum install python2-pip -y --disablerepo=* --enablerepo=epel 8 | fi 9 | pip2 install ws4py 10 | cat > /usr/bin/ws-server.py <