Python爬虫第17节-动态渲染页面抓取之Selenium使用下篇

目录

引言

一、获取节点信息

1.1 获取属性

1.2 获取文本值

1.3 获取ID、位置、标签名、大小

二、切换Frame

三、延时等待

3.1 隐式等待

3.2 显式等待

四、前进后退

五、Cookies

六、选项卡管理

七、异常处理


引言

        这一节我们继续讲解Selenium的使用下篇,在利用Selenium进行网页操作时,获取节点信息以及应对各种相关场景是关键环节。很多人起初习惯通过获取网页源代码,再用解析库提取信息,但其实Selenium自身就蕴含着诸多更便捷的方式。接下来,我们就深入了解下如何借助Selenium直接获取节点信息,以及处理Frame切换、等待、Cookies操作等一系列实用技巧。

一、获取节点信息

        前文提到,通过page_source属性可获取网页源代码,进而使用正则表达式、Beautiful Soup、pyquery等解析库提取信息。

        然而,既然Selenium已提供选择节点的方法,且返回的是WebElement类型,那么它必然也具备直接提取节点属性、文本等信息的方法和属性。如此一来,我们便无需通过解析源代码来获取信息,操作更加便捷。

        接下来,让我们看看如何获取节点信息。

1.1 获取属性

        如果想要获取网页中某个节点的属性值,我们可以运用`get_attribute()`方法来达成这一目的。不过需要注意的是,在使用这个方法之前,必须要先将目标节点选中才行。下面为你展示具体的示例: 

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChainsbrowser = webdriver.Chrome()
url = 'https://www.baidu.com/'
browser.get(url)# 旧版API
# logo = browser.find_element_by_id('zh-top-link-logo')
# 新版API
logo = browser.find_element(By.ID, 'lg')print(logo)
print(logo.get_attribute('class'))

当执行这段代码时,程序将自动启动浏览器并访问百度页面。随后,程序会在页面中定位到百度的logo节点,进而获取并打印出该节点的相关信息,以及它的`class`属性值。在控制台中呈现的输出结果如下:

        使用`get_attribute()`方法时,只要在调用该方法的过程中传入你期望获取的节点属性名称,就可以顺利地获取到该属性所对应的值。 

1.2 获取文本值

        对于每一个`WebElement`类型的节点而言,它们都具备`text`这一属性。在实际操作中,我们仅需直接调用该属性,就能够获取到这个节点内部所包含的文本信息。这种获取文本信息的方式,和`Beautiful Soup`库中的`get_text()`方法,以及`pyquery`库中的`text()`方法的作用类似。下面给出具体的示例来进行说明: 

from selenium import webdriver
from selenium.webdriver.common.by import By
import timebrowser = webdriver.Chrome()
url = 'https://www.zhihu.com/signin?next=%2F'
browser.get(url)# 等待页面加载
time.sleep(2)# 新版API
# 不能处理带空格,对于包含多个类名的元素,我们应该使用 CSS 选择器。
#button = browser.find_element(By.CLASS_NAME, '')# 新版API - 使用CSS选择器
button = browser.find_element(By.CSS_SELECTOR, '.Button.SignFlow-submitButton')print(button.text)

        这段代码的执行逻辑是这样的:首先,它会启动并打开知乎的页面。页面加载完毕后,代码会在页面中找到“登录注册”按钮对应的节点。在成功获取该节点之后,代码便会将这个节点的文本值打印输出。

控制台打印结果为:

登录/注册

1.3 获取ID、位置、标签名、大小

        除了前面提到的属性之外,`WebElement`节点还拥有一些其他非常实用的属性。就像`id`属性,通过它可以获取到节点对应的`id`标识;`location`属性则专门用来获取该节点在网页页面中所处的相对位置;`tag_name`属性能够让我们得知节点的标签名称;而`size`属性可以获取到节点的尺寸大小,也就是它的宽度和高度信息。下面通过具体的示例来展示这些属性的使用方法: 

from selenium import webdriver
from selenium.webdriver.common.by import By
import timebrowser = webdriver.Chrome()
url = 'https://www.zhihu.com/signin?next=%2F'
browser.get(url)# 等待页面加载
time.sleep(2)# 新版API
# 不能处理带空格,对于包含多个类名的元素,我们应该使用 CSS 选择器。
#button = browser.find_element(By.CLASS_NAME, '')# 新版API - 使用CSS选择器
button = browser.find_element(By.CSS_SELECTOR, '.Button.SignFlow-submitButton')print(button.text)
print(button.id)
print(button.location)
print(button.tag_name)
print(button.size)

输出结果:

        上述代码首先获取“登录注册”按钮这个节点,接着调用其`id`、`location`、`tag_name`、`size`属性来获取相应的属性值。通过这些属性,我们能更全面地了解节点在页面中的特征和位置信息,有助于更精准地进行页面元素的操作和分析 。

二、切换Frame

        在网页里,有一种节点叫做`iframe`,也就是子Frame。它就像是页面里嵌套的子页面,有着和外部网页一样的结构。当使用Selenium打开网页时,默认是在父级Frame的环境下进行操作的。要是页面中有子Frame,直接操作的话,是没办法获取到子Frame里面的节点的。要是想操作子Frame里的内容,就得用`switch_to.frame()`方法来切换Frame。下面是具体的示例: 

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementExceptionbrowser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)browser.switch_to.frame('iframeResult')
try:# 旧版API# logo = browser.find_element_by_class_name('logo')# 新版APIlogo = browser.find_element(By.CLASS_NAME, 'logo')
except NoSuchElementException:print('NO LOGO')
browser.switch_to.parent_frame()# 旧版API
# logo = browser.find_element_by_class_name('logo')
# 新版API
logo = browser.find_element(By.CLASS_NAME, 'logo')print(logo)
print(logo.text)

控制台输出:

        上述代码以之前演示动作链操作的网页作为示例。一开始,利用`switch_to.frame()`方法进入子Frame,接着尝试查找子Frame里的`logo`节点。但实际上,子Frame中并没有这个节点,这就会触发`NoSuchElementException`异常。捕获到这个异常后,程序会输出`NO LOGO`。之后,使用`switch_to.parent_frame()`方法返回父级Frame,再次去获取`logo`节点,这时就能够成功获取到该节点,并且打印出节点及其文本内容。 

        由此可知,当网页包含子Frame时,如果要获取子Frame内的节点,一定要先使用`switch_to.frame()`方法切换到相应的Frame,之后才能继续进行后续操作。不然,可能会因为找不到节点而致使操作失败。 

三、延时等待

        在Selenium里,`get()`方法会在网页框架加载结束时执行完毕。不过,这时获取的`page_source`,有可能不是浏览器完全加载好的页面内容。要是页面有额外的Ajax请求,仅靠网页源代码或许无法成功获取相关数据。所以,得设置延时等待,保证所需的节点都已经加载出来。

        延时等待的方式主要有两种,分别是隐式等待和显式等待。 

 

3.1 隐式等待

 

        当运用隐式等待开展测试工作时,要是Selenium在文档对象模型(DOM)里找不到指定的节点,它不会马上停止,而是会继续等待。要是超过了预先设定的时间,还是没找到节点,就会抛出节点未找到的异常。简单来讲,在查找节点时,如果这个节点没有立刻出现,隐式等待会让程序等待一段时间之后,再去查找DOM中的节点。需要注意的是,隐式等待的默认等待时间是0。下面是具体的示例: 

from selenium import webdriver
from selenium.webdriver.common.by import By
import timebrowser = webdriver.Chrome()
browser.implicitly_wait(10)
url = 'https://www.zhihu.com/signin?next=%2F'
browser.get(url)# 新版API
# 不能处理带空格,对于包含多个类名的元素,我们应该使用 CSS 选择器。
#button = browser.find_element(By.CLASS_NAME, '')# 新版API - 使用CSS选择器
button = browser.find_element(By.CSS_SELECTOR, '.Button.SignFlow-submitButton')print(button)

        在上述代码里,借助`implicitly_wait()`方法将隐式等待时间设定成了10秒。这意味着当Selenium查找节点却未能立即找到时,会持续等待10秒,若10秒内节点加载出来则继续执行后续操作,若超过10秒仍未找到节点,就会抛出节点未找到的异常。 

3.2 显式等待

        隐式等待在实际应用中效果并非总能尽如人意,这是因为它所设置的等待时间是固定的。然而,页面的加载时间会受到网络状况、服务器响应等多种因素的影响,固定的等待时间难以适配各种复杂情况。 

        相比之下,显式等待就要灵活得多。它允许我们明确指定要查找的节点,同时设定最长的等待时间。在规定的时间范围内,如果节点成功加载完成,程序就会返回该节点;但要是超过了设定时间,节点依旧没有加载出来,程序便会抛出超时异常。下面通过一个示例来具体说明: 

 

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()
browser.get('https://www.taobao.com/')# 等待页面加载
wait = WebDriverWait(browser, 10)# 定位搜索输入框
# 使用ID定位更准确
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))# 定位搜索按钮
# 使用更精确的CSS选择器
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button.btn-search.tb-bg')))print("搜索框:", input)
print("搜索按钮:", button)
print("搜索框类型:", input.get_attribute('type'))
print("搜索按钮文本:", button.text)

 

        在这段代码里,首先引入了`WebDriverWait`对象,并且把最长等待时间设定成了10秒。接着调用`until()`方法,同时传入等待条件`expected_conditions`。就拿`presence_of_element_located`这个条件来说,它代表节点已经完成加载,其参数是节点的定位元组,这里指的是ID为`q`的搜索框节点。也就是说,在10秒的时间内,要是ID为`q`的节点成功加载出来,程序就会返回这个节点;要是超过10秒还没加载好,就会抛出异常。

 

        对于按钮节点,等待条件被设置为`element_to_be_clickable`(节点可点击),也就是去查找CSS选择器为`.btn - search`的按钮。若在10秒内这个按钮变得可以点击(意味着已经成功加载),程序就会返回该按钮节点;若超过10秒按钮还是不可点击(即未加载完成),同样会抛出异常。

        当网络状况良好时,运行这段代码能够成功加载并输出这两个节点。具体的控制台输出如下:

控制台输出如下:

搜索框: <selenium.webdriver.remote.webelement.WebElement (session="958f257d68f99e09f2e00835aa7eea4d", element="f.EF316286D5F2BC448BCF689697FBF6B0.d.ECC671338A30A18D014C352C3583444B.e.2")>
搜索按钮: <selenium.webdriver.remote.webelement.WebElement (session="958f257d68f99e09f2e00835aa7eea4d", element="f.EF316286D5F2BC448BCF689697FBF6B0.d.ECC671338A30A18D014C352C3583444B.e.12")>
搜索框类型: text
搜索按钮文本: 搜索

        一旦网络状态不好,在那预先设定的10秒时间内,节点无法顺利完成加载,这种情况下程序就会抛出`TimeoutException`异常。

         此外,等待条件的类型其实是多种多样的,除了前面提到的那些,还可以用来判断网页的标题内容,或者查看某个节点内部是不是包含特定的文字信息等等。所有的等待条件以及它们对应的含义,都详细地罗列在了下表当中。 

等待条件及其含义

        若你想了解更多关于等待条件参数的详细信息以及它们的具体用法,可查阅官方文档,链接为:(http://selenium - python.readthedocs.io/api.html#module - selenium.webdriver.support.expected_conditions)。在该文档中你能获取更全面和深入的讲解。 

四、前进后退

        在日常使用浏览器的过程中,前进和后退功能是我们经常会用到的。而Selenium也提供了对这些操作的支持。在Selenium里,通过调用`back()`方法就能实现浏览器页面的后退操作,使用`forward()`方法则可以实现页面的前进操作。下面为你展示具体的示例代码:

import time
from selenium import webdriverbrowser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(1)
browser.forward()
browser.close()

        在上述代码里,程序首先会依次访问百度、淘宝以及Python官网这三个网页。接着调用`back()`方法,此时浏览器会向后退回到淘宝页面。在等待1秒钟之后,再调用`forward()`方法,浏览器便会前进到Python官网页面,最后关闭浏览器。借助这样的操作方式,我们能够在Selenium所驱动的浏览器中模拟用户在浏览网页时前进和后退的操作。 

五、Cookies

        借助Selenium,我们可以非常方便地对Cookies进行各类操作,像获取Cookies信息、添加新的Cookies以及删除指定的Cookies等。下面是具体的示例代码,它将展示如何使用Selenium来完成这些操作:

from selenium import webdriverbrowser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

        在代码执行时,第一步是访问知乎页面。当页面加载完毕后,浏览器会自动生成Cookies。此时调用`get_cookies()`方法,就能获取到页面所有的Cookies信息并打印输出。

        随后,使用`add_cookie()`方法来添加一个新的Cookie,该方法需要传入一个字典,字典里要包含`name`(名称)、`domain`(域)和`value`(值)等必要信息。再次调用`get_cookies()`方法时,输出结果中会显示新增了刚刚添加的那个Cookie。

        最后,执行`delete_all_cookies()`方法,这个操作会把所有的Cookies都删除。当再次获取Cookies时,得到的结果就会为空。

        下面是控制台可能出现的输出情况:

        没错,利用上述提到的`get_cookies()`、`add_cookie()`和`delete_all_cookies()`等方法,可轻松对浏览器里的Cookies进行管理和操作。无论是在测试环境中模拟用户登录状态,还是在数据采集时处理特定的用户标识信息,这些操作都能灵活满足不同场景下的数据处理需求,提升自动化测试与数据处理的效率和准确性。

六、选项卡管理

        在日常浏览网页过程中,我们经常会同时打开多个选项卡来提高浏览效率。在Selenium里,也具备对选项卡进行操作的能力。下面是一个示例,为你展示如何在Selenium中操作选项卡: 

import time
from selenium import webdriverbrowser = webdriver.Chrome()
browser.get('https://www.baidu.com')# 打开新窗口
browser.execute_script('window.open()')
print(browser.window_handles)# 切换到新窗口
# 旧版API
# browser.switch_to_window(browser.window_handles[1])
# 新版API
browser.switch_to.window(browser.window_handles[1])
browser.get('https://www.taobao.com')
time.sleep(1)# 切换回第一个窗口
# 旧版API
# browser.switch_to_window(browser.window_handles[0])
# 新版API
browser.switch_to.window(browser.window_handles[0])
browser.get('https://python.org')

控制台输出如下:

        在上述代码中,整体操作模拟了用户在浏览器中对多个选项卡进行管理的场景。具体而言,一开始打开百度页面,之后借助`execute_script()`方法执行`window.open()`这条JavaScript语句,从而新开一个选项卡。`window_handles`属性发挥了重要作用,调用它可以获取当前所有已打开选项卡的信息,它会返回一个包含各选项卡代号的列表。

        要想实现选项卡之间的切换,新版switch_to.window方法就派上用场了,只需把目标选项卡的代号作为参数传入即可。在示例里,先将第二个选项卡的代号传入该方法,成功切换到第二个选项卡后,在这个选项卡中打开了淘宝页面。等待1秒之后,又把第一个选项卡的代号传入switch_to.window 方法,从而切换回第一个选项卡,并在该选项卡中打开了Python官网页面。

        通过这样的操作方式,能够在Selenium中灵活地对多个选项卡进行管理,完美模拟了用户在实际浏览网页时于不同页面间进行切换的操作。

七、异常处理

        在运用Selenium开展自动化测试或者网页操作时,各种异常情况难以避免,像超时异常、节点未找到异常等错误都可能出现。一旦碰到这类错误,程序往往会停止运行。为了防止程序因为异常而中断,我们可以借助`try - except`语句来捕获并处理各种异常。 

        下面先通过一个节点未找到的异常示例,来看看如何运用`try - except`语句进行异常处理: 

from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Chrome()
browser.get('https://www.baidu.com')# 旧版API
# browser.find_element_by_id('hello')
# 新版API
browser.find_element(By.ID, 'hello')

        上述代码在打开百度页面之后,试图去查找一个ID为`hello`的节点,然而这个节点实际上并不存在于页面中,所以会触发异常。当代码运行起来,控制台就会输出相应的错误信息,下面是具体的输出情况: 

        从输出情况能够看出,代码抛出了`NoSuchElementException`异常,一般而言,这意味着在页面中没有找到指定的节点。为了避免程序因为这样的异常而中断运行,我们可以采用`try - except`语句来捕获并处理异常。下面是具体的示例代码:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementExceptionbrowser = webdriver.Chrome()
try:browser.get('https://www.baidu.com')
except TimeoutException:print('Time Out')
try:browser.find_element(By.ID, 'hello')
except NoSuchElementException:print('No Element')
finally:browser.close()

        在这段代码里,`try - except`语句发挥了重要作用,它能够捕获不同操作时可能出现的异常。针对`get()`方法,代码捕获`TimeoutException`异常,一旦出现超时情况,就会输出`Time Out`。而对于`find_element_by_id()`方法,捕获的是`NoSuchElementException`异常,要是没有找到指定的节点,便会输出`No Element`。 

        另外,代码里的`finally`块保证了无论是否有异常发生,浏览器最终都会被关闭。下面是控制台可能出现的输出内容: 

No Element

        要是还想了解更多Selenium里的异常类,能去参考官方文档,链接是:(http://selenium - python.readthedocs.io/api.html#module - selenium.common.exceptions) 。 

        上面把Selenium的各项功能都介绍了一遍,到这儿,咱们对它的常用操作方法也都清楚了。有了Selenium,处理JavaScript动态渲染的页面就简单多了。在网页数据抓取、自动化测试这些工作中,Selenium可是个既强大又好用的工具。不管是做简单的页面操作,还是获取复杂的动态数据,Selenium都能派上大用场,让我们高效完成任务。往后,大家可以根据自己实际的需求,进一步去研究和使用Selenium的更多高级功能,来解决不同场景下网页数据处理和测试的问题 。 

 

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

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

相关文章

容器docker入门学习

这里写目录标题 容器容器的软件厂商 dockerdocker引擎 虚拟化虚拟化技术 docker安装详解1、安装检查2、安装yum相关的工具3、安装docker-ce软件4、查看docker版本5、启动docker服务6、设置docker开机启动7、查看有哪些docker容器运行进程8、查看容器里有哪些镜像9、下载nginx软…

文献总结:NIPS2023——车路协同自动驾驶感知中的时间对齐(FFNet)

FFNet 一、文献基本信息二、背景介绍三、相关研究1. 以自车为中心的3D目标检测2. 车路协同3D目标检测3. 特征流 四、FFNet网络架构1. 车路协同3D目标检测任务定义2. 特征流网络2.1 特征流生成2.2 压缩、传输与解压缩2.3 车辆传感器数据与基础设施特征流融合 3. 特征流网络训练流…

git 出现 port 443 Connection timed out

梯子正常延迟不算严重&#xff0c;但在使用git push时反复出现 fatal: unable to access https://github.com/irvingwu5/xxxx.git/ Error in the HTTP2 framing layer Failed to connect to github.com port 443 after 136353 ms: Connection timed out 将git的网络配置与梯子…

【2025年4月18日】android studiio最新设置沉浸式状态栏教程

&#x1f62b;【2025年4月18日】搞了一整天&#xff0c;终于完美搞定 Android 沉浸式状态栏&#xff08;WebView 本地HTML&#xff09; 最近在做一个个人项目&#xff0c;用 Android 加载本地 HTML 做个小工具。按理说用 WebView 加载页面很简单嘛——结果沉浸式状态栏这个坑…

如何删除 Launchpad 中 Chrome 的图标

有一天突然在 Launchpad 中出现下面的图标&#xff0c;在 Finder 的 Applications 中也没有&#xff0c;不知道如何删除。最终在《How to remove chrome app icons from launchpad?》中找到了答案。中文互联网上并没有搜到相关帖子&#xff0c;遂作记录。 解决办法很简单&am…

PHP8.2.9NTS版本使用composer报错,扩展找不到的问题处理

使用composer install时报错&#xff1a; The openssl extension is required for SSL/TLS protection but is not available. If you can not enable the openssl extension, you can disable this error, at y our own risk, by setting the ‘disable-tls’ option to true.…

一本通 2063:【例1.4】牛吃牧草 1005:地球人口承载力估计

Topic&#xff1a; Ideas&#xff1a; 为什么把这两道题放在一起呢&#xff1f;就是因为这两道题很类似&#xff0c;都是很简单的数学题&#xff0c;只要你会列出数学等式&#xff0c;你就学会这道题了&#xff01; 下面把计算过程展示给大家 Code&#xff1a; //2025/04/18…

基于用户的协同过滤推荐系统实战项目

文章目录 基于用户的协同过滤推荐系统实战项目1. 推荐系统基础理论1.1 协同过滤概述1.2 基于用户的协同过滤原理1.3 相似度计算方法1.3.1 余弦相似度(Cosine Similarity)1.3.2 皮尔逊相关系数(Pearson Correlation)1.3.3 欧几里得距离(Euclidean Distance)1.3.4 调整余弦相似度…

【SpringBoot】基于Filter实现SQL注入过滤器

最近扫出了一个SQL注入安全漏洞&#xff0c;用户的非法输入可能导致数据泄露、数据篡改甚至系统崩溃&#xff0c;为了有效防范 SQL 注入攻击&#xff0c;除了在代码层面使用参数化查询和预编译语句外&#xff0c;还可以通过实现一个Filter来过滤掉潜在的危险输入。本文将介绍如…

Spring Boot 项目里设置默认国区时区,Jave中Date时区配置

在 Spring Boot 项目里设置国区时区&#xff08;也就是中国标准时间&#xff0c;即 Asia/Shanghai&#xff09;&#xff0c;可通过以下几种方式实现&#xff1a; 方式一&#xff1a;在application.properties或application.yml里设置 application.properties properties sp…

Python环境中在线训练机器学习模型所遇到的问题及解决方案

我最近开发个智能控制系统,包括实时数据采集、预测、策略优化等功能,最近增加在线学习功能,也就是在线进行模型训练,在线进行模型训练时出现了问题,现象为: 控制台报: cmdstanpy - INFO - Chain [1] start processing所有任务、线程停止,Web服务登录无法访问后台的pyt…

【教程】无视硬件限制强制升级Windows 11

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 1、下载升级工具&#xff1a;https://github.com/builtbybel/Flyby11/releases 2、解压后打开软件&#xff1a; 3、拖入win11.iso或者自动下载&#xf…

麦科信汽车诊断示波器在机车维修领域中的应用实例

麦科信汽车诊断示波器在机车维修领域中的应用实例 “Micsig SATO1004的错误帧统计功能与历史波形存储&#xff0c;让我们在诊断间歇性CAN故障时有了决定性武器。这不仅是工具升级&#xff0c;更是维修理念的革新。” — Ian Coffey, Mototek技术总监&#xff08;欧洲ECU诊…

【IDEA2020】 解决开发时遇到的一些问题

目录 一、批量更新数据库数据 逐条更新 Db.updateEntitiesBatch() 二、Error running&#xff0c;Command line is too long. Shorten command line 报错场景 报错分析 解决方法 一、批量更新数据库数据 逐条更新 List<UserModel> ums userMapper.selectListBy…

算法01-最小生成树prim算法

最小生成树prim算法 题源&#xff1a;代码随想录卡哥的题 链接&#xff1a;https://kamacoder.com/problempage.php?pid1053 时间&#xff1a;2025-04-18 难度&#xff1a;4⭐ 题目&#xff1a; 1. 题目描述&#xff1a; 在世界的某个区域&#xff0c;有一些分散的神秘岛屿&…

cpolar 内网穿透 实现公网可以访问本机

1、登录网站&#xff0c;升级成专业版&#xff0c;测试的话建议选一个月付费&#xff0c;选择预留 2、保留的TCP地址增加一条记录&#xff0c;描述可以自己取 3、验证&#xff0c;生成一个Authtocken码 4、在安装目录下&#xff0c;打开CMD命令&#xff0c;复制上面的码运行aut…

c#内存泄露的原因和解决办法

内存泄漏的原因 不正确的对象引用&#xff1a;最常见的原因是对象不再需要时未被垃圾回收器回收。例如&#xff0c;如果一个对象被一个不再使用的变量引用&#xff0c;它将不会被垃圾回收。事件订阅者未取消&#xff1a;如果订阅了一个事件但没有在对象不再需要时取消订阅&…

TDengine Restful 接口API

简介 为支持各种不同类型平台的开发&#xff0c;TDengine 提供符合 RESTful 设计标准的 API&#xff0c;即 REST API。为最大程度降低学习成本&#xff0c;不同于其他数据库 REST API 的设计方法&#xff0c;TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数…

【Contiki】Contiki process概述

00. 目录 文章目录 00. 目录01. 进程类型02. 进程结构03. 事件04. 进程调度函数05. 程序实例06. process实现07. 附录 01. 进程类型 进程类型主要有**协同式&#xff08;cooperative&#xff09;和抢占式&#xff08;preemptive&#xff09;**两种。 协同式进程&#xff0c;要…

哪种电脑更稳定?Mac?Windows?还是云电脑? 实测解密

随着科技的发展进步&#xff0c;电脑已成为当下各类群体的必备产品之一&#xff0c;它的妙用有很多&#xff0c;无论是学生党、打工人还是已经退休的人群或都离不开它的存在。然而&#xff0c;电脑虽好却也差异很大、不同品牌、不同系统、不同配置、不同价位的统统都会有区别。…