本文是关于爬虫工具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 文件夹中, 则直接调用.
browser = webdriver.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()
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定位
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指向模糊, 从而引发报错.
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来寻找搜索框的位置.
browser.find_element_by_xpath("//*[@id='kw']").send_keys('python')
-
css定位 该方法比xpath简洁且更快一些
browser.find_element_by_css_selector('#kw').send_keys('python')
-
定位多个元素 当然, 有时候我们就是需要多个元素, 那么就只需要使用复数s 即可.
browser.find_elements_by_class_name(name)
browser.find_elements_by_id(id_)
browser.find_elements_by_name(name)
6. 获取元素信息
通常在上一步定位元素之后, 会对元素进行一些操作.
-
获取元素属性 例如想要获取百度logo的信息, 先定位图片元素, 再获取信息
logo = browser.find_element_by_class_name('index-logo-src')
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或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. 页面交互
除了直接获取页面的元素, 有时候还需要对页面进行一些操作.
-
输入/清除文本 例如在百度搜索框输入"冬奥会", 然后清除
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()
双击是double_click , 找不到合适的例子就不提了. 这里是ActionChains 可以深入挖掘, 是定义一系列的操作一起perform , 当然, 普通的一些操作其实也够了. -
悬停 我就放放不进去. ActionChains(browser).move_to_element(move).perform()
-
下拉框选择 需要导入一个相关的库, 以访问MySQL官网, 选择下载对应操作系统为例. from selenium.webdriver.support.select import Select
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)
Select(select_os).select_by_value("3")
time.sleep(2)
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')
send_keys(Keys.CONTRL,'c')
send_keys(Keys.CONTRL,'x')
send_keys(Keys.CONTRL,'v')
send_keys(Keys.F1)
send_keys(Keys.F12)
9. 其他
-
延时等待 可以发现, 在上面的程序中, 有些效果需要延时等待才能够出现, 在实际中也是需要一定的延时, 一方面是为了不过于频繁访问而被认为是爬虫, 另一方面也是由于网络资源加载需要一定时间来等待.
time.sleep(2)
-
截图 可以保存为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)
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就是爬虫程序就封杀或需要验证码.
当然还有其他的一些手段, 以后遇到再补充.
参考
- 2万字带你了解Selenium全攻略!
- selenium webdriver 开启网页失败,被发现为爬虫,的解决办法
个人收获
这次回顾了selenium的使用方法, 仔细深究的话操作是很细的, 模仿真正的浏览器运行是没有问题的, 包括登录访问什么的都很简单, 还可以作为浏览器上的按键精灵来使用😂.
相比于直接获取资源的爬虫来说肯定是较慢的, 但胜于功能强大, 还是可以提高摸鱼工作效率的👍.
|