WebDriver API剖析----执行JavaScript脚本

页面上的操作有时通过Selenium是无法实现的,如滚动条、时间控件等,此时就需要借助JavaScript来完成。

WebDriver提供了一个内置方法来操作JavaScript,代码如下:

driver.execute_script(self, script, args)

可以通过两种方式在浏览器中执行JavaScript。

1、在文档根级别执行JavaScript

在文档根级别下,使用JavaScript提供的方法捕获想要的元素,然后声明一些操作并使用web Driver执行此JavaScript。例如:

JJScript = "document.getElementsByName('input')[1].click();"
driver.execute_script(JJScript)

2、在元素级别执行JavaScript

在元素级别下,使用webdriver捕获想要使用的元素,然后使用JavaScript声明一些操作并通过将web元素作为参数传递给JavaScript来使用webdriver执行此JavaScript。例如:

BtnName = driver.find_element_by_xpath("//*[@id='sb_form_go']")
driver.execute_script("arguments[0].click;", BtnName)

程序说明:

(1)通过webdriver提供的XPath方法捕获元素,代码如下:

BtnName = driver.find_element_by_xpath("//*[@id='sb_form_go']")

(2)声明JavaScript并对元素执行单击操作,代码如下:

arguments[0].click

(3)通过execute_script()使用的JavaScript语句作为字符串  值调用方法,代码如下:

driver.execute_script("arguments[0].click;", BtnName)

当有多个JS操作时,可以书写如下操作:

from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("https://www.baidu.com")

SearchName = driver.find_element_by_xpath('//*[@id="kw"]')
BtnName = driver.find_element_by_xpath('//*[@id="su"]')
driver.execute_script("arguments[0].value='bella'; arguments[1].click();", SearchName, BtnName)
sleep(3)
driver.quit()

 :一般来说,不建议通过JavaScript来执行selenium已经至耻的功能。selenium已有功能比JavaScript更完善,例如在操作元素、获取元素的值等方面,都会有更全面的验证机制(例如判断元素是否存在、是否不为0、是否处于可操作性状态等),完全没有必要使用没有验证机制所以会照样操作,所以会出现非正常的测试结果。

1、JavaScript操作日期控件

日期控件在网站上经常遇到,如12306网站、旅游订票网站(携程、去哪儿等)、租车网站(如神州租车)等。

1.1、常规日期控件的操作

下面用12306网站为例进行介绍,如图:

当通过send_keys给时间控件赋值时,看到只是把时间控件打开了,并没有选择设定的日期。采用JS赋值,则可以完成对时间控件的操作,代码如下:

from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("https://www.12306.cn/index/")
# driver.find_element_by_xpath('//*[@id="train_date"]').send_keys("2024-08-30")
DateJS = "document.getElementById('train_date').value = '2024-08-30'"
driver.execute_script(DateJS)
sleep(3)
driver.quit()

 用send_keys()结果:

用JS的结果:

2、JavaScript控制浏览器滚动条

当访问页面上的展现结果超过一屏时,如果想浏览或操作屏幕下半部分的内容时,由于被屏幕遮挡,因此无法操作对应的元素。这时就需要借助滚动条来拖动屏幕,实现浏览更多的内容或使被操作的元素展现在屏幕上。

滚动条是无法直接被定位到的,webdriver中也没有直接的方法控制滚动条。此时遍需要借助JavaScript来操作滚动条。

2.1、控制滚动条上下滑动

代码如下:

from selenium import webdriver
from time import sleep

driver = webdriver.Firefox()
driver.get("https://www.baidu.com")

driver.set_window_size(800, 600)
driver.find_element_by_xpath("//*[@id='kw']").send_keys("bella")
driver.find_element_by_xpath("//*[@id='su']").click()

sleep(4)
js = "var q=document.documentElement.scrollTop = 10000"     # 滚动条到底部
driver.execute_script(js)
sleep(3)

ks = "var a=document.documentElement.scrollTop = 0"     # 滚动条回到顶部
driver.execute_script(ks)
sleep(4)
driver.quit()

 :JS中可以修改scroll Top的值来定位浏览器右侧滚动条的位置,0表示最上面,10000表示最底部,scrollTop的值介于0-10000之间。

2.2、控制横向滚动条

通过scrollTo(x,y)来实现横向与纵向滚动条的移动,x是横坐标,y是纵坐标。y为0时,x设置任意数,便是滚动条左右滚动的情况。

代码如下:

from selenium import webdriver
from time import sleep

driver = webdriver.Firefox()
driver.get("https://www.baidu.com")

driver.set_window_size(800, 600)
driver.find_element_by_xpath("//*[@id='kw']").send_keys("bella")
driver.find_element_by_xpath("//*[@id='su']").click()
sleep(4)
Js = "window.scrollTo(100,0)"
driver.execute_script(Js)
sleep(4)
driver.quit()

效果图:

scrollTo函数还可以通过其他方式来实现滚动条。

  • scrollHeight:获取浏览器的滚动高度;
  • scrollWidth:获取刘阿龙年起的股东你宽度;
  • scrollLeft:设置或获取窗口可见内容与最左端之间的距离;
  • scrollTop:设置或获取窗口可见内容与最顶端之间的距离;
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("https://www.baidu.com")
driver.set_window_size(800, 600)
driver.find_element_by_xpath("//*[@id='kw']").send_keys("bella")
driver.find_element_by_xpath("//*[@id='su']").click()
sleep(4)
# 滚动条到最底部
DownJs = "window.scrollTo(0,document.body.scrollHeight)"
driver.execute_script(DownJs)
sleep(2)
# 滚动条回到初始位置
InitJs = "window.scrollTo(0,0)"
driver.execute_script(InitJs)
sleep(2)
# 滚动调到最左侧
LeftJs = "window.scrollTo(document.body.scrollWidth,600)"
driver.execute_script(LeftJs)
sleep(2)
# 滚动条回到初始位置
driver.execute_script(InitJs)
sleep(4)
driver.quit()

3、引入JavaScript库处理HTML5拖曳

首先,先编写个测试页面,该页面完全使用HTML5原生支持拖曳功能,页面代码如下:

<html>
	<head>

	<style type="text/css">
		#div1{
			width:300px;
			height:100px;
			padding:10px;
			border:1px solid #aaaaaa  
		}
	</style>

	<script type="text/javascript">
		function allowDrop(ev){
			ev.preventDefault();
		}
		function drag(ev){
			ev.dataTransfer.setData("Text", ev.target.id);
		}
		function drop(ev){
			ev.preventDefault();
			var data = ev.dataTransfer.getData("Text");
			ev.target.appendChild(document.getElementById(data));
			alert("图片放置成功");
		}
	</script>
	</head>
	<body>
	 <p>请把图片拖放到方框中:</p>
	 <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
	 <br/>
	 <img id="drag1" src="https://cdn.ptpress.cn/pubcloud/3/app/0718A6B0/cover/20191204BD54009A.png" draggable="true" ondragstart="drag(event)">
	</body>
</html>	

引用第三方库有两种方式,先说第一种,引用方式是在网页中嵌入<script>标签,让<script>

标签的src库指向第三方库。但由于浏览器加载<script>中的JavaScript时是异步加载的,因此用这种方式引用外部库时,必须要等待库加载完毕才能执行下一步操作。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Firefox()
driver.get("file:///F:/TestDragAndDrop.html")

injectJSTemplate = "var injectionScript = document.createElement('script'); injectionScript.src = arguments[0]; document.getElementsByTagName('head')[0].appendChild(injectionScript)"
jQueryLibPath = "https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"
driver.execute_script(injectJSTemplate, jQueryLibPath)

WebDriverWait(driver, 10).until(lambda d: d.execute_script("return typeof(jQuery)!='undefined';"))

dndLibPath = "http://blog-static.cnblogs.com/files/realdigit/drag_and_drop_helper.js"
driver.execute_script(injectJSTemplate, dndLibPath)

WebDriverWait(driver, 10).until(lambda d: d.execute_script("return typeof(drag_and_drop_loaded)!='undefined';"))

driver.execute_script("$('#drag1').simulateDragDrop({dropTarget: '#div1'});")

第二种引用方式就是直接加载并执行第三方库的内容,这种方式属于同步加载,因此不需要在引用各个JavaScript库时等待加载完毕。整体而言,第二种方式比第一种方式简洁。

from selenium import webdriver
import urllib.request

driver = webdriver.Firefox()
driver.get("file:///F:/TestDragAndDrop.html")

jQueryLibPath = "https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"
with urllib.request.urlopen(jQueryLibPath) as response:
    dnd_all_javascript = response.read().decode('utf-8')
driver.execute_script(dnd_all_javascript)

dndLibPath = "http://blog-static.cnblogs.com/files/realdigit/drag_and_drop_helper.js"
with urllib.request.urlopen(dndLibPath) as response:
    dnd_all_javascript = response.read().decode('utf-8')
driver.execute_script(dnd_all_javascript)

driver.execute_script("$('#drag1').simulateDragDrop({dropTarget: '#div1'});")

:引入外部JavaScript库可能会对现有功能造成影响,例如造成变量或函数名称冲突,原型被意外修改等,导致网站功能异常,因此引入之前需要仔细评估该库对网站的影响。 

若有同学会JavaScript其他的功能欢迎补充。

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值