问题描述
我正在尝试使用Python和Selenium登录到Azure DevOps。我可以很好地输入用户名和密码,但是我在手机上设置了Microsoft Authenticator App,以便在尝试登录时提示我“批准”或“拒绝”。
我尝试让Selenium等到登录页面上的“否”按钮元素出现(请参见下面的屏幕截图), 但它似乎不喜欢它。我看了this post,它与Google的Authenticator有关。该解决方案使用了Google Authenticator的秘密以及pyotp。我似乎无法找到一种方法,至少对我本人而言,可以从MS Authenticator中获得秘密。我已签出this指南,但无权访问Azure AD。
def signin(user,passwd):
# find elements before passing information
username = browser.find_element_by_name('loginfmt')
username.send_keys(user)
username.send_keys(Keys.ENTER)
time.sleep(1)
password = browser.find_element_by_name('passwd')
password.send_keys(passwd)
password.send_keys(Keys.ENTER)
try:
webdriverwait(browser,60).until(
EC.element_to_be_clickable((By.ID,"idBtn_Back"))
).click()
finally:
sys.exit('Timeout for 2FA approval reached. Try again.')
不幸的是,正如我在上面简要提到的那样,即使在保持登录状态页面出现后,Python也无法检测到“否”按钮。我真的不在乎使用哪个按钮,因为脚本使用的是我未登录的浏览器的单独实例。
我已经考虑设置一个长time.sleep()
命令,但这似乎是一种非常愚蠢的方法。有人有建议吗?
解决方法
Python无法检测到“否”按钮。
每当我发现Python发生奇怪的事情,绝对没有任何意义,程序根本不执行所告诉的事情时,请相信我,我总是在那里找到try-except
语句。而我的朋友是你的错。
也finally
will always execute。 try
是否有效都没关系。
WebDriverWait(browser,60).until(
EC.element_to_be_clickable((By.ID,"idBtn_Back"))
).click()
完全是错误的!尝试单独运行它:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-13-b43596b524d7> in <module>
9
10 WebDriverWait(driver,60).until(EC.element_to_be_clickable((By.ID,"i0116")))
---> 11 driver.find_element_by_id("i0116").send_keys("u18ec013@svnitsuratg.onmicrosoft.com").click()
12
13 WebDriverWait(driver,"idSIButton9")))
AttributeError: 'NoneType' object has no attribute 'click'
因为您根本无法在.click()
的输出(即WebDriverWait
)上调用None
。
以下代码可以正常工作:
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
driver = webdriver.Chrome(executable_path='path/to/executable')
driver.get("https://login.microsoftonline.com")
WebDriverWait(driver,"i0116")))
driver.find_element_by_id("i0116").send_keys("your_emailid")
WebDriverWait(driver,"idSIButton9")))
driver.find_element_by_id("idSIButton9").click()
driver.find_element_by_id("i0118").send_keys("your_password")
WebDriverWait(driver,"idSIButton9")))
driver.find_element_by_id("idSIButton9").click()
WebDriverWait(driver,"idSIButton9")))
driver.find_element_by_id("idSIButton9").click()
对于您而言,只需将其更改为:
def signin(user,passwd):
# find elements before passing information
username = browser.find_element_by_name('loginfmt')
username.send_keys(user)
username.send_keys(Keys.ENTER)
time.sleep(1)
password = browser.find_element_by_name('passwd')
password.send_keys(passwd)
password.send_keys(Keys.ENTER)
try:
WebDriverWait(browser,"idBtn_Back")))
browser.find_element_by_id("idSIButton9").click()
except:
sys.exit('Timeout for 2FA approval reached. Try again.')