前言
一般的窗口切换就是浏览器打开多个窗口,使用selenium在多个窗口中相互切换。除此之外,还会遇到iframe窗口,这种相当于大盒子中嵌套小盒子,对于这种窗口切换,重点就是进入某个盒子,退出某个盒子。知道当前在哪个盒子中,就好搞操作了。
窗口切换
重点:
- driver.switch_to系列,切换窗口,包括三个常用的方法:
- switch_to.window,切换窗口,替换
switch_to_window
- switch_to.frame,进入iframe,替换
switch_to_frame
- switch_to.default_content,退出iframe,替换原方法
switch_to_default_content
- switch_to.window,切换窗口,替换
- window_handles,窗口数组
根据这两个方法组合,就达到切换窗口的目的了。我们来演示一个,从百度入口输入关键字并且点击某个结果(因为点击某个链接,会在新的窗口中打开),然后再切换回来。
代码如下:
import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 获取driver driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) try: # 发请求 driver.get('https://www.baidu.com') # 定位标签并输入值然后点击 driver.find_element_by_id('kw').send_keys('听雨危楼-cnblogs') time.sleep(1) driver.find_element_by_id('su').click() # 在新窗口中,点击结果标签 wait.until(EC.presence_of_element_located((By.LINK_TEXT, '听雨危楼 - 博客园'))).click() # driver.find_element_by_link_text('听雨危楼').click() # 所有打开的窗口都存在这个数组中 # print(driver.window_handles) # ['CDwindow-922052E58B50E4A32401C904D478CC8E', 'CDwindow-AC58D7837A577C8878BE283F554B0E52', 'CDwindow-8196C4B6F2DEAAD7F0AF10DA17BC44ED'] # 根据数组下标索引切换窗口 time.sleep(3) driver.switch_to.window(driver.window_handles[1]) time.sleep(3) driver.switch_to.window(driver.window_handles[0]) time.sleep(2) driver.switch_to.window(driver.window_handles[2]) finally: # 关闭浏览器 time.sleep(3) driver.quit() # 截止2019-6-11,代码无误
效果如下:
iframe窗口切换
iframe记住两个方法:
- switch_to.frame(iframe),进入窗口
- switch_to.default_content(),退出窗口
完成一个使用selenium自动发163邮件的程序。
直接上代码:
import time import datetime from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By def login(user, pwd): """ 登录163邮箱 """ # 由于可以扫码登录,而我们选择用户名和密码登录,所以,要点击 密码登录 time.sleep(1) wait.until(EC.presence_of_element_located((By.ID, 'switchAccountLogin'))).click() # 进入iframe,因为有多个iframe,所以获取的是数组,在分析页面后,数组0索引的iframe是登陆的iframe time.sleep(3) iframe = driver.find_elements_by_tag_name('iframe') # print(iframe) ''' [ <selenium.webdriver.remote.webelement.WebElement (session="3f92dbd96e72746e7d27d64e6b412318", element="0.855888743369456-2")>, <selenium.webdriver.remote.webelement.WebElement (session="3f92dbd96e72746e7d27d64e6b412318", element="0.855888743369456-3")>, <selenium.webdriver.remote.webelement.WebElement (session="3f92dbd96e72746e7d27d64e6b412318", element="0.855888743369456-4")>, <selenium.webdriver.remote.webelement.WebElement (session="3f92dbd96e72746e7d27d64e6b412318", element="0.855888743369456-5")> ] ''' driver.switch_to.frame(iframe[0]) # 获取用户名和密码标签,并输入对应的值 time.sleep(1) driver.find_element_by_class_name('dlemail').send_keys(user) time.sleep(2) driver.find_element_by_class_name('dlpwd').send_keys(pwd) time.sleep(2) driver.find_element_by_id('dologin').click() def send_mail(): """ 发送163邮件,需要传递163的用户名和密码,收件人和内容 """ try: # 第1步,执行登陆 login(user, pwd) # 第2步,点击写信按钮 wait.until(EC.presence_of_element_located((By.ID, '_mail_component_24_24'))).click() # driver.find_element_by_id('_mail_component_24_24').click() # 第3步,获取收件人,主题,内容框标签,写入内容 time.sleep(1) # 3.1 填写收件人 wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'nui-editableAddr-ipt'))).send_keys(addr) # 收件人 time.sleep(2) # 3.2 填写主题 title = driver.find_elements_by_class_name('nui-ipt-input') # print(11111, title) title[2].send_keys(theme) # 主题 # title.send_keys(theme) # 主题 # 3.3 进入content所在iframe,填写内容 time.sleep(1) content_iframe = driver.find_element_by_class_name('APP-editor-iframe') driver.switch_to.frame(content_iframe) # 虽然nui-scroll这个类名在整个网页中有多个,但是这个iframe中只有一个,所以我们直接send_keys就行 nui_scroll = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'nui-scroll'))) # print(22222222, nui_scroll) # <selenium.webdriver.remote.webelement.WebElement (session="106a6f5778c14568827014435ddcfcd9", element="0.07847410617283446-1")> nui_scroll.send_keys(content) # 第4步,因为发送按钮不在此时的iframe中,所以要先退出iframe,才能点击发送按钮 # 4.1 退出iframe time.sleep(1) driver.switch_to.default_content() # 4.2 点击发送按钮 time.sleep(1) # 这个发送按钮的类名有多个,最好for循环一下,因为有坑,发送按钮是第3个,前面还有两个空标签,但是前端检查中看不到 driver.find_elements_by_class_name('nui-btn-text')[2].click() finally: # 关闭浏览器 time.sleep(3) driver.quit() # 截止2019-6-11,代码无误 if __name__ == '__main__': from getpass import getpass user = input("邮箱: ").strip() # 填写你的163账号 pwd = getpass('密码: ') # 填写你的163密码 # 获取driver driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) # driver.maximize_window() # 发请求 driver.get('https://mail.163.com/') addr = "1206180814@qq.com" # 收件人 theme = '我是你爸爸' # 主题 content = '天不生我李淳罡,剑道万古如长夜 ———— {}'.format(datetime.datetime.now()) # 发送内容 send_mail()
效果如下:
其他版本:
import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) try: driver.get('https://mail.163.com/') driver.maximize_window() time.sleep(2) wait.until(EC.presence_of_element_located((By.ID, 'switchAccountLogin'))).click() time.sleep(1) iframe_obj = driver.find_elements_by_tag_name('iframe') # print(iframe_obj) driver.switch_to.frame(iframe_obj[0]) driver.find_element_by_class_name('dlemail').send_keys('tingyuweilou') time.sleep(1) driver.find_element_by_class_name('dlpwd').send_keys('blackheiheihei') time.sleep(1) driver.find_element_by_id('dologin').click() wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="_mail_component_24_24"]/span[2]'))).click() wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'nui-editableAddr-ipt'))).send_keys('1206180814@qq.com') theme = driver.find_elements_by_class_name('nui-ipt-input') # print(theme) theme[2].send_keys('邮件主题') content = driver.find_element_by_class_name('APP-editor-iframe') driver.switch_to.frame(content) driver.find_element_by_class_name('nui-scroll').send_keys('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') driver.switch_to.default_content() driver.find_element_by_class_name('nui-ico-sent').click() finally: # 无论如何,都要关闭浏览器 time.sleep(10) driver.quit()
效果如下:
qq发邮件
发送消息
import time from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import event_firing_webdriver as EC from selenium.webdriver.common.by import By from getpass import getpass driver = webdriver.Chrome() wait = WebDriverWait(driver,10) try: driver.get('https://mail.qq.com/') driver.maximize_window() time.sleep(2) name_obj = driver.find_element_by_id('login_frame') driver.switch_to.frame(name_obj) print(name_obj) driver.find_element_by_id('u').send_keys('2436300135') time.sleep(1) driver.find_element_by_id('p').send_keys('111111') driver.find_element_by_id('login_button').click() time.sleep(1) driver.find_element_by_id('composebtn').click() time.sleep(2) content = driver.find_element_by_id('mainFrame') driver.switch_to.frame(content) time.sleep(2) driver.find_element_by_xpath('//*[@id="toAreaCtrl"]/div[2]/input').send_keys('2897653646@qq.com') driver.find_element_by_id('subject').send_keys('嘿嘿') time.sleep(3) test = driver.find_element_by_class_name('qmEditorIfrmEditArea') driver.switch_to.frame(test) time.sleep(1) driver.find_element_by_xpath('/html/body').send_keys('222') time.sleep(1) driver.switch_to.parent_frame()# 如果当前已是主文档,则无效果 driver.find_element_by_xpath('//*[@id="toolbar"]/div/a[1]').click() driver.switch_to.default_content() #跳出f1,进入topwindow层 finally: time.sleep(2) driver.quit()
带附件
import unittest import smtplib import HTMLTestRunner from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header class TestStringMethods(unittest.TestCase): def test_upper(self): """判断 foo.upper() 是否等于 FOO""" self.assertEqual('foo'.upper(), 'FOO') def test_isupper(self): """ 判断 Foo 是否为大写形式 """ self.assertTrue('Foo'.isupper()) def get_case_result(): """ 获取测试用例报告 """ suite = unittest.makeSuite(TestStringMethods) file_path = r'./result.html' with open(file_path, 'wb') as f: HTMLTestRunner.HTMLTestRunner( stream=f, title='HTMLTestRunner版本关于upper的测试报告', description='判断upper的测试用例执行情况').run(suite) f1 = open(file_path, 'r', encoding='utf-8') res = f1.read() f1.close() return res def send_email(): """ 发送邮件 """ # 第三方 SMTP 服务 mail_host = "smtp.qq.com" # 设置服务器 mail_user = "1206xxx4@qq.com" # 用户名 mail_pass = "bcemjxxxkvwhggea" # 口令 # 设置收件人和发件人 sender = '1206180814@qq.com' receivers = ['1206180814@qq.com', 'tingyuweilou@163.com', '3300799899@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱 # 创建一个带附件的实例对象 message = MIMEMultipart() # 邮件主题、收件人、发件人 subject = '请查阅--测试报告' # 邮件主题 message['Subject'] = Header(subject, 'utf-8') message['From'] = Header("{}".format(sender), 'utf-8') # 发件人 message['To'] = Header("{}".format(';'.join(receivers)), 'utf-8') # 收件人 # 邮件正文内容 html 形式邮件 send_content = get_case_result() # 获取测试报告 html = MIMEText(_text=send_content, _subtype='html', _charset='utf-8') # 第一个参数为邮件内容 # 构造附件 att = MIMEText(_text=send_content, _subtype='base64', _charset='utf-8') att["Content-Type"] = 'application/octet-stream' file_name = 'result.html' att["Content-Disposition"] = 'attachment; filename="{}"'.format(file_name) # # filename 为邮件附件中显示什么名字 message.attach(html) message.attach(att) try: smtp_obj = smtplib.SMTP() smtp_obj.connect(mail_host, 25) # 25 为 SMTP 端口号 smtp_obj.login(mail_user, mail_pass) smtp_obj.sendmail(sender, receivers, message.as_string()) smtp_obj.quit() print("邮件发送成功") except smtplib.SMTPException: print("Error: 无法发送邮件") if __name__ == '__main__': send_email()