Войдите в несколько учетных записей одновременно в Chrome с Selenium & Python - PullRequest
1 голос
/ 15 октября 2019

Я управляю около 150 учетными записями электронной почты своей компании и написал сценарий Python для Selenium WebDriver, который автоматизирует действия (удаление спама, очистка корзины, ...) одна учетная запись за другой, несколько раз в день, и этослишком медленный и постоянно падает. Я читал, что Selenium Grid с Docker в Amazon AWS может справиться с этой задачей, и кажется, что «параллельный» вариант для Selenium WebDriver тоже может.

Что мне нужно сделать одновременно:

1) Вход в систему (все учетные записи)

2) Выполнение действий (удаление спама, очистка корзины, ...)

3) Закрытие экземпляров Chrome

В настоящее время я должен использовать цикл for для создания в 150 раз одних и тех же инструкций, которые я храню в списках, и это совсем не оптимизировано, это приводит к сбою моего компьютера ... В двух словах,Я знаю, что это не тот путь, и я с нетерпением жду возможности одновременной параллельной работы.

Вот сокращенная версия кода, который я использую:

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.common.exceptions import TimeoutException


## GET THE USERS' EMAILS
emails = []
pwds = []
with open("users.txt", "r") as users_file: # Open the text file containing emails and pwds
  for line in users_file:
      email_and_pwd = line.split() # Extract the line of the .txt file as a list
      emails.append(email_and_pwd[0]) # Add the email in the emails list
      pwds.append(email_and_pwd[1]) # Add the pwd in the pwds list
nbr_users = len(emails) # number of users


## CREATE LISTS OF INSTRUCTIONS THAT WILL BE EXECUTED LATER AS CODE
create_new_driver = []
go_to_email_box = []
fill_username_box = []
fill_password_box = []
# Here I have the same type of lines to create lists that will contain the instructions to click on the Login button, then delete spams, then empty the trash, etc...


## FILL THE LISTS WITH INSTRUCTIONS AS STRINGS
for i in range(nbr_users):
  create_new_driver_element = 'driver' + str(i) + ' = webdriver.Chrome(options = chrome_options)'
  create_new_driver.append(create_new_driver_element)

  # Here I have the same type of lines to create the rest of the instructions to fill the lists


## EXECUTE THE INSTRUCTIONS SAVED IN THE LISTS
for user in range(nbr_users):
  exec(create_new_driver[user])
  # Here I have the same type of lines to execute the code contained in the previously created lists

Послепросмотр интернета в течение нескольких дней безрезультатно, любая помощь приветствуется. Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

Я попытался прокомментировать @ Jetro Cao's ответ, но это было слишком много, чтобы уместиться в комментарии. Я основываю свой ответ на его работе.

Почему ваша программа работает медленно?

Как упоминалось @ Jetro Cao , вы запускаете всепоследовательно, а не параллельно.

Будет ли это легче сделать с помощью другого инструмента?

Да. Если возможно, вам следует использовать инструмент администрирования электронной почты (например, G Suite for gmail), а не входить в эти учетные записи индивидуально с помощью сценариев Python.

Безопасно ли хранить мои 150 учетных данных в текстефайл?

Нет. Если только это не бессмысленные аккаунты ботов без каких-либо конфиденциальных писем.

Советы по коду:

В целом ваш код отлично подходит для начала. Несколько конкретных комментариев:

  1. Избегайте использования exec
  2. Используйте многопоточность в соответствии с рекомендациями @ Jetro Cao
  3. Youне предоставили нам большую часть вашего кода. При использовании селена некоторые приемы могут помочь ускорить процесс. Одним из примеров является прямая загрузка страницы входа в систему, а не загрузка домашней страницы, а затем «нажатие» входа.
import threading

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.common.exceptions import TimeoutException


## GET THE USERS' EMAILS
emails = []
pwds = []
with open("users.txt", "r") as users_file: # Open the text file containing emails and pwds
for line in users_file:
    email, pwd= line.split() # Extract the line of the .txt file as a list
    emails.append(email) # Add the email in the emails list
    pwds.append(pwd) # Add the pwd in the pwds list
nbr_users = len(emails) # number of users


## CREATE LISTS OF INSTRUCTIONS THAT WILL BE EXECUTED LATER AS CODE
drivers = []
go_to_email_box = []
fill_username_box = []
fill_password_box = []
# Here I have the same type of lines to create lists that will contain the instructions to click on the Login button, then delete spams, then empty the trash, etc...


## FILL THE LISTS WITH INSTRUCTIONS AS STRINGS

threads = []
for i in range(nbr_users):
    t = threading.Thread(target=webdriver.Chrome, kwargs={'options': chrome_options})
    t.start()
    threads.append(t)

for t in threads:
    t.join()
0 голосов
/ 15 октября 2019

Я догадываюсь, что ваша программа работает медленно из-за того, что вы выполняете набор инструкций для одного пользователя за другим. И хотя я не знаю специфики работы Selenium, я бы предположил, что там, вероятно, происходит довольно много сетевых операций ввода-вывода, для которых вы ждете завершения с каждым пользователем, прежде чем выполнять тот же набор для следующего пользователя. .

Как вы правильно поняли, вам нужно уметь распараллеливать их больше. * Потоковый модуль Python может помочь вам в этом, в частности, вам нужен класс Thread.

Используя только ваш create_new_driver в качестве примера, вы можете попробовать что-то вроде следующего:

# ...
# your other imports
# ...
import threading

# ...
# setting up your user info and instructions lists
# ...

# create function that will execute the instructions for a single user,
# which will be used as the argument for target param of the Thread constructor 
def manage_single_user(i):
    user = nbr_user[i]
    exec(create_new_driver[user])
    # execute rest of the instructions for same user

threads = []
for i in range(nbr_users):
    t = threading.Thread(target=manage_single_user, args=(i,))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...