【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用
概述
前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法,它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特,强大,而且使用更为方便,目前检测少,强烈推荐!!!
这里推荐观看十一姐 B 站 DrissionPage 系列视频,很详细:
合集·爬虫自动化 DrissionPage 实战案例:
https://space.bilibili.com/308704191/channel/collectiondetail?sid=1947582
DrissionPage 相关资料:
官方文档:https://www.drissionpage.cn
Drissionpage “姊妹库”:https://gitee.com/haiyang0726/SaossionPage
DrissionPage 的使用
介绍
DrissionPage 是一个基于 python 的网页自动化工具。它既能控制浏览器,也能收发数据包,还能把两者合而为一。可兼顾浏览器自动化的便利性和 requests 的高效率。它功能强大,内置无数人性化设计和便捷功能。它的语法简洁而优雅,代码量少,对新手友好。
-
支持系统:Windows、Linux、Mac;
-
python 版本:3.6 及以上;
-
支持应用:Chromium 内核浏览器(如 Chrome、Edge),electron 应用;
特性
强大的自研内核
本库采用全自研的内核,内置了无数实用功能,对常用功能作了整合和优化,对比 selenium,有以下优点:
- 无 webdriver 特征;
- 无需为不同版本的浏览器下载不同的驱动;
- 运行速度更快;
- 可以跨 iframe 查找元素,无需切入切出;
- 把 iframe 看作普通元素,获取后可直接在其中查找元素,逻辑更清晰;
- 可以同时操作浏览器中的多个标签页,即使标签页为非激活状态,无需切换;
- 可以直接读取浏览器缓存来保存图片,无需用 GUI 点击另存;
- 可以对整个网页截图,包括视口外的部分(90 以上版本浏览器支持);
- 可处理非
open
状态的 shadow-root。
亮点功能
除了以上优点,本库还内置了无数人性化设计。
- 极简的语法规则,集成大量常用功能,代码更优雅;
- 定位元素更加容易,功能更强大稳定;
- 无处不在的等待和自动重试功能。使不稳定的网络变得易于控制,程序更稳定,编写更省心;
- 提供强大的下载工具。操作浏览器时也能享受快捷可靠的下载功能;
- 允许反复使用已经打开的浏览器。无需每次运行从头启动浏览器,调试超方便;
- 使用 ini 文件保存常用配置,自动调用,提供便捷的设置,远离繁杂的配置项;
- 内置 lxml 作为解析引擎,解析速度成几个数量级提升;
- 使用 POM 模式封装,可直接用于测试,便于扩展;
- 高度集成的便利功能,从每个细节中体现;
- 还有很多细节,这里不一一列举,欢迎实际使用中体验。
安装升级
# 安装
pip install DrissionPage# 升级最新稳定版
pip install DrissionPage --upgrade# 指定版本升级
pip install DrissionPage==4.0.0b17
- 如何在无界面 Linux 使用:
CentOS 请参考这篇文章:
linux 部署说明:https://blog.csdn.net/sinat_39327967/article/details/132181129
Ubuntu 请参考这篇文章:
DrissionPage 在 Ubuntu Linux 的使用:https://zhuanlan.zhihu.com/p/674687748
使用
访问网页
from DrissionPage import ChromiumPage, ChromiumOptionsco = ChromiumOptions().set_paths(browser_path=r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe")
# 1、设置无头模式:co.headless(True)
# 2、设置无痕模式:co.incognito(True)
# 3、设置访客模式:co.set_argument('--guest')
# 4、设置请求头user-agent:co.set_user_agent()
# 5、设置指定端口号:co.set_local_port(7890)
# 6、设置代理:co.set_proxy('http://localhost:1080')
page = ChromiumPage(co)page.get('https://gitee.com/login', retry=3, timeout=15, interval=2)# 定位到账号文本框,获取文本框元素
ele = page.ele('#user_login')
# 输入对文本框输入账号
ele.input('您的账号')
# 定位到密码文本框并输入密码
page.ele('#user_password').input('您的密码')
# 点击登录按钮
page.ele('@value=登 录').click()
获取浏览器路径的方法:
- 这里的浏览器路径不一定是 Chrome,Edge 等 Chromium 内核的浏览器都可以;
- 打开浏览器,在地址栏输入
chrome://version
(Edge 输入edge://version
),回车
如图所示,红框中就是要获取的路径:
- 此法不限于 Windows,有界面的 Linux 也是这样取路径。
- get()
该方法用于跳转到一个网址。当连接失败时,程序会进行重试:
获取查找元素
本库提供一套简洁易用的语法,用于快速定位元素,并且内置等待功能、支持链式查找,减少了代码的复杂性。
同时也兼容 css selector、xpath、selenium 原生的 loc 元组。
定位元素大致分为三种方法:
- 在页面或元素内查找子元素;
- 根据 DOM 结构相对定位;
- 根据页面布局位置相对定位;
- xpath 方式:
# 输入
page.ele('xpath://input[@id="bindMobileFree"]').input("123456789")
# 点击
page.ele('x://span[@class="getYZM_btn"]').click()
- 其他方式:
from DrissionPage import SessionPagepage = SessionPage()
page.get('https://gitee.com/explore')# 获取包含“全部推荐项目”文本的 ul 元素
ul_ele = page.ele('tag:ul@@text():全部推荐项目') # 获取该 ul 元素下所有 a 元素
titles = ul_ele.eles('tag:a') # 遍历列表,打印每个 a 元素的文本
for i in titles: print(i.text)
foot = page.ele('#footer-left') # 用 id 查找元素
first_col = foot.ele('css:>div') # 使用 css selector 在元素的下级中查找元素(第一个)
lnk = first_col.ele('text:命令学') # 使用文本内容查找元素
text = lnk.text # 获取元素文本
href = lnk.attr('href') # 获取元素属性值print(text, href, '\n')# 简洁模式串联查找
text = page('@id:footer-left')('css:>div')('text:命令学').text
print(text)
等待
-
✅️️ 页面对象的等待方法:
-
📌
wait.load_start()
:此方法用于等待页面进入加载状态;-
注意
get()
已内置等待加载开始,后无须跟wait.load_start()
;
-
-
📌
wait.doc_loaded()
:此方法用于等待页面文档加载完成;- 注意
- 此功能仅用于等待页面主 document 加载,不能用于等待 js 加载的变化;
- 除非
load_mode
为None
,get()
方法已内置等待加载完成,后面无须添加等待;
- 注意
-
📌
wait.eles_loaded()
:此方法用于等待元素被加载到 DOM; -
📌
wait.ele_displayed()
:此方法用于等待一个元素变成显示状态; -
📌
wait.ele_hidden()
:此方法用于等待一个元素变成隐藏状态; -
📌
wait.ele_deleted()
:此方法用于等待一个元素被从 DOM 中删除; -
📌
wait.download_begin()
:此方法用于等待下载开始; -
📌
wait.upload_paths_inputted()
:此方法用于等待自动填写上传文件路径; -
📌
wait.new_tab()
:此方法用于等待新标签页出现; -
📌
wait.title_change()
:此方法用于等待 title 变成包含或不包含指定文本; -
📌
wait.url_change()
:此方法用于等待 url 变成包含或不包含指定文本。 比如有些网站登录时会进行多重跳转,url 发生多次变化,可用此功能等待到达最终需要的页面; -
📌
wait.alert_closed()
:此方法用于等待弹出框被关闭; -
📌
wait()
:此方法用于等待若干秒;
-
-
✅️️ 元素对象的等待方法
-
📌
wait.displayed()
:此方法用于等待元素从隐藏状态变成显示状态; -
📌
wait.hidden()
:此方法用于等待元素从显示状态变成隐藏状态; -
📌
wait.deleted()
:此方法用于等待元素被从 DOM 删除; -
📌
wait.covered()
:此方法用于等待元素被其它元素覆盖; -
📌
wait.not_covered()
:此方法用于等待元素不被其它元素覆盖; -
📌
wait.enabled()
:此方法用于等待元素变为可用状态; -
📌
wait.disabled()
:此方法用于等待元素变为不可用状态; -
📌
wait.stop_moving()
:此方法用于等待元素运动结束; -
📌
wait.clickable()
:此方法用于等待元素可被点击; -
📌
wait.disabled_or_deleted()
:此方法用于等待元素变为不可用或被删除; -
📌
wait()
:此方法用于等待若干秒。
-
监听网络数据
- 注意:要先启动监听,再执行动作,
listen.start()
之前的数据包是获取不到的; - 等待并获取:
- 等待并获取:
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.get('https://gitee.com/explore/all') # 访问网址,这行产生的数据包不监听page.listen.start('gitee.com/explore') # 开始监听,指定获取包含该文本的数据包(部分url)
for _ in range(5):page('@rel=next').click() # 点击下一页res = page.listen.wait() # 等待并获取一个数据包print(res.url) # 输出数据包urlprint(res.response.headers) # 输出响应头print(res.response.statusText) # 输出响应状态码print(res.response.body) # 输出响应内容
- 实时获取:
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.listen.start('gitee.com/explore') # 开始监听,指定获取包含该文本的数据包
page.get('https://gitee.com/explore/all') # 访问网址i = 0
for packet in page.listen.steps():print(packet.url) # 打印数据包urlpage('@rel=next').click() # 点击下一页i += 1if i == 5:break
动作链
- ✅️ 使用方法
* 📌 使用内置actions
属性
```python
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.get('https://www.baidu.com')
page.actions.move_to('#kw').click().type('DrissionPage')
page.actions.move_to('#su').click()
```* 📌 使用新对象```python
from DrissionPage import ChromiumPage
from DrissionPage.common import Actionspage = ChromiumPage()
ac = Actions(page)
page.get('https://www.baidu.com')
ac.move_to('#kw').click().type('DrissionPage')
ac.move_to('#su').click()
```* 📌 操作方式```python
ac.move_to(ele).click().type('some text')
```
-
✅️ 移动鼠标
- 📌
move_to()
:此方法用于移动鼠标到元素中点,或页面上的某个绝对坐标; - 📌
move()
:此方法用于使鼠标相对当前位置移动若干距离; - 📌
up()
:此方法用于使鼠标相对当前位置向上移动若干距离; - 📌
down()
:此方法用于使鼠标相对当前位置向下移动若干距离; - 📌
left()
:此方法用于使鼠标相对当前位置向左移动若干距离; - 📌
right()
:此方法用于使鼠标相对当前位置向右移动若干距离。
- 📌
-
✅️ 鼠标按键
- 📌
click()
:此方法用于单击鼠标左键,单击前可先移动到元素上; - 📌
r_click()
:此方法用于单击鼠标右键,单击前可先移动到元素上; - 📌
m_click()
:此方法用于单击鼠标中键,单击前可先移动到元素上; - 📌
db_click()
:此方法用于双击鼠标左键,双击前可先移动到元素上; - 📌
hold()
:此方法用于按住鼠标左键不放,按住前可先移动到元素上; - 📌
release()
:此方法用于释放鼠标左键,释放前可先移动到元素上; - 📌
r_hold()
:此方法用于按住鼠标右键不放,按住前可先移动到元素上; - 📌
r_release()
:此方法用于释放鼠标右键,释放前可先移动到元素上; - 📌
m_hold()
:此方法用于按住鼠标中键不放,按住前可先移动到元素上; - 📌
m_release()
:此方法用于释放鼠标中键,释放前可先移动到元素上。
- 📌
-
✅️ 滚动滚轮
- 📌
scroll()
:此方法用于滚动鼠标滚轮,滚动前可先移动到元素上;
- 📌
-
✅️ 键盘按键和文本输入
- 📌
key_down()
:此方法用于按下键盘按键。非字符串按键(如 ENTER)可输入其名称,也可以用 Keys 类获取; - 📌
key_up()
:此方法用于提起键盘按键。非字符串按键(如 ENTER)可输入其名称,也可以用 Keys 类获取; - 📌
input()
:此方法用于输入一段文本或多段文本,也可输入组合键。多段文本或组合键用列表传入; - 📌
type()
:此方法用于以按键盘的方式输入一段或多段文本。也可输入组合键。type()
与input()
区别在于前者模拟按键输入,逐个字符按下和提起,后者直接输入一整段文本。
- 📌
-
✅️ 等待
- 📌
wait()
:此方法用于等待若干秒;
- 📌
-
✅️ 属性
- 📌
owner
:此属性返回使用此动作链的页面对象; - 📌
curr_x
:此属性返回当前光标位置的 x 坐标; - 📌
curr_y
:此属性返回当前光标位置的 y 坐标。
- 📌
-
✅️ 示例
- 📌 模拟输入 ctrl+a
from DrissionPage import ChromiumPage from DrissionPage.common import Keys, Actions# 创建页面 page = ChromiumPage() # 创建动作链对象 ac = Actions(page)# 鼠标移动到<input>元素上 ac.move_to('tag:input') # 点击鼠标,使光标落到元素中 ac.click() # 按下 ctrl 键 ac.key_down(Keys.CTRL) # 输入 a ac.type('a') # 提起 ctrl 键 ac.key_up(Keys.CTRL)
链式写法:
ac.click('tag:input').key_down(Keys.CTRL).type('a').key_up(Keys.CTRL)
更简单的写法:
ac.click('tag:input').type(Keys.CTRL_A)
- 📌 拖拽元素
把一个元素向右拖拽 300 像素:
from DrissionPage import ChromiumPage from DrissionPage.common import Actions# 创建页面 page = ChromiumPage() # 创建动作链对象 ac = Actions(page)# 左键按住元素 ac.hold('#div1') # 向右移动鼠标300像素 ac.right(300) # 释放左键 ac.release()
把一个元素拖拽到另一个元素上:
ac.hold('#div1').release('#div2')
-
✅️ 页面对象内置动作链
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.actions.move_to((300, 500)).hold().move(300).release()
标签页操作
📌 注意:可以对多标签页操作, 即可实现并发自动化。
-
✅️️ 标签页总览
- 📌
tabs_count
:此属性返回标签页数量。 - 📌
tab_ids
:此属性以list
方式返回所有标签页 id。
- 📌
-
✅️️ 新建标签页
- 📌
new_tab()
:该方法用于新建一个标签页,该标签页在最后面。只有 Page 对象拥有此方法。
- 📌
-
✅️️ 获取标签页对象
- 📌
get_tab()
:此方法用于获取一个标签页对象。可指定标签页序号、id、标题、url、类型等条件用于检索。当id_or_num
不为None
时,其它参数无效。当所有参数都为None
时,获取 Page 对象控制的标签页的 Tab 对象。title
、url
和tab_type
三个参数是与关系。只有 Page 对象拥有此方法。 - 📌
get_tabs()
:此方法用于查找符合条件的 tab 对象
- 📌
-
✅️️ 使用多例
from DrissionPage import ChromiumPage from DrissionPage.common import Settingspage = ChromiumPage() page.new_tab() page.new_tab()# 未启用多例: tab1 = page.get_tab(1) tab2 = page.get_tab(1) print(id(tab1), id(tab2))# 启用多例: Settings.singleton_tab_obj = False tab1 = page.get_tab(1) tab2 = page.get_tab(1) print(id(tab1), id(tab2))
-
✅️️ 关闭和重连
- 📌
close()
- 📌
disconnect()
- 📌
reconnect()
- 📌
close_tabs()
- 📌
-
✅️️ 激活标签页
- 📌
set.tab_to_front()
- 📌
set.activate()
- 📌
-
✅️️ 多标签页协同
截图和录像
✅️️ 页面截图
# 对整页截图并保存
page.get_screenshot(path='tmp', name='pic.jpg', full_page=True)
✅️️ 元素截图
img = page('tag:img')
img.get_screenshot()
bytes_str = img.get_screenshot(as_bytes='png') # 返回截图二进制文本
✅️️ 页面录像
from DrissionPage import ChromiumPagepage = ChromiumPage()
page.screencast.set_save_path('video') # 设置视频存放路径
page.screencast.set_mode.video_mode() # 设置录制
page.screencast.start() # 开始录制
page.wait(3)
page.screencast.stop() # 停止录制
执行 JS 语句
page.run_js(f'localStorage.setItem("__user_token.v3",`{token}`)')page.run_js(f'localStorage.setItem("__user_info",`{token}`)')cookies_set = ""
cookies_set += f'document.cookie=`__user_token.v3={token}; path=/;domain=i.shengcaiyoushu.com;`;'page.run_js(cookies_set)
反检测
在 Selenium、Playwright 、Playwright 的使用中,我们讲到了自动化工具容易被网站检测,也提供了一些绕过检测的方案。这里我们介绍一下 DrissionPage 的反检测方案。
以 https://bot.sannysoft.com 为例,我们分别测试正常模式与无头模式下的检测结果:
- 正常模式:
- 无头模式:
可以发现,我们没有做任何反检测的操作,都不会被检测到,就连使用无头模式也只有 userAgent 有问题,不过我们 co.set_user_agent() 设置一下就可以了,虽然这些只是最基本的检测机制,但也够用了。
总结
DrissionPage 语法简洁,使用方便,底层基于 CDP 协议,拥有较强的反检测机制,目前不需要做任何反检测的操作就可以绕过国内外绝大多数的网站自动化检测,包含但不限于 (xx 验证码、某数、5s)。 还有很多强大的功能这里没法一一展示,强烈推荐!
相关文章:
【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用
概述 前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法,它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特,强大,而且使用更为方便,目前检测少,强烈推荐!!&a…...
c++_0基础_讲解7 练习
这一讲我为大家准备了几道题目,大家试着独自做一下(可能来自不同网站) 整数大小比较 - 洛谷 题目描述 输入两个整数,比较它们的大小。若 x>yx>y ,输出 > ;若 xyxy ,输出 ÿ…...
docker一些常用命令以及镜像构建完后部署到K8s上
docker一些常用命令以及镜像构建完后部署到K8s上 1.创建文件夹2.删除文件3.复制现有文件内容到新建文件4.打开某个文件5.查看文件列表6.解压文件(tar格式)7.解压镜像8.查看镜像9.删除镜像10.查看容器11.删除容器12.停止运行容器13.构建镜像14.启动容器15…...
在typora中利用正则表达式,批量处理图片
一,png格式 在 Typora 中批量将 HTML 图片标签转换为简化的 Markdown 图片链接,且忽略 alt 和 style 属性,可以按照以下步骤操作: 打开 Typora 并加载你的文档。按下 Ctrl H(在 Windows/Linux 上)或 Cmd…...
构建LangChain应用程序的示例代码:33、如何在LangChain框架中使用HumanInputChatModel来模拟人工输入的聊天模型教程
除了HumanInputLLM,LangChain还提供了一个伪聊天模型类,可以用于测试、调试或教育目的。这允许您模拟对聊天模型的调用,并模拟如果人类接收到这些消息会如何响应。 在这篇笔记中,我们将介绍如何使用这个模型。 我们首先在代理中…...
虚拟机使用桥接模式网络配置
1、获取本机的网络详细信息 windowr 输入cmd 使用ipconfig -all 一样即可 在自己的虚拟机中设置网络 虚拟机中的ip ---------192.168.36.*,不要跟自己的本机ip冲突 网关-----------192.168.36.254 一样即可 dns -----------一样即可,我多写了几个&am…...
韩顺平0基础学java——第24天
p484-508 System类 常见方法 System.arrycopy(src,0,dest,1,2); 表示从scr的第0个位置拷贝2个,放到目标数组索引为1的地方。 BigInteger和BigDecimal类 保存大整数和高精度浮点数 BigInte…...
leecode N皇后
深度优先遍历,然后回溯 思考得到的技巧: 1.先思考怎么用学过的数据结构解题 2.回溯不只需要知道最后一步,还需要知道之前所走的每一步 3. 棋盘的生成,.join([]),可以变列表为字符串 看题解得到的技巧: 1.妙啊…...
2024050802-重学 Java 设计模式《实战模板模式》
重学 Java 设计模式:实战模版模式「模拟爬虫各类电商商品,生成营销推广海报场景」 一、前言 黎明前的坚守,的住吗? 有人举过这样一个例子,先给你张北大的录取通知书,但要求你每天5点起床,12点…...
UNIAPP-ADB无线调试
ADB下载 SDK 平台工具版本说明 | Android Studio | Android Developers (google.cn) 环境变量配置 ADB版本查看 adb version 手机使用数据线连接到电脑 手机需要授权adb调试(开发人员选项里面) CMD输入命令 adb tcpip 5555 到了这一步你手机已经启动了adb服务了&…...
【stm32-新建工程】
stm32-新建工程 ■ 下载相关STM32Cube官方固件包(F1,F4,F7,H7)■ 1. ST官方搜索STM32Cube■ 2. 搜索 STM32Cube■ 3. 点击获取软件■ 4. 选择对应的版本下载■ 5. 输入账号信息■ 6. 出现下载弹框,等待下载…...
写点什么吧,作为STM32系列的开篇……
自从本科毕业后,就再也没碰过单片机…… 自从研究生毕业后,就再也没碰过硬件…… 自以为以前单片机玩的熟得很,特别是ATMEGA系列的AVR单片机,由于老师的推荐,本科时花了好多精力在这个系列单片机上面…… 本科时STM…...
代码随想录算法训练营第十天| 232.用栈实现队列|225. 用队列实现栈|20. 有效的括号|1047. 删除字符串中的所有相邻重复项
232.用栈实现队列 文档讲解:代码随想录 视频讲解:栈的基本操作! | LeetCode:232.用栈实现队列_哔哩哔哩_bilibili 知道要用两个栈实现,具体咋做忘了。队列的特性是先进先出,栈是先进后出,入队操…...
Pulsar 社区周报 | No.2024-06-07 | Apache Pulsar 新分支 3.3 版本发布
“ 各位热爱 Pulsar 的小伙伴们,Pulsar 社区周报更新啦!这里将记录 Pulsar 社区每周的重要更新,每周发布。 ” 本期主题:Apache Pulsar 新分支 3.3 版本发布 Apache Pulsar 新分支 3.3 版本发布:Apache Pulsar 3.3.0[1…...
Go源码--sync库(3):sync.Pool(2)
回收 回收其实就是将 pool.local 置为空 可以让垃圾回收器回收 我们来看下 源码 func init() {// 将 poolCleanup 注册到 gc开始前的准备工作处理器中在 STW时执行runtime_registerPoolCleanup(poolCleanup) }这里注册了清理程序到GC前准备工作 也就是发生GC前需要执行这段代…...
Go如何在本地引用以及发布并引用自定义工具包
如何引用本地自定义工具包 我们首先要准备两个项目,分别为需要引入的工具包和当前项目。 myutils、myproject1. myutils为我们的项目1-工具包 package mypakgeimport "strings"func IsContains(s string) bool {if strings.Contains(s, "a")…...
使用了代理IP怎么还会被封?代理IP到底有没有效果
代理IP作为一种网络工具,被广泛应用于各种场景,例如网络爬虫、海外购物、规避地区限制等。然而,很多用户在使用代理IP的过程中却发现自己的账号被封禁,这让他们不禁产生疑问:使用了代理IP怎么还会被封?代理…...
在WSL2的Ubuntu中安装和使用Docker/Podman
在WSL2的Ubuntu中安装和使用Docker/Podman 0. 目的 当网络环境良好(例如在公司,能直接访问Google等)时, Docker/Podman 安装和使用不是问题。 当网络环境不佳(例如在家里),要把 WSL2 的 Ubun…...
【WEEK16】Learning Objectives and Summaries【Spring Boot】【English Version】
Learning Objectives: Learning SpringBoot Learning Content: Reference video tutorials【狂神说Java】SpringBoot最新教程IDEA版通俗易懂Dubbo and Zookeeper Integration Learning time and outputs: Week16 TUE~FRI 2024.6.11【WEEK16】 【DAY2】Dubbo和Zookeeper集成第…...
AI大模型会让搜索引擎成为历史吗?
AI大模型会让搜索引擎成为历史吗? 随着人工智能技术的不断发展,AI大模型已经在许多领域展现出了强大的能力。从自然语言处理到图像识别,AI大模型的应用越来越广泛。在这种背景下,有人开始提出一个问题:AI大模型是否可…...
SpringSecurity6从入门到实战之SpringSecurity6自定义认证规则
SpringSecurity6从入门到实战之SpringSecurity6自定义认证规则 Spring Security 中默认所有的 http 请求都需要先认证通过后,才能访问。那么, 如何指定不需要认证就可以直接访问的资源呢?比如 用户的登录页面和注册页面,都是不需要…...
Java IO:byte[]、char[]、String三种对象的转换
String与byte[]对象进行转换时应指定编码格式,否则有潜在的乱码问题。byte[] b s.getBytes(“utf-8”); String s new String(b,“utf-8”); Java的IO库提供了专门的管道来对这3个对象进行读写,他们是StringReader/Writer CharArrayReader/Writer Byt…...
Elasticsearch:简化数据流的数据生命周期管理
作者:来自 Elastic Andrei Dan 今天,我们将探索 Elasticsearch 针对数据流的新数据管理系统:数据流生命周期,从版本 8.14 开始提供。凭借其简单而强大的执行模型,数据流生命周期可让n 你专注于数据生命周期的业务相关方…...
Verilog综合出来的图
Verilog写代码时需要清楚自己综合出来的是组合逻辑、锁存器还是寄存器。 甚至,有时写的代码有误,vivado不能识别出来,这时打开综合后的schematic简单查看一下是否综合出想要的结果。 比如:误将一个always模块重复一遍,…...
KT-H6测距模块标品,测距范围1500m,demo报价1000RMB,批量报价500RMB
激光测距传感器是一种用于测量距离的模块,通常由传感器和相关电子设备组成,测距模块可以集成到各种设备和系统中,以实现准确的测距和定位功能。KT-H6系列激光测距模块,为自主研发,激光波长905nm的激光器,专为热成像、夜视仪、无人机、安防、瞄具等产品定身打造,其优点是…...
C数据结构:排序
目录 冒泡排序 选择排序 堆排序 插入排序 希尔排序 快速排序 hoare版本 挖坑法 前后指针法 快速排序优化 三数取中法 小区间优化 快速排序非递归 栈版本 队列版本 归并排序 归并排序非递归 编辑 计数排序 各排序时间、空间、稳定汇总 冒泡排序 void Bub…...
【Python】在 Pandas 中使用 AdaBoost 进行分类
我们都找到天使了 说好了 心事不能偷藏着 什么都 一起做 幸福得 没话说 把坏脾气变成了好沟通 我们都找到天使了 约好了 负责对方的快乐 阳光下 的山坡 你素描 的以后 怎么抄袭我脑袋 想的 🎵 薛凯琪《找到天使了》 在数据科学和机器学习的工作…...
持续总结中!2024年面试必问 20 道并发编程面试题(九)
上一篇地址:持续总结中!2024年面试必问 20 道并发编程面试题(八)-CSDN博客 十七、请解释什么是Callable和FutureTask。 Callable和FutureTask是Java并发API中的重要组成部分,它们用于处理可能产生结果的异步任务。 …...
Linux:线程池
Linux:线程池 线程池概念封装线程基本结构构造函数相关接口线程类总代码 封装线程池基本结构构造与析构初始化启动与回收主线程放任务其他线程读取任务终止线程池测试线程池总代码 线程池概念 线程池是一种线程使用模式。线程过多会带来调度开销,进而影…...
集成学习方法:Bagging与Boosting的应用与优势
个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] 📱…...
长沙高端网站建设/公司网站seo外包
最近在尝试leetcode,今天做了一道简单题目,正好开通了博客,分享下自己.net 代码: 1 public int Reverse(int x)2 {3 var intQuery new Queue<int>();4 long temp 0;5 6 whil…...
淮安市哪里可以做网站/免费网站友情链接
部署prometheus监控服务器 安装监控服务器修改配置文件编写service文件,管理服务查看监控数据 所有主机系统均为CentOS7,提前配置IP、主机名、系统YUM源 安装监控软件(192.168.4.10主机操作) 安装软件 [rootprometheus ~]# tar …...
公司网络推广公司/百度seo文章
//头文件的东西,请根据自己的安装目录设置#include #include #include #include #include #include #include #include #include using namespace std;void close_app(GtkWidget *widget, gpointer data) {gtk_main_quit();}//使用gtk编译参数加上 pkg-config --cfl…...
ps做网站网页好吗/搜索关键词软件
建立脚手架成功之后就会看见这样的目录,bin是http模块的配置文件 app.js是服务器端的配置文件 public是你服务器的静态资源存放目录 routes 是的node.js路由存放目录 views是你得界面文件 是我是基于 ejs模块 所以里面的文件都是 ejs的后缀的文件 想修改监听端口 新浪…...
11电影网/北京自动seo
AOP是什么? AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程。AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现。 案例:在应用程序中…...
网站开发怎么谈/seo超级外链工具免费
爬取网站时经常会遇到需要登录的问题,这是就需要用到模拟登录的相关方法。python提供了强大的url库,想做到这个并不难。这里以登录学校教务系统为例,做一个简单的例子。 首先得明白cookie的作用,cookie是某些网站为了辨别用户身份…...