How to execute all javascript content on webpage with selenium to find and send login form info on fully loaded webpage

匆匆过客 提交于 2019-12-24 00:54:13

问题


I've been trying to make a Python script to login into a certain website, navigate through the menu, fill out a form and save the file it generates to a folder.

I've been using Selenium trying to make the website fully load so i can find the elements for the login, but i'm being unsucessful, maybe because the website does a lot of JavaScript content before it fully loads, but i can't make it fully load and show me the data i want.

I tried Robobrowser, Selenium, Requests and BeautifulSoup to get it done.

import requests
from bs4 import BeautifulSoup
from selenium import webdriver

url = "https://directa.natal.rn.gov.br/"

driver = webdriver.Chrome(executable_path="C:\\webdrivers\\chromedriver.exe")
driver.get(url)

html = driver.execute_script("return document.documentElement.outerHTML")
sel_soup = BeautifulSoup(html, 'html.parser')

senha = driver.find_element_by_xpath('//*[@id="senha"]')
senha.send_keys("123")

I expected to have filled the password (senha) field with "123" but i can't even find the element.


回答1:


To send the character sequence 123 to the password (senha) field, as the the desired elements are within a <frame> so you have to:

  • Induce WebDriverWait for the desired frame to be available and switch to it.
  • Induce WebDriverWait for the desired element to be clickable.
  • You can use the following solution:

    • Code Block:

      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
      
      options = webdriver.ChromeOptions()
      options.add_argument("start-maximized")
      options.add_argument('disable-infobars')
      options.add_argument("--disable-extensions")
      driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
      driver.get("https://directa.natal.rn.gov.br/")
      WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame[name='mainsystem'][src^='main']")))
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.input[name='usuario']"))).send_keys("Tads")
      driver.find_element_by_css_selector("input.input[name='senha']").send_keys("123")
      
  • Browser Snapshot:

Here you can find a relevant discussion on Ways to deal with #document under iframe




回答2:


It seems like what's needed here is a little bit of a scroll, wait and switch, incase the login fields just aren't ready for input :) The below should work, whereby we actually scroll to the element, having switch to the iframe, before we interact with the rest of the login form. You're able to adjust the delay from 5 seconds to anything of your preference.

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException

""" Variables """
url = "https://directa.natal.rn.gov.br/"
delay = 5 # seconds

""" Initiate driver """
driver = webdriver.Chrome(executable_path="C:\\webdrivers\\chromedriver.exe")

""" Go to url """
driver.get(url)

""" Iframe switch """
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"frame[name='mainsystem'][src^='main']")))


""" Attempt to get all our elements """
try:
    """ Username """
    usuario = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'usuario')))
    """ Password """
    senha = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'senha')))

    print("All elements located!")

except TimeoutException:
    print("Loading took too much time!")
    exit(0)

"""Scroll to our element """
driver.execute_script("arguments[0].scrollIntoView();", usuario)

""" Input data into our fields """
usuario.send_keys("username")
senha.send_keys("password")

""" Locate our login element """
login = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'acessar')))

""" Click Login """
login.click()


来源:https://stackoverflow.com/questions/55713324/how-to-execute-all-javascript-content-on-webpage-with-selenium-to-find-and-send

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!