четверг, 10 июля 2014 г.

Курсы валют из будущего и странности центрального банка России

Сначала предыстория... Мне понадобилось для одной хитрой платформы поставлять курсы валют. По умолчанию эта платформа умеет забирать курсы валют с национального банка Украины и с центрального банка России. При этом если допустим ты указываешь, что необходимо брать курсы валют с Украины, то там в перечне курсов появляется стоимость рубля в гривнах, а если берёшь курсы валют с ЦБР (центральный банк России), то там есть стоимость гривен. В целом на платформе по расписанию срабатывает скрипт, который забирает котировки в XML формате с сайтов банков, далее он их парсит и кладет в базу данных. Проблема вся в том, что формат представления XML отличается конкретно и по идее надо переписывать парсер. Но мне то надо забирать курсы валют с национального банка кыргызской республики (НБКР), а там вообще третий формат... Я решил пойти по наименьшему пути сопротивления - а именно забирать курсы с НБКР и приводить их в такой же вид, как XML у ЦБР, а дальше отдавать результат на саму платформу. Так вот у каждой валюты есть свой цифровой уникальный код + как оказалось у некоторых банков есть свой внутренний идентификатор каждой валюты (например у ЦБР выглядит примерно так - R01234). Так вот в XML у ЦБР я нашел идентификаторы под все вообразимые валюты, кроме рубля. Немного поставило меня в ступор, но я решил проблему тем, что для своего парсера валют ввёл внутренний идентификатор от балды. Ну как бы ладно - всё работает и хорошо... Далее я сливаю XML файл с НБКР (а дело было 9 июля) и глядя в него смотрю на дату актуальности курсов валют на определенный период и вижу что она равняется 10 июля (т.е. такое складывается ощущение, что в НБКР работают Нострадамусы и они наперед знают какой будет курс валют на завтра)... Ну как бы фиг с ним - главное что пашет... А теперь код:

Писано всё это дело на python 3 версии...

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Скрипт для сбора данных о курсах валют с НБКР с дальнейшим преобразованием вида XML файла
# Дата последнего исправления: 9.07.2014
# Разработал: Constantine
#------------------------------------------------------------------------------------------------------------------------------------

# Импорт необходимых модулей

from datetime import datetime
from urllib.request import Request, urlopen, urlretrieve
from urllib.error import  URLError
import xml.etree.ElementTree as etree
import os

# Начало программы
print ('\n \t',str(datetime.now()))
print ('-'*40)

# Объявление переменных

ndaily = ('daily.xml') # Необработанный XML файл, получаемый с www.nbkr.kg и находящийся в директории, где пашет парсер
geturl = ('http://www.nbkr.kg/XML/daily.xml') # Урл, откуда берём необработанный XML
rdaily = ('course.xml') # Куда будем сохранять данные

# Объявление функций


def checkget(text): # Функция проверки связи и доступности файла daily.xml на сервере НБКР
    req = Request(text)
    try:
        response = urlopen(req)
        return 1
    except URLError as e:
        if hasattr(e, 'reason'):
            print('Server nbkr.kg is unavaliable.')
            print('Reason: ', e.reason)
        elif hasattr(e, 'code'):
            print('Server return an error code.')
            print('Error code: ', e.code)
        else:
            # everything is fine
            print ('Ok')
        return 0

def restest(rfile):
    try:
        with open(rfile, 'r+') as file:
            pass
        return 1
      
    except IOError as e:
        print ("Cant find result file. Trying to create new...")
        return 0


def restest2(rfile):
    try:
        with open(rfile, 'w', encoding='utf8') as file:
            pass
        return 1
    except IOError as e:
        print ("Can't create result file. Check your permissions...")
        return 0

def parser(nd, rd):
    try:
        tree = etree.parse(nd)
        root = tree.getroot()
        f = open(rd, 'w', encoding='utf8')
        f.write('<?xml version="1.0" encoding="windows-1251" ?>\n')
        f.write('<ValCurs Date="'+root.attrib['Date']+'" ''name="'+root.attrib['Name']+'">\n')
       
        for i in range(len(root)):
            isocode = (root[i].attrib['ISOCode'])
            if isocode == 'USD':
                idc = 'R01235'
                numcode = '840'
                vname = 'Доллар США'
            elif isocode == 'EUR':
                idc = 'R01239'
                numcode = '978'
                vname = 'Евро доллар'
            elif isocode == 'KZT':
                idc = 'R01335'
                numcode = '398'
                vname = 'Казахский тенге'
            elif isocode == 'RUB':
                idc = 'R06785'
                numcode = '643'
                vname = 'Российский рубль'
            f.write('<Valute ID="'+idc+'">\n')
            f.write('    <NumCode>'+numcode+'</NumCode>\n')
            f.write('    <CharCode>'+isocode+'</CharCode>\n')
            f.write('    <Nominal>'+root[i].find('Nominal').text+'</Nominal>\n')
            f.write('    <Name>'+vname+'</Name>\n')
            f.write('    <Value>'+root[i].find('Value').text+'</Value>\n')
            f.write('</Valute>\n')
        f.write('</ValCurs>')
        f.close()
        return 1
    except:
        return 0

# Начало работы программы

print ('System check... ')

abc = checkget(geturl)

if abc < 1:
    print ('Can not establish a connection. Please check your channels')
elif abc == 1:
    print ('File on nbkr.kg is avaliable. \nDownload begining... ')
    destination = geturl.rsplit('/',1)[1]
    urlretrieve(geturl, destination)
    print ('File download ',geturl, 'is done.')
else:
    print ('Unexpected error. Programm exiting...')
   
if os.path.isfile(ndaily) and os.path.getsize(ndaily)>0:
    print ('File is ready... Data load is begining...')
else:
    print ('File not ready for loading, probably daily.xml is corupt!')


wt = restest(rdaily)

if wt==1:
    resp = parser(ndaily, rdaily)
elif wt==0:
    wta = restest2(rdaily)
    if wta ==1:
        print ('File course.xml has been created, Trying to parse and load data into file...')
        resp = parser(ndaily, rdaily)
    elif wta ==0:
        print ("Can't make result file. Please check your pewrmissions...")

if resp == 1:
    print ('Data load is done!\n'+'-'*40)
else:
    print ('Can\'t load data. File is unavaliable for write.')

# Конец программы


Комментариев нет:

Отправить комментарий