О чем это
В этой статье мы разберемся, что такое «робот», поймем, как они помогают операционистам, напишем и запустим простого робота на Python.
Исходный код робота и данные для работы можно скачать здесь.
Макросы на стероидах
Робот имитирует действия человека, сидящего за компьютером.
Он может открывать программы, нажимать в них на кнопки, читать и вводить данные.
То, что сейчас называется роботом, впервые стало популярно в 80-х годах прошлого века под названием «макрос»: при нажатии определенной комбинации клавиш макрос вместо оператора вводил и считывал необходимые данные из текстового терминала, что помогало форматировать текст и выполнять другие рутинные операции.
С появлением графических интерфейсов макросы на время остановились в развитии. Прорыв случился только с появлением пакета Microsoft Office ’97 в 1997 году с появлением возможности записывать действия пользователя и превращать их в исполняемый код на Visual Basic for Applications.
Сейчас макросы наиболее активно используются в онлайн-играх, для автоматизации тестирования и в офисных пакетах.
В 2010 начинается бурный переход от самописных решений к коробочным и облачным решениям, которые не всегда легко изменить под потребности клиента. Например, довольно трудно как технически, так и организационно из облачного решения обратиться к учетной системе компании и вытянуть из нее какие-либо справочные данные.
Для решения подобных задач часто привлекают операционистов. Например, в самом простом случае, операционист может открыть окно локальной программы и запись за записью синхронизировать справочник с другой облачной программой.
Сценарии могут быть и более сложными, причем нередко требуется применение интеллекта операциониста.
Задача нашего первого робота
Наш первый робот будет имитировать работу операциониста CRM в сценарии «обогати клиентские данные в локальной CRM полем ИНН из облачного сервиса».
Процесс AS IS (как работает операционист CRM до появления робота)
-
Операционист открывает локальную CRM-систему. Для нашего учебного примера для простоты мы не будем устанавливать промышленную CRM, а воспользуемся приложением Microsoft Office Excel, в котором будет открыт файл с полями «Фамилия», «Имя», «Отчество», «Дата рождения» и «Номер паспорта».
-
Операционист запускает браузер и переходит на страницу https://service.nalog.ru/inn.do
-
Операционист читает правила сервиса и соглашается с ними нажимая соответствующую галочку.
-
Сайт отображает форму поиска ИНН.
-
Операционист переключается в окно Excel, находит ячейку с фамилией и нажимает клавиши Ctrl + C, копируя данные в буфер обмена.
-
Операционист переключается в браузер и вставляет в него поле данные из буфера обмена.
-
Пункты 4-5 операционист повторяет для полей «Имя», «Отчество», «Дата рождения» и «Номер паспорта».
-
Операционист нажимает на сайте кнопку «Отправить запрос».
-
Сайт какое-то время думает и затем отображает ИНН.
-
Операционист выделяет ИНН, копирует его в буфер обмена и переносит его обратно в Excel.
-
Операционист повторяет шаги выше для остальных записей о пользователе.
Процесс TO BE (как будет работать робот)
-
Робот находит окно Excel и перемещает курсор в левый верхний угол (в начало клиентских данных). Конечно, робот мог бы прочесть Excel-файл напрямую, но для учебного примера мы предположим, что этой возможности нет, что робот имеет доступ только к пользовательскому интерфейсу CRM и вынужден имитировать действия оператора.
-
Робот запускает браузер и открывает в нем ссылку https://service.nalog.ru/inn.do. Если появляется окно с приглашением принять условия обслуживания, то робот имитирует нажатие на эту галочку.
-
Робот переключается в окно Excel и последовательно копирует все клиентские данные из ячеек Excel в буфер обмена, а из буфера обмена — в массив в памяти робота.
-
Робот переключается в браузер и последовательно получает ИНН для каждой клиентской записи, для этого:
-
Вставляет данные из памяти в форму на сайте https://service.nalog.ru/inn.do.
-
Нажимает кнопку «Отправить запрос».
-
Ждет пока сайт отобразит ИНН во всплывающей подсказке.
-
Копирует ИНН из всплывающей подсказки в память программы рядом с данными о клиенте.
-
-
Робот переключается в окно Excel, находит столбец «ИНН» и вставляет ИНН из памяти программы в соответствующие ячейки.
Выбираем язык программирования
Робота можно написать практически на любом современном языке программирования. Помимо этого в свободной продаже можно найти лицензии на целые пакеты роботизации и существуют сценарии, при которых их использование экономически оправдано.
Мы будем использовать язык Python, поскольку мы в конечном счете заменяем операциониста и со временем для этого могут потребоваться инструменты для программирования искусственного интеллекта, которые в Python присутствуют в полном объеме.
Помимо этого язык Python является простым в освоении и на нем проходит обучение программированию в Minecraft. Я знаю это потому, что мой семилетний сын программирует на Python в Minecraft и, кстати, одно из его любимых развлечений — роботизировать в Minecraft рутинные задачи, например, рыть тоннели к алмазам и строить место для ночлега.
Язык Python используется многими компаниями и банками, в том числе для задач роботизации он используется и в МКБ.
Подготовка
Для работы потребуется установить:
-
Excel для имитации CRM
-
Google Chrome для доступа к сайту https://service.nalog.ru/inn.do
-
Python 3, его можно скачать с сайта https://www.python.org/downloads/
-
PyWinAuto для имитации работы операциониста в Excel и любом другом не-браузерном приложении
pip3 install pywinauto
-
selenium web driver для имитации работы операциониста в Google Chrome. Для установки этого пакета необходимо выполнить два шага:
-
Скачать исполняемое приложение ChromeWebDriver отсюда https://chromedriver.chromium.org/downloads , при этом обратите внимание на версию — она должна совпадать с версией Google Chrome
-
Установить пакет для Python3
-
pip3 install selenium
Переходим к программированию
Для программирования робота нам потребуется запускать приложения, копировать из них данные в буфер обмена, вставлять в них данные из буфера обмена и нажимать на кнопки.
В обычной жизни это делает операционист.
При программировании робота эти действия имитируют библиотеки pywinauto для классических приложений и selenium — для браузерных.
При работе этих приложений со стороны будет создаваться ощущение, что за компьютером кто-то сидит: конечно, мышь по столу ездить не будет и кнопки на клавиатуре не будут продавливаться, но на мониторе будет кипеть бурная деятельность: данные будут вводиться, экраны переключаться, текст будет копироваться и вставляться — почти как при работе настоящего операциониста.
Из плохих новостей — компьютером в этот момент нельзя будет пользоваться: за ним «сидит» робот.
Код CrmAppAgent
Вся логика работы с CRM упакована в класс CrmAppAgent.
В нем реализованы как методы перемещения курсора, копирования и вставки данных, так и более высокоуровневые методы для получения списка записей и вставки ИНН напротив записей о клиенте.
from pywinauto import Application from pywinauto import clipboard import time class CrmAppAgent: def __init__(self): window_title_regular_expression = ".*data.*" excel_app = Application(backend="uia").connect(title_re=window_title_regular_expression) excel_window = excel_app.window(title_re=window_title_regular_expression) self.excel_app = excel_app self.excel_window = excel_window def deselect(self): excel_window = self.excel_window excel_window.type_keys('{ESC}') def move_cursor_to_top_left_corner(self): excel_window = self.excel_window excel_window.type_keys('^{HOME}') def move_cursor_down(self): excel_window = self.excel_window excel_window.type_keys('{DOWN}') def move_cursor_to_first_person_cell(self): excel_window = self.excel_window self.move_cursor_to_top_left_corner() self.move_cursor_down() def read_cell_contents(self): excel_window = self.excel_window excel_window.type_keys('^c') time.sleep(0.1) cell_data = clipboard.GetData() result = cell_data.rstrip() return result def move_cursor_right(self): excel_window = self.excel_window excel_window.type_keys('{RIGHT}') def move_cursor_to_first_left_cell(self): excel_window = self.excel_window excel_window.type_keys('{HOME}') def read_person(self): excel_window = self.excel_window last_name = self.read_cell_contents() if not last_name: return None self.move_cursor_right() first_name = self.read_cell_contents() self.move_cursor_right() middle_name = self.read_cell_contents() self.move_cursor_right() birthday = self.read_cell_contents() self.move_cursor_right() passport = self.read_cell_contents() self.move_cursor_down() self.move_cursor_to_first_left_cell() return { "last_name": last_name, "first_name": first_name, "middle_name": middle_name, "birthday": birthday, "passport": passport } def read_persons(self): excel_window = self.excel_window result = [] self.deselect() self.move_cursor_to_first_person_cell() while True: person = self.read_person() if person: result.append(person) else: break return result def move_cursor_to_first_inn(self): excel_window = self.excel_window self.move_cursor_to_top_left_corner() self.move_cursor_down() for i in range(5): self.move_cursor_right() def fill_inns(self, inns): excel_window = self.excel_window self.move_cursor_to_first_inn() for inn in inns: excel_window.type_keys(inn) self.move_cursor_down()
Код InnAppAgent
Логика работы с приложением https://service.nalog.ru/inn.do упакована в класс InnAppAgent.
Работа с этим приложением ведется через selenium web driver, что позволяет находить элементы на HMTL-странице веб-приложения по идентификаторам и код получается чище и короче, нежели код роботизации классического приложения.
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.keys import Keys import os class InnAppAgent: def __init__(self): browser = self.get_browser() self.browser = browser browser.implicitly_wait(10) SERVICE_URL = 'https://service.nalog.ru/inn.do' browser.get(SERVICE_URL) accept_terms_and_conditions_page_shown = browser.current_url != SERVICE_URL if accept_terms_and_conditions_page_shown: self.accept_terms_and_conditions() def get_browser(self): options = webdriver.ChromeOptions() options.add_argument("--start-maximized") current_folder = os.getcwd() web_driver_executable_name = "chromedriver.exe" web_driver_executable_path = "{}\\{}".format(current_folder, web_driver_executable_name) result = webdriver.Chrome(executable_path=web_driver_executable_path, chrome_options=options) return result def accept_terms_and_conditions(self): browser = self.browser browser.find_element(By.XPATH, '//a[@class="checkbox checkbox-off"]').click() browser.find_element(By.XPATH, '//button[@id="btnContinue"]').click() def fill_person_data(self, person): browser = self.browser input_data = { "fam": person["last_name"], "nam": person["first_name"], "otch": person["middle_name"], "bdate": person["birthday"], "docno": person["passport"] } for element_id, input_value in input_data.items(): element = browser.find_element(By.ID, element_id) element.clear() for symbol in input_value: element.send_keys(symbol) time.sleep(0.1) def submit_data(self): browser = self.browser browser.find_element(By.ID, 'btn_send').click() def read_inn(self): browser = self.browser previous_inn_element = browser.find_element(By.ID, "resultInn") previous_inn = previous_inn_element.text WebDriverWait(driver=browser, timeout=10, poll_frequency=1).until(lambda drv: drv.find_element(By.ID, "resultInn").text != previous_inn) inn_element = browser.find_element(By.ID, "resultInn") result = inn_element.text return result def submit_data_and_read_inn(self): browser = self.browser self.submit_data() return self.read_inn() def find_inn(self, person): browser = self.browser self.fill_person_data(person=person) result = self.submit_data_and_read_inn() return result def find_inns(self, persons): browser = self.browser return [self.find_inn(person=person) for person in persons]
Код сценария робота
Бизнес-логика по взаимодействию роботов вынесена в класс EnrichPersonsWithInnsScenario.
Сценарий очень короткий, поскольку все нюансы взаимодействия с приложением CRM и приложением https://service.nalog.ru/inn.do вынесена в классы-агенты.
class EnrichPersonsWithInnsScenario: def __init__(self, crm_app_agent, inn_app_agent): self.crm_app_agent = crm_app_agent self.inn_app_agent = inn_app_agent def run(self): crm_app_agent = self.crm_app_agent persons = crm_app_agent.read_persons() inn_app_agent = self.inn_app_agent inns = inn_app_agent.find_inns(persons=persons) crm_app_agent.fill_inns(inns=inns) crm_app_agent = CrmAppAgent() inn_app_agent = InnAppAgent() enrich_persons_with_inns_scenario = EnrichPersonsWithInnsScenario(crm_app_agent=crm_app_agent, inn_app_agent=inn_app_agent) enrich_persons_with_inns_scenario.run()
Финальный листинг
Исходный код робота и данные для работы можно скачать здесь: https://github.com/vasiliy-mikhailov/robot_tutorial
Запуск программы
-
Откройте файл data.xlsx при помощи Excel. Робот будет искать окно с названием «data», поэтому переименовывать файл нельзя.
-
Опционально: поменяйте в Excel тестовые данные клиента на свои. Если этого не сделать, то сайт https://service.nalog.ru/inn.do не сможет найти ИНН и сценарий не дойдет до конца. Реальные данные не включены в учебный пример по соображениям соблюдения закона о персональных данных.
-
Сохраните скрипт robot.py в любую папку.
-
Положите в эту же папку файл chromedriver.exe.
-
Перейдите в эту папку и выполните в ней команду.
python3.exe robot.py
-
Вы увидите как запустится браузер и робот примет в нем условия обслуживания.
-
Затем откроется окно Excel и робот начнет перемещаться по ячейкам и копировать их содержимое.
-
После того как робот скопирует все ячейки, переключитесь в окно браузера и посмотрите как робот вводит эти данные в форму и получает ИНН.
-
Если робот сможет вычислить все ИНН, то он перейдет обратно в Excel и заполнит ячейку с ИНН.
-
Обратите внимание на то, что робот может не выполнить работу до конца. Наиболее частые ошибки: невозможность скопировать данные в буфер обмена с ошибкой «Доступ запрещен» и зависание сервиса https://service.nalog.ru/inn.do на стадии поиска ИНН.
Поздравляю, что дальше?
Вы только что написали своего первого робота на языке программирования Python.
Обязательно покажите его домочадцам и посмотрите на их удивленные глаза, когда компьютер сам будет открывать окна и нажимать на клавиши — это бесценно.
Для принятия решения о том, стоит ли заниматься этим дальше, нужно найти задачи для роботизации в компании и убедить руководство в том, что это выгодно.
Поиск задач под роботизацию
Если вы выходите домой в 21:00, а операционисты все еще сидят, подойдите к ним и посмотрите, что они делают. Вполне может быть, что они выполняют рутинные операции по вводу данных, тогда весьма вероятно, что это ваши будущие клиенты. Присмотритесь и к другим шаблонным процессам в компании. Подумайте, как можно улучшить работу.
Экономика вопроса
Роботизация имеет смысл, если стоимость работы команды разработчиков окупается экономией от сокращения ручного труда операционистов и их высвобождения для решения других задач.
Простые роботы могут быть написаны Junior-разработчиком, однако, когда количество роботов растет, возникает потребность в размещении их на серверах, организации автоматического процесса поставки и мониторинга исполнения. Для организации этого процесса и формирования правильной архитектуры обычно требуется Senior-разработчик.
Роботы капризны, и за ними нужно приглядывать. Сократить затраты на сопровождение роботов помогут системы автоматизированного развертывания и мониторинга, которые может сделать Senior-разработчик.
Развиваем технические навыки
Для более глубокого изучения рекомендую прочесть и перенабрать своими руками примеры кода из книга «Автоматизация рутинных задач с помощью Python».
Это поможет набрать необходимую скорость перед тем, как появится первый реальный заказ на роботизацию.
Удачи в изучении Python!
ссылка на оригинал статьи https://habr.com/ru/articles/586334/
Добавить комментарий