🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 

概述

selenium是网页应用中最流行的自动化测试工具,可以用来做自动化测试或者浏览器爬虫等。官网地址为:相对于另外一款web自动化测试工具QTP来说有如下优点:

  • 免费开源轻量级,不同语言只需要一个体积很小的依赖包
  • 支持多种系统,包括Windows,Mac,Linux
  • 支持多种浏览器,包括Chrome,FireFox,IE,safari,opera等
  • 支持多语言,包括Java,C,python,c#等主流语言
  • 支持分布式测试用例执行

python+selenium环境安装

首先需要安装python(推荐3.7+)环境,然后直接用pip install selenium安装依赖包即可。

另外还需要下载浏览器相应的webdriver驱动程序,注意下载的驱动版本一定要匹配浏览器版本。

  • Firefox浏览器驱动:
  • Chrome浏览器驱动:
  • IE浏览器驱动:
  • Edge浏览器驱动:
  • Opera浏览器驱动:

下载以后可以把驱动程序加到环境变量,这样使用时就不用手动指定驱动程序路径。

使用selenium启动浏览器

可以在python中使用下面的代码启动一个Chrome浏览器,然后控制这个浏览器的行为或者读取数据。

from selenium import webdriver# 启动Chrome浏览器,要求chromedriver驱动程序已经配置到环境变量
# 将驱动程序和当前脚本放在同一个文件夹也可以
driver = webdriver.Chrome()# 手动指定驱动程序路径
driver = webdriver.Chrome(r'D:/uusama/tools/chromedriver.exe')driver = webdriver.Ie()        # Internet Explorer浏览器
driver = webdriver.Edge()      # Edge浏览器
driver = webdriver.Opera()     # Opera浏览器
driver = webdriver.PhantomJS()   # PhantomJSdriver.get('http://uusama.com')  # 打开指定路径的页面

启动的时候还可以设置启动参数,比如下面的代码实现启动时添加代理,并且忽略https证书校验。

from selenium import webdriver# 创建chrome启动选项对象
options = webdriver.ChromeOptions()options.add_argument("--proxy-server=127.0.0.1:16666")  # 设置代理
options.add_argument("---ignore-certificate-errors")  # 设置忽略https证书校验
options.add_experimental_option("excludeSwitches", ["enable-logging"])  # 启用日志# 设置浏览器下载文件时保存的默认路径
prefs = {"download.default_directory": get_download_dir()}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)

启动的时候还可以设置启动参数,比如下面的代码实现启动时添加代理,并且忽略https证书校验。

from selenium import webdriver# 创建chrome启动选项对象
options = webdriver.ChromeOptions()options.add_argument("--proxy-server=127.0.0.1:16666")  # 设置代理
options.add_argument("---ignore-certificate-errors")  # 设置忽略https证书校验
options.add_experimental_option("excludeSwitches", ["enable-logging"])  # 启用日志# 设置浏览器下载文件时保存的默认路径
prefs = {"download.default_directory": get_download_dir()}
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)

一些非常有用的启动选项,下面使用的options = webdriver.ChromeOptions():

  • options.add_argument("--proxy-server=127.0.0.1:16666"): 设置代理,可以结合mitmproxy进行抓包等
  • option.add_experimental_option('excludeSwitches', ['enable-automation']): 设置绕过selenium检测
  • options.add_argument("---ignore-certificate-errors"): 设置忽略https证书校验
  • options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}): 设置不请求图片模式加快页面加载速度
  • chrome_options.add_argument('--headless'): 设置无头浏览器

selenium页面加载等待和检测

使用selenium打开页面以后,还不能立刻操作,需要等到待处理页面元素加载完成,这时就需要检测和等待页面元素加载。

使用time.sleep()等待

最简单的方法就是打开页面以后,使用time.sleep()强制等待一定时间,该方法只能设置一个固定时间等待,如果页面提前加载完成,则会空等阻塞。

from time import sleep
from selenium import webdriverdriver = webdriver.Chrome()
driver.get('http://uusama.con')
time.sleep(10)
print('load finish')

使用implicitly_wait设置最长等待时间

另外还可以使用implicitly_wait设置最长等待时间,如果在给定时间内页面加载完成或者已经超时,才会执行下一步。该方法会等到所有资源全部加载完成,也就是浏览器标签栏的loading图表不再转才会执行下一步。有可能页面元素已经加载完成,但是js或者图片等资源还未加载完成,此时还需要等待。

另需注意使用implicitly_wait只需设置一次,且对整个driver生命周期都起作用,凡是遇到页面正在加载都会阻塞。

示例如下:

from selenium import webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(30)   # 设置最长等30秒
driver.get('http://uusama.com')
print(driver.current_url)driver.get('http://baidu.com')
print(driver.current_url)

使用WebDriverWait设置等待条件

使用WebDriverWait(selenium.webdriver.support.wait.WebDriverWait)能够更加精确灵活地设置等待时间,WebDriverWait可在设定时间内每隔一段时间检测是否满足某个条件,如果满足条件则进行下一步操作,如果超过设置时间还不满足,则抛出TimeoutException异常,其方法声明如下:

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

其中各参数含义如下:

  • driver:浏览器驱动
  • timeout:最长超时时间,默认以秒为单位
  • poll_frequency:检测的间隔(步长)时间,默认为0.5秒
  • ignored_exceptions:忽略的异常,即使在调用until()或until_not()的过程中抛出给定异常也不中断

WebDriverWait()一般配合until()或until_not()方法使用,表示等待阻塞直到返回值为True或者False,需要注意这两个方法的参数都需是可调用对象,即方法名称,可以使用expected_conditions模块中的方法或者自己封装的方法。 

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditionsdriver = webdriver.Chrome()
driver.get("http://baidu.com")# 判断id为`input`的元素是否被加到了dom树里,并不代表该元素一定可见,如果定位到就返回WebElement
element = WebDriverWait(driver, 5, 0.5).until(expected_conditions.presence_of_element_located((By.ID, "s_btn_wr")))# implicitly_wait和WebDriverWait都设置时,取二者中最大的等待时间
driver.implicitly_wait(5)# 判断某个元素是否被添加到了dom里并且可见,可见代表元素可显示且宽和高都大于0
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID, 'su')))# 判断元素是否可见,如果可见就返回这个元素
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID, value='kw')))

下面列出expected_conditions常用的一些方法:

  • title_is: 判断当前页面title是否精确等于预期
  • title_contains: 判断当前页面title是否包含预期字符串
  • presence_of_element_located: 判断某个元素是否被加到了dom树里,并不代表该元素一定可见
  • visibility_of_element_located: 判断某个元素是否可见(元素非隐藏,并且元素的宽和高都不等于0)
  • visibility_of: 跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
  • presence_of_all_elements_located: 判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
  • text_to_be_present_in_element: 判断某个元素中的text是否包含了预期的字符串
  • text_to_be_present_in_element_value: 判断某个元素中的value属性是否包含了预期的字符串
  • frame_to_be_available_and_switch_to_it: 判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
  • invisibility_of_element_located: 判断某个元素中是否不存在于dom树或不可见
  • element_to_be_clickable: 判断某个元素中是否可见并且是enable的,这样的话才叫clickable
  • staleness_of: 等某个元素从dom树中移除,注意,这个方法也是返回True或False
  • element_to_be_selected: 判断某个元素是否被选中了,一般用在下拉列表
  • element_selection_state_to_be: 判断某个元素的选中状态是否符合预期
  • element_located_selection_state_to_be: 跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator

检测document是否加载完成

另外还可以使用driver.execute_script('return document.readyState;') == 'complete'来检测document是否加载完成。

注意document加载完成,是不包括那种异步加载ajax请求动态渲染dom的,这种需要使用WebDriverWait检测某个元素是否渲染完成。

selenium元素定位和读取

查找元素

selenium提供了一系列api方便获取chrome中的元素,这些API都返回WebElement对象或其列表,如:

  • find_element_by_id(id): 查找匹配id的第一个元素
  • find_element_by_class_name(): 查找匹配class的第一个元素
  • find_elements_by_xpath(): 查找匹配xpath的所有元素
  • find_elements_by_css_selector(): 查找匹配css选择器的所有元素

其实可以看WebDriver类里面的实现源码,其核心实现都是调用两个基本函数:

  • find_element(self, by=By.ID, value=None): 查找匹配策略的第一个元素
  • find_elements(self, by=By.ID, value=None): 查找匹配策略的所有元素

其中by参数可以是ID, CSS_SELECTOR, CLASS_NAME, XPATH等。下面举几个简单的例子:

  • 通过xpath查询包含文本登录的第一个元素: find_element_by_xpath("//*[contains(text(),'登录')]")
  • 查询包含类名refresh的所有元素: find_elements_by_class_name('refresh')
  • 查询table表格的第二行: find_element_by_css_selector('table tbody > tr:nth(2)')

dom元素交互

上面介绍的元素查找结果WebElement对象,常用的api有:

  •  element.text: 返回元素的文本内容(包括所有后代节点的内容),注意如果元素display=none则返回为空字符串
  • element.screenshot_as_png: 元素的截图
  • element.send_keys("input"): 元素输入框输入input字符串
  • element.get_attribute('data-v'): 获取data-v名称属性值,除了自定义节点属性,还可以获取如textContent等属性
  • element.is_displayed(): 判断元素是否用户可见
  • element.clear(): 清除元素文本
  • element.click(): 点击元素,如果元素不可点击会抛出ElementNotInteractableException异常
  • element.submit(): 模拟表单提交

查找元素失败处理

如果找不到指定元素,则会抛出NoSuchElementException异常,而且需要注意,display=none的元素是可以获取到的,凡是在dom节点中的元素都可以获取到。

而且实际使用的时候要注意一些js代码动态创建的元素,可能需要轮询获取或者监控。

一个检查是否存在指定元素的方法如下:

def check_element_exists(xpath):try:driver.find_element_by_xpath(xpath)except NoSuchElementException:return Falsereturn True

selenium交互控制

ActionChains动作链

webdriver通过ActionChains对象来模拟用户操作,该对象表示一个动作链路队列,所有操作会依次进入队列但不会立即执行,直到调用perform()方法时才会执行。其常用方法如下:

  • click(on_element=None): 单击鼠标左键
  • click_and_hold(on_element=None): 点击鼠标左键,不松开
  • context_click(on_element=None): 点击鼠标右键
  • double_click(on_element=None): 双击鼠标左键
  • send_keys(*keys_to_send): 发送某个键到当前焦点的元素
  • send_keys_to_element(element, *keys_to_send): 发送某个键到指定元素
  • key_down(value, element=None): 按下某个键盘上的键
  • key_up(value, element=None): 松开某个键
  • drag_and_drop(source, target): 拖拽到某个元素然后松开
  • drag_and_drop_by_offset(source, xoffset, yoffset): 拖拽到某个坐标然后松开
  • move_by_offset(xoffset, yoffset): 鼠标从当前位置移动到某个坐标
  • move_to_element(to_element): 鼠标移动到某个元素
  • move_to_element_with_offset(to_element, xoffset, yoffset): 移动到距某个元素(左上角坐标)多少距离的位置
  • perform(): 执行链中的所有动作
  • release(on_element=None): 在某个元素位置松开鼠标左键

模拟鼠标事件

下面代码模拟鼠标移动,点击,拖拽等操作,注意操作时需要等待一定时间,否则页面还来不及渲染。

from time import sleep
from selenium import webdriver
# 引入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChainsdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")
action_chains = ActionChains(driver)target = driver.find_element_by_link_text("搜索")
# 移动鼠标到指定元素然后点击
action_chains.move_to_element(target).click(target).perform()
time.sleep(2)# 也可以直接调用元素的点击方法
target.click()
time.sleep(2)# 鼠标移动到(10, 50)坐标处
action_chains.move_by_offset(10, 50).perform()
time.sleep(2)# 鼠标移动到距离元素target(10, 50)处
action_chains.move_to_element_with_offset(target, 10, 50).perform()
time.sleep(2)# 鼠标拖拽,将一个元素拖动到另一个元素
dragger = driver.find_element_by_id('dragger')
action.drag_and_drop(dragger, target).perform()
time.sleep(2)# 也可以使用点击 -> 移动来实现拖拽
action.click_and_hold(dragger).release(target).perform()
time.sleep(2)
action.click_and_hold(dragger).move_to_element(target).release().perform()

模拟键盘输入事件

通过send_keys模拟键盘事件,常用有:

  • send_keys(Keys.BACK_SPACE): 删除键(BackSpace)
  • send_keys(Keys.SPACE): 空格键(Space)
  • send_keys(Keys.TAB): 制表键(Tab)
  • send_keys(Keys.ESCAPE): 回退键(Esc)
  • send_keys(Keys.ENTER): 回车键(Enter)
  • send_keys(Keys.F1): 键盘 F1
  • send_keys(Keys.CONTROL,'a'): 全选(Ctrl+A)
  • send_keys(Keys.CONTROL,'c'): 复制(Ctrl+C)
  • send_keys(Keys.CONTROL,'x'): 剪切(Ctrl+X)
  • send_keys(Keys.CONTROL,'v'): 粘贴(Ctrl+V)

示例:定位到输入框,然后输入内容

# 输入框输入内容
driver.find_element_by_id("kw").send_keys("uusamaa")# 模拟回车删除多输入的一个字符a
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)

警告框处理

用于处理调用alert弹出的警告框。

  • driver.switch_to_alert(): 切换到警告框
  • text:返回alert/confirm/prompt中的文字信息,比如js调用alert('failed')则会获取failed字符串
  • accept():接受现有警告框
  • dismiss():关闭现有警告框
  • send_keys(keysToSend):将文本发送至警告框

selenium浏览器控制

基本常用api

下面列出一些非常实用的浏览器控制api:

  • driver.current_url: 获取当前活动窗口的url
  • driver.switch_to_window("windowName"): 移动到指定的标签窗口
  • driver.switch_to_frame("frameName"): 移动到指定名称的iframe
  • driver.switch_to_default_content(): 移动到默认文本内容区
  • driver.maximize_window(): 将浏览器最大化显示
  • driver.set_window_size(480, 800): 设置浏览器宽480、高800显示
  • driver.forword(), driver.back(): 浏览器前进和后退
  • driver.refresh(): 刷新页面
  • driver.close(): 关闭当前标签页
  • driver.quiit(): 关闭整个浏览器
  • driver.save_screenshot('screen.png'): 保存页面截图
  • driver.maximize_window(): 将浏览器最大化显示
  • browser.execute_script('return document.readyState;'): 执行js脚本

selenium读取和加载cookie

使用get_cookies和add_cookie可以实现将cookie缓存到本地,然后启动时加载,这样可以保留登录态。实现如下

import os
import json
from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")# 读取所有cookie并保存到文件
cookies = driver.get_cookies()
cookie_save_path = 'cookie.json'
with open(cookie_save_path, 'w', encoding='utf-8') as file_handle:json.dump(cookies, file_handle, ensure_ascii=False, indent=4)# 从文件读取cookie并加载到浏览器
with open(cookie_save_path, 'r', encoding='utf-8') as file_handle:cookies = json.load(file_handle)for cookie in cookies:driver.add_cookie(cookie)

selenium打开新的标签页窗口

使用driver.get(url)会默认在第一个标签窗口打开指定连接,点击页面中的_blank的链接时也会打开一个新的标签窗口。

还可以用下面的方式手动打开一个指定页面的标签窗口,需要注意打开新窗口或者关闭以后,还需要手动调用switch_to.window切换当前活动的标签窗口,否则会抛出NoSuchWindowException异常。

from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")new_tab_url = 'http://uusama.com'
driver.execute_script(f'window.open("{new_tab_url}", "_blank");')
time.sleep(1)# 注意:必须调用switch_to.window手动切换window,否则会找不到tab view
# 聚焦到新打开的tab页面,然后关闭
driver.switch_to.window(driver.window_handles[1])
time.sleep(2)
driver.close()   # 关闭当前窗口# 手动回到原来的tab页面
driver.switch_to.window(driver.window_handles[0])
time.sleep(1)

除了使用execute_script外,还可以使用模拟打开新tab页按键的方式新建一个标签页窗口:

  • driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')
  • ActionChains(driver).key_down(Keys.CONTROL).send_keys('t').key_up(Keys.CONTROL).perform()

selenium一些问题记录

获取隐藏元素的文本内容

 如果一个元素是隐藏的,即display=none,虽然可以通过find_element查找到该元素,但是用element.text属性是获取不到该元素文本内容的,其值是空字符串,这时可以用下面的方式获取:

element = driver.find_element_by_id('uusama')
driver.execute_script("return arguments[0].textContent", element)
driver.execute_script("return arguments[0].innerHTML", element)# 相应的也可以把隐藏的元素设置为非隐藏
driver.execute_script("arguments[0].style.display = 'block';", element)

浏览器崩溃WebDriverException异常处理

比如在Chrome中长时间运行一个页面会出现Out Of Memory内存不足的错误,此时WebDriver会抛出WebDriverException异常,基本所有api都会抛出这个异常,这个时候需要捕获并进行特殊处理。

我的处理方式是记录页面的一些基本信息,比如url,cookie等,并定期写入到文件中,如果检测到该异常,则重启浏览器并且加载url和cookie等数据。

selenium抓取页面请求数据

网上有通过driver.requests或者通过解析日志来获取页面请求的方式,但是我感觉都不是很好使。最后使用mitmproxy代理进行抓包处理,然后启动selenium时填入代理来实现。

proxy.py为在mitmproxy基础上封装的自定义代理请求处理,其代码如下:

import os
import gzip
from mitmproxy.options import Options
from mitmproxy.proxy.config import ProxyConfig
from mitmproxy.proxy.server import ProxyServer
from mitmproxy.tools.dump import DumpMaster
from mitmproxy.http import HTTPFlow
from mitmproxy.websocket import WebSocketFlowclass ProxyMaster(DumpMaster):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)def run(self, func=None):try:DumpMaster.run(self, func)except KeyboardInterrupt:self.shutdown()def process(url: str, request_body: str, response_content: str):# 抓包请求处理,可以在这儿转存和解析数据passclass Addon(object):def websocket_message(self, flow: WebSocketFlow):# 监听websockt请求passdef response(self, flow: HTTPFlow):# 避免一直保存flow流,导致内存占用飙升# flow.request.headers["Connection"] = "close"# 监听http请求响应,并获取请求体和响应内容url = flow.request.urlrequest_body = flow.requestresponse_content = flow.response# 如果返回值是压缩的内容需要进行解压缩if response_content.data.content.startswith(b'\x1f\x8b\x08'):response_content = gzip.decompress(response_content.data.content).decode('utf-8')Addon.EXECUTOR.submit(process, url, request_body, response_content)def run_proxy_server():options = Options(listen_host='0.0.0.0', listen_port=16666)config = ProxyConfig(options)master = ProxyMaster(options, with_termlog=False, with_dumper=False)master.server = ProxyServer(config)master.addons.add(Addon())master.run()if __name__ == '__main__':with open('proxy.pid', mode='w') as fin:fin.write(os.getpid().__str__())run_proxy_server()

在使用mitmproxy过程中,随着时间推移proxy.py会出现占用内存飙升的问题,在github的issue区有人也遇到过,有说是因为http连接keep-alive=true请求会一直保存不会释放,导致请求越多越占用内存,然后通过添加flow.request.headers["Connection"] = "close"来手动关闭连接,我加了以后有一定缓解,但还是不能从根本上解决。

最后通过写入proxy.pid记录代理程序进程,然后用另外一个程序定时重启proxy.py来解决内存泄漏的问题。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

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

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

相关文章

[机缘参悟-235]:通过AI人工升级网络的工作方式和特征理解人的思维方式

AI人工神经网络通过模拟生物神经元连接机制、构建层级化特征提取结构,并结合数据驱动的学习方式,为理解人类思维方式提供了技术参照框架,但其本质仍是基于统计的模式匹配,与人类意识层面的思维存在根本差异。以下从其工作方式、基…

【C#补全计划:类和对象(七)—— 重写虚方法】

一、virtual和override1. 问题引入:使用里氏替换原则时,使用父类容器装载子类对象,若不使用virtual和override而是使用new,当子类调用两个类共有的方法时,调用的是父类的方法而不是子类的方法:using System…

TCPIP之常用协议

一、TCPIP之网络支撑协议 1.ARP ARP是网络层协议,在同一广播域内,将IP地址解析成MAC地址. 1.1 无故ARP 请求型无故ARP 设备在网络中不管是自动获取ip地址还是手动配置ip地址,设备都会发送请求型无故ARP检查这个ip地址是否有重复的。 应…

网络之路24:VLAN基础实验

正文共:2345 字 18 图,预估阅读时间:3 分钟目录网络之路第一章:Windows系统中的网络0、序言1、Windows系统中的网络 1.1、桌面中的网卡 1.2、命令行中的网卡 1.3、路由表 1.4、家用路由器网络之路第二章:认识企业设备2…

基于Verilog的神经网络加速器设计

本设计实现了一个高效的神经网络加速器,专注于卷积神经网络(CNN)的核心计算功能。该设计具有以下创新点: 并行处理架构:同时处理多个卷积窗口,提高计算吞吐量 动态权重加载:支持运行时更新卷积核权重 流水线优化:卷积、激活、池化三级流水线设计 可配置参数:支持不同尺寸…

基于springboot的零食商城的设计与实现/零食销售系统的设计与实现

用户:注册,登录,商品信息,团购商品,公告资讯,后台管理,在线客服,购物车,个人中心管理员:登录,个人中心,用户管理,商品类型…

《剑指offer》-算法篇-位运算

题目二进制中“1”的个数代码实现二进制中“1”的个数题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。思路:求“1”的个数等价于求n-1与n进行“与”运算后不等于0所需要的运算次数。注意:这里的整数可能…

项目上线中的跨域问题

本文将深入解析跨域问题的本质,并提供实用的解决方案。引言 跨域问题可以说是前端开发者的"老朋友"了,特别是在项目从开发环境迁移到生产环境时,这个问题更是频繁出现。许多开发者对跨域的理解停留在表面,导致在项目上线…

dubbo应用之3.0新特性(响应式编程)(2)

一、介绍 Dubbo 3.0 的响应式编程基于 Triple 协议和 Reactor/RxJava 实现,支持全链路异步非阻塞通信。它通过引入 Mono、Flux 等响应式类型,打通跨进程的数据流式传输,天然支持反压、限流等控制能力。相比传统基于 CompletableFuture 的异步方式,响应式编程更适用于高并发…

力扣-22.括号生成

题目链接 22.括号生成 class Solution {List<String> res new ArrayList<>();StringBuilder path new StringBuilder();void backtracking(int n, int left, int right) {if (left right 2 * n) {res.add(path.toString());return;}if (left < n) {path.a…

架构实战——互联网架构模板(“网络层”技术)

目录 一、负载均衡 1.1、DNS 1.1.1、DNS 负载均衡的优点 1.1.2、DNS 负载均衡的缺点 1.2、Nginx 、LVS 、F5 1.2.1、软件和硬件的区别 1.2.2、4 层和 7 层的区别 二、CDN 三、多机房 3.1、同城多机房 3.2、跨城多机房 3.3、跨国多机房 四、多中心 本文来源:极客时间vip课程笔记…

TCP/IP 网络编程面试题及解答

在Qt/C面试中&#xff0c;若涉及“熟悉TCP/IP网络编程”&#xff0c;面试官通常会结合TCP/IP协议基础、Qt网络编程框架&#xff08;如Qt Network模块&#xff09;、C网络编程实现以及实际场景问题来提问。以下是常见面试题及解答&#xff1a; 一、TCP/IP协议基础 1. TCP和UDP的…

unity开发中Hash、Queue、LinkedList简单介绍

在Unity游戏开发中&#xff0c;除了Dictionary和List外&#xff0c;以下三种数据结构能高效解决特定问题场景&#xff1a;1. HashSet<T>&#xff1a;闪电级存在性检查 核心特点&#xff1a;基于哈希表实现的高效集合&#xff0c;元素唯一且无视顺序 优势&#xff1a; O(1…

智慧园区:科技与生活的完美融合

在城市的喧嚣中&#xff0c;我们常常渴望一片宁静而充满活力的绿洲。如今&#xff0c;随着科技的飞速发展&#xff0c;智慧园区应运而生&#xff0c;它不仅满足了我们对美好生活的向往&#xff0c;更以其独特的魅力&#xff0c;成为现代城市中一道亮丽的风景线。今天&#xff0…

继续打卡day6

383. 赎金信 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool canConstruct(string ransomNote, string magazine) {unordered_map<char, int> us;for(auto c: ransomNote){us[c]; // 将字符串存储}for(auto c: magazine){if(us.count(c)){us[c]-…

LIMA:大语言模型对齐的“少即是多”革命——原理、实验与范式重构

“千样本激活千亿参数&#xff1a;重新定义大模型对齐的本质” LIMA&#xff08;Less Is More for Alignment&#xff09; 是由 Meta AI 联合 卡内基梅隆大学 等机构于 2023年 提出的突破性大模型对齐框架&#xff0c;其核心颠覆了传统对齐需海量数据的认知&#xff0c;证明仅用…

vite.config.js常用配置

vite.config.js常用配置 import { defineConfig } from vite import { resolve } from "path"; import vue from vitejs/plugin-vueexport default defineConfig({plugins: [vue(), ], // 配置需要使用的插件列表base: ./, // 在生产中服务时的基本公共路径publicD…

JVM知识点(2)

目录 Java中可作为GC Roots的引用有哪几种&#xff1f; finalize方法 垃圾回收算法 标记-清除 标记-复制 标记-整理 分代收集算法 为什么要用分代收集 标记复制的标记过程和复制会不会停顿 MinorGC&#xff0c;MajorGC&#xff0c;MixedGC&#xff0c;FullGC FullGC…

Java HashMap中的compute及相关方法详解:从基础到Kafka Stream应用

HashMap是Java集合框架中最常用的数据结构之一&#xff0c;它提供了高效的键值对存储和检索功能。在Java8中&#xff0c;HashMap引入了一系列新的原子性更新方法&#xff0c;包括compute()、computeIfAbsent()和computeIfPresent()等&#xff0c;这些方法极大地简化了在Map中进…

【php中ssti模板注入讲解】

php中场景模板 1. Smarty 使用安全模式来执行不信任的模板,只运行PHP白名单里的函数。 2. Twig 与Smarty类似,不过无法利用该模板的SSTI调用静函数。 php常见模板入门 Smarty 不使用预先准备好的模板 使用预先准备好的模板 对值进行拼接后使用模板展示 设置在模板中…