python的webdriver应用

本文总结如何使用python的webdriver插件,应用自动化测试以及爬虫抓取数据。

工具选择

  1. 谷歌版本下载:https://www.iplaysoft.com/tools/chrome/

  1. webdriver版本:http://npm.taobao.org/mirrors/chromedriver/

https://chromedriver.storage.googleapis.com/index.html

webdriver和谷歌的版本需要对应,比如谷歌的版本是109,就得下载109版本的webdriver

  1. vscode开发工具:https://code.visualstudio.com/

  1. python3.7:https://www.python.org/downloads/

vscode的python插件

1、首先安装python3.7软件

window的cmd下,输入python若出现以下的提示,就是安装完成。

2、安装python插件

点击左侧栏Extension (或输入 Ctrl + shift + X) 进入插件面板。

3、创建venv虚拟目录

该目录下的文件,独立存放python的第三方软件包。比如在D盘新建一个文件夹venv,在vscode终端中运行以下命令。

D:                      #进入D盘
md venv                 #新建venv文件夹
python -m venv /venv    #使用Python创建venv环境
cd /venv
source bin/activate     #激活venv环境,可以看到虚拟环境中的 Package 只有最基础的 pip、setuptools
cd /venv
deactivate              #退出venv环境

使用pyvenv.cfg简化venv的开关,这样,vscode在运行相关Python程序的时候,就能自动开关venv环境了。

打开vscode,使用快捷键ctrl+shift+’ 或 菜单栏-terminal-new terminal,打开终端

D:
cd /venv
source bin/activate
deactivate

通常,vscode就会在该目录下,自动创建一个pyvenv.cfg文件。

今后只要用vscode打开这个目录,直接运行Python程序,就会自动切换到venv模式下运行。

到这里就可以使用python自带pip工具,安装一个第三方软件selenium

pip3 install selenium

第一支脚本

webdriver是selenium的组件,Selenium 是一个 Web 的自动化测试工具,最初是为网站自动化测试而开发的。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。它支持所有主流的浏览器(包括 IE、Firefox、Safari、Opera 和 Chrome 等)。

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

class testlogin:
    def __init__(self):
        self.driver = webdriver.Chrome()
        self.driver.get("www.baidu.com")
if __name__ == "__main__":
    test=testlogin()

当然啦,也可以使用无界面形态。Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。相比于现代浏览器,Headless Chrome 更加方便测试 web 应用,获得网站的截图,做爬虫抓取信息等。相比于较早的 PhantomJS 等,Headless Chrome 则更加贴近浏览器环境

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

class testlogin:
    def __init__(self):
        #=====改写部分====begin
        chrome_options = webdriver.ChromeOptions()
        # 增加无界面选项
        chrome_options.add_argument('--headless')
        # 如果不加这个选项,有时定位会出现问题
        chrome_options.add_argument('--disable-gpu')
        #=====改写部分====end
        self.driver = webdriver.Chrome(options=chrome_options)
        self.driver.get("www.baidu.com")
if __name__ == "__main__":
    test=testlogin()

初识selenium

Selenium 提供了以下几种定位元素的方法:

描述

查找一个元素

查找多个元素

通过 ID 定位元素

find_element_by_id()

find_elements_by_id()

通过 Name 定位元素

find_element_by_name()

find_elements_by_name()

通过 XPath 定位元素

find_element_by_xpath()

find_elements_by_xpath()

通过完整链接文本定位超链接

find_element_by_link_text()

find_elements_by_link_text()

通过部分链接文本定位超链接

find_element_by_partial_link_text()

find_elements_by_partial_link_text()

通过标签名定位元素

find_element_by_tag_name()

find_elements_by_tag_name()

通过类名定位元素

find_element_by_class_name()

find_elements_by_class_name()

通过CSS选择器定位元素

find_element_by_css_selector()

find_elements_by_css_selector()

也可以用find_element统一函数写法,再在参数里声明通过什么方式定位元素,比如

find_element(By.ID,’元素ID’) 对应 find_element_by_id(‘元素ID’)

如何找到元素

比如登录百度账号,点击登录按钮,在浏览器上按下F12,按下图依次点击。

最后找到id=s-top-loginbtn,就是需要找的id元素,于是脚本就可以做以下的修改。

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

class testlogin:
    def __init__(self):
        chrome_options = webdriver.ChromeOptions()
        # 增加无界面选项
        chrome_options.add_argument('--headless')
        # 如果不加这个选项,有时定位会出现问题
        chrome_options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(options=chrome_options)
        self.driver.get("www.baidu.com")
    #=====新增部分====begin
    def loginClick(self):
        loginbtn = self.driver.find_element(By.ID,'s-top-loginbtn')        
        loginbtn.click()        
    #=====新增部分====end

if __name__ == "__main__":
    test=testlogin()
    test.loginClick()

一些高阶写法

1、如何跳转页面

需要准确跳转至页面,才能取到元素。

第一种情况:同一页面里有多个frame的话,就得找到对应的frame才行。

#    转到页面
    def switchIframe(self,src):
        #返回到主窗体
        self.driver.switch_to.default_content()
        iframes = self.driver.find_elements(By.TAG_NAME,"iframe")
        iframe = None
        for frm in iframes:
            if re.search(src,frm.get_attribute("src"))!=None:
                iframe=frm     
        self.driver.switch_to.frame(iframe)

第二种情况,同时找开了多个页面

    def switchWindow(self,url):
        windows = self.driver.window_handles
        for w in windows:
            self.driver.switch_to.window(w)
            if self.driver.current_url.startswith(url):
#                print(self.driver.title)
                break
        #有时只需要找开最后一个页面。
        self.driver.switch_to.window(self.driver.window_handles[-1])
        self.driver.maximize_window()

2、xpath写法详解

其实xpath用法比较复杂,一般只会用到第1,2,3点。第4,5,6点需要的时候再查找的。

2.1基本用法:

//tagname[@attribute=‘value’]

其中,tagname表示标签名称,@后面跟随属性名称,等号后面是属性值。如果需要查找多重下级,则在父级的xpath路径后继续追加定位,例如://div[@id=’car_genre_id’]/div/div,表示 id是car_genre_id的div元素的子节点div的子节点div。

2.2xpath的绝对路径和相对路径

1)单斜线‘/’代表绝对路径,表示该符号后面的元素是上一级节点的子节点的一个,只能一级级按序向下查询,不能跳级;

2)双斜线’//’代表相对路径,表示下级任何子节点或者任何嵌套子节点中的一个,可以跳级;

  举个栗子,在路径//div[@id=’root’]/input中,表示越过所有父节点,直接在整个html页面中查找id是’root’的div元素,因为div标签前是代表相对定位的双斜线’//’;而对于input标签来说,它必须是id是’root’的div的一级子节点,它和div中间不能越过其他的层级,因为input标签前是代表绝对路径的单斜线’/’ 。

2.3如何获取元素的xpath路径

  大多浏览器的开发者模式中都具备了输出元素xpath路径的功能。以chrome为例,点击F12后,在DOM树中选中元素,右键> Copy > CopyXpath后,在记事本上黏贴,即可得到该元素的xpath路径。

2.4使用contains属性查找元素

    contains表示查找属性包含该属性值value的页面标签元素,注意是包含,并不是完全等于,类似于sql查找语句中like的用法。

    语法为: //tagname[contains(attribute1,’value1′) and contains(attribute2,’value2′) and … ]

    举个例子,路径 //div[@id=”root”]//div[contains(text(),’共’] ,表示在id是’root’的div中,越过层级关系,查找文本信息包含”共”的div元素;

    路径//div[@id=’root’]//div[contains(className,’ant-Btn’)], 表示在id是’root’的div中,越过层级关系,查找className属性中包含’ant-Btn’属性的元素;

2.5 查找父级节点和平级节点

2.5.1父节点定位子节点:

# 1.串联寻找
print driver.find_element_by_id('B').find_element_by_tag_name('div').text
# 2.xpath父子关系寻找
print driver.find_element_by_xpath("//div[@id='B']/div").text
# 3.css selector父子关系寻找
print driver.find_element_by_css_selector('div#B>div').text
# 4.css selector nth-child
print driver.find_element_by_css_selector('div#B div:nth-child(1)').text
# 5.css selector nth-of-type
print driver.find_element_by_css_selector('div#B div:nth-of-type(1)').text
# 6.xpath轴 child
print driver.find_element_by_xpath("//div[@id='B']/child::div").text driver.quit()

2.5.2由子节点定位父节点:

这里我们有两种办法,第1种是 .. 的形式,就像我们知道的,. 表示当前节点,.. 表示父节点;第2种办法跟上面一样,是xpath轴中的一个:parent,取当前节点的父节点。这里也是css selector的一个痛点,因为css的设计不允许有能够获取父节点的办法(至少目前没有)

# 1.xpath: `.`代表当前节点; '..'代表父节点
print driver.find_element_by_xpath("//div[@id='C']/../..").text
# 2.xpath轴 parent
print driver.find_element_by_xpath("//div[@id='C']/parent::*/parent::div").text

2.5.3由弟弟节点定位哥哥节点

# 1.xpath,通过父节点获取其哥哥节点
print driver.find_element_by_xpath("//div[@id='D']/../div[1]").text
# 2.xpath轴 preceding-sibling
print driver.find_element_by_xpath("//div[@id='D']/preceding-sibling::div[1]").text

2.5.4由哥哥节点定位弟弟节点

# 1.xpath,通过父节点获取其弟弟节点
print driver.find_element_by_xpath("//div[@id='D']/../div[3]").text
# 2.xpath轴 following-sibling
print driver.find_element_by_xpath("//div[@id='D']/following-sibling::div[1]").text
# 3.xpath轴 following
print driver.find_element_by_xpath("//div[@id='D']/following::*").text
# 4.css selector +
print driver.find_element_by_css_selector('div#D + div').text
# 5.css selector ~
print driver.find_element_by_css_selector('div#D ~ div').text

2.6使用xpath定位元素时需要注意的地方

  1)保证xpath路径的唯一性。

    一定要保证xpath路径在页面中是唯一的。如果不太确定,可以在chrome的开发者工具打开的情况下,点击ctrol+F,在弹出的输入框中输入xpath

的路径,观察当前页面下,以该路径查找到的元素是不是只有一个;

  2)尽量不要使用通配符*

    *表示可以是当前页面中的任意标签,这样在查找时会增大负载,尽量准确地写出标签名称

  3)建议使用相对路径定位

    如果前面页面的元素结构发生调整,那么之前的绝对定位就会作废。而使用相对路径,可以减少定位对页面HTML元素结构的依赖性,且相对路径

往往长度较短,更加准确美观。在优化定位方式时,可以将此原则作为参考。

3、执行js脚本

有时直接用selenium接口操作元素失效,不妨尝试直接执行js脚本。

    def executeJs(self):
        jsStr = "document.getElementById('append').getElementsByTagName('li')[0].click()"
        self.driver.execute_script(jsStr)

4、等待元素出现再操作

有时某个元素需等待一段时间才会出现,如果用time.sleep(20000),等待20秒,再执行点击操作,也可以,只是有点low;有时网络没有延迟或页面响应较快,不用等20秒,而是等1秒就出现呢,为了保证元素出现,程序每次都会等待20秒,这样等待时长也是挺难受的。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
#    设置等待20秒超时时间,20秒内,如果出现id='append',就直接执行点击操作
def waitForShow(self):
        append = WebDriverWait(self.driver, 20).until(expected_conditions.presence_of_element_located((By.ID, "append")))
        append.click()

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年6月16日
下一篇 2023年6月16日

相关推荐