本文是关于爬虫工具selenium的介绍, 包括安装和常见的使用方法, 稍作整理以备之后使用.


文章目录

  • 1. selenium 安装
  • 2. 基本用法
  • 3. 浏览器设置
  • 4. 网页基本信息
  • 5. 定位页面元素
  • 6. 获取元素信息
  • 7. 页面交互
  • 8. 键盘操作
  • 9. 其他
  • 10. 反爬
  • 参考
  • 个人收获


1. selenium 安装

selenium是一款常用的爬虫工具, 与常见的爬虫库相比, 它是直接模拟并调用浏览器直接运行, 从而可以避免很多的反爬机制, 某些程度上类似于按键精灵. 但功能更强大, 自定义性更强.

首先我们需要在python环境中安装selenium库.

pip install selenium
# 或
conda install selenium

除了基本python依赖库, 我们还需要安装浏览器驱动, 由于我使用chrome较多, 这里选择的是chomedriver, 其他浏览器需要寻找对应驱动.

  1. 首先打开chrome浏览器, 在地址栏输入Chrome://version, 查看浏览器对应版本号, 例如目前我的是:98.0.4758.82 (正式版本) (64 位).
  2. 然后在chromedriver网址中寻找到对应版本下载并解压即可.(这是官网, 有墙)
  3. 最后将chromedriver.exe放在python环境的Scripts文件夹中, 或项目文件夹中, 或者放在喜欢的文件夹下(不是).

ok, 然后就开始我们的学习之路吧!

2. 基本用法

  1. 导入库
from selenium import webdriver
  1. 初始化浏览器
    若已经放入Scripts文件夹中, 则直接调用.
# 初始化选择chrome浏览器
browser = webdriver.Chrome()

否则需要手动选择浏览器的路径, 相对路径或绝对路径都可以.

# 初始化选择chrome浏览器
browser = webdriver.Chrome(path)

这时运行会发现有一个chrome浏览器自动弹出, 若我们想要程序安静运行的时候, 就可以设置无界面, 也叫无头浏览器.

# 参数设置
option = webdriver.ChromeOptions()
option.add_argument("headless")

browser = webdriver.Chrome(options=option)
  1. 访问网址
# 访问百度
browser.get(r'https://www.baidu.com/')
  1. 关闭浏览器
# 关闭浏览器
browser.close()

3. 浏览器设置

  1. 浏览器大小
# 全屏
browser.maximize_window()

# 分辨率 600*800
browser.set_window_size(600,800)
  1. 浏览器刷新
    同刷新键, 最好写个异常检测
try:
    # 刷新页面
    browser.refresh()
    print('刷新页面')
except Exception as e:
    print('刷新失败')
  1. 前进/后退
# 后退
browser.back()
# 前进
browser.forward()

4. 网页基本信息

当前网页的标题等信息.

# 网页标题
print(browser.title)
# 当前网址
print(browser.current_url)
# 浏览器名称
print(browser.name)

也可以直接获取网页源码, 这就可以直接使用正则表达式Bs4xpath等工具进行解析了.

print(browser.page_source)

5. 定位页面元素

定位页面元素, 即直接寻找浏览器的中渲染后的元素, 而不是源代码, 以如下搜索框标签为例

<!-- 百度页面的搜索框 -->
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
  1. 按照id/name/class定位
# 在百度搜索框中输入python
browser.find_element_by_id('kw').send_keys('python')
browser.find_element_by_name('wd').send_keys('python')
browser.find_element_by_class_name('s_ipt').send_keys('python')
  1. 按照tag定位
    但是实际上一个页面可能会存在很多个相同的tag, 这时候会使得tag指向模糊, 从而引发报错.
# 在百度搜索框中输入python
browser.find_element_by_tag_name('input').send_keys('python')
  1. link定位
    定位连接名称, 例如在百度左上角链接的例子中进行定位.
<div id="s-top-left" class="s-top-left-new s-isindex-wrap">
    <a href="http://news.baidu.com" target="_blank" class="mnav c-font-normal c-color-t">新闻</a>
    <a href="https://www.hao123.com" target="_blank" class="mnav c-font-normal c-color-t">hao123</a>
    <a href="http://map.baidu.com" target="_blank" class="mnav c-font-normal c-color-t">地图</a>
    ...
</div>

直接根据链接的名称来定位.

# 点击新闻链接
browser.find_element_by_link_text('新闻').click()

但有时候链接名称很长, 可以使用模糊定位partial, 当然, 链接指向得唯一.

# 点击含有闻的链接
browser.find_element_by_partial_link_text('闻').click()
  1. xpath定位
    以上的方法必须保证元素唯一, 当元素不唯一的时候, 就需要使用xpath来进行唯一定位了, 例如使用xpath来寻找搜索框的位置.
# 在百度搜索框中输入python
browser.find_element_by_xpath("//*[@id='kw']").send_keys('python')
  1. css定位
    该方法比xpath简洁且更快一些
# 在百度搜索框中输入python
browser.find_element_by_css_selector('#kw').send_keys('python')
  1. 定位多个元素
    当然, 有时候我们就是需要多个元素, 那么就只需要使用复数s即可.
# element s
browser.find_elements_by_class_name(name)
browser.find_elements_by_id(id_)
browser.find_elements_by_name(name)

6. 获取元素信息

通常在上一步定位元素之后, 会对元素进行一些操作.

  1. 获取元素属性
    例如想要获取百度logo的信息, 先定位图片元素, 再获取信息
# 先使用上述方法获取百度logo元素
logo = browser.find_element_by_class_name('index-logo-src')
# 然后使用get_attribute来获取想要的属性信息
logo = browser.find_element_by_class_name('index-logo-src')
logo_url = logo.get_attribute('src')
  1. 获取元素文本
    首先直接使用class寻找热榜元素, 但是有多个元素, 所以使用复数elements来获得, 并使用for循环打印. 获取文本时使用text来获取
# 获取热榜
hots = browser.find_elements_by_class_name('title-content-title')
for h in hots:
    print(h.text)
  1. 获取其他属性
    获取例如id或tag
logo = browser.find_element_by_class_name('index-logo-src')
print(logo.id)
print(logo.location)
print(logo.tag_name)
print(logo.size)

7. 页面交互

除了直接获取页面的元素, 有时候还需要对页面进行一些操作.

  1. 输入/清除文本
    例如在百度搜索框输入"冬奥会", 然后清除
# 首先获取搜索框元素, 然后使用send_keys输入内容
search_bar = browser.find_element_by_id('kw')
search_bar.send_keys('冬奥会')
# 稍微等两秒, 不然就看不见了
time.sleep(2)
search_bar.clear()
  1. 提交(回车)
    上述内容输入后, 需要点击回车来提交, 才能得到想要的搜索信息.

这篇博文2022年2月5日编写时百度已经发现selenium啦, 所以需要增加一些伪装手段, 在本文最后.👉 直达反爬.

search_bar.send_keys('冬奥会')
search_bar.submit()
  1. 点击
    当我们需要进行点击操作的时候, 使用click. 例如之前的提交, 也可以找到百度一下这个按钮, 然后click!
# 点击热榜第一条
hots = browser.find_elements_by_class_name('title-content-title')
hots[0].click()

单选多选同理, 定位到对应元素, 然后click即可.

而偶尔也会使用右击, 那就需要新的依赖库.

from selenium.webdriver.common.action_chains import ActionChains

hots = browser.find_elements_by_class_name('title-content-title')
# 鼠标右击
ActionChains(browser).context_click(hots[0]).perform()
# 双击
# ActionChains(browser).double_click(hots[0]).perform()

双击是double_click, 找不到合适的例子就不提了.
这里是ActionChains可以深入挖掘, 是定义一系列的操作一起perform, 当然, 普通的一些操作其实也够了.

  1. 悬停
    我就放放不进去.
ActionChains(browser).move_to_element(move).perform()
  1. 下拉框选择
    需要导入一个相关的库, 以访问MySQL官网, 选择下载对应操作系统为例.
from selenium.webdriver.support.select import Select

# 访问mysql下载官网
browser.get(r'https://dev.mysql.com/downloads/mysql/')
select_os = browser.find_element_by_id('os-ga')
# 使用索引选择第三个
Select(select_os).select_by_index(3)
time.sleep(2)
# 使用value选择value="3"的
Select(select_os).select_by_value("3")
time.sleep(2)
# 使用文本值选择macOS
Select(select_os).select_by_visible_text("macOS")
  1. 拖拽
    多用于验证码之类的, 参考菜鸟小例子
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
import time  

browser = webdriver.Chrome()
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)  
time.sleep(2)

browser.switch_to.frame('iframeResult')

# 开始位置
source = browser.find_element_by_css_selector("#draggable")

# 结束位置
target = browser.find_element_by_css_selector("#droppable")

# 执行元素的拖放操作
actions = ActionChains(browser)
actions.drag_and_drop(source, target)
actions.perform()
# 拖拽
time.sleep(15)

# 关闭浏览器
browser.close()

8. 键盘操作

键盘的大部分操作都有相应的命令使用, 需要导入Keys

from selenium.webdriver.common.keys import Keys

# 常见键盘操作
send_keys(Keys.BACK_SPACE)  # 删除键
send_keys(Keys.SPACE)  # 空格键
send_keys(Keys.TAB)  # 制表键
send_keys(Keys.ESCAPE)  # 回退键
send_keys(Keys.ENTER)  # 回车键
send_keys(Keys.CONTRL,'a')  # 全选(Ctrl+A)
send_keys(Keys.CONTRL,'c')  # 复制(Ctrl+C)
send_keys(Keys.CONTRL,'x')  # 剪切(Ctrl+X)
send_keys(Keys.CONTRL,'v')  # 粘贴(Ctrl+V)
send_keys(Keys.F1)  # 键盘F1
send_keys(Keys.F12)  # 键盘F12

9. 其他

  1. 延时等待
    可以发现, 在上面的程序中, 有些效果需要延时等待才能够出现, 在实际中也是需要一定的延时, 一方面是为了不过于频繁访问而被认为是爬虫, 另一方面也是由于网络资源加载需要一定时间来等待.
# 简单的就可以直接使用
time.sleep(2)  # 睡眠2秒
# 还有一些 隐式等待 implicitly_wait 和显示等待 WebDriverWait等操作, 另寻
  1. 截图
    可以保存为base64/png/file三种
browser.get_screenshot_as_file('截图.png')
  1. 窗口切换
    我们的程序是针对当前窗口进行工作的, 但有时候程序需要切换窗口, 那么就需要切换当前工作窗口.
# 访问网址:百度
browser.get(r'https://www.baidu.com/')
hots = browser.find_elements_by_class_name('title-content-title')
hots[0].click()  # 点击第一个热榜
time.sleep(2)
# 回到第 i 个窗口(按顺序)
browser.switch_to_window(browser.window_handles[0])
time.sleep(2)
hots[1].click()  # 点击第一个热榜

当然, 若页面内有iframe元素的话, 则需要切换到该iframe元素中, 可以根据其id切换, 类似的如下

# 切换到子框架
browser.switch_to.frame('iframeResult')
  1. 下拉进度条
    有些网页的内容是随着进度条的下滑而出现的, 所以需要下拉进度条这个操作. 这个操作是使用js代码实现的, 所以我们需要让浏览器执行js代码即可, 其他js代码类似.
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')

10. 反爬

例如上面的百度被发现了, 就需要更好的伪装我们的浏览器browser.

browser = webdriver.Chrome()

browser.execute_cdp_cmd(
    "Page.addScriptToEvaluateOnNewDocument",
    {"source": """Object.defineProperty(
        navigator,
        'webdriver',
        {get: () => undefined})"""
    }
)

网站检测selenium的原理是:

  1. selenium 在开启后的浏览器加了一些变量值, 如:window.navigator.webdriver 等等.
  2. 像window.navigator.webdriver, 在正常的谷歌浏览器是undefined, 在selenium打开的谷歌浏览器是true. 网站就下发js代码, 检测这个变量值给网站, 网站判断这个值, 为true就是爬虫程序就封杀或需要验证码.

当然还有其他的一些手段, 以后遇到再补充.

参考

  1. 2万字带你了解Selenium全攻略!
  2. selenium webdriver 开启网页失败,被发现为爬虫,的解决办法

个人收获

这次回顾了selenium的使用方法, 仔细深究的话操作是很细的, 模仿真正的浏览器运行是没有问题的, 包括登录访问什么的都很简单, 还可以作为浏览器上的按键精灵来使用😂.

相比于直接获取资源的爬虫来说肯定是较慢的, 但胜于功能强大, 还是可以提高摸鱼工作效率的👍.