0


python爬虫---selenium模块

1、原理及安装

1.1 原理

Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。这个工具的主要功能包括:测试与浏览器的兼容性——测试应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成.Net、Java、Perl等不同语言的测试脚本。—百度百科

自动化程序与浏览器流程图

1.2 安装
1.2.1 selenium
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2.2 Chrome浏览器
1.2.3 Chrome浏览器驱动

浏览器驱动

1.3 环境配置
  • 浏览器驱动下载后将其放在没有中文的路径下(只需留下exe应用程序即可)

驱动位置

  • 复制路径将其放入环境变量中

环境变量配置

  • 若不配置环境变量则每次都需要配置路径
from selenium import webdriver

wd = webdriver.Chrome(service=Service(r'E:\software\anaconda3\envs\crawler\chromedriver.exe'))
  • 配置环境变量后则可以省去此步骤
from selenium import webdriver

wd = webdriver.Chrome()

2、元素定位

  • 每次使用selenium控制驱动打开浏览器的时候,网页总是自动关闭
from selenium import webdriver

# 创建 WebDriver 对象
wd = webdriver.Chrome()# 调用WebDriver对象的get方法打开指定网址
wd.get('https://www.byhy.net/_files/stock1.html')
  • 可以使用下面的驱动方式使得页面一直显示
from selenium import webdriver

# 不自动关闭浏览器
options = webdriver.ChromeOptions()
options.add_experimental_option("detach",True)# 将option作为参数添加到Chrome中
wd = webdriver.Chrome(options=options)
wd.get('https://www.baidu.com/')
2.1 通过id定位
# 根据id选择元素,返回的就是该元素对应的WebElement对象
element_id = wd.find_element(By.ID,'wrapper')
2.2 通过class定位
element_class = wd.find_element(By.CLASS_NAME,"wrapper_new")print(element_class)
2.3 通过name定位
element_name = wd.find_element(By.NAME,"baidu-site-verification")print(element_name)# 没有内容只返回对象print(element_name)
2.4 通过tag_name定位
element_tag_name = wd.find_element(By.TAG_NAME,"meta")print(element_tag_name)# 没有内容只返回对象print(element_tag_name)
2.5 通过Xpath语法定位

只能定位到标签位置,并不能直接定位到内容然后返回,只能返回对象再使用.text获取内容

element_Xpath = wd.find_element(By.XPATH,"//div[@class='nav-logo']/a")print(element_Xpath)
2.6 通过css语法定位
element_CSS = wd.find_element(By.CSS_SELECTOR,"#db-nav-movie")print(element_CSS)
2.7 通过文本定位
wd.find_element(By.XPATH,"//*[contains(text(),'排行榜')]").click()# 点击并进行跳转操作

我们发现直接使用上面的程序进行获取会报错,这是因为浏览器的加载需要时间,程序没有等待而是直接获取元素,这就导致获取失败

  • 解决方式:- 强制等待:# 让程序睡眠一秒等待浏览器加载import timetime.sleep(1)- 显式等待:# 实际上是依据try-except异常捕获进行判断from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.common.exceptions import TimeoutExceptionfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECwd = webdriver.Chrome()wd.get("https://movie.douban.com/top250?start=25&filter=")defsearch():try: element = WebDriverWait(driver,10,0.5).until( EC.presence_of_element_located((By.ID,"wrapper")))except TimeoutException:return search()- 隐式等待:# 隐式等待,每隔半秒寻找一次元素,最长等10秒wd.implicitly_wait(10)

3、浏览器控制

3.1 修改浏览器窗口大小
3.1.1 修改指定大小
wd.set_window_size(600,800)
3.1.2 全屏显示
wd.maximize_window()
3.2 浏览器访问

webdriver提供了

back

forward

两种方式实现页面的前进或后退。

下面我们使用豆瓣电影TOP250作为例子进行演示:

​ 1、访问主页

​ 2、进入排行榜

​ 3、进入剧情分类

​ 4、返回排行榜

​ 5、返回主页

​ 6、进入排行榜

import time

from selenium import webdriver

wd = webdriver.Chrome()# 访问主页链接
wd.get("https://movie.douban.com/top250")
time.sleep(1)# 进入排行榜
wd.get("https://movie.douban.com/chart")# 在原标签页面打开# # 新标签中打开# js = "window.open('https://movie.douban.com/chart')"# wd.execute_script(js)
time.sleep(1)# 进入剧情分类
wd.get("https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=")
time.sleep(5)# 返回排行榜
wd.back()
time.sleep(1)# 返回主页
wd.back()
time.sleep(1)# 进入排行榜
wd.forward()
time.sleep(1)
  • 刷新页面
wd.refrech()
  • 切换页面
# 获取打开的多个窗口句柄
windows = driver.window_handles
# 切换到当前最新打开的窗口
wd.switch_to.window(windows[-1])

4、鼠标操作

并不是直接操作我们现在使用的鼠标,而是使用抽象出来的鼠标进行操作

4.1 ActionChains方法

执行动作需要要使用perform()方法,否则动作不执行

click(on_element=None) ——单击鼠标左键
click_and_hold(on_element=None) ——点击鼠标左键,不松开
context_click(on_element=None) ——点击鼠标右键
double_click(on_element=None) ——双击鼠标左键
drag_and_drop(source, target) ——拖拽到某个元素然后松开
key_down(value, element=None) ——按下某个键盘上的键
key_up(value, element=None) ——松开某个键
move_to_element(to_element) ——鼠标移动到某个元素
perform() ——执行链中的所有动作
release(on_element=None) ——在某个元素位置松开鼠标左键
send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
send_keys_to_element(element,*keys_to_send) ——发送某个键到指定元素
move_by_offset(x,y)  ——移动到某个坐标
4.2 鼠标移动

待执行动作:

​ 1、移动到value值为Write on hover的元素上,显示为Mouse moved;

​ 2、移动到value值为Blank on hover的元素上,显示框清空;

​ 3、最后再移动到value值为Write on hover的元素上。

这种方式对有隐藏属性元素操作十分有用。

action = ActionChains(wd)
time.sleep(2)

action.move_to_element(write_element).perform()
time.sleep(2)

action.move_to_element(blank_element).perform()
time.sleep(2)

action.move_to_element(write_element).perform()
time.sleep(3)

wd.quit()
4.3 鼠标拖拽

待执行动作:

​ 1、将被拖拽元素拖拽到第一个方框,观察变化;

​ 2、将被拖拽元素拖拽到第二个方框,观察变化。

action.drag_and_drop(item, item1).perform()
time.sleep(1)

action.drag_and_drop(item, item3).perform()
time.sleep(5)
4.4 鼠标点击

待执行动作:

​ 1、点击单击元素;

​ 2、点击双击元素;

​ 3、点击右击元素;

​ 4、点击选择元素。

# 链式用法
ActionChains(wd).click(click).double_click(click_double).context_click(click_right).\
    click(click_select1).click(click_select2).click(click_select3).\
    click(click_checkbox).perform()

5、键盘操作

5.1 keys类键盘操作

操作作用说明Keys.F1F1键Keys.SPACE空格Keys.TABTab键Keys.ESCAPEESC键Keys.ALTAlt键Keys.SHIFTShift键Keys.ARROW_DOWN向下箭头Keys.ARROW_LEFT向左箭头Keys.ARROW_RIGHT向右箭头Keys.ARROW_UP向上箭头

5.2 组合操作

操作作用说明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)

5.3 示例

待执行动作:

​ 1、找到包含排行第一电影名称的元素;

​ 2、将其复制到豆瓣电影的搜索框中;

​ 3、使用鼠标操作进行点击。

# 定位到第一个电影标题
title = wd.find_element(By.XPATH,"//div[@class='hd']/a/span[1]")# 获取元素的文本
text_to_copy = title.text

# # 使用JavaScript将文本复制到剪贴板
wd.execute_script("window.getSelection().selectAllChildren(arguments[0]);window.getSelection().rangeCount > 0 && window.getSelection().getRangeAt(0).deleteContents();", title)# wd.execute_script("document.execCommand('copy')")
action = ActionChains(wd)
action.send_keys(Keys.CONTROL,"c")# 定位到搜索框
input_ = wd.find_element(By.XPATH,"//div[@class='inp']/input")# 粘贴复制的文本到搜索框
input_.send_keys(text_to_copy)# 等待搜索按钮加载完成
search_button = WebDriverWait(wd,10).until(EC.element_to_be_clickable((By.XPATH,"//input[@value='搜索']")))# 点击搜索按钮
search_button.click()

6、元素等待

6.1 强制等待
# 让程序睡眠一秒等待浏览器加载import time
time.sleep(1)
6.2 显式等待
# 使用EC类中的方法进行判断from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wd = webdriver.Chrome()
wd.get("https://movie.douban.com/top250?start=25&filter=")defsearch():try:
        element = WebDriverWait(driver,10,0.5).until(
            EC.presence_of_element_located((By.ID,"wrapper"))# 判断ID为wrapper元素是否可见)except TimeoutException:return search()

方法描述title_is(‘百度一下’)判断当前页面的 title 是否等于预期title_contains(‘百度’)判断当前页面的 title 是否包含预期字符串presence_of_element_located(locator)判断元素是否被加到了 dom 树里,并不代表该元素一定可见visibility_of_element_located(locator)判断元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0text_to_be_present_in_element(locator , ‘百度’)判断元素中的 text 是否包含了预期的字符串ext_to_be_present_in_element_value(locator , ‘某值’)判断元素中的 value 属性是否包含了预期的字符串frame_to_be_available_and_switch_to_it(locator)判断该 frame 是否可以 switch 进去,True 则 switch 进去,反之 Falseinvisibility_of_element_located(locator)判断元素中是否不存在于 dom 树或不可见element_to_be_clickable(locator)判断元素中是否可见并且是可点击的staleness_of(element)等待元素从 dom 树中移除element_to_be_selected(element)判断元素是否被选中,一般用在下拉列表element_selection_state_to_be(element, True)判断元素的选中状态是否符合预期,参数 element,第二个参数为 True/Falseelement_located_selection_state_to_be(locator, True)跟上一个方法作用相同,但传入参数为 locatoralert_is_present()判断页面上是否存在 alert

6.3 隐式等待
# 隐式等待,每隔半秒寻找一次元素,最长等10秒,超过时间后返回异常
wd.implicitly_wait(10)

7、高级操作

7.1 无界面启动

优势:

​ 1、速度更快:Headless模式下的测试速度通常比普通模式更快。这对于大规模测试或需要频繁执行的 测试场景非常有利。

​ 2、更加稳定Headless模式下的测试不会弹出可见的浏览器窗口,可以在后台静默运行,不影响用户体 验。同时,由于无需考虑浏览器窗口的操作,测试更稳定,容易集成到持续集成(CI)系统中。

from selenium import webdriver

option = webdriver.ChromeOptions()# 加载浏览器的静默模式
option.add_argument("--headless")

driver = webdriver.Chrome(options=option)
driver.get("https://www.baidu.com")print(driver.page_source)

driver.quit()
7.2 页面切换

点击跳转链接打开新页面时,selenium依然在之前的页面上进行操作,若想在新页面操作,需要更新操作页面。

# 返回的值是一个列表,按照时间顺序进行排序
wd.window_handles[i]
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

handles =[]
wd = webdriver.Chrome()
wd.get("https://movie.douban.com/top250?start=")
wd.implicitly_wait(5)

handles.append(wd.current_window_handle)
wd.find_element(By.XPATH,"//div[@class='global-nav-items']/ul/li/a").click()

time.sleep(1)# 切换到最新打开的窗口# wd.switch_to.window(wd.window_handles[-1])
handles.append(wd.current_window_handle)print(handles)>>>['74AB56A47773D439438ECAB53147B24B','74AB56A47773D439438ECAB53147B24B']
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

handles =[]
wd = webdriver.Chrome()
wd.get("https://movie.douban.com/top250?start=")
wd.implicitly_wait(5)

handles.append(wd.current_window_handle)
wd.find_element(By.XPATH,"//div[@class='global-nav-items']/ul/li/a").click()

time.sleep(1)# 切换到最新打开的窗口
wd.switch_to.window(wd.window_handles[-1])
handles.append(wd.current_window_handle)print(handles)>>>['5FEA7C45627785F02C6B7D56409D0E39','8EC96C8F3F2978F524D49AE2F54F55A1']
  • 通过观察句柄的异同,我们可以判断,实现了页面的更新。
7.3 表单切换

在页面中有时可能遇到

frame/iframe

表单嵌套的操作,无法直接获取被嵌套元素,这时我们就需要进行表单切换操作。

# 以QQ切换为密码登录为例from selenium.webdriver.common.by import By
from selenium import webdriver
import time

handles =[]
wd = webdriver.Chrome()
wd.get("https://qzone.qq.com/")
wd.implicitly_wait(5)

login_frame = wd.find_element(By.ID,"login_frame")# 切换到iframe
wd.switch_to.frame(login_frame)
wd.find_element(By.ID,"switcher_plogin").click()

username = wd.find_element(By.XPATH,"//input[@id='u']")
password = wd.find_element(By.XPATH,"//input[@id='p']")

username.send_keys("123")
password.send_keys("123")

wd.find_element(By.XPATH,"//a[@class='login_button']").click()
time.sleep(1)
7.4 selenium模拟Javascript
7.4.1 弹窗处理

获取弹窗内容方式。

方法描述

text

获取弹窗中的文字

accept

接受(确认)弹窗内容

dismiss

解除(取消)弹窗

send_keys

发送文本至警告框

7.4.2 模拟动作
from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get('https://www.jd.com/')
temp_height =0whileTrue:# 滑动下拉框
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
    time.sleep(1)
    check_height = driver.execute_script("return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;")if check_height ==11922:break
7.5 cookies操作
7.5.1 调用方法

方法描述

get_cookies

获得所有cookies信息

get_cookies(name)

返回指定name名称的cookies信息

add_cookies(cookie_dict)

添加cookie,必须有name值和value值

delete_cookie(name)

删除特定的cookie信息

delete_all_cookies()

删除所有的cookie信息

7.5.2 cookies属性值

属性含义name必选参数,规定cookies的名称value必选参数,规定cookies的值expire可选参数,规定cookies的有效期domain可选参数,规定cookies的域名path可选参数,规定cookies服务器的路径secure可选参数,规定是否通过安全的https连接来传输cookieshttpOnly可选参数,防止XSS攻击(跨站脚本攻击)

7.6 其他操作
7.6.1 常见操作
# 截图
get_screenshot_as_file()# 获取当前页面url
driver.current_url

# 获取当前html源码
driver.page_source

# 获取当前页面标题
driver.title

# 获取浏览器名称
driver.name

# 对页面进行截图,返回二进制数据
driver.get_screenshot_as_png()# 设置浏览器尺寸
driver.get_window_size()# 获取浏览器尺寸,位置
driver.get_window_rect()# 获取浏览器位置(左上角)
driver.get_window_position()# 设置浏览器尺寸
driver.set_window_size(width=640, height=480)# 设置浏览器位置(左上角)
driver.set_window_position(x=500, y=600)# 设置浏览器的尺寸,位置
driver.set_window_rect(x=200, y=400, width=1000, height=600)
7.6.2 隐藏selenium指纹特征
import time
from selenium.webdriver import Chrome

option = webdriver.ChromeOptions()
option.add_argument("--headless")# 无头浏览器需要添加user-agent来隐藏特征
option.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36')

driver = Chrome(options=option)
driver.implicitly_wait(5)withopen('stealth.min.js')as f:
    js = f.read()

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{"source": js
})

driver.get('https://bot.sannysoft.com/')
driver.save_screenshot('hidden_features.png')

相关代码地址: https://gitee.com/justinc666/crawler/tree/master/selenium


本文转载自: https://blog.csdn.net/sjc122333/article/details/142422474
版权归原作者 Justinc. 所有, 如有侵权,请联系我们删除。

“python爬虫---selenium模块”的评论:

还没有评论