selenium学习

2023-12-18 20:53:41

前期准备

pip install selenium

获取浏览器驱动

我使用的浏览器是Chrome,所以这里只介绍关于Chrome获取浏览器驱动的方法:
需要注意的是:selenium 4.x 对之前版本的部分API调用方式进行了调整,这里就包括关于浏览器获取驱动的方式,最新版本获取驱动的方式如下:
1.在Chrome浏览器的设置页面查看自己浏览的版本

2.在如下页面获取对应的驱动:

人机验证

API如下:

# 获取驱动并打开网页
service = Service(executable_path=r"/Users/liujianlei/Downloads/mopi/chromedriver-mac-arm64/chromedriver")
driver = webdriver.Chrome(service=service)

常用API

selenium常用引入的包如下:

from bs4 import BeautifulSoup
import requests
import openpyxl
from fake_useragent import UserAgent
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

常用api如下:

获取元素

新版本对获取元素的api调用方式,新的api使用方式如下:

# inputTag = driver.find_element_by_id("value")  # 利用ID查找
# 改为:
inputTag = driver.find_element(By.ID, "value")

# inputTags = driver.find_element_by_class_name("value")  # 利用类名查找
# 改为:
inputTag = driver.find_element(By.CLASS_NAME, "value")

# inputTag = driver.find_element_by_name("value")  # 利用name属性查找
# 改为:
inputTag = driver.find_element(By.NAME, "value")

# inputTag = driver.find_element_by_tag_name("value")  # 利用标签名查找
# 改为:
inputTag = driver.find_element(By.TAG_NAME, "value")

# inputTag = driver.find_element_by_xpath("value")  # 利用xpath查找
# 改为:
inputTag = driver.find_element(By.XPATH, "value")

# inputTag = driver.find_element_by_css_selector("value")  # 利用CSS选择器查找
# 改为:
inputTag = driver.find_element(By.CSS_SELECTOR, "value")

控制浏览器操作

  • 控制浏览器窗口大小

driver.set_window_size(480, 800)

  • 浏览器后退,前进

# 后退 driver.back()

# 前进 driver.forward()

  • 刷新

driver.refresh() # 刷新

鼠标操作

  • perform(): 执行所有 ActionChains 中存储的行为;
  • context_click(): 右击;
  • double_click(): 双击;
  • drag_and_drop(): 拖动;
  • move_to_element(): 鼠标悬停。
  • 需要注意的是:鼠标操作完之后,一定要紧跟perform(),不然这

键盘操作

  • 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)
  • send_keys(Keys.CONTROL,'x') 剪切(Ctrl+X)
  • send_keys(Keys.CONTROL,'v') 粘贴(Ctrl+V)
  • send_keys(Keys.F1) 键盘 F1
  • ……
  • send_keys(Keys.F12) 键盘 F12

获取断言信息

text = driver.page_source # 获取当前页面的源码:需要注意的是:
动态加载:driver.page_source 获取的源码是当前浏览器渲染后的完整页面源码,包括通过 JavaScript 动态加载的内容。而 requests 获取的源码是初始的静态页面源码,不包含 JavaScript 动态加载的内容。

AJAX 请求:如果页面中通过 AJAX 请求加载内容,requests 获取的源码可能不包含这部分内容,而 driver.page_source 获取的源码会包含通过 AJAX 请求加载的内容。

JavaScript 渲染:requests 不能执行 JavaScript,因此无法获取 JavaScript 渲染后的页面内容,而 driver.page_source 获取的源码是经过 JavaScript 渲染后的页面内容。

综上所述,如果网站通过 JavaScript 动态加载内容或进行 AJAX 请求,那么 driver.page_source 获取的源码和 requests 获取的源码可能会有所不同。在实际应用中,您需要根据具体的需求和情况选择合适的获取源码的方法。
由于以上等原因,最终使用requests获取的网页源码可能和selenium获取的源码有所缺失,一般我们直接使用selenium获取网页的源码
title = driver.title # 打印当前页面title
now_url = driver.current_url # 打印当前页面URL

等待页面加载完成

  • 显示等待

显式等待使WebdDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")

element = WebDriverWait(driver, 5, 0.5).until(
                      EC.presence_of_element_located((By.ID, "kw"))
                      )
element.send_keys('selenium')
driver.quit()

WebDriverWait类是由WebDirver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。具体格式如下:

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

  • driver :浏览器驱动。
  • timeout :最长超时时间,默认以秒为单位。
  • poll_frequency :检测的间隔(步长)时间,默认为0.5S。
  • ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。
  • WebDriverWait()一般由until()或until_not()方法配合使用,下面是until()和until_not()方法的说明。
  • until(method, message=‘’) 调用该方法提供的驱动程序作为一个参数,直到返回值为True。
  • until_not(method, message=‘’) 调用该方法提供的驱动程序作为一个参数,直到返回值为False。

在本例中,通过as关键字将expected_conditions 重命名为EC,并调用presence_of_element_located()方法判断元素是否存在。

  • EC对应的不同方法如下:
  1. presence_of_element_located:等待直到某个元素出现在DOM中。
  2. visibility_of_element_located:等待直到某个元素在页面上可见。
  3. element_to_be_clickable:等待直到某个元素可被点击。
  4. text_to_be_present_in_element:等待直到某个元素包含特定的文本。
  • 隐式等待

隐式等待:通过设置隐式等待时间,可以让WebDriver在查找元素或执行操作时等待一定的时间。如果在规定的时间内找到了元素,就会立即执行后续的操作;如果超过了设定的时间而没有找到元素,就会抛出NoSuchElementException异常。隐式等待对整个WebDriver的生命周期都起作用,只需要设置一次即可。

driver.implicitly_wait(10)

切换模块

切换窗口

handles = driver.window_handles
print("handles的类型为:",type(handles))
print("handles = ",handles)
print("title的值为:",title)
# 切换具柄
driver.switch_to.window(handles[1])

切换实例:
?

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# 获取驱动并打开网页
service = Service(executable_path=r"/Users/liujianlei/Downloads/mopi/chromedriver-mac-arm64/chromedriver")
driver = webdriver.Chrome(service=service)
# 打开网页
url = "https://login.anjuke.com/login/form"
driver.get(url)
# 等待元素加载出来
wait = WebDriverWait(driver,10,0.5).until(EC.presence_of_element_located((By.XPATH,"//*[@id=\"iframeLoginIfm\"]")))
# 查找对应的iframe元素
iframe = driver.find_element(By.XPATH,"//*[@id=\"iframeLoginIfm\"]")
# 切换为iframe
driver.switch_to.frame(iframe)
# 点击切换为账号密码登录
element = driver.find_element(By.XPATH,"//*[@id=\"pwdTab\"]")
# 点击元素
element.click()
# 输入用户名
user_element = driver.find_element(By.ID,"pwdUserNameIpt")
user_element.send_keys("123")
# 输入密码
pwd_element = driver.find_element(By.ID,"pwdIpt")
pwd_element.send_keys("123")
# 勾选我已同意
element_agree = driver.find_element(By.ID,"checkagree")
element_agree.click()
# 点击登录
login_element =driver.find_element(By.ID,"pwdSubmitBtn")
login_element.click()
# 切换为上一层的图层
driver.switch_to.parent_frame()
# 点击家居网进行页面跳转,查看当前是哪个窗口
element_web = driver.find_element(By.XPATH,"/html/body/div[1]/a[1]/i")
element_web.click()
# 获取当前的window
window_name = driver.title
print("{}为当前的title".format(window_name))
time.sleep(100)
# element = driver.find_element(By.XPATH,"//*[@id=\"phoneIpt\"]")
# element.send_keys("13153382278")
# 切换新的元素

切换iframe

# 切换为iframe
driver.switch_to.frame(iframe)
# 点击切换为账号密码登录
element = driver.find_element(By.XPATH,"//*[@id=\"pwdTab\"]")
# 点击元素
element.click()
# 输入用户名
user_element = driver.find_element(By.ID,"pwdUserNameIpt")
user_element.send_keys("123")
# 输入密码
pwd_element = driver.find_element(By.ID,"pwdIpt")
pwd_element.send_keys("123")
# 勾选我已同意
element_agree = driver.find_element(By.ID,"checkagree")
element_agree.click()
# 点击登录
login_element =driver.find_element(By.ID,"pwdSubmitBtn")
login_element.click()
# 切换为上一层的图层
driver.switch_to.parent_frame()

切换实例:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# 练习:访问聚合,点击“开发者”
url = "https://www.juhe.cn/"
service = Service(executable_path=r"/Users/liujianlei/Downloads/mopi/chromedriver-mac-arm64/chromedriver")
driver = webdriver.Chrome(service= service)
driver.get(url)
driver.find_element(By.LINK_TEXT,"开发者").click()
# 查看是哪个窗口
title = driver.title
# 获取所有的窗口具柄
handles = driver.window_handles
print("handles的类型为:",type(handles))
print("handles = ",handles)
print("title的值为:",title)
# 切换具柄
driver.switch_to.window(handles[1])
# 点击新页面的元素
element = driver.find_element(By.XPATH,"//*[@id=\"__layout\"]/div/div[1]/div[1]/div/div/div[1]/div/a[2]").click()
# 切换回原来的具柄
driver.switch_to.window(handles[0])
#点击新的元素
driver.find_element(By.XPATH,"/html/body/div[3]/header/div/div[1]/ul/li[2]/a").click()
time.sleep(200)

警告框处理

alert = driver.switch_to_alert()
  • text:返回 alert/confirm/prompt 中的文字信息。
  • accept():接受现有警告框。
  • dismiss():解散现有警告框。
  • send_keys(keysToSend):发送文本至警告框。keysToSend:将文本发送至警告框。

下拉框选择

from selenium import webdriver
from selenium.webdriver.support.select import Select
from time import sleep

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.baidu.com')
sel = driver.find_element_by_xpath("//select[@id='nr']")
Select(sel).select_by_value('50')  # 显示50条

文件上传

driver.find_element_by_name("file").send_keys('D:\\upload_file.txt')  # # 定位上传按钮,添加本地文件

cookie操作

WebDriver操作cookie的方法:

  • get_cookies(): 获得所有cookie信息。
  • get_cookie(name): 返回字典的key为“name”的cookie信息。
  • add_cookie(cookie_dict) : 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值。
  • delete_cookie(name,optionsString):删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”。
  • delete_all_cookies(): 删除所有cookie信息

调用JavaScript代码

js="window.scrollTo(100,450);"
driver.execute_script(js) # 通过javascript设置浏览器窗口的滚动条位置

通过execute_script()方法执行JavaScripts代码来移动滚动条的位置。

窗口截图

driver.get_screenshot_as_file("D:\\baidu_img.jpg") # 截取当前窗口,并指定截图图片的保存位置

关闭浏览器

  • close() 关闭单个窗口
  • quit() 关闭所有窗口

练习

爬取关于cxk的b站视频数据

from bs4 import BeautifulSoup
import requests
import openpyxl
from fake_useragent import UserAgent
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
# 创建excel表格
wb = openpyxl.Workbook()
ws = wb.active
ws.append(["名称","视频地址","观看次数","弹幕数量","发布时间"])
output_file = "./cxk-with-basketball-video.xlsx"
# 创建虚拟ua
ua = UserAgent()
headers = {"user-agent":ua.random}
# 打开b站官网
url = "https://www.bilibili.com/"
# 创建service
service = Service(executable_path=r"/Users/liujianlei/Downloads/mopi/chromedriver-mac-arm64/chromedriver")
driver = webdriver.Chrome(service= service)
# 打开b站
driver.get(url)
# 定位输入框并输入内容
content = "蔡徐坤 篮球"
driver.find_element(By.CLASS_NAME,"nav-search-input").send_keys(content)
# 获取按钮
driver.find_element(By.CLASS_NAME,"nav-search-btn").click()
# 进行页面的跳转
time.sleep(1)
handles = driver.window_handles
driver.switch_to.window(handles[-1])
# 显示等待直到元素加载完成
#wait = WebDriverWait(driver,10,0.5).until(EC.presence_of_element_located((By.XPATH,"//*[@id=\"bili-header-container\"]/div/div/ul[1]/li[8]/a/span")))
# 获取对应的URL并进行访问
# new_url = driver.current_url
# response = requests.get(new_url,headers=headers)
text = driver.page_source
soup = BeautifulSoup(text,"html.parser")
# 获取当前共有多少页
buttons = soup.find_all("button",{"class":"vui_button vui_button--no-transition vui_pagenation--btn vui_pagenation--btn-num"})
last_index = int(buttons[-1].text)
# 使用bs进行内容的读取
# for i in range(1,34):
#     print("当前是第{}页".format(i))

tags = soup.find_all(class_="bili-video-card__wrap __scale-wrap")

for tag in tags:
    contents = tag.find_all("span", {"class": "bili-video-card__stats--item"})
    view_num = contents[0].text
    lang_num = contents[1].text
    title = tag.find("h3", {"class": "bili-video-card__info--tit"}).get("title")
    time = tag.find("span", {"class": "bili-video-card__info--date"}).text
    href = tag.find("a", attrs={"data-idx": "all"}).get("href")
    # 将结果进行保存
    ws.append([title, href, view_num, lang_num, time])
    # 浏览器页面定位到下面
    # driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    # print("已经滑动到最底部了")
    driver.implicitly_wait(10)
    #WebDriverWait(driver,20,0.5).until(EC.element_to_be_clickable((By.CLASS_NAME,"vui_button vui_pagenation--btn vui_pagenation--btn-side")))
    # 定位下一页元素并进行点击
# 最后将excel表格进行保存
driver.find_element(By.CSS_SELECTOR,
                    "#i_cecream > div > div:nth-child(2) > div.search-content--gray.search-content > div > div > div > div.flex_center.mt_x50.mb_x50 > div > div > button:nth-child(11)").click()

wb.save(output_file)
# 关闭driver
driver.close()


notes:

元素定位不到的可能原因:

如果在使用Selenium时无法定位到下一页按钮,可能有几种原因。以下是一些可能的解决方法:

  1. 等待页面加载完成:确保页面已经完全加载,有时下一页按钮可能需要一些时间才会出现在DOM中。您可以使用隐式等待或显式等待确保页面加载完成后再进行定位。

  2. 使用合适的定位方法:尝试使用不同的定位方法来寻找下一页按钮,比如通过ID、CSS选择器、XPath等。

  3. 查看页面源代码:查看页面源代码,确认下一页按钮的HTML结构和属性,以便更好地定位它。

  4. 检查是否在iframe中:如果下一页按钮位于iframe中,您需要先切换到该iframe,然后再进行定位。

  5. 使用JavaScript点击:如果其他方法无法定位到下一页按钮,可以尝试使用JavaScript来模拟点击操作。

以下是一个示例,演示了如何使用Selenium和JavaScript模拟点击下一页按钮:

# 导入需要的模块
from selenium import webdriver

# 启动浏览器
driver = webdriver.Chrome()

# 打开网页
driver.get("https://www.example.com")

# 使用JavaScript点击下一页按钮
next_button = driver.find_element_by_xpath("//button[@id='next']")
driver.execute_script("arguments[0].click();", next_button)

如果这些方法仍然不能解决问题,那么可能需要对具体的网页和定位情况进行更深入的分析和调试。

?

文章来源:https://blog.csdn.net/m0_65431718/article/details/135022974
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。