Пример #1
0
    def get_for_date(self, date):
        if date < self._min_supported_date:
            return

        log.info("Getting Sberbank %s rates for %s...", self._name, date)

        day_urls = self._get_urls(date)
        if not day_urls:
            log.debug("There is no data for Sberbank %s rates for %s.", self._name, date)
            return

        for url_id, url in enumerate(day_urls):
            try:
                xls_contents = fetch_url(url).content
            except RequestException as e:
                if e.response is not None and e.response.status_code == requests.codes.not_found:
                    # It's a common error when we have 2 reports per day
                    (log.warning if url_id == len(day_urls) - 1 else log.debug)(
                        "Unable to download '%s': %s. Skipping it...", url, e)
                else:
                    raise Error("Failed to get Sberbank currency rates from {}: {}.", url, e)
            else:
                break
        else:
            return

        try:
            rates = self.parse(xls_contents)
        except Exception as e:
            raise Error("Error while reading Sberbank currency rates obtained from {}: {}", url, e)

        log.debug("Gotten rates: %s", rates)

        return rates
Пример #2
0
    def _get_month_urls(self, date):
        month_rates_url = "{prefix}moscow/ru/quotes/{archive}/index.php?year115={year}&month115={month}".format(
            prefix=self.__url_prefix, archive=self._sberbank_archive_name, year=date.year, month=date.month)

        rate_list_html = fetch_url(month_rates_url).text

        base_url = "/common/img/uploaded/banks/uploaded_mb/c_list/{}/download/".format(self._sberbank_rates_list_name)

        rate_url_matches = list(re.finditer(
            r'"(?P<url>' + re.escape(base_url) + r'(?P<year>\d{4})/(?P<upload_month>\d{2})/' +
            self._sberbank_rates_name + r'(?P<month>\d{2})(?P<day>\d{2})(_\d)?.xls)"', rate_list_html, re.VERBOSE))

        day_urls = {}

        if not rate_url_matches and not _is_month_may_be_empty(date):
            raise Error("Server returned an unexpected response")

        for match in rate_url_matches:
            rate_year, rate_month = int(match.group("year")), int(match.group("month"))

            if (rate_year, rate_month) != (date.year, date.month):
                # If we ask for data that Sberbank doesn't have it returns data for previous/current month/year.
                if not day_urls and _is_month_may_be_empty(date):
                    return day_urls

                raise Error("Server returned data for invalid month ({:02d}.{} instead of {:02d}.{}) on {}",
                            rate_month, rate_year, date.month, date.year, month_rates_url)

            url = match.group("url")
            if "://" not in url:
                url = self.__url_prefix + url.lstrip("/")

            day_urls.setdefault(int(match.group("day")), []).append(url)

        return day_urls
Пример #3
0
def _get_tinkoff_rates():
    rates = {}

    try:
        for rate in fetch_url("https://www.tinkoff.ru/api/v1/currency_rates").json()["payload"]["rates"]:
            if (
                rate["category"] == "DepositPayments" and
                rate["fromCurrency"]["name"] in ("USD", "EUR") and
                rate["toCurrency"]["name"] == "RUB"
            ):
                rates[rate["fromCurrency"]["name"] + "_SBRF"] = (Decimal(rate["sell"]), Decimal(rate["buy"]))

        if len(rates) != 2:
            raise Error("Unable to find all requested rates in API response")
    except Exception as e:
        raise Error("Failed to get currency rates from Tinkoff: {}.", e)

    return rates