目录
认识Selenium
Selenium是什么
这里引用Selenium中文网的介绍:
“Selenium测试直接运行在浏览器中,就像真正的用户在操作一样”
Selenium 是web自动化测试工具集,包括IDE、Grid、RC(selenium 1.0)、WebDriver(selenium 2.0)等。
Selenium IDE 是firefox浏览器的一个插件。提供简单的脚本录制、编辑与回放功能。
Selenium Grid 是用来对测试脚步做分布式处理。现在已经集成到selenium server 中了。
RC和WebDriver 更多应该把它看成一套规范,在这套规范里定义客户端脚步与浏览器交互的协议。以及元素定位与操作的接口。
Selenium的发展
Selenium 诞生于 2004 年,Selenium RC(远程控制)和 Selenium ID诞生也就是Selenium1,由于它使用的是基于Javascript的自动化引擎,浏览器对于Javascript的使用有诸多限制,使得Selenium的使用非常艰难。2006年出现了一个新项目WebDriver,这一项目主要目的是为了解决JavaScript环境沙箱(沙箱是一种按照安全策略限制程序行为的执行环境。)问题,能够能通过浏览器和操作系统的本地方法直接和浏览器进行通话。2008年Selenium和WebDriver两项目合并,这就是Selenium2。2016 年,Selenium 3 诞生。移除了不再使用的 Selenium 1 中的 Selenium RC,并且官方重写了所有的浏览器驱动。
Selenium的安装
使用Pycharm直接安装:
Selenium快速入门
Selenium八种元素定位方法
方法 | 示例 |
---|---|
name定位 | .find_element(By.NAME, 'value') |
id定位 | .find_element(By.ID, 'value') |
class name定位 | .find_element(By.CLASS_NAME, 'value') |
tag name定位 | .find_element(By.TAG_NAME, 'value') |
link text定位 | .find_element(By.LINK_TEXT, 'value') |
partial link text定位 | .find_element(By.PARTIAL_LINK_TEXT, 'value') |
xpath定位 | .find_element(By.XPATH, 'value') |
css selector定位 | .find_element(By.CSS_SELECTOR, 'value') |
- 上面这八种方法里最强大的就是XPath了,很方便。
用百度举个例子。
用XPath来定位,可以直接右键代码。
复制它的XPath粘贴到 .find_element(By.XPATH, 'value')
value中
.find_element(By.XPATH, '//*[@id="kw"]')
其实可以看到我们也可以用id定位
.find_element(By.ID, 'kw')
但是有时候在一些小网站会出现相同的id,就会定位不准确。
Selenium库常用的方法
方法 | 描述 |
---|---|
back() | 控制浏览器回退 |
clear() | 清空文本 |
click() | 单击元素 |
forward() | 控制浏览器前进 |
get_attribute(name) | 获取元素属性 |
is_displayed() | 设置元素用户是否可见 |
refresh() | 刷新当前页面 |
send_keys(‘value’) | 模拟输入 |
set_window_size() | 设置浏览器窗口大小 |
size() | 设置元素尺寸 |
submit() | 提交表单 |
text | 获取元素文本 |
Selenium实战练习
这里通过一个淘宝“抢购”脚本来练习学习一下Selenium的基础操作。
准备工作
我们先进入淘宝将整个流程操作一遍。大致可以得出以下流程
- 进入淘宝登陆页面
- 登陆成功进入购物车(可以点击页面购物车按钮/访问购物车链接)
- 等待抢购时间到达
- 选择购物车中的商品(此处简化购物车中只有待“抢购”商品,直接点击全选按钮)
- 点击“结算”按钮
- 点击“提交订单”(提交订单即为锁单成功,可以手动支付)
代码实现
设置用户代理
在开始之前我们要先设置一个请求头User-Agent(用户代理),它可以让服务器识别你使用的操作系统版本、CPU类型、浏览器信息等等。如果不去设置这个信息,直接使用爬虫打开就会出现访问错误、无权限等错误信息。
复制
options = webdriver.ChromeOptions()
user_ag = "Mozilla/5.0 *********************************** "
options.add_argument(f'user-agent={user_ag}')
driver = webdriver.Chrome(options=options)
打开淘宝
这里用到的是.get()
driver.get(
"https://login.taobao.com/member/login.jhtml?spm=a21bo.21814703.754894437.1.5af911d9tBuTtn&f=top&redirectURL"
"=https%3A%2F%2Fwww.taobao.com%2F")
# 窗口最大化
driver.maximize_window()
登录淘宝
账号密码登录
driver.find_element(By.XPATH, '//*[@id="fm-login-id"]').send_keys('user_id')
driver.find_element(By.XPATH, '//*[@id="fm-login-password"]').send_keys('password')
driver.find_element(By.XPATH, '//*[@id="login-form"]/div[4]/button').click()
这个方法登录一般情况会出现验证码,而且会一直验证失败
这里就需要注入js反反爬了,较为复杂且不是本文章的主要目的。
所以我们选择二维码登录
首先找到二维码登录的按钮,获取它的XPath。
driver.find_element(By.XPATH, '//*[@id="login"]/div[1]/i').click()
进入购物车
扫码登陆成功进入购物车
driver.get('https://cart.taobao.com/')
选择商品
这里为了方便直接点击全选,找到全选的XPath路径。
driver.find_element(By.XPATH, '//*[@id="J_SelectAll2"]').click()
结算
driver.find_element(By.XPATH, '//*[@id="J_Go"]/span').click()
提交订单
driver.find_element(By.XPATH, '//*[@id="submitOrderPC_1"]/div[1]/a[2]').click()
大家可以试一下用其他定位方法尝试一下,还是很简单的。
完整代码
from datetime import datetime
from selenium import webdriver
import time
import json
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
# 方法一,密码登录
def login1():
driver.find_element(By.XPATH, '//*[@id="fm-login-id"]').send_keys('15097922996')
driver.find_element(By.XPATH, '//*[@id="fm-login-password"]').send_keys('sr1317ba1')
driver.find_element(By.XPATH, '//*[@id="login-form"]/div[4]/button').click()
try:
# 找到滑块
slider = driver.find_element(By.XPATH, '//*[@id="nc_1_n1z"]')
# 判断滑块是否可见
if slider.is_displayed():
# 点击并且不松开鼠标
ActionChains(driver).click_and_hold(on_element=slider).perform()
# 往右边移动258个位置
ActionChains(driver).move_by_offset(xoffset=258, yoffset=0).perform()
# 松开鼠标
ActionChains(driver).pause(0.5).release().perform()
except:
time.sleep(7)
# 方法二,二维码登录(最稳定)
def login2():
driver.find_element(By.XPATH, '//*[@id="login"]/div[1]/i').click()
# 扫码登陆
print('扫码')
# 设置等待时间
time.sleep(10)
print('即将开始')
# driver.find_element(By.XPATH, '//*[@id="login-form"]/div[4]').click()
time.sleep(3)
if __name__ == '__main__':
# 抢购时间设置
# 获取电脑现在的时间, year month day
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
times = f'{now[:8]}{input("日:")} {input("时:")}:{input("分:")}:{input("秒:")}.000000'
options = webdriver.ChromeOptions()
user_ag = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 " \
"Safari/537.36 "
options.add_argument('user-agent=%s' % user_ag)
driver = webdriver.Chrome(executable_path="chromedriver", options=options)
# 注入js代码反反爬
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
# 打开淘宝登录页面
# 窗口最大化
driver.maximize_window()
# 登录
login1()
time.sleep(1)
# 登录后跳转购物车
driver.get('https://cart.taobao.com/')
not_already = True
while not_already:
try:
print('等待抢购时间到达')
# 脚本注入当前页面
sreach_window = driver.window_handles
driver.switch_to.window(sreach_window[-1])
# 获取电脑现在的时间, year month day
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
# 对比时间,时间到的话就点击结算
print(now)
print('抢购时间:\n', times)
# 判断是不是到了秒杀时间?
if now > times:
# 刷新界面全选购物车
while True:
try:
# driver.refresh()
if driver.find_element(By.XPATH, '//*[@id="J_SelectAll2"]'):
driver.find_element(By.XPATH, '//*[@id="J_SelectAll2"]').click()
# driver.find_element(By.XPATH, '//*[@id="J_SelectAll2"]').click()
print("全选商品")
time.sleep(2)
break
except Exception as e:
print(e)
print('全选失败')
# driver.close()
time.sleep(0.01)
while True:
try:
# print("点击结算按钮")
break
except Exception as e:
print(e)
print("结算失败")
# driver.close()
pass
time.sleep(0.01)
while True:
try:
sreach_window = driver.window_handles
time.sleep(1)
driver.switch_to.window(sreach_window[-1])
if driver.find_element(By.XPATH, '//*[@id="submitOrderPC_1"]/div[1]/a[2]'):
print("提交订单")
driver.find_element(By.XPATH, '//*[@id="submitOrderPC_1"]/div[1]/a[2]').click()
print('over')
not_already = False
time.sleep(3)
break
except Exception as e:
print(e)
print("提交订单失败")
# driver.close()
pass
time.sleep(0.01)
except:
pass
time.sleep(0.01)
driver.close()