读后笔记 -- Python 全栈测试开发 Chapter3:Selenium

3.1 HTML

3.1.2 HTML 元素

  HTML 元素分为三种类型:

类型     常用的元素
块状元素 该元素的内容相对于前后元素内容另起一行

可实现自定义高度和宽度,常作为其他元素的容器,

可实现内联元素和其他块状元素的包含操作

div, dl, menu, dt, dd, ol, ul, h1-h6,

p, form, hr, table, tr, td 等

内联元素 该元素的内容与其前后元素的内容在一行显示 以行内的形式逐个显示,没有自己的形状,

a, br, select, u, span, i, em, strong,

img, input, b 等

可变元素 需要根据上下文关系来确定是 块状元素 还是 内联元素  

applet, button, script, object, map, iframe, 

del, ins 等 

<!-- ul 和 ol,其中 ol 标签表示的是有序列表,ul 表示的是无序列表 -->
<!-- span 是用于组合行内元素,便于格式化 -->

3.1.7 HTML 页面

<html>
    <head>
	<title>Combine all elements in an entire HTML Page</title>
    </header>
<body> <!-- Title --> <div id="header"> <h1>Welcome to Wood Programming</h1> </div> <p>This is wood programming's QR code</p> <!-- This is wood programming's QR code --> <div id="image"> <img src="wood.jpg" height="200" width="200"> </div> <!-- embed iframe frame --> <p>You can baidu if you want to learn more</p> <iframe src="https://www.bing.com" name="iframe_1" width="600" height="300"></iframe> <!-- Do a simple investigation --> <form action="success" method="post"> <!-- input, password --> <div> Username: <br/><input type="text" /><br/> Age: <br/><input type="text" /><br/> <!-- link has some problem, can't connect --> 验证码:<input type="text" /><img src="http://123.57.71.195:8787/index.php/home/seccode/makecode.html?1591430678772" /><br/> <input type="text"/><br/> </div> </form> <div> which language do you like: <br/> Java<input type="checkbox" /><br/> Python<input type="checkbox" /><br/> Other<input type="checkbox" /><br/> sex: Male<input type="radio" name="sex" /> Female<input type="radio" name="sex" /><br/> Graduation: <select> <option>Not Selected</option> <option>Doctor</option> <option>Bachlor</option> <option>Colleage</option> </select><br/><br/> Note:<textarea clos="10" rows="6"></textarea><br/> <input type="submit" value="submit" onclick="javascript:alert('Confirm to submit?')"/> <input type="reset" value="reset"/> <input type="button" value="confirm"/> </div> </body> </html>

3.2 CSS

1. HTML5体系主要由 HTML5、CSS3 和 JS 等技术构成。

2. CSS:表现 HTML 或 XML 等文件样式。可以控制页面的整体样式,HTML 标签设计 只能用于定义文档内容,过多的属性都是通过 css 进行完成。简单来说,CSS 使用一系列标签完成 HTML 中文档内容的格式化操作。

    css 的作用:1)实现 html 样式表的定义;2)解决了内容与表现分离问题;3)外部样式表可以极大的提高工作效率(所有的样式表都存储在外部的css文件中)

3. CSS 将样式层叠为一个,样式不仅可以定义在单个 HTML 元素中,也可以定义在一个外部 CSS 文件中,甚至可以在同一 HTML 文档中引用多个外部样式表。

4. CSS 语法结构:选择器和声明。如:p {text-align:center; color:yellow;}

    

5. CSS 对空格无影响,大小写不敏感。但涉及 HTML 融合,class 和 id 对大小写敏感。

6. CSS 高级语法:

    备注:相关的 css 定义放在 <style> </style> 内

选择器的分组

h1,h2,h3 {

   color: red;

}

分组选择器用 “,” 隔开
选择器的继承

body {

  font-family: arial, sans-serif;

}

p {

  font-family: Times, "Times New Roman", serif;

}

1. 通过继承,子元素将 继承 body 的所有属性

2. 如使用其他属性,可额外定义一个,如 p

派生选择器

li strong {

  font-style: italic;

  font-weight: normal;

}

<p><strong>我是粗体,因为我不在列表中,规则无效</strong></p>

<li><strong>我是斜体,因为strong在li 中</strong></li>

# 第二行将是斜体,因为 strong 在 li 元素内

后代选择器

语法: 祖先元素 后代元素 { }

如: h1 em {color: red;}

作用于 N 代元素
子元素选择器

语法: 父元素>子代元素 { }

如: div>ul {color: red;}

仅作用于第 1 代元素

3.3 Selenium 基础

1. Selenium 框架的构成

Selenium IDE                     Firefox 的一个插件,可录制生成脚本。脚本可回放或转成其他语言

Selenium RC 

  -- Client Libraries          通过编写测试脚本来控制 Selenium Server 库

  -- Selenium Server        主要负责控制浏览器的行为

    -- Launcher             启动浏览器,然后将 Selenium Core 加载到浏览器页面

    -- Http Proxy           完成对应浏览器的代理设置

    -- Core                    一系列 JS 函数的集合,只有通过 JS 才可以实现用程序对浏览器进行相应的操作

Selenium WebDriver           Selenium RC 的升级版,基于 RC 的再次封装,可直接发送命令给浏览器
Selenium Grid                    用于不同机器、浏览器的并行测试

selenium 的基础知识(selenium探秘【SeleniumRC的组成和SeleniumRC的有优缺点】)link: https://blog.csdn.net/Liuyanan990830/article/details/124691851

 

2. Firefox 安装 Selenium IDE

  • Firefox browser:  key in "about:addons" in web
  • search "selenium" after 'Find more add-ons'
  • click the find out IDE to the detail then 'Add to Firefox'
  • after installation, there is a  icon on Firefox

          

selenium IDE 的主要用途可以辅助 selenium 脚本的开发,录制时会录制相关的元素定位。

 


3.4 Selenium 元素定位

定位类别 元素 示例
1. 8种基本元素定位
1) id
# 百度搜索框
# element_search_input = driver.find_element_by_id("kw")
# element_search_input = driver.find_element_by_name("wd")
element_search_input = driver.find_element_by_class_name("s_ipt")
# element_search_input = driver.find_element_by_tag_name("input") # 不易定位,一般相同的 tag 很多

element_search_input.send_keys("id test")

# 搜索一下
# element_search_btn = driver.find_element_by_id("su")
element_search_btn = driver.find_element_by_class_name("s_btn") # baidu 搜索按钮: class="btn self-btn bg s_btn"
element_search_btn.click()

# 登录按钮
element_login_from_homepage = driver.find_element_by_name("tj_login")
element_login_from_homepage.click()

# 忘记密码
# element_forget_pwd = driver.find_element_by_link_text("忘记密码?")
element_forget_pwd = driver.find_element_by_partial_link_text("忘记")
element_forget_pwd.click() 
2) name
3) class_name
4) tag_name
5) link_text
6) partial_link_text
7) xpath

7.1)绝对路径   /html/body/div[1]/div/div/div/div/div/ul/li[1]/input

7.2)相对路径

   - 7.2.1)属性定位:                                           //标签名[@属性名=属性值]    //input[@name='uname']

   - 7.2.2)多属性定位+逻辑运算符(and / or /not)://标签名[@属性名=属性值]    //input[@name='uname' and @pwd='upasswd']

                 一般属性不超过2个

   - 7.2.3)嵌入函数

    a) text 函数:                                            //标签名[text()=文本内容]

    b) contains 函数:                                     //标签名[contains(@属性名, 对应属性名的部分值)]

    c) starts-with 函数:                                  //标签名[starts-with(@属性名, 对应属性名的前面部分值)]

    d) ends-with 函数:                                   //标签名[ends-with(@属性名, 对应属性名的后面部分值)]

8) css

通过选择器(具体看书 P68-69)如: driver.find_element_by_css_selector("div>h3>a")

常使用的有:.class(class定位)/ #id (id定位)/ :first-child / :nth-child(n) / :last-child

2. 复数定位 

find_elements_by_id() / name() / class_name() / tag_name() /

                        link_text() / partial_link_text() / xpath() / css_selector()

1)返回的是列表数据类型,可通过索引取出具体的元素;

2)pop() / pop(-1):获取最后一个元素, pop(2):获取第三个元素

如: driver.find_elements("css selector", ".manv").pop().click()

3. By 定位 

find_element(By.ID, "属性值") / By.NAME / By. CLASS_NAME

                      By.TAG_NAME / By.LINK_TEXT / By.PARTIAL_LINK_TEXT /

                      By.XPATH / By.CSS_SELECTOR

 
4. 父子定位、二次定位 

父子定位:往上找可定位的父元素

二次定位:先定位到可定位的一级标签,作为基准再次定位

父子定位: driver.find_element(By.XPATH, "//div[@class='total_bodyer']/div[3]/p")

二次定位: driver.find_element_by_id("s-top-left").find_element_by_link_text('贴吧').click()

5. JS 定位 

应用于:基本方式无法定位,如 Windows 窗口、浏览器滚动条等

常用的定位方式:

  • document.getElementByID()
  • ------  下面返回的都是列表,需要添加索引定位 ------
  • document.getElementsByName()
  • document.getElementsByTagName()
  • document.getElementsByClassName()
  • document.querySelectorAll() 

*document 表示当前 HTML 对象

API: https://developer.mozilla.org/zh-CN/docs/Web/API

 
# 百度左上角 hao123
hao123 = "document.getElementsByClassName('mnav')[1].click()"
driver.execute_script(hao123)
6. jQuery 定位 

应用于较复杂的页面,前面几种定位方式都无法处理。

1. 两种方式

1)通过 jQuery 选择器完成元素的选择操作,可获取一个或一组元素;

2)通过 jQuery 遍历选择元素(常用于较复杂的层级元素) 

*手册:https://www.w3school.com.cn/jquery/jquery_ref_selectors.asp

2. 文本赋值使用的该方法的value属性,如是按钮,直接使用click()方法;

3. 如已定位到对应的对象,但无法完成某些事件的操作,则可通过该对象调用

标签声明的操作对象的属性值(js脚本),然后execute_script该js脚本

   # 百度输入框输入 ‘jQuery test’
element_jquery_search_input = """$('input[name="wd"]').val('jQuery test')"""
driver.execute_script(element_jquery_search_input)

# 点击搜索
element_jquery_btn = "$('#su').click()"
driver.execute_script(element_jquery_btn)

# js 脚本
7.  隐藏元素的操作

1)通过 JS 定位到元素,获取对象;

2)removeAttribute 和 setAttribute 使其处于显示状态 

# 修改属性值

driver.get("http://192.168.2.211:30020/index.html#/")

element_checkbox = "document.getElementsByClassName('el-checkbox__original')[0].setAttribute('aria-hidden', 'true')"

driver.execute_script(element_checkbox)


3.5 Selenium 操作浏览器

浏览器操作 语法
前进 driver.forward() / driver.back()
窗口

最大:driver.maximize_window()

最小:driver.minimize_window()

全屏:driver.fullscreen_window()

关闭 driver.close() (关闭当前) / driver.quit() (关闭所有)
获取属性

当前 url:driver.current_url

当前对象的句柄: driver.curent_window_handle

当前对象的标题: driver.title

当前对象的所有句柄(选项卡): driver.window_handles    # 列表形式

切换到某个窗口(通过句柄):driver.switch_to.window(句柄名)

     recommendated: set a name for window handle

     handle_baidu = driver.window_handles[0]

     driver.switch_to.window(handle_baidu)

截图:driver.get_screenshot_as_file(r"e:\test.png")

alert 框

无法直接定位,需要:

1)switch_to.alert 切换到 alert 对象

2)调用对应方法或属性: accept() / dismiss() # 取消 / text 

滚动条 

滚动条无法直接定位,需要借助 js 脚本实现。

   1)指定上下滚动高度

  js = 'var browser=document.documentElement.scrollTop=100'
driver.execute_script(js)

2) 滚动条上下左右滚动
2.1)scrollTo(x, y) 滚动坐标,相对原点的滚动位置
driver.execute_script("window.scrollTo(0, 100)")

2.2) 相对当前坐标点的滚动
driver.execute_script("window.scrollBy(0, 100)")
3)滚动到指定元素位置(最常用)
target = driver.find_element_by_xpath("//tbody[@id='tbody']/tr[1]/td[8]/span[2]")
driver.execute_script("arguments[0].scrollIntoView();", target) 

其中, arguments[0]:传入的定位元素的对象
default:arguments[0].scrollIntoView(true):滚动完成后,元素作为第一行显示
arguments[0].scrollIntoView(faluse):滚动完成后,元素作为最后一个元素,相对于true,页面位置偏下

3.6 WebDriver API 及对象识别技术(一)

3.6.1. 鼠标键盘事件

1)鼠标事件:from selenium.webdriver.common.action_chains import ActionChains
      相关事件: context_click(),double_clcik(),drag_and_drop(),move_to_element(),click_and_hold()
2)键盘事件:from selenium.webdriver.common.keys import Keys
  相关事件:Keys.BACKSPACE;Keys.SPACE;Keys.CONTROL, 'a';Keys.CONTROL, 'c';Keys.CONTROL, 'v';

3.6.2. 多个 frame 间切换

 1)切换 frame 及 切换回主文档

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://mail.163.com/")
driver.implicitly_wait(30)

# swith to iframe, b/c input text of login is in another frame, need to swtich to it firstly, or it can't be located in default frame.
# driver.switch_to.frame(0)    # workable
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(@id, 'x-URS-iframe')]"))
driver.find_element_by_name("email").send_keys("456")
driver.find_element_by_name("password").send_keys("456")

#back to main page
driver.switch_to.default_content()

# fail to locate
driver.find_element_by_name("password").send_keys("789")

2)嵌套 frame 的操作

 ** iframe1 -> iframe2:需要进行2步

3.6.3 下拉列表框

# ----- 以宽客猫后台的用户管理界面的下拉框为例 ------
#
1. 直接定位
driver.find_element_by_xpath("//div[@class='user_sele']/ul[1]/select[1]/option[2]").click() sleep(3) # 2. 二次定位 get_select = driver.find_element_by_xpath("//div[@class='user_sele']/ul[1]/select[1]") get_select.find_element_by_css_selector("option[value='2']").click() sleep(3) # 3. Select 模块(需要导入下面的模块) from selenium.webdriver.support.select import Select select_object = Select(driver.find_element_by_xpath("//div[@class='user_sele']/ul[1]/select[1]")) # 3.1) 通过索引定位 select_object.select_by_index(4) sleep(3) # 3.2)通过 value 值定位 select_object.select_by_value("-1") sleep(3) # 3.3)通过文本值定位 select_object.select_by_visible_text("已禁用")

3.7 WebDriver API 及对象识别技术(二)

3.7.1 三种等待方式

等待方式 说明 实现 作用域
强制等待 强制等待xx秒

from time import sleep

sleep(2)

当前语句

隐式等待

(常用)

等待整个页面加载完毕,才继续下一步

如提前加载完毕则不等待,直接执行下一步

一般 5~30 s

页面响应时间+网络传输+机器性能,总体不超过 30s

* 页面的响应:2s 最佳,5s 良好,8s 一般

driver.implicitly_wait(30)

整个脚本的生命周期,

故只设置一次

显式等待

(常用)

针对单个元素设置一定的频率,刷新当前页面,检测是否存在该元素

常与 try...except 一起使用

from selenium.webdriver.support.wait import WebDriverWait  or

from selenium.webdriver.support.ui import WebDriverWait

当前语句
element_search_input = WebDriverWait(driver, 5, 1).until(lambda x:x.find_element_by_id("kw"))
element_search_input.send_keys("Hello World")

# WebDriverWait 对象只存在两个方法: until 和 until_not;
# until 和 until_not 需要传入一个参数 method
# method 传入的对象只能是两种:1)匿名函数 lambda;2)预置条件对象 expected_condition (from selenium.webdriver.support import expected_condition as EC);
'''
用例测试 until 方法的入参一: 匿名函数 lambda
lambda x:x.find_element_by_id("kw") 实际上就是在执行:driver.find_element_by_id("kw")    
通过点击 WebDriverWait的 until 方法,可以看到 value = method(self._driver)
是通过传入驱动到 method 方法的
'''
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")

element_search_input = WebDriverWait(driver, 5, 1).until(lambda x:x.find_element_by_id("kw"))
element_search_input.send_keys("Hello World")
'''
用例测试:用来了解python 类的内置函数 __call__ 方法,通过直接引用类的对象,通过函数的形式,就可以直接调用 call 方法,不需要进行调用具体的方法(相对简单方便);
如果没有声明该方法,对象不可直接使用函数式调用 class title_is(object): def __init__(self, title): self.title = title def __call__(self, driver): return self.title == driver.title 简单用例: class A: def __init__(self): print("initialize") def __call__(self): print("common method") # 创建一个类A 的对象 a = A() # 直接通过 a() 就可以调用类A 的 call 方法,结果是:initialize (下一行) commn method a() '''
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() driver.get("http://www.baidu.com") try: # EC.title_is("百度一下,你就知道") 创建一个 title_is 的对象,后面是 __init__ 方法所需的参数 # 再通过 (driver) 传入 __call__ 方法所需的 driver, # 上面2步结合起来,就是执行完整的 调用了 title_is的 call 方法 print(EC.title_is("百度一下,你就知道")(driver)) except: print("Can not located")
from selenium.webdriver.support.wait import WebDriverWait
# from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")

'''
1)通过查看 EC.presence_of_element_located 的源码
    def __call__(self, driver):
        return _find_element(driver, self.locator)
2)再查看 _find_element
    def _find_element(driver, by):
        try:
            return driver.find_element(*by)
    # 由上面一句代码可知,传入的参数 by,在下面执行的时候被拆分成类似于 (By.ID, 'kw'),因为 find_element 的参数是两个参数
      由此可知,_find_element(driver, by)的参数 by 是一个元组
'''
try:
    # element_search_input = EC.presence_of_element_located((By.ID, 'kw'))(driver)
    # -> 上一步最终转换为
    element_search_input = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, 'kw1')))
    element_search_input.send_keys("awesome")
except:
    print("element can't be located")
# EC 常用的几个:
element_search_input = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, 'kw')))               # 传 locator
element_search_input = WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.ID, 'kw')))             # 传 locator 
element_search_input = WebDriverWait(driver, 5).until(EC.visibility_of(driver.find_element(by=By.ID, value='kw'))) # 传 element 
element_search_input.send_keys(
"awesome")

3.7.2 文件上传与下载

1. 文件上传

1)针对上传文件控件,其 type 属性为 file 的,可以定位到该元素,然后直接通过 send_keys(filePath) 的方式,上传文件

def upload_file(self, filePath):
    # 上传文件控件,"type=file"的,上传文件定位到元素后,直接通过 send_keys 即可
    self.driver.find_element_by_id('file_v').send_keys(filePath)

2)非普通:windows 下 需要借助第三方工具 AutoIT 来实现

   官网: https://www.autoitscript.com/site,下载 AutoIT

    组件:SciTE Scipt Editor:编辑器;   AutoIt Window Info:windows 弹框等窗口元素定位;    Compile Script to .exe:将 1)编辑器保存的 .au3 文件转成 .exe

# step1:AutoIT 脚本,然后保存成 .au3 文件
; 聚焦一个 Windows 窗口,传入的参数中 ControlID 对应 ClassNameNN
ControlFocus("打开", "", "Edit1")
; 设置窗口的等待时间
WinWait("打开","", 5)
; 将文件路径写入指定的文本框
ControlSetText("打开", "", "Edit1", $CmdLine[1])
; 点击打开
ControlClick("打开","打开(&O)", "Button1")

注: AutoIT 脚本中以 “;” 符合为注释符
不同的浏览器的定位的元素不同【特别注意】
# step2:使用 Compile Script to .exe,将文件转成 upfile.exe # step3:在 python 中调用 get_path = os.path.dirname(os.path.abspath(__file__)) + "img\python.png" driver.find_element_by_name('file').click() # 单击上传文件按钮 os.system("upfile.exe %s" %get_path) # 上传本地文件

2. 文件下载

# 通过 firefox 的 about:config 查看浏览器相关配置
fp = webdriver.FirefoxProfile()
#指定文件下载路径
# set to customized folder, 0: default directory
fp.set_preference("browser.download.folderList", 2)
fp.set_preference("browser.download.dir", "E:\Temp")

#设置下载文件的类型
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream")

driver = webdriver.Firefox(firefox_profile=fp)
driver.get("https://www.python.org/downloads/")

element_download_href = driver.find_element_by_xpath("//div[@class='download-for-current-os']/div[3]/p/a")
download_href = element_download_href.get_attribute('href')

# download the file from href
driver.get(download_href)
# 配置 chrome,通过 chrome://about 可查看链接
options = webdriver.ChromeOptions()
prefs = {"profile.default_content_settings.popups": 0,
         "download.default_directory": "E:\\Temp",
         "safebrowsing.enabled": True }

options.add_experimental_option('prefs', prefs)

driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.python.org/downloads/")

element_download_href = driver.find_element_by_xpath("//div[@class='download-for-current-os']/div[3]/p/a")
download_href = element_download_href.get_attribute('href')

# download the file from href
driver.get(download_href)

3.7.3 验证码

1. 基本功能:当前访问页面的数据安全性;减少用户的并发数

2. 类型:1)纯数字、纯字母;2)汉字组合;3)数学运算题;4)滑动;5)图片;6)短信;7)语音;8)邮箱

3. 验证码的实现:开发实现时有对应的验证码资源库

  • 本地资源:通常定义在某种容器列表中,如列表等;1)-5)
  • 网络资源:相关的数据全部调用第三方接口或网络爬取的相关数据; 1)- 8)

4. 解决验证码:

  • 1)屏蔽;
  • 2)万能验证码;
  • 3)如果是本地资源库,则只保留一张;
  • 4)打码平台完成,如 斐斐、超人、图鉴等;
  • 5)Python-tesseract 模块进行光学字符识别;
---------- Base_Class.py ----------
from selenium import webdriver

class BaseClass():
    def __init__(self, url, browserType):
        if browserType == "Chrome":
            self.get_driver = webdriver.Chrome()
        elif browserType == "Firefox":
            self.get_driver = webdriver.Firefox()
        else:
            print("not supported browser type %s" % browserType)
        self.get_driver.implicitly_wait(10)

        self.get_driver.get(url)

---------- Cloud_Code.py ----------
import json
import requests
import base64
from io import BytesIO
from PIL import Image
from sys import version_info

def base64_api(uname, pwd, img):
    img = img.convert('RGB')
    buffered = BytesIO()
    img.save(buffered, format="JPEG")

    '''
    version_info是sys模块中的一个函数,主要用于返回你当前所使用的Python版本号。
    version_info是一个包含了版本号5个组成部分的元祖,这5个部分分别是主要版本号(major)、次要版本号(minor)、
                        微型版本号(micro)、发布级别(releaselevel)和序列号(serial)。
    '''
    if version_info.major >= 3:
        b64 = str(base64.b64encode(buffered.getvalue()), encoding='utf-8')
    else:
        b64 = str(base64.b64encode(buffered.getvalue()))

    data = {"username": uname,
            "password": pwd,
            "image": b64
            }

    result = json.loads(requests.post("http://api.ttshitu.com/base64", json=data).text)

    if result['success']:
        return result['data']['result']
    else:
        return result['message']

    return ""

if __name__ == '__main__':
    img_path = "code.png"
    img = Image.open(img_path)
    result = base64_api(uname="wood", pwd="wood1314", img=img)
    print(result)


---------- 3.7.3_example1.py ----------

from PIL import Image
import time
from Base_Class import BaseClass
from Cloud_Code import base64_api

class Dsmall_Login(BaseClass):
    def __init__(self, url, browserType):
        super().__init__(url, browserType)

    def get_code_image(self):
        # save whole web page as a picture
        self.get_driver.maximize_window()
        self.get_driver.get_screenshot_as_file("index.png")

        # get the verify code position
        time.sleep(5)
        get_code_element = self.get_driver.find_element_by_xpath("//img[@ms-click='@reloadcode']")
        get_left = get_code_element.location["x"]
        get_upper = get_code_element.location["y"]
        get_right = get_code_element.size["width"] + get_left
        get_lower = get_code_element.size["height"] + get_upper

        # create image object
        get_image = Image.open("index.png")

        get_new_image = get_image.crop((get_left, get_upper, get_right, get_lower))
        get_new_image.save("code.png")

    def get_code(self, uname, pwd, img):
        get_code = base64_api(uname, pwd, img)
        print(get_code)

if __name__ == '__main__':
    ds = Dsmall_Login("https://quantpt.gecenet.com/manage/index.html#/login/login", "Chrome")
    ds.get_code_image()
    ds.get_code(uname="wood", pwd="wood1314", img=Image.open("code.png"))

 

posted on 2022-02-14 09:24  bruce_he  阅读(92)  评论(0编辑  收藏  举报