コード例 #1
0
def get_address(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит адрес место нахождения

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Место нахождения
    """
    result = ''
    try:
        result = soup.find('td', text='Место нахождения') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Почтовый адрес') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "address" could not be found'
            logging.error(logger(msg))
            comment.write('\t• адрес место нахождения организации;')
    return result
コード例 #2
0
def get_author_email(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит электронную почту

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Электронная почта
    """
    result = ''
    try:
        result = soup.find('td', text='Электронная почта') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Адрес электронной почты') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "author_email" could not be found'
            logging.error(logger(msg))
            comment.write('\t• электронную почту организации;')
    return result
コード例 #3
0
def get_contract_deposit(soup: BeautifulSoup, price: float,
                         comment: Commentator) -> float:
    """Функция находит обеспечение контракта

    :param comment: -- объект Commentator
    :param price: -- цена котракта
    :param soup: -- объект BeautifulSoup
    :return: Обеспечение контракта
    """
    result = 0.0
    try:
        raw_data = ''.join(soup.find('span', {'class': 'section__title'},
                                     text='Размер обеспечения исполнения контракта')
                           .find_next('span', {'class': 'section__info'})
                           .text
                           .split()[0]) \
            .strip()
        contract_deposit = to_numeric(raw_data)
        if contract_deposit < 1:
            contract_deposit = price * contract_deposit
        result = contract_deposit
    except AttributeError:
        msg = 'Data for the field "contract_deposit" could not be found'
        logging.error(logger(msg))
        comment.write('\t• обеспечение контракта;')
    return result
コード例 #4
0
def get_warranty_deposit(soup: BeautifulSoup, price: float,
                         comment: Commentator) -> float:
    """Функция находит обеспечение гарантийных обязательств

    :param comment: -- объект Commentator
    :param price: -- цена котракта
    :param soup: -- объект BeautifulSoup
    :return: Обеспечение гарантийных обязательств
    """
    result = 0.0
    try:
        warranty_deposit = to_numeric(''.join(
            soup.find(
                'span', {
                    'class': 'section__title'
                },
                text='Размер обеспечения гарантийных обязательств').find_next(
                    'span', {
                        'class': 'section__info'
                    }).text.split('\xa0')[:-1]).strip())
        if warranty_deposit < 1:
            warranty_deposit = price * warranty_deposit
        result = warranty_deposit
    except AttributeError:
        msg = 'Data for the field "warranty_deposit" could not be found'
        logging.error(logger(msg))
        comment.write('\t• обеспечение гарантийных обязательств;')
    return result
コード例 #5
0
def get_platform_url(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит адрес электронной площадки

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Адрес электронной площадки

    """
    result = ''
    try:
        result = soup.find('td', text='Адрес электронной площадки в ' +
                                      'информационно-телекоммуникационной сети ' +
                                      '«Интернет»') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Адрес электронной площадки в ' +
                                    'информационно-телекоммуникационной сети "Интернет"') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "platform_url" could not be found'
            logging.error(logger(msg))
            comment.write('\t• адрес электронной площадки;')
    return result
コード例 #6
0
def get_author_phone(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит телефон

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Телефон
    """
    result = ''
    try:
        result = soup.find('td', text='Телефон') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Номер контактного телефона') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "author_phone" could not be found'
            logging.error(logger(msg))
            comment.write('\t• телефон организации;')
    return result
コード例 #7
0
def get_end_date(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит дату и время окончания подачи заявок(по местному времени заказчика)

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Дата и время окончания подачи заявок(по местному времени заказчика)
    """
    result = ''
    try:
        result = date_formatter(
            soup.find('span',
                      text='(по местному времени заказчика)').find_next(
                          'td').text.split()[0].strip())
    except AttributeError:
        try:
            result = datetime_formatter(
                soup.find('span', {
                    'class': 'section__title'
                },
                          text='Дата и время окончания срока подачи заявок').
                find_next('span', {
                    'class': 'section__info'
                }).text.strip())
        except AttributeError:
            msg = 'Data for the field "end_date" could not be found'
            logging.error(logger(msg))
            comment.write('\t• дату и время окончания подачи заявок;')
    return result
コード例 #8
0
def get_init_date(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит дату размещения извещения

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Дата размещения извещения

    """
    result = ''
    try:
        result = date_formatter(
            soup.find('td', text='Дата размещения извещения').find_next(
                'td').text.split()[0].strip())
    except AttributeError:
        try:
            result = datetime_formatter(
                soup.find('span', {
                    'class': 'cardMainInfo__title'
                },
                          text='Размещено в ЕИС').find_next(
                              'span', {
                                  'class': 'cardMainInfo__content'
                              }).text.strip())
        except AttributeError:
            msg = 'Data for the field "init_date" could not be found'
            logging.error(logger(msg))
            comment.write('\t• дату размещения извещения о закупке;')
    return result
コード例 #9
0
def get_type(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит способ размещения закупки

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Способ размещения закупки
    """
    result = ''
    # TODO: если новая структура HTML-страницы станет преимущественной, то блоки try – поменять местами
    try:
        result = soup.find('td', text='Способ размещения закупки') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Способ определения поставщика (подрядчика, исполнителя)') \
                .find_next('span', {'class': 'section__info'}) \
                .text
        except AttributeError:
            msg = 'Data for the field "type" could not be found'
            logging.error(logger(msg))
            comment.write('\t• способ размещения закупки;')
    return result
コード例 #10
0
def get_result_date(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит дату подведения итогов

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Дата подведения итогов
    """
    result = ''
    try:
        result = date_formatter(
            soup.find('td', text='Дата подведения итогов').find_next(
                'td').text.split()[0].strip())
    except AttributeError:
        try:
            result = datetime_formatter(
                soup.find('span', {
                    'class': 'section__title'
                },
                          text="""
                            Дата и время рассмотрения и оценки первых частей заявок
                        """).find_next('span', {
                              'class': 'section__info'
                          }).text.strip())
        except AttributeError:
            msg = 'Data for the field "result_date" could not be found'
            logging.error(logger(msg))
            comment.write('\t• дату подведения итогов;')
    return result
コード例 #11
0
def get_author_manager(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит контактное лицо

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Контактное лицо
    """
    result = ''
    try:
        result = soup.find('td', text='Контактное лицо') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Ответственное должностное лицо') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "author_manager" could not be found'
            logging.error(logger(msg))
            comment.write('\t• ФИО контактного лица организации;')
    return result
コード例 #12
0
def get_author_name(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит наименование организации

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Наименование организации
    """
    result = ''
    try:
        result = soup.find('td', text='Наименование организации') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'section__title'},
                               text='Организация, осуществляющая размещение') \
                .find_next('span', {'class': 'section__info'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "author_name" could not be found'
            logging.error(logger(msg))
            comment.write('\t• наименование организации;')
    return result
コード例 #13
0
def get_author_ogrn(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит ОГРН

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: ОГРН
    """
    result = ''
    try:
        result = soup.find('td', text='ОГРН') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        msg = 'Data for the field "author_ogrn" could not be found'
        logging.error(logger(msg))
        comment.write('\t• ОГРН организации;')
    return result
コード例 #14
0
def get_price(soup: BeautifulSoup, comment: Commentator) -> float:
    """Функция находит начальную (максимальную) цену договора

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: начальная (максимальная) цена договора
    """
    result = np.nan
    try:
        result = to_numeric(
            soup.find('div', {
                'class': 'price-block__value'
            }).text.replace('\xa0', '').split()[0])
    except AttributeError:
        msg = 'Data for the field "price" could not be found'
        logging.error(logger(msg))
        comment.write('\t• начальную (максимальную) цену договора;')
    return result
コード例 #15
0
def get_id(soup: BeautifulSoup, comment: Commentator) -> int:
    """Функция находит реестровый номер извещения

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: реестровый номер извещения
    """
    result = 0
    try:
        result = int(
            soup.find('div', {
                'class': 'registry-entry__header-mid__number'
            }).text.strip().split()[1].strip())
    except AttributeError:
        msg = 'Data for the field "id" could not be found'
        logging.error(logger(msg))
        comment.write('\t• реестровый номер извещения;')
    return result
コード例 #16
0
def get_law(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит федеральный закон

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: федеральный закон
    """
    result = ''
    try:
        result = soup.find('div', {'class': 'registry-entry__header-top__title text-truncate'}) \
            .text \
            .strip() \
            .split()[0] \
            .strip()
    except AttributeError:
        msg = 'Data for the field "law" could not be found'
        logging.error(logger(msg))
        comment.write('\t• номер федерального закона;')
    return result
コード例 #17
0
def get_url(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит URL-закупки на ЕИС в сфере закупок

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: URL-закупки на ЕИС в сфере закупок
    """
    result = ''
    try:
        _url = soup.find('div', {'class': 'registry-entry__header-mid__number'}) \
            .find('a') \
            .get('href')
        if 'https://zakupki.gov.ru' not in _url:
            _url = f"https://zakupki.gov.ru{_url}"
        result = _url
    except AttributeError:
        msg = 'Data for the field "url" could not be found'
        logging.error(logger(msg))
        comment.write('\t• URL-закупки на ЕИС в сфере закупок;')
    return result
コード例 #18
0
def get_timezone(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит часовой пояс заказчика

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Часовой пояс заказчика
    """
    result = ''
    try:
        result = soup.find('td', text='Дата начала срока подачи заявок') \
            .find_next('td') \
            .text \
            .split()[1] \
            .replace('(', '') \
            .replace(')', '') \
            .strip()
    except AttributeError:
        msg = 'Data for the field "timezone" could not be found'
        logging.error(logger(msg))
        comment.write('\t• часовой пояс заказчика;')
    return result
コード例 #19
0
def get_comment(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит преимущества, требования к участникам

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Преимущества, требования к участникам
    """
    result = ''
    _result = ''
    try:
        result += '\nПреимущества:\n\n'
        result += soup.find('span', {'class': 'section__title'}, text='Преимущества') \
                      .find_next('span', {'class': 'section__info'}) \
                      .text \
                      .strip() + '\n'
        result += '\nТребования к участникам:\n\n'
        result += soup.find('span', {'class': 'section__title'}, text='Требования к участникам') \
            .find_next('span', {'class': 'section__info'}) \
            .text \
            .strip() \
            .replace('\n', '') \
            .replace('\t', '') \
            .replace('\xa0', ' ') + '\n'
        result += '\nОграничения и запреты:\n\n'
        result += soup.find('span', {'class': 'section__title'}, text='Ограничения и запреты') \
            .find_next('span', {'class': 'section__info'}) \
            .text \
            .strip() \
            .replace('\n', '') \
            .replace('\t', '') \
            .replace('\xa0', ' ') + '\n'
        _result = result
    except AttributeError:
        msg = 'Data for the field "timezone" could not be found'
        logging.error(logger(msg))
        comment.write('\t• требования и ограничения к участникам;')
    return _result
コード例 #20
0
def get_tender_deposit(soup: BeautifulSoup, comment: Commentator):
    """Функция находит обеспечение заявки

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Обеспечение заявки
    """
    result = None
    try:
        response = soup.find('td', text='Обеспечение заявки') \
            .find_next('td') \
            .text \
            .strip()
        if response == 'Не требуется':
            result = 0.0
        else:
            try:
                result = to_numeric(response)
            except ValueError:
                result = response
                msg = f'Cannot convert "tender_deposit"={response} to float'
                logging.error(logger(msg))
    except AttributeError:
        try:
            result = to_numeric(''.join(
                soup.find('span', {
                    'class': 'section__title'
                },
                          text='Размер обеспечения заявки').find_next(
                              'span', {
                                  'class': 'section__info'
                              }).text.split('\xa0')[:-1]).strip())
        except AttributeError:
            msg = 'Data for the field "tender_deposit" could not be found'
            logging.error(logger(msg))
            comment.write('\t• обеспечение заявки;')
    return result
コード例 #21
0
def get_description(soup: BeautifulSoup, comment: Commentator) -> str:
    """Функция находит наименование закупки

    :param comment: -- объект Commentator
    :param soup: -- объект BeautifulSoup
    :return: Наименование закупки
    """
    result = ''
    try:
        result = soup.find('td', text='Наименование закупки') \
            .find_next('td') \
            .text \
            .strip()
    except AttributeError:
        try:
            result = soup.find('span', {'class': 'cardMainInfo__title'}, text='Объект закупки') \
                .find_next('span', {'class': 'cardMainInfo__content'}) \
                .text \
                .strip()
        except AttributeError:
            msg = 'Data for the field "description" could not be found'
            logging.error(logger(msg))
            comment.write('\t• наименование/объект закупки;')
    return result
コード例 #22
0
def get_card_data(card=None) -> dict:
    """Функция парсит информацию о закупке и записывает с структурированный словарь

    :param card: -- объект BeautifulSoup
    :return: -- словарь со структуированной информацией о закупке
    """
    comment = Commentator()
    card_data = create_card()
    msg = f'Card #{hash(card)} starts recording'
    logging.info(logger(msg))
    card_data['time'] = time.time()

    # пишем данные из карточки закупки
    card_data['id'] = get_id(card, comment)  # 'id', Реестровый номер извещения
    card_data['law'] = get_law(card, comment)  # 'law', Федеральный закон
    card_data['url'] = get_url(
        card, comment)  # 'url', URL-закупки на ЕИС в сфере закупок
    card_data['price'] = get_price(
        card, comment)  # 'price', Начальная (максимальная) цена договора

    # пишем данные из по ссылке закупки, для 44-ФЗ и 223-ФЗ представление страницы с данными различается
    try:
        lot_url = card_data['url']
        soup: BeautifulSoup = get_soup(get_request(lot_url))
        msg = f'Card #{hash(card)} starts recording by url'
        logging.info(logger(msg))

        card_data['type'] = get_type(
            soup, comment)  # 'type', Способ размещения закупки
        card_data['description'] = get_description(
            soup, comment)  # 'description', Наименование закупки
        card_data['init_date'] = get_init_date(
            soup, comment)  # 'init_date', Дата размещения извещения
        card_data['platform'] = get_platform(
            soup, comment)  # 'platform', Наименование электронной площадки
        card_data['platform_url'] = get_platform_url(
            soup, comment)  # 'platform_url', Адрес электронной площадки
        card_data['tender_deposit'] = get_tender_deposit(
            soup, comment)  # 'tender_deposit', Обеспечение заявки
        card_data['contract_deposit'] = get_contract_deposit(
            soup, card_data['price'],
            comment)  # 'contract_deposit', Обеспечение контракта
        card_data['warranty_deposit'] = get_warranty_deposit(
            soup, card_data['price'], comment
        )  # 'warranty_deposit', Обеспечение гарантийных обязательств
        card_data['author_name'] = get_author_name(
            soup, comment)  # 'author_name', Наименование организации
        card_data['author_inn'] = get_author_inn(soup,
                                                 comment)  # 'author_inn', ИНН
        card_data['author_ogrn'] = get_author_ogrn(
            soup, comment)  # 'author_ogrn', ОГРН
        card_data['address'] = get_address(
            soup, comment)  # 'address', Место нахождения
        card_data['author_manager'] = get_author_manager(
            soup, comment)  # 'author_manager', Контактное лицо
        card_data['author_email'] = get_author_email(
            soup, comment)  # 'author_email', Электронная почта
        card_data['author_phone'] = get_author_phone(
            soup, comment)  # 'author_phone', Телефон
        card_data['start_date'] = get_start_date(
            soup, comment)  # 'start_date', Дата начала срока подачи заявок
        card_data['end_date'] = get_end_date(
            soup, comment
        )  # 'end_date', Дата и время окончания подачи заявок(по местному времени заказчика)
        card_data['timezone'] = get_timezone(
            soup, comment)  # 'timezone', Часовой пояс заказчика
        card_data['result_date'] = get_result_date(
            soup, comment)  # 'result_date', Дата подведения итогов
        comment.write(get_comment(
            soup, comment))  # 'comment',  # Комментарий к сделке
    except AttributeError:
        msg = f'Failed to make an entry from the purchasing #{hash(card)}'
        logging.error(logger(msg))

    # Пишем данные из раздела документы карточки закупки
    try:
        docs_url = make_part_url(card_data['url'])
        soup = get_soup(get_request(docs_url))
        msg = f'Card #{hash(card)} starts recording by documets url {docs_url}'
        logging.info(logger(msg))
        try:
            card_data['docs'] = get_docs_hrefs223(soup)
        except AttributeError:
            card_data['docs'] = get_docs_hrefs44(soup)
    except AttributeError:
        msg = f'Data for the field "docs" could not be found by url'
        logging.error(logger(msg))
        comment.write('\t• ссылки на документы;')

    card_data[
        'comment'] = comment.comment  # 'comment',  # Комментарий к сделке

    return card_data