小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
弹窗处理
JavaScript
有三种弹窗 alert
(确认)、confirm
(确认、取消)、prompt
(文本框、确认、取消)。
处理方式:先定位(switch_to.alert
自动获取当前弹窗),再使用 text
、accept
、dismiss
、send_keys
等方法进行操作
方法 | 描述 |
---|---|
text | 获取弹窗中的文字 |
accept | 接受(确认)弹窗内容 |
dismiss | 解除(取消)弹窗 |
send_keys | 发送文本至警告框 |
这里写一个简单的测试页面,其中包含三个按钮,分别对应三个弹窗。
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="alert">alert</button>
<button id="confirm">confirm</button>
<button id="prompt">prompt</button>
<script type="text/javascript">
const dom1 = document.getElementById("alert")
dom1.addEventListener('click', function(){
alert("alert hello")
})
const dom2 = document.getElementById("confirm")
dom2.addEventListener('click', function(){
confirm("confirm hello")
})
const dom3 = document.getElementById("prompt")
dom3.addEventListener('click', function(){
prompt("prompt hello")
})
</script>
</body>
</html>
下面使用上面的方法进行测试。为了防止弹窗操作过快,每次操作弹窗,都使用 sleep
强制等待一段时间。
from selenium import webdriver
from pathlib import Path
from time import sleep
driver = webdriver.Firefox()
driver.get('file:///' + str(Path(Path.cwd(), '弹窗.html')))
sleep(2)
# 点击alert按钮
driver.find_element_by_xpath('//*[@id="alert"]').click()
sleep(1)
alert = driver.switch_to.alert
# 打印alert弹窗的文本
print(alert.text)
# 确认
alert.accept()
sleep(2)
# 点击confirm按钮
driver.find_element_by_xpath('//*[@id="confirm"]').click()
sleep(1)
confirm = driver.switch_to.alert
print(confirm.text)
# 取消
confirm.dismiss()
sleep(2)
# 点击confirm按钮
driver.find_element_by_xpath('//*[@id="prompt"]').click()
sleep(1)
prompt = driver.switch_to.alert
print(prompt.text)
# 向prompt的输入框中传入文本
prompt.send_keys("Dream丶Killer")
sleep(2)
prompt.accept()
'''输出
alert hello
confirm hello
prompt hello
'''
注:细心地读者应该会发现这次操作的浏览器是
Firefox
,为什么不用Chrome
呢?原因是测试时发现执行prompt
的send_keys
时,不能将文本填入输入框。尝试了各种方法并查看源码后确认不是代码的问题,之后通过其他渠道得知原因可能是Chrome
的版本与selenium
版本的问题,但也没有很方便的解决方案,因此没有继续深究,改用Firefox
可成功运行。这里记录一下我的Chrome
版本,如果有大佬懂得如何在Chrome
上解决这个问题,请在评论区指导一下,提前感谢! selenium:3.141.0 Chrome:94.0.4606.71
上传 & 下载文件
上传文件
常见的 web 页面的上传,一般使用 input
标签或是插件(JavaScript
、Ajax
),对于 input
标签的上传,可以直接使用 send_keys(路径)
来进行上传。 先写一个测试用的页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" name="">
</body>
</html>
下面通过 xpath
定位 input
标签,然后使用 send_keys(str(file_path)
上传文件。
from selenium import webdriver
from pathlib import Path
from time import sleep
driver = webdriver.Chrome()
file_path = Path(Path.cwd(), '上传下载.html')
driver.get('file:///' + str(file_path))
driver.find_element_by_xpath('//*[@name="upload"]').send_keys(str(file_path))
下载文件
Chrome浏览器
Firefox
浏览器要想实现文件下载,需要通过 add_experimental_option
添加 prefs
参数。
download.default_directory
:设置下载路径。profile.default_content_settings.popups
:0 禁止弹出窗口。
下面测试下载搜狗图片。指定保存路径为代码所在路径。
from selenium import webdriver
prefs = {'profile.default_content_settings.popups': 0,
'download.default_directory': str(Path.cwd())}
option = webdriver.ChromeOptions()
option.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(options=option)
driver.get("https://pic.sogou.com/d?query=%E7%83%9F%E8%8A%B1&did=4&category_from=copyright")
driver.find_element_by_xpath('/html/body/div/div/div/div[2]/div[1]/div[2]/div[1]/div[2]/a').click()
driver.switch_to.window(driver.window_handles[-1])
driver.find_element_by_xpath('./html').send_keys('thisisunsafe')
代码最后两句猜测有理解什么意思的吗~,哈哈,实际作用是当你弹出像下面的页面 “您的连接不是私密连接” 时,可以直接键盘输入 “thisisunsafe” 直接访问链接。那么这个键盘输入字符串的操作就是之间讲到的
send_keys
,但由于该标签页是新打开的,所以要通过switch_to.window()
将窗口切换到最新的标签页。
Firefox浏览器
Firefox
浏览器要想实现文件下载,需要通过 set_preference
设置 FirefoxProfile()
的一些属性。
browser.download.foladerList
:0 代表按浏览器默认下载路径;2 保存到指定的目录。browser.download.dir
:指定下载目录。browser.download.manager.showWhenStarting
:是否显示开始,boolean
类型。browser.helperApps.neverAsk.saveToDisk
:对指定文件类型不再弹出框进行询问。- HTTP Content-type对照表:www.runoob.com/http/http-c…
from selenium import webdriver
import os
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.dir",os.getcwd())
fp.set_preference("browser.download.folderList",2)
fp.set_preference("browser.download.manager.showhenStarting",True)
fp.set_preference("browser.helperApps.neverAsk.saveToDisk","application/octet-stream")
driver = webdriver.Firefox(firefox_profile = fp)
driver.get("https://pic.sogou.com/d?query=%E7%83%9F%E8%8A%B1&did=4&category_from=copyright")
driver.find_element_by_xpath('/html/body/div/div/div/div[2]/div[1]/div[2]/div[1]/div[2]/a').click()
运行效果与 Chrome
基本一致,这里就不再展示了。
cookies操作
cookies
是识别用户登录与否的关键,爬虫中常常使用 selenium + requests
实现 cookie
持久化,即先用 selenium
模拟登陆获取 cookie
,再通过 requests
携带 cookie
进行请求。
webdriver
提供 cookies
的几种操作:读取、添加删除。
get_cookies
:以字典的形式返回当前会话中可见的cookie
信息。get_cookie(name)
:返回cookie
字典中key == name
的cookie
信息。add_cookie(cookie_dict)
:将cookie
添加到当前会话中delete_cookie(name)
:删除指定名称的单个cookie
。delete_all_cookies()
:删除会话范围内的所有cookie
。
下面看一下简单的示例,演示了它们的用法。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
# 输出所有cookie信息
print(driver.get_cookies())
cookie_dict = {
'domain': '.csdn.net',
'expiry': 1664765502,
'httpOnly': False,
'name': 'test',
'path': '/',
'secure': True,
'value': 'null'}
# 添加cookie
driver.add_cookie(cookie_dict)
# 显示 name = 'test' 的cookie信息
print(driver.get_cookie('test'))
# 删除 name = 'test' 的cookie信息
driver.delete_cookie('test')
# 删除当前会话中的所有cookie
driver.delete_all_cookies()
调用JavaScript
webdriver
对于滚动条的处理需要用到 JavaScript
,同时也可以向 textarea
文本框中输入文本( webdriver
只能定位,不能输入文本),webdriver
中使用execute_script方法实现 JavaScript
的执行。
滑动滚动条
通过 x ,y 坐标滑动
对于这种通过坐标滑动的方法,我们需要知道做表的起始位置在页面左上角(0,0),下面看一下示例,滑动 CSDN 首页。
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
sleep(1)
js = "window.scrollTo(0,500);"
driver.execute_script(js)
通过参照标签滑动
这种方式需要先找一个参照标签,然后将滚动条滑动至该标签的位置。下面还是用 CSDN 首页做示例,我们用循环来实现重复滑动。该 li
标签实际是一种懒加载,当用户滑动至最后标签时,才会加载后面的数据。
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
sleep(1)
driver.implicitly_wait(3)
for i in range(31, 102, 10):
sleep(1)
target = driver.find_element_by_xpath(f'//*[@id="feedlist_id"]/li[{i}]')
driver.execute_script("arguments[0].scrollIntoView();", target)
其他操作
关闭所有页面
使用 quit()
方法可以关闭所有窗口并退出驱动程序。
driver.quit()
关闭当前页面
使用 close()
方法可以关闭当前页面,使用时要注意 “当前页面” 这四个字,当你关闭新打开的页面时,需要切换窗口才能操作新窗口并将它关闭。,下面看一个简单的例子,这里不切换窗口,看一下是否能够关闭新打开的页面。
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
driver.implicitly_wait(3)
# 点击进入新页面
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
# 切换窗口
# driver.switch_to.window(driver.window_handles[-1])
sleep(3)
driver.close()
可以看到,在不切换窗口时,driver
对象还是操作最开始的页面。
对当前页面进行截图
wendriver
中使用 get_screenshot_as_file()
对 “当前页面” 进行截图,这里和上面的 close()
方法一样,对于新窗口的操作,一定要切换窗口,不然截的还是原页面的图。对页面截图这一功能,主要用在我们测试时记录报错页面的,我们可以将 try except
结合 get_screenshot_as_file()
一起使用来实现这一效果。
try:
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
except:
driver.get_screenshot_as_file(r'C:\Users\pc\Desktop\screenshot.png')
对于刚入门 Python
或是想要入门 Python
的小伙伴,可以微信搜【Python新视野
】,一起交流学习,都是从新手走过来的,有时候一个简单的问题卡很久,但可能别人的一点拨就会恍然大悟,由衷的希望大家能够共同进步。