Validus A dead simple Python data validation library.…
helium详细教程, 轻量级Selenium webdriver, Python 自动化, helium安装升级, Helium实现web的自动化, 氦气, Helium文档
Helium 是一款 Web 端自动化开源框架,全称是:Selenium-Python-Helium,从名字上就可以看出,Helium 似乎和 Selenium 息息相关
确实,Helium 针对 Selenium 进行了封装,它屏蔽了 Selenium 很多实现细节,提供了更加简洁直观的 API,更方便我们进行 Web 端的自动化
官方表示,要实现同样的功能,Helium 相比 Selenium 要少 30% – 50% 的代码
目前,Helium 仅支持 Chrome 和 FireFox
优缺点
Helium 主要包含下面 6 个优点:
- Helium 自带 WebDriver,不需要下载、配置浏览器驱动
- 内嵌页面 iframe 页面元素直接操作,不需要使用 switch_to.frame() 切换 iframe
- 窗体管理更方便,可以直接使用窗口标题或部分标题内容来切换窗体
- 隐式等待,针对某个元素执行点击操作,Selenium 如果元素没有出现,脚本会执行失败;而 Helium 默认最多等待 10s,等待元素出现后立马执行点击操作
- 显式等待,Helium 提供更加优雅的 API 来等待页面元素出现
- API 更简洁直观,代码量少
Helium 主要缺点,体现在:
- 由于封装,屏蔽了很多细节,所以它不合适二次开发
- 目前仅支持 Chrome 和 FireFox 浏览器
- 版本更新慢、遗留 Bug 及文档少
安装依赖和升级webdriver
项目地址:https://github.com/mherrmann/selenium-python-helium
Helium cheatsheet: https://github.com/mherrmann/selenium-python-helium/blob/master/docs/cheatsheet.md
API 文档:https://selenium-python-helium.readthedocs.io/en/latest/api.html
安装:
# helium 核心文件 pip3 install helium
遇到版本不一致,类似以下的报错:
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 89 Current browser version is 96.0.4664.45 with binary path /usr/bin/google-chrome
那么可以用 chromedriver-autodownloader 自动升级
项目地址:https://github.com/umardy/chromedriver-autodownloader
安装:
# chromedriver驱动升级 pip install chromedriver-autodownloader
用法:
from chromedriver_autodownloader import download_chromedriver download_chromedriver() # download and extract chromedriver to current directory # or download_chromedriver(target_dir) # download and extract to spesified target directory
如果您使用 helium 并希望将 chromedriver 提取到它的 webdriver 路径,您可以编写如下代码:
download_chromedriver('helium')
或者使用:webdriver-manager
项目地址:https://pypi.org/project/webdriver-manager/
安装:
pip install webdriver-manager
使用:
# before from selenium import webdriver driver = webdriver.Chrome('/home/user/drivers/chromedriver') # now # Use with Chrome: from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager driver = webdriver.Chrome(ChromeDriverManager().install()) # Use with Chromium: from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from webdriver_manager.utils import ChromeType driver = webdriver.Chrome(ChromeDriverManager(chrome_type=ChromeType.CHROMIUM).install()) # Use with FireFox: from selenium import webdriver from webdriver_manager.firefox import GeckoDriverManager driver = webdriver.Firefox(executable_path=GeckoDriverManager().install()) # Use with IE from selenium import webdriver from webdriver_manager.microsoft import IEDriverManager driver = webdriver.Ie(IEDriverManager().install()) # Use with Edge from selenium import webdriver from webdriver_manager.microsoft import EdgeChromiumDriverManager driver = webdriver.Edge(EdgeChromiumDriverManager().install()) 实例:
Try using ChromeDriverManager
from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.set_headless() browser =webdriver.Chrome(ChromeDriverManager().install(),chrome_options=chrome_options) browser.get('https://google.com') # capture the screen browser.get_screenshot_as_file("capture.png")
查看github项目的源码,每个方法都有介绍及使用说明
https://github.com/mherrmann/selenium-python-helium/blob/master/helium/__init__.py
__all__ = [ | |
# Actions: 方法 | |
‘attach_file‘, ‘click‘, ‘doubleclick’, ‘drag’, ‘drag_file’, ‘find_all‘, | |
‘get_driver‘, ‘go_to‘, ‘highlight‘, ‘hover‘, ‘kill_browser’, ‘press‘, | |
‘refresh’, ‘rightclick’, ‘scroll_down’, ‘scroll_left’, ‘scroll_right’, | |
‘scroll_up’, ‘select’, ‘set_driver’, ‘start_chrome’, ‘start_firefox’, | |
‘switch_to’, ‘wait_until‘, ‘write‘, | |
# Predicates: | |
‘Alert’, ‘Button’, ‘CheckBox’, ‘ComboBox’, ‘Config’, ‘Image’, ‘Link’, | |
‘ListItem’, ‘Point’, ‘S‘, ‘RadioButton’, ‘Text‘, ‘TextField’, ‘Window’, | |
# Keys: | |
‘ADD’, ‘ALT’, ‘ARROW_DOWN’, ‘ARROW_LEFT’, ‘ARROW_RIGHT’, ‘ARROW_UP’, | |
‘BACK_SPACE’, ‘CANCEL’, ‘CLEAR’, ‘COMMAND’, ‘CONTROL’, ‘DECIMAL’, ‘DELETE’, | |
‘DIVIDE’, ‘DOWN’, ‘END’, ‘ENTER’, ‘EQUALS’, ‘ESCAPE’, ‘F1’, ‘F2’, ‘F3’, | |
‘F4’, ‘F5’, ‘F6’, ‘F7’, ‘F8’, ‘F9’, ‘F10’, ‘F11’, ‘F12’, ‘HELP’, ‘HOME’, | |
‘INSERT’, ‘LEFT’, ‘LEFT_ALT’, ‘LEFT_CONTROL’, ‘LEFT_SHIFT’, ‘META’, | |
‘MULTIPLY’, ‘NULL’, ‘NUMPAD0’, ‘NUMPAD1’, ‘NUMPAD2’, ‘NUMPAD3’, ‘NUMPAD4’, | |
‘NUMPAD5’, ‘NUMPAD6’, ‘NUMPAD7’, ‘NUMPAD8’, ‘NUMPAD9’, ‘PAGE_DOWN’, | |
‘PAGE_UP’, ‘PAUSE’, ‘RETURN’, ‘RIGHT’, ‘SEMICOLON’, ‘SEPARATOR’, ‘SHIFT’, | |
‘SPACE’, ‘SUBTRACT’, ‘TAB’, ‘UP’ | |
] |
或者通过一下函数获取
dir()
将为您提供范围变量列表:globals()
会给你一个全局变量字典locals()
会给你一个局部变量字典
例如:
S(".img") dir(S(".img")) dir(S(".img").web_element) S(".img").web_element.src
使用
启动浏览器
def start_firefox(url=None, headless=False, options=None)
- 这三个参数都有默认值,为None,所以都为可选填的
url:要访问的网站网址
headless:是否隐藏浏览器,即执行脚本时,浏览器是否可见
options:浏览器配置,要使用options时需引入配置模块
例子:
from helium import * start_firefox("google.com") start_chorme(headless=True) from selenium.webdriver import ChromeOptions #firefox引入FirefoxOptions options = ChromeOptions() options.add_argument('--start-maximized') options.add_argument('--proxy-server=1.2.3.4:5678') start_chrome("www.ikeepstudying.com",headless=True,options=options)
- 和selenium 搭配,防止反爬系列
def open_url(): # 加启动配置 options = webdriver.ChromeOptions() # 防止反爬 options.add_experimental_option('useAutomationExtension', False) options.add_experimental_option('excludeSwitches', ['enable-automation']) driver = webdriver.Chrome(chrome_options=options) set_driver(driver) ''' <script> if(window.navigator.webdriver == true){ document.write("<span>看到这段就代表你是爬虫</span>") }else{ document.write("<span>真正的信息在这儿呢</span>") } </script> ''' go_to(r"file:///E:/auto_task/helium_test/test.html") time.sleep(5)
访问网址
def go_to(url)
- 这个比较简单,直接用url即可
写入
def write(text, into=None)
- 顾名思义,将内容写入输入框的功能,其中into为非必填,如果没填的话,默认输入到页面找到的第一个输入框,如果要填的话,对应的是element。
options = ChromeOptions() options.add_argument("--start-maximized") start_chrome("https://www.zhihu.com/signin?next=%2F",options=options) click(Text("密码登录")) write("python@123.com",into=S("@username")) write("python",into="密码") write("royfans",TextField("Username")) # 大小写不敏感 write("Zlf111",into="Password") write("test2",into=TextField(to_right_of="username")) click("Remember password") click("Log in") click(TextField("Site"))
按键
def press(key)
- 普通字母数字直接用’key’就可以了,如果是特殊按键,这用对应的按键名即可,组合件的话,用+号连接
press('A') press('a') press(ENTER) press(CONTROL + 'a')
- 特殊按键对应的按键名可以在selenium.webdriver.common.keys.Keys找到。具体如下:
NULL = Keys.NULL CANCEL = Keys.CANCEL HELP = Keys.HELP BACK_SPACE = Keys.BACK_SPACE TAB = Keys.TAB CLEAR = Keys.CLEAR RETURN = Keys.RETURN ENTER = Keys.ENTER SHIFT = Keys.SHIFT LEFT_SHIFT = Keys.LEFT_SHIFT CONTROL = Keys.CONTROL LEFT_CONTROL = Keys.LEFT_CONTROL ALT = Keys.ALT LEFT_ALT = Keys.LEFT_ALT PAUSE = Keys.PAUSE ESCAPE = Keys.ESCAPE SPACE = Keys.SPACE PAGE_UP = Keys.PAGE_UP PAGE_DOWN = Keys.PAGE_DOWN END = Keys.END HOME = Keys.HOME LEFT = Keys.LEFT ARROW_LEFT = Keys.ARROW_LEFT UP = Keys.UP ARROW_UP = Keys.ARROW_UP RIGHT = Keys.RIGHT ARROW_RIGHT = Keys.ARROW_RIGHT DOWN = Keys.DOWN ARROW_DOWN = Keys.ARROW_DOWN INSERT = Keys.INSERT DELETE = Keys.DELETE SEMICOLON = Keys.SEMICOLON EQUALS = Keys.EQUALS NUMPAD0 = Keys.NUMPAD0 NUMPAD1 = Keys.NUMPAD1 NUMPAD2 = Keys.NUMPAD2 NUMPAD3 = Keys.NUMPAD3 NUMPAD4 = Keys.NUMPAD4 NUMPAD5 = Keys.NUMPAD5 NUMPAD6 = Keys.NUMPAD6 NUMPAD7 = Keys.NUMPAD7 NUMPAD8 = Keys.NUMPAD8 NUMPAD9 = Keys.NUMPAD9 MULTIPLY = Keys.MULTIPLY ADD = Keys.ADD SEPARATOR = Keys.SEPARATOR SUBTRACT = Keys.SUBTRACT DECIMAL = Keys.DECIMAL DIVIDE = Keys.DIVIDE F1 = Keys.F1 F2 = Keys.F2 F3 = Keys.F3 F4 = Keys.F4 F5 = Keys.F5 F6 = Keys.F6 F7 = Keys.F7 F8 = Keys.F8 F9 = Keys.F9 F10 = Keys.F10 F11 = Keys.F11 F12 = Keys.F12 META = Keys.META COMMAND = Keys.COMMAND
点击/双击/右击
def click(element) #单击 def doubleclick(element) #双击 def rightclick(element)
示例:
click("Sign in") click(Button("OK")) click(Point(200, 300)) click(ComboBox("File type").top_left + (50, 0))
拖拽
def drag(element, to)
- 将一个元素拖拽到指定位置,这个个人使用时,自己用elment-ui写了个drag功能一直拖拽失败,比较尴尬。
官方示例:
drag(“Drag me!”, to=”Drop here.”)
拖拽文件
def drag_file(file_path, to)
将本地的文件拖入到浏览器指定的位置,挺好用的一个功能。
示例:
click("配置管理") wait_until(Text("文件上传").exists) click("文件上传") drag_file(r"D:\\1.jpg",to="将文件拖到此处,或点击上传")
上传文件
def attach_file(file_path, to=None)
- 将文件上传,这个针对的是input type=“file”
示例:
start_chrome("file:///D:/1.html",options=options) attach_file(r"D:\\2.jpg")
按住/松开左键
def press_mouse_on(element)
def release_mouse_over(element)
鼠标悬浮
def hover(element)
示例:
hover("File size") hover(Button("OK")) hover(Link("Download")) hover(Point(200, 300)) hover(ComboBox("File type").top_left + (50, 0)) hover("任务中心") click("任务查询")
向上/下/左/右滚动屏幕
def scroll_down(num_pixels=100) def scroll_up(num_pixels=100) def scroll_right(num_pixels=100) def scroll_left(num_pixels=100)
不设置参数时默认为100像素,设置参数的话直接写数字就可以
查找元素组
def find_all(predicate)
这个比较简单,就是找元素组,然后根据index来取元素。示例:
find_all(Button("Open")) find_all(Window()) find_all(TextField("Address")) find_all(Text("进入")) click(find_all(Text("进入"))[0]) # 有相同的placehold,用find_all 查找全部元素 p = find_all(TextField("Please select")) click(p[0])
下拉框选择
def select(combo_box, value)
从下拉选项中选择一项,示例:
select("Language", "English") select(ComboBox("Language"), "English")
刷新页面
def refresh()
直接使用即可
等待元素
def wait_until(condition_fn, timeout_secs=10, interval_secs=0.5)
等待某个条件为真才继续往下执行。默认的超时时间为10s,每0.5查询一次,这俩参数选填。可以设置超时时间和轮询间隔。
注意:condition_fn等待条件直接采用函数的话,不能带()或者直接用lambda后带完整函数。
示例:
wait_until(Text("Finished!").exists) wait_until(lambda:Text("Finished!").exists())
配置文件—隐式等待时间
等待时间:
首先要知道隐式等待时间的含义,是指执行脚本时,如果某个元素元素刚开始没找到,会默认等待一段时间,超时后才会抛出错误。显示等待这是直接在代码里写等待多久,比如time.sleep(xxx)
- 配置管理:
helium中有个Config类
class Config:
里面只介绍了隐式等待时间的设置。默认值为10s,如果要自己设置,直接调用config即可:
如果要关闭隐式等待时间,则只需要将时间设置为0即可。
onfig.implicit_wait_secs(10)
UI基础类: class GUIElement
最基础的UI类,用的上的只有一个函数
def exists(self)
用于判断某个元素是否存在,返回true或false
元素基础类:class HTMLElement(GUIElement)
界面元素类,继承GUIElement,有六个属性:
width #元素宽度 height #高度 x #元素在界面上的X轴坐标 y #y轴坐标 top_left #元素坐上角的坐标 web_element #转换为web_element,之后可以调用selenium元素的属性和方法
示例:
start_chrome("file:///D:/1.html",options=options) element = Button("submit") width = element.width height = element.height x = element.x y = element.y top_left = element.top_left web_el_text = element.web_element.text web_el_tag = element.web_element.tag_name print("元素大小:{width}*{height},元素位置:{x},{y},元素左上角位置:{top_left},元素文本:{web_el_text},元素类别:{web_el_tag}".format( width = width, height = height, x = x, y = y, top_left = top_left, web_el_text = web_el_text, web_el_tag = web_el_tag ))
结果如下图,可以发现x,y实际就是top_left的具体坐标值,而top_left的返回类型为Point,所以要对top_left做位置变换需要用Point数据:
此外,要关注一下__init__方法,也就是类的初始化:
def __init__(self, below=None, to_right_of=None, above=None, to_left_of=None)
这个是说在可以通过相对位置来实现元素及控件的查找
below #在某个元素下方 above #在某个元素上方 to_right_of #在某个元素右侧 to_left_of #在某个元素左侧
所有基于HTMLElement类的元素或者控件都可以通过这4个相对位置来实现元素查找。
例子:
Button("登录",below="password") #位于password下的登录按钮
元素定位类:class S(HTMLElement)
它是基于HTMLElement的,不同定位方式是通过符号来区分的 @ #对应name . #对应class # #对应id // #对应xpath或者css selector 示例: write("testname",into=S("#username")) find_all(S("table > tr > td", below="Email")) write("abc",into=S("[type=text]"))
Helium比较特殊,元素定位类是继承HTMLElement的,而其他控件,比如Button、Link等也全都继承HTMLElement,所以这几个是并列关系,也就是说
控件无法通过定位类S来实现控件查找,只能基于控件文本和HTMLElement中的四个相对位置来实现控件查找
比如Button(S(“#submit”)是错误的,可以通过Button(“登录”,below=“username”)来实现查找。
控件类
所有控件类都继承HTMLElement类,所以可以试用HTMLElement和GUIElement类的方法与属性。
- 文本控件
用于获取界面文本的控件,拥有value属性来获取控件对应的文本
class Text(HTMLElement) @property def value(self)
示例
Text("Do you want to proceed?").exists() Text(below="Email", to_right_of="John").value
- 链接控件
用于识别界面上的链接,拥有href属性可以获取链接对应的url
class Link(HTMLElement) @property def href(self)
示例:
click(Link("Block User", to_right_of="John Doe")) Link("ikeepstudying").href
3.序列控件
可以获取界面上的序列
元素
class ListItem(HTMLElement)
示例:
click(ListItem("List item 1", below="My first list:")) assert ListItem("List item 1").exists() ListItem("Account Resource").exists()
4.按钮控件
可以获取按钮控件,具有is_enabled方法,用于判断按钮是否有被disabled
class Button(HTMLElement) def is_enabled(self)
示例:
click(Button("OK")) click(Button("Log In", below=TextField("Password"))) Button("OK").is_enabled()
5.图片控件
识别图片元素,从__init__类的初始化函数可以看到相对其他控件的text=None(,图片控件的是alt=None,也就是说要通过alt而非text来识别图片,至于什么是alt,这个是html基础,不懂得可以百度。
class Image(HTMLElement) def __init__(self, alt=None, below=None, to_right_of=None, above=None,to_left_of=None)
示例:
click(Image(alt="logo")) lick(Image("logo", to_left_of=ListItem("Download"))) Image("logo").exists()
6.文本框控件
可识别可以用于输入的文本框控件,它是通过label加相对位置来定位的,这个label既可以采用本文框左侧的文字,也可以采用文本框内部的提示语,也就是html的placeholder里的文本。
value属性,可以获取文本框里的文本;
is_enabled()方法,识别文本框是否被disabled,界面上显示的就是置灰
is_editable()方法,识别文本框是否可编辑,也就是是否有配置readonly,这时控件是不置灰的,但是不可编辑。
class TextField(HTMLElement) def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None) @property def value(self) def is_enabled(self) def is_editable(self)
示例:
html代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>hello worlds</h1> username:<input placeholder="请输入用户名"></input> </body> </html>
自动化代码如下:
from helium import * from selenium.webdriver import ChromeOptions import time Config.implicit_wait_secs=30 options = ChromeOptions() options.add_argument("--start-maximized") start_chrome("file:///D:/1.html",options=options) write("test1",into=TextField("username")) time.sleep(3) write("test2",into=TextField(to_right_of="username")) time.sleep(3) write("test3",into=TextField("请输入用户名")) element = Button("submit")
上面3种方式都是可以找到input控件的,都可以成功输入。
7.下拉列表框控件
这个相对select来说范围更广,一般来说既可以指的select,也可以指dropdown控件,特别是一些可以通过输入文本来匹配选项的控件,都可以用这个控件。
查看__init__可以发现跟文本框是一样的,都是用label来识别控件,查找方法类似上面文本框控件。它本身经常和select一起使用,用于选中某一选项。
value属性:可以获取已选中项的值
options属性:可以获取所有可以选择的选项内容
is_editable()方法:判断是否可输入文本来匹配选项\
class ComboBox(HTMLElement) def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None) def is_editable(self) @property def value(self) @property def options(self)
示例:
ComboBox("Language").value select(ComboBox(to_right_of="John Doe", below="Status"), "Active")
8.复选框控件 顾名思义,识别复选框用的。 is_enabled()方法:判断是否被disabled is_checked()方法:判断是否被选中\
class CheckBox(HTMLElement) def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None) def is_enabled(self) def is_checked(self)
示例:
CheckBox("已阅读xx").is_checked() click(CheckBox("记住登录状态", below=Button("登录")))
9.单选框控件 单选框专用 is_selected()方法:判断是否被选中\
class RadioButton(HTMLElement) def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None) def is_selected(self)
示例:
RadioButton("Windows").is_selected() click(RadioButton("我同意", below="用户协议"))
弹窗Alert
这个是专门针对alert弹窗的,是继承GUIElement的,所以没法用四个相对位置来查找,不过一般alert都会位于界面最顶层,所以一般也比较容易识别出来。
通过__init__可以知道它可以通过文本来查找弹窗,特别是对于多个弹窗的话,用文本来区分即可,如果只有一个弹窗,可以search_text放空一般也可以找到
text属性:获取弹窗上的文本内容
accept()方法:相当于点击弹窗上的OK / 确认键
dismiss()方法:相当于点击弹窗上的Cancel / 取消按键
class Alert(GUIElement) def __init__(self, search_text=None) @property def text(self) def accept(self) def dismiss(self)
示例:
write("12",into=Alert("请输入个数")) Alert().accept() Alert().dismiss()
坐标点Point
通过x,y来表示元素在界面上的具体坐标,如果要偏移位置,可以用+或者-来实现。
class Point(namedtuple('Point', ['x', 'y'])) def __init__(self, x=0, y=0) @property #X轴坐标 def x(self) @property #Y轴坐标 def y(self) def __eq__(self, other) # 对比两个Point看是否相等 def __ne__(self, other) # 对比两个Point看是否相等 def __hash__(self) #hash,返回x + 7*y,暂时未知作用 def __add__(self,delta) #相加,delta对应某个point def __radd__(self,delta) #功能和add一致,为啥叫radd未知 def __sub__(self,delta) #相减 def __rsub__(self,delta) #相减,同sub一样
示例:
print(Point(100,100)+ (Point(1,2))) print(Point(100,100).__add__(Point(1,2)))
窗口
可以用于或者窗口title也可以配合switch_to来进行窗口的切换
class Window(GUIElement) def __init__(self, title=None) @property #窗口的title def title(self) @property #返回selenium driver的标识,本身不具备操控界面的能力 def handle(self)
示例:
print(Window().title) switch_to(Window("标题")) switch_to(find_all(Window())[0])
窗口切换switch_to
通过窗口的title来切换窗口
def switch_to(window)
示例:
switch_to("Google") switch_to(Window("Google")) switch_to(find_all(Window())[0])
关掉浏览器
就是单纯的关掉浏览器,如果不调用该方法,执行完后浏览器会保持打开状态
def kill_browser()
高亮highlight
为了凸显某一元素便于查看或者在操作某一元素前,可以采用highlight来标识出来,然后再采用截图的话,可以明确知道该步骤在页面上对哪个元素进行操作。
def highlight(element)
示例:
highlight(TextField(“username”))
效果图:
与selenium配合(set_driver/get_driver)
set_driver(driver)用于将selenium的driver切换到helium,这样就可以直接使用helium的api了
get_driver()用于获取helium的driver,然后driver后可以使用selenium语句
从selenium到helium:
from selenium import webdriver from helium import * driver = webdriver.Chrome() set_driver(driver) go_to("http://127.0.0.1:8080/#/login")
从helium到selenium:
from helium import * start_chrome() driver = get_driver() #或者直接driver = start_chrome() element = driver.find_element_by_id('auto_test') print(element.text) driver.save_screenshot("D:/1.png")
实战应用
1.时间选择:
click(TextField("added at")) click("17") click("17") click('ok')
2. 搜索下拉选择
ListItem("Account Resource").exists()
本文:helium详细教程, 轻量级Selenium webdriver, Python 自动化, helium安装升级, Helium实现web的自动化, 氦气, Helium文档