这是一个用来更新公园信息的数据管理系统,而截图这个页面主要是用来更新site信息的,幸运的是这个页面的每个元素都可以用ID来定位。其中包含三种形式的信息:文本框,下拉列表和复选按钮。我的实现思路是把ID对应定位信息放在excel表格里,通过抓取excel表里提供的定位信息和所对应的需要更新的值进行数据更新。
这里分别对文本框信息输入,下拉列表选择和复选按钮勾选做了封装处理,再把相应的方法统一放到update方法来实现。这样就不需要再对每个字段进行单独处理了。
封装代码:
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException, TimeoutException
import traceback
import time
class BasePage:
def __init__(self, driver):
self.driver = driver
# 对查找单个页面元素进行封装。
def find_element(self, by, locator):
by = by.lower()
element = None
if by in ['id', 'name', 'xpath', 'class', 'tag', 'link', 'plink']:
try:
if by == 'id':
element = self.driver.find_element_by_id(locator)
elif by == 'name':
element = self.driver.find_element_by_name(locator)
elif by == 'xpath':
element = self.driver.find_element_by_xpath(locator)
elif by == 'class':
element = self.driver.find_element_by_class_name(locator)
elif by == 'tag':
element = self.driver.find_element_by_tag_name(locator)
elif by == 'link':
element = self.driver.find_element_by_link_text(locator)
elif by == 'plink':
element = self.driver.find_element_by_partial_link_text(locator)
else:
print('Not find the element "{}"!'.format(locator))
return element
except NoSuchElementException as e:
print(traceback.print_exc())
else:
print('Provided a wrong locator "{}"!'.format(locator))
# 对查找多个页面元素进行封装。
def find_elements(self, by, locator):
by = by.lower()
elements = None
if by in ['id', 'name', 'xpath', 'class', 'tag', 'link', 'plink']:
try:
if by == 'id':
elements = self.driver.find_elements_by_id(locator)
elif by == 'name':
elements = self.driver.find_elements_by_name(locator)
elif by == 'xpath':
elements = self.driver.find_elements_by_xpath(locator)
elif by == 'class':
elements = self.driver.find_elements_by_class_name(locator)
elif by == 'tag':
elements = self.driver.find_elements_by_tag_name(locator)
elif by == 'link':
elements = self.driver.find_elements_by_link_text(locator)
elif by == 'plink':
elements = self.driver.find_elements_by_partial_link_text(locator)
else:
print('Not find the element "{}"!'.format(locator))
return elements
except NoSuchElementException as e:
print(traceback.print_exc())
else:
print('Provided a wrong locator "{}"!'.format(locator))
# 点击页面元素
def click(self, by, locator):
element = self.find_element(by, locator)
element.click()
# 输入框输入新信息
def type(self, by, locator, value):
y = [x for x in value if x != '']
if len(y) > 0:
element = self.find_element(by, locator)
element.clear()
element.send_keys(value.strip())
else:
pass
# 下拉菜单通过可见文本进行选择
def select(self, by, locator, text):
y = [x for x in text if x != '']
if len(y) > 0:
element = self.find_element(by, locator)
element_element = Select(element)
element_element.select_by_visible_text(text.strip())
else:
pass
# 复选按钮勾选时我们需要首先勾掉已选选项
def uncheck(self, by, locator, options):
y = [x for x in options if x != '']
if len(y) > 0:
elements = self.find_elements(by, locator)
for element in elements:
element.click()
else:
pass
# 选择excel表格所提供的选项进行勾选
def check(self, by, locator, options):
y = [x for x in options if x != '']
if len(y) > 0:
be_options = options.split(',')
for option in be_options:
element = self.find_element(by, locator.format(option.strip()))
element.click()
else:
pass
# def input(self, left_title, excel_title, by, locator, values):
# y = [x for x in values if x != '']
# if len(y) > 0:
# if left_title == excel_title:
# self.type(by, locator, values)
# else:
# pass
# 根据excel表格提供标题所包含的关键字来决定进行哪种数据操作
def update(self, title, by, values):
y = [x for x in values if x != '']
if len(y) > 0:
if '_Text' in title: # 文本框
field = title.strip().split('_')
locator = field[0]
self.type(by, locator, values)
elif '_Select' in title: # 下拉列表
field = title.strip().split('_')
locator = field[0]
self.select(by, locator, values)
elif '_Option' in title: # 复选按钮
field = title.strip().split('_')
locator = field[0]
self.uncheck('xpath', '//input[@checked="" and contains(@id, "{}__")]'.format(locator), values)
self.check('id', '%s__{}'%locator, values)
else:
print('Please indicate the data type for the title "{}" in Excel!!!'.format(title))
else:
pass
# def set(self, left_title, excel_title, by, locator, text):
# y = [x for x in text if x != '']
# if len(y) > 0:
# if left_title == excel_title:
# self.select(by, locator, text)
# else:
# pass
# 登录系统进行封装方便以后重用
def login_orms(self, url, username, password):
# driver = webdriver.Firefox(executable_path='D:\\Selenium 3.14\\geckodriver.exe')
self.driver.delete_all_cookies()
self.driver.get(url)
self.driver.maximize_window()
time.sleep(2)
self.type('id', 'userName', username)
self.type('id', 'password', password)
self.click('id', 'okBtnAnchor')
time.sleep(2)
# 登录系统后选择Contract
def goto_manager_page(self, url, username, password, contract, page):
self.login_orms(url, username, password)
time.sleep(2)
self.click('xpath', "//option[text()='" + contract + " Contract']") # 通过click也可以对下拉列表进行选择
time.sleep(2)
self.click('link', page)
time.sleep(2)
下面是实现代码(这里没有对操作excel表格进行封装)
from Orms.BasePage import *
import xlrd
""""""
url = 'reserveamerica.com/xxxx'
account_user = 'xxx'
account_password = 'xxx'
wb = xlrd.open_workbook('D://SiteandLoopSetUp.xls')
""""""
sheet1 = wb.sheet_by_index(0)
sheet2 = wb.sheet_by_index(1)
# read provided information in Excel.
contract = sheet1.col_values(0)[1].strip()
park_name = sheet1.col_values(1)[1].strip()
search_ids = sheet1.col_values(2)[1:]
check_in_times = sheet1.col_values(3)[1:]
check_out_times = sheet1.col_values(4)[1:]
cols_num = sheet1.ncols
print('There will be "{}" fields need to update as following:'.format(cols_num))
left_titles = sheet1.row_values(0)[5:cols_num]
print(left_titles)
browser = webdriver.Firefox(executable_path='D:\\Selenium 3.14\\geckodriver.exe')
driver = BasePage(browser)
driver.goto_manager_page(url=url, username=account_user, password=account_password, contract=contract, page='Inventory Manager')
# Input park name and search
driver.type('id', 'FacilitySearchCriteria.facilityName', park_name)
driver.click('xpath', '//a[@aria-label="Search"]')
time.sleep(3)
# Click facility id in search results to facility details page
driver.click('xpath', '//tr[@name="e_Glow"]/td/a')
time.sleep(2)
# Choose Loop/Site Set-up for Facility Details drop-down list
driver.select('id', 'page_name', 'Loop/Site Set-up')
time.sleep(2)
driver.click('xpath', '//a[@tabindex="-1" and @accesskey="S"]')
time.sleep(2)
for x in range(len(search_ids)):
try:
driver.select('id', 'search_type', 'Site ID')
time.sleep(2)
driver.type('id', 'search_value', search_ids[x])
driver.click('id', 'goAnchor')
time.sleep(2)
driver.click('xpath', '//tr[@name="e_Glow"]/td[2]/a')
time.sleep(2)
# in_time and out_time are required fields, need to handle separately.
in_time = check_in_times[x].strip().split(' ')
y = [x for x in in_time if x != '']
if len(y) > 0:
driver.type('id', 'Checkin Time', in_time[0])
driver.select('id', 'Checkin Time_ispm', in_time[1])
else:
pass
out_time = check_out_times[x].strip().split(' ')
y = [x for x in out_time if x != '']
if len(y) > 0:
driver.type('id', 'Checkout Time', out_time[0])
driver.select('id', 'Checkout Time_ispm', out_time[1])
else:
pass
# update left information in excel.
for i in range(len(left_titles)):
title = left_titles[i]
excel_values = sheet1.col_values(5+i)[1:]
driver.update(title, 'id', excel_values[x])
except Exception as e:
raise Exception
else:
driver.click('xpath', '//a[@aria-label="OK"]')
以上就是我模拟手工操作进行自动填写页面表格的实现方法,虽然每次做都需要查找需要更新信息的页面元素ID的值并拷贝到excel中,但是对于几十个Contract几十种形式的site类型,加起来有上千个fields需要单独处理,这样做就显得简单很多。
当然肯定还有不完善的地方,比如都用的强制等待而没有用隐形等待,也一定有更好的实现方式,欢迎各位指正~~~