网络爬虫 Selenium知识

本文详细介绍Selenium自动化测试工具的安装、配置与基本使用方法,包括浏览器操作、元素定位、鼠标键盘事件模拟、JS命令执行、等待策略、多窗口与多标签页处理等核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# Selenium (firefox)

# 1,介绍:
# selenium 是一个 web 的自动化测试工具,是一个包,可以支持 C、 java、ruby、python、或都是 C# 语言。

# 1)安装:
# 1-1)安装 selenium  
# pip install selenium  # 在 python中安装 selenium  
# conda install -n data_analysis selenium  在 anaconda的虚拟环境中中安装 selenium  

# 1-2) 安装webdriver
# 各大浏览器webdriver地址可参见:https://docs.seleniumhq.org/download/
# Firefox:https://github.com/mozilla/geckodriver/releases/
# Chrome:https://sites.google.com/a/chromium.org/chromedriver/ 或者
# http://chromedriver.storage.googleapis.com/index.html
# IE:http://selenium-release.storage.googleapis.com/index.html
# 注:webdriver需要和对应的浏览器版本以及selenium版本对应

# 下载的压缩包文件名为:geckodriver-v0.26.0-win64.zip 解压之后得到 geckodriver.exe
# webdriver安装路径:
# Win:复制 geckodriver.exe 到Python/Anaconda安装目录下: C:\Users\XuYunPeng\anaconda3\


# 2,基本使用:
# 2-1)启动浏览器:
from selenium import webdriver
browser = webdriver.Firefox()  # browser = webdriver.Chrome() # browser = webdriver.Ie()
browser.get('http://www.baidu.com/')

# 2-2-1)设定 chorme无界面模式:
from selenium import webdriver

options = webdriver.ChromeOptions()     # chorme
options.add_argument('--headless')      # 设置无界面

browser=webdriver.Chorme(options=options) 
browser.get('http://www.baidu.com/')

# 2-2-2)设定 firefox无界面模式:
from selenium import webdriver

options = webdriver.FirefoxOptions()    # firefox
options.add_argument('--headless')      # 设置无界面

browser=webdriver.Firefox(options=options) 
browser.get('http://www.baidu.com/')


# 2-3)访问页面:
browser.get('http://www.renren.com/')
browser.maximize_window()  # 窗口最大化,可有可无,看情况
# browser.minimize_window()

# 2-4)定位元素并交互:
# 定位元素的方法:
# id定位:find_element_by_id()
# name定位:find_element_by_name()
# class定位:find_element_by_class_name()
# link定位:find_element_by_link_text()
# partial link定位:find_element_by_partial_link_text()
# tag定位:find_element_by_tag_name()
# xpath定位:find_element_by_xpath()
# css定位:find_element_by_css_selector()

# 以上是单元素的定位,多元素的定位把 element改为 elements即可。

# 通用方法:
# 将 By导入,使用 browser.find_element(By.ID,idname)  其中 browser=webdriver.Firefox()
from selenium import webdriver
from selenium.webdriver.common.by import By 
browser = webdriver.Firefox()  
browser.get('http://www.renren.com/')
input_first=browser.find_element(By.ID,'email')

# 元素定位的举例:

#coding=utf-8
from selenium import webdriver
browser=webdriver.Firefox()
browser.get("http://www.baidu.com")
# 百度输入框的定位方式:
# 通过id方式定位
browser.find_element_by_id("kw").send_keys("Collin")
# 通过name方式定位
browser.find_element_by_name("wd").send_keys("Collin")
# 通过tag name方式定位
browser.find_element_by_tag_name("input").send_keys("Collin")
# 通过class name方式定位
browser.find_element_by_class_name("s_ipt").send_keys("Collin")
# 通过CSS方式定位
browser.find_element_by_css_selector("#kw").send_keys("Collin")
# 通过xpath方式定位
browser.find_element_by_xpath("//input[@id='kw']").send_keys("Collin")
# 点击 搜索
browser.find_element_by_id("su").click()
time.sleep(3)  # 强制等待,后面再讲。
browser.quit()


# 示例 1:登录人人网:
from selenium import webdriver
from selenium.webdriver.common.by import By 
browser = webdriver.Firefox() 
browser.get('http://www.renren.com/')
# browser.maximize_window() 
# browser.minimize_window()

# browser.find_element_by_id('email').clear()
# browser.find_element_by_id('email').send_keys('xxx@sina.com')
browser.find_element(By.ID,'email').clear()
browser.find_element(By.ID,'email').send_keys('test@qq.com')
browser.find_element(By.ID,'password').send_keys('testtsettset')
browser.find_element(By.ID,'login').click()  # 操作浏览器
browser.close() # 关闭
browser.quit()  # 退出


# 3,鼠标事件:
# e.click() 
# 除了可以使用 click( ) 来模拟鼠标的单击操作,现在Web产品中还提供了更丰富的鼠标交互方式,例如鼠标右键、双击、悬停、拖动等功能,
# 在WebDriver中,将这些关于鼠标操作的方法都封装在 ActionChains 类中。

# 4, 键盘事件
# 1) e.send_keys(要输入的值)
#  同样,操作键盘的几个方法也被封装进了 ActionChains 类中,如 actions.click(e).send_keys(要输入的值)

# 2),要想调用键盘按键操作,需要引入 keys 包:
from selenium.webdriver.common.keys import Keys   # 通过 send_keys()调用按键:
send_keys(Keys.TAB) # TAB
send_keys(Keys.ENTER) # 回车

# 鼠标事件一般包括鼠标右键、双击、拖动、移动鼠标到某个元素上等等。
# ActionChains方法列表:
# 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) ——拖拽到某个元素然后松开
# drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开
# key_down(value, element=None) ——按下某个键盘上的键
# key_up(value, element=None) ——松开某个键
# move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标
# move_to_element(to_element) ——鼠标移动到某个元素
# move_to_element_with_offset(to_element, xoffset, yoffset) ——移动到距某个元素(左上角坐标)多少距离的位置
# perform() ——执行链中的所有动作
# release(on_element=None) ——在某个元素位置松开鼠标左键
# send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
# send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素 

# ActionChains基本用法:
# 首先需要了解ActionChains的执行原理,当你调用ActionChains的方法时,不会立即执行,而是会将所有的操作按顺序存放在一个队列里,
# 当你调用perform()方法时,队列中的时间会依次执行。这种情况下我们可以有两种调用方法: 

# 链式写法
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu =  driver.find_element_by_css_selector(".nav #submenu1")
 
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

# 分步写法
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")
 
actions = ActionChains(driver)

actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()


# 示例 1 菜鸟教程:
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Firefox()
url = "http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"
browser.get(url)
actions = ActionChains(browser)  # 将操作放入 actionchain中串行执行

browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')

actions.drag_and_drop(source, target)
actions.perform()

# 示例 2 登录人人网:
from selenium import webdriver
from selenium.webdriver.common.by import By 
from selenium.webdriver import ActionChains

browser = webdriver.Firefox() 
browser.get('http://www.renren.com/')
actions = ActionChains(browser)

# browser.maximize_window() 
# browser.find_element(By.ID,'email').clear()
# browser.find_element(By.ID,'email').send_keys('test@qq.com')
# browser.find_element(By.ID,'password').send_keys('testtsettset')
# browser.find_element(By.ID,'login').click()  # 操作浏览器

email=browser.find_element(By.ID,'email')
email.clear()
actions.click(email).send_keys('120789@qq.com')

psw=browser.find_element(By.ID,'password')
actions.click(psw).send_keys('12345678')

actions.perform()

browser.close() # 关闭
browser.quit()  # 退出


# 5,执行 js命令:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("http://www.zhihu.com/explore")

browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')


# 6, 输出和关闭浏览器:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("http://www.zhihu.com/explore")

print(browser.current_url)   # https://www.zhihu.com/explore
print(browser.page_source)   # JSON格式的数据
browser.close()
browser.quit()


# 7, frame标签:
# 很多网页中存在 frame 标签,要处理frame里面的数据,首先要切入frame,处理完了还要切出来。 
# 切入 -- switch_to.frame(),
# 切出 -- switch_to.parent_frame().

# 示例:
# 在 id为 iframeResult的 frame里寻找 css_selector为'draggable' 及 class_name为 'logo'的元素
# 如果在 iframeResult里找不到 class_name为 'logo'的元素就退出 iframeResult,然后再寻找。

# encoding:utf-8
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Firefox()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')     # 进入iframe  iframeResult 是 iframe 的 id   
source = browser.find_element_by_css_selector('#draggable')
print(source)
try:
    logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
    print('NO LOGO')
browser.switch_to.parent_frame()           # 退出 iframe
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)


# <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="cf33eb76-09fb-45c4-8c19-f4ca9df3df03", element="67784163-bf88-480e-99c5-1efa9ae4a94a")>
# NO LOGO
# <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="cf33eb76-09fb-45c4-8c19-f4ca9df3df03", element="80aca415-4215-4207-aa85-d7816c145389")>
# RUNOOB.COM


# 8, 等待:

# 1) 强制等待:  time.sleep(10)
# 优点:简单明了.
# 缺点:不智能,可能会影响程序效率。

import time
time.sleep(10)

# 2) 隐式等待:  browser.implicitly_wait(100) 
# 优点:相比sleep() ,隐性更加智能,它会在你设置的时间内判断网页是否加载完成,如果完成了,就进行下一步;在设置的时间内没有加载完成,
# 则会报超时加载;
# 缺点:随着ajax技术的广泛应用,页面的元素往往都可以局部加载,也就是在整个页面没有加载完的时候,可能我们需要的元素已经加载完成了,
# 那就么有必要再等待整个页面的加载。

# 1.隐性等待的设置是全局性的,在开头设置过之后,整个的程序运行过程中都会有效,都会等待页面加载完成;不需要每次设置一遍;
# 2.页面加载完成后新打开的弹窗是没有等待效果的

from selenium import webdriver
browser = webdriver.Firefox()
browser.implicitly_wait(100)    # 等待整个页面加载完成
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)


# 3)显式等待
# 举例:
# input= WebDriverWait(browser, 100).until(EC.presence_of_element_located((By.ID, 'q'))) # 最长等待100秒,直到 id为 'q'的元素出现
# button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))  # 最长等待100秒,直到按钮可以点击。
 
# WebDriverWait(browser, 100).until_not(EC.presence_of_element_located((By.ID, 'q')))  #最长等待100秒,直到 id为 'q'的元素消失
# button = wait.until_not(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))  #最长等待100秒,直到按钮不可以点击。

# 示例 1:
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

browser = webdriver.Firefox()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 100)    # 
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
print(input, button)

# 示例 2:
from datetime import datetime
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.Chrome()
driver.get("http://www.baidu.com")
driver.maximize_window()
try:
    print(datetime.now())  #
    element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID, "kw")))

    print(datetime.now())
    element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID, "kw111")))

finally:
    print(datetime.now())
    driver.quit()


# 注意:最好对于元素选择全部独立封装成方法,在每个方法中可以加上日志、显示等待
# 对于 until()和 until_not()使用的布尔参数还有:
# title_is:判断当前页面的title是否等于预期
# title_contains:判断当前页面的title是否包含预期字符串
# presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
# visibility_of_element_located:判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
# visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
# presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
# text_to_be_present_in_element:判断某个元素中的text是否 包含 了预期的字符串
# text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
# frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
# invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
# element_to_be_clickable - it is Displayed and Enabled:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
# staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
# element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
# element_located_to_be_selected
# element_selection_state_to_be:判断某个元素的选中状态是否符合预期
# element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
# alert_is_present:判断页面上是否存在alert



# 10, 控制浏览器的前进和后退:
import time
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.back()
time.sleep(1)
browser.forward()
# browser.close()


# 11, cookie 操作
get_cookies()
delete_all_cookies()
add_cookie()

# 示例:
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'hahah'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

# 12, 选项卡管理:
# 通过执行js命令实现新开选项卡 window.open(),所有选项卡都存在列表 browser.window_handles 里,
# 通过 browser.window_handles[0]就可以操作第一个选项卡。

import time
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()')  # 用 js 实现新开选项卡
print(browser.window_handles)
browser.switch_to_window(browser.window_handles[1])  # 切换选项卡
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to_window(browser.window_handles[0]) # 切换选项卡
browser.get('https://python.org')


# 13, 异常处理:
# 这里的异常比较复杂,官网的参考地址: http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions
# 现用现查,这里只进行简单的演示,查找一个不存在的元素:

# 示例:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()
参考:
https://www.cnblogs.com/yanshw/p/10852860.html
https://www.cnblogs.com/zhaof/p/6953241.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值