from selenium import webdriver
from selenium.webdriver.common.by import By
import time
显式等待需要导入两个模块
from selenium.webdriver.support.wait import WebDriverWait #等待类
from selenium.webdriver.support import expected_conditions as EC #条件类
# 打开浏览器
driver = webdriver.Chrome()
# 加载项目地址,打开京东
driver.get("https://re.m.jd.com/page/homelike")
#代码运行比页面加载快,所以要等待
#1.强制等待3秒
time.sleep(3)、
元素定位不到的场景一
元素还没有加载出来,就执行了代码
智能等待
**(1)隐式等待
#注意:隐式等待的顺序要求:
'''**
**# 必须在元素定位之前设置!
✅ 正确顺序**
driver = webdriver.Chrome()
driver.get("https://example.com")
driver.implicitly_wait(10) # 先设置隐式等待
# 后执行元素定位(会自动应用等待)
element = driver.find_element(By.ID, "username")
# ❌ 错误顺序 - 设置无效
driver = webdriver.Chrome()
driver.get("https://example.com")
# 先定位元素(此时没有等待机制)
element = driver.find_element(By.ID, "username")
# 后设置隐式等待(对上面的查找不起作用)
driver.implicitly_wait(10)
'''
**# 原因: 隐式等待是 WebDriver 的全局配置,设置后才会对所有后续的 find_element 操作生效。
driver.implicitly_wait(10) #等待10秒,10秒之内找到元素,则停止等待**
(2)显式等待
注意: 显式等待的顺序要求
必须在元素定位时使用,不能提前或延后!
'''
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# ✅ 正确顺序 - 等待和定位是一体的
driver = webdriver.Chrome()
driver.get("https://example.com")
# 创建等待对象
wait = WebDriverWait(driver, 10)
# 显式等待本身就包含了定位逻辑
element = wait.until(EC.presence_of_element_located((By.ID, "username")))
element.send_keys("test")
# ❌ 错误顺序 - 先定位再等待(没有意义)
driver = webdriver.Chrome()
driver.get("https://example.com")
# 先尝试定位(可能找不到元素就报错)
element = driver.find_element(By.ID, "username")
# 再创建等待对象(已经晚了)
wait = WebDriverWait(driver, 10)
'''
**# 原因: 显式等待的工作机制是"等待 + 定位"的组合,
它会在指定时间内反复尝试定位元素直到满足条件。**
# 创建等待对象,最多等待10秒
wait = WebDriverWait(driver,10,0.5)
# 等待元素存在后才操作(参数是一个元组格式,且只返回一个数据)
jd_goods1 = wait.until(EC.presence_of_element_located((By.XPATH,"//ul[@class='service-bd']/li[1]/div[@class='first-cate-container']/a[1]")))
# #定位元素
jd_goods = driver.find_elements(By.XPATH,"//ul[@class='service-bd']/li[1]/div[@class='first-cate-container']/a")
jd_goods1 = jd_goods[0]
# 点击
jd_goods1.click()
wait2 = WebDriverWait(driver,10,0.5)
jd_goods2 = wait2.until(EC.presence_of_element_located((By.XPATH,"//div[@class='jd-pick-feeds-container']/div[@class='jdpc-row']/div/div/a[@href='javascript:void(0)']/div/div/img[@data-exposureimg='https://sh.jd.com/g/qiyglPV53qLJ2-s?pos_offset=1']")))
jd_goods2 = wait2.until(EC.presence_of_element_located((By.XPATH,"//img[@src='//m.360buyimg.com/mobilecms/s500x500_jfs/t1/423204/30/6209/186419/69e7143dFa546dcd4/00833203208711ff.jpg!q70.dpg']")))
jd_goods2.click()
元素定位不到的场景二:driver.window_handles
1.先获取所有窗口句柄
2.切换窗口
'''
**# 切换窗口,定位元素
# ❌ 错误做法:先获取窗口,再点击
all_windows = driver.window_handles # 此时只有1个窗口 ['窗口A']
link.click() # 点击后打开新窗口
driver.switch_to.window(all_windows[-1]) # 还是窗口A!因为列表没更新
# ✅ 正确做法:先点击,再获取窗口
link.click() # 点击后打开新窗口
time.sleep(2) # 等待新窗口生成
all_windows = driver.window_handles # 此时有2个窗口 ['窗口A', '窗口B']
driver.switch_to.window(all_windows[-1]) # 成功切换到窗口B**
# 获取当前窗口句柄
driver.current_window_handle
# 返回当前窗口的句柄
original_window = driver.current_window_handle
print(f"原始窗口: {original_window}")
# 获取所有窗口句柄
driver.window_handles
# 返回所有窗口句柄列表
all_windows = driver.window_handles
print(f"所有窗口: {all_windows}")
# 切换到指定窗口
driver.switch_to.window(all_windows[指定索引])
# 切换到最新窗口,切换到最后打开的窗口
driver.switch_to.window(all_windows[-1])
# 切换到第一个窗口,切换到最早打开的窗口
driver.switch_to.window(all_windows[0])
# 关闭当前窗口,关闭当前控制的窗口
driver.close()
# 关闭所有窗口,关闭浏览器,结束会话
driver.quit()
元素定位不到的场景三:iframe/frame
#当前定位元素在iframe/frame中需要先切换frame,在定位元素
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import time
# # 初始化浏览器
driver = webdriver.Chrome()
driver.get("目标网址")
**# driver.maximize_window()
将浏览器窗口扩展到屏幕的最大尺寸**
确保页面的所有元素都可见,避免因窗口太小导致元素被隐藏
模拟用户正常使用浏览器的方式
try:
# # 1. 点击登录链接
login_link = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//a[text()='登录']"))
)
login_link.click()
time.sleep(1)
2. 切换iframe(选择其中一种方式)
#方式一:通过iframe的id或name
# # driver.switch_to.frame("iframe的id或name")
# 方式二:通过索引(第几个iframe)
# # driver.switch_to.frame(0)
方式三:通过WebElement(推荐
**# iframe_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//iframe[@id='login_frame']"))
)
driver.switch_to.frame(iframe_element)**
# 3. 点击密码登录
pswdlogin = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//a[text()='密码登录']"))
)
pswdlogin.click()
time.sleep(1)
# 4. 输入用户名
username_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "username")) # 根据实际元素修改
)
username_input.clear()
username_input.send_keys("your_username")
# 5. 输入密码
password_input = driver.find_element(By.ID, "password") # 根据实际元素修改
password_input.clear()
password_input.send_keys("your_password")
# 6. 点击登录按钮
login_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "login_btn")) # 根据实际元素修改
)
login_button.click()
# 7. 等待登录成功(跳转到主页或出现成功提示)
WebDriverWait(driver, 10).until(
EC.url_contains("主页URL") # 或 EC.presence_of_element_located(...)
)
print("登录成功!")
except TimeoutException:
print("操作超时,未找到元素")
except NoSuchElementException:
print("元素不存在")
except Exception as e:
print(f"发生错误:{e}")
finally:
# 8. 切换回主文档
driver.switch_to.default_content()
# 9. 关闭浏览器
# driver.quit()
'''
time.sleep(5)