文章目录
简答题
总结selenium的特点
- 开源、免费
- 跨平台:Linux,windows,MAC, Solaris
- 支持多浏览器:chrome, IE, firefox, Edge, Oprea
- 支持多语言:C#, Java, Perl, PHP, Python, Ruby
selenium常用API
元素定位
定位方法:
# selenium 4.x 版本使用:
from selenium.webdriver.common.by import By
driver.find_element(By.xxx, xxx)
id定位
通过id属性来定位元素
HTML规定id属性在整个HTML文档中必须是唯一的
from selenium.webdriver.common.by import By
driver.find_element(By.ID, id)
name定位
以name属性定位
HTML文档中name属性值可以重复
from selenium.webdriver.common.by import By
driver.find_element(By.NAME, name)
class_name定位
根据元素class属性定位
HTML通过使用class来定义元素的样式
from selenium.webdriver.common.by import By
driver.find_element(By.CLASS_NAME, class_name)
tag_name定位
通过标签名定位
HTML本质是由不同tag组成,每一个tag会在页面中存在多个,所以不方便进行精确定位,一般很少使用
from selenium.webdriver.common.by import By
driver.find_element(By.TAG_NAME, tag_name)
link_text定位
专门用来定位超链接元素<a>标签</a>
,并且是通过超链接的文本内容来定位元素
link_text为超链接的全部文本内容
from selenium.webdriver.common.by import By
driver.find_element(By.LINK_TEXT, link_text)
partial_link_text定位
对link_text的补充,可以使用局部文本匹配元素
from selenium.webdriver.common.by import By
driver.find_element(By.PARTIAL_LINK_TEXT, partial_link_text)
XPath定位
- 路径-定位
- 绝对路径: /html根结点开始,使用/分隔元素层级(不建议使用)
- 相对路径: 以 // 开始,//input 或 //*
- 元素属性-定位
//input[@id='属性值']
或者//*[@id='属性值']
- 属性与逻辑结合-定位(多个属性)
//*[@name='属性值' and @class='属性值']
- 层级与属性结合-定位(找父属性)
//*[@id='p1']/input
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, xpath)
Xpath-延伸
//*[text()="xxx"] # 文本内容是xxx的元素
//*[contains(@attribute, 'xxx')] # 属性中含有xxx的元素
//*[starts-with(@attribute, 'xxx')] # 属性以xxx开头的元素
CSS定位
- id选择器
- #id
- class选择器
- .class
- 元素选择器
- 根据元素的标签名选择
- element
- 属性选择器
- 根据元素的属性名和值选择
- [attribute=value] 或者 element[attribute=value]
- 层级选择器
- 根据元素的父子关系选择
- element1>element2,element2必须为element1的直接子元素
- element1 element2,element2为element1的后代元素
from selenium.webdriver.common.by import By
driver.find_element(By.CSS_SELECTOR, css_selector)
CSS延伸
input[type^='p'] # type属性以p字母开头的元素
input[type$='d'] # type属性以d字母结束的元素
input[type*='w'] # type属性包含w字母的元素
元素操作、浏览器操作方法
- 元素常用的操作方法
- 使用方法:定位元素.方法
- 例:
driver.find_element(By.ID, 'su').click()
click() # 单击元素
send_keys(value) # 模拟输入
clear() # 清除文本
- 操作浏览器的常用方法
- 使用方法:driver.方法(前提:
driver = webdriver.Chrome()
) - 例:
driver.maximize_window() # 窗口最大化
- 使用方法:driver.方法(前提:
maximize_window() # 最大化浏览器窗口 --> 模拟浏览器最大化按钮
set_window_size(width, height) # 设置浏览器窗口大小 --> 设置浏览器宽、高(像素点)
set_window_position(x, y) # 设置浏览器窗口位置 --> 设置浏览器位置
back() # 后退 --> 模拟浏览器后退按钮
forward() # 前进 --> 模拟浏览器前进按钮
refresh() # 刷新 --> 模拟浏览器F5刷新
close() # 关闭当前窗口 --> 模拟点击浏览器关闭按钮
quit() # 关闭浏览器驱动对象 --> 关闭所有程序启动的窗口
title # 获取页面title
current_url # 获取当前页面URL
close()和quit()区别:
- close():关闭当前主窗口
- quit():关闭由driver对象启动的所有窗口
当前只有一个窗口二者没有区别
- 获取元素信息的常用方法
- 使用方法:定位元素.方法
- 例:
driver.find_element(By.ID, 'su').get_attribute("id")
size # 返回元素大小
text # 获取元素的文本
get_attribute("xxx") # 获取属性值,传递的参数为元素的属性名
is_displayed() # 判断元素是否可见
is_enabled() # 判断元素是否可用
is_selected() # 判断元素是否选中,用来检查复选框或单选按钮是否被选中
- text和size调用时没有括号
- get_attribute使用场景:判断一组元素是否为想要的元素或者判断元素属性值是否正确
鼠标和键盘操作
- 鼠标操作的方法
- 说明:在Selenium中将操作鼠标的方法封装在ActionChains类中
导包:from selenium.webdriver import ActionChains
实例化对象:action = ActionChains(driver)
方法
context_click(element).perform() # 右击
double_click(element).perform() # 双击
drag_and_drop(source, target).perform() # 拖动
move_to_element(element).perform() # 悬停
- 键盘操作的方法
- 使用方法:定位元素.send_keys(方法)
- 例:
driver.find_element(By.ID, 'su').send_keys(Keys.BACKSPACE)
导包:from selenium.webdriver import Keys
方法
send_keys(Keys.BACK_SPACE) # 删除键(BackSpace)
send_keys(Keys.SPACE) # 空格键(Space)
send_keys(Keys.TAB) # 制表键(Tab)
send_keys(Keys.ESCAPE) # 回退键(Esc)
send_keys(Keys.ENTER) # 回车键(Enter)
send_keys(Keys.CONTROL,'a') # 全选(Ctrl+A)
send_keys(Keys.CONTROL,'c') # 复制(Ctrl+C)
元素等待
- 隐式等待
- 显式等待
显式等待
针对单个元素生效
定位指定元素时,如果能定位到元素则直接返回该元素,不触发等待;如果不能定位到该元素,则间隔一段时间后再去定位元素;如果达到最大时长还没有找到指定元素,则抛出超时异常TimeoutException
导包 等待类
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait()
WebDriverWait(driver, timeout, poll_frequency=0.5)
- driver:浏览器驱动对象
- timeout:超时的时长,单位:秒
- poll_frequecy:检测间隔时间,默认为0.5秒
调用方法:until(method):直到。。。时
- method:函数名称,该函数用来实现对元素的定位
- 一般使用匿名函数来实现:
- lambda x: x.find_element_by_id("userA")
应用
element = webDriverWait(driver, 10, 1).until(lambda x: x.find_element_by_id("userA"))
验证码处理
cookie跳过登录方法
- 使用方法:driver.方法
- get_cookie(name)
- name:为cookie的名称
- get_cookies() # 获取本网站所有本地cookie
- add_cookie(cookie_dict) # 添加cookie
- cookie_dict:一个字典对象,必选的键包括:"name" and "value"
添加cookie后必须使用driver.refresh()刷新方法,否则看不到登录效果
python操作mysql数据库
python操作数据库的过程:
创建连接-获取游标-执行命令-关闭游标-关闭连接
创建连接
python访问 mysql需要用pymysql库
import pymysql
def mysql_db():
conn = pymysql.connect(
host="127.0.0.1",
port=3306,
database="spider",
charset="utf8",
user="root",
passwd="root"
)
关于游标,执行SQL,查询数据
游标需要创建游标还要关闭游标,为防止忘关游标,所以用with
# 打开数据库可能有风险,所以添加异常捕捉
try:
with conn.cursor() as cursor:
# 准备sql语句
sql = "select * from user"
cursor.execute(sql)
## 执行完SQL语句后的返回结果都是保存到cursor中,所以要从cursor中获取全部数据
datas = cursor.fetchall()
print("获取的数据:\n", datas)
except Exception as e:
print("数据库操作异常:\n", e)
finally:
# 不管成功还是失败,都要关闭数据库连接
conn.close()
curcor中获取数据的fetchall, fetchone, fetchmany
- fetchall: 获取当前SQL语句能查出来的全部数据
- fetchone: 每次获取一条数据,但是获取到这条数据之后指针会往后移一行数据
- fetchmany: 直接告诉他想要多少条数据
cursor.fetchmany(3) # 获取三条数据
插入一条数据
重点一个是commit,一个是rollback。有提交的地方一定要有回滚,回滚到上次提交的地方
try:
with conn.cursor() as cursor:
# 准备sql语句
value = "12, 'zj'"
sql = f"insert into user values ({value});"
# 执行SQL语句
cursor.execute(sql)
# 执行完SQL语句之后要提交
conn.commit()
print("提交成功")
except Exeption as e:
# 如果执行失败要回滚
conn.rollback()
print("数据库操作异常:\n", e)
finally:
# 不管成功还是失败,都要关闭数据库连接
conn.close()
添加多条数据
try:
with conn.cursor() as cursor:
# 准备要插入的数据
value = "(13,'张三'),(14,'李四'),(15,'王五')"
# 准备SQL语句
sql = f"insert into user values {value};"
# 执行SQL语句
cursor.execute(sql)
# 执行完要提交
conn.commit()
print("提交成功")
except Exception as e:
# 如果执行失败要回滚
conn.rollback()
print("数据库操作异常:\n", e)
finally:
# 不管成功还是失败,都要关闭数据库连接
conn.close()
修改、更新数据
只需要修改添加的SQL语句,其他不变
增删改查,除了查询,其他都要提交
try:
with conn.cursor() as cursor:
# 准备sql语句
sql = f"update user set name='封校'"
# 执行SQL语句
cursor.execute(sql)
# 执行完提交
conn.commit()
except Exception as e:
# 执行失败回滚
conn.rollback()
print("数据库操作异常:\n", e)
finally:
# 无论是否执行成功都要关闭数据库连接
conn.close()
删除数据
try:
with conn.cursor() as cursor:
sql = "delete from user where id=12;"
cursor.execute(sql)
conn.commit()
except Exception as e:
conn.rollback()
print("数据库操作异常:\n", e)
finally:
conn.close()