• selenium自动化测试python


    一。环境部署

    1.selenium安装 

    pip3 install selenium

    1.安装浏览器驱动

    WebDriver 需要通过浏览器驱动来与浏览器交互,以下列出几种常用的浏览器驱动下载地址:

    Chrome:

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

    Firefox:
    https://github.com/mozilla/geckodriver/releases

    Edge:
    https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver

    Safari:
    https://webkit.org/blog/6900/webdriver-support-in-safari-10

    使用不同的浏览器,需要下载对应版本驱动,并且确保驱动文件如chromedriver.exe放到你的系统环境PATH中,这里我将它放到python安装目录下。D:Python36chromedriver.exe

    selenium思维导图详细使用介绍:

    二。元素定位:

     1 <!DOCTYPE html>
     2 <html lang="zh-CN">
     3 <body>
     4     <h1 class="head_title">你好,<span id="world">世界!</span></h1>
     5     <a href="https://www.kancloud.cn/@guanfuchang" target="_blank">我的看云首页</a>
     6     <br/>
     7     <br/>
     8     <div id="login_form" class="login">
     9         用户名:<input name="username" class="ptqa user_name" placeholder="用户名" value="Milton" required/>
    10         密码:<input type="text" name="password" class="ptqa pwd" placeholder="密码" value="ptqa" required/>
    11         地区:
    12         <select class="city">
    13             <option value="gz">广州</option>
    14             <option value="fs">佛山</option>
    15             <option value="mm">茂名</option>
    16             <option value="hb">襄樊</option>
    17         </select>
    18 
    19         <br>
    20         <br>
    21         <button>提交</button>
    22         <br>
    23 
    24     </div>
    25 </body>
    26 </html>
    环境准备
     1 在同个目录下创建一个find_location.py文件,初始化工作
     2 from selenium import webdriver
     3 import os
     4 
     5 # 创建Chrome驱动实例
     6 driver = webdriver.Chrome()
     7 
     8 # 启动浏览器并且导航到指定URL
     9 # 这里为了覆盖更多的元素定位,我自己编写了一个本地的hello.html文件。
    10 file_path = 'file:///' + os.path.abspath('hello.html')
    11 driver.get(file_path)
    初始化工作
    find_element_by_class_name(self, name):
    find_elements_by_class_name(self, name):
    # 定位class名称为“head_title"的元素
    head_title = driver.find_element_by_class_name("head_title")
    print(head_title.text)
    通过class定位
    find_element_by_id(self, id_):
    find_elements_by_id(self, id_):
    # 定位id为“world”的元素
    world = driver.find_element_by_id("world")
    print(world.text)
    通过id定位
    find_element_by_name(self, name):
    find_elements_by_name(self, name):
    # 定位name为“username”的元素
    username = driver.find_element_by_name("username")
    print(username.get_attribute("value"))
    通过name属性定位
    1 find_element_by_tag_name(self, name):
    2 find_elements_by_tag_name(self, name):
    3 # 定位标签为<button>的元素
    4 submit_btn = driver.find_element_by_tag_name("button")
    5 print(submit_btn.text)
    通过标签名定位
     1 find_element_by_link_text(self, link_text):
     2 find_element_by_partial_link_text(self, link_text):
     3 
     4 # 定位链接文本完全匹配“我的看云首页”的元素
     5 kancloud = driver.find_element_by_link_text("我的看云首页")
     6 print(kancloud.get_attribute("href"))
     7 
     8 # 定位链接文本部分匹配“看云首页”的元素
     9 kancloud = driver.find_element_by_partial_link_text("看云首页")
    10 print(kancloud.get_attribute("href"))
    通过链接文本定位
     1 find_element_by_xpath(self, xpath):
     2 find_elements_by_xpath(self, xpath):
     3 
     4 # xpath定位,相对路径定位用户名输入框
     5 username = driver.find_element_by_xpath("//body/div/input")
     6 print(username.get_attribute("value"))
     7 
     8 # xpath定位,相对路径与属性结合 定位密码输入框
     9 password = driver.find_element_by_xpath("//input[@name='password']")
    10 print(password.get_attribute("value"))
    11 
    12 # xpath定位,多个属性结合 定位密码输入框
    13 password = driver.find_element_by_xpath("//input[@name='password'][@type='text']")
    14 print(password.get_attribute("value"))
    通过xpath定位
     1 find_element_by_css_selector(self, css_selector):
     2 find_elements_by_css_selector(self, css_selector):
     3 
     4 # css选择器,标签+属性 定位用户名输入框
     5 username = driver.find_element_by_css_selector("input[name='username']")
     6 print(username.get_attribute("value"))
     7 
     8 复制
     9 # css选择器,标签+class类名 定位用户名输入框
    10 username = driver.find_element_by_css_selector("input.user_name")
    11 print(username.get_attribute("value"))
    12 
    13 # css选择器,标签+多个class类名,定位密码输入框,注意不要空格,空格代表下一级子元素
    14 password = driver.find_element_by_css_selector("input.ptqa.pwd")
    15 print(password.get_attribute("value"))
    16 
    17 # css选择器,id+多个class类名,定位密码输入框
    18 password = driver.find_element_by_css_selector("#login_form .ptqa.pwd")
    19 print(password.get_attribute("value"))
    20 
    21 # css选择器,多级class类名,定位密码输入框
    22 password = driver.find_element_by_css_selector(".login .ptqa.pwd")
    23 print(password.get_attribute("value"))
    24 
    25 # css选择器,class类名+属性,定位密码输入框
    26 password = driver.find_element_by_css_selector(".login .ptqa[name='password']")
    27 print(password.get_attribute("value"))
    28 
    29 #css 选择器,根据父子关系,定位密码输入框
    30 password = driver.find_element_by_css_selector("div[id='login_form']>input[name='password']")
    31 print(password.get_attribute("value"))
    32 
    33 # css 选择器,根据兄弟关系,定位密码输入框
    34 password = driver.find_element_by_css_selector("input[name='username']+input")
    35 print(password.get_attribute("value"))
    通过css选择器定位
     1 上面的所有元素定位 find_element_by_xxx和find_elements_by_xxx调用的结果,实际上都是在调用以下两种方法,我们也可以直接调用一下两种方法即可。
     2 
     3 find_element(self, by=By.ID, value=None):
     4 find_elements(self, by=By.ID, value=None):
     5 
     6 class By(object):
     7     """
     8     Set of supported locator strategies.
     9     """
    10 
    11     ID = "id"
    12     XPATH = "xpath"
    13     LINK_TEXT = "link text"
    14     PARTIAL_LINK_TEXT = "partial link text"
    15     NAME = "name"
    16     TAG_NAME = "tag name"
    17     CLASS_NAME = "class name"
    18     CSS_SELECTOR = "css selector"
    19 
    20 
    21 例如:
    22 from selenium.webdriver.common.by import By
    23 # 根据id,定位id为“world”的元素
    24 world = driver.find_element(By.ID,"world")
    25 print(world.text)
    26 
    27 # xpath定位,相对路径与属性结合 定位密码输入框
    28 password = driver.find_element(By.XPATH,"//input[@name='password']")
    29 print(password.get_attribute("value"))
    30 
    31 # css选择器,标签+属性 定位用户名输入框
    32 username = driver.find_element(By.CSS_SELECTOR,"input[name='username']")
    33 print(username.get_attribute("value"))
    通用的终极定位语法

    三。元素操作:

     1 清除文本输入框
     2 clear(self)
     3 
     4 点击元素
     5 click(self)
     6 
     7 提交表单
     8 submit(self)
     9 
    10 发送信息
    11 send_keys(self, *value)
    12 
    13 获取元素的文本
    14 text
    WebElement 中常见的元素操作
     1 获取元素属性
     2 get_attribute(self, name)
     3 
     4 判断元素可见
     5 is_displayed(self)
     6 
     7 判断元素可用
     8 is_enabled(self)
     9 
    10 判断元素是否被选中
    11 is_selected(self)
    WebElement 中常见的元素属性
    1 获取元素位置
    2 location
    3 
    4 获取元素大小
    5 size
    6 
    7 获取元素的文本
    8 text
    WebElement 中常见的属性方法
    1 ActionChains中提供一些复杂操作,如鼠标移动,鼠标按钮操作,按键操作和上下文菜单交互等,这些操作在实际运用中其实复杂操作并不常用,这里只简单介绍一个元素拖拽的例子,其他方法,请自行查看源码。
    2 
    3 element = driver.find_element_by_name("source")
    4 target = driver.find_element_by_name("target")
    5 
    6 from selenium.webdriver import ActionChains
    7 action_chains = ActionChains(driver)
    8 # 拖拽(在元素A上按住鼠标左键不放,拖动到元素B上,然后松开鼠标)
    9 action_chains.drag_and_drop(element, target).perform()
    ActionChains 中的复杂操作

    四。浏览器当行操作:

    五。元素等待;

    六。 示例演示

    获取页面源码数据:
    通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。

     动作链:它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。

    from selenium import webdriver
    from selenium.webdriver import ActionChains
    import time
    browser = webdriver.Chrome()
    url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
    browser.get(url)
    browser.switch_to.frame('iframeResult')
    source = browser.find_element_by_css_selector('#draggable')
    target = browser.find_element_by_css_selector('#droppable')
    actions = ActionChains(browser)
    # actions.drag_and_drop(source, target)
    # actions.perform() #执行动作链
    actions.click_and_hold(source)
    time.sleep(3)
    for i in range(5):
        actions.move_by_offset(xoffset=17,yoffset=0).perform()
        time.sleep(0.5)
    
    actions.release()
    示例:实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处

    浏览器前进后退演示:

    import time
    from selenium import webdriver
     
    browser=webdriver.Chrome()
    browser.get('https://www.baidu.com')
    browser.get('https://www.taobao.com')
    browser.get('http://www.sina.com.cn/')
     
    browser.back()
    time.sleep(10)
    browser.forward()
    browser.close()
    需要:模拟浏览器的前进后退

    Cookie处理:

      使用Selenium,还可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。示例如下:

    from selenium import webdriver
     
    browser = webdriver.Chrome()
    browser.get('https://www.zhihu.com/explore')
    print(browser.get_cookies())
    browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
    print(browser.get_cookies())
    browser.delete_all_cookies()
    print(browser.get_cookies())
    cookie操作演示

    异常处理:

    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException
    
    try:
        browser=webdriver.Chrome()
        browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
        browser.switch_to.frame('iframssseResult')
    
    except TimeoutException as e:
        print(e)
    except NoSuchFrameException as e:
        print(e)
    finally:
        browser.close()
    异常处理演示

    selenium实现模拟百度搜索功能

    from selenium import webdriver
    from time import sleep
    
    #实例化一个浏览器对象
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    #基于url发起请求
    sleep(2)
    bro.get('https://www.baidu.com/')
    #实现页面标签的定位
    sleep(2)
    input_tag = bro.find_element_by_id('kw')
    input_tag.send_keys('周杰伦')
    sleep(2)
    btn = bro.find_element_by_id('su')
    btn.click()
    sleep(3)
    #获取当前浏览器打开的页面对应的源码数据
    page_text = bro.page_source
    print(page_text)
    sleep(2)
    bro.quit()
    需求:使用selenium在百度上进行数据搜索

     selenium实现无可视化展示

    from selenium.webdriver.chrome.options import Options
    from selenium import webdriver
    from time import sleep
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    
    #实例化一个浏览器对象
    bro = webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options)
    #基于url发起请求
    sleep(2)
    bro.get('https://www.baidu.com/')
    #实现页面标签的定位
    sleep(2)
    input_tag = bro.find_element_by_id('kw')
    input_tag.send_keys('周杰伦')
    sleep(2)
    btn = bro.find_element_by_id('su')
    btn.click()
    sleep(3)
    bro.save_screenshot('./1.jpg') # 进行截图保存
    #获取当前浏览器打开的页面对应的源码数据
    page_text = bro.page_source  # 爬取页面源码
    print(page_text)
    sleep(2)
    bro.quit()
    使用无可视化界面搜索并截图和爬取页面源码

     加载js文件实现动态加载浏览器数据

    滚轮向下滑动一屏的高度:window.scrollTo(0,document.body.scrollHeight)
    from selenium import webdriver
    from time import sleep
    
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    # bro = webdriver.PhantomJS(executable_path = '')
    bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
    sleep(2)
    #让滚轮向下滑动
    js = 'window.scrollTo(0,document.body.scrollHeight)'
    bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    
    a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
    a_tag.click()
    sleep(2)
    
    #源码数据就包含了所有的新闻数据
    page_text = bro.page_source
    
    with open('./wangyi.html','w',encoding='utf-8') as fp:
        fp.write(page_text)
    需求:网易新闻,实现滚轮滑动加载更多数据

    这里引出一个无界面浏览器:phantomjs实现了一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canvas/svg绘制等功能都很完备,在页面抓取、页面输出、自动化测试等方面有广泛的应用。

    驱动包百度共享下载:链接:https://pan.baidu.com/s/15j5RpkVAryKRa_VFrjdqDw      提取码:zptn 

    from selenium import webdriver
    from time import sleep
    
    # bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    bro = webdriver.PhantomJS(executable_path = './phantomjs.exe')  #这里输入的是phantomjs.exe驱动路径
    bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
    sleep(2)
    #让滚轮向下滑动
    js = 'window.scrollTo(0,document.body.scrollHeight)'
    bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    
    a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
    a_tag.click()
    sleep(2)
    
    #源码数据就包含了所有的新闻数据
    page_text = bro.page_source
    
    with open('./wangyi.html','w',encoding='utf-8') as fp:
        fp.write(page_text)
    需求:通过无界面浏览器爬取数据

    PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现

    from selenium import webdriver
    import time
    
    # phantomjs路径
    path = r'PhantomJS驱动路径'
    browser = webdriver.PhantomJS(path)
    
    # 打开百度
    url = 'http://www.baidu.com/'
    browser.get(url)
    time.sleep(3)
    browser.save_screenshot(r'phantomjsaidu.png')
    
    # 查找input输入框
    my_input = browser.find_element_by_id('kw')
    # 往框里面写文字
    my_input.send_keys('美女')
    time.sleep(3)
    #截屏
    browser.save_screenshot(r'phantomjsmeinv.png')
    
    # 查找搜索按钮
    button = browser.find_elements_by_class_name('s_btn')[0]
    button.click()
    time.sleep(3)
    browser.save_screenshot(r'phantomjsshow.png')
    time.sleep(3)
    browser.quit()
    需求:PhantomJS截图演示

    selenium实现切换iframe:

    from selenium import webdriver
    from time import sleep
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    url = 'https://qzone.qq.com/'
    bro.get(url=url)
    #将当前页面切换到了指定的iframe中,后续才可以定位到iframe中存在的标签
    bro.switch_to.frame('login_frame')
    a_tag = bro.find_element_by_id('switcher_plogin')
    a_tag.click()
    sleep(3)
    
    bro.quit()
    需求:模拟QQ空间登录切换iframe
    import requests
    from selenium import webdriver
    from lxml import etree
    import time
    
    driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver')
    driver.get('https://qzone.qq.com/')
    #在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素,直接定位是定位是定位不到的。这个时候就需要通过switch_to_frame()方法将当前定位的主体切换了frame 里。
    driver.switch_to.frame('login_frame')
    driver.find_element_by_id('switcher_plogin').click()
    
    #driver.find_element_by_id('u').clear()
    driver.find_element_by_id('u').send_keys('328410948')  #这里填写你的QQ号
    #driver.find_element_by_id('p').clear()
    driver.find_element_by_id('p').send_keys('xxxxxx')  #这里填写你的QQ密码
        
    driver.find_element_by_id('login_button').click()
    time.sleep(2)
    driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    time.sleep(2)
    driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    time.sleep(2)
    driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
    time.sleep(2)
    page_text = driver.page_source
    
    tree = etree.HTML(page_text)
    #执行解析操作
    li_list = tree.xpath('//ul[@id="feed_friend_list"]/li')
    for li in li_list:
        text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()')
        text = ''.join(text_list)
        print(text+'
    
    
    ')
        
    driver.close()
    需求:登录QQ空间,爬取数据代码

    selenium规避被检测识别

    现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 
    undefined。而使用selenium访问则该值为true。那么如何解决这个问题呢?
    
    只需要设置Chromedriver的启动参数即可解决问题。在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:
    from selenium.webdriver import Chrome
    from selenium.webdriver import ChromeOptions
    
    option = ChromeOptions()
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    driver = Chrome(options=option)
    from selenium import webdriver
    from time import sleep
    import time
    
    if __name__ == '__main__':
        url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='
        # 发起请求前,可以让url表示的页面动态加载出更多的数据
        path = r'C:UsersAdministratorDesktop爬虫授课day05ziliaophantomjs-2.1.1-windowsinphantomjs.exe'
        # 创建无界面的浏览器对象
        bro = webdriver.PhantomJS(path)
        # 发起url请求
        bro.get(url)
        time.sleep(3)
        # 截图
        bro.save_screenshot('1.png')
    
        # 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息))
        js = 'window.scrollTo(0,document.body.scrollHeight)'
        bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码
        time.sleep(2)
    
        bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码
        time.sleep(2)
        bro.save_screenshot('2.png') 
        time.sleep(2) 
        # 使用爬虫程序爬去当前url中的内容 
        html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html) 
        with open('./source.html', 'w', encoding='utf-8') as fp: 
            fp.write(html_source) 
        bro.quit()
    需求:使用懒加载爬取豆瓣网中的电影信息演示代码
  • 相关阅读:
    SQL优化大全
    程序的装入和链接
    Linux系统管理常用命令
    作业、进程、线程
    MySQL优化大全
    Linux系统结构 详解
    NoSQL数据库探讨
    操作系统内存管理——分区、页式、段式管理
    进程调度算法
    操作系统文件管理
  • 原文地址:https://www.cnblogs.com/iamjianghao/p/10559479.html
Copyright © 2020-2023  润新知