Реально ли ускорить существующий скрипт ?

Доброго времени суток. У меня имеется скрипт который заполняет на сайте определенные поля, сайт откровенно говоря громоздкий и веб драйверу требуется заполнить более 400 позиций.

Сам скрипт выглядит примерно так:

def company_1():
    ...
    Поиск, присвоения переменных для заполнения:
    ...
    ==========================
    input('Press ENTER to start')
    ==========================

    def insert(path,value,value_name=None):
      try: 
          elem = driver.find_element_by_xpath(path)
          elem.clear()
          pyperclip.copy(str(value))
          elem.send_keys(Keys.CONTROL+'V')
      except: 
            if value_name != None: not_found_list.append(value_name)

    def select(path,value,value_name=None):
      try: driver.find_element_by_xpath(path).select_by_visible_text(value)
      except: 
            if value_name != None: not_found_list.append(value_name)

   insert('//*[@id="ui-view"]/div/div[3]/div/div[2]/div/div[1]/div/div/div[2]/bpo-comp-property[2]/div/ul/li[3]/input', S1_street, 'S1_street')
   select('//*[@id="ui-view"]/div/div[3]/div/div[2]/div/div[1]/div/div/div[2]/bpo-comp-property[2]/div/ul/li[14]/select', Zoning)

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

Если задача этого шага - не проверять ввод текста, а заполнение полей для дальнейшей работы с этой формой, то смотрите в стороне executescritp - и выполняйте на стороне браузера один большой толстый скрипт, который все поля заполнит.

1 лайк

Скорость зависит от числа элементов, над которым надо выполнить действие. 400 элементов в одном тесте - это слишком много. Явно требуется пересмотреть подход к проектированию тестов.

1 лайк

А можно чуть более конкретной информации как выглядит строка этого скрипта ?
Сколько пытался найти инфу вообще по теме “execute_script” для питона, толкового ничего не находил :frowning:

К сожалению, но надо заполнять именно эти все поля. :slight_smile:

Может заполнять надо и все, но обязательно ли это делать в один подход ? Возможно, стоит разделить функционал по отдельным тестам. Конечно, это существенно, не ускорит процесс, если запускать в один поток, но решит проблему через запуск тестов параллельно

1 лайк

Попробую подумать в этом направлении, возможно ли разделить на несколько параллельных скриптов.

Со стороны питона вообще все элементарно


execute_script(script, *args)
Synchronously Executes JavaScript in the current window/frame.

Args:	
  script: The JavaScript to execute.
  *args: Any applicable arguments for your JavaScript.

Usage:	
driver.execute_script(‘document.title’)

Возможно, будут сложности с составлением самих скриптов javascript.
Но тут надо, быть в теме.

https://www.google.ru/search?ie=UTF-8&hl=ru&q=python%20selenium%20javascript&gws_rd=ssl

1 лайк

Спасибо, буду разбираться. Надо узнать какой javascript отвечает за заполнение поля. :slight_smile:

можно вобще-то без джаваскрипта. Вместо sendKeys

elem.setAttribute("value", "blablabla")

Причина задержки в том что sendKeys иммитирует нажатие клавишь и для более корректной работы ставит паузы между нажатиями. setAttribute просто установит текст в нужный сразу. Скорость выполнения должна быть раза в 4 выше, если тексты были короткими. Если длинными, то даже более быстрым

3 лайка

Спасибо. Это работает только для полей типа input или select’ы можно пробовать таким же методом ?

Для селектов скорее понадобится

elem.setAttribute("selected", "Blabla")

Но вы можете определять тип елемента в функции инсерт и в зависимости от этого править нужный параметр. Все-равно это будет быстрее чем иммитация клавишь

1 лайк

От имитации клавиш я избавился путем модуля pyperclip, имитируя вставку с буфера обмена, но это решение не сильно элегантное. Буду пробовать и тестировать через установку атрибута.

Попробовал через setAttribute - к сожалению не работает, вызывает ошибку. :frowning:

elem.setAttribute('value', '1')
AttributeError: 'WebElement' object has no attribute 'setAttribute'

Замени этим кодом

Пробовал. Данный код просто добавит к элементу атрибут value который не будет отображаться.

Зайдите на страницу, руками заполните поле, посмотрите в какой аттрибут сохранился текст и используйте этот аттрибут в коде.

Вот как выглядит поле:

<input type="text" tabindex="1" class="form-control input-sm ng-pristine ng-untouched ng-valid ng-empty" 
ng-model="bpo.Address" ng-disabled="isSubjectProp" ng-change="flagForGeocode()" comp-enter-kp="">

Когда ввожу какой-либо текст - ни один из атрибутов не меняется. Проскакивает какое-то изменение в классе и затем снова в исходное вид возвращается.

Потому что это Angular. С ним надо джаваскриптом колбаситься. Но вроде есть воркэраунд. Попробуйте делать для примера выше

elem.setAttrubute("ng-init", "bpo.Address='Blablalb'")

Только тот тип что перед равно для каждого элемента распарсить придется, но это не сложно, считайте аттрибут ng-model и подставьте.

Я не проверял, но в гугл переписках писали что костыль работает. Если не сработает, то ускорение только на джаваскрипте.

Задача состоит в том, чтобы проверить заполнение полей или это просто вбивалка данных? Если 2-й случай - используйте фабрики или прямой SQL, чтобы заполнить необходимыми данными БД. Это будет на 1…2 порядка быстрее как минимум.