[Selenium, Python], WebDriverWait (драйвер, время ожидания) .until () не может найти элемент, TimeoutException - PullRequest
0 голосов
/ 13 апреля 2020

Я программирую бота, который автоматически извлекает обувь из 'https://www.nike.com.br'. У меня есть URL страницы оформления заказа, и процесс оформления заказа выглядит следующим образом:

  1. Решить CAPTCHA
  2. Выбрать размер обуви
  3. Перейти к способу оплаты
  4. Оформить заказ

Я позаботился о CAPTCHA, используя Chrome Профиль по умолчанию в Chrome Driver. После того, как CAPTCHA решена, размеры обуви отображаются на странице динамически. Источник веб-страницы содержит JSON объектов, в которых хранится вся информация о доступных размерах обуви, поэтому я анализирую ее из источника документа и использую ее для случайного выбора одного из доступных размеров обуви.

Вот код


'''==================================== SECTION - I ===================================='''


default_profile = r'--user-data-dir=C:\Users\{}\AppData\Local\Google\Chrome\User Data'.format(getpass.getuser())

options = webdriver.ChromeOptions()
options.add_argument(default_profile)                              # Adding Default Chrome Profile
#options.add_argument("--disable-extensions")
#options.add_argument("--disable-gpu")
#options.add_argument("--headless")

driver = webdriver.Chrome(executable_path='WebDrivers/chromedriver.exe', options=options)

driver.get('https://www.nike.com.br/Snkrs/Produto/MX-720-818/153-169-211-209098')
html_source = driver.page_source

'''==================================== SECTION - II ===================================='''
#           Getting past CAPTCHA

WebDriverWait(driver, 10).until(
                                EC.frame_to_be_available_and_switch_to_it(
                                    ( By.CSS_SELECTOR,
                                      r"iframe[name^='a-'][src^='https://www.google.com/recaptcha/api2/anchor?']"
                                    )
                                ))

WebDriverWait(driver, 10).until(
                                EC.element_to_be_clickable(
                                    ( By.XPATH, 
                                      r'/html/body/div[2]/div[3]/div[1]/div/div/span'
                                    )
                                )).click()

'''==================================== SECTION - III ===================================='''

#           PARSING JSON Object FROM DOCUMENT BODY ( PRETTY UGLY HACKS DOWN HERE [ WORKING FINE THOUGH! ] )

script_index   = html_source.index('<main role="main" class="container-fluid" id="produto">')
JSON_start_index = html_source[script_index::].index('{') + script_index,  html_source[script_index::].index('{')
JSON_end_index = html_source[JSON_start_index[0]::].index('</script>') + script_index + JSON_start_index[1]

availability_JSON_str = html_source[JSON_start_index[0]:JSON_end_index:1].strip()

shoe_size_objects = json.loads(availability_JSON_str)

#           APPENDING AVAILABLE SHOES TO A LIST

available_shoes = []

for shoe_size in shoe_size_objects:                         # Iterating each shoe size object

    if shoe_size_objects[shoe_size]['TemEstoque'] == '1':   # Shoe Size is available (TemEstoque is attribute name)

        available_shoes.append(shoe_size)


selected_size = random.choice(available_shoes)     # Selecting one of available shoe size randomly

'''==================================== SECTION - IV ===================================='''

def get_size_ID():                # UTILITY FUNCTION [ Works Fine, Ignore ]

    global shoe_size_objects
    global selected_size

    for size in shoe_size_objects:

        if shoe_size_objects[size]['Tamanho'] == str(selected_size):

            return 'tamanho__id{}'.format(selected_size)



size_elem = None

'''==================================== PROBLEMATIC CODE ===================================='''

WebDriverWait(driver, 5).until(
                                EC.frame_to_be_available_and_switch_to_it(
                                ( By.CSS_SELECTOR,
                                  "iframe[name^='a-'][src^='https://www.google.com/recaptcha/api2/anchor?']"
                                )
                                ))

size_elem = WebDriverWait(driver, 5).until(
                                            EC.visibility_of_element_located(
                                            ( By.ID,
                                              get_size_ID()
                                            )
                                            ))

driver.execute_script("arguments[0].click();", size_elem)

#ActionChains(driver).move_to_element(size_elem).click(size_elem).perform()

ДЕТАЛИ:

Вы должны заметить, что я использую профиль по умолчанию chrome, то есть тот, где сохраняются учетные данные моей кредитной карты и синхронизированные пароли / автоматический вход в систему , Вот как я планирую решить CAPTCHA и заполнить учетные данные (через автозаполнение, которое, как мы надеемся, будет активировано при необходимости). После того, как капча решена, размеры обуви отображаются динамически, имея общий вид:

[ul] / [li] / [input type = 'radio'] / [label]

Я получаю ElementNotInteractable исключение при нацеливании на метку, поэтому я нацеливаюсь на элемент ввода по его идентификатору.

ПРОБЛЕМА:

Итак, я просмотрел большинство важных вопросов здесь, в StackOverflow, и обнаружил, что мне нужен код, указанный в разделе iv для выбора размера (.click () не работает). Тем не менее, это не работает. Это всегда истекает и не может найти элемент ввода. Я пытался получить доступ к нему по ID, классу, XPATH, имени, но ни один не работал.

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

Я пробовал разные способы доступа к нему, например

  • wait.until (E C .visibility_of_element_located ((By.ID/XPATH,'id ')))
  • wait.until (E C .presence_of_element_located ((By.ID/XPATH, 'id'])))

  • wait.until (E C .element_to_be_clickable ((By.ID/XPATH, 'id'))

но без помощи, все, что я получаю, это исключение тайм-аута.

Любая помощь будет высоко оценена .:)

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