Selenium
selenium为爬虫框架, 能打开本地浏览器, 然后根据DOM元素执行输入和点击操作
Selenium安装
python安装包
pip install selenium然后根据本地浏览器下载并安装相关驱动文件
Selenium简单使用
对象创建
from selenium import webdriver # 导入包
# 生成firefox的可操控对象, 可传入额外参数进行控制
driver = webdriver.Firefox(options=None, service=None)信息查看
| 命令 | 注释 |
|---|---|
driver.current_url | 返回当前界面的url |
driver.title | 返回当前页面的标题 |
driver.page_source | 返回当前页面的源码 |
driver.name | 返回当前浏览器的名称 |
相关操作
屏幕截屏
driver.save_screenshot(path) # 截屏, 并将截屏存储在指定文件路径
driver.save_full_page_screenshot(path) # 截整个屏? 暂时不理解区别控制操作
driver.get(url) # 打开一个网址,同时会把 response 信息自动保存
driver.back() # 返回上一个网址
driver.forward() # 前进到一个网址
driver.refresh() # 刷新网址
driver.close() # 关闭当前标签页,不关闭浏览器
driver.quit() # 关闭浏览器,释放进程
driver.set_window_size(WIDTH, HEIGHT) # 修改浏览器大小元素查找
# 定位DOM树中相关元素位置
from selenium.webdriver.common.by import By # 定位相关包
## 通过id进行定位
item_find = driver.find_element(by=By.ID, value='id_value')
## 通过class定位
item_find = driver.find_element(by=By.CLASS_NAME, value='class_value')
## 通过xpath定位
item_find = driver.find_element(by=By.XPATH, value='xpath_value')
## 通过CSS选择器定位
item_find = driver.find_element(by=By.CSS_SELECTOR, value="css_value")
## 有两种find方式,
## 第一种driver.find_element会返回第一个符合检索条件的对象
## 第二种driver.find_elements会返回一个list, 包含所有符合检索条件的对象元素操作
# 对DOM树中相关元素操作
## 清除内容, 貌似需要相关元素是输入框?
item_find.clear()
## 填入内容, 需要相关元素是填入框
item_find.send_keys(string)
## 获取内容
item_find.text
## 获取属性
item_find.get_attribute('style')
## 能否获取到
item_find.is_displayed()
## 判断可勾选按钮是否被勾选到
item_find.is_selected()
## 判断元素是否被启用, 如必须填写信息才能按下提交
item_find.is_enabled()额外参数
# options配置
## 获取options对象
options = webdriver.FirefoxOptions()
## 退出沙盒模式
options.add_argument("--no-sandbox")
## 无头浏览器模式, 似乎是将js代码直接放到内存中执行, 并没有显示界面
options.add_argument("--headless")
## 不使用显卡
options.add_argument('--disable-gpu')
## 指定火狐浏览器可执行文件的位置
options.binary_location = firefox_bin
## 添加代理服务器
options.add_argument("--proxy-server=http://ip:port")
## 修改请求头
options.add_argument("--user-agent=xxxxxxxx")# profile支持
profile = webdriver.FirefoxProfile()
## 是否允许js运行
profile.set_preference("javascript.enabled", False)
# service配置
service = webdriver.FirefoxService()Selenium进阶操作
标签页操作
# 返回当前标签页对象
driver.current_window_handle
# 获取当前浏览器对象的所有标签页对象
driver.window_handles
# 跳转到指定的标签页, 需要输入上一个返回的标签页对象
driver.switch_to.window(item)
## 注意! 上述输入的标签页对象会随着新标签页打开动态变化, 需要根据上条命令加下标实时指定!cookie获取
# 获取当前浏览器的cookie
driver.get_cookies()
## 提纯cookie, 注意, 需根据实际使用提纯
{data["name"]: data["value"] for data in driver.get_cookies()}js代码执行
# 执行js代码, 需要手敲js代码...
driver.execute_script(js)
## 打开新的标签页
js = "window.open('https://bing.com');"
## 向下滚动到500像素位置
js = "window.scrollTo(0,1000);"等待加载
# 等待, 应对网页的动态加载
## 强制等待
time.sleep(number)
## 隐式等待, 每隔一段时间自动检测元素是否定位成功,
### 若成功, 则立马继续执行
### 若超过设置的最大有效时间还未定位成功, 则报错
driver.implicitly_wait(number)
## 显式等待, 确定等待某个指定元素, 软件测试中用的较多弹窗操作
# 获取弹窗对象
alert = driver.switch_to.alert
## 查看弹窗对象文字信息
alert.text
## 接受警告
alert.accept()
## 取消弹窗, 如果能取消
alert.dismiss()
## 输入值
alert.send_keys()键盘操作
from selenium.webdriver.common.keys import Keys # 导包
## 需要先找到对应元素
item_find.send_keys(Keys.BACK_SPACE) ## 删除键
item_find.send_keys(Keys.SPACE) ## 空格键
item_find.send_keys(Keys.TAB) ## TAB
item_find.send_keys(Keys.LEFT) ## 左移
item_find.send_keys(Keys.RIGHT) ## 右移
item_find.send_keys(Keys.ENTER) ## 回车
item_find.send_keys(Keys.ESCAPE) ## ESCAPE
item_find.send_keys(Keys.ALT) ## ALT
item_find.send_keys(Keys.DELETE) ## DELETE
item_find.send_keys(Keys.SHIFT) ## SHIFT
item_find.send_keys(Keys.PAGE_UP) ## PAGE_UP
item_find.send_keys(Keys.PAGE_DOWN) ## PAGE_DOWN
item_find.send_keys(Keys.END) ## END
item_find.send_keys(Keys.HOME) ## HOME
item_find.send_keys(Keys.INSERT) ## INSERT
item_find.send_keys(Keys.UP) ## UP
item_find.send_keys(Keys.DOWN) ## DOWN
item_find.send_keys(Keys.NUMPAD0) ## 小键盘上数字, 自行更改
item_find.send_keys(Keys.F1) ## F1, 自行更改
item_find.send_keys(Keys.CONTROL, 'a') ## CTRL + a
item_find.send_keys(Keys.CONTROL, 'c') ## CTRL + c 似乎没有往剪切板里边写
item_find.send_keys(Keys.CONTROL, 'v') ## CTRL + v
item_find.send_keys(Keys.CONTROL, 'x') ## CTRL + x 似乎没有往剪切板里边写鼠标操作
from selenium.webdriver.common.action_chains import ActionChains # 导包
## 需要传入drive得到鼠标操作对象
mouse_obj = ActionChains(driver)
obj = mouse_obj.click(item_find) # 单击元素, 并不会立即生效, 而是会加入队列
obj.perform() # 开始执行队列中所有操作
obj = mouse_obj.double_click(item_find) # 双击鼠标左键
obj = mouse_obj.click_and_hold(item_find) # 长按鼠标左键
obj = mouse_obj.context_click(item_find) # 单击鼠标右键
obj = mouse_obj.move_to_element(item_find) # 鼠标悬停, 似乎没效果
obj = mouse_obj.drag_and_drop(item_find1, item_find2) # 鼠标从1拖拽到2, 未尝试
obj = mouse_obj.drag_and_drop_by_offset(item_find, xoffset, yoffset) # 鼠标从目标元素拖拽到某个坐标, 未做尝试
obj = mouse_obj.move_by_offset(xoffset, yoffset) # 鼠标移动到某个坐标, 未做尝试
obj = mouse_obj.move_to_element_with_offset(item_find, xoffset, yoffset) # 鼠标移动到距某个元素多少距离, 未做尝试
obj = mouse_obj.release(item_find) # 在某个元素位置松开鼠标左键
obj = mouse_obj.send_keys(*keys_to_send) # 发送多个参数到当前鼠标指向的元素, 未做尝试
obj = mouse_obj.send_keys_to_element(item_find, *keys_to_send) # 发送多个参数到指定元素, 未做尝试
obj = mouse_obj.key_down(Keys. , item_find) # 按下某个键盘上的键
obj = mouse_obj.key_up(Keys. , item_find) # 松开某个键盘上的键
# 可链式定义, 如
mouse_obj.click(item_find).click(item_find).click(item_find).perform()第三方模块
这个包是为了拦截某些报文,从报文中提取出图片等内容
pip install selenium-wirefrom seleniumwire import webdriver # 使用第三方包
# 与上述过程一致
# 获取请求头
for request in driver.requests:
pprint(request.headers)
# 获取响应头
for request in driver.requests:
pprint(request.response.headers)隐藏selenium指纹
不让网站检测出是机器人
加载js文件隐藏
js文件太大了, 就不直接贴出来了
with open(stealth.min.js, "r") as f:
js = f.read()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": js})不太行, 似乎linux下执行会报错, 可能是适配windows的吧
浏览器Debug模式
打开浏览器的Debug模式, 然后使用之前下载的浏览器驱动接管进入Debug模式的浏览器, 此方法相当于用户正常打开了一个浏览器, 能有效隐藏爬虫.
Firefox下连接Debug模式隐藏指纹(失败!)
尝试用Firefox进入Debug模式, 但似乎进入失败, 并没有正常监听端口, 在Windows下也做了尝试, 似乎也没有正常监听, 但还是记录下基本思路
# 打开debug模式, 并允许远程控制, 并设置控制端口为2828
firefox --marionette --remote-debugging-port 2828
## --marionette 允许远程控制
## --remote-debugging-port 远程控制的监听端口
## 就是这一步失败的! firefox根本没有监听端口! 我 netstat -ntlp 看过了!
## 真是稀奇! 明明 firefox -h 里边就这么写的!
# 使用浏览器驱动连接上已经打开的窗口
geckodriver --connect-existing --marionette-port 2828
## --connect-existing 连接已经打开的窗口
## --marionette-port 打开窗口的远程监听端口driver = webdriver.Remote(command_executor="http://localhost:4444")好像发现了问题! /usr/bin/firefox是个能正常打开的文件! 似乎是里边设置了如何调用firefox! 等会再去看看原因
Chrome下连接Debug模式隐藏指纹
很好, 起码在Debian下正常连接上了, Windows下没有测试过
# 打开chrome浏览器调试模式
google-chrome --remote-debugging-port=9222 --user-data-dir=/home/why/chrome/
## --remote-debugging-port 远程调试端口
## --user-data-dir 浏览器存放数据位置, 设置之后可以和默认浏览器环境错开
# 使用浏览器驱动连接上已经打开的窗口
chromedriver --port=4444 --adb-port=9222
## --port 浏览器驱动监听的端口
## --adb-port 浏览器远程调试端口options = webdriver.ChromeOptions()
options.debugger_address = "127.0.0.1:9222"
driver = webdriver.Chrome(options=options)