内容引用原文地址: https://www.jianshu.com/nb/25338984
本文使用python3.6.5.
Selenium是一个用于Web应用程序测试的工具。
Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Firefox,Safari,Chrome,Opera等。
使用python爬虫调用selenium来模拟正常用户访问浏览器.
安装selenium:
win: pip install seleniumliunx: pip3 install selenium
安装ChromeDriver, 该工具供selenium使用Chrome.
ChromeDriver: http://npm.taobao.org/mirrors/chromedriver/
下载前先查看本地环境的Chrome版本, 然后去上面的link中下载对应的ChromeDriver版本.
ChromeDriver版本 | 支持的Chrome版本 |
---|---|
v2.37 | v64-66 |
v2.36 | v63-65 |
v2.35 | v62-64 |
v2.34 | v61-63 |
v2.33 | v60-62 |
v2.32 | v59-61 |
v2.31 | v58-60 |
v2.30 | v58-60 |
v2.29 | v56-58 |
v2.28 | v55-57 |
v2.27 | v54-56 |
v2.26 | v53-55 |
v2.25 | v53-55 |
v2.24 | v52-54 |
v2.23 | v51-53 |
这里只是对应版本中的一部分, 各位的Chrome版本可能超出了这里的版本范围.
但是通过版本对比, 可以发现每个driver版本对应的chrome版本范围为3.
通过规律, 各位就能知道自己该下那个版本的driver了.
/usr/loacl/bin
目录中.如前面说的, 我们能使用python导入selenium来控制浏览器访问网站.
也就是说能使用py打开浏览器自动化访问.
#!/usr/bin/env python3from selenium import werdriverimport timedriver = webdriver.Chrome() # 创建Chrome对象.# 操作这个对象.driver.get('https://www.baidu.com') # get方式访问百度.time.sleep(2)driver.quit() # 使用完, 记得关闭浏览器, 不然chromedriver.exe进程为一直在内存中.
#!/usr/bin/env python3''' 根据chrome浏览器2017年发布的新特性, 需要unix版本的chrome版本高于57, windows版本的chrome版本高于58, 才能使用无界面运行.'''from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsimport timechrome_opt = Options() # 创建参数设置对象.chrome_opt.add_argument('--headless') # 无界面化.chrome_opt.add_argument('--disable-gpu') # 配合上面的无界面化.chrome_opt.add_argument('--window-size=1366,768') # 设置窗口大小, 窗口大小会有影响.# 创建Chrome对象并传入设置信息.driver = webdriver.Chrome(chrome_options=chrome_opt) # 操作这个对象.driver.get('https://www.baidu.com') # get方式访问百度.time.sleep(2)print(driver.page_source) # 打印加载的page code, 证明(prove) program is right.driver.quit() # 使用完, 记得关闭浏览器, 不然chromedriver.exe进程为一直在内存中.
Easy EG
#!/usr/bin/env python3from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionschrome_opt = Options() # 创建参数设置对象.chrome_opt.add_argument('--windows-size=1366,768') # 设置浏览器窗口大小.# 创建chrome对象并传入设置信息.driver = webdriver.Chrome(chrome_options=chrome_opt)driver.quit()
常用的启动项
启动参数 | 作用 |
---|---|
–user-agent=”“ | 设置请求头的User-Agent |
–window-size=长,宽 | 设置浏览器分辨率 |
–headless | 无界面运行 |
–start-maximized | 最大化运行 |
–incognito | 隐身模式 |
–disable-javascript | 禁用javascript |
–disable-infobars | 禁用浏览器正在被自动化程序控制的提示 |
详细的参数解释: https://peter.sh/experiments/chromium-command-line-switches/
禁用图片加载
Chrome的禁用图片加载参数设置比较复杂,如下所示:
prefs = { 'profile.default_content_setting_values' : { 'images' : 2 }}options.add_experimental_option('prefs',prefs)
使用浏览器时常常会有弹窗弹出,以下选项可以禁止弹窗:
prefs = { 'profile.default_content_setting_values' : { 'notifications' : 2 } } options.add_experimental_option('prefs',prefs)
chromedriver.exe一般可以放在环境文件中,但是有时候为了方便部署项目,或者为了容易打包,我们可以将chromedriver.exe放到我们的项目目录中,然后在初始化Chrome Webdriver对象时,传入chromedriver.exe的路径。
from selenium import webdriverdriver = webdriver.Chrome(executable_path='chromedriver.exe')driver.quit()
get(url): 在当前浏览器会话中访问传入的url地址, driver.get('https://www.baidu.com')
.
close(): 关闭浏览器当前窗口。
quit(): 退出webdriver并关闭所有窗口。
refresh(): 刷新当前页面。
title: 获取当前页的标题。
page_source: 获取当前页渲染后的源代码。
current_url: 获取当前页面的url。
window_handles: 获取当前会话中所有窗口的句柄。
方法 | 作用 |
---|---|
find_element_by_xpath() | 通过Xpath 查找 |
find_element_by_class_name() | 通过class属性 查找 |
find_element_by_css_selector() | 通过css选择器 查找 |
find_element_by_id() | 通过id 查找 |
find_element_by_link_text() | 通过链接文本 查找 |
find_element_by_name() | 通过name属性 进行查找 |
find_element_by_partial_link_text() | 通过链接文本的部分匹配 查找 |
find_element_by_tag_name() | 通过标签名 查找 |
查找后返回的是一个Webelement
对象。
查找多个元素: 将其中的element加上一个s,则是对应的多个查找方法。
上面的方法都是将第一个找到的元素进行返回,而将所有匹配的元素进行返回使用的是find_elements_by_*
方法。
add_cookie(cookie_dict) : 给当前会话添加一个cookie。
cookie_dict: 一个字典对象,必须要有”name”和”value”两个键,可选的键有:“path”, “domain”, “secure”, “expiry” 。
用法:
driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’})driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’})driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’, ‘secure’:True})
get_cookie(name): 按name获取单个Cookie,没有则返回None。
get_cookies(): 获取所有Cookie,返回的是一组字典。
delete_all_cookies(): 删除所有Cookies。
delete_cookie(name): 按name删除指定cookie。
driver.get_screenshot_as_file(‘/Screenshots/foo.png’)
get_window_position(windowHandle=’current’): 获取当前窗口的x,y坐标。
get_window_rect(): 获取当前窗口的x,y坐标和当前窗口的高度和宽度。
get_window_size(windowHandle=’current’): 获取当前窗口的高度和宽度。
switch_to_frame(frame_reference): 将焦点切换到指定的子框架中
switch_to_window(window_name): 切换窗口
execute_async_script(script, *args) : 在当前的window/frame中异步
执行JS代码。
script = “var callback = arguments[arguments.length - 1]; ”script2 = “window.setTimeout(function(){ callback(‘timeout’) }, 3000);” driver.execute_async_script(script + script2)
execute_script(script, *args): 在当前的window/frame中同步
执行JS代码。
前面有讲到使用find
等方法来查找单个或多个元素对象, 其结果返回一个Webelement
对象.
现在我们操作这个对象.
们经常需要模拟键盘的输入,当输入普通的值时,在send_keys()
方法中传入要输入的字符串就好了。
但是我们有时候会用到一些特殊的按键,这时候就需要用到我们的Keys类。
EG:
# 要使用按键值, 需要导入下面keys.from selenium.webdriver.common.keys import Keyselem.send_keys(Keys.CONTROL, 'c')
对应的属性 |
---|
ADD = u’\ue025’ |
ALT = u’\ue00a’ |
ARROW_DOWN = u’\ue015’ |
ARROW_LEFT = u’\ue012’ |
ARROW_RIGHT = u’\ue014’ |
ARROW_UP = u’\ue013’ |
BACKSPACE = u’\ue003’ |
BACK_SPACE = u’\ue003’ |
CANCEL = u’\ue001’ |
CLEAR = u’\ue005’ |
COMMAND = u’\ue03d’ |
CONTROL = u’\ue009’ |
DECIMAL = u’\ue028’ |
DELETE = u’\ue017’ |
DIVIDE = u’\ue029’ |
DOWN = u’\ue015’ |
END = u’\ue010’ |
ENTER = u’\ue007’ |
EQUALS = u’\ue019’ |
ESCAPE = u’\ue00c’ |
F1 = u’\ue031’ |
F2 = u’\ue032’ |
F3 = u’\ue033’ |
F4 = u’\ue034’ |
F5 = u’\ue035’ |
F6 = u’\ue036’ |
F7 = u’\ue037’ |
F8 = u’\ue038’ |
F9 = u’\ue039’ |
F10 = u’\ue03a’ |
F11 = u’\ue03b’ |
F12 = u’\ue03c’ |
HELP = u’\ue002’ |
HOME = u’\ue011’ |
INSERT = u’\ue016’ |
LEFT = u’\ue012’ |
LEFT_ALT = u’\ue00a’ |
LEFT_CONTROL = u’\ue009’ |
LEFT_SHIFT = u’\ue008’ |
META = u’\ue03d’ |
MULTIPLY = u’\ue024’ |
NULL = u’\ue000’ |
NUMPAD0 = u’\ue01a’ |
NUMPAD1 = u’\ue01b’ |
NUMPAD2 = u’\ue01c’ |
NUMPAD3 = u’\ue01d’ |
NUMPAD4 = u’\ue01e’ |
NUMPAD5 = u’\ue01f’ |
NUMPAD6 = u’\ue020’ |
NUMPAD7 = u’\ue021’ |
NUMPAD8 = u’\ue022’ |
NUMPAD9 = u’\ue023’ |
PAGE_DOWN = u’\ue00f’ |
PAGE_UP = u’\ue00e’ |
PAUSE = u’\ue00b’ |
RETURN = u’\ue006’ |
RIGHT = u’\ue014’ |
SEMICOLON = u’\ue018’ |
SEPARATOR = u’\ue026’ |
SHIFT = u’\ue008’ |
SPACE = u’\ue00d’ |
SUBTRACT = u’\ue027’ |
TAB = u’\ue004’ |
UP = u’\ue013’ |
一般来说我们与页面的交互可以使用Webelement
的方法来进行点击等操作。但是,有时候我们需要一些更复杂的动作,类似于拖动,双击,长按等等。
这时候就需要用到我们的Action Chains
(动作链)了。
from selenium.webdriver import ActionChainsfrom selenium import webdriverdriver = webdriver.Chrome() # 创建webdriver对象.element = driver.find_element_by_name("source") # 查找单一元素对象.target = driver.find_element_by_name("target") # 同上.actions = ActionChains(driver) # 创建动作链对象.# 在element元素上点击抓起,移动到target元素上松开放下。 类似鼠标.actions.drag_and_drop(element, target)actions.perform() # 执行动作.
在导入动作链模块以后,需要声明一个动作链对象,在声明时将webdriver对象当作参数传入,并将对象赋值给一个actions变量。
然后我们通过这个actions变量,调用其内部附带的各种动作方法进行操作。
注:在调用各种动作方法后,这些方法并不会马上执行,而是会按你代码的顺序存储在ActionChains对象的队列中。当你调用perform()时,这些动作才会依次开始执行。
在selenium操作浏览器的过程中,每一次请求url
,selenium
都会等待页面加载完毕以后,才会将操作权限再次交给我们的程序。
但是,由于ajax
和各种JS代码
的异步加载问题,所以我们在使用selenium
的时候常常会遇到操作的元素还没有加载出来,就会引发报错。为了解决这个问题,Selenium
提供了几种等待的方法,让我们可以等待元素加载完毕后,再进行操作。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Chrome()driver.get("http://somedomain/url_that_delays_loading")try: # 创建wait对象. element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) )finally: driver.quit()
在这个例子中,我们在查找一个元素的时候,不再使用find_element_by_*
这样的方式来查找元素,而是使用了WebDriverWait
。
try代码块中的代码的意思是:在抛出元素不存在异常之前,最多等待10秒。在这10秒中,WebDriverWait
会默认每500ms运行一次until之中的内容,而until中的EC.presence_of_element_located
则是检查元素是否已经被加载,检查的元素则通过By.ID
这样的方式来进行查找。
就是说,在10秒内,默认每0.5秒检查一次元素是否存在,存在则将元素赋值给element这个变量。如果超过10秒这个元素仍不存在,则抛出超时异常。
隐式等待指的是,在webdriver
中进行find_element
这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。
这个值默认是0,可以通过以下方式进行设置:
from selenium import webdriverdriver = webdriver.Chrome()driver.implicitly_wait(10) # 单位是秒driver.get("http://somedomain/url_that_delays_loading")myDynamicElement = driver.find_element_by_id("myDynamicElement")
Expected Conditions这个类提供了很多种常见的检查条件可以供我们使用。
WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'some')))
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'some')))
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='some')))
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'some')))
WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'some')))
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"some"),u'设置'))
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'some'),u'百度一下'))
WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(some))
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'some')))
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"some"))).click()
WebDriverWait(driver,10).until(EC.staleness_of(driver.find_element(By.ID,'some')))
WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"some")))
WebDriverWait(driver,10).until(EC.element_selection_state_to_be(driver.find_element(By.XPATH,"some"),True))
WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be((By.XPATH,"some"),True))
WebDriverWait(driver,10).until(EC.alert_is_present())
''' 示意代码, 不完整.'''from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome()wait = WebDriverWait(driver, 10)# 等待直到元素可以被点击element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
pass
联系客服