zoukankan      html  css  js  c++  java
  • 汇率转换器

    """
    一个货币转换器,支持货币汇率实时转换,汇率使用 https://finance.google.cn/finance/converter 谷歌的服务
    """
    import unittest
    import re
    from parameterized import parameterized, param
    from app.apis.fliggy.utils import LogManager, RequestClient, decorators, RedisManager
    from app import config as app_config
    
    
    class CurrencyConverter(object):
        _rate_pattern = re.compile('<span class=bld>(S*?) .*?</span>')
        _redis = None
        _log = LogManager('CurrencyConverter').get_logger_and_add_handlers()
    
        def __init__(self, from_currency, to_currency='CNY'):
            """
            :param from_currency: 需要被转换的货币
            :param to_currency: 需要兑换成的货币
            """
            self._from_currency = from_currency
            self._to_currency = to_currency
            self._rate = None
            if not self._redis:  # 使用数据库7
                self.__class__._redis = RedisManager(app_config.redis_host, port=app_config.redis_port,
                                                     db=7, password=app_config.redis_password).get_redis()
            self._redis_key_name = 'rate:{}_{}'.format(self._from_currency, self._to_currency)
    
        @decorators.handle_exception(3)  # 发生错误后重试三次
        def _acquire_rate_from_google_finance(self):
            """从谷歌网站实时请求和解析出汇率"""
            url = 'https://finance.google.cn/finance/converter'
            params = {
                'a': 1,
                'from': self._from_currency,
                'to': self._to_currency,
                'meta': ''
            }
            resp = RequestClient().request_with_proxy('get', url, params=params)
            self._rate = self._rate_pattern.search(resp.text).group(1)
    
        def get_rate(self):
            """获取汇率,汇率优先使用reids,redis中不存在的汇率则从google实时获取,获取后放入redis中设置1小时过期"""
            if not self._redis.exists(self._redis_key_name):
                self._log.debug('开始从google获取汇率')
                self._acquire_rate_from_google_finance()
                rate = self._rate
                if rate:
                    self._redis.set(self._redis_key_name, rate)
                    self._redis.expire(self._redis_key_name, 60 * 60)
                    return float(rate)
                else:
                    self._log.error('从google获取汇率失败')
                    raise Exception('从google获取汇率失败')
            else:
                self._log.debug('开始从redis中获取汇率')
                return float(self._redis.get(self._redis_key_name).decode('utf8'))
    
    
    class _Test(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            cls.log = LogManager('test').get_logger_and_add_handlers()
    
        @parameterized.expand([param('USD'),
                               param('CNY', to_currency='USD')
                               ])
        def test_from_usd_to_cny(self, from_currency, to_currency='CNY'):
            """
            测试美元和人民币之间的转换
            :return:
            """
            converter = CurrencyConverter(from_currency, to_currency)
            rate = converter.get_rate()
            self.assertIsNotNone(rate, msg='获取的汇率错误')
            self.log.debug('从 {} 转换为 {} 的汇率是 --> {}'.format(from_currency, to_currency, rate))
    
    
    if __name__ == '__main__':
        unittest.main()
  • 相关阅读:
    Codeforces Round #104 (Div. 1) C. Lucky Subsequence
    UVALive 4848 Tour Belt
    ...
    HDU4609 计数问题+FFT
    hdu6129 Just Do It!
    hdu6133 Army Formations 线段树合并
    迭代FFT
    第二类Stirling数
    project euler113
    HBase 常用shell命令
  • 原文地址:https://www.cnblogs.com/ydf0509/p/9140397.html
Copyright © 2011-2022 走看看