- browser: 浏览器
- 封装了浏览器相关操作
- 创建一个默认浏览器:
Browser()
- 浏览器默认配置:
Browser.DEFAULT_CONFIG
- 创建自定义浏览器:
Browser(config=config)
,config根据默认配置的数据结构传入即可
import importlib
from selenium.webdriver import Chrome, ChromeOptions, ActionChains
from selenium.webdriver.remote.webdriver 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 loguru import logger
from collections import namedtuple, defaultdict
Locator = namedtuple('Locator', ('type', 'value'))
class Browser:
MAX_TIMEOUT = 30
DEFAULT_CONFIG = {
'browser': 'Chrome',
# 显示等待超时时间
'timeout': MAX_TIMEOUT,
# 地址栏搜索页面加载超时时间
'page_max_load_time': MAX_TIMEOUT,
'browser_options':{
# 浏览器-无界面模式
'--headless': False,
# 浏览器-root权限
'--no-sandbox': True,
# 浏览器-禁用共享内存
'--disable-dev-shm-usage': True
}
}
def __init__(self, config=None):
# 加载配置
config = config or {}
self.config = {**Browser.DEFAULT_CONFIG, **config}
# 创建驱动
self.driver = Browser.create_driver(self.config)
# 全屏
self.driver.maximize_window()
# 隐式等待
self.driver.implicitly_wait(self.config.get('timeout'))
# 显示等待
self.waiter = WebDriverWait(self.driver, timeout=self.config.get('timeout'))
# 元素操作
self.action = ActionChains(self.driver)
logger.info(f'初始化浏览器配置 => {self.config}')
@staticmethod
def create_driver(config) -> WebDriver:
# 获取配置信息
browser_name = config.get('browser')
browser_options_name = browser_name + 'Options'
browser_options_kwargs = config.get('browser_options')
# 动态导入模块
webdriver = importlib.import_module('selenium.webdriver.__init__')
# 根据配置创建浏览器驱动和配置
browser_class = getattr(webdriver, browser_name)
browser_options = getattr(webdriver, browser_options_name)()
for k, v in browser_options_kwargs.items():
if v is True:
browser_options.add_argument(k)
return browser_class(options=browser_options)
# js操作
def js(self, script: str, *args):
logger.info(f'js操作 => {script}({args})')
self.driver.execute_script(script, *args)
# 页面级操作
def search(self, url):
logger.info(f'当前页面地址栏输入 => {url}')
self.driver.set_page_load_timeout(self.config.get('page_max_load_time'))
self.driver.get(url)
def f5(self):
logger.info('刷新当前页面')
self.driver.refresh()
def close_window(self):
logger.info('关闭当前窗口')
self.driver.close()
def quit_browser(self):
logger.info('关闭浏览器')
self.driver.quit()
@property
def html(self):
_ = self.driver.page_source
logger.info(f'源码 => {_}')
return _
def to_window(self, handle):
logger.info(f'跳转到指定窗口 => {handle}')
self.driver.switch_to.window(handle)
def current_window(self):
_ = self.driver.current_window_handle
logger.info(f'当前窗口 => {_}')
return self.driver.current_window_handle
def all_window(self):
_ = self.driver.window_handles
logger.info(f'所有窗口 => {_}')
return _
def to_frame_by_element(self, locator):
# 这里只支持通过子元素进入,如果需要通过引用则重写
logger.info(f'进入{locator}元素所在frame => {locator}')
self.driver.switch_to.frame(self.find_elements(locator))
def move_to_by_element(self, locator):
logger.info(f'窗口显示位置移到到{locator}')
self.action.move_to_element(self.find_element(locator))
def move_to_by_js(self, x=100000, y=100000):
# 未传参 或 超出了范围 则 滑到末尾
logger.info(f'js滑动窗口 => window.scrollTo({x},{y})')
x = x if 0<=x<=100000 else 100000
y = y if 0<=x<=100000 else 100000
self.js(f'window.scrollTo({x},{y})')
# 元素级操作
def _accord_wait(self, scanner):
return self.waiter.until(scanner)
def find_element(self, locator: Locator):
logger.info(f'显示等待获取一个元素 => {locator}')
return self._accord_wait(ec.presence_of_element_located(locator))
def find_elements(self, locator):
logger.info(f'显示等待获取一组元素 => {locator}')
return self._accord_wait(ec.presence_of_all_elements_located(locator))
def input(self, locator: Locator, text):
logger.info(f'输入文本 => {locator} => {text}')
ele = self.find_element(locator)
ele.clear()
ele.send_keys(text)
def click(self, locator: Locator):
logger.info(f'点击元素 => {locator}')
self.find_element(locator).click()
def text(self, locator: Locator):
_ = self.find_element(locator).text
logger.info(f'获取元素文本 => {locator} => {repr(_)}')
return _
def test():
# 创建浏览器1
browser1 = Browser()
# 创建浏览器2
browser2 = Browser()
# 浏览器搜索
browser.search('http://www.baidu.com')
# 浏览器搜索
browser.search('https://www.cnblogs.com/yufeihlf/p/5689042.html')
if __name__ == '__main__':
test()