• Почему выдает Syntax error: Operator expected?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Там кажется "=<" этот оператор пишется.
    Ух, скучаю по прологу=). 20 лет прошло, а вспоминаю с теплотой.
    правильно ли будет, если введу такой запрос: nabor(X,Y,Z,K,170).

    Ага. В том-то и весь смысл.
    Ответ написан
    1 комментарий
  • Не понять регулярку?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Эта регулярка будет совпадать с текстом, начинающимся с открывающейся квадратной скобки, состоящий из одного или более любых символов вплоть до ближайшей закрывающей скобки.
    Вопросик нужен, чтобы плюсик был нежадным, то есть не сожрал закрывающуюся скобку тоже. По умолчанию + и * жадные, то есть сожрут как можно больше символов, но чтобы в целом выражение сматчилось.
    Если ваш текст "12[34]56[78]90", то жадная регулярка (без вопросика) найдёт "[34]56[78]", а не жадная найдёт "[34]" и "[78]".
    Ответ написан
    Комментировать
  • Как исправить ошибку dictionary changed size during iteration?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Проблема связана с тем, что вы пытаетесь модифицировать словарь, по элементам которого итерируетесь.
    В условиях вашего кода это не проблема. Но вы должны сначала прежде чем начнётся цикл с удалениями) взять список пар элементов из вашего словаря.
    products.items() возвращает не список, а итератор по элементам словаря. Само собой этот итератор ломается как только вы удаляете из словаря первый элемент.
    Но если этот итератор до первого удаления полностью превратить в список, то удалять потом можно что хотите.
    for product_id, value in list(products.items()):
        if value['g_1'] == 0:
            del products[product_id]

    Или так:
    new_products_dict = {k: v for k, v in products.items() if v['g_1'] != 0}

    Здесь создаётся новый словарь из элементов, которые удовлетворяют вашим условиям.
    Ответ написан
    1 комментарий
  • Как сделать игру типа wofenshtein 3D?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Во-первых, у луча нет конца, только начало. У вас, наверно, отрезок.
    x = cos(fi) * R
    y = sin(fi) * R

    fi - угол в радианах: (градусы разделить 180 и умножить на Pi)
    R - радиус.

    Если ваш игрок не в нуле координат, то прибавьте его координаты:
    x = cos(fi) * R + x_игрока
    y = sin(fi) * R + y_игрока
    Ответ написан
    54 комментария
  • В чем преимущества платных почтовых сервисов перед своим?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Как всё платное по отношению к бесплатному и своему имеет следующие преимущества:
    • развёртывать самому не надо
    • следить за обновлениями и актуальностью не надо
    • почти не надо держать руку на пульсе современных тенденций спамерзкой и антиспамерской активности и нюансов
    • если ваш сервер попадёт в черный список, то это только ваша проблема, если покупной, то не только ваша=)
    Ответ написан
    1 комментарий
  • Где найти годный парсер адресов?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    У вас в примере очень чистые аккуратные адреса.
    Не очень понятно что вы имели в виду под "разложить по полочкам" и какие именно вам нужны полочки.
    Общий подход для переработки таких массивов слабо структурированных данных следующий.
    1. Процесс переработки должен быть поэтапный. Каждый этап должен вносить минимальные не калечащие изменения в как можно бОльшую часть датасета.
    2. Каждый этап должен быть прозрачным. Затронутые модификацией значения можно для удобства контроля (глазами) дедуплицировать и сортировать. Это позволит легко увидеть любые аномалии.
    3. Нужно вести подробную статистику изменений на каждом этапе. Все выбросы статистики должны проверяться глазами: слишком короткое минимальное слово или число слов, слишком длинные слова или наборы, слишком большие или малые числа...
    4. На каждом этапе нужно сохранять предыдущее состояние датасета или держать исходное и иметь удобный инструментарий для быстрого полного накатывания всех этапов на исходный датасет. Иногда этапы имеет смысл переставить местами, потому что обнаружилось незамеченное ранее калечащее изменение пару этапов назад.
    5. Серия мелких правок простыми операциями предпочтительнее сложных алгоритмов и регэкспов. Например в вашем случае гораздо лучше серией прсотых и понятных реплейсов заменить "ул." на "улица", "пл." на "площадь" и т.д.
      Чтобы не городить сложные регекспы имеет смысл сплитнуть строки по словам и заменять слова целиком, либо одним из шагов добавить в начало и конец строки пробелы. Это упростит регекспы и не даст наделать незаметных сразу косяков.
      Затронутые реплейсами строки можно отсортирвоать и дедуплицировать для просмотра глазами. Вдруг у вас есть много переулков Плава-Лагуны, которые принято тоже так сокращать.
    6. Если у вас есть справочник улиц, можно все записи в обработанном датасете, для которых нашлось однозначное соответствие улицы из справочника, пометить специальным флагом и больше не трогать в них улицы. Остаток можно снова подвергнуть сортировке и дедупликации (заодно можно частотность посчитать) и вычищать массово или точечно начиная с чамых частых случаев реплейсами, регекспами, и т.д.

    В вашем случае:
    1. Разделите адреса по запятой, сохраните в отдельные поля. лучше CSV, а не в БД. Проще. При обнаружении больше двух (в вашем случае) запятых сразу падайте, кричите, считайте число таких случаев, решайте вручную, если их не много, делайте отдельный фильтр с фиксом на отдельном этапе если много.
    2. Отсортируйте и дедуплицируйте (на секундочку) все три столбца по отдельности, просмотрите глазами получившиеся множества, поищите проблемы. Автоматизируйте этот шаг, он вам понадобится еще не раз.
    3. Обработайте датасет серией очевидных реплейсов, которые снизят разнообразие. Устранятся сокращения, множественные варианты одного и того же написания, различия в регистрах букв.
    4. Вытащите из ФИАС каталог улиц. Можно взять в формате КЛАДР, там попроще может оказаться и в отдельном файле. Разметьте очищаемый датасет ссылками на найденные в справочнике улицы. Просмотрите дедуплицированные и отсортированные (по алфавиту и по частотности) оставшиеся улицы. Поищите стандартные проблемы, которые можно пофиксить автоматически, внесите ручные правки для узких частных случаев (но программно реплейсами в отдельном этапе, чтобы можно было повторно обработать исходный датасет).


    Если у вас датасет весь примерно такой, как в примере, то я за пару тысяч рублей его вам почищу независимо от его размера. Почти независимо.=)
    Ответ написан
    2 комментария
  • Как поворачивать координату линии?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Начните с того, что, хотя бы, расскажите про двумерный или трехмерный случай идет речь.
    Обычно конец луча никто никуда не поворачивает.
    У вас есть луч и поверхность. Луч - это половина прямой. Если задать его уравнением и также уравнениями задать поверхность, а потом дополнительным неравенством добавить ограничения (поверхности и прямой), то решение получившейся системы будет точками пересечения луча и поверхности. Нас интересует ближайшая точка пересечения от начала луча.

    Ваша поверхность в точке пересечения с лучом имеет нормаль. Это перпендикуляр к поверхности в данной точке.
    Итак, дано:
    точка старта луча (O),
    точка пересечения (P) луча с поверхностью,
    вектор нормали (n) в этой точке.
    Нужно получить вектор (v) направления нового луча из точки P.

    Построим вектор PO = O - P (да-да, любые координаты - это вектор из начала координат) Если вычесть из вектора O вектор P, получим вектор направления из P в сторону O.

    Итак, у нас есть два вектора: PO и n. Угол падения у нас равен углу отражения и искомый вектор v будет лежать в плоскости этих двух векторов. Нам нужно повернуть вектор PO в упомянутой плоскости на удвоенный угол между нормалью и вектором PO.

    Любую плоскость можно задать точкой и нормалью (вектором перпендикуляра к плоскости). Чтобы получить этот перпендикуляр, назовём его вектором w, нужно сделать векторное произведение PO на n. Это будет ось вращения. Она направлена будет по правилу "буравчика".
    Чтобы повернуть вокруг этой оси ваш вектор PO, проще всего умножить его на матрицу поворота.
    Вот статья, которая это с рисунками показывает.
    https://scicenter.online/avtomatizatsiya-scicenter...
    Ответ написан
    3 комментария
  • Существует ли поле ввода даты в tkinter python3?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    https://google.gik-team.com/?q=tkinter+date+widget

    Вам уже посоветовали в комментариях это
    Ответ написан
    2 комментария
  • Как сделать редирект со своего сайта на другой с сохранением данных?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Если разные сайты на разных доменах, то не получится. Если на разных субдоменах, то тоже не получится, если куки ставятся конкретно на домен.
    Читайте про OAuth.
    Это именно то, что вам нужно.
    Для всех существующих фреймворков можно найти код поддержки этого протокола.
    Ответ написан
    Комментировать
  • Как правильно выполнить sql запрос при помощи bat файла?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Попробуйте так:
    set isql="C:\\Program Files(x86)\\FireBird\\FireBird_2_1\\BIN\\isql.exe"
    echo ^
    SELECT C.CODE AS "Табельный", C.NAME AS "Ф.И.О.", T.TRANZDATE AS "Дата", max(T.TRANZTIME) AS "Время", T.INFOSTR AS "Карта" sum(T.SUMM) AS "Сумма" FROM DOCUMENT D LEFT JOIN TRANZT T ON D.ID = T.DOCUMENTID JOIN CLIENT C ON D.CLIENTID = C.ID WHERE T.TRANZDATE = cast('now' as date) and D.STATE = 1 AND D.ISFISCAL = 1 AND D.CLIENTID >=0 AND T.TRANZTYPE = '36' GROUP BY C.CODE, C.NAME, T.TRANZDATE, T.INFOSTR; ^
    | %isql% 127.0.0.1/3050:E:\Torgovlya54\MAIN.GDB sysdba masterkey > outputfile.txt

    Каждая строчка, передаваемая isql должна закачиваться "^", чтобы попасть в одну команду с echo и передаться на вход isql.
    Весь выхлоп isql направлен в текстовый файл.
    У меня винды под рукой нет и файрбёрда тем более. так что пробуйте сами. Пишите если не получится -- будем еще смотреть.
    Ответ написан
    23 комментария
  • Python уведомление Windows?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вот например с помощью этой библиотеки:

    https://automated-testing.info/t/avtomatizacziya-w...
    Ответ написан
    Комментировать
  • Почему sql запрос обновляет только числовые значение?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Потому, что собирать sql таким способом (постановками строк и конкатенацией) очень плохая идея. Используйте параметризированные запросы. Даже в. Php это можно и нужно делать.
    Ответ написан
    Комментировать
  • Как с помощью regexp заменить 5 найденый элемент а не все?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Replace:(.*?</a>){5}
    To: $0<a href="url_here">text</a>
    Ответ написан
    1 комментарий
  • Как вызвать из GUI методы?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Мне кажется вы взялись сразу за много задач и пытаетесь решить их одновременно.
    Хорошее решение было бы таким:
    1. Оформить основную бизнес-логику как отдельную библиотеку.
    2. Сделать CLI интерфейс для для вашей функциональности. Это будет отдельный скрипт. который с помощью argparse разбирает параметры командной строки, извлекает из них аргументы и запускает бизнес-логику. Возможно уже этого будет достаточно. особенно если можно вынести редко изменяемую конфигурацию в отдельный json или yaml файл и сделать на уровне операционной системы биндинг вашей утилиты в контекстное меню "Открыть с помощью". CLI утилита вполне способна сделать все необходимые преобразования, создать новый документ и открыть его экселем или что там привязано к xls.
    3. Если так уж нужна GUI, то я бы не советовал для вашей задачи делать нативное приложение с окошками и кнопочками. Можно сделать тривиальный веб-сервис на flask с одной единственной веб-формой, которая позволяет загрузить xls-файл с компа и потом скачать закэшированный результат. Также можно отобразить ошибки преобразования сверстав их в html.

    Прелесть веб-сервиса в том, что деплой решения будет в контролируемой серверной среде, а не на машине пользователя, где что угодно может пойти не так.
    Разработка и поддержка такого решения обходится гораздо дешевле.

    Ок. Давайте более по существу.
    1. Содержимое всех ваших модулей с бизнес-логикой (ParseExcelOMS.py, ParseExcelMIS.py и т.д.) выделите в отдельные функции, входными аргументами которых будут имена файлов.
    2. Импортируйте эти модули в модуле с GUI, и там, получив имена файлов, вызывайте нужные функции.

    Если не будет получаться - приходите с конкретными вопросами. А-то не понятно что именно вам не понятно. Вроде код у вас слишком сложный для непонимания автором концепции функций.
    Ответ написан
  • Почему парсер всех внутренних ссылок сайта на Python не хочет парсить некоторые сайты?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    На в каждом теге "a" есть `href`.
    from urllib.parse import urlparse
    from bs4 import BeautifulSoup
    import requests
    import lxml
    DOMAIN = 'apexair.ru'
    HOST = 'http://' + DOMAIN
    FORBIDDEN_PREFIXES = ['#', 'tel:', 'mailto:']
    links = set()  # множество всех ссылок
    headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
    response = requests.get(HOST, headers=headers)
    # print(response.content)
    
    def add_all_links_recursive(url, maxdepth=1):
        # print('{:>5}'.format(len(links)), url[len(HOST):])
    
        # глубина рекурсии не более `maxdepth`
    
        # список ссылок, от которых в конце мы рекурсивно запустимся
        links_to_handle_recursive = []
        # получаем html код страницы
        request = requests.get(url, headers=headers)
        # парсим его с помощью BeautifulSoup
        soup = BeautifulSoup(request.content, 'lxml')
        # рассматриваем все теги <a>
    
        for tag_a in soup.find_all('a', href=lambda v: v is not None):
            link = tag_a['href']
    
            # если ссылка не начинается с одного из запрещённых префиксов
            if all(not link.startswith(prefix) for prefix in FORBIDDEN_PREFIXES):
                # проверяем, является ли ссылка относительной
                # например, `/oplata` --- это относительная ссылка
                # `http://101-rosa.ru/oplata` --- это абсолютная ссылка
                if link.startswith('/') and not link.startswith('//'):
                    # преобразуем относительную ссылку в абсолютную
                    link = HOST + link
                # проверяем, что ссылка ведёт на нужный домен
                # и что мы ещё не обрабатывали такую ссылку
                if urlparse(link).netloc == DOMAIN and link not in links:
                    links.add(link)
                    links_to_handle_recursive.append(link)
    
        if maxdepth > 0:
            for link in links_to_handle_recursive:
                add_all_links_recursive(link, maxdepth=maxdepth - 1)
    
    
    def main():
        add_all_links_recursive(HOST + '/')
        for link in links:
            print(link)
    
    
    if __name__ == '__main__':
        main()
    Ответ написан
    5 комментариев
  • Как с помощью OpenCV очистить подобные изображения?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Капча слабая:
    - шрифты не варьируются,
    - размер фиксированный,
    - линии однопиксельные,
    - шум однотипный.

    Не парьтесь с лишним от линиями. Переводите изображение в lab; работайте в монохромном канале яркости. Подберите похожий шрифт и размер, обучите 10 нейронок на свою цифру каждая. Сканируйте окном с пиксельных шагом. Этого будет достаточно

    Но! Линии однопиксельные толщиной, контрастные и обычно отличаются по цвету от фоновой цифры.
    Прям хочется убрать, правда?
    Можно это сделать алгоритмически.
    Перебираем все пиксели и анализируем соседние. При нахождении контрастного пикселя запускаем алгоритм "короеда" с дополнительным условием. Если углы между первым пикселем и последующими предокрашенными начинают отличаться более чем на пороговый епсилон, который ещё и от расстояния может уменьшаться, то процесс короеда останавливаем, линия не подтверждена. По факту естественного завершения короеда берём для каждой точки средний цвет из двух в перпендикулярном линии направлении.
    Ответ написан
    Комментировать
  • Как преобразовать строки Excel в datetime?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вытаскивайте данные из экселя в списки питона (чем вам там удобнее).
    Получается:
    data=[
        ['дата', '1', '2', '3', '4', '5', '6', '7', ...],
        ['Ноябрь 2019', '11', '22', '33', '44', '55', '66', '77', ...],
        ['Декабрь 2019', '11', '22', '33', '44', '55', '66', '77', ...],
        ...
    ]

    Потом собираете данные в нужный формат:
    import datetime
    import locale
    
    def replace_month(dt: str) -> str:
        dt = dt.replace('Январь', 'января')
        dt = dt.replace('Февраль', 'февраля')
        # ...
        return dt
    
    locale.setlocale(locale.LC_TIME, "ru_RU.utf8")
    head = data[0]
    data = data[1:]
    result_rows = []
    for row in data:
        for day, value in zip(head[1:], row[1:]):
            dt = replace_month(f'{day} {row[0]}')
            try:
                dt = datetime.datetime.strptime(dt, '%d %B %Y')
            except ValueError:
                pass  # тут у нас дата не сконвертнулась, например, 30 февраля. Пофиг.
            else:
                result_rows.append((dt, value))

    Код написал в браузере, не проверял, поэтому может где-то опечатался. Не обессутьте.
    Если форматы дат не постоянны, можно сделать несколько попыток преобразования по разным форматам и локалям.
    Закинуть как обратно в ексель - это тоже отдельная задача.
    Ответ написан
  • Как обойти граф?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Если у вас граф ацикличный (ну то есть без циклов совсем), то вам подойдёт следующий алгоритм (назовём его "метод эррозии"):
    1. Удаляем из графа все узлы (кроме заданных в условии), у которых только одна связь.
    2. Повторяем П.1. пока есть что удалять.
    3. PROFIT!!! У вас в графе остался только искомый путь.

    Можно как предложили выше:
    1. Начинаем от стартового узла А. Окрашиваем его цветом i=0.
    2. Окрашиваем всех неокрашенных соседей узлов цвета i цветом i + 1, пока не покрасим целевой узел B (это теперь текущий узел x=B), тогда останавливаем раскраску.
    3. От текущего узла x (покрашенного цветом i) переходим к его соседу с цветом i-1 запоминая значения x в списке L пока i>0.
    4. PROFIT!!! У нас в L все узлы пути от B к A. Остальные узлы можно удалить из графа.
    Ответ написан
    Комментировать
  • Как будет выглядеть этот код на Python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    def gcd(m: int, n: int) -> int:
        modulo = m % n    
        return n if modulo == 0 else gcd(n, modulo)
    
    n = int(input('Enter n:'))
    m = int(input('Enter m:'))
    divv = gcd(n, m)
    P = m // divv
    Q = n // divv
    
    print(P, Q)
    input('Press enter...')
    Ответ написан
    Комментировать
  • Как ускорить этот простой код?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Строго говоря этот код не делает ничего полезного. Только вычисляет степени и забывает их тут же. Это значит, что никаких побочных эффектов кроме задержки и нагрева процессора код не создаёт.
    Отсюда (да, звучит как занудство, но каков вопрос, таков и ответ!), логичные 4 варианта:
    1. Если нагрев процессора обязателен, то ускорить код можно уменьшив число 100000 в скобках.
    2. Если нагрев не нужен, то можно поставить time.sleep(3) и получить задержку нужной длительности.
    3. Если нам важна зависимость задержки от производительности компьютера, но код нужно немного ускорить, см Вариант 1..
    4. Если ни задержка, ни нагревание не нужно, то удалите ВЕСЬ цикл и вы получите минимально возможную задержку.

    Какого черта такие хреновые формулировки вопросов?!
    Ответ написан
    Комментировать