1. 程式人生 > >Python +Selenium 底層API封裝(日誌+截圖管理)

Python +Selenium 底層API封裝(日誌+截圖管理)

使用:

import seleniumKing
king = seleniumKing.WebTools(path)
king.Open(URL)

直接附上原始碼:
 

import os
import sys
import time

from PIL import Image, ImageFilter
from pytesseract import pytesseract
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains

from util_s.logger import Logger
from util_s.config import Config

ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
sys.path.append(ROOT_DIR)


class WebTools(object):
    """selenium 底層API相關封裝"""
    def __init__(self, path="webTools"):
        self.Time_out = 5
        self.Time_poll = 0.5
        self.logger = Logger(path).getlog()

    """
    瀏覽器相關方法:
    前進,後退,重新整理,開啟,獲取Url,獲取Title
    """

    # 前進瀏覽器
    def Forward(self):
        self.driver.forward()
        self.logger.info("前進瀏覽器")

    # 後退瀏覽器
    def Back(self):
        self.driver.back()
        self.logger.info("後退瀏覽器")

    # 重新整理瀏覽器
    def Refresh(self):
        self.driver.refresh()
        self.logger.info("重新整理瀏覽器")

    # 開啟瀏覽器
    def Open(self, url, browser_type=Config().get("browser_type")):
        if browser_type == 'Firefox':
            self.driver = webdriver.Firefox()
        elif browser_type == 'Chrome':
            self.driver = webdriver.Chrome()
        elif browser_type == 'IE':
            self.driver = webdriver.Ie()
        else:
            self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)
        self.driver.get(url)
        self.logger.info("開啟瀏覽器:" + str(self.driver).split(".")[2] + "-" + "[" + url + "]")

    # 關閉瀏覽器
    def Quit(self):
        time.sleep(2)
        self.driver.quit()
        self.logger.info("關閉瀏覽器")

    # 關閉視窗
    def Close(self):
        self.driver.close()
        self.logger.info("關閉視窗")

    # 獲取瀏覽器URL
    def Get_Url(self):
        time.sleep(1)
        url = self.driver.current_url
        self.logger.info("獲取瀏覽器URL:" + "[" + str(url) + "]")
        return url

    # 獲取瀏覽器Title
    def Get_title(self):
        time.sleep(1)
        title = self.driver.title
        self.logger.info("獲取瀏覽器Title:" + "[" + str(title) + "]")
        return title

    """
    WebElement相關方法:
    提交表單,返回元素尺寸,返回元素文字,返回屬性值,返回元素是否可見,睡眠,返回當前驗證碼
    """

    # 提交表單
    def Submit(self, by):
        self.find(by).submit()
        self.logger.info("提交表單:By" + "[" + str(by) + "]")

    # 返回元素尺寸
    def Get_size(self, by):
        time.sleep(1)
        size = self.find(by).size
        self.logger.info("返回元素尺寸:By" + "[" + str(by) + "]-" + str(size))
        return size

    # 返回元素文字
    def Get_text(self, by):
        time.sleep(1)
        text = self.find(by).text
        self.logger.info("返回元素尺寸:By" + "[" + str(by) + "]-" + str(text))
        return text

    # 返回屬性值
    def Get_attribute(self, by, name):
        time.sleep(1)
        attribute = self.find(by).get_attribute(name)
        self.logger.info("返回屬性值:By/name" + "[" + str(by) + "/" + str(name) + "]-" + str(attribute))
        return attribute

    # 返回元素是否可見
    def Get_result(self, by):
        time.sleep(1)
        result = self.find(by).is_displayed()
        self.logger.info("返回元素是否可見:By" + "[" + str(by) + "]-" + str(result))
        return result

    # 返回當前驗證碼
    def Get_img_test(self, by, click_by):
        for a in range(100):
            time.sleep(1)
            file_path = os.path.dirname(os.path.abspath('.')) + '/testOutput/screenshots/'
            rq = "get_element_img"
            screen_name = file_path + rq + '.png'
            imger = self.get_element_img(by)
            im = Image.open(imger)
            img = im.convert('RGBA')
            pix = img.load()
            R = 125
            G = 125
            B = 125
            for y in range(img.size[1]):  # 二值化處理,這個閾值為R=125,G=125,B=125
                for x in range(img.size[0]):
                    if pix[x, y][0] < R or pix[x, y][1] < B or pix[x, y][2] < G:
                        pix[x, y] = (0, 0, 0, 255)
                    else:
                        pix[x, y] = (255, 255, 255, 255)
            img.save(imger)
            image = Image.open(imger)
            filterimg = image.filter(ImageFilter.MedianFilter)
            texts = pytesseract.image_to_string(filterimg)
            text = texts.lower()
            fomart = 'abcdefghijklmnopqrstuvwxyz0123456789'
            for c in texts:
                if c not in fomart:
                    text = text.replace(c, '')
            if len(str(text)) == 4:
                filterimg.save(screen_name)
                self.logger.info("驗證碼識別:" + text + ">>>" + imger)
                return text
            time.sleep(1)
            self.find(click_by).click()
            print(str(click_by))

    # 睡眠
    def Sleep(self, times):
        time.sleep(times)
        self.logger.info("睡眠:" + str(times))

    """
    滑鼠事件相關方法:
    右擊,懸停,雙擊,拖放
    """

    # 右擊
    def Cilck_right(self, by):
        ActionChains(self.driver).context_click(self.find(by)).perform()
        self.logger.info("右擊:By" + "[" + str(by) + "]")

    # 懸停
    def Move_to(self, by):
        ActionChains(self.driver).move_to_element(self.find(by)).perform()
        self.logger.info("懸停:By" + "[" + str(by) + "]")

    # 雙擊
    def Cilck_Double(self, by):
        ActionChains(self.driver).double_click(self.find(by)).perform()
        self.logger.info("雙擊:By" + "[" + str(by) + "]")

    # 拖放
    def Go_attribute(self, by_f, by_t):
        ActionChains(self.driver).drag_and_drop(self.find(by_f), self.find(by_t)).perform()
        self.logger.info("拖放:By" + "[" + str(by_f) + "->" + str(by_t) + "]")

    """
    鍵盤事件相關方法:
    回退字元,全選,複製,貼上, 撤銷,換行,空格,製表, 輸入,單擊,清除
    """

    # 回退字元
    def Keys_back(self, by):
        self.find(by).send_keys(Keys.BACK_SPACE)
        self.logger.info("回退字元:By" + "[" + str(by) + "]")

    # 全選
    def Keys_Ctrl_A(self, by):
        self.find(by).send_keys(Keys.CONTROL, "a")
        self.logger.info("全選:By" + "[" + str(by) + "]")

    # 複製
    def Keys_Ctrl_C(self, by):
        self.find(by).send_keys(Keys.CONTROL, "c")
        self.logger.info("複製:By" + "[" + str(by) + "]")

    # 貼上
    def Keys_Ctrl_V(self, by):
        self.find(by).send_keys(Keys.CONTROL, "v")
        self.logger.info("貼上:By" + "[" + str(by) + "]")

    # 撤銷
    def Keys_Ctrl_Z(self, by):
        self.find(by).send_keys(Keys.CONTROL, "z")
        self.logger.info("撤銷:By" + "[" + str(by) + "]")

    # 換行
    def Keys_Enter(self, by):
        self.find(by).send_keys(Keys.ENTER)
        self.logger.info("換行:By" + "[" + str(by) + "]")

    # 空格
    def Keys_Space(self, by):
        self.find(by).send_keys(Keys.SPACE)
        self.logger.info("空格:By" + "[" + str(by) + "]")

    # 製表
    def Keys_Tab(self, by):
        self.find(by).send_keys(Keys.TAB)
        self.logger.info("製表:By" + "[" + str(by) + "]")

    # 輸入
    def Input(self, by, inputvalue):
        self.find(by).clear()
        self.find(by).send_keys(inputvalue)
        self.logger.info("輸入:By" + "[" + str(str(by)) + "]")

    # 輸入_子元素
    def Input_Child(self, by, by1, inputvalue):
        self.find_Child(by, by1).clear()
        self.find_Child(by, by1).send_keys(inputvalue)
        self.logger.info("輸入_子元素:By" + "[" + str(by) + ">>>" + str(by1) + "]")

    # 單擊
    def Click(self, by):
        self.find(by).click()
        self.logger.info("單擊:By" + "[" + str(by) + "]")

    # 單擊_子元素
    def Click_Child(self, by, by1):
        self.find_Child(by, by1).click()
        self.logger.info("單擊_子元素:By" + "[" + str(by) + ">>>" + str(by1) + "]")

    # 清除
    def Clear(self, by):
        self.find(by).clear()
        self.logger.info("清除:By" + "[" + str(by) + "]")

    # 清除_子元素
    def Clear_Child(self, by, by1):
        self.find_Child(by, by1).clear()
        self.logger.info("清除_子元素:By" + "[" + str(by) + ">>>" + str(by1) + "]")

    # 確認警告框
    def Alert_accept(self):
        self.driver.switch_to_alert().accept()
        self.logger.info("確認警告框")

    # 取消警告框
    def Alert_dismiss(self):
        self.driver.switch_to_alert().dismiss()
        self.logger.info("取消警告框")

    # 返回警告框內容
    def Get_alert_text(self):
        text = self.driver.switch_to_alert().text
        self.logger.info("返回警告框內容:" + str(text))
        return text

    # 輸入警告框內容
    def Input_alert_text(self, text):
        self.driver.switch_to_alert().send_keys(text)
        self.logger.info("輸入警告框內容:" + str(text))

    # 返回所有Window控制代碼
    def Get_driver_windows(self):
        driver_windows = self.driver.window_handles
        self.logger.info("返回所有Window控制代碼:" + str(driver_windows))
        return driver_windows

    # 返回當前Window控制代碼
    def Get_driver_window(self):
        driver_window = self.driver.current_window_handle
        self.logger.info("返回當前Window控制代碼:" + str(driver_window))
        return driver_window

    # 切換Windows
    def Switch_window(self, window):
        self.driver.switch_to.window(window)
        self.logger.info("切換Windows:" + str(window))

    # 切換Frame
    def Switch_frame(self, by):
        self.driver.switch_to.frame(by)
        self.logger.info("切換Frame:By" + "[" + str(by) + "]")

    # 查詢元素
    def find(self, by):
        try:
            element = WebDriverWait(self.driver, self.Time_out, self.Time_poll, "NoFindWebelement").until(
                EC.presence_of_element_located(by))
            return element
        except:
            log = ("未找到Webelement:By" + "[" + str(by) + "]截圖:>>>" + self.get_windows_img())
            self.logger.info(log)

    # 查詢子元素
    def find_Child(self, by, by1):
        try:
            element = self.driver.find_element(*by)
            time.sleep(1)
            element = element.find_element(*by1)
            return element
        except:
            log = ("未找到Webelement:By" + "[" + str(by) + ">>>" + str(by1) + "]截圖:>>>" + self.get_windows_img())
            self.logger.info(log)

    # 查詢元素們
    def finds(self, by):
        try:
            elements = WebDriverWait(self.driver, self.Time_out, self.Time_poll, "未找到Webelement").until(
                EC.presence_of_all_elements_located(by))
            return elements
        except:
            log = ("未找到Webelement:By" + "[" + str(by) + "]截圖:>>>" + self.get_windows_img())
            self.logger.info(log)

    # 儲存瀏覽器截圖
    def get_windows_img(self):
        """
        在這裡我們把file_path這個引數寫死,直接儲存到我們專案根目錄的一個資料夾./testOutput/screenshots下
        """
        file_path = os.path.dirname(os.path.abspath('.')) + '/testOutput/screenshots/'
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        screen_name = file_path + rq + '.png'
        try:
            self.driver.get_screenshot_as_file(screen_name)
            return rq + '.png'
        except:
            self.logger.info("截圖失敗")

    # 儲存元素截圖
    def get_element_img(self, by):
        """
        在這裡我們把file_path這個引數寫死,直接儲存到我們專案根目錄的一個資料夾./testOutput/screenshots下
        """
        file_path = os.path.dirname(os.path.abspath('.')) + '/testOutput/screenshots/'
        rq = "get_element_img"
        screen_name = file_path + rq + '.png'
        element = self.find(by)
        try:
            self.driver.save_screenshot(screen_name)
            left = element.location['x']
            top = element.location['y']
            right = element.location['x'] + element.size['width']
            bottom = element.location['y'] + element.size['height']
            im = Image.open(screen_name)
            im = im.crop((left, top, right, bottom))
            im.save(screen_name)
            return screen_name
        except:
            self.logger.info("元素截圖失敗")