众所周知,Python通常结合selenium模块来完成一些web的自动化测试以及RPA(Robotic Process Automation)工作。事实上,Selenium还可以支持插入js语句、执行js语句、返回js语句的执行结果到python程序中。这对于那些已经习惯了Javascript语法的程序员们,简直是一大神器。

  举个简单的例子,我们用selenium原生的方法对页面的一个input元素执行输入时,通常需要用到selenium中的send_keys以及clear方法,

代码类似于:

driver.find_element_by_xpath('//*[@id="dataList"]//input').clear()
driver.find_element_by_xpath('//*[@id="dataList"]//input').send_keys("Your contents")

  该方法大多数时候已经足够好用,但是仔细分析,send_keys方法主要是模拟的用户键盘操作,程序执行时必须要保证该元素始终获取焦点,页面执行过程中尽量不能动页面,否则send_keys方法可能会失效。而且我们每次send_keys之前需要对input元素已有的text进行清空,即初始化。笔者推荐使用JS注入selenium的方法来达到更好的效果,在selenium中写JS语句往往是如下形式:

js="document.getElementsByClassName('form-control')[0].value='%s';"%(requestCode[i][0].value)
driver.execute_script(js)

  该方法,相当于是直接调用页面元素的value方法来进行赋值,不用考虑变量初始化问题,它属于网页后台功能,类似于F12直接在console中执行代码,不需要光标停留在该input元素上。

使用JS后,我们就可以使用诸如document.getElementsByClassName、QuerySelector、QuerySelectorAll等JS方法定位元素,玩儿法大大丰富;

近日,笔者在一个具体的项目中,需要提取页面某表格的某一列值,该表格虽然最多支持100行来分页,但是用户可视区域只能显示15行。笔者需要提取该列的每一个值做后续判断。开始的方法是用的原生的selenium写法:

elements=driver.find_elements_by_xpath("//tr[contains(@id,'datagrid-row-r1-1')]")
for element1 in elements:
textList1=element1.text
value2=re.search(r"(H\d{13})",textList1)
slaStatus=re.search(r"(aa|bb|cc)",textList1)
statusList.append(slaStatus.group(1))
value2List.append(value2.group(1))

奇怪的事情发生了,该elements对象是一个列表,尽管它超过15个元素,但是每次遍历过程中,始终只能读取到前15个元素的text属性,之后的element元素,其text始终为空。笔者过程中换用了正则表达式、cssSelector、xpath等多种方法来提取该属性,总是只能提取到前15个元素的text属性。但是笔者将鼠标悬停在elements中,可以看到VSCode已经捕获到了所有对应元素的text,百思不得其解:

最后,笔者使用JS注入的方法完美避开了此问题,达到同样效果。

js=r"""
var ss="";
for(var i= 1; i< document.querySelectorAll('[field="x"]').length; i ++)
{
ss=ss+document.querySelectorAll('[field="x"]')[i].innerText;
ss=ss.replace(/[\r\n]/g,"")+"|";
};
return ss;
"""
value2

=driver.execute_script(js)

value2List=value2.split("|")

  该方法中,笔者使用document.querySelectorAll方法获取到field属性="x"的所有元素的合集,遍历过程中,取其innerText并最终借助“|”拼接成字符串。最后在python环境下通过字符串的split方法基于“|”拆分成列表,相当于编码再解码。笔者之所以这样操作是因为,如果js语句执行结果返回的是一个数组,该数组如何与python中的列表直接对接?

无论如何,使用JS的方法完美地提取到了页面元素的属性,达到同样的效果。程序员尤其是新手,在编程过程中难免遇到这样那样的问题。但是一旦你掌握了足够多的方法,就总能在不断尝试过程中接近想要的答案!

Python selenium中注入并执行Javascript语句的更多相关文章

  1. 爬虫之动态HTML处理(Selenium与PhantomJS )执行 JavaScript 语句

    执行 JavaScript 语句 1.隐藏百度图片 from selenium import webdriverimport time driver = webdriver.PhantomJS()dr ...

  2. python中使用excutemany执行update语句,批量更新

    python中使用excutemany执行update语句,批量更新 # coding:utf8 import pymysql import logging connection = pymysql. ...

  3. 在 Selenium 中让 PhantomJS 执行它的 API

    from selenium import webdriver driver = webdriver.PhantomJS() script = "var page = this; page.o ...

  4. python return中的or和and语句

    python return中的or和and语句 1.二元运算: 如果一个True,一个False或两个false: return True and False # 返回False return Tru ...

  5. 案例:执行 JavaScript 语句

    隐藏百度图片 # coding=utf-8 from selenium import webdriver driver = webdriver.PhantomJS(executable_path=r' ...

  6. C#中使用MySqlCommand执行插入语句后获取该数据主键id值的方法

    .net中要连接mysql数据库,需要引用MySql.Data.dll文件,这文件在mysql官网上有下载. 接着通过MySqlCommand执行插入语句后想要获取该数据主键id值的方法如下: lon ...

  7. python selenium中iframe切换、window切换方法

    一.selenium中iframe切换方法: 方法一:switch_to.frame frame函数中提供了三种定位方法:by index, name, or webelement. driver.s ...

  8. 【JavaScript】关于 eval()执行JavaScript语句的一次实验测试

    实验主题: eval() 函数可以计算某个字符串,并执行其中的 JavaScript 代码.该函数只接受原始字符串作为参数,如果 string 不是原始字符串,那么该方法将不作任何的改变的返回.因此请 ...

  9. selenium执行JavaScript语句:控制滚动条 聚焦元素 改变下拉选项

    1. 执行js脚本 控制滚动条 # http://www.cnblogs.com/yoyoketang/p/6128655.html In [347]: js = "window.scrol ...

随机推荐

  1. Python内置模块之configparse

    一.概述 1.1.处理的文件形式 configparse 主要是用来处理类似于windows的 ini文件,这个文件的特点是有多个节(section),每个节下会存储多个k=v的值 如下配置 [har ...

  2. Android 基础一 TextView,Style样式,Activity 传值,选择CheckBox 显示密码

    1.修改TextView字体 mTextView = (TextView) findViewById(R.id.textview1); mTextView.setText("I am her ...

  3. Actor消息发送及等待结果关键字

    class Task extends Actor{ override def act(): Unit = { while(true){ receive({ case SmTask(file) => ...

  4. golang 如何将imagemagick 和golang 打包到docker 环境中

    公司最近开发了个项目,用到了imagemagick 和golang 环境,在我本地机上开发妥妥的,结果准备部署到线上环境的时候,出现了大坑,尝试了无数次后,最后还是解决了,官方说有问题也不说清楚点,一 ...

  5. cJSON源码分析

    JSON (JavaScript Object Notation) 是一种常见使用的轻量级的数据交换格式,既有利于人工读写,也方便于机器的解析和生成. 关于JSON格式的定义,参看网站[1].在该网站 ...

  6. 咸鱼入门到放弃4——Http协议

    一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...

  7. 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)

    原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...

  8. 在'for'循环中获取索引

    ints = [8, 23, 45, 12, 78] 当使用循环遍历它时,在这种情况下如何访问循环索引,从1到5? 最普遍的办法是设置索引变量(通常在C或PHP等语言中使用),但这被认为是非pytho ...

  9. 对.zip格式的文件进行解压缩

    //第一个参数就是需要解压的文件,第二个就是解压的目录public static boolean upZipFileDir(File zipFile, String folderPath) { Zip ...

  10. Kali Linux常用服务配置教程启动DHCP服务

    Kali Linux常用服务配置教程启动DHCP服务 通过前面的介绍,DHCP服务就配置好了.接下来,用户就可以使用该服务器来获取IP地址了.下面将对前面配置的服务进行测试. 1.启动DHCP服务 如 ...