【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用

7gr7ew.png

概述

前三期文章中已经介绍到了 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 应用;

7grmWB.png

特性

强大的自研内核

本库采用全自研的内核,内置了无数实用功能,对常用功能作了整合和优化,对比 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),回车
    如图所示,红框中就是要获取的路径:

7grpXt.png

  • 此法不限于 Windows,有界面的 Linux 也是这样取路径。
  • get()

该方法用于跳转到一个网址。当连接失败时,程序会进行重试:

7grlrP.png

获取查找元素

本库提供一套简洁易用的语法,用于快速定位元素,并且内置等待功能、支持链式查找,减少了代码的复杂性。

同时也兼容 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_modeNoneget()方法已内置等待加载完成,后面无须添加等待;
    • 📌 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 对象。titleurltab_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 为例,我们分别测试正常模式与无头模式下的检测结果:

  • 正常模式:
7gr0mb.png
  • 无头模式:

7gr3he.png

可以发现,我们没有做任何反检测的操作,都不会被检测到,就连使用无头模式也只有 userAgent 有问题,不过我们 co.set_user_agent() 设置一下就可以了,虽然这些只是最基本的检测机制,但也够用了。

总结

DrissionPage 语法简洁,使用方便,底层基于 CDP 协议,拥有较强的反检测机制,目前不需要做任何反检测的操作就可以绕过国内外绝大多数的网站自动化检测,包含但不限于 (xx 验证码、某数、5s)。 还有很多强大的功能这里没法一一展示,强烈推荐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/347497.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动求导实现与可视化

前言 micrograd为一个自动梯度引擎&#xff0c;其实现了反向传播算法&#xff0c;用于学习理解深度学习中的自动求导原理。自动求导无论再传统的机器学习中还是深度学习或是目前非常热门的大语言模型GPT中其都是非常重要基础部分。 反向传播算法可以高效计算出神经网络中损失…

Springboot多租户博客网站的设计-计算机毕业设计源码80600

摘 要 博客网站是当今网络的热点&#xff0c;博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体&#xff0c;Blog站点所形成的网状结构促成了不同于以往社区的Blog文化&#xff0c;Blog技术缔造了“博客”文化。本文课题研究的“多租户博客网站”&#xff0c;网…

微服务之网关

1、什么是微服务网关&#xff1f; 微服务网关是一种用于管理和调度微服务的工具或服务&#xff0c;它在微服务架构中扮演着关键角色。以下是关于微服务网关的清晰概述&#xff1a; 概念定义&#xff1a; 微服务网关是微服务架构中的前端门户&#xff0c;它提供了一个统一的入…

【Git】Git 的基本操作 -- 详解

一、创建 Git 本地仓库 要提前说的是&#xff0c;仓库是进行版本控制的一个文件目录。我们要想对文件进行版本控制&#xff0c;就必须先创建一个仓库出来。 创建⼀个 Git 本地仓库对应的命令为 git init &#xff0c;注意命令要在文件目录下执行&#xff0c;例如&#xff1a;…

【前端项目笔记】1 登录与登出功能实现

项目笔记 ☆☆代表面试常见题 前后端分离&#xff1a;后端负责写接口&#xff0c;前端负责调接口。 登录/退出功能 登录业务流程 登录页面&#xff1a;用户名密码 调用后台接口进行验证 通过验证&#xff0c;根据后台响应状态跳到项目主页 登录业务相关技术点&#xff1…

专业学习|博弈论-课程沿革

学习来源&#xff1a;北京大学刘霖《博弈论》MOOC公开课 备注&#xff1a;仅做学习分享&#xff0c;请勿转载&#xff0c;转载必究&#xff01; &#xff08;一&#xff09;博弈论的预备知识 基本的微积分的知识和概率论的知识。简单的说会求导数&#xff0c;会求简单的积分&am…

AI大模型的战场:通用与垂直的较量

AI大模型的战场&#xff1a;通用与垂直的较量 引言&#xff1a;AI界的“通才”与“专家” 在AI的大千世界里&#xff0c;有这样两类模型&#xff1a;一类是像瑞士军刀一样多功能的通用大模型&#xff0c;另一类则是像手术刀一样精准的垂直大模型。它们在AI战场上展开了一场激…

E: 仓库 “http://download...graphics:/darktable/xUbuntu_22.04 InRelease” 没有数字签名

问题 Ubuntu22.04装了darktable软件没装好&#xff0c;已经卸载了但是没卸载干净,终端使用 sudo apt update 出现的问题&#xff1a; 解决&#xff1a; sudo nano /etc/apt/sources.list.d/*darktable*.list找到了该软件的相关仓库条目&#xff1a;直接给他注释掉就行了。

使引用作为函数参数将变量i和j的值互换

C之所以增加引用机制&#xff0c;主要是把它作为函数参数&#xff0c;以扩充函数传递数据的功能。 解题思路&#xff1a; 传递变量的地址。形参是指针变量&#xff0c;实参是一个变量的地址&#xff0c;调用函数时&#xff0c;形参&#xff08;指针变量&#xff09;得到实参变…

WWDC24 快速回顾

今天凌晨&#xff0c;苹果公司在2024年全球开发者大会&#xff08;WWDC24&#xff09;上&#xff0c;发布了一系列的系统更新。然而&#xff0c;对于期待苹果带来突破性创新的消费者来说&#xff0c;今年的大会似乎并没有达到预期的震撼效果。 下面让我看看&#xff0c;苹果都带…

STM32定时器输出pwm的几种模式

目录 定时器 输出脉冲模式&#xff1a; PWM模式&#xff08;PWM Mode&#xff09; 输出比较模式&#xff08;Output Compare Mode&#xff09; 总结 占空比&#xff1a; 输出比较模式与占空比 PWM模式与占空比 输出比较模式与PWM模式的结合 输出比较模式实例&#xf…

汇凯金业:上海黄金交易所简介

上海黄金交易所(SGE)是中国唯一合法进行黄金交易的国家级市场&#xff0c;遵循公开、公平、公正和诚实信用的原则&#xff0c;在中国人民银行的领导下&#xff0c;于2002年10月30日正式开业。交易所不以盈利为目的&#xff0c;实行自律性管理。 组织形式及会员 交易所实行会员…

Java:双色球案例

文章目录 题目最终代码及运行结果过程中出现的问题判断选取的小球数字是否满足条件获奖多少没输出其他问题 学到的东西 题目 最终代码及运行结果 package com.zhang; /* 双色球案例: 投注号码由6个红球和1个蓝球号码组成。红色球号码从1——33中选择&#xff0c;蓝色球号码从1…

深度学习-注意力机制和分数

深度学习-注意力机制 注意力机制定义与起源原理与特点分类应用领域实现方式优点注意力机制的变体总结注意力分数定义计算方式注意力分数的作用注意力分数的设计总结 注意力机制&#xff08;Attention Mechanism&#xff09;是一个源自对人类视觉研究的概念&#xff0c;现已广泛…

jenkins 自动化任务构建案例

一新建Item 输入一个名称&#xff0c;点击Freestyle project 进入到配置项 选择 This project is parameterized&#xff0c;点击String Parameter 添加 变量值 command添加执行的命令 二构建 点击build构建触发器 三查看控制台 控制台输出信息无误

VB.NET实现上位机自动识别可用串口

在实际应用中有时会牵扯到挑选可用串口&#xff0c;比如上位机和从站设备使用Modbus RTU协议进行通讯时需要选择COM串口&#xff0c;每次启动连接前都在设备管理器查看较为麻烦&#xff0c;可以设置一个串口自动识别功能&#xff0c;如果选择了错误的串口还可以提示串口选择错误…

fdtd(时域有限差分)仿真

FDTD Solutions 是一款非常好用的微纳光学设计工具。该软件提供了丰富的设计功能&#xff0c;支持 CMOS 图像传感器&#xff0c;OLED 和液晶&#xff0c;表面计量&#xff0c;表面等离子体&#xff0c;石墨烯&#xff0c;太阳能电池&#xff0c;集成光子组件&#xff0c;超材 料…

2024年水利水电技术与能源环境国际会议(ICWRHTEE2024)

2024年水利水电技术与能源环境国际会议(ICWRHTEE2024) 会议简介 2024国际水利水电技术与能源环境大会&#xff08;ICWRHTEE 2024&#xff09;将在中国深圳举行。 我们主要专注于水利水电技术和能源环境研究领域&#xff0c;致力于为国内外不同大学、研究院所、企事业单位的专…

11_1、多态性:概念及运算符重载

多态性 多态的概念和类型多态的类型多态的实现 运算符重载运算符重载的概念和规则概念规则 运算符重载为类的成员函数双目运算符单目运算符 运算符重载为类的友元函数双目运算符重载单目运算符重载 多态的概念和类型 消息&#xff1a;消息在C编程中指的是对类的成员函数的调用…

[2024-06]-[大模型]-[Ollama]- WebUI

主要涉及要部署的前端webui是来源于:https://github.com/open-webui/open-webui 正常就使用: docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-web…