0


爬虫 selenium

爬虫 selenium

【一】介绍

【1】说明

  • Selenium是一款广泛应用于Web应用程序测试的自动化测试框架- 它可以模拟用户再浏览器上的行为- 对Web应用进行自动化测试
  • 主要作用:- 浏览器控制:启动、切换、关闭不同浏览器- 元素定位于操作:通过CSS选择器、Xpath等定位方式定位元素位置- 网页操作和内容获取:打开、刷新网页、获取URL、获取网页源码、截图、元素定位- 测试功能:测试Web应用程序的功能和性能,例如测试表单验证、等待Ajax请求完成操作- 测试兼容性:测试应用程序是否能很好的运行在不同浏览器、不同操作系统上

【2】安装引入

  • 安装
  1. pip install selenium

【3】驱动下载

在这里插入图片描述

  • chrome驱动下载地址 - Chrome for Testing availability (googlechromelabs.github.io)

【4】简单示例

  1. import os
  2. import time
  3. from selenium import webdriver
  4. from selenium.webdriver.edge.service import Service
  5. # 驱动位置
  6. browser_path = os.path.join(os.path.dirname(__file__),'msedgedriver.exe')# 需要使用Service对象传递位置,要不然第一运行程序很慢,要等待查找
  7. ser = Service(browser_path)# 根据驱动选和浏览器进行选择
  8. browser = webdriver.Edge(service=ser)# 打开网页
  9. browser.get("http://www.baidu.com")# 等待10
  10. time.sleep(10)# 关闭浏览器
  11. browser.quit()

【二】浏览器操作

【1】基础操作

(1)指定驱动

  • 需要使用Service对象指定驱动位置 - 要不然第一运行程序很慢- 要等待查找程序慢慢查找
  1. from selenium.webdriver.edge.service import Service
  2. # 驱动位置
  3. browser_path = os.path.join(os.path.dirname(__file__),'msedgedriver.exe')# 需要使用Service对象指定驱动位置
  4. ser = Service(browser_path)# 根据驱动选和浏览器进行选择
  5. browser = webdriver.Edge(service=ser)

(2)基础操作

  • 常用 - browser.get(url)访问指定网址- browser.maximize_window()最大化浏览器- browser.current_url浏览器当前网址- browser.page_source网页源码- browser.close()关闭当前窗口- browser.quit()关闭浏览器实例
  • 窗口(选项卡): - browser.window_handles:所有选项卡列表,每个都是24位字符串- browser.execute_script(“window.open();”):打开一个新的选项卡- browser.switch_to.window(browser.window_handles[-1]):切换选项卡,切换到最新打开的选项卡
  • 其他 - browser.set_window_size(width, height):设置浏览器大小(宽, 高)- browser.forward():浏览器前进- browser.forward():浏览器前进- browser.title:浏览器标题- browser.name:浏览器名称

(3)八大选择器

  • 需要导入标签定位工具
  1. from selenium.webdriver.common.by import By
  • browser.find_element(By.ID, value) - 通过ID查找
  • browser.find_element(By.NAME, value) - 通过Name属性查找
  • browser.find_element(By.CLASS_NAME, value) - 通过class属性查找
  • browser.find_element(By.TAG_NAME, value) - 通过标签名查找
  • browser.find_element(By.LINK_TEXT, value) - 通过链接(a标签)文字进行精确定位
  • browser.find_element(By.PARTIAL_LINK_TEXT, value) - 通过链接(a标签)文字进行模糊定位
  • browser.find_element(By.XPATH, value) - 通过XPath表达式进行定位
  • browser.find_element(By.CSS_SELECTOR, value) - 通过css选择器定位

(4)元素操作

  • 首先通过选择器拿到元素- tag = browser.find_element(By.选择器, value)tag = browser.find_elements(By.选择器, value)
  • 常用- tag.text:获取标签的文本内容- tag.get_attribute(key):根据属性名获取属性值- tag.click():对标签进行点击操作- tag.clear():清空可输入标签内的数据- tag.send_keys(data):向标签(input、textarea … …)内输入数据- tag.submit():对标签进行提交操作- tag.screenshot(‘1.png’):对标签元素进行截图
  • 其他:- tag.id:selenium内部使用的id- tag.get_property(key):不是所有的 WebDriver 都支持,推荐使用get_attribute(key)- tag.location:获取坐标位置{‘x’: 630, ‘y’: 2121}- tag.location_once_scrolled_into_view:滚动页面到指定元素的位置,底部对齐,可输出坐标位置还是字典格式- tag.size:元素的大小{‘height’: 36, ‘width’: 80}- tag.tag_name:获取标签的标签名- tag.is_selected():判断元素是否被选中- tag.is_enabled():判断元素是否可编辑- tag.is_displayed:判断元素是否演示- tag._upload(filename):上传文件- tag.value_of_css_property(‘color):获取的属性值,这个就是获取颜色属性rgba(57, 81, 179, 1)

【2】页面等待

(1)为什么要等待

  • 放置频率过高,对别人的服务器不好
  • 等待页面的标签元素加载

(2)等待的方法

  • 强制等待(无条件等待)- 使用time模块中的sleep方法
  • 隐式等待- 通过browser.implicitly_wait(time_to_wait=2)- 设置的是WebDriver在整个会话期间等待元素加载到dom的时间,全局的配置- 超过指定时间任然未找到将报错
  • 显示等待(智能等待)- 针对指定元素指定等待时间- from selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC# 等待元素出现wait = WebDriverWait(browser,10,0.5)wait.until(EC.presence_of_element_located((By.ID,'id_value')))- WebDriverWait(浏览器, 等待时间, 查找频率(默认0.5s))- 超出时间也会报错

【3】动作链

(1)什么是动作链

  • 动作链是一种用于模拟复杂用户交互操作的功能- 鼠标、键盘操作等
  • 导入动作链类ActionChains
  1. from selenium.webdriver.common.action_chains import ActionChains
  • 导入键盘类Keys
  1. from selenium.webdriver.common.keys import Keys

(2)常用鼠标、键盘操作

  • 鼠标(鼠标操作最后一定要perform) - context_click():右击- double_click():双击- double_and_drop():拖拽- move_to_element():悬停- perform():执行
  • 键盘(键盘操作可以直接使用) - send_keys(Keys.BACK_SPACE):删除键- send_keys(Keys.SPACE):空格键- send_keys(Keys.TAB):制表键- send_keys(Keys.ESCAPE):回退键- send_keys(Keys.ENTER):回车键- send_keys(Keys.CONTROL, ‘a’):全选- send_keys(Keys.CONTROL, ‘c’):复制- send_keys(Keys.CONTROL, ‘v’):粘贴- send_keys(Keys.CONTROL, ‘x’):剪切- send_keys(Keys.F1):键盘F1
  • 事件监听 - click(on_element=None) :左键点击- click_and_hold(on_element=None) :单击左键不松开- context_click(on_element=None):右键点击- double_click(on_element=None):双击左键- drag_and_drop(source,target):拖拽某个元素- drag_and_drop_by_offset(source,xoffset,yoffset):拖拽并移动指定像素- key_down(value,element=None):按下某个键盘- key_up(value, element=None):松开键盘上的某个键- move_by_offset(xoffset, yoffset):移动指定像素- move_to_element(to_element):移动到指定元素- move_to_element_with_offset(to_element, xoffset, yoffset):移动到指定元素的位置(距元素左上角)- pause(seconds):暂停所有输入,指定时间- perform():执行所有操作- reset_action():结束已经存在的操作并重置- release(on_element=None):在某个元素位置松开鼠标- send_keys(*keys_to_send):发送某个键或文本到当前焦点的元素- send_keys_to_element(element, *keys_to_send):发送某个键或文本到指定元素

【4】动作链示例

(1)搜狗输入

  • 实际上不用动作链更方便,这里为了演示
  1. import time
  2. from selenium import webdriver
  3. from selenium.webdriver.edge.service import Service
  4. from selenium.webdriver.common.by import By
  5. from selenium.webdriver.common.action_chains import ActionChains
  6. from selenium.webdriver.common.keys import Keys
  7. service = Service('.\msedgedriver.exe')
  8. browser = webdriver.Edge(service=service)
  9. browser.get("https://www.sogou.com/")
  10. browser.maximize_window()
  11. time.sleep(1)# 创建动态链实例
  12. action = ActionChains(browser)# 找到输入文本框
  13. input_elm = browser.find_element(By.XPATH,'//*[@id="query"]')
  14. input_elm.send_keys("周润发")# 输入文本# 搜索按钮
  15. search_ele = browser.find_element(By.XPATH,'//*[@id="stb"]')
  16. action.move_to_element(search_ele).click().perform()# 必须要perform# 等待3s
  17. time.sleep(3)# 从新找到输入文本框
  18. input_elm = browser.find_element(By.XPATH,'//*[@id="upquery"]')# input_elm.clear() # 简单直接
  19. input_elm.send_keys(Keys.CONTROL,"a")# 复杂
  20. time.sleep(0.5)
  21. input_elm.send_keys(Keys.BACK_SPACE)
  22. time.sleep(0.5)
  23. input_elm.send_keys('周星驰')
  24. time.sleep(0.5)# 搜索按钮
  25. search_ele = browser.find_element(By.XPATH,'//*[@id="searchBtn"]')
  26. action.click(search_ele).perform()# 一定要perform
  27. time.sleep(2)
  28. browser.close()
  29. browser.quit()

(2)拖拽标签滑动

  1. import time
  2. from selenium import webdriver
  3. from selenium.webdriver.edge.service import Service
  4. from selenium.webdriver.common.by import By
  5. from selenium.webdriver.common.action_chains import ActionChains
  6. from selenium.webdriver.common.keys import Keys
  7. service = Service('.\msedgedriver.exe')
  8. browser = webdriver.Edge(service=service)
  9. browser.get('http://sahitest.com/demo/dragDropMooTools.htm')
  10. browser.maximize_window()
  11. time.sleep(1)# 获取元素
  12. source_div = browser.find_element(By.XPATH,'//*[@id="dragger"]')
  13. target_div1 = browser.find_element(By.XPATH,"/html/body/div[2]")
  14. target_div2 = browser.find_element(By.XPATH,"/html/body/div[3]")
  15. target_div3 = browser.find_element(By.XPATH,"/html/body/div[4]")
  16. target_div4 = browser.find_element(By.XPATH,"/html/body/div[5]")# 实例化动作链
  17. action = ActionChains(browser)# 拖拽方式一: 直接drag_and_drop
  18. time.sleep(1)
  19. action.drag_and_drop(source_div, target_div1).perform()# 拖拽方式二:先click_and_hold,然后move_to_element,再然后release
  20. time.sleep(1)
  21. action.click_and_hold(source_div).move_to_element(target_div2).release().perform()# 拖拽方式三:先计算偏移量,然后drag_and_drop_by_offset
  22. time.sleep(1)
  23. x = target_div3.location['x']- source_div.location['x']
  24. y = target_div3.location['y']- source_div.location['y']
  25. action.drag_and_drop_by_offset(source_div, x, y).perform()# 拖拽方式四:先click_and_hold,然后到目标位置release
  26. time.sleep(1)
  27. action.click_and_hold(source_div).release(target_div4).perform()
  28. time.sleep(2)
  29. browser.close()
  30. browser.quit()

(3)框架(frame)内拖动标签

  • 测试网址:菜鸟教程在线编辑器 (runoob.com) - 无法直接操作- 需要先切换到指定框架内
  1. import random
  2. import time
  3. import selenium.common.exceptions
  4. from selenium import webdriver
  5. from selenium.webdriver.edge.service import Service
  6. from selenium.webdriver.common.by import By
  7. from selenium.webdriver.common.action_chains import ActionChains
  8. from selenium.webdriver.common.keys import Keys
  9. service = Service('.\msedgedriver.exe')
  10. browser = webdriver.Edge(service=service)
  11. browser.maximize_window()
  12. browser.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
  13. time.sleep(2)# 根据frameid进行切换
  14. browser.switch_to.frame('iframeResult')# 获取元素标签
  15. source_div = browser.find_element(By.XPATH,'//*[@id="draggable"]')
  16. target_div = browser.find_element(By.XPATH,'//*[@id="droppable"]')# 实例动作链对象
  17. action = ActionChains(browser)# 计算需要移动的偏移量
  18. x = target_div.location['x']- source_div.location['x']try:while x:
  19. m =min(random.randint(1, x),30)
  20. action.drag_and_drop_by_offset(source_div, m,0).perform()
  21. x -= m
  22. time.sleep(random.randint(50,150)/1000)except selenium.common.exceptions.UnexpectedAlertPresentException:pass
  23. time.sleep(2)
  24. browser.close()
  25. browser.quit()

【5】执行JS代码

(1)需求何来

  • 前端显示受限
  • 页面滚动条无法通过元素获取
  • 通过执行JS代码,甚至还可以修改页面参数

(2)使用方法

  • 打开新的页面
  1. browser.execute_script("window.open()")
  2. browser.switch_to.window(browser.window_handles[-1])
  3. browser.get("http://baidu.com")
  • 滚动到页面底部
  1. browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
  • 点击元素
  1. next_url = browser.find_element(By.XPATH,'//*[@id="sogou_next"]')
  2. script_str ='arguments[0].click()'
  3. browser.execute_script(script_str, next_url)
  • 输入文本
  1. input_div = browser.find_element(By.XPATH,'//*[@id="upquery"]')
  2. script_str ='arguments[0].value = arguments[1]'
  3. browser.execute_script(script_str, input_div,'周杰伦')
  • 获取元素属性
  1. element = browser.find_element(By.XPATH,'//*[@id="searchBtn"]')
  2. script_str ='return arguments[0].getAttribute("value");'
  3. attribute_value = browser.execute_script(script_str, element)print(attribute_value)# 搜狗搜索
  • 拖动元素 - 速度过快,还是使用动作链
  1. source_div = browser.find_element(By.XPATH,'')
  2. target_div = browser.find_element(By.XPATH,'')
  3. script_str ='''
  4. var source = arguments[0], target = arguments[1];
  5. var offsetX = target.getBoundingClientRect().left - source.getBoundingClientRect().left;
  6. var offsetY = target.getBoundingClientRect().top - source.getBoundingClientRect().top;
  7. var event = new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window });
  8. source.dispatchEvent(event);
  9. event = new MouseEvent('mousemove', { bubbles: true, cancelable: true, view: window, clientX: offsetX, clientY: offsetY });
  10. source.dispatchEvent(event);
  11. event = new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window });
  12. source.dispatchEvent(event);
  13. '''
  14. browser.execute_script(script_str, source_div, target_div)
  • 隐藏或伪装浏览器自动化
  1. browser.execute_script("Object.defineProperties(navigator,{webdriver:{get:()=>undefined}})")

【6】options

(1)介绍

  • 无头浏览器是一种没有图形界面(GUI)的的网络浏览器
  • 他通过在内存中渲染页面,然后将结果发送回请求它的用户或程序来实现对网络的访问,而不会在屏幕上显示网页
  • 优点 - 执行速度快、减少干扰、资源消耗低、易于集成、应用范围广
  • 缺点 - 不能完全模拟用户真实行为、不适用于需要页面渲染验证的场景、调试困难

(2)页面渲染机制

  1. 解析HTML,构建DOM树
  2. 解析CSS,生成CSSOM树
  3. 合并DOM树和CSSOM树,生成渲染树
  4. 根据渲染树进行布局
  5. 调用GPU绘制渲染树,合并图层,显示在屏幕上
  • 无头浏览器跳过了后面的三个步骤

(2)如何使用

  • 无头浏览器有时还是需要指定窗口大小的 - 模拟不同设备大小- 网页渲染需要- 截图一致性
  1. from selenium.webdriver.edge.options import Options
  2. options = Options()# 指定窗口分辨率
  3. options.add_argument("window-size=1920x1080")# 隐藏滚动条,应对特殊界面
  4. options.add_argument('--hide-scrollbars')# 启用无头浏览器
  5. options.add_argument('--headless')# 不加载图片,提升速度
  6. options.add_argument('blink-settings=imagesEnabled=false')# 禁用GPU加速
  7. options.add_argument('--disable-gpu')# 添加IP代理 proxy=f"http://{ip}:{port}"
  8. options.add_argument(f'--proxy-server={proxy}')# 隐身模式(无痕模式)
  9. options.add_argument('--incognito')# 设置请求头的User-Agent
  10. options.add_argument('--user-agent=""')# 浏览器最大化
  11. options.add_argument('--start-maximized')# 设置中文
  12. options.add_argument('lang=zh_CN.UTF-8')
  • 去除自动化控制的设置
  1. options.add_experimental_option("excludeSwitches",["enable-automation"])
  2. options.add_experimental_option('useAutomationExtension',False)
  • 示例 - 百度可以- 搜狗不行
  1. import time
  2. from selenium import webdriver
  3. from selenium.webdriver.edge.service import Service
  4. from selenium.webdriver.common.by import By
  5. from selenium.webdriver.edge.options import Options
  6. from selenium.webdriver.support.ui import WebDriverWait
  7. from selenium.webdriver.support import expected_conditions as EC
  8. edge_options = Options()# 指定窗口分辨率
  9. edge_options.add_argument("window-size=1920x1080")# 隐藏滚动条,应对特殊界面
  10. edge_options.add_argument('--hide-scrollbars')# 启用无头浏览器
  11. edge_options.add_argument('--headless')# 不加载图片,提升速度
  12. edge_options.add_argument('blink-settings=imagesEnabled=false')# 规避bug
  13. edge_options.add_argument('--disable-gpu')
  14. service = Service('.\msedgedriver.exe')
  15. browser = webdriver.Edge(service=service, options=edge_options)
  16. browser.maximize_window()
  17. browser.get('https://www.baidu.com/')
  18. time.sleep(2)
  19. element = WebDriverWait(browser,10).until(EC.element_to_be_clickable((By.XPATH,'//*[@id="su"]')))
  20. script_str ='return arguments[0].getAttribute("value");'
  21. attribute_value = browser.execute_script(script_str, element)print(attribute_value)# 百度一下
  22. time.sleep(1)
  23. browser.close()
  24. browser.quit()

【7】cookie操作

(1)常用方法

  • browser.get_cookies():获取当前页面cookies,是列表套字典
  • browser.add_cookie(cookie_dict):添加cookie
  • browser.delete_cookies(name):根据name删除指定cookie
  • browser.delete_all_cookies():删除所有的cookie

(2)查看add_cookie源码注释

  1. """
  2. Adds a cookie to your current session.
  3. :Args:
  4. - cookie_dict: A dictionary object, with required keys - "name" and "value";
  5. optional keys - "path", "domain", "secure", "httpOnly", "expiry", "sameSite"
  6. :Usage:
  7. ::
  8. driver.add_cookie({'name' : 'foo', 'value' : 'bar'})
  9. driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'})
  10. driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure' : True})
  11. driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'sameSite' : 'Strict'})
  12. """
  • cookie_dict以字典的形式传入 - 字典中必须有name和value两个键- 可选的键有:“path”, “domain”, “secure”, “httpOnly”, “expiry”, “sameSite”
  • 键名的含义 - name:cookie的名称。唯一标识符,区分不同的cookie- value:cookie对应的值- domain:cookie适用的域名。定义哪些域名可以接收和发送cookie- expiry或max-age:cookie的过期时间- path:cookie适用的URL路径- httpOnly:一个标识,指示cookie是否只能通过HTTP(S)协议访问,而不能通过客户端脚本(如javascript)访问- secure:一个标识,指示cookie是否只能通过安全的HTTPS连接传输- sameSite:定义cookie的sameSite属性,控制何时发送cookie,有助于放置跨站请求伪造(csrf)攻击,有三个值 - Strict:仅当请求来自同一站点才发送cookie- Lax:在导航到目标站点(即链接点击)或顶级导航到相同站点时发送cookie- None:浏览器始终发送cookie,不考虑请求的站点。 - 这通常和Secure属性一起使用,以增强安全性

(3)使用方法

  1. # 保存cookies
  2. cookies = browser.get_cookies()withopen(cookie_path,'wt', encoding='utf8')as fp:
  3. json.dump(cookies, fp=fp)
  1. # 添加cookiewithopen(cookie_path,'rt', encoding='utf8')as fp:
  2. cookies = json.load(fp=fp)for cookie in cookies:
  3. browser.add_cookie(cookie)
  1. # 转为requets中的cookies字典withopen(cookie_path,'rt', encoding='utf8')as fp:
  2. cookies = json.load(fp=fp)
  3. requests_cookies ={cookie.get('name'):cookie.get('value')for cookie in cookies}
  1. # 转换为headers中的cookiefrom urllib.parse import quote # 用于编码cookie的名称和值 withopen(cookie_path,'rt', encoding='utf8')as fp:
  2. cookies = json.load(fp=fp)
  3. headers_cookie ="; ".join([f"{quote(cookie['name'])}={quote(cookie['value'])}"for cookie in cookies])

本文转载自: https://blog.csdn.net/weixin_48183870/article/details/137607293
版权归原作者 在飞行-米龙 所有, 如有侵权,请联系我们删除。

“爬虫 selenium”的评论:

还没有评论