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

news2025/5/15 2:27:20

目录

引言

一、获取节点信息

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 ActionChains

browser = 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 time

browser = 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 time

browser = 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 NoSuchElementException

browser = 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')
    # 新版API
    logo = 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 time

browser = 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 EC

browser = 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 webdriver

browser = 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 webdriver

browser = 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 webdriver

browser = 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 By

browser = 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, NoSuchElementException

browser = 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.coloradmin.cn/o/2338213.html

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

相关文章

HarmonyOS 第2章 Ability的开发,鸿蒙HarmonyOS 应用开发入门

第2章 Ability的开发 本章内容 本章介绍HarmonyOS的核心组件Ability的开发。 2.1 Ability概述 2.2 FA模型介绍 2.3 Stage模型介绍 2.4 Ability内页面的跳转和数据传递 2.5 Want概述 2.6 实战:显式Want启动Ability 2.7 实战:隐式Want打开应用管理 2.8 小结 2.9 习题 2.1 Abili…

day2-小白学习JAVA---java第一个程序

java第一个程序 1、新建一个文件&#xff0c;以.java为结尾2、用编辑器打开后写入代码&#xff08;本人写前端&#xff0c;所以用vscode&#xff0c;也可用其他&#xff09;3、编译文件4、运行文件5、HelloWorld代码解释6、文档注释 1、新建一个文件&#xff0c;以.java为结尾 …

Rockchip 新一代 64 位处理器 RK3562--九鼎开发板

RK3562 是 Rockchip 新一代 64 位处理器 RK3562&#xff08;Quad-core ARM Cortex-A53&#xff0c;主频 最高 2.0GHz&#xff09;&#xff0c;最大支持 8GB 内存&#xff1b;内置独立的 NPU&#xff0c;可用于轻量级人工智能应用&#xff0c;RK3562 拥有 PCIE2.1/USB3.0 OTG/…

z-library电子图书馆最新地址的查询方法

对于喜欢读书的伙伴们&#xff0c;应该都听说过z站&#xff08;z-library&#xff09;&#xff0c;优点多多&#xff0c;缺点就是地址不稳定&#xff0c;经常会变化网站地址。然后我最近发现了一个工具&#xff0c;可以不间断更新官方可用的z站地址&#xff1a;电子书最新地址

Spring Boot 3 + SpringDoc:打造接口文档

1、背景公司 新项目使用SpringBoot3.0以上构建&#xff0c;其中需要对外输出接口文档。接口文档一方面给到前端调试&#xff0c;另一方面给到测试使用。 2、SpringDoc 是什么&#xff1f; SpringDoc 是一个基于 Spring Boot 项目的库&#xff0c;能够自动根据项目中的配置、…

Json 在线格式化 - 加菲工具

Json 在线格式化 打开网站 加菲工具 选择“Json 在线格式化” 或者直接进入 https://www.orcc.top/tools/json 输入Json&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果

HarmonyOS-ArkUI V2装饰器: @Monitor装饰器:状态变量修改监听

Monitor作用 Monitor的作用就是来监听状态变量的值变化的。被Monitor修饰的函数,会在其对应监听的变量发生值的变化时,回调此函数,从而可以让您知道是什么值发生变化了,变化前是什么值,变化后是什么值。 V1版本的装饰器,有个叫@Watch的装饰器,其实也有监听变化的能力,…

微信小程序文字混合、填充动画有效果图

效果图 .wxml <view class"text" style"--deg:{{deg}}deg;"><view>混合父级颜色</view> </view> <view class"fill {{status?action:}}">文字颜色填充</view> <button bind:tap"setStatus"…

【计算机网络 | 第一篇】计算机网络基础知识

网络分层模型 1.OSI七层模型国际标准化组织提出的一个网络分层模型&#xff0c;总共有七层&#xff0c;其大体功能以及每一层分工如下所示&#xff1a; 每一层都专注做一件事&#xff0c;并且每一层都需要下一层提供的功能。 OSI七层模型七层结构体系清晰&#xff0c;理论完整…

再读bert(Bidirectional Encoder Representations from Transformers)

再读 BERT&#xff0c;仿佛在数字丛林中邂逅一位古老而智慧的先知。初次相见时&#xff0c;惊叹于它以 Transformer 架构为罗盘&#xff0c;在预训练与微调的星河中精准导航&#xff0c;打破 NLP 领域长久以来的迷雾。而如今&#xff0c;书页间跃动的不再仅是 Attention 机制精…

uCOS3实时操作系统(系统架构和中断管理)

文章目录 系统架构中断管理ARM中断寄存器相关知识ucos中断机制 系统架构 ucos主要包含三个部分的源码&#xff1a; 1、OS核心源码及其配置文件&#xff08;ucos源码&#xff09; 2、LIB库文件源码及其配置文件&#xff08;库文件&#xff0c;比如字符处理、内存管理&#xff0…

图像预处理-图像噪点消除

一.基本介绍 噪声&#xff1a;指图像中的一些干扰因素&#xff0c;也可以理解为有那么一些点的像素值与周围的像素值格格不入。常见的噪声类型包括高斯噪声和椒盐噪声。 滤波器&#xff1a;也可以叫做卷积核 - 低通滤波器是模糊&#xff0c;高通滤波器是锐化 - 低通滤波器就…

6.数据手册解读—运算放大器(二)

目录 6、细节描述 6.1预览 6.2功能框图 6.3 特征描述 6.3.1输入保护 6.3.1 EMI抑制 6.3.3 温度保护 6.3.4 容性负载和稳定性 6.3.5 共模电压范围 6.3.6反相保护 6.3.7 电气过载 6.3.8 过载恢复 6.3.9 典型规格与分布 6.3.9 散热焊盘的封装 6.3.11 Shutdown 6.4…

用 Deepseek 写的uniapp油耗计算器

下面是一个基于 Uniapp 的油耗计算器实现&#xff0c;包含 Vue 组件和页面代码。 1. 创建页面文件 在 pages 目录下创建 fuel-calculator 页面&#xff1a; <!-- pages/fuel-calculator/fuel-calculator.vue --> <template><view class"container"…

thinkphp实现图像验证码

示例 服务类 app\common\lib\captcha <?php namespace app\common\lib\captcha;use think\facade\Cache; use think\facade\Config; use Exception;class Captcha {private $im null; // 验证码图片实例private $color null; // 验证码字体颜色// 默认配置protected $co…

【k8s系列4】工具介绍

1、虚拟机软件 vmware workstation 2、shell 软件 MobaXterm 3、centos7.9 下载地址 &#xff08;https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.374bf5adOaiFPW&#xff09; 4、上网软件

Spark-SQL核心编程2

路径问题 相对路径与绝对路径&#xff1a;建议使用绝对路径&#xff0c;避免复制粘贴导致的错误&#xff0c;必要时将斜杠改为双反斜杠。 数据处理与展示 SQL 风格语法&#xff1a;创建临时视图并使用 SQL 风格语法查询数据。 DSL 风格语法&#xff1a;使用 DSL 风格语法查询…

STM32单片机入门学习——第41节: [12-1] Unix时间戳

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.18 STM32开发板学习——第41节: [12-1] Unix时间戳 前言开发板说明引用解答和科普一…

无人机自主导航与路径规划技术要点!

一、自主导航与路径规划技术要点 1. 传感器融合 GPS/北斗定位&#xff1a;提供全局定位&#xff0c;但在室内或遮挡环境下易失效。 惯性测量单元&#xff08;IMU&#xff09;**&#xff1a;通过加速度计和陀螺仪实时追踪姿态&#xff0c;弥补GPS信号丢失时的定位空缺。 …

AI绘画SD中,如何保持生成人物角色脸部一致?Stable Diffusion精准控制AI人像一致性两种实用方法教程!

在AI绘画StableDiffusion中&#xff0c;一直都有一个比较困难的问题&#xff0c;就是如何保证每次出图都是同一个人。今天就这个问题分享一些个人实践&#xff0c;大家和我一起来看看吧。 一. 有哪些实现方式 方式1&#xff1a;固定Seed种子值。 固定Seed种子值出来的图片人…