这是使用 Selenium 和 Python 构建 Web 自动化脚本的更大函数的一部分。该网站有时会提供弹出窗口,这会导致
ElementClickInterceptedException
,但弹出窗口并不总是提供;有时没有弹出窗口。
我编写了这个函数来关闭弹出窗口(如果它已提供):
def close_popup():
try:
WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//x-button'))).click()
time.sleep(1)
except:
NoSuchElementException
print("No pop-up found")
然后我在主部分编写了一个 try/ except 块来调用该函数:
try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.LINK_TEXT, "Click here!"))).click()
except ElementClickInterceptedException:
close_popup()
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.LINK_TEXT, "Click here!"))).click()
这确实按预期工作,但它违反了 DRY(不要重复自己),因为
try:
之后的行与块的最后一行相同。
我确实先搜索了这个,但没有找到与我的问题完全相同的。我发现那些人询问代码中的一些错误。我的代码确实有效,只是违反了 DRY。
我如何重构才能使我的代码符合 Python 风格并且不违反 DRY?
DRY 主要涉及将业务逻辑保留在一个地方;即不要到处重复逻辑决策,就像这样:
if len(user.subaccounts) > 3 and user.license == 'basic':
raise UpgradeSubscription
应该在一个地方检查此类事情,而不是在整个代码库中的多个地方。因为当您的业务规则最终不可避免地发生变化时,这将导致不一致。
所以,这里并没有特别违反DRY;您的两行代码非常接近,如果更改其中一行,将其复制粘贴到下面三行可能不会有什么问题。
话虽如此,明显的选择是:
def close():
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.LINK_TEXT, "Click here!"))).click()
try:
close()
except ElementClickInterceptedException:
close_popup()
close()
或者类似的东西:
for i in range(2):
try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.LINK_TEXT, "Click here!"))).click()
except ElementClickInterceptedException:
if i == 0:
close_popup()
else:
raise
虽然前一个可以说更具可读性。