Mi código funciona, pero no en todos los casos. Básicamente, la funcionalidad es hacer clic en un botón load_more hasta que ya no aparezca.

A partir de ahora, simplemente tengo un bucle que encuentra el botón cargar más y hace clic dos veces, pero hay casos en que hará clic en otra cosa cuando el botón cargar más desaparezca.

Estaba planeando hacer un ciclo while, que constantemente encontraría el clic en la opción load_more hasta que desaparezca loadmore y luego rompa el ciclo.

Aquí está el código: (Esto simplemente lo encuentra y hace clic dos veces)

load_more = browser.find_element_by_css_selector("#mainContent > div.left-panel > div > div.result-list > div > div.content")
WebDriverWait(browser, timeout).until(EC.visibility_of(load_more))

#Need bugfix, 
for i in range(2):
    browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)
    ActionChains(browser).move_to_element(load_more).click().perform()

Me di cuenta cuando jugaba con el botón cargar más que.

<div class="progressbtnwrap" data-search-type="search" style="display: block;">

Cuando el botón cargar más está presente en el sitio, el elemento se establece en "display: block;"

Pero una vez que desaparece el botón cargar más,

<div class="progressbtnwrap" data-search-type="search" style="display: none;">

El elemento cambia a ninguno, observe "display: none;"

¿Alguna sugerencia de cómo puedo buscar esto?

Al mirar a través de las documentaciones de selenio, no pude encontrar ninguna forma de buscar este elemento y verificar específicamente si el estilo no se activa,

https://selenium-python.readthedocs.io/locating-elements.html

Mi objetivo aquí es crear algo como esto

while(True):
    if browser.find_element_by_notsurewhat == "block":
        ActionChains(browser).move_to_element(load_more).click().perform()
    if browser.find_element_by_notsurewhat == "none":
        break
    browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)

Estoy seguro de que la lógica debe ser mucho más complicada que eso, o incluso si lo que quiero lograr es posible, ¡cualquier sugerencia sería increíble!

¡Gracias a todos!

Actualizar:

def load_more(browser):
    print("I'm in the function LOAD MORE")
    try:
        if browser.find_element_by_xpath('//*[@id="mainContent"]/div[1]/div/div[5]/div'):
            print("I HAVE ENTERED THE TRY BLOCK WITHIN THE LOAD MORE FUNCTION")
            return True
    except Exception as e:
        print(e)
        return False
    return False
while load_more(browser):
    print("I'm in the while loop!")
    ActionChains(browser).move_to_element(load_more).click().perform()
    browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)

Al colocar mis comandos de localización y clic, comencé a recibir el siguiente error:

Traceback (most recent call last):
  File "C:\Users\David\eclipse-workspace\Web_Scrap\setup.py", line 81, in <module>
    ActionChains(browser).move_to_element(load_more).click().perform()
  File "C:\Users\David\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\action_chains.py", line 83, in perform
    action()
  File "C:\Users\David\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\action_chains.py", line 293, in <lambda>
    Command.MOVE_TO, {'element': to_element.id}))
AttributeError: 'function' object has no attribute 'id'

Me di cuenta al tratar de averiguar exactamente dónde se bloquea el programa que, una vez que se ejecuta el siguiente código, el programa se bloquea, pero esto funciona antes de colocar esto dentro del bucle while o la función. (Intenté colocar la línea scrollIntoView dentro de la función justo antes del intento y recibí un error similar).

ActionChains(browser).move_to_element(load_more).click().perform()
browser.execute_script("return arguments[0].scrollIntoView(true);", load_more)

Load more button visible

Load more button Gone

0
david yeritsyan 8 sep. 2018 a las 03:33

3 respuestas

La mejor respuesta

Si el atributo de estilo para un elemento html está configurado para mostrar: ninguno, el selenio no podrá encontrar el elemento utilizando las funciones de selector DOM incorporadas como find_element_by_id / find_elements_by_class, etc. Simplemente puede ajustar la operación de búsqueda en un intento, excepto bloquee y agregue un retraso para permitir al navegador un tiempo para la llamada Ajax.

def load_more(browser):
    time.sleep(1)
    try:
        display = browser.execute_script("return document.getElementsByClassName('progressbtnwrap')[0].style.display")
        if display == 'none':
            return False
        elem = browser.find_element_by_xpath('//div[contains(@class, "progressbtnwrap")]/div[contains(@class, "content")]')
        browser.execute_script("arguments[0].click();", elem)
        return True
    except Exception as e:
        print("Error")
        print(e)
    return False

while load_more(browser):
    print("scrolling further")
1
gurpreet singh chahal 9 sep. 2018 a las 05:04

Suponiendo que actualmente solo está tratando de encontrar una manera de cómo puede verificar el estilo actual de su elemento, puede usar este código.

driver.execute_script("return arguments[0].style.display;", load_more)

Y puede usar para verificar que cuando el valor de retorno es 'ninguno' durante unos segundos, lo que significa que no se cargarán más datos, puede salir de su ciclo.

0
Kamal 8 sep. 2018 a las 09:06

La forma idiomática de hacer esto es usar "esperas explícitas" (AKA WebDriverWait con ExpectedConditions).

Lo siguiente esperará hasta que el elemento ya no sea visible. Si no desaparece en 10 segundos, se genera un TimeOutError:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.invisibility_of_element_located(By.CLASS_NAME, 'progressbtnwrap'))
2
Corey Goldberg 8 sep. 2018 a las 05:19