diff --git a/README.md b/README.md index e5126b7..873e827 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,28 @@ # MetricAliexpressExchangeRate -CSV экспортер курса Aliexpress и курса ЦБ РФ + +[![MIT License](https://img.shields.io/github/license/serega404/EasyESPRealy)](https://github.com/serega404/MetricAliexpressExchangeRate) + +Экспортер курса Aliexpress и ЦБ РФ + +Для сбора метрик я использую [Victoria Metric](https://github.com/VictoriaMetrics/VictoriaMetrics) в режиме CSV + +Особая благадарность сайту cbr-xml-daily.ru за предоставление данных с сайта cbr.ru + +### Запуск через Cron + +``` Cron +*/10 * * * * python3 /home/bots/KursExporter/main.py +``` + +### Отображение в Grafana + +Файл для импорта: [grafana.json](./grafana.json) + + +### Библиотеки + +* [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/) + +### Лицензия + +Распространяется под MIT License. Смотри файл [`LICENSE`](./LICENSE) для того что бы узнать подробности. diff --git a/grafana.json b/grafana.json new file mode 100644 index 0000000..37a9fea --- /dev/null +++ b/grafana.json @@ -0,0 +1,250 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 34, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "RvWcMg1nk" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "currencyRUB" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 4, + "interval": "10m", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "RvWcMg1nk" + }, + "editorMode": "code", + "exemplar": false, + "expr": "last_over_time(exchange_usd_rub{source=\"Central Bank Of Russia\"}[1h])", + "format": "time_series", + "hide": false, + "instant": true, + "legendFormat": "CBRF", + "range": false, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "RvWcMg1nk" + }, + "editorMode": "code", + "exemplar": false, + "expr": "last_over_time(exchange_usd_rub{source=\"AliExpress\"}[1h])", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "Ali", + "range": false, + "refId": "A" + } + ], + "title": "Разница", + "transformations": [ + { + "id": "calculateField", + "options": { + "mode": "reduceRow", + "reduce": { + "reducer": "diff" + }, + "replaceFields": true + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "RvWcMg1nk" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 1, + "mappings": [], + "max": 100, + "min": 40, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "currencyRUB" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 2, + "interval": "10m", + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "RvWcMg1nk" + }, + "editorMode": "code", + "expr": "exchange_usd_rub{}", + "legendFormat": "{{source}}", + "range": true, + "refId": "A" + } + ], + "title": "Курс доллара", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "hidden": false + }, + "timezone": "", + "title": "Курс AliExpress", + "uid": "ghA0PTGVk", + "version": 10, + "weekStart": "" +} \ No newline at end of file diff --git a/grafana.png b/grafana.png new file mode 100644 index 0000000..dcad1ff Binary files /dev/null and b/grafana.png differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..424e5b1 --- /dev/null +++ b/main.py @@ -0,0 +1,55 @@ +import requests, re, json +from bs4 import BeautifulSoup + +# Config + +Ali1USDPageURL = 'https://aliexpress.ru/item/32892046259.html' +CBRFApiSiteURL = 'https://www.cbr-xml-daily.ru/daily_json.js' +MetricServerURL = 'http://192.168.0.100:8428/' + +KursAli = "" +KursCBRF = "" + +# Ali + +site = requests.get(Ali1USDPageURL) + +if (site.status_code != 200): + print("Ali request error: " + str(site.status_code)) + exit() + +soup = BeautifulSoup(site.text, "html.parser") + +for tag in soup.find_all("span", class_="product-price-current"): + KursAli = (''.join(x for x in tag.text if (x.isdigit() or x == ','))).replace(',','.') + +print("Курс Ali: " + KursAli) + +# ЦБ РФ + +site = requests.get(CBRFApiSiteURL) + +if (site.status_code != 200): + print("Kurs request error: " + str(site.status_code)) + exit() + +KursCBRF = str(json.loads(site.text)["Valute"]["USD"]["Value"]) +print("Курс ЦБ РФ: " + KursCBRF) + +# Send metrics ↓ + +url = MetricServerURL + 'api/v1/import/csv?format=1:label:source,2:metric:exchange_usd_rub' + +if KursCBRF != '': + x = requests.post(url, "Central Bank Of Russia," + KursCBRF) + if (x.status_code != 200 and x.status_code != 204): + print("Не удалось отправить метрику: " + str(x.status_code)) +else: + print("Курс ЦБ РФ пуст") + +if KursAli != '': + x = requests.post(url, "AliExpress," + KursAli) + if (x.status_code != 200 and x.status_code != 204): + print("Не удалось отправить метрику: " + str(x.status_code)) +else: + print("Курс Али пуст") \ No newline at end of file