selenium 介绍
selenium是web脚本测试工具,在爬虫中也可以利用它来模拟真人操作,在一些防爬机制比较严格的网页爬虫中十分有效,它的优势在于能模拟真人操作,处理动态渲染网页、验证码等情况,缺点在于效率较低。
本文写作流程
声明 笔者水平有限,有错误欢迎指出。笔者也借此记录selenium学习的过程,以便后续复习。
1.1 安装selenium库
conda install selenium
1.2 selenium常用类
selenium官方技术文档
selenium官方技术文档
①webdriver类主要方法和属性
②BY类
③WebElement类的方法及属性
④Wait类
⑤expected_conditions (EC)类
⑥TimeoutException 类
1.2.1webdriver类主要方法和属性
1、库导入
from selenium.webdriver import webdriver
2、实例化webdriver 类
driver = webdriver.Edge()
可选的浏览器
.Edge()
.Chrom()
…
3、driver 对象的方法及属性
driver.get(url)
driver.exit()
diver.find_element(BY. , " ") #返回一个WebElement
driver.find_elements(BY. , " ") #返回由WebElement 组成的列表
driver.title
1.2.2 By类
用于定位页面元素,作为dircer.find_element()的参数
1、库导入
from selenium.webdriver.common.by import By
2、定位策略
By 类提供了多种定位策略,可以根据元素的不同属性来选择最合适的策略。这些策略包括:
ID:通过元素的 id 属性定位。
Name:通过元素的 name 属性定位。
Class Name:通过元素的 class 属性定位。
Tag Name:通过元素的标签名定位(如 div, span)。
CSS Selector:通过 CSS 选择器定位。
CSS选择器解释链接
XPath:通过 XPath 表达式定位。
3、使用不同的 By 方法定位元素
# 通过 ID 定位
element_by_id = driver.find_element(By.ID, 'element_id')
# 通过 Name 定位
element_by_name = driver.find_element(By.NAME, 'element_name')
# 通过 Class Name 定位
element_by_class_name = driver.find_element(By.CLASS_NAME, 'element_class')
# 通过 Tag Name 定位
element_by_tag_name = driver.find_element(By.TAG_NAME, 'div')
# 通过 CSS Selector 定位
element_by_css_selector = driver.find_element(By.CSS_SELECTOR, '.class_name #element_id')
# 通过 XPath 定位
element_by_xpath = driver.find_element(By.XPATH, '//div[@id="element_id"]')
By类作为EC.element_to_be_clickable()的参数时,(by, value)作为元组传入
#示例代码
next_page_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button/span[contains(text(),"下一页")]')))
1.2.3 WebElement对象的方法及属性**
WebElement对象一般是某个页面元素
1、WebElement对象常用方法
click()
# 模拟点击元素的操作。
element.click()
send_keys(*value)
# 向元素发送键盘输入。特殊的输入包含在Keys类中,包括RETURN、ALT等
element.send_keys("text to input")
clear()
# 清除元素中的内容(通常用于输入框)。
element.clear()
submit()
# 提交表单。如果元素位于表单内,则提交该表单。
element.submit()
get_attribute(name)
# 获取元素的属性值。
attribute_value = element.get_attribute("attribute_name")
get_property(name)
# 获取元素的属性值。与 get_attribute 类似,但更倾向于 JavaScript 属性。
property_value = element.get_property("property_name")
get_css_value(property_name)
# 获取元素的 CSS 样式属性值。
css_value = element.get_css_value("property_name")
is_displayed()
# 检查元素是否在页面上可见。
is_visible = element.is_displayed()
is_enabled()
# 检查元素是否可用。
is_enabled = element.is_enabled()
is_selected()
# 检查元素是否被选中(适用于复选框、单选按钮等)。
is_selected = element.is_selected()
find_element(by, value)
# 在当前元素内查找子元素。
child_element = element.find_element(By.CSS_SELECTOR, "selector")
1.2.4 wait类
等待类用于实现显式等待,直到某个条件发生为止。Selenium 提供了 WebDriverWait 和条件类 expected_conditions。
以下转载
3.5.1 元素级等待机制——强制等待
利用time模块中的time.sleep()来实现,这种做法的弊端很明,处理起来毫无弹性。执行的速度和机器的性能有关,如果有一台机器严重卡顿,登录面板有可能 3s 都弹不出来
import time
time.sleep(5)
3.5.2 元素级等待机制——隐式等待
webdriver.implicitly_wait(等待秒数)
是在执行 find_element()/find_elements()这类函数时,如果在规定的时间内找到元素那么将立即结束等待,否则会一直等待,如果超过时间元素还未出现就会抛出找不到元素的异常
案例演示
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 设置的最长隐式等待时间为 10s
driver.get("https://www.baidu.com")
driver.find_element(By.LINK_TEXT, "登录").click()
driver.find_element(By.LINK_TEXT, "立即注册").click()
在这个案例中虽然设置的最长隐式等待时间为 10s,但由于通常 1s 内登录面板就会弹出,因此 Selenium 检测到元素已经存在就会结束等待立即执行下一行代码
注:隐式等待是全局设置的,一旦设置会在整个WebDriver实例的生命周期内生效
3.5.3 元素级等待机制——显示等待
元素级等待的最佳实践方式是显示等待,显示等待机制只需要指定条件判断函数,Selenium会每隔一定的时间检测该条件是否成立,如果成立就立刻执行下一步,否则一直等待,直到超过最大等待时间抛出超时异常
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait 的实例化方法如下
WebDriverWait(WebDriver实例, 超时秒数, 检测时间间隔[可选], 可忽略异常集合[可选] )
‘’’
可选参数1:检测时间间隔:调用 until 或 until_not 传入的条件判断函数的间隔时间,默认为 0.5s
可选参数2:可忽略异常集合:在调用 until 或 until_not 中传入的条件判断函数时,如果抛出的是这个集合中定义的异常,代码就不会执行失败,会继续正常执行
‘’’
实例化 WebDriverWait 对象后,可以调用 WebDriverWait 对象的以下两个函数来执行等待,等待直到条件判断函数的返回值不为 False
WebDriverWait.until(条件判断函数, “超时后的自定义异常消息”[可选])
WebDriverWait.until_not(条件判断函数, “超时后的自定义异常消息”[可选])
# 等待元素可见
wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((By.ID, 'element_id')))
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接
1.2.4 expected_conditions (EC)类
该类包含了许多条件,用于在显式等待中判断条件是否满足。
1、库导入
from selenium.webdriver.support import expected_conditions as EC
2、常用方法
# 等待元素可点击
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'element_id')))
......
1.2.5 TimeoutException 类
是 Selenium 中用于处理超时情况的异常类。它通常在等待某个条件满足或某个元素加载时出现,当超时时间到达而条件未满足时会抛出该异常。TimeoutException 是一个继承自 WebDriverException 的类。
1、导入 TimeoutException 类
要在代码中处理 TimeoutException,首先需要从 selenium.common.exceptions 导入
from selenium.common.exceptions import TimeoutException
2、什么时候会抛出 TimeoutException
显式等待超时:当使用显式等待 (WebDriverWait) 等待某个条件时,如果在规定的时间内条件没有满足,就会抛出 TimeoutException。
页面加载超时:如果设置了页面加载超时时间,而页面没有在规定时间内加载完毕,也会抛出该异常。
3、示例
try:
# 使用显式等待等待元素加载,最长等待时间为10秒
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'example_element_id'))
)
print(element.text)
except TimeoutException:
print("超时异常:元素未在规定时间内加载")
finally:
# 关闭浏览器
driver.quit()
2、下载浏览器对应驱动并设置系统路径
浏览器驱动的下载在此省略,自行浏览器搜索相关博客。
有遇到的报错
selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for MicrosoftEdge
最终解决的方法是重新在环境变量中设置了Path,我原来设的Path变量只设到了msedgedriver.exe所在的文件夹,后来加到了msedgedriver.exe的位置。
#原来的
#D:\
#后来的
#D:\msedgedriver.exe
3、CMD端打开浏览器并设置端口
大致步骤,管理员运行打开CMD
cd C:\Program Files (x86)\Microsoft\Edge\Application
msedge.exe --remote-debugging-port=9222 --user-data-dir="D:\AutoEdge"
#这里的AutoEdge文件用于存放浏览器产生的数据
遇到的报错
WebDriverException: Message: no such execution context: frame does not have execution context
后来搜索这个ERROR,原来是第一次cmd端打开Edge浏览器时设置的用户数据文件不能有其它东西,要建一个空的文件夹。
msedge.exe --remote-debugging-port=9222 --user-data-dir="D:\AutoEdge"
#这里第一次运行这句代码时,AutoEdge得是一个空的文件夹。
Edge浏览器端口接法教程
传送门
4、seleniuim接管浏览器&爬虫
爬取思路参考https://blog.csdn.net/fullbug/article/details/136296522
链接中案例基于Chrom浏览器,但我想使用Edge浏览器,selenium3对Chrom浏览器和Edge浏览器的webdriver对象的options参数是不一样的,所以我的接口在CMD端写好后,还得弄明白Edge浏览器的options参数怎么写。
找到了这篇文档,记录了EdgeOptions()对象的使用。linkhttps://www.cnblogs.com/fanghsiu/p/15838879.html
但我还是不明白怎么添加port参数和日志文件地址参数。
查看了selenium官方文档
https://github.com/SeleniumHQ/seleniumhq.github.io/blob/trunk/examples/python/tests/browsers/test_edge.py
在初始化Edge浏览器这步,遇到了很多报错,最终实现时的代码如下
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
# 指定 msedgedriver 的路径
driver_path = "D:\msedgedriver.exe" # 请替换为实际的 msedgedriver 路径
# 初始化浏览器
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
service = Service(executable_path=driver_path)
driver = webdriver.Edge(service=service, options=options)
遇到的报错
在代码中,当我想将executable_path=driver_path直接作为webdriver.Edge()的参数时,也遇到了报错,报错信息提示没有executable这个参数,后来在ChatGPT的帮助下通过Service类添加。代码如上。
已成功爬取,附上完整代码
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException, NoSuchWindowException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from urllib.parse import quote
from pyquery import PyQuery as pq
import time
# 指定 msedgedriver 的路径
driver_path = "D:\msedgedriver.exe" # 请替换为实际的 msedgedriver 路径
# 初始化浏览器
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
service = Service(executable_path=driver_path)
try:
driver = webdriver.Edge(service=service, options=options)
except Exception as e:
print(f"初始化 WebDriver 时发生错误: {e}")
raise
wait = WebDriverWait(driver, 240)
def login_taobao():
try:
login_url = 'https://login.taobao.com//member//login.jhtml'
driver.get(login_url)
# input_login_id = wait.until(EC.presence_of_element_located((By.NAME, "fm-login-id")))
# input_login_passward = wait.until(EC.presence_of_element_located((By.NAME, "fm-login-password")))
# input_login_id.send_keys("")# *************************添加自己的账号
# input_login_passward.send_keys("") #***************添加自己的密码
# submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit.password-login')))
# submit.click()
is_login = wait.until(EC.url_changes(login_url))
return is_login
except TimeoutException:
print("TimeoutException")
# submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.fm-button.fm-submit.password-login')))
# submit.click()
is_login = wait.until(EC.url_changes(login_url))
if is_login:
return is_login
else:
login_taobao()
def get_products(products):
try:
html = driver.page_source
doc = pq(html)
items = doc('.Card--doubleCardWrapper--L2XFE73').items()
for item in items:
p = {
'url': item.attr('herf'),
'price': item.find('.Price--priceInt--ZlsSi_M').text() + item.find(
".Price--priceFloat--h2RR0RK").text(),
'title': item.find('.Title--title--jCOPvpf').text(),
'shop': item.find(".ShopInfo--shopName--rg6mGmy").text(),
'salenum': item.find('.Price--realSales--FhTZc7U').text()}
print(p)
products.append(p)
except:
print("-----get_products_ERROR-------")
def Index_page(url, cur_page, max_page, products):
try:
driver.get(url)
get_products(products)
time.sleep(5)
next_page_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//button/span[contains(text(),"下一页")]')))
next_page_btn.click()
change = wait.until(EC.url_changes(url))
if change and cur_page < max_page:
url = driver.current_url
cur_page = cur_page + 1
Index_page(url, cur_page, max_page, products)
except TimeoutException:
print('--------Index_page() TimeoutException----------')
def main():
is_login = login_taobao()
if is_login:
KEYWORD = "植物"
url = "https://s.taobao.com//search?area=c2c&commend=all&page=1&q=" + quote(KEYWORD) + "&tab=all"
max_page = 10
products = []
Index_page(url, 1, max_page, products)
else:
print('登录失败')
main()
版权归原作者 Nianianla 所有, 如有侵权,请联系我们删除。