浅测 长亭雷池 WAF “动态防护”

本文首发于 Anyeの小站

前言

雷池 WAF 社区版的更新速度是真快啊,几乎一周一个小版本,俩月一个大版本,攻城狮们真的狠啊,没法测了。

|25%xauto

废话不多说,前两天看到了 这篇文章,对雷池的“动态防护”功能挺感兴趣,特地来试试。

安装部署

本文以测评为主,不再阐述部署过程,介绍一下我这里的测试环境:

VM1:1Panel 部署 OpenResty,部署项目 Anyeの导航 ,IP(192.168.0.220)

VM2:部署雷池 WAF 社区版,添加站点,开启“动态防护”,IP(192.168.0.225)

测试

扒取页面

通常,我会采用这种方式来复刻一个主题,最常用的就是直接从浏览器开发人员工具中扒取出页面的 html,css,js 等文件,来重制主题。

开启了雷池动态防护的页面,会有一个解密的过程,其实也就是 js 执行的过程

|100%x100%

|100%x100%

HTML

这个过程极大的延长了页面的加载时间,大致是 3s 左右。

页面打开后,对于元素发现页面构建相同,代表页面并没有因为加密而产生变形

|100%x100%

|100%x100%

可见页面已加密,不过加密也导致 索引 页面严重增大🤣,看看后期有没有希望继续优化。

JS

加密了 js 文件尝试了一下,每次返回的js加密结果都不相同。

|100%x100%

很明显是进行了混淆,不过经过文本对比后发现了端倪。

这里贴出完整 js 代码

// 源js文件
/*! * Lazy Load - JavaScript plugin for lazy loading images * * Copyright (c) 2007-2017 Mika Tuupola * * Licensed under the MIT license: *   http://www.opensource.org/licenses/mit-license.php * * Project home: *   https://appelsiini.net/projects/lazyload * * Version: 2.0.0-beta.2 * */
(function(root, factory) {if (typeof exports === "object") {module.exports = factory(root);} else if (typeof define === "function" && define.amd) {define([], factory(root));} else {root.LazyLoad = factory(root);}
}
)(typeof global !== "undefined" ? global : this.window || this.global, function(root) {"use strict";const defaults = {src: "data-src",srcset: "data-srcset",selector: ".lazyload"};/** * Merge two or more objects. Returns a new object. * @private * @param {Boolean}  deep     If true, do a deep (or recursive) merge [optional] * @param {Object}   objects  The objects to merge together * @returns {Object}          Merged values of defaults and options */const extend = function() {let extended = {};let deep = false;let i = 0;let length = arguments.length;/* Check if a deep merge */if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {deep = arguments[0];i++;}/* Merge the object into the extended object */let merge = function(obj) {for (let prop in obj) {if (Object.prototype.hasOwnProperty.call(obj, prop)) {/* If deep merge and property is an object, merge properties */if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {extended[prop] = extend(true, extended[prop], obj[prop]);} else {extended[prop] = obj[prop];}}}};/* Loop through each object and conduct a merge */for (; i < length; i++) {let obj = arguments[i];merge(obj);}return extended;};function LazyLoad(images, options) {this.settings = extend(defaults, options || {});this.images = images || document.querySelectorAll(this.settings.selector);this.observer = null;this.init();}LazyLoad.prototype = {init: function() {/* Without observers load everything and bail out early. */if (!root.IntersectionObserver) {this.loadImages();return;}let self = this;let observerConfig = {root: null,rootMargin: "0px",threshold: [0]};this.observer = new IntersectionObserver(function(entries) {entries.forEach(function(entry) {if (entry.intersectionRatio > 0) {self.observer.unobserve(entry.target);self.loadImage(entry.target);}});},observerConfig);this.images.forEach(function(image) {self.observer.observe(image);});},loadAndDestroy: function() {if (!this.settings) {return;}this.loadImages();this.destroy();},loadImage: function(image) {image.onerror = function() {image.onerror = null;image.src = image.srcset = image.dataset.original;};let src = image.getAttribute(this.settings.src);let srcset = image.getAttribute(this.settings.srcset);if ("img" === image.tagName.toLowerCase()) {if (src) {image.dataset.original = image.src;image.src = src;}if (srcset) {image.srcset = srcset;}} else {image.style.backgroundImage = "url(" + src + ")";}},loadImages: function() {if (!this.settings) {return;}let self = this;this.images.forEach(function(image) {self.loadImage(image);});},destroy: function() {if (!this.settings) {return;}this.observer.disconnect();this.settings = null;}};root.lazyload = function(images, options) {return new LazyLoad(images,options);};if (root.jQuery) {const $ = root.jQuery;$.fn.lazyload = function(options) {options = options || {};options.attribute = options.attribute || "data-src";new LazyLoad($.makeArray(this),options);return this;};}return LazyLoad;
});
// 动态防护加密后的js文件
function vgo8rYXzpS() {var YIhUo91Nlh = 99.6174697329428;while (YIhUo91Nlh < 6) {YIhUo91Nlh++}var kJsBQ2iTCw = 77.7991427720637;while (kJsBQ2iTCw < 8) {kJsBQ2iTCw++}var Uv8SujYUUJ = 54.122410119766634;62.94717341414315 + 14.215159769026501;"eCDkWHqKcu";20.29250300507593 + 96.90578776550426;var hKDl2Z6IyR = 2.1154780179250436;while (hKDl2Z6IyR < 9) {hKDl2Z6IyR++}var jJJdYPyWC8 = 96.35369160356686;while (jJJdYPyWC8 < 10) {jJJdYPyWC8++}var q1lUq8lALI = 79.3826780702858;var KSm4kSmK5Q = 16.811363665066132;while (KSm4kSmK5Q < 5) {KSm4kSmK5Q++}while (q1lUq8lALI < 5) {q1lUq8lALI++}var k8jxtioSu1 = 46.12863667479478;if (k8jxtioSu1 < 50)VdgkMuAloP("dbKMKN3DiD");elseVdgkMuAloP("Z_GUlDIf7g");32.61116098968565 + 39.92340222133316;var WOIqRFoBWI = 35.570788142150256;while (WOIqRFoBWI < 10) {WOIqRFoBWI++}var REP52ajkkB = 68.57029249635578;while (REP52ajkkB < 9) {REP52ajkkB++}var UvGT8ugsmm = 77.45257249038768;var c_XLMPoMhw = 70.0508383263844;var oXNng_nyI3 = 61.714023740614785;"f3dzUmlSrt";while (oXNng_nyI3 < 8) {oXNng_nyI3++}"oiou9de1Yg";"jdpOma9ApF";var NeReO5OH2M = 63.89278655453103;while (NeReO5OH2M < 8) {NeReO5OH2M++}var _p_ydR_UZY = 83.88263735619535;var F85mcn2g_m = 17.165604886412726;while (F85mcn2g_m < 10) {F85mcn2g_m++}24.428701219017995 + 36.33105120927406;var E_btPRjrmk = 95.02151619364821;var No5m6438qj = 4.1049208686863246;while (No5m6438qj < 9) {No5m6438qj++}while (E_btPRjrmk < 6) {E_btPRjrmk++}var NW66eJHW18 = 80.32092123501981;if (NW66eJHW18 < 50)VdgkMuAloP("wVsjIS9XQo");elseVdgkMuAloP("GoLW5hTcVj");43.682142399473555 + 22.477837399452866;var UNuZiogsXq = 70.37483244640134;while (UNuZiogsXq < 6) {UNuZiogsXq++}var JyjoRvjvV4 = 60.33084553561216;"PPLO3pqrCR";function VdgkMuAloP() {"CCutBlYuiL";"MgmL5Sv_33";19.82880014765916 + 66.83450544153038;var eH8bW0LeRO = 91.84505170089825;var GGEb99P0LW = 92.75726773787632;"eM_DBnNLNQ";"LTExkL39fU";var ayFeMZ7J9o = 4.08422739984733;var rvzNYoM37B = 42.468405912837106;while (rvzNYoM37B < 6) {rvzNYoM37B++}"YLovxab17O";var dpUNCcw57i = 4.9146145098517575;while (dpUNCcw57i < 10) {dpUNCcw57i++}var ZjzssshCHy = 22.711581319339555;"lsyj2Pu6bi";"mAdio22F97";95.9152148251555 + 18.563789346616783;"Kisq7F_TOW";var EO9rGZSTTK = 53.3184198670574;while (EO9rGZSTTK < 6) {EO9rGZSTTK++}var Lfrg2SayBj = 96.40296951052316;var SR4gkdmFPm = 24.691037844119176;while (SR4gkdmFPm < 7) {SR4gkdmFPm++}"njAS_NShim";"DIoi_JwNCk";var qZALlgtAos = 65.84687374547939;while (qZALlgtAos < 5) {qZALlgtAos++}"i8UnwEQqP2";var mkzN8inJtT = 89.67717243925355;"EXgVlnAkaM";var HGgVbs9bD5 = 56.50704313244045;var myQFrz2kY4 = 54.55344568694437;while (myQFrz2kY4 < 8) {myQFrz2kY4++}var VcC388Sonl = 78.22901590625897;while (VcC388Sonl < 5) {VcC388Sonl++}var EDQM5T4i5x = 58.12080899105871;while (EDQM5T4i5x < 8) {EDQM5T4i5x++}var lS3HRC8N0e = 42.29800294748819;while (lS3HRC8N0e < 5) {lS3HRC8N0e++}}
}
(function(that, a) {var checkF = new RegExp("\\w *\\(\\){.+}");"Saz5menkPn";var checkR = new RegExp("(\\[x|u](\\w){2,4})+");var checkFunction = function checkFunction1() {if (checkR.test(checkFunction.toString())) {f2([2, 15, 12])};return '\x63\x68\x65\x63\x6b\x46\x75\x6e\x63\x74\x69\x6f\x6e'};var f1 = function f1(a) {a.push[a];f2(a)};var f2 = function f2(a) {a.push[a];f1(a)};if (!checkF.test(checkFunction.toString())) {f2([])} else if (checkR.test(checkFunction.toString())) {f2([1, 3, 7])};"ISXAG9bapu";var KOaO2Jk15j = 13.366279497772231;KOaO2Jk15j = 65.44109390187671;return a(that);function f5OTtZ1pUr() {"PFAZrkUkjJ";"yohosCBZku";"czcc_QG98P";var Y7ZMWHKbB5 = 54.61165307973092;while (Y7ZMWHKbB5 < 7) {Y7ZMWHKbB5++}"RAAE3i3HNJ";var yYJU5WMbNs = 81.78463513401672;var Dsj0YbE3nh = 60.12962678573978;while (Dsj0YbE3nh < 8) {Dsj0YbE3nh++}"OrNvH3Vm8U";var FcVeaK_8CJ = 70.65213865609662;var V10P1fXl1e = 93.28700416475893;while (V10P1fXl1e < 7) {V10P1fXl1e++}var _jQaUeEOlz = 50.09958863458343;while (_jQaUeEOlz < 6) {_jQaUeEOlz++}"mkyDT6LuXp";"i_d0Jej01W";93.1178573977863 + 65.0171586053574;"MdcdXdZD8e";var FvwOTr68cW = 63.96686898919228;while (FvwOTr68cW < 5) {FvwOTr68cW++}12.007514883700402 + 67.83201664204582;var lVk87OnDY0 = 10.352772574019035;while (lVk87OnDY0 < 10) {lVk87OnDY0++}"ZIxYt7RDz5";var HOjmKYxZYn = 73.07394273998264;var xf5LYnXM_h = 34.42670716048105;while (xf5LYnXM_h < 7) {xf5LYnXM_h++}25.31980979829108 + 70.92299314386324;53.64987099085665 + 15.95767193794893;81.04615728361688 + 53.03190420900158;"xMyhHs6tqa";var CicbLkYxKL = 71.43209809856342;while (CicbLkYxKL < 9) {CicbLkYxKL++}81.82768180662697 + 44.54696909044475;"a7S1hc6l6e";40.02457556515699 + 50.13884740950273}
}
)(this, function(that) {var EfanXdEsAo = 45.044183852209066;var YiD8rJkjM4 = 60.40560906974519;while (YiD8rJkjM4 < 9) {YiD8rJkjM4++}var SFXCSJnYT5 = 5.6590674829357;function DROWk3baLH() {var zJ2eGCAqG6 = 88.73517894514487;while (zJ2eGCAqG6 < 7) {zJ2eGCAqG6++}"fVZRgjskF7";var imVKfLWElR = 98.4392536479853;var JRZm9ZRXt9 = 65.52198475056669;"B07bldh2rt";94.61531928891331 + 21.79165407508193;"H7umcmyF_g";var kUwyNiUzjX = 48.5975080540464;while (kUwyNiUzjX < 5) {kUwyNiUzjX++}var G5q4i5ptYT = 17.20767169078439;while (G5q4i5ptYT < 9) {G5q4i5ptYT++}"S0RQAJX7ZD";var sbwEsBL3on = 31.621188048769;var Rbqnn2M5lo = 1.6814855430946412;var wXdYUzqLKS = 53.13735728383625;var iIMDA_Qowp = 87.59602310423611;55.899852486295956 + 23.463153124052145;49.64055650210554 + 21.699124979927305}
});
(function(root, factory) {if (typeof exports === "object") {module.exports = factory(root)} else if (typeof define === "function" && define.amd) {define([], factory(root))} else {root.LazyLoad = factory(root)}20.075305793669145 + 96.72088665263502;function mCbgSrID5z() {var ymZDdeQQne = 84.05118287547904;while (ymZDdeQQne < 8) {ymZDdeQQne++}"oeSlUltLf7";var vRcSMA7HZy = 95.63940228416716;while (vRcSMA7HZy < 5) {vRcSMA7HZy++}42.847416356461686 + 64.228599747433;var S4X325xZd0 = 36.8477478357082;var OjdsnE6IgU = 54.6819719737484;while (OjdsnE6IgU < 7) {OjdsnE6IgU++}var tsdIhKV6Tu = 21.849203694513204;"IBEZHnHB9P";var W1xUDNOclb = 97.45176245010938;var qBhKSMePxI = 53.918246237085604;while (qBhKSMePxI < 8) {qBhKSMePxI++}var tG5h3fCZpA = 8.9527278684316;1.8795339533222326 + 85.30147367116075;3.4838274267666733 + 52.70631782675951;var sglVSvKjZv = 13.453736652916252;while (sglVSvKjZv < 9) {sglVSvKjZv++}var bzJ8IfE03K = 72.4963090140686;var IzYpLOgN6D = 1.7126081902147487;86.90125410102027 + 60.096220564929666;55.32420449194843 + 93.21714769547813;15.44123941754805 + 88.74042551968007;"ayjAX7QOFR";"nsviM21tO7";"RGvq8LBnOO";2.5365166268296333 + 58.41895276641477;var NwT9TZgChj = 3.2736264569624316;"ZVRMQfyCrJ";"fwutOlKiEI";var Ejy2yBkKAt = 51.83509013431559;while (Ejy2yBkKAt < 7) {Ejy2yBkKAt++}92.07691206149254 + 13.437580090223227;"qdd7jYm20k";var j2KtWorODN = 42.14264503067741;2.478519996620122 + 58.627727544483704}
}
)(typeof global !== "undefined" ? global : this.window || this.global, function(root) {"use strict";var defaults = {src: "data-src",srcset: "data-srcset",selector: ".lazyload"};var extend = function extend1() {var extended = {};var deep = false;var i = 0;var length = arguments.length;if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {deep = arguments[0];i++}var merge = function merge(obj) {for (var prop in obj) {if (Object.prototype.hasOwnProperty.call(obj, prop)) {if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {extended[prop] = extend(true, extended[prop], obj[prop])} else {extended[prop] = obj[prop]}}}};for (; i < length; i++) {var obj = arguments[i];merge(obj)}return extended};function LazyLoad(images, options) {this.settings = extend(defaults, options || {});this.images = images || document.querySelectorAll(this.settings.selector);this.observer = null;this.init()}LazyLoad.prototype = {init: function init() {if (!root.IntersectionObserver) {this.loadImages();return}var self = this;var observerConfig = {root: null,rootMargin: "0px",threshold: [0]};this.observer = new IntersectionObserver(function(entries) {entries.forEach(function(entry) {if (entry.intersectionRatio > 0) {self.observer.unobserve(entry.target);self.loadImage(entry.target)}})},observerConfig);this.images.forEach(function(image) {self.observer.observe(image)})},loadAndDestroy: function loadAndDestroy() {if (!this.settings) {return}this.loadImages();this.destroy()},loadImage: function loadImage(image) {image.onerror = function() {image.onerror = null;image.src = image.srcset = image.dataset.original};var src = image.getAttribute(this.settings.src);var srcset = image.getAttribute(this.settings.srcset);if ("img" === image.tagName.toLowerCase()) {if (src) {image.dataset.original = image.src;image.src = src}if (srcset) {image.srcset = srcset}} else {image.style.backgroundImage = "url(" + src + ")"}},loadImages: function loadImages() {if (!this.settings) {return}var self = this;this.images.forEach(function(image) {self.loadImage(image)})},destroy: function destroy() {if (!this.settings) {return}this.observer.disconnect();this.settings = null}};root.lazyload = function(images, options) {return new LazyLoad(images,options)};if (root.jQuery) {var $ = root.jQuery;$.fn.lazyload = function(options) {options = options || {};options.attribute = options.attribute || "data-src";new LazyLoad($.makeArray(this),options);return this}}98.21293314139757 + 7.022202427695869;return LazyLoad;var zb5YrDEzX8 = 49.67145292566205;function EMQ2TiywJ2() {"kDDG4hcurX";"LmMQDl5Guf";"H1d2hSNdZu";"vR3uU0dztV";"BYg6Cwwew1";"Z7Cgb85The";var vqCn2LKHiQ = 79.8849526204871;while (vqCn2LKHiQ < 6) {vqCn2LKHiQ++}"HzKhtzFo0S";var Ruo3QF3HKv = 57.10873587557603;while (Ruo3QF3HKv < 8) {Ruo3QF3HKv++}var NIVPEUabT_ = 25.838978101412078;var pmvJIgXrA7 = 41.71629707156116;while (pmvJIgXrA7 < 7) {pmvJIgXrA7++}var cTqhNJmnqp = 7.679109504729966;var Xkldnu7eiS = 89.26080892492617;while (Xkldnu7eiS < 8) {Xkldnu7eiS++}var Iq6adjqOVj = 86.04734679658776;while (Iq6adjqOVj < 7) {Iq6adjqOVj++}var TyC7F0mXPj = 57.405394830228786;while (TyC7F0mXPj < 7) {TyC7F0mXPj++}var q7oS54FoCf = 19.715578974920984;6.354381716758419 + 48.514464467999424;var JPOOCo51Cg = 94.50513995137923;18.85838453981073 + 55.22787281970704;"rUww9Es4UQ"}
});

可见该加密方式采用了:

  • 变量名和函数名替换:将原有的变量名和函数名替换为难以理解的字符或字符串,例如vgo8rYXzpSYIhUo91Nlh等。
  • 字符串混淆:将代码中的字符串通过某些算法转换为难以阅读的形式。
  • 控制流改变:通过添加无意义的循环、条件判断等,改变代码的控制流,使得代码执行过程变得复杂。
  • 代码拆分:将代码拆分为多个部分,并通过某些机制动态地组合执行。

可见还是较为容易反混淆的,期待后期加强。

python 爬取

根据 官方文档 所述,动态防护还是为了可以更好地阻止爬虫和攻击自动化程序的分析,那么就尝试编写一段python代码来进行 HTML 内容爬取测试。

比如爬取 本站导航站,这里使用 Microsoft 的 playwright 库

import asyncio
from playwright.async_api import async_playwrightasync def scrape_data():async with async_playwright() as p:browser = await p.chromium.launch(headless=True)page = await browser.new_page()# 加载页面await page.goto('http://192.168.0.220')# 等待页面加载完成await page.wait_for_load_state('networkidle')# 提取链接、图标和描述items = await page.query_selector_all('.list-item.block')data = []for item in items:link = await item.query_selector('a.list-content')if link:href = await link.get_attribute('href')title = await link.query_selector('.list-title')desc = await link.query_selector('.list-desc')img = await item.query_selector('img')data.append({'link': href,'title': await title.inner_text() if title else None,'desc': await desc.inner_text() if desc else None,'icon': await img.get_attribute('src') if img else None,})await browser.close()return data# 运行
async def main():data = await scrape_data()for entry in data:print(entry)asyncio.run(main())

源站执行爬取后输出:

|100%x100%

雷池防护后:

|100%x100%

效果明显,不过,感觉还是有绕过的空间呀?试试浏览器有头模式?

import asyncio
from playwright.async_api import async_playwrightasync def scrape_data():async with async_playwright() as p:# 指定浏览器路径并启用有头模式browser = await p.chromium.launch(headless=False,  # 设置为 False 以显示浏览器窗口executable_path="C:\\Users\\Anye\\AppData\\Local\\Chromium\\Application\\chrome.exe")page = await browser.new_page()# 加载本地服务器上的页面await page.goto('http://192.168.0.225/')# 手动处理人机验证print("请手动处理页面上的人机验证...")await page.wait_for_selector('.list-item.block', timeout=0)  # 等待页面加载完成,没有超时限制# 提取链接、图标和描述items = await page.query_selector_all('.list-item.block')data = []for item in items:link = await item.query_selector('a.list-content')if link:href = await link.get_attribute('href')title = await link.query_selector('.list-title')desc = await link.query_selector('.list-desc')img = await item.query_selector('img')data.append({'link': href,'title': await title.inner_text() if title else None,'desc': await desc.inner_text() if desc else None,'icon': await img.get_attribute('src') if img else None,})await browser.close()return data# 运行
async def main():data = await scrape_data()for entry in data:print(entry)asyncio.run(main())

结果:成功获取内容

|100%x100%

既然这样,那岂不是等待解密后就可以获取内容了,那么等待5秒试试?

import asyncio
from playwright.async_api import async_playwrightasync def scrape_data():async with async_playwright() as p:browser = await p.chromium.launch(headless=True)page = await browser.new_page()# 加载页面await page.goto('http://192.168.0.225')# 等待页面加载完成await page.wait_for_load_state('networkidle')# 等待5秒await page.wait_for_timeout(5000)# 提取链接、图标和描述items = await page.query_selector_all('.list-item.block')data = []for item in items:link = await item.query_selector('a.list-content')if link:href = await link.get_attribute('href')title = await link.query_selector('.list-title')desc = await link.query_selector('.list-desc')img = await item.query_selector('img')data.append({'link': href,'title': await title.inner_text() if title else None,'desc': await desc.inner_text() if desc else None,'icon': await img.get_attribute('src') if img else None,})await browser.close()return data# 运行
async def main():data = await scrape_data()for entry in data:print(entry)asyncio.run(main())

|100%x100%

成功获取。

雷池开发别打我,HTML 确实不太好加密

不过目前来讲确实可以拦截大部分爬虫的爬取,正常爬虫不会长时间等待页面加载,也不会用有头模式。

测试++

经测试,开启 人机验证 后,是可以有效拦截爬虫获取内容。

|100%x100%

|100%x100%

不过还是希望雷池开发大大可以继续研究研究如何加强“动态防护”的算法😘。

后记

不让黑客,越雷池一步。

本次测试为内部测试环境,请勿用于黑客攻击行为。后期雷池也会加强加密算法,保护 WEB 安全。

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

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

相关文章

去掉el-table表头右侧类名是gutter,width=17px的空白区域(包括表头样式及表格奇偶行样式和表格自动滚动)

代码如下&#xff1a; <el-table:data"tableData"ref"scroll_Table":header-cell-style"getRowClass":cell-style"styleBack"height"350px"style"width: 100%"><el-table-column prop"id" l…

Scrum团队在迭代中如何处理计划外的工作

认为 Scrum 团队不做计划其实是一个误区&#xff0c;实际上很多 Scrum 团队在冲刺计划会议以及在细化工作项时均会进行详细规划。此外&#xff0c;他们还会创建一个路线图&#xff0c;以便显示他们在多个冲刺中的计划。 Scrum 团队需要经常进行计划&#xff0c;以便在不断变化…

混合动力电动汽车介绍(二)

接续前一章内容&#xff0c;本篇文章介绍混合动力汽车串联、并联和混联的系统组成和工作原理。 一、串联混合动力电动汽车的系统组成和工作原理 上图为串联混合动力电动汽车的结构简图。汽车由电动机-发电机驱动行驶&#xff0c;电机控制器的动力来自油箱-发动机-发电机-发电机…

基于Spring Boot框架的分页查询和文件上传

分页查询 分析 要想从数据库中进行分页查询&#xff0c;我们要使用LIMIT关键字&#xff0c;格式为&#xff1a;limit 开始索引 每页显示的条数 假设一页想展示10条数据 查询第1页数据的SQL语句是&#xff1a; select * from emp limit 0,10; 查询第2页数据的SQL语句是&…

6、架构-服务端缓存

为系统引入缓存之前&#xff0c;第一件事情是确认系统是否真的需要缓 存。从开发角度来说&#xff0c;引入缓存会提 高系统复杂度&#xff0c;因为你要考虑缓存的失效、更新、一致性等问题&#xff1b;从运维角度来说&#xff0c;缓存会掩盖一些缺 陷&#xff0c;让问题在更久的…

npm彻底清理缓存

在使用npm过程中&#xff0c;肯定会遇到清缓存的情况&#xff0c;网上的命令一般为 npm cache clear --force有时笔者在清理缓存之后npm install依然失败&#xff0c;仔细发现&#xff0c;执行该命令之后npm报了一个警告 npm WARN using --force Recommended protections dis…

代码随想录算法训练营第27天|● 39. 组合总和● 40.组合总和II● 131.分割回文串

组合总和 题目链接 39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; class Solution {public List<List<Integer>> res new ArrayList<>();public List<Integer> list new ArrayList<>();public int sum 0;/**…

LoadRunner 录制脚本时提示无Internet访问/加载慢,如何解决?

LoadRunner 录制脚本时提示无Internet访问/加载慢&#xff0c;如何解决&#xff1f; 在使用LoadRunner 12.02 进行录制脚本时提示无Internet访问&#xff0c;这是如下图&#xff1a; 翻译中文如下&#xff1a; 这里&#xff0c;我认为大家应该都已经点过yes了&#xff0c;但是…

python结构化模式匹配switch-case,Python 3.10中引入,Python的模式匹配(pattern matching)语法

增加了采用模式加上相应动作的 match 语句 和 case 语句 的形式的结构化模式匹配。 模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支&#xff0c;并基于不同的数据形式应用特定的动作。 语法与操作 模…

Linux下配置Pytorch

1.Anaconda 1.1虚拟环境创建 2.Nvidia驱动 3.CUDA驱动安装 4.Pytorch安装 具体的步骤如上&#xff1a;可参考另一位博主的博客非常详细&#xff1a; Linux服务器配置PythonPyTorchCUDA深度学习环境_linux cuda环境配置-CSDN博客https://blog.csdn.net/NSJim/article/detai…

极海APM32F072用Keil5烧录失败Error: Flash Download failed -“Cortex-MO+“

在用Keil5烧录时&#xff0c;出现错误弹窗&#xff0c;大概长这样&#xff1a; 检查了一圈设置&#xff0c;都搞不好。 先用J-Flash&#xff0c;显示读写保护&#xff08;未截图&#xff09;&#xff0c;会跳出界面让选择是否解除读写保护&#xff1a; 1.点击允许读操作YES&am…

DNF手游攻略:0氪攻略,转职技巧与避坑指南!

在DNF手游的冒险旅程中&#xff0c;角色的转职是一次重要的成长经历。通过转职&#xff0c;玩家可以获得全新的技能和属性&#xff0c;提升自己在地下城中的战斗力。本文将为您介绍转职后的关键技巧和日常任务&#xff0c;帮助您更好地适应新的职业身份&#xff0c;成为地下城中…

Python从0到100(二十九):requests模块处理cookie

1 爬虫中使用cookie 为了能够通过爬虫获取到登录后的页面&#xff0c;或者是解决通过cookie的反扒&#xff0c;需要使用request来处理cookie相关的请求 1.1 爬虫中使用cookie的利弊 带上cookie的好处 能够访问登录后的页面能够实现部分反反爬 带上cookie的坏处 一套cookie往往…

【设计模式】JAVA Design Patterns——Monitor(监视器模式)

&#x1f50d;目的 主要目的是为多个线程或进程提供一种结构化和受控的方式来安全地访问和操作共享资源&#xff0c;例如变量、数据结构或代码的关键部分&#xff0c;而不会导致冲突或竞争条件。 &#x1f50d;解释 通俗描述 监视器模式用于强制对数据进行单线程访问。 一次只允…

ROS2在RVIZ2中加载机器人urdf模型

参考ROS2-rviz2显示模型 我这边用的solid works生成的urdf以及meshes&#xff0c;比参考的方法多了meshes 问题一&#xff1a;Error retrieving file [package://rm_dcr_description/meshes/leftarm_link7.STL]: Package [rm_dcr_description] does not exist 这个是urdf模型中…

VisualStudio中:如果某个项目不显示SVN的show log等,而其他项目都正常

VisualStudio中&#xff1a;如果某个项目不显示SVN的show log等&#xff0c;而其他项目都正常。说明大概率是当前项目的问题&#xff0c;而不是VisualStudio的问题&#xff01; 1.这个项目内有一个“隐藏”文件夹.svn 》先删除&#xff01; 2.如果外层文件夹有红色感叹号&…

Csv--01--ExportUtil 写文件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 ExportUtil案例&#xff1a; ExportUtil.writeCsvFile ExportUtil import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists;import org.apache…

记录request中上传图片接口的测试过程

F12抓取的接口地址如下&#xff1a; 入参&#xff1a; 注意圈出来的部分参数 apifox调试接口 python相关代码&#xff1a; 接口调用相关文件&#xff1a; select_photo.py 输出结果&#xff1a; 相关接口的一些封装&#xff1a;

【一百零三】【算法分析与设计】并查集,并查集的实现,P3367 【模板】并查集

并查集的实现 描述 给定一个没有重复值的整形数组arr&#xff0c;初始时认为arr中每一个数各自都是一个单独的集合。请设计一种叫UnionFind的结构&#xff0c;并提供以下两个操作。 boolean isSameSet(int a, int b): 查询a和b这两个数是否属于一个集合 void union(int a, int …

K210视觉识别模块学习笔记2:固件的下载升级_官方数字识别例程导入方法

今日开始学习K210视觉识别模块:固件的下载升级_官方数字识别例程导入方法 主要学习如何升级固件库&#xff0c;在哪下载固件库&#xff0c;以及如何在TF卡正确导入官方例程&#xff1a; 亚博智能的K210视觉识别模块...... 固件库版本: canmv_yahboom_v2.1.1.bin 本次最终目…