Selenium

一. 环境准备

  1. selenium库下载

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium
    
  2. 浏览器驱动下载并部署

    下载

    # 谷歌驱动     https://chromedriver.storage.googleapis.com/index.html
    # edge驱动     https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
    # 360浏览器驱动   使用对应内核版本的谷歌驱动即可
    

    部署

    # 需要将下载的驱动解压,只提取  名为 chromedriver.exe/msedgedriver.exe的文件
    将驱动文件放到项目目录下
    
  3. 使用

    #  Chrome
    
    from selenium import webdriver
    
    
    # 创建浏览器操作对象
    Driver_Path = './chromedriver.exe'
    browser = webdriver.Edge(path)
    
    # 	Edge
    
    from selenium import webdriver
    
    
    # 创建浏览器操作对象
    Driver_Path = './msedgedriver.exe'
    browser = webdriver.Edge(path)
    
    #  360浏览器
    """ 下载360内核86版本,下载chromedriver.exe 86版本 能正常驱动360浏览器 """
    
    from selenium import webdriver
    
    Browser_Path = r"F:\Box\QT\360X\360se6\Application\360se.exe" # 这里是360安全浏览器的路径
    Driver_Path = "./chromedriver.exe"
    chrome_options = webdriver.ChromeOptions()
    chrome_options.binary_location =  Browser_Path 
    browser = webdriver.Chrome(Driver_Path, chrome_options=chrome_options)
    

操作注意

定位不到(1.检查代码,2.检查等待时间,3.检查框架,4.检查滚动条)

示例模板

驱动对象:   browser = webdriver.Edge("msedgedriver.exe")
浏览器打开: browser.get("https://www.baidu.com")
元素定位:   元素对象 = browser.find_element(By.模式, '值')         单元素定位
          元素对象 = browser.find_elements(By.模式, '值')[索引]   多元素单选择定位     (返回列表)
内容发送:   元素对象.send_keys("图片")  //还可以带上参数模拟按下某个按键  ,Keys.ENTER
按钮点击:   元素对象.click()
浏览器退出 : browser.quit() /close()关闭当前页面

--------------------------------------------------------------------------------------------------------------
# 获取
        元素对象.get_attribute('name/id/class'))  # 获取指定元素属性内容
        元素对象.tag_name  # 获取指定元素标签名
        元素对象.text  # 获取指定标签包裹的内容 <>text

# 获取页面请求信息
        browser.get_cookies()  获取cookie
        browser.current_url 获取最终url
        browser.page_source 获取页面源码

# 执行js代码
		browser.execute_script("js代码")  # 执行js代码



------------------------------------------------------------------------------------------------------------
#####反爬虫措施
# 绕过window.navigator.webdriver控件检测
option = Options()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_argument('--disable-blink-features=AutomationControlled')
 
driver = webdriver.Chrome()

二. 元素定位

#  示例

from selenium import webdriver
from selenium.webdriver import Keys
from selenium.webdriver.common.by import By  # 定位元素模块


browser = webdriver.Edge("msedgedriver.exe")  #  定义一个驱动对象
browser.get("https://www.baidu.com")  # 打开浏览器页面


browser.find_element(By.ID, 'kw').send_keys("图片")  # 定位到输入框  
browser.find_element(By.ID, 'su').click()        # 定位到确定按钮    

# 退出浏览器
browser.quit()

七大定位

返回值为一个元素对象 定位不到(1.检查代码,2.检查等待时间,3.检查框架,4.检查滚动条)

  1. id定位
browser.find_element(By.ID, 'ID值')  
是整个HTML页面中唯一的,可以通过ID属性来唯一定位一个元素,是元素定位的首选方式 (唯一的)               
  1. name定位
browser.find_element(By.NAME, 'Name值')
根据元素的name来定位属性,但name不是唯一的                (默认定位第一个)            
  1. class定位
browser.find_element(By.CLASS_NAME, 'Class值')  
根据class定位属性,并不是唯一的                         (默认定位第一个)
                 
  1. tag定位
browser.find_element(By.TAG_NAME, 'Tag值')
元素的标签名来定位元素,并不是唯一的                      (默认定位第一个)           
  1. link_text定位
# link_text定位  超链接标签文本内容定位   (匹配完整的文本内容)              (定位唯一)
            browser.find_element(By.LINK_TEXT, 'Link_text值')
# link_text模糊  超链接标签文本内容定位   (精准/模糊的文本内容定位)          (默认定位第一个)
"""             time.sleep(1)      给浏览器一些时间进行页面加载                   """
"""             browser.find_element(By.PARTIAL_LINK_TEXT, 'Link_text值')    """
""" 注意:在浏览器从搜索引擎上访问网页后,进行链接文本匹配搜索之前,需要设置延迟(给浏览器一点加载时间)"""
  1. xpath路径定位
#    标签路径结构定位,路径是准确的,唯一的。
browser.find_element(By.XPATH, 'xpath路径值')                         
                                 .                  当前节点                  
                                 ..                 当前节点的父节点           
                                 /a                 根下为a的标签              
                                /a/b                a下为b的标签               
                                //a                 所有为a的标签              
                                //a/b               所有父元素为a的b标签       
                                //a[@属性='值']      标签下属性匹配   (第一个)    
                                //a[@属性='值' and @属性='值')]  标签下组合属性匹配   
                                //a[@属性='值')]/b              父级下定位子级      
time.sleep(1)   文本     //a[text()="内容"]     完整文本信息匹配  (第一个)     
time.sleep(1)   文本     //a[contains(text(),"部分内容")]  部分文本信息匹配    
  1. css选择器定位
#     css样式选择定位 (效率高,语法简单) ====> selector选择器
"""             browser.find_element(By.CSS_SELECTOR, 'xpath路径值')                      """
"""                                         ID选择器       #id                            """
"""                  (默认第一个)             Class选择器    .class                          """
"""                  (默认第一个)             标签选择器      tab                             """
"""                  (匹配任何)               通用选择器      *                              """
"""                  (匹配所有符合元素)         多元素选择器     a,b    (逗号)                  """
"""                  (匹配所有a的后代元素b)     后代选择器       a 空格 b                       """
"""                  (匹配父元素中所有的子元素)  子元素选择器      a > b                         """
"""                  (匹配最接近父元素的子元素)  最近选择器        a + b  (1个)                  """
"""                  (匹配父元素后所有同级的子元素) 同元素器        a ~ b                        """
"""                  (匹配指定标签下符合属性条件的元素)            标签名[属性名='属性值']          """
"""                  (匹配属性值以a开头的标签元素)                标签名[属性名^='a']             """
"""                  (匹配的值以a结尾的指定标签名的元素)           标签名[属性名$='a']             """
"""                  (匹配属性的值包含a的指定标签的元素)           标签名[属性名*='a']             """
"""                  (属性1的值为a,属性2的值包含b)              标签名[属性1='a'][属性2*='b']    """
"""             browser.find_elements(By.CSS_SELECTOR, 'xpath路径值')                      """
"""browser.find_elements(By.CSS_SELECTOR, '#a,.b')[索引]       多元素选择器 (多个元素之间选择)  """

多元素选择器

# browser.find_elements(By.模式, '值')[索引]      # 还可以后面接参数  .click()等   多元素单选择定位     (返回列表)
#当有多个属性相同的元素时使用,利用[索引]来选择单个元素

获取标签指定属性值

获取标签指定属性值    元素对象.get_attribute('属性名')  将返回属性值
                   元素对象.text  返回标签内的内容

三.元素等待

from selenium import webdriver
from time import sleep

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By


等待的意义:    
      在浏览器加载新的页面时,需要时间加载,如果没加载完就进行信息的获取,那么就会报错(匹配不到)。在这个情况下就需要设置等待
      等待的方式: 
          强制等待  time.sleep(0)      缺点:等待时间不好控制,如果短了依然会报错。
                                          如果时间长了但是已经加载完了,那么就会浪费时间
                                          
          隐式等待:browser.implicitly_wait(0)        全局最大超时时间  (整个页面)
                      整个程序运行过程有效,如果在规定时间内没有加载完就会报错,如果在规定时间内加载完成,自动执行后面代码。
                      缺点:  要全部加载完毕才能执行后面代码,影响效率  (该设置之前的页面)
                  
           显示等待: 明确的等到某个元素的出现或者某个元素的可点击等。
                       等到就可以返回元素对象,在超时时间到达之后仍没有等到,就抛出异常.
                       (直到元素出现才操作,如果超时则报异常)    
                       优点: 指定等待的对象  
                            
                            需要导入模块:
                            from selenium.webdriver.support.ui import WebDriverWait
                            from selenium.webdriver.support import expected_conditions as ec
                            from selenium.webdriver.common.by import By        
                                      
                            expected_conditions(提供一系列场景判断的方法):  
                            判断一个元素是否存在,如何判断alert弹窗出来了,如何判断动态的元素等等一系列的判断。
                            ec.title_is("判断内容")(browser)  //判断当前页面的title是否完全等于预期字符串,返回布尔值
                                            


browser = webdriver.Edge("msedgedriver.exe")
browser.get("https://www.baidu.com")
browser.find_element(By.ID, "kw").send_keys("热点新闻")
browser.find_element(By.ID, 'su').click()

# 第一种  添加等待,等待页面加载完毕  (不加会导致匹配不到而报错)
# sleep(1)


# 第二种  添加等待,等待页面加载完毕  (不加会导致匹配不到而报错)
# browser.implicitly_wait(3)


# 第三钟  添加等待,等待页面加载完毕  (不加会导致匹配不到而报错)   查元素(等待包含"wd"这个元素加载完以后,再进行后面的操作)
# element = WebDriverWait(browser, 10, 0.5, ignored_exceptions=None).until(ec.presence_of_element_located((By.ID, "kw")),"找不到")
#                        驱动    timeout最长超时时间
#                                    poll_frequency检测时间间隔
#                                         ignored_exceptions超时后的异常信息(默认抛出NoSuchElementException异常)  ####可以不加
#          WebDriverWait()提供两个方法用于处理等待的条件: until(method,message=""):   每隔一段时间(poll_frequency)调用method.直到返回值不为Fasle或不为空
#                                                   (查找元素是否存在)             method:需要执行的method
#                                                                               message: 抛出异常时的文案,会返回TimeoutException,表示超时
#                                                   until_not(method,message=""): 调用该方法提供的驱动程序作为一个参数,直到返回值为False_
# element.click()

browser.find_element(By.PARTIAL_LINK_TEXT, '看看头条').click()  # 匹配超链接文本内容(模糊匹配)的元素
sleep(2)
browser.quit()

四.场景判断

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec  # 场景判断模块



expected_conditions(提供一系列场景判断的方法  简写ec):  判断一个元素是否存在,如何判断alert弹窗出来了,如何判断动态的元素等等一系列的判断。
    用法1:       ec.title_is("判断内容")(browser)       //判断当前页面的title是否完全等于预期字符串,返回布尔值
    用法2:       ec.title_contains("判断内容")(browser) //判断当前页面的title是否包含预期字符串,返回布尔值
    用法3:       ec.presence_of_element_located      //判断某个元素是否被加载成功(加到了dom树里),并不代表该元素一定可见

五.浏览器常用操作

1.基本

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By

"""
浏览器常用操作  ====> 浏览器驱动.操作()
1.   get()   打开浏览器指定网页
2.   close()  关闭当前窗口--->模拟点击浏览器关闭按钮
3.   quit()   关闭浏览器驱动对象--->关闭所有程序启动的窗口


4.  maximize_window()               最大化浏览器窗口---->模拟浏览器最大化按钮       
    minimize_window()               最小化
5.  set_window_size(width,height)   设置浏览器窗口大小
6.  set_window_position(x,y)        设置浏览器窗口位置


7.  back()                          后退---->模拟浏览器后退按钮
8.  forward()                       前进---->模拟浏览器前进按钮
9.  refresh()                       刷新---->模拟浏览器刷新

10. title()                         获取页面title    要使用print打印
11. current_url                     获取当前页面URL   要使用print打印
"""

2.选中,取消选中

import time
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains  # 处理弹窗的模块

# 针对单选框,复选框的处理
"""
     单/复选框:        
     1.单/复选框的勾选    (要先定位,再使用click勾选)元素对象.click
     2.判断是否勾选     元素对象.is_selected()   返回布尔值
  ----------------------------------------------------------------------------------------------------------------------   
     
     Tab键与复选框的组合  :  Tab键相当于多个复选框之间来回切换一次 (要先定位到其中一个复选框)   send_keys(Keys.按键)
                           Tab键将选中已经选中的单选按钮
     空格键与复选框的组合  :  空格键就相当于点击一次的操作      (要先定位到其中一个复选框) send_keys(Keys.按键)
  ----------------------------------------------------------------------------------------------------------------------
     
     下拉选择框:  标签             要使用下拉选择框按钮元素对象
            1.通过元素定位+click进行选择
            
            2.通过select模块进行选择      
            from selenium.webdriver.support.select import Select
            ----   Select(下拉框元素对象).select_by-index(索引)          通过索引定位
            ----   Select(下拉框元素对象).select_by_visible_text("值")   通过文本值定位
            ----   Select(下拉框元素对象).select_by_value("值")          通过value值定位 
  ----------------------------------------------------------------------------------------------------------------------          
             
"""
browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.baidu.com/")
browser.maximize_window()  # 最大化窗口
ActionChains(browser).move_to_element(browser.find_element(By.ID, "s-usersetting-top")).perform()  # 悬浮到设置按钮
browser.find_element(By.LINK_TEXT, "搜索设置").click()  # 单击下拉列表的链接,打开搜索设置界面
browser.implicitly_wait(1)  # 等待新窗口加载完成后
#   勾选单选按钮
browser.find_element(By.ID, "s1_1").click()
sleep(2)
browser.find_element(By.ID, "s1_2").click()
sleep(2)
#
browser.find_element(By.LINK_TEXT, "保存设置").click()  # 单击保存设置
browser.implicitly_wait(1)  # 等待新窗口加载完成后
browser.switch_to.alert.accept()  # 接受弹出框       =====> 弹出框处理
time.sleep(2)
browser.quit()

3.文件上传,下载

from selenium import webdriver
from time import sleep
"""
文件上传:    (再页面上有一个:  文件选择按钮,单击弹窗资源管理器来选择文件  )    要先定位到该按钮
            send_keys("文件路径")    r"路径":取消路径中的转义字符
                      注意:   该方法只针对才能使用
                      扩展:   send_keys(文本/Keys.按键/文件)

文件下载:     
         第一种:  有下载按钮/链接,点击即可下载 
            (核心代码即可实现(定位+click),  以下设置为指定浏览器的下载设置)
              1.ChromeOptions    一个配置chrome启动时属性的类,可以为chrom添加以下参数
                                                    add_experimental_option
              2.os模块
              3.下载文件
        
                使用:     options = webdriver.ChromeOptions()   # 实例化类对象
                         prefs = {
                                 'profile.default_content_settings.popups':0 ,        
                                 'download.default_directory':os.getcwd()
                                 }
                                #     设置为禁止弹出下载窗口,设置文件下载路径,os.getcwd(获取当前工作目录)
                        options.add_experimental_option('prefs',prefs)
                        
                        browers = webdriver.Chrome(options=options)
                        
                        
                        定位到下载/链接位置元素    <核心步骤>
                        下载:    click()       <核心步骤>
        
         第二种:   没有下载按钮时,通过爬虫下载图片     #  图片地址(定位+属性值获取)
                  data = requests.get("图片地址").content二进制       # 还可以  .txt文本
                  with open('文件名.扩展名','wb') as file:
                      file.write(data)
                                   


"""

4.屏幕截图

from selenium import webdriver
from time import sleep
"""   
两种方式
browser.save_screenshot('文件名.png'/指定path)               # png格式
browser.get_screenshot_as_file('文件名.png'/指定path)        # png格式
"""
browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.baidu.com")
browser.save_screenshot('文件名.png')

browser.quit()

5.移动滚动条

import time
from selenium import webdriver
from time import sleep

from selenium.webdriver import Keys
from selenium.webdriver.common.by import By

"""
当需要定位的元素位于滚动条下方时,就需要模拟滚动滚动条进行页面加载
(页面中出现滚动条的情况下,不是所有元素都能全部加载完毕,需要滚动时加载滚动区域之前的页面)
       -----------------------------------
                      scrollTop  实现滚动          该方法可以调滚动一次的距离
                      Keys实现滚动                 该方法只能一次一次按
                      scrollBy(x,y)实现滚动        较灵活  移动一次   # x:右边移动    y:下移动
       -----------------------------------

第一种:
       注意;    需要借助execute_script() 方法来执行下面的js语法
               js语法:
                     js = 'var fun=document.documentElement.scrollTop=5000'     数值为移动像素
                     browers.execute_script(js)           执行js代码



第二种:
      browers.send_keys(Keys.)      
     
第三种:   js="window.scrollBy(0,5000)"     # x:右边移动    y:下移动     直接拖动
            "window.scrollTo(x,y)"     #  直接移动到坐标点
        browser.execute_script(js) 
        
        注意:  scrollTo(x,y)   参数可以设置:          
                              移动到顶部 scrollTo(document.body.scrollHeight,0)
                              移动到底部 scrollTo(0,document.body.scrollHeight)
"""

browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://pic.netbian.com/4kmeinv/")
browser.maximize_window()  # 最大化窗口
time.sleep(1)

# 第一种
# js = 'var fun=document.documentElement.scrollTop=5000'  # 数值为移动像素
# browser.execute_script(js)  # 执行js代码

# 第二种
# browser.find_element(By.XPATH, '//*[@id="main"]/div[2]/a[2]').send_keys(Keys.DOWN)  # 寻找一个定位点,再按下“向下”键

# 第三种
js="window.scrollBy(0,5000)"     # x:右边移动    y:下移动
browser.execute_script(js)
time.sleep(3)
browser.quit()

6. 鼠标,键盘模拟操作

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By

                WebDerver中用来负责实现这些测试的类ActionChains类
模拟鼠标操作:     ====>  浏览器驱动.操作()
    元素对象 = browser.find_element(By.模式, '值')
    1. 单击    click()左键单击        |      ActionChains(驱动).context_click(定位的元素对象).perform()   右键单击
    2. 双击    ActionChains(驱动).double_click(定位的元素对象).perform()   
    3. 拖曳    ActionChains(驱动).drag_and_drop(开始位置元素对象,结束位置元素对象).perform()        开始/结束位置都是网页上目标对象的位置
    4. 移动    ActionChains(驱动).move_to_element(定位的元素对象).perform() 
    
    

模拟键盘操作:      驱动.send_keys(Keys.按键)     from selenium.webdriver.common.keys import Keys
    0.模拟键盘输入内容   send_keys("内容")
    1.模拟删除键        send_keys(Keys.Back_SPACE)
    2.模拟空格键        send_keys(Keys.SPACE)
    3.模拟制表键        send_keys(Keys.TAB)
    4.模拟esc键        send_keys(Keys.ESCAPE)
    5.模拟回车键        send_keys(Keys.ENTER)
    6.模拟全选          send_keys(Keys.CONTROL,'a')
    7.模拟复制          send_keys(Keys.CONTROL,'c')
    8.模拟剪切          send_keys(Keys.CONTROL,'x')
    9.模拟粘贴          send_keys(Keys.CONTROL,'v')

KEY键码

    key值      对应ascii码值
    NULL = '\ue000'
    CANCEL = '\ue001'  			# ^break
    HELP = '\ue002'
    BACKSPACE = '\ue003'
    BACK_SPACE = BACKSPACE		# 删除键
    TAB = '\ue004'				# TAB键
    CLEAR = '\ue005'
    RETURN = '\ue006'
    ENTER = '\ue007'			# 回车键
    SHIFT = '\ue008'			# Shift键
    LEFT_SHIFT = SHIFT			# Shift键
    CONTROL = '\ue009'
    LEFT_CONTROL = CONTROL		# Ctrl键
    ALT = '\ue00a'				# Alt键
    LEFT_ALT = ALT
    PAUSE = '\ue00b'
    ESCAPE = '\ue00c'			# ECS键
    SPACE = '\ue00d'			# 空格键
    PAGE_UP = '\ue00e'			# PgUp
    PAGE_DOWN = '\ue00f'		# PgDn
    END = '\ue010'				# End
    HOME = '\ue011'				# Home
    LEFT = '\ue012'				# ← 键
    ARROW_LEFT = LEFT
    UP = '\ue013'				# ↑ 键
    ARROW_UP = UP
    RIGHT = '\ue014'			# → 键
    ARROW_RIGHT = RIGHT
    DOWN = '\ue015'				# ↓ 键
    ARROW_DOWN = DOWN
    INSERT = '\ue016'			# insert键
    DELETE = '\ue017'			# Del键
    SEMICOLON = '\ue018'		# ;键
    EQUALS = '\ue019'			# = 键

    NUMPAD0 = '\ue01a'  		# 数字小键盘
    NUMPAD1 = '\ue01b'
    NUMPAD2 = '\ue01c'
    NUMPAD3 = '\ue01d'
    NUMPAD4 = '\ue01e'
    NUMPAD5 = '\ue01f'
    NUMPAD6 = '\ue020'
    NUMPAD7 = '\ue021'
    NUMPAD8 = '\ue022'
    NUMPAD9 = '\ue023'
    MULTIPLY = '\ue024'			# * 键
    ADD = '\ue025'				# + 键
    SEPARATOR = '\ue026'		# , 键
    SUBTRACT = '\ue027'			# - 键
    DECIMAL = '\ue028'			# . 键
    DIVIDE = '\ue029'			# / 键

    F1 = '\ue031'  				# F1
    F2 = '\ue032'
    F3 = '\ue033'
    F4 = '\ue034'
    F5 = '\ue035'
    F6 = '\ue036'
    F7 = '\ue037'
    F8 = '\ue038'
    F9 = '\ue039'
    F10 = '\ue03a'
    F11 = '\ue03b'
    F12 = '\ue03c'

    META = '\ue03d'
    COMMAND = '\ue03d'


使用如下:
send_keys(Keys.BACK_SPACE)		# 删除键(BackSpace)
send_keys(Keys.SPACE)			# 空格键(Space)
send_keys(Keys.TAB)				# 制表键(TAB)
send_keys(Keys.ESCAPE)			# 回退键(ESCAPE)
send_keys(Keys.ENTER)			# 回车键(ENTER)
send_keys(Keys.CONTROL,'a')		# 全选(Ctrl+A)
send_keys(Keys.CONTROL,'c')		# 复制(Ctrl+C)
send_keys(Keys.CONTROL,'x')		# 剪切(Ctrl+X)
send_keys(Keys.CONTROL,'v')		# 粘贴(Ctrl+V)
send_keys(Keys.F1)				# 键盘F1

7. 窗口和框架的切换

import time

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By

# 定位不到元素的3个原因  :  定位方式有问题    没有等待完成     页面中有框架

#  iframe框架切换            iframe(网页嵌入多个页面)