入门Selenium

一、什么是Selenium

​ Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的。Selenium 可以直接调用浏览器,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器),可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏等。既然可以调用浏览器,就可以做到在浏览器中看到是什么样子,抓取的源码也是什么样子,也就是可见即可爬

二、安装环境

2.1、安装Chrome浏览器

2.2、安装Selenium包

pip install selenium -i https://pypi.douban.com/simple

安装完成后,进入Python命令行交互模式,导入Selenium包,如果没有报错,就说明安装成功

Python 3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import selenium
>>>

2.3、安装ChromeDriver

查看Chrome浏览器版本号,右上角–>设置—>关于Chrome

在这里插入图片描述

进入ChromeDriver镜像网站,选择合适的版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLqGzf31-1628811468057)(入门Selenium工具.assets/image-20210414181253475.png)]

配置环境变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FDxtJOSN-1628811468061)(入门Selenium工具.assets/image-20210414181439401.png)]

进入终端模式,输入Chromedriver

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x1fzrtlW-1628811468064)(入门Selenium工具.assets/image-20210414181528365.png)]

三、用法

3.1、简单使用

from selenium import webdriver

# 如果driver没有添加到了环境变量,则需要将driver的绝对路径赋值给executable_path参数
# driver = webdriver.Chrome(executable_path='/home/worker/Desktop/driver/chromedriver')
# 如果driver添加了环境变量则不需要设置executable_path

# 1.实例化对象
driver = webdriver.Chrome()
url = 'https://www.baidu.com/'

# 访问网页
driver.get(url)

# 截图功能
driver.save_screenshot("baidu.png")  

# 打印页面的标题
print(driver.title) 

# 一定要退出!不退出会有残留进程!
# quit会退出整个浏览器,而close只会关闭一个标签
driver.quit() 
driver.close()
  • 实例化一个driver对象
  • 使用世界要关闭

3.2、Selenium提取数据

  • 了解 driver对象的常用属性和方法
  • 掌握 driver对象定位标签元素获取标签对象的方法
  • 掌握 标签对象提取文本和属性值的方法

3.2.1、driver对象的常用属性和方法

在使用selenium过程中,实例化driver对象后,driver对象有一些常用的属性和方法

  1. driver.page_source 当前标签页浏览器渲染之后的网页源代码
  2. driver.current_url 当前标签页的url
  3. driver.close() 关闭当前标签页,如果只有一个标签页则关闭整个浏览器
  4. driver.quit() 关闭浏览器
  5. driver.forward() 页面前进
  6. driver.back() 页面后退
  7. driver.screen_shot(img_name) 页面截图

3.2.2、driver对象定位标签元素获取标签对象的方法

在selenium中可以通过多种方式来定位标签,返回标签元素对象

find_element_by_id 								(返回一个元素)
find_element(s)_by_class_name 					(根据类名获取元素列表)
find_element(s)_by_name 						(根据标签的name属性值返回包含标签对象元素的列表)
find_element(s)_by_xpath 						(返回一个包含元素的列表)
find_element(s)_by_link_text 					(根据连接文本获取元素列表)
find_element(s)_by_partial_link_text 			(根据链接包含的文本获取元素列表)
find_element(s)_by_tag_name 					(根据标签名获取元素列表)
find_element(s)_by_css_selector 				(根据css选择器来获取元素列表)
  • 注意:
    • find_element和find_elements的区别:
      • 多了个s就返回列表,没有s就返回匹配到的第一个标签对象
      • find_element匹配不到就抛出异常,find_elements匹配不到就返回空列表
    • by_link_text和by_partial_link_tex的区别:全部文本和包含某个文本

3.2.3、标签对象提取文本内容和属性值

find_element仅仅能够获取元素,不能够直接获取其中的数据,如果需要获取数据需要使用以下方法

  • 对元素执行点击操作 element.click()
    • 对定位到的标签对象输入数据
  • 对定位到的标签对象输入数据
    • 通过定位获取的标签对象的 text 属性,获取文本内容
  • 获取属性值 element.get_attribute("属性名")
    • 通过定位获取的标签对象的 get_attribute 函数,传入属性名,来获取属性的值

四、查找节点

4.1、单个节点

所有获取单个节点的方法:

  • find_element_by_id ——根据id属性定位
  • find_element_by_name ——根据name属性定位
  • find_element_by_xpath ——根据Xpath定位
    • 用id或者name属性来找到一个靠近的元素(比较理想的是父元素),这样再依靠他们的相对关系来确定目标元素的位置。
    • 推荐使用Xpath helper插件
  • find_element_by_link_text ——根据链接文本定位
  • find_element_by_partial_link_text ——根据部分链接文本定位
  • find_element_by_tag_name ——根据标签名定位
  • find_element_by_class_name ——根据class定位
  • find_element_by_css_selector ——根据CSS选择器定位

通用方法:

  • find_element(查找方式By,值)

4.2、多个节点定位

所有获取多个节点的方法(下列方法会返回一个list,其余使用方式相同):

  • find_elements_by_name
  • find_elements_by_xpath
  • find_elements_by_link_text
  • find_elements_by_partial_link_text
  • find_elements_by_tag_name
  • find_elements_by_class_name
  • find_elements_by_css_selector

通用的方法

  • find_elements

五、事件等待(Waits)

利用Waits来给页面动作执行提供了时间间隔——比如加载元素,元素定位等

显示Waits

除了time.sleep()

另外一种更好的办法:它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回。否则抛出超时异常

WebDriverWait结合ExpectedCondition

# 来自文档的例子
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delay_loading")
try:
    element = WebDriverWait(driver,10)
    element.until(EC.presence_of_element_located((By.ID,"myDynamicElement"))
    )
finally:
    driver.quit()
    
'''
这段代码会等待10秒,如果10秒内找到元素则立即返回,否则会抛出TimeoutException异常,WebDriverWait默认每500毫秒调用一下ExpectedCondition直到它返回成功为止。ExpectedCondition类型是布尔的,成功的返回值就是true,其他类型的ExpectedCondition成功的返回值就是 not null
'''

expected_condition等待条件

title_is	标题是某内容
title_contains	标题包含某内容
presence_of_element_located		节点加载出来,传入定位元组,如(By.Id,'P')
visibility_of_element_located	节点可见,传入定位元组
visibility_of	可见,传入节点对象
presence_of_all_elements_located	所有节点加载出来
text_to_be_present_in_element	某个节点文本包含某文字
text_to_be_present_in_element_value		某个节点值包含某文字
frame_to_be_available_and_switch_to_it	加载并切换
invisibility_of_element_located		节点不可见
element_to_be_clickable 	节点可点击
staleness_of	判断一个节点是否仍在DOM,可判断页面是否已经刷新
element_to_be_selected	节点可选择,传节点对象
element_located_to_be_selected	节点可选择,传入定位元组
element_selection_state_to_be  传入节点对象以及状态,相等返回 True,否则返回 False
element_located_selection_state_to_be 传入定位元组以及状态,相等返回 True,否则返回 False
alert_is_present	是否出现警告 

隐式Waits

如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。

也就是说,查找节点而节点没有出现,隐式等待将等待一段时间后再查找DOM,默认的时间是0

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id('myDynamicElement')

比较总结:

隐式Waits会让同一个问题根据不同的操作系统,不同的浏览器,不同的Selenium版本上都会不同的表现。而显示Waits可以在我们能想到的任何条件上更加灵活的处理情况,甚至可以忽略某些异常

六、动作链

没有特别的执行对象,比如鼠标拖曳、键盘按键——动作链

参考文档:动作链

#-----------------链式模型---------------------#
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

# 找到两个元素
# 构建ActionChains对象——ActionChains(driver)
# 行为方法加入队列——move_to_element(menu).click(hidden_submenu)
# 执行触发——perform()

#-----------------单个按序---------------------#
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
action.perform()
  • click(on_element=None)

    • 点击一个元素
    • 参数: * on_element:要点击的元素,如果是None,点击鼠标当前的位置
  • click_and_hold(on_element=None)

    • 鼠标左键点击一个元素并且保持
  • double_click(on_element=None)

    • 双击一个元素
  • drag_and_drop(source, target)

    • 鼠标左键点击source元素,然后移动到target元素释放鼠标按键
    • 参数: source:鼠标点击的元素 target:鼠标松开的元素
  • drag_and_drop_by_offset(source, xoffset,yoffset)

    • 拖拽目标元素到指定的偏移点释放
    • 参数: source:点击的参数 xoffset:X偏移量 * yoffset:Y偏移量
  • key_down(value,element=None)

    • 只按下键盘,不释放。我们应该只对那些功能键使用(Contril,Alt,Shift)

    • 参数: value:要发送的键,值在Keys类里有定义 element:发送的目标元素,如果是None,value会发到当前聚焦的元素上

    • # 按下Ctrl+C
      ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()
      
    • ADD = u'\ue025'
      ALT = u'\ue00a'
      ARROW_DOWN = u'\ue015'
      ARROW_LEFT = u'\ue012'
      ARROW_RIGHT = u'\ue014'
      ARROW_UP = u'\ue013'
      BACKSPACE = u'\ue003'
      BACK_SPACE = u'\ue003'
      CANCEL = u'\ue001'
      CLEAR = u'\ue005'
      COMMAND = u'\ue03d'
      CONTROL = u'\ue009'
      DECIMAL = u'\ue028'
      DELETE = u'\ue017'
      DIVIDE = u'\ue029'
      DOWN = u'\ue015'
      END = u'\ue010'
      ENTER = u'\ue007'
      EQUALS = u'\ue019'
      ESCAPE = u'\ue00c'
      F1 = u'\ue031'
      F10 = u'\ue03a'
      F11 = u'\ue03b'
      F12 = u'\ue03c'
      F2 = u'\ue032'
      F3 = u'\ue033'
      F4 = u'\ue034'
      F5 = u'\ue035'
      F6 = u'\ue036'
      F7 = u'\ue037'
      F8 = u'\ue038'
      F9 = u'\ue039'
      HELP = u'\ue002'
      HOME = u'\ue011'
      INSERT = u'\ue016'
      LEFT = u'\ue012'
      LEFT_ALT = u'\ue00a'
      LEFT_CONTROL = u'\ue009'
      LEFT_SHIFT = u'\ue008'
      META = u'\ue03d'
      MULTIPLY = u'\ue024'
      NULL = u'\ue000'
      NUMPAD0 = u'\ue01a'
      NUMPAD1 = u'\ue01b'
      NUMPAD2 = u'\ue01c'
      NUMPAD3 = u'\ue01d'
      NUMPAD4 = u'\ue01e'
      NUMPAD5 = u'\ue01f'
      NUMPAD6 = u'\ue020'
      NUMPAD7 = u'\ue021'
      NUMPAD8 = u'\ue022'
      NUMPAD9 = u'\ue023'
      PAGE_DOWN = u'\ue00f'
      PAGE_UP = u'\ue00e'
      PAUSE = u'\ue00b'
      RETURN = u'\ue006'
      RIGHT = u'\ue014'
      SEMICOLON = u'\ue018'
      SEPARATOR = u'\ue026'
      SHIFT = u'\ue008'
      SPACE = u'\ue00d'
      SUBTRACT = u'\ue027'
      TAB = u'\ue004'
      UP = u'\ue013'
      
  • key_up(value,element=None)

  • move_by_offset(xoffset,yoffset)

    • 将当前鼠标的位置进行移动
  • move_to_element(to_element)

    • 把鼠标移到一个元素的中间
  • move_to_element_with_offset(to_element,xoffset,yoffset)

    • 鼠标移动到元素的指定位置,偏移量以元素的左上角为基准
  • perform()

    • 执行所有存储的动作
  • release(on_element=None)

    • 释放一个元素上的鼠标按键,
    • 参数: * on_element:如果为None,在当前鼠标位置上释放
  • send_keys(*keys_to_send)

    • 向当前的焦点元素发送键
  • send_keys_to_element(element,*keys_to_send)

    • 向指定的元素发送键

七、执行JavaScript

有一些操作,Selenium API并没有提供。比如下拉进度条,但是我们可以通过模拟JavaScript来达到效果

from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
broser.execute_script('alert("To Bottom")')
# 拉到底部后,然后弹出alert警告框

八、警告框

class selenium.webdriver.common.alert.Alert(driver)

  • accept()

    • 确认提示框
  • authenticate(username,password)

    • 向一个认证的对话框发送用户名和密码,会自动点击确认

    • 参数: username:username区域要填写的字符串 password:password区域要填写的字符串

    • driver.switch_to.alert.authenticate('cheese','secretGouda')
      
  • dismiss()

    • 忽略提示框
  • send_keys(KeysToSend)

    • 向对话框输入字符
  • text

    • 提示框的文本

接受和忽略弹框:

Alert(driver).accept()
Alert(driver).dismiss()

prompt里输入字符:

name_prompt = Alert(driver)
name_prompt.send_keys("Willian Shakephere")
name_prompt.accept()

读取prompt的提示字符:

alert_text = Alert(driver).text
self.assertEqual("Do you wish to quit?",alert_text)

九、获取节点信息

classselenium.webdriver.remote.webelement.WebElement(parent,id_,w3c=False)

代表一个DOM元素,检测不到元素是是否DOM相连时,会抛出StaleEleementReferenceException异常

  • 获取属性:get_attribute(name)

    • 返回元素指定的属性
    • 如果属性不存在,它会返回和属性名相同的字符串,如果没有属性是这个名字,返回None
    • 被认为是真假的值会返回布尔类型,其他所有的非None值都会以字符串的形式返回。属性不存在,返回None
  • 获取文本值:text

    • Beautiful Soup的 get_text() 方法
    • pyquery的 text()方法
  • 获得id、位置、标签名和大小

    • id——可以用来==做比较

      • if element1 == element2:
            print("These 2 are equal")
        
    • location - 元素在可渲染的画布上的位置

    • location_once_scrolled_into_view

      • 用这个来检查元素在屏幕的位置以方便我们点击它,这个方法可能造成元素滚动到视图里。 返回屏幕左上角的位置,元素不可见返回None
    • size - 元素的尺寸

    • tag_name - 元素的标签名

  • 其他

    • is_displayed() - 元素对用户是否可见

    • is_enabled() - 元素是否可用

    • is_selected() - 元素是否被选中,可用来检测单选或者复选按钮是否被选中

    • screenshot(filename) - 获取当前元素的截图,有IOError会返回False,文件名要包含完整路径

    • send_keys(*value) - 模拟向元素输入

      • form_textfiled = driver.find_element_by_name("username")
        form_textfiled.send_keys("admin")
        
      • file_input = driver.find_element_by_name('profilePic')
        file_input.send_keys('path/to/profilepic.gif')
        
    • submit() - 提交表单

    • value_of_css_property(property_name) - CSS属性的值

    • parent - WebDriver实例的内部引用,元素是从哪里发现的

    • rect - 元素尺寸和位置的dict

    • screenshot_as_base64 - 当前元素截图的base64编码字符串

    • screenshot_as_png - 当前元素截图的二进制数据

十、切换Frame

网页有一种节点叫 iframe,也就是子 Frame。

当 Selenium打开页面后,默认是在父级里面操作,是不能获取子 Frame里面的节点

  • switch_to_frame(frame_reference)方法来切换Frame

十一、前进和后退

class selenium.webdriver.remote.webdriver.WebDriver(command_executor=‘http://127.0.0.1:4444/wd/hub’, desired_capabilities=None, browser_profile=None, proxy=None, keep_alive=False)

浏览器有前进和后退功能,Selenium完成这个操作的方法是

  • back()
  • forward()

十二、Cookies

  • delete_all_cookies() - 删除当前会话的所有cookie
  • delete_cookie(name) - 删除一个指定的cookie
  • get_cookie(name) - 返回一个指定的cookie,不存在返回None
  • get_cookies() - 返回一组dict,相当于当前会话的可用cookie

十三、选项卡管理

  • browser.execute_script(‘window.open()’)——开启选项卡
  • window_handles - 返回当前会话内所有窗口的资源句柄
  • switch_to_window(window_name) —切换选项卡

十四、异常处理

异常处理

参考资料:


selenium + python 中文文档

Selenium with Python

Python3网络爬虫开发实战

FAQ:

附录:FAQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值