本文是关于爬虫工具selenium的介绍, 包括安装和常见的使用方法, 稍作整理以备之后使用.
1. selenium 安装
selenium是一款常用的爬虫工具, 与常见的爬虫库相比, 它是直接模拟并调用浏览器直接运行, 从而可以避免很多的反爬机制, 某些程度上类似于按键精灵. 但功能更强大, 自定义性更强.
首先我们需要在python环境中安装selenium库.
pip install selenium
# 或
conda install selenium
除了基本python依赖库, 我们还需要安装浏览器驱动, 由于我使用chrome较多, 这里选择的是chomedriver
, 其他浏览器需要寻找对应驱动.
- 首先打开chrome浏览器, 在地址栏输入
Chrome://version
, 查看浏览器对应版本号, 例如目前我的是:98.0.4758.82 (正式版本) (64 位)
. - 然后在chromedriver网址中寻找到对应版本下载并解压即可.(这是官网, 有墙)
- 最后将
chromedriver.exe
放在python环境的Scripts
文件夹中, 或项目文件夹中, 或者放在喜欢的文件夹下(不是).
ok, 然后就开始我们的学习之路吧!
2. 基本用法
-
导入库
from selenium import webdriver
-
初始化浏览器
若已经放入Scripts
文件夹中, 则直接调用.# 初始化选择chrome浏览器 browser = webdriver.Chrome()
否则需要手动选择浏览器的路径, 相对路径或绝对路径都可以.
# 初始化选择chrome浏览器 browser = webdriver.Chrome(path)
这时运行会发现有一个chrome浏览器自动弹出, 若我们想要程序安静运行的时候, 就可以设置无界面, 也叫
无头浏览器
.# 参数设置 option = webdriver.ChromeOptions() option.add_argument("headless") browser = webdriver.Chrome(options=option)
-
访问网址
# 访问百度 browser.get(r'https://www.baidu.com/')
-
关闭浏览器
# 关闭浏览器 browser.close()
3. 浏览器设置
-
浏览器大小
# 全屏 browser.maximize_window() # 分辨率 600*800 browser.set_window_size(600,800)
-
浏览器刷新
同刷新键, 最好写个异常检测try: # 刷新页面 browser.refresh() print('刷新页面') except Exception as e: print('刷新失败')
-
前进/后退
# 后退 browser.back() # 前进 browser.forward()
4. 网页基本信息
当前网页的标题等信息.
# 网页标题
print(browser.title)
# 当前网址
print(browser.current_url)
# 浏览器名称
print(browser.name)
也可以直接获取网页源码, 这就可以直接使用正则表达式
、Bs4
和xpath
等工具进行解析了.
print(browser.page_source)
5. 定位页面元素
定位页面元素, 即直接寻找浏览器的中渲染后的元素, 而不是源代码, 以如下搜索框标签为例
<!-- 百度页面的搜索框 -->
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
-
按照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')
-
按照tag定位
但是实际上一个页面可能会存在很多个相同的tag, 这时候会使得tag指向模糊, 从而引发报错.# 在百度搜索框中输入python browser.find_element_by_tag_name('input').send_keys('python')
-
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()
-
xpath定位
以上的方法必须保证元素唯一, 当元素不唯一的时候, 就需要使用xpath来进行唯一定位了, 例如使用xpath来寻找搜索框的位置.# 在百度搜索框中输入python browser.find_element_by_xpath("//*[@id='kw']").send_keys('python')
-
css定位
该方法比xpath简洁且更快一些# 在百度搜索框中输入python browser.find_element_by_css_selector('#kw').send_keys('python')
-
定位多个元素
当然, 有时候我们就是需要多个元素, 那么就只需要使用复数s
即可.# element s browser.find_elements_by_class_name(name) browser.find_elements_by_id(id_) browser.find_elements_by_name(name)
6. 获取元素信息
通常在上一步定位元素之后, 会对元素进行一些操作.
-
获取元素属性
例如想要获取百度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')
-
获取元素文本
首先直接使用class寻找热榜元素, 但是有多个元素, 所以使用复数elements
来获得, 并使用for循环
打印. 获取文本时使用text
来获取# 获取热榜 hots = browser.find_elements_by_class_name('title-content-title') for h in hots: print(h.text)
-
获取其他属性
获取例如id或taglogo = browser.find_element_by_class_name('index-logo-src') print(logo.id) print(logo.location) print(logo.tag_name) print(logo.size)
7. 页面交互
除了直接获取页面的元素, 有时候还需要对页面进行一些操作.
-
输入/清除文本
例如在百度搜索框输入"冬奥会", 然后清除# 首先获取搜索框元素, 然后使用send_keys输入内容 search_bar = browser.find_element_by_id('kw') search_bar.send_keys('冬奥会') # 稍微等两秒, 不然就看不见了 time.sleep(2) search_bar.clear()
-
提交(回车)
上述内容输入后, 需要点击回车来提交, 才能得到想要的搜索信息.这篇博文
2022年2月5日
编写时百度已经发现selenium啦, 所以需要增加一些伪装手段, 在本文最后.👉 直达反爬.search_bar.send_keys('冬奥会') search_bar.submit()
-
点击
当我们需要进行点击操作的时候, 使用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
, 当然, 普通的一些操作其实也够了. -
悬停
我就放放不进去.ActionChains(browser).move_to_element(move).perform()
-
下拉框选择
需要导入一个相关的库, 以访问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")
-
拖拽
多用于验证码之类的, 参考菜鸟小例子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. 其他
-
延时等待
可以发现, 在上面的程序中, 有些效果需要延时等待才能够出现, 在实际中也是需要一定的延时, 一方面是为了不过于频繁访问而被认为是爬虫, 另一方面也是由于网络资源加载需要一定时间来等待.# 简单的就可以直接使用 time.sleep(2) # 睡眠2秒 # 还有一些 隐式等待 implicitly_wait 和显示等待 WebDriverWait等操作, 另寻
-
截图
可以保存为base64/png/file三种browser.get_screenshot_as_file('截图.png')
-
窗口切换
我们的程序是针对当前窗口进行工作的, 但有时候程序需要切换窗口, 那么就需要切换当前工作窗口.# 访问网址:百度 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')
-
下拉进度条
有些网页的内容是随着进度条的下滑而出现的, 所以需要下拉进度条这个操作. 这个操作是使用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的原理是:
- selenium 在开启后的浏览器加了一些变量值, 如:window.navigator.webdriver 等等.
- 像window.navigator.webdriver, 在正常的谷歌浏览器是undefined, 在selenium打开的谷歌浏览器是true. 网站就下发js代码, 检测这个变量值给网站, 网站判断这个值, 为true就是爬虫程序就封杀或需要验证码.
当然还有其他的一些手段, 以后遇到再补充.
参考
个人收获
这次回顾了selenium的使用方法, 仔细深究的话操作是很细的, 模仿真正的浏览器运行是没有问题的, 包括登录访问什么的都很简单, 还可以作为浏览器上的按键精灵来使用😂.
相比于直接获取资源的爬虫来说肯定是较慢的, 但胜于功能强大, 还是可以提高摸鱼工作效率的👍.