【zabbix监控+python爬虫+shell脚本】 理财对接天天基金网实现相关基金波动邮件/钉钉提醒
前序
刚开始接触理财, 第一次朋友介绍的是[安信证券]这款app, 看了几天, 以每笔500的价格入手了两个基金玩玩接触一下行情, 后来发现, 每次都不知道它什么时候更新这个变动净值参数,每次都要自己去搜索, 或者又要登录一遍去看盈亏, 够懒吧, 嘿嘿, 后来突发奇想, 跟朋友了解一下是不是有什么公式能计算得到相关的净值参数的, 于是翻了一遍, 发现对[天天基金网]这个web来比较轻松愉快一些, 那么既然有了想法, 就开干吧。
目的展示
当基金发现波动的时候, 来信息提示, -代表下跌,正数代表上涨
架构拓展
容器:
zabbix-server : Docker
zabbix-agent : CentOS Linux release 7.7.1908 (Core)
版本:
nginx1.17 + mysql5.7.22 + php7 + zabbix4.2.5
python2.7.5
技术模型
【zabbix】
zabbix这块, 使用到的无非就是一个开源的项目而已, 不难, 自行搭建, 至于有伙伴说不知道怎么搭, 那么建议你去找度娘聊一下, 或者搜一下我之前写的zabbix搭建的文章, 但是我的文章水平都很有限,没办法,人就这样,还想上天不成[/哭泣/]。
【python】
python这块, 用爬虫,使用的是原生的python2.7, 由于我的是centos7.7, 有点抗拒8, 至于有人问为什么呢,俺不知道,也不想说,哈。
【shell】
shell这个就很简单了, 无非就是推送一下python爬去下来的数据, 扔给zabbix, 对了, zabbix我用的是主动模式, 至于为什么用主动模式, 因为我的zabbix是扔在docker里面的, 所以我每次搭建一个监控的时候就直接导入我的zabbix镜像, 然后进去start一下相关进程就好了, 干净。
提醒:进行下面操作之前,zabbix得预先搭建好, 我这边就不再演示了。
代码目录文件简介
1 2 3 4 5 6 7 | -rwxr-xr-x 1 zabbix zabbix 21 Jan 14 20:32 fund.code 基金代码 -rwxr-xr-x 1 zabbix zabbix 119 Jan 14 22:44 fund.dict 基金代码+基金名称 -rwxr-xr-x 1 zabbix zabbix 909 Jan 15 11:19 fund_dict2.sh 基金净值百分比筛选shell -rwxr-xr-x 1 zabbix zabbix 801 Jan 15 09:56 fund_dict.sh 基金净值筛选shell drwxr-xr-x 2 zabbix zabbix 4096 Jan 15 11:50 fund_log 日志目录 -rwxr-xr-x 1 zabbix zabbix 1713 Jan 15 14:20 fund.py 爬虫 -rwxr-xr-x 1 zabbix zabbix 1211 Jan 15 10:13 fund.sh 筛选今天和昨天净值 |
fund.code
1 2 3 4 | [root@mail script] # cat fund.code 001071 003986 007244 |
fund.dict
1 2 3 4 | [root@mail script] # cat fund.dict 001071,华安媒体互联网混合 003986,申万菱信中证500指数优选增强A 007244,安信核心竞争力混合C |
fund_dict2.sh
fund_dict.sh与fund_dict2.sh基本相同, 不过就是后面筛选的参数不一样,自动获取今天的时间和昨天的时间(以今天的为标准), 当今天的基金净值为更新的时候拿到的参数是空的, 这个时间会进入判断, 如果拿到的参数为空,那就是说今天的相关基金净值还没有更新, 那么这个时候就取昨天的为准, 一旦发现更新, 就推送到监控上面去触发, 然后提醒, 告诉自己今天的基金是涨还是跌。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@mail script] # cat fund_dict2.sh #************************************************************************* # > File Name: fund_dict.sh # > Author: chenglee # > Main : chengkenlee@sina.com # > Blog : http://www.cnblogs.com/chenglee/ # > Created Time : Tue 14 Jan 2020 10:48:10 PM CST #************************************************************************* #!/bin/bash today=` date + "%Y-%m-%d" ` yesterday=` date -d "yesterday ${today}" +%Y-%m-%d` fund_code=$1 cd /zabbix/zabbix-agent/script todaydata=` cat fund_log /fund_ ${fund_code}.log | grep "${today}" | sed 's/ //g' | awk -F '|' '{print$5}' ` if [ -z "$todaydata" ]; then yesterdaydata=` cat fund_log /fund_ ${fund_code}.log | grep "${yesterday}" | sed 's/ //g' | awk -F '|' '{print$5}' ` echo $yesterdaydata #echo $yesterdaydata > fund_log/${fund_code}.profit else echo $todaydata #echo $todaydata > fund_log/${fund_code}.profit fi |
fund_dict.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #************************************************************************* # > File Name: fund_dict.sh # > Author: chenglee # > Main : chengkenlee@sina.com # > Blog : http://www.cnblogs.com/chenglee/ # > Created Time : Tue 14 Jan 2020 10:48:10 PM CST #************************************************************************* #!/bin/bash today=` date + "%Y-%m-%d" ` yesterday=` date -d "yesterday ${today}" +%Y-%m-%d` fund_code=$1 cd /zabbix/zabbix-agent/script todaydata=` cat fund_log /fund_ ${fund_code}.log | grep "${today}" | sed 's/ //g' | awk -F '|' '{print$4}' ` if [ -z "$todaydata" ]; then yesterdaydata=` cat fund_log /fund_ ${fund_code}.log | grep "${yesterday}" | sed 's/ //g' | awk -F '|' '{print$4}' ` echo $yesterdaydata else echo $todaydata fi |
fund_log
1 2 3 4 | total 12 -rw-r--r-- 1 zabbix zabbix 546 Jan 15 14:30 fund_001071.log -rw-r--r-- 1 zabbix zabbix 546 Jan 15 14:30 fund_003986.log -rw-r--r-- 1 zabbix zabbix 546 Jan 15 14:30 fund_007244.log |
fund.py
爬虫, 实现将相关基金的净值参数根据相关日期拿下来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/env python "" " # Author: chenglee # Created Time : Tue 14 Jan 2020 08:16:54 PM CST # File Name: ji.py # Description: "" " # -*- coding:utf-8 -*- # url:http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=007244&sdate=2020-01-01&edate=2020-01-15&per=20 import requests from bs4 import BeautifulSoup from prettytable import * def get_url(url, params=None, proxies=None): rsp = requests.get(url, params=params, proxies=proxies) rsp.raise_for_status() return rsp.text def get_fund_data(code, start= '' , end= '' ): record = { 'Code' : code} url = 'http://fund.eastmoney.com/f10/F10DataApi.aspx' params = { 'type' : 'lsjz' , 'code' : code, 'page' : 1, 'per' : 65535, 'sdate' : start, 'edate' : end} html = get_url(url, params) soup = BeautifulSoup(html, 'html.parser' ) records = [] tab = soup.findAll( 'tbody' )[0] for tr in tab.findAll( 'tr' ): if tr .findAll( 'td' ) and len(( tr .findAll( 'td' ))) == 7: record[ 'Date' ] = str( tr . select ( 'td:nth-of-type(1)' )[0].getText().strip()) record[ 'NetAssetValue' ] = str( tr . select ( 'td:nth-of-type(2)' )[0].getText().strip()) record[ 'ChangePercent' ] = str( tr . select ( 'td:nth-of-type(4)' )[0].getText().strip()) records.append(record.copy()) return records def demo(code, start, end): table = PrettyTable() table.field_names = [ 'Code' , 'Date' , 'NAV' , 'Change' ] table.align[ 'Change' ] = 'r' records = get_fund_data(code, start, end) for record in records: table.add_row([record[ 'Code' ], record[ 'Date' ], record[ 'NetAssetValue' ], record[ 'ChangePercent' ]]) return table if __name__ == "__main__" : print demo( '001071' , '2020-01-01' , '2020-01-15' ) |
爬下来的数据是怎么样的呢, 是这样的
fund.sh
过滤, 调用爬虫去获取, 我定义的是每5分钟获取一次, 扔进crontab里面自生自灭了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #************************************************************************* # > File Name: fund.sh # > Author: chenglee # > Main : chengkenlee@sina.com # > Blog : http://www.cnblogs.com/chenglee/ # > Created Time : Tue 14 Jan 2020 08:27:06 PM CST #************************************************************************* #!/bin/bash today=` date + "%Y-%m-%d" ` day1=` cat fund.py | grep print | cut -d '(' -f2| cut -d ')' -f1 | sed "s|'||g" | sed 's/ //g ' | awk -F ' , ' ' {print$2}'` day2=` cat fund.py | grep print | cut -d '(' -f2| cut -d ')' -f1 | sed "s|'||g" | sed 's/ //g ' | awk -F ' , ' ' {print$3}'` function running(){ exec 2< "fund.code" while read line2<&2 do fund_code=` cat fund.py | grep print | cut -d '(' -f2| cut -d ')' -f1 | sed "s|'||g" | sed 's/ //g ' | awk -F ' , ' ' {print$1}'` sed -i "s|${fund_code}|${line2}|g" fund.py python fund.py > fund_log /fund_ ${line2}.log done } function main(){ if [ $day2 != $today ]; then sed -i "s|${day2}|${today}|g" fund.py fi if [ ! -d "fund_log" ]; then mkdir fund_log fi running } function sleeping(){ cd /zabbix/zabbix-agent/script main } sleeping |
最随便的操作
1. 授权给zabbix
注: 因为到时候要扔进zabbix去进行自动化操作, 你不给它工钱, 又想让它干活, 它会跟你大吼一个 "Permission denied" 然后罢工你信不信。
1 2 3 | chmod -R zabbix:zabbix /zabbix/zabbix-agent/script/ chmod +x /zabbix/zabbix-agent/script/ *.sh chmod +x /zabbix/zabbix-agent/script/ *.py |
2. zabbix-agentd要配置好
注: 这些值是要推送给监控上面的, 后面加的是你要监控的基金代码, so easy.
3. 定时炸弹
注: 定时运行爬虫, 爬取最新数据下来分析, 每5分钟爬一次。
1 | * /5 * * * * sh /zabbix/zabbix-agent/script/fund .sh |
运行之后回事什么样子的呢, 就像这个样子, 会在相关日志目录下生成相关的基金数据日志
注:上面已经说了, zabbix已经搭建好了吧, 那么现在就来配置告警吧。
zabbix大焖锅
注:这个是要在zabbix server中配置的。
告警方式双推送。
1. 钉钉
1.1钉钉告警shell
注:钉钉需要配置后台推送,扔个文件进去相关目录,记得授权和修改你的钉钉机器人地址, 有些python没有装requests模块的, pip install requests装一下就好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [root@608135bcf753 alertscripts] # pwd /data/zabbix-4 .2.5 /share/zabbix/alertscripts [root@608135bcf753 alertscripts] # cat dingding.py #!/usr/bin/python # -*- coding: utf-8 -*- import requests import json import sys import os headers = { 'Content-Type' : 'application/json;charset=utf-8' } api_url= "https://oapi.dingtalk.com/robot/send?access_token=8b8c40dfe9c7e98bc575dd963aac459f880" #需要更换你机器人的地址 def msg(text): json_text= { "msgtype" : "text" , "text" : { "content" : text }, "at" : { "atMobiles" : [ "186..." #需要@群里谁 ], "isAtAll" : False #是否全部@,True为是,False为否 } } print requests.post(api_url,json.dumps(json_text),headers=headers).content if __name__ == '__main__' : text = sys.argv[1] msg(text) |
1.2告警媒介类型
1.3动作
警示度
操作
消息传送指定
1.4 用户
报警媒介
2. 邮件
注:邮件不用配置后台哈,邮件这块我用的是zoho域名邮箱, zoho是什么?呃,水平有限不知道怎么解释。登登登....百度一下,你就知道。
基本上操作与钉钉无异。
触发器:{fund:funds_001071.diff()}=1
当发现当前值与上一个值有差异时(有差异代表已更新), 触发。
3.成果
页面动态展示
当发现更新,钉钉提醒
当发现更新,邮件提醒