"在当今数字化的世界中,网页自动化已经成为了不可或缺的技能。想象一下,您可以通过编写代码,让浏览器自动执行各种操作,从点击按钮到填写表单,从网页抓取数据到进行自动化测试。学习 Selenium,这一功能强大的自动化工具,将为您打开无尽的可能性。在本博客中,您将深入探索 Selenium 的精髓,学习如何构建稳定、高效的自动化脚本,以及如何应用这些技能来提升工作效率、加速开发流程和实现可靠的网页交互。无论您是一名开发人员、自动化工程师还是对网页技术感兴趣的爱好者,本博客将带您踏上一段令人激动的学习之旅,释放出无限的可能性。准备好挑战传统、超越自我,掌握 Selenium,引领网页自动化的未来吗?让我们一起探索吧!"
Selenium
简介
简介
Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,
可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。
Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
官网
selenium官网
https://selenium-python.readthedocs.io/index.html
注意
Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用
但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器
安装
安装selenium
pip install selenium
安装ChromeDriver
国内源
https://registry.npmmirror.com/binary.html?path=chromedriver/
ChromeDriver
版本号要对应/帮助-关于Google Chrome——>找到对应版本下载——>下载的文件解压到python_version\Scripts
安装Firefox geckodriver
国内源
https://download-installer.cdn.mozilla.net/pub/firefox/releases/
Firefox geckodriver
安装firefox最新版本,添加Firefox可执行程序到系统环境变量。记得关闭firefox的自动更新
将下载的geckodriver.exe 放到path路径下 D:\Python\python_version\
基础知识
基础操作
创建浏览器对象
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
打开页面
chrome.get('http://www.baidu.com')
打开本地页面
import os
file_path='file:///'+os.path.abspath('./1.下拉菜单.html')
chrome.get(file_path)
获取页面html源码【换行】
page = chrome.page_source
休眠
from time import sleep
sleep(8)
关闭浏览器
chrome.quit()
操作浏览器
窗口大小
chrome.maximize_window() #窗口最大化
chrome.set_window_size(600, 800) #设置窗口大小
前进和后退
chrome.forward()
chrome.back()
基础定位
定位元素
from selenium.webdriver.common.by import By
chrome.find_element(By.ID,'su')
chrome.find_element(By.XPATH, "//option[@value='10.69']").click()
find_element(type,value) 一个元素
find_elements(type,value) 多个元素
By中参数选择
XPATH【xpath选择器】
ID【id属性】
NAME【name属性 】
CLASS_NAME 【class属性】
LINK_TEXT 【超链接的文本】
PARTIAL_LINK_TEXT = "partial link text"
TAG_NAME = "tag name"
CSS_SELECTOR = "css selector"
操作元素
click 点击对象
send_keys 在对象上模拟按键输入
clear 清除对象的内容,如果可以的话
基础示例
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
chrome.get('http://www.baidu.com')
sleep(3)
chrome.find_element(By.ID, 'kw').send_keys('CSDN')
sleep(3)
chrome.find_element(By.ID, 'su').click()
sleep(3)
常用操作
定位下拉菜单
注意
在定位下拉菜单时,要先定位到父级元素,然后再做一个模拟光标移动,再点击所选项
页面代码
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Level Locate</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.9/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<h3>Level locate</h3>
<div class="span3 col-md-3">
<div class="well">
<div class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Link1</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" id="dropdown1" >
<li><a tabindex="-1" href="http://www.bjsxt.com">Action</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
<li><a tabindex="-1" href="#">Something else here</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="#">Separated link</a></li>
</ul>
</div>
</div>
</div>
<div class="span3 col-md-3">
<div class="well">
<div class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Link2</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" >
<li><a tabindex="-1" href="#">Action</a></li>
<li><a tabindex="-1" href="#">Another action</a></li>
<li><a tabindex="-1" href="#">Something else here</a></li>
<li class="divider"></li>
<li><a tabindex="-1" href="#">Separated link</a></li>
</ul>
</div>
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.9/dist/js/bootstrap.min.js"></script></html>
核心代码
# 定位父级元素
chrome.find_element(By.LINK_TEXT, 'Link1').click()
sleep(4)
# 做一个移动光标的动作【模拟人工,非必要】
menu = chrome.find_element(By.LINK_TEXT, 'Action')
webdriver.ActionChains(chrome).move_to_element(menu).perform()
# 定位子集元素
menu.click()
示例代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
import os
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
file_path = 'file:///' + os.path.abspath('./1.下拉菜单.html')
chrome.get(file_path)
sleep(3)
# 定位父级元素
chrome.find_element(By.LINK_TEXT, 'Link1').click()
sleep(4)
# 做一个移动光标的动作【模拟人工,非必要】
menu = chrome.find_element(By.LINK_TEXT, 'Action')
webdriver.ActionChains(chrome).move_to_element(menu).perform()
# 定位子集元素
menu.click()
sleep(4)
定位下拉框
简介
相比定位下拉菜单,下拉框可以直接定位到元素
页面代码
<html>
<body>
<select id="ShippingMethod" onchange="updateShipping(options[selectedIndex]);" name="ShippingMethod">
<option value="12.51">UPS Next Day Air ==> $12.51</option>
<option value="11.61">UPS Next Day Air Saver ==> $11.61</option>
<option value="10.69">UPS 3 Day Select ==> $10.69</option>
<option value="9.03">UPS 2nd Day Air ==> $9.03</option>
<option value="8.34">UPS Ground ==> $8.34</option>
<option value="9.25">USPS Priority Mail Insured ==> $9.25</option>
<option value="7.45">USPS Priority Mail ==> $7.45</option>
<option value="3.20" selected="">USPS First Class ==> $3.20</option>
</select>
</body>
</html>
核心代码
# 定位到选择框,并利用xpath进行选取
m = chrome.find_element(By.ID, "ShippingMethod")
m.find_element(By.XPATH, "//option[@value='10.69']").click()
示例代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
import os
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
file_path = 'file:///' + os.path.abspath('./3.drop_down.html')
chrome.get(file_path)
sleep(3)
# 定位到选择框,并利用xpath进行选取
m = chrome.find_element(By.ID, "ShippingMethod")
m.find_element(By.XPATH, "//option[@value='10.69']").click()
sleep(3)
chrome.quit()
定位层级内元素
简介
有时候我们定位一个元素,定位器没有问题,但一直定位不了,这时候就要检查这个元素是否在一个frame中
页面代码
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<title>inner</title>
</head>
<body>
<div class="row-fluid">
<div class="span6 well">
<h3>inner</h3>
<iframe id="f2" src="https://cn.bing.com/" width="700" height="500"></iframe>
</div>
</div>
</body>
</html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<title>frame</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"
rel="stylesheet"/>
</head>
<body>
<div class="row-fluid">
<div class="span10 well">
<h3>frame</h3>
<iframe id="f1" src="2.inner.html" width="800" , height="600"></iframe>
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/@bootcss/v3.bootcss.com@1.0.8/dist/js/bootstrap.min.js"></script>
</html>
</html>
核心代码
可以利用以下方法进入到内层元素【参数时id属性】
chrome.switch_to.frame('f1')
示例代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
import os
# 定位层级内元素【三层】
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
file_path = 'file:///' + os.path.abspath('./2.outer.html')
chrome.get(file_path)
sleep(3)
# 切换到frame里【根据id】
chrome.switch_to.frame('f1')
chrome.switch_to.frame('f2')
# 定位三层里的元素【www.baidu.com】
chrome.find_element(By.ID, 'sb_form_q').send_keys('CSDN')
chrome.find_element(By.ID, 'search_icon').click()
sleep(3)
处理弹窗
页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>This is a page</title>
</head>
<body>
<div id="container">
<div style="font: size 30px;">Hello,Python Spider</div>
</div>
</body>
<script>
alert('这个是测试弹窗')
</script>
</html>
核心代码
# 定位弹出窗口,并点击
chrome.switch_to.alert.accept()
示例代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
import os
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
file_path = 'file:///' + os.path.abspath('./4.弹出框.html')
chrome.get(file_path)
sleep(3)
# 定位弹出窗口,并点击
chrome.switch_to.alert.accept()
sleep(4)
chrome.quit()
拖拽元素
简介
拖拽元素:如拖拽div标签【块级】
页面代码
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Auto-scroll</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
#draggable, #draggable2, #draggable3 { width: 100px; height: 100px; padding: 0.5em; float: left; margin: 0 10px 10px 0; }
body {font-family: Arial, Helvetica, sans-serif;}
table {font-size: 1em;}
.ui-draggable, .ui-droppable {background-position: top;}
</style>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$( "#draggable" ).draggable({ scroll: true });
$( "#draggable2" ).draggable({ scroll: true, scrollSensitivity: 100 });
$( "#draggable3" ).draggable({ scroll: true, scrollSpeed: 100 });
} );
</script>
</head>
<body>
<div id="draggable" class="ui-widget-content">
<p>Scroll set to true, default settings</p>
</div>
<div id="draggable2" class="ui-widget-content">
<p>scrollSensitivity set to 100</p>
</div>
<div id="draggable3" class="ui-widget-content">
<p>scrollSpeed set to 100</p>
</div>
<div style="height: 5000px; width: 1px;"></div>
</body>
</html>
核心代码
# 定位要拖拽的元素
div1 = chrome.find_element(By.ID, 'draggable')
div2 = chrome.find_element(By.ID, 'draggable2')
div3 = chrome.find_element(By.ID, 'draggable3')
sleep(3)
# 拖拽【把div1拖拽到div2处】
ActionChains(chrome).drag_and_drop(div1, div2).perform()
sleep(3)
# 拖拽【把div3向左/下各拖拽10px】
ActionChains(chrome).drag_and_drop_by_offset(div3, 10, 10).perform()
sleep(3)
示例代码
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from time import sleep
from selenium.webdriver.common.by import By
import os
# 定位弹出框
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
file_path = 'file:///' + os.path.abspath('./5.拖拽元素.html')
chrome.get(file_path)
sleep(3)
# 定位要拖拽的元素
div1 = chrome.find_element(By.ID, 'draggable')
div2 = chrome.find_element(By.ID, 'draggable2')
div3 = chrome.find_element(By.ID, 'draggable3')
sleep(3)
# 拖拽【把div1拖拽到div2处】
ActionChains(chrome).drag_and_drop(div1, div2).perform()
sleep(3)
# 拖拽【把div3向左/下各拖拽10px】
ActionChains(chrome).drag_and_drop_by_offset(div3, 10, 10).perform()
sleep(3)
chrome.quit()
调用JS方法
简介
有时候我们需要控制页面滚动条上的滚动条,但滚动条并非页面上的元素,这个时候就需要借助js是来进行操作
注意
js都可以直接打开浏览器开发者工具去测试
控制台————输入js即可
核心代码
js = "window.scrollTo(100,400)"# 拉动滚动条
driver.execute_script(js)
示例代码
from selenium.webdriver.chrome.service import Service
from selenium import webdriver
from time import sleep
service = Service('./chromedriver.exe')
chrome = webdriver.Chrome(service=service)
chrome.get('https://www.jd.com/')
# 拉动滚动条
js = "window.scrollTo(100,400)"
chrome.execute_script(js)
sleep(3)
功能
等待元素
强制等待
作用:当代码运行到强制等待这一行的时候,无论出于什么原因,都强制等待指定的时间,需要通过time模块实现
优点:简单
缺点:无法做有效的判断,会浪费时间
from time import sleep
sleep(3)
隐式等待
作用:到了一定的时间发现元素还没有加载,则继续等待我们指定的时间,
如果超过了我们指定的时间还没有加载就会抛出异常,如果没有需要等待的时候就已经加载完毕就会立即执行
优点: 设置一次即可,所有操作都会等待
缺点:必须等待加载完成才能到后续的操作,或者等待超时才能进入后续的操作
from selenium import webdriver
chrome.implicitly_wait(10)
显示等待
作用:指定一个等待条件,并且指定一个最长等待时间,会在这个时间内进行判断是否满足等待条件,如果成立就会立即返回,
如果不成立,就会一直等待,直到等待你指定的最长等待时间,如果还是不满足,就会抛出异常,如果满足了就会正常返回
优点:专门用于对指定一个元素等待,加载完即可运行后续代码
缺点:多个元素都需要要单独设置等待
from selenium.webdriver.support.wait import WebDriverWait
# 0.5:指定检查条件的频率,单位为秒。也就是每隔0.5秒检查一次条件是否满足
wait = WebDriverWait(driver,10,0.5)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'next')))
隐藏浏览器
实现
# 设置参数,将浏览器隐藏起来(无头浏览器)
options = ChromeOptions()
options.add_argument('--headless')
# 创建Chrome浏览器时加入参数
service = Service('./chromedriver')
driver = Chrome(service=service,options=options)
代理模式
实现1
# 设置参数,给浏览器设置代理
options = ChromeOptions()
# options.add_argument('--proxy-server=http://ip:port')
options.add_argument('--proxy-server=http://221.199.36.122:35414')
# 设置驱动
service = Service('./chromedriver')
# 启动Chrome浏览器
driver = Chrome(service=service,options=options)
实现2
from selenium.webdriver.common.proxy import ProxyType,Proxy
# 设置参数,给浏览器设置代理
ip = 'http://113.76.133.238:35680'
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = ip
proxy.ssl_proxy = ip
# 关联浏览器
capabilities = DesiredCapabilities.CHROME
proxy.add_to_capabilities(capabilities)
# 设置驱动
service = Service('./chromedriver')
# 启动Chrome浏览器
driver = Chrome(service=service,desired_capabilities=capabilities)
防检测设置
实现
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
options = ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)
chrome = Chrome(chrome_options=options)
chrome.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => false
})
"""
})
chrome.get('http://httpbin.org/get')
info = chrome.page_source
print(info)
sleep(20)
实战
虎牙
爬取英雄联盟全部分页的主播和对应的人气
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from lxml import etree
from selenium.webdriver.common.by import By
service = Service('../0.工具/chromedriver.exe')
chrome = webdriver.Chrome(service=service)
# 设置隐式等待
chrome.implicitly_wait(5)
# 爬取英雄联盟页面的数据
chrome.get('https://www.huya.com/g/lol')
# 做一个循环,退出条件是下一页没有数据
while True:
# 分析数据
e = etree.HTML(chrome.page_source)
names = e.xpath('//i[@class="nick"]/@title') # 获取主播昵称
person_nums = e.xpath('//i[@class="js-num"]/text()') # 获取主播人气
# 提取数据
for n, p in zip(names, person_nums):
print(f'{n}————————————{p}')
try:
# 找到下一页的按钮
next_btn = chrome.find_element(By.XPATH, '//a[@class="laypage_next"]')
# 点击下一页
next_btn.click()
except Exception as e:
break
# if chrome.page_source.find('laypage_next') == -1:
# break
# # 找到下一页的按钮
# next_btn = chrome.find_element(By.XPATH, '//a[@class="laypage_next"]')
# # 点击下一页
# next_btn.click()
chrome.quit()