#! /usr/bin/env/python3  
# -*- coding=utf-8 -*-  
"""  
======================模块功能描述=========================      
       @File     : aa.py  
       @IDE      : PyCharm       @Author   :       @Date     : 2025/5/6 11:30  
       @Desc     : =========================================================  
"""  
import time  
from time import sleep  
  
# selenium 4  
from selenium import webdriver  
from selenium.webdriver.chrome.options import Options  
from selenium.webdriver.common.by import By  
  
#  导入edge浏览器# from selenium.webdriver.edge.options import Options  
  
options = Options()  
options.add_argument("start-maximized")  # 最大化窗口  
options.add_experimental_option("detach", True)  # 保持浏览器窗口不自动关闭  
# 伪装浏览器没有受到自动测试软件的控制  
options.add_experimental_option("excludeSwitches", ['enable-automation'])  
# 创建浏览器对象  
driver = webdriver.Chrome(options=options)  
driver.get("http://v5.crmeb.net/admin")  
driver.implicitly_wait(5)  
driver.find_element('xpath', '//*[@id="app"]/div[1]/div[1]/div/form/div[1]/div/div/input').clear()  
driver.find_element('xpath', '//*[@id="app"]/div[1]/div[1]/div/form/div[2]/div/div/input').clear()  
sleep(2)  
# 重新输入数据 admin crmeb.comdriver.find_element('xpath', '//*[@id="app"]/div[1]/div[1]/div/form/div[1]/div/div/input').send_keys('admin')  
driver.find_element('xpath', '//*[@id="app"]/div[1]/div[1]/div/form/div[2]/div/div/input').send_keys('crmeb.com')  
driver.find_element('xpath', '//*[@id="app"]/div[1]/div[1]/div/form/div[3]/div/button').click()  
# selenium4写法  
textarea = driver.find_element('tag name', 'textarea')  
# 清楚原输入框数据  
sleep(2)  
driver.quit()  
# print(driver.page_source)  
driver.refresh()
options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')                   # 解决DevToolsActivePort文件不存在的报错
options.add_argument('window-size=1920x3000')         # 指定浏览器分辨率
options.add_argument('--disable-gpu')                 # 规避GPU相关bug
options.add_argument('--incognito')                   # 隐身模式(无痕模式)
options.add_argument('--disable-javascript')          # 禁用javascript
options.add_argument('--start-maximized')             # 最大化运行(全屏窗口)
options.add_argument('--hide-scrollbars')             # 隐藏滚动条
options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片
options.add_argument('--headless')                    # 无头模式, 静默运行, 无可视化界面
options.add_argument('lang=en_US')                    # 设置语言
options.add_argument('User-Agent=Mozilla/5.0...')     # 自定义UA
options.binary_location = r"C:\Program Files...chrome.exe"  # 指定浏览器位置

prefs = {
    "credentials_enable_service": False,
    "profile.password_manager_enabled": False
}
options.add_experimental_option("prefs", prefs)       # 屏蔽密码提示框

这句话是指设置代理(谷歌浏览器)

options.add_argument('User-Agent=Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BLA-AL00 Build/HUAWEIBLA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.9 Mobile Safari/537.36')
#设置窗口大小
dr.set_window_size( width: 500, height: 600)

最小化窗口

dr.minimize_window()

隐式等待

#隐式等待
#一次编程,到处运行
# 等待页面加载, 加载完成即下一步, 如果5秒还未加载完成, 就会出现timeout超时错误
dr.implicitly_wait(5)
# 输入搜索框内容
dr.find_element( by: 'id', value: 'kw').send_keys("测试")

基本元素定位的方式

#元素定位的方式有id, name, xpath, css, link_text, partial_link_text, tag_name, class

id 定位
id就好比我们的身份证号码,在一个页面,id必须是唯一的,如果id不唯一,可以
投诉开发编码不规范

# 通过id找查元素
baidu_id=dr.find_element_by_id('kw')  # selenium2 支持这种写法 4不支持

在selenium3和selenium4早期只支持这种写法

baidu_id=dr.find_element(By.ID, 'kw')

selenium 4.32 当前版本还支持这种写法

baidu_id=dr.find_element( by: "id", value: "kw")

selenium4中提供了5种相对定位器

Id和name是使用的最多的元素定位方式 name好比人的名字, 在一个页面name往往也不相同

dr.find_element( by: 'name', value: "edit"),send_keys("好的。阿健")

获取页面HTML代码

print(driver.page_source)

xpath 定位 万能定位
xpath分为 绝对路径和相对路径

绝对的路径:
html/body/center/p/table/tbody/tr[6]/td[2]/input[1]

driver.find_element('xpath', 'html/body/center/p/table/tbody/tr[6]/td[2]/input[1]').sendkeys()

相对的路径
//代表层级
//input 代表在所有input标签下。type='text' 是指找到type=text的元素
input可以换成其他标签。需要找哪个元素就换成对应的标签,或者换成*,//*代表所有的标签层级下面
使用其他属性,反正可以唯一标识该标签就行。
这里还可以改成//*[@id='kw']

dr.find_element('xpath', '//input[@type="text"]').send_keys("abc")
driver.find_element( 'xpath', '//*[@id="kw"]').send_keys("abc")

父子级定位
父子级定位,如果要找的元素,父级代码中有唯一可以标识的元素,就可以限定为父级,在找到对应的元素。

//td[@id='123']/input[1]

如果元素没有唯一可以标识的属性,那么就使用多属性组合。
在所有input标签下,找到属性type为text并且name为edit的元素。

dr.find_element( by: "xpath', value: "//input[atype="text"
Aname=
).send_keys('abc')
/input[@type="text"][@name="edit"]

清除元素数据

元素定位.clear()//清除

获取title

print(dr.title)

获取当前url地址

print(dr.current_url)

断言(验证是否正确, 看它是否报错)

assert dr.title == 'CRMEB标准版-123'

如果前后两个条件相等,则默认运行后续的代码,如果不相等,则报错,正因为有错误,
所有就有BUG。

#获取title
print(dr.title)
#获取当前url地址
print(dr.current_url)
assert dr.title == 'CRMEB标准版-123'

模拟浏览器刷新操作

dr.back()
dr.forward()
井模拟浏览器刷新操作
dr.refresh()
//input[@type="text" and @name="edit"]
class 定位 不太靠谱。如果能保证页面
某个元素的class属性是唯一的,那么可以使用

tag标签定位
一个页面往往有多个标签, 标签定位极为不靠谱 ,除非该元素对应的标签独一无二。

# 例如页面中只有一个textarea标签时可用
textarea = driver.find_element_by_tag_name('textarea')

# selenium4写法
textarea = driver.find_element('tag name', 'textarea')
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage:
    def __init__(self, driver: WebDriver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    def find(self, locator):
        return self.wait.until(EC.presence_of_element_located(locator))
    
    def click(self, locator):
        self.find(locator).click()
    
    def input_text(self, locator, text):
        self.find(locator).send_keys(text)
from selenium.webdriver.common.by import By
from pages.base_page import BasePage

class LoginPage(BasePage):
    # 元素定位器
    USERNAME_INPUT = (By.ID, 'username')
    PASSWORD_INPUT = (By.CSS_SELECTOR, '#password')
    SUBMIT_BUTTON = (By.XPATH, '//button[@type="submit"]')
    
    def login(self, username, password):
        self.input_text(self.USERNAME_INPUT, username)
        self.input_text(self.PASSWORD_INPUT, password)
        self.click(self.SUBMIT_BUTTON)
        return HomePage(self.driver)  # 返回下一个页面对象
from selenium.webdriver.common.by import By
from pages.base_page import BasePage

class HomePage(BasePage):
    WELCOME_TEXT = (By.CLASS_NAME, 'welcome-msg')
    
    def get_welcome_text(self):
        return self.find(self.WELCOME_TEXT).text
import unittest
from selenium import webdriver
from pages.login_page import LoginPage

class TestLogin(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(10)
    
    def test_valid_login(self):
        login_page = LoginPage(self.driver)
        login_page.driver.get("https://example.com/login")
        
        home_page = login_page.login("admin", "password123")
        welcome_text = home_page.get_welcome_text()
        
        self.assertIn("Welcome", welcome_text)
    
    def tearDown(self):
        self.driver.quit()