Python 高级自动化技巧 | Selenium
这篇文章与OnePublish交叉发布
DEV Network 怎么样?
在这篇文章中我想分享我目前实习期间的自动化经验。
实际上,我想在一个真实的项目上向你解释这一点,但不幸的是,我没有找到任何符合我所有要求的平台。
但是,如果您是 Python 开发人员,您将需要这些技巧来快速构建自动化程序。那么,让我们开始吧!
Web 驱动程序
正确配置 Web 驱动程序对于运行自动化至关重要。如果您想使用Chrome作为 Web 驱动程序,则应安装chromedriver。但是,如果您想选择 Firefox,则应安装geckodriver。
创建一个类
通过创建类,您可以轻松处理 URL 并调用函数,这样就不必在每个函数中创建 Web 驱动程序。请看以下代码:
from selenium import webdriver
class Bot:
def __init__(self):
self.bot = webdriver.Firefox(executable_path='/path/to/geckodriver')
automate = Bot()
因此,当你需要函数中的驱动程序时,只需编写:
def search(self):
bot = self.bot
bot.get('www.google.com')
处理登录
为了处理登录,您应该在 __init__ 函数中添加字段。请看以下代码:
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class Bot:
def __init__(self,username,password):
self.username = username
self.password = password
self.bot = webdriver.Firefox(executable_path='/path/to/geckodriver')
def login(self):
bot = self.bot
bot.get('https://website.com/')
time.sleep(3)
email = bot.find_element_by_id('userNameBox')
password = bot.find_element_by_id('passWordBox')
email.clear()
password.clear()
email.send_keys(self.username)
password.send_keys(self.password)
bot.find_element_by_id('LoginBtn').click()
time.sleep(3)
automate = Bot('your_username', 'your_password')
automate.login()
处理登录的非常简单的方法。
循环点击
如果要循环点击,务必使用time.sleep()。因为自动化需要时间来执行下一次点击。如果不使用 time.sleep(),则会出现 ElementClickInterceptedException 错误。
for elem in elements:
elem.click()
time.sleep(3)
将数据写入 CSV
网上有很多关于如何将数据写入 CSV 的解决方案和示例。假设您有多个数组,并且希望将它们以正确的字段名称(列名)写入 CSV。
让我更清楚一点……
我的任务是抓取一些短语,并将它们翻译成所有语言,然后将这些数据写入 CSV 文件。因此,我使用了 GT API,并为每种语言创建了一个数组。
我有很多数组,所以我需要以某种方式在正确的字段名称(列名)下写下每个翻译。
以下代码演示了处理此类问题的最佳解决方案:
# zip arrays
languages_translations = zip(ar,hy,ms,bg,zh_cn_SAR,zh_cn,
zh_tw_singapore,zh_tw,hr,cs,da,nl,en_australia,en_uk,en_usa,et,fi)
# Write to CSV
with open('translations.csv', mode='w', newline='', encoding="utf-8") as csv_file:
fieldnames = ['Arabic', 'Armenian (Armenia)', 'Bahasa Malaysia (Malaysia)', 'Bulgarian (Bulgaria)', 'Chinese (Hong Kong SAR)',
'Chinese (Simplified)','Chinese (Singapore)','Chinese (Traditional)','Croatian (Croatia)', 'Czech (Czech Republic)',
'Danish (Denmark)','Dutch (The Netherlands)','English (Australia)','English (UK)', 'English (US)','Estonian (Estonia)','Finnish (Finland)']
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for lang in languages_translations:
writer.writerow(dict(zip(fieldnames, lang)))
如您所见,您应该压缩所有数组,循环它并写入压缩字段名称和循环项的行字典。
通过这种方式,您将把所有数据正确地写入 CSV 文件。
处理弹出窗口或 iframe
另一个具有挑战性的任务是在自动化过程中处理弹出窗口或 iframe。如果需要与弹出窗口或 iframe 元素交互,则应该告诉 Selenium 将窗口从主窗口切换到弹出窗口。处理完弹出窗口后,应该切换回主窗口。
# find iframe or popup element
iframe = bot.find_element_by_tag_name('iframe')
# switch to iframe or popup window
bot.switch_to.frame(iframe)
# interact with elements
textarea = bot.find_element_by_tag_name('body')
textarea.send_keys('Some Keys Here')
# switch back to main window
bot.switch_to.default_content()
太棒了!我给你提供了网上那些很复杂的解决方案。
如果您必须处理警报弹出窗口,您也可以使用此方法。
将 CSV 数据发送到 Web 元素
有时您需要将 csv 数据发送到 Web 元素(例如多个文本框)。
假设您有多个面板,其中包含多个文本框,并且您必须将 CSV 行发送到这些文本框中
所以每个 CSV 行都属于不同的面板。听起来很疯狂吧?这就是训练你大脑的方法 :) 你必须以某种方式迭代每个面板文本框对应的每个 CSV 行。
在我们继续之前,如果您想查找更多类似的文章,请访问Reverse Python 。
好吧!我们先看看代码,然后我会解释:
def send_keys_textboxes(self,url):
bot = self.bot
# go to url
bot.get(url)
# reader object which will iterate over lines in the given csvfile
with open('translations.csv', 'rt', encoding='utf8') as csvfile:
langs = csv.reader(csvfile, delimiter=',', quotechar='"')
# create list of langs
langs = list(langs)
elements = bot.find_elements_by_xpath("//a[@data-tag='globalize']")
# Using index to handle multiple panels
index = 0
try:
for elem in elements:
class_of_element = elem.get_attribute("class")
if class_of_element == 'cs-trans-icon':
# Panel opens with click
elem.click()
time.sleep(3)
textBoxes = bot.find_elements_by_tag_name('textarea')
# Loop only specific index of list
phrases = langs[index]
# Itearating TextBoxes
for i in range(len(phrases)):
textBoxes[i].send_keys(phrases[i].title())
time.sleep(3)
# Increasing index for next panel
index = index+1
try:
bot.find_element_by_class_name('CsImageButton').click()
except NoSuchElementException:
bot.find_element_by_class_name('cso-btn').click()
time.sleep(3)
except ElementClickInterceptedException:
pass
索引在此解决方案中起着重要作用。我们之前提到过,我们需要处理多个面板,因此索引可以避免循环读取每个面板中的所有行。假设您有 3 行数据,如果不使用索引,程序将继续循环,直到读取完第 3 行。因此,每个文本框将有 3 个值。但是,我们只需要将第一行的值发送到第一个面板的文本框中,将第二行的值发送到第二个面板的文本框中,依此类推。
一旦定义了索引,我们就可以迭代文本框。这样,行中的第一个值将发送到第一个文本框,行中的第二个值将发送到第二个文本框,依此类推。
这些示例来自真实世界的项目,因此我建议将这篇文章加入书签。
处理下拉菜单
因此,有两种方法可以处理下拉菜单。
第一个解决方案是使用 selenium 的 Select 方法从下拉列表中选择选项。
from selenium.webdriver.support.ui import Select
bot = self.bot
bot.get("https://example.com")
select = Select(bot.find_element_by_xpath("//select"))
# select bu index of option
select.select_by_index(2)
# select by text of option
select.select_by_visible_text('Visible Text')
# select by value of option
select.select_by_value('value')
第二种解决方案是仅使用 xpath 单击下拉项:
bot.find_element_by_xpath("//select/option[text()='Option_Text_Here']").click()
使用 xpath 导航父元素
有时 HTML 结构可能会混乱,导致您无法选择所需的元素。在这种情况下,最好导航到父元素或使用 XPath 返回:
# elem is a web element object
# selenium will jump 2 step back to look for parent element
parent_element = elem.find_element_by_xpath('..').find_element_by_xpath('..')
任务完成!
就这些了!我和大家分享了我的 Python 自动化经验,希望它能帮到你,并节省你在网上搜索的时间。
请访问Reverse Python获取更多文章(您不会失望的),并在评论中告诉我我的下一篇文章应该涉及什么。
很快再见,DEVs!保持联系!
文章来源:https://dev.to/thedevtimeline/advanced-automation-tips-with-python-selenium-17j0