风火编程--selenium和webdriver等待/点击/frame/window切换窗口最大化/滚动/js定位

本文详细介绍Selenium结合Chromedriver进行网页自动化测试的高级配置技巧,包括无头模式、页面加载策略、元素等待策略、多窗口切换、iframe处理、滚动加载及截图等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

chromedriver的一些初始化设置

import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
    chrome_options = Options()
    # 设置无头
    chrome_options.add_argument('--headless')
    # 设置不加载图片
    prefs = {"profile.managed_default_content_settings.images": 2}
    chrome_options.add_experimental_option("prefs", prefs)
    driver = webdriver.Chrome(
    chrome_options=chrome_options, executable_path=r'D:\software\python36\chromedriver.exe')
    # 设置页面加载超时
    driver.set_page_load_timeout(20) 
    # 设置页面异步js执行超时
   driver.set_script_timeout(10)  

等待

显式等待
   from selenium.webdriver.support.wait import WebDriverWait
   from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, max_wait)
wait.until(EC.element_to_be_clickable((By.ID, 'sendPhoneCode'))).click()

# 其他判断加载的方法

# *****常用: 判断元素以加载到DOM, 传入element
presence_of_element_located
 # *****常用: 判断某个元素中是否可点击
element_to_be_clickable

   # 判断某个元素是否可见, 传入locator
invisibility_of_element_located
 # 判断该frame是否可以switch进去,如果是返回True并且switch进去,否则返回False
frame_to_be_available_and_switch_to_it
    # 判断某个元素中的text是否 包含 了预期的字符串
text_to_be_present_in_element
# 判断某个元素中的value属性是否包含了预期的字符串
text_to_be_present_in_element_value
# 将某个元素从dom树中移除,返回True或False
staleness_of
# 判断某个元素是否被选中了,一般用在下拉列表
element_to_be_selected
# 判断元素是否可见
visibility_of
# 判断标题等于
title_is
# 标题包含
title_contains
# 判断页面上是否存在alert
alert_is_present
# 确认弹出框
driver.switch_to.alert.accept()
隐式等待
driver.implicitly_wait(seconds)
强制等待
time.sleep(seconds)

新标签中打开url, 并切换到该标签

js = 'window.open("{}");'.format(dl_url)
driver.execute_script(js)
driver.switch_to_window(driver.window_handles[1])

窗口最大化

最大化方式打开
chrome_options = Options()
chrome_options.add_argument('--start-maximized')
已开窗口最大化
driver.maximize_window()

窗口切换

driver.switch_to.window(driver.window_handles[-1])

iframe的处理

sleep(2)
iframe = driver.find_element_by_xpath('//iframe[@class="iframe"]')
 driver.switch_to.frame(iframe)
 driver.switch_to_default_content()
 load = driver.find_element_by_xpath('//a[@id="WkDialogOk"]')
 load.click()
 driver.close()

滚动加载

js滚动1
time.sleep(2)
js = "var q=document.documentElement.scrollTop=1000"
or
js = 'page.evaluate("window.scrollTo(0, document.body.scrollHeight);")'
driver.execute_script(js)

js滚动2

target = browser.find_element_by_class_name("loadmore disabled")
if target.xpath('./text()').extract_first() != "没有更多了":
# 拖动到可见的元素去
    js = "arguments[0].scrollIntoView();"
    driver.execute_script(js, target)
    time.sleep(1)

js滚动3

    js = "window.scrollBy(0,{})"
    driver.execute_script(js.format(random.uniform(0, 5000)))
pagedown滚动
try:
    for i in range(25):
        roll = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@lang="en"]')))
        roll.send_keys(Keys.PAGE_DOWN)
        sleep(2)
except:
    driver.quit()

点击

正常点击
target.click()
被遮挡的元素点击
from selenium.webdriver.common.keys import Keys
target.sendkeys(Keys.ENTER)
js点击1
js = 'var q=document.getElementById("map-distance").click()'
driver.execute_script(js)
js点击2
js1 = 'var q=document.getElementById("mapdistance").children[3].setAttribute("class","on")'
js2 = 'var a=document.getElementById("mapdistance").children[0].removeAttribute("class")'
driver.execute_script(js1)
driver.execute_script(js2)

js定位元素

# 获取指定 ID 的元素
document.getElementById()
# 获取包含带有指定类名的所有元素的节点列表
document.getElementsByClassName()    
# 获取指定Name的所有元素的节点列表
document.getElementsByName()    
# 获取带有指定标签名称的所有元素的节点列表
document.getElementsByTagName()

提取标签数据

element = driver.find_element_by_id("...")
# 获取文本
text = element.text
# 获取属性
href = element.get_attribute("href")
# 隐藏的文本内容
判断是否可见
erlement.is_display()
返回值为False的一般隐藏在以下三个属性中:
textContent / innerText / innerHTML
text = element.get_attribute('textContent ')

DEMO

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

input = wait.until(EC.presence_of_element_located((By.ID, 'input')))
input.send_keys("keywords")
button= wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="btn"]')))
 button.click()

参考链接:

https://www.cnblogs.com/nbkhic/p/4885041.html
服务器部署

https://blog.youkuaiyun.com/fengmm521/article/details/79661771

注意
如果使用–headless拿不到数据, 是因为版本太高了, 换成62之前的版本即可
http://www.manongjc.com/article/7635.html
创建chromedriver的软连接到全局路径

ln -s /opt/google/chromedriver /usr/bin/chromedriver

chrome历史版本下载链接

https://www.chromedownloads.net/chrome64linux-stable/
https://www.chromedownloads.net/chrome64linux/

chrome与driver版本
https://www.chromedownloads.net/chrome64linux/
https://downzen.com/en/windows/google-chrome/versions/

driver下载

http://chromedriver.storage.googleapis.com/index.html
https://phantomjs.org/download.html

selenium支持phontomjs 的版本

pip3 install selenium==2.48.0

phontomjs参考链接

https://www.168seo.cn/python-2/3385.html


dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = (
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0")
# 设置user-agent请求头
dcap["phantomjs.page.settings.loadImages"] = False  # 禁止加载图片
driver = webdriver.PhantomJS(desired_capabilities=dcap)
#使用代理
chrome_options.add_argument("--proxy-server=http://202.20.16.82:10152")

设置为开发模式

此步骤很重要,设置chrome为开发者模式,防止被各大网站识别出来

options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])

截取指定坐标范围的图片

加载图片

image = wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="qrcode-img"]/img')))

获取图片左上角坐标

location = image.location
print('参考坐标:{}'.format(location))

获取图片参考尺寸

size = image.size()
print('参考尺寸:{}'.format(size))

获取整个页面的图片

img_screen = driver.get_screenshot_as_png()
open_img = Image.open(BytesIO(img_screen))

首次截取图片

left = location['x']
top = location['y']
height = size['height']
width = size['width']
right = left + width
bottom = top + height
print(left, top, right, bottom)
target_img = open_img.crop((left, top, right, bottom))
target_img.show()

调整left, top, right, bottom的值
直到得到理想的效果

保存图片

target_img .save('target_img.png')

设定参数
options = webdriver.ChromeOptions()
options.binary_location = chromebrowser_path # 指定浏览器路径
# options.add_argument(“–window-size=800,600”) # 指定窗口大小打开
options.add_argument(“–start-maximized”) # 全屏打开
options.add_argument(“–window-position=100,100”) # 指定窗口位置
prefs = {“profile.managed_default_content_settings.images”: 2} # 不加载图片
options.add_experimental_option(“prefs”, prefs)

if not head:
    options.add_argument('--headless')  # 无头
else:
    options.add_argument(
        '--user-data-dir=' + chromedata_path)  # 使用chrome插件

driver_ = webdriver.Chrome(executable_path=chromedriver_path, options=options)
wait_ = WebDriverWait(driver_, 30)
Traceback (most recent call last): File "C:\Users\czadmin\PyCharmMiscProject\cyllq.py", line 9, in <module> browser.find_element(By.CSS_SELECTOR, "btnLogin").click() ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\czadmin\AppData\Local\Programs\Python\Python313\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 740, in find_element return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"] ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\czadmin\AppData\Local\Programs\Python\Python313\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 346, in execute self.error_handler.check_response(response) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "C:\Users\czadmin\AppData\Local\Programs\Python\Python313\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 245, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"btnLogin"} (Session info: chrome=134.0.6998.117); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception Stacktrace: GetHandleVerifier [0x00007FF7FC9AFE45+26629] (No symbol) [0x00007FF7FC916010] (No symbol) [0x00007FF7FC7A931A] (No symbol) [0x00007FF7FC7FF8E7] (No symbol) [0x00007FF7FC7FFB1C] (No symbol) [0x00007FF7FC8534A7] (No symbol) [0x00007FF7FC827AEF] (No symbol) [0x00007FF7FC850169] (No symbol) [0x00007FF7FC827883] (No symbol) [0x00007FF7FC7F0550] (No symbol) [0x00007FF7FC7F1803] GetHandleVerifier [0x00007FF7FCD072BD+3529853] GetHandleVerifier [0x00007FF7FCD1DA22+3621858] GetHandleVerifier [0x00007FF7FCD124D3+3575443] GetHandleVerifier [0x00007FF7FCA7B77A+860474] (No symbol) [0x00007FF7FC92088F] (No symbol) [0x00007FF7FC91CBC4] (No symbol) [0x
03-21
<think>好的,我现在需要解决用户提到的Selenium中常见的NoSuchElementException问题,特别是当使用CSS选择器btnLogin时找不到元素的情况。首先,我应该回忆一下常见的导致元素无法定位的原因,然后逐步分析可能的解决方案。 首先,用户提到使用的是CSS选择器btnLogin,但可能这里的选择器书写是否正确?比如,如果btnLogin是一个id,那么正确的CSS选择器应该是#btnLogin。如果是class的话,应该是.btnLogin。用户可能遗漏了前缀符号,导致选择器不正确,从而引发异常。 其次,元素可能还未加载完成,这时候直接定位就会失败。这时候应该考虑使用显式等待,通过WebDriverWaitexpected_conditions来等待元素出现。比如,用户提供的引用[3]中的代码示例,使用WebDriverWait设置超时时间,并检查元素是否存在。这样可以避免因为页面加载慢导致的元素找不到的问题。 另外,页面可能存在iframe或者frame,元素嵌套在其中,这时候需要先切换到对应的frame才能找到元素。用户如果没有切换的话,直接查找会失败。这时候应该检查页面结构,确认是否有frame存在,并执行driver.switch_to.frame操作。 还有一种可能是元素的属性是动态生成的,比如每次页面加载时id或class会变化,这时候需要确认选择器是否稳定,或者改用其他属性定位,比如XPath中的部分匹配或文本内容。 此外,浏览器窗口可能没有最大化,导致元素不在可视区域内,或者被其他元素遮挡,虽然这种情况较少见,但有时候也会影响元素的定位。可以尝试最大化窗口或者滚动到元素的位置。 还要检查是否正确安装了WebDriver,比如引用[4]提到的ChromeDriver需要正确安装并配置环境变量。如果驱动不匹配或者路径错误,可能导致页面加载不完全,从而元素无法找到。 最后,可能需要查看页面HTML结构,确认元素的定位方式是否正确。可以通过浏览器的开发者工具检查元素,确认CSS选择器是否准确无误。如果有拼写错误或者层级错误,也会导致定位失败。 综合以上可能的原因,解决方案应首先检查选择器是否正确,然后添加显式等待,处理frame,确认元素属性稳定性,并确保驱动配置正确。用户提供的引用[3]中的显式等待方法是一个关键点,可以有效解决元素加载延迟的问题。同时,引用[4]的环境配置也是基础,需要确保正确安装驱动。</think>要解决Selenium中因元素未找到而抛出`NoSuchElementException`的问题(例如使用CSS选择器`btnLogin`定位时),可以按以下步骤排查: ### 1. **验证CSS选择器语法** - **错误示例**:直接使用`btnLogin`可能遗漏了符号前缀。若`btnLogin`是元素的`id`属性,正确写法应为`#btnLogin`;若是`class`属性则应为`.btnLogin`[^3]。 - **检查方式**:在浏览器开发者工具中按`Ctrl+F`输入选择器,确认是否能匹配到目标元素。 ### 2. **添加显式等待** 元素可能因页面加载延迟未渲染完成。使用显式等待替代直接定位: ```python from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "#btnLogin")) ) ``` 此代码会等待最多10秒,直到元素出现。 ### 3. **处理iframe/frame嵌套** 若元素位于iframe中,需先切换到对应iframe: ```python iframe = driver.find_element(By.CSS_SELECTOR, "iframe#login_frame") driver.switch_to.frame(iframe) # 再尝试定位元素 ``` 操作完成后需切换回默认内容:`driver.switch_to.default_content()`。 ### 4. **检查元素是否在弹窗或新窗口** 如果点击按钮后触发了新窗口或弹窗,需切换窗口句柄: ```python main_window = driver.current_window_handle for handle in driver.window_handles: if handle != main_window: driver.switch_to.window(handle) ``` ### 5. **确认页面兼容性与动态属性** - 若元素属性是动态生成的(如随机ID),改用其他稳定属性,例如`XPath`部分匹配: ```python driver.find_element(By.XPATH, "//button[contains(@class, 'btnLogin')]") ``` - 使用`execute_script`滚动到元素可见区域: ```python element = driver.find_element(By.CSS_SELECTOR, "#btnLogin") driver.execute_script("arguments[0].scrollIntoView();", element) ``` ### 6. **环境配置检查** - 确认`ChromeDriver`版本与浏览器匹配,并已添加到环境变量[^4]。 - 更新Selenium库:`pip install --upgrade selenium` ### 示例完整代码 ```python 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 driver = webdriver.Chrome() driver.get("https://example.com/login") try: # 显式等待 + 处理iframe WebDriverWait(driver, 10).until( EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe.login")) ) btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "#btnLogin")) ) btn.click() finally: driver.quit() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值