爬虫瑞数5案例:某通信

news2024/11/13 9:30:09

声明:
该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关

一、瑞数简介

瑞数动态安全 Botgate(机器人防火墙)以“动态安全”技术为核心,通过动态封装、动态验证、动态混淆、动态令牌等技术对服务器网页底层代码持续动态变换,增加服务器行为的“不可预测性”,实现了从用户端到服务器端的全方位“主动防护”,为各类 Web、HTML5 提供强大的安全保护。

二、瑞数特点
  1. 会有多层debugger,可以点击Never pause here过掉debugger
  2. 会有多次请求
  • 瑞数4、瑞数5有两次相同的请求,瑞数4第一个请求状态码202,瑞数5第一个请求状态412,第一次请求响应的html,会有个script标签外链js加载 t s = w i n d o w [ ′ _ts = window[' ts=window[_ts’],外链js代码可以固定,也可以通过对外链js发送请求获取js代码
  • 瑞数5.5有两次相同的请求,第一次请求状态码412,响应的html有外链js,此外链js代码可以固定,也可以通过对外链js发送请求获取js代码
  • 瑞数6和瑞数5.5编译过程差不多
  1. 第一次响应的html,都会包含动态加载的meta标签包含content、两个script标签,
  • 瑞数4、瑞数5用第一个script加载包含_ts = window[‘$_ts’]的js文件,第二个script加载一段自执行的js,用于把之前加载的代码处理成可用的js代码,处理后的js字符串,通过call执行,并生成cookie
  • 瑞数5.5用第一个script加载包含_ts = window[‘$_ts’]代码,第二个script加载自执行js文件,用于把之前加载的代码处理成可用的js代码,处理后的js字符串,通过call执行,并生成cookie
  1. 都会有特有的cookie标识
  • 瑞数4:FSSBBIl1UgzbN7N80T,生成值的第一个字符就是代数
  • 瑞数5:IdlEqTWW2ERnT,生成值的第一个字符就是代数
  • 瑞数5.5:1EzPGwRUoQaWT,生成值的第一个字符就是代数
  1. 瑞数会检测当前执行的文件是哪一个,可以使用delete __filename、delete __dirname
三、瑞数5特点
  1. 两层debugger,可以点击Never pause here过掉debugger
  2. 同一个请求两次
  3. 第一次请求失败,状态码是412
  • 首先会生成一个js文件: t s = w i n d o w [ ′ _ts = window[' ts=window[_ts’],代码可以固定
  • 然后响应返回一个html页面,里面会有动态加载的meta标签包含content、一个script标签加载刚才js文件、一段script标签包含的js代码
  • 这段js代码是个自执行方法,会把之前的js代码,转换成可用的js代码,并通过call方法执行eval函数生成vm文件,在vm文件生成cookie,赋值给document.cookie
  • 响应的cookie名字是:IdlEqTWW2ERnS
  1. 第一次请求js代码生成的 cookie的名字是:IdlEqTWW2ERnT,生成值的第一个字符就是代数
  2. 第二次请求,会正确拿到数据
四、找出需要加密的参数
  1. js运行atob(‘aHR0cHM6Ly93d3cuMTAwMTAuY29tL25ldDUvMDc0Lw==’) 拿到网址,F12打开调试工具(打开F12会遇到无限debugger,这是个eval执行的debugger,右击左侧代码行点击Never pause here过掉即可),刷新页面,找到 net5/074/ 请求(状态200),鼠标右击请求找到Copy>Copy as cUrl(cmd)
    在这里插入图片描述
  2. 打开网站:https://spidertools.cn/#/curl2Request,把拷贝好的curl转成python代码,新建 liantong.py,把代码复制到该文件
    在这里插入图片描述
  3. 多运行几次liantong.py,会发现请求失败,状态码是412,仔细分析cookie会发现IdlEqTWW2ERnS、IdlEqTWW2ERnT,而IdlEqTWW2ERnT值得第一个字符是5,这是瑞数特点之一,字符5代表是瑞数5代
    在这里插入图片描述
  4. 新建liantong.js,用于放扣下的代码
五、瑞数5 cookie 分析
  1. 使用hook定位IdlEqTWW2ERnT,参数生成位置,这里我使用的是油猴
    在这里插入图片描述
  2. 编辑好油猴脚本,启动该脚本,切换到Application,清除浏览器的cookie,一定要清除cookie
    在这里插入图片描述在这里插入图片描述
  3. 清除cookie后,刷新页面后会进入油猴脚本里的debugger,一直点击跳过当前函数执行,就会找到IdlEqTWW2ERnT赋值的地方
    在这里插入图片描述
  4. 分析IdlEqTWW2ERnT赋值的地方,会发现是在_KaTeX parse error: Expected group after '_' at position 9: MK函数中,搜索_̲MK会找到调用该函数地方,点击跳过断点,会进入该断点。注意这是个虚拟文件,每次生成的都不一样,需结合当前代码分析
    在这里插入图片描述
  5. 分析右侧的堆栈,找到不属于该虚拟文件的栈,分别点击查看会发现一个call方法,该方法就是生成虚拟文件的地方,这个文件是第一次请求的响应结果
    在这里插入图片描述
  6. 使用无痕窗口打开网站,F12打开调试工具,点击sources,找到事件监听勾选script
    在这里插入图片描述
  7. 切换到Application,清除浏览器的cookie,一定要先清除cookie,清除cookie后,刷新页面,会看到一个js文件,这是第一次请求生成的,把这个文件代码全部拷贝到liantong.js
    在这里插入图片描述
  8. 点击跳过断点,会进入一个html文件,这是第一次请求响应结果,分析文件会发现一个meta标签、一个script标签引入了刚才生成的js、还有一个script标签里面有很多代码,代码用于把之前的js转换成可用的js代码
    在这里插入图片描述
  9. 在该文件搜索.call,会找到一个.call方法执行,在该行打上断点
    在这里插入图片描述
  10. 点击跳过断点,鼠标悬浮到_$PU上会发现很多js字符串,这就是经过该自执行方法转换后的js
    在这里插入图片描述
  11. 这里要注意虚拟文件是动态生成的,每次获取到的都是不一样的,为了方便调试,把html文件替换成本地文件,这样每次生成的虚拟文件就是一样的,右击该html文件名称,点击Override content,如果替换成功后代码都在一行,可以在本地找到该文件,用编辑器打开,格式化一下,并在call的位置打上断点
    在这里插入图片描述在这里插入图片描述
  12. 把script中的自执行方法全部拷贝到liantong.js,运行liantong.js,会发现报window的错误,window是浏览器环境的,node环境不存在,接下来开始补环境
    在这里插入图片描述
六、补环境
  1. 首选在代码顶部补上window环境,并用代理自动把需要补的环境吐出来,新建jsProxy.js把下面代码拷贝过去
// 代理器封装
function getEnv(proxy_array) {
    for(var i=0; i<proxy_array.length; i++){
        handler = `{\n
            get: function(target, property, receiver) {\n
                   console.log('方法:get','    对象:${proxy_array[i]}','    属性:',property,'    属性类型:',typeof property,'    属性值类型:',typeof target[property]);
                   return target[property];
            },
            set: function(target, property, value, receiver){\n
                    console.log('方法:set','    对象:${proxy_array[i]}','    属性:',property,'    属性类型:',typeof property,'    属性值类型:',typeof target[property]);
                    return Reflect.set(...arguments);
            }
        }`;
        eval(`
            try{\n
                ${proxy_array[i]};\n
                ${proxy_array[i]} = new Proxy(${proxy_array[i]},${handler});
            }catch(e){\n
                ${proxy_array[i]}={};\n
                ${proxy_array[i]} = new Proxy(${proxy_array[i]},${handler});
            }   
        `)
    }
}

// proxy_array = ['window', 'document', 'location', 'navigator', 'history','screen','target' ]
// getEnv(proxy_array)

module.exports = getEnv

在这里插入图片描述

  1. 运行liantong.js,会发现在获取window.top时报错了,在控制台输出window.top得知 window.top = window,在代码顶部补上window.top
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
  2. 运行liantong.js,会发现在获取document.createElement时报错了,document.createElement是用来创建标签的,在代码顶部补上document.createElement,之所以return出一个json,是因为标签也是一个对象
    在这里插入图片描述在这里插入图片描述
  3. 运行liantong.js,会发现在获取document.createElement时又报错了,创建的标签是div,补上div,并找到打印信息最后的位置,会看到报错代码
    在这里插入图片描述在这里插入图片描述
  4. 在浏览器call断点处,点击进入该方法内部会找到虚拟文件,在虚拟文件内搜索KaTeX parse error: Expected group after '_' at position 4: xX[_̲rB[157]],会找到该方法的位置,在该行打上断点,点击跳过断点,会进入刚才的断点,把代码信息在控制输出,会发现是获取div下的i标签,获取出的结果是 length:0,在代码顶部补上该代码
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  5. 运行liantong.js,会发现在获取window.attachEvent时报错了,找到打印信息最后的位置,会看到报错代码,在虚拟文件内搜索KaTeX parse error: Expected group after '_' at position 4: 5g[_̲rB[195]],会找到该方法的位置,在该代码处有个判断,在if和else中都打上断点,点击跳过断点,if断点,把代码信息在控制输出,会发现是window.addEventListener,获取出的结果是 undefined,在代码顶部补上该代码
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  6. 运行liantong.js,会发现在获取document.getElementsByTagName时报错了,找到打印信息最后的位置,会看到报错代码,在虚拟文件内搜索KaTeX parse error: Expected group after '_' at position 4: 5f[_̲rB[157]],会找到多个该方法的位置,在所有的KaTeX parse error: Expected group after '_' at position 4: 5f[_̲rB[157]]打上断点,点击跳过断点,会进入某一个断点,打印出信息,会发现是两个meta对象和length,在代码顶部补上代码
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  7. 两个meta标签需要补什么代码,就要分析下面的逻辑了,点击跳过当前函数执行,分析代码,会发现需要最后一个标签上的content,需要最后一个标签parentNode.removeChild 移除标签,最后会把content返回,根据分析补上代码
    在这里插入图片描述在这里插入图片描述
  8. 重复运行liantong.js,按照上面的方法补全环境
  9. 补完环境,修改liantong.js,再运行,会发现已经拿到IdlEqTWW2ERnT
    在这里插入图片描述
七、python代码验证结果
  1. 修改liantong.js,因为meta中的content、还有js代码都是动态生成的,所以要用字符暂时占位,分别注释掉之前content的值和js,用meta_content、js_code代替
    在这里插入图片描述在这里插入图片描述
  2. 修改fdc.py
    在这里插入图片描述在这里插入图片描述
  3. 点击运行fdc.py,会发现第二个请求报400,那是因为瑞数会检测当前执行的文件是哪一个
    在这里插入图片描述
  4. 修改liantong.js,再运行fdc.py,会发现数据获取成功
    在这里插入图片描述在这里插入图片描述
八、最终代码

1.liantong.js,代码太多只贴补环境的那块儿

delete __dirname
delete __filename


var getEnv = require('./jsProxy')

//补window环境
window = global
window.top = window
window.addEventListener = function (event) {
    console.log('window中的addEventListener接受的值:', event)
}

//补document
div = {
    getElementsByTagName: function (res) {
        console.log('div中的getElementsByTagName接受的值:', res)
        if (res == 'i') {
            return {length: 0}
        }
    }
}

meta = {
    0: {},
    1: {
        // content: '{qqiWR9xjADLqtZr.GKDUqs39vLCd6fuDojxTsXPqq|[MOVUqGS9kDwYAY2MHmG8qqenYagvFTYnqaVRkcNykUE2QpL1UOm3DmV.UaxMHf24DULSwPQ.o1WoFaQ0osgoFcNzHGWFl1x7iueMEnWPYsGUinpbxrEUmkAWiA36crg6r1VwErNIEG9BVaVFkaqEkf9kra7lrS9tYs3eEPaaxSeIEA9HkkfRiYYWHS7gkPZdkrEPtnQwYs3.eahnr50RXqCjtH09dcbnU7yq4AOBU4TRXVkvoMVtL1OLxi7NNT4YAHqEZm5GKFxqZfCPrWTwLGBbkWL54mK.oiLLSmOEEieM2f_8iwg4amB1DX0kaTVQrgEnzs8CJMW67uDuJ.35XOKaH.0ac80{AVhRPOD1oF7LTncUsEzy56uo8iJ7aOK.T3d7d7kbbH.qS7sbNHjwPZbUgFjASBsb.WM9dBo_PH_LpL1cfl4096k162hsQioxBGHtAihVlwBPeCtEe8.qfQg.wHVg9MepzcbGPT1sAl.orvE_e5EwA2MzQ9Wbt9r1r0r4q!x7z,aac,amr,asm,avi,bak,bat,bmp,bin,c,cab,css,csv,com,cpp,dat,dll,doc,dot,docx,exe,eot,fla,flc,fon,fot,font,gdb,gif,gz,gho,hlp,hpp,htc,ico,ini,inf,ins,iso,js,jar,jpg,jpeg,json,java,lib,log,mid,mp4,mpa,m4a,mp3,mpg,mkv,mod,mov,mim,mpp,msi,mpeg,obj,ocx,ogg,olb,ole,otf,py,pyc,pas,pgm,ppm,pps,ppt,pdf,pptx,png,pic,pli,psd,qif,qtx,ra,rm,ram,rmvb,reg,res,rtf,rar,so,sbl,sfx,swa,swf,svg,sys,tar,taz,tif,tiff,torrent,txt,ttf,vsd,vss,vsw,vxd,woff,woff2,wmv,wma,wav,wps,xbm,xpm,xls,xlsx,xsl,xml,z,zip,apk,plist,ipaqqqqqqqqqqqqqqkRxA1WYW8i2ZaYc0IH9V_UAlwSf3|gYBRPSpKnWLGmzpn1RFgTvfn.WMN2nKrBqVWPwqrME6aBAcYAxK7XifNgJ9qoIDrOhYVmscevR1Qa3rJyk2QrpCg4rYlO8OZfH6qvFCY8H209hArJH6q1VnpSrlaPkAxixrTXpaEYh2ZXAfJ4JoABM1TUmKV0p1w6lTaAFbYgEArBRbVr393oFOmsRvqi8DwDEYpOFkzaRuL9ECQFHfAFhcyeEqLuhcQr3al2qpe5oO7YraggcozOmq06MaQaWcW5HOqD3aEPhnL4hrVNECWVlGqJ3C0IMkzUomlrq 0wR7HvJ6IsUC410DntKRngA;QyqA82EGtIB6ePNEeYo9NG;iEm6gdSTTpYiqU10OlvsnG;yMG8gk5okQ97gP4eb.IadA;T8F36FaS9AtR4sXBkRr0iG;RTlM3IYjAzboXbIiNSIFRA;t7_svh3Kc3.VU9jOjAJgdq;.8D9Zx78FrKF.Zn4xbfmIG;IMhCM7gXESIqShs5TNMo9A;pvBPF7OtrK6trS5vZYizwa;9qxqLXuEeDQeAlNfAL_l.A;VNeyFcNDtQZhV2sfCxyHqA;kT4JL2WRSOhvUIEcOjSrva;LpFhLGWYI8eFx_X999MLEq;NqssQaVItFB0TevtNxJrkG;AI3RN3R7lP0BBnYsoCO5KG;xrYRhwM6FYW7zCsPL.iecq;0kOXzZzt1eXLrlPo.QQ4xG;ApKNqLIRoybF5rIxSnabBG;hfgZrtz_KscdFC6a3f1wKA;Ddfe167m26649h_g.S8UKVgXBt1074790432r0YQLJiVGhVajrMQpjFqUZuNqV80Tt89zds6ycR9fGsCNkl3650r0q}!DBEbb61kMgq_GKiDIZLg9oiwINe0CsjYI7qgLVKAwKS03oewpcl4FvNLIO7y1Tff8kgLIo2mtKfXR6JJw6Y_YTwPJKJxRTp2FUNdsvSGFU2gYvm7YUlP16wcwTJjWYNC36rssnfssmwnM0eVKbYnVvZFwTxcov2N1Dx0MKEKUCfl1YLAi0Y_KDyAxfA7VnfnQ9fZKcfIsvwaIDWDEvy5tmVaiUaqqqqqqqqqqqqqq',
        content:'meta_content',
        parentNode: {
            removeChild: function (tag) {
                console.log('meta中的removeChild接受的值:', tag)
            }
        }
    },
    length: 2
}

script = {
    0: {
        getAttribute: function (attr) {
            if (attr == 'r') {
                return 'm'
            } else {
                console.log('script-0中的getAttribute接受的值:', attr)
            }
        },
        parentElement: {
            removeChild: function (tag) {
                console.log('script-0中的removeChild接受的值:', tag)
            }
        }
    },
    1: {
        getAttribute: function (attr) {
            if (attr == 'r') {
                return 'm'
            } else {
                console.log('script-1中的getAttribute接受的值:', attr)
            }
        },
        parentElement: {
            removeChild: function (tag) {
                console.log('script-1中的removeChild接受的值:', tag)
            }
        }
    },
    length: 2
}

document = {
    createElement: function (tag) {
        if (tag == 'div') {
            return div
        } else {
            console.log('document中的createElement接受的值:', tag)
            return {}
        }
    },
    getElementsByTagName: function (tag) {
        if (tag == 'meta') {
            return meta
        } else if (tag == 'script') {
            return script
        } else {
            console.log('document中的etElementsByTagName接受的值:', tag)
            return {}
        }
    },
    addEventListener: function (event) {
        console.log('addEventListener中的addEventListener接受的值:', event)
    }
}

//补location
location = {
    "href": "http://www.fangdi.com.cn/index.html",
    "origin": "http://www.fangdi.com.cn",
    "protocol": "http:",
    "host": "www.fangdi.com.cn",
    "hostname": "www.fangdi.com.cn",
    "pathname": "/index.html",
}


proxy_array = ['window', 'document', 'location', 'navigator', 'history', 'screen', 'target']
getEnv(proxy_array)

setTimeout = function () {}
setInterval = function () {}

2.liantong.py

import requests
from lxml import etree
import execjs


headers = {
    "authority": "www.10010.com",
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "accept-language": "zh-CN,zh;q=0.9",
    "cache-control": "no-cache",
    "pragma": "no-cache",
    "referer": "https://www.10010.com/net5/074/",
    "sec-ch-ua": "\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\"",
    "sec-fetch-dest": "document",
    "sec-fetch-mode": "navigate",
    "sec-fetch-site": "same-origin",
    "upgrade-insecure-requests": "1",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
}
cookies = {
    "acw_tc": "7ca5d88f17015087471991589e7aaf60449722c524d081494298817c09",
    # "IdlEqTWW2ERnS": "5CpqLJemFR4RhDjScSbW0fcGGelTwNSyoMhucdXeL3Z80biBCbVVYyTHFBzLLWz.vkIjRdXg60OaZFc2pXabWza",
    # "IdlEqTWW2ERnT": "5RK.CfCYjeLaqqqDWtwWcxAsNzFkioaOcdxDruWHvOZhr2j.if2TO_92UwKQqbgOsD2RkQ42q8JYNIMRCCDb8MsBTVnPwB_EsW4uwqx1YXRlwXjujtvQ_9uLIkV5St86IbXTaJ7FEUpY4CQaSr6iqusCSrgQwqMMw_XPTFh.pcqmNXQr9dvRPlHOmq6Dzu3MZYl0l9RrKYpqXpgQhjgyslIzX8a69uhomTKcZBCCb30UeLb5HPeqlKrrmd2ZegamlG3Vt_KVhT8AXGxdYdlBVMx"
}

request_session = requests.session()
request_session.headers.update(headers)
request_session.cookies.update(cookies)

url = "https://www.10010.com/net5/074/"


def get_cookie():

    response = request_session.get(url)
    cookies['IdlEqTWW2ERnS'] = response.cookies['IdlEqTWW2ERnS']
    request_session.cookies.update(cookies)
    html = etree.HTML(response.text)
    meta_content = html.xpath('//meta[2]/@content')[0]
    js_code = html.xpath('//script[2]/text()')[0]
    return meta_content,js_code

meta_content,js_code = get_cookie()

with open('liantong.js','r',encoding='utf-8') as js_file:
    js_text = js_file.read()
    js_text = js_text.replace('meta_content',meta_content)
    js_text = js_text.replace("'js_code'",js_code)
    js = execjs.compile(js_text)
    cookies['IdlEqTWW2ERnT'] = js.call('get_cookie')
    request_session.cookies.update(cookies)
    response = request_session.get(url)
    response.encoding = 'utf-8'
    print(response.text)
    print(response)

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

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

相关文章

Javaweb之Mybatis的动态SQL的详细解析

3. Mybatis动态SQL 3.1 什么是动态SQL 在页面原型中&#xff0c;列表上方的条件是动态的&#xff0c;是可以不传递的&#xff0c;也可以只传递其中的1个或者2个或者全部。 而在我们刚才编写的SQL语句中&#xff0c;我们会看到&#xff0c;我们将三个条件直接写死了。 如果页面…

4.7 MEMORY AS A LIMITING FACTOR TO PARALLELISM

虽然CUDA寄存器和共享内存在减少对全局内存的访问次数方面非常有效&#xff0c;但必须注意保持在这些内存的容量范围内。这些内存是线程执行所需的资源形式。每个CUDA设备提供有限的资源&#xff0c;从而限制了给定应用程序可以同时驻留在SM中的线程数量。通常&#xff0c;每个…

第11章 GUI Page480~486 步骤二十七 “脏数据”与“新文档”状态维护

wxMyPainterFrame类定义中声明新的成员&#xff1a; 增加一个全局变量&#xff0c;初始化新成员&#xff1a; 先实现TrySaveFile() SaveFile()暂时为空实现 增加两个新的私有成员方法&#xff1a; wxMyPainterFrame类中&#xff0c;修改了“_items”的几个地方 ① 鼠标抬起时…

设计模式的艺术P1基础—2.3 类之间的关系

设计模式的艺术P1基础—2.3 类之间的关系 在软件系统中&#xff0c;类并不是孤立存在的&#xff0c;类与类之间存在各种关系。对于不同类型的关系&#xff0c;UML提供了不同的表示方式 1&#xff0e;关联关系 关联&#xff08;Association&#xff09;关系是类与类之间最常用…

属性动画的使用

文章目录 1 概述2 创建属性动画页面3 属性动画参数调整延时播放时间delay的设置onFinish回调函数的使用 4 关闭属性动画页面5 参考 1 概述 属性动画&#xff0c;是最为基础的动画&#xff0c;其功能强大、使用场景多&#xff0c;应用范围较广。常用于如下场景中&#xff1a; …

代码随想总结

1. 刷题技能成长 之前跟着代码随想录刷过一段时间&#xff0c;但是因为是自己刷不知道每天该刷几道题&#xff0c;而且没有组织的坚持异常困难&#xff0c;第一次在刷完链表之后&#xff0c;就逐渐停滞不前&#xff0c;十一月份看到了代码随想录的训练营&#xff0c;纠结要不要…

配置git服务器

第一步&#xff1a; jdk环境配置 &#xff08;1&#xff09;搜索【高级系统设置】&#xff0c;选择【高级】选项卡&#xff0c;点【环境变量】 &#xff08;2&#xff09;在【系统变量】里面&#xff0c;点击【新建】 &#xff08;3&#xff09;添加JAVA_HOME环境变量JAVA_HO…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux系统编程第六天-Linux信号(物联技术666)

更多配套资料CSDN地址:点赞+关注,功德无量。更多配套资料,欢迎私信。 物联技术666_嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记-CSDN博客物联技术666擅长嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记,等方面的知识,物联技术666关注机器学习,arm开发,物联网,嵌入式硬件,单片机…

基于zookeeper实现服务节点HA主备自动切换

文章目录 前言一、架构图和流程图二、流程说明1.服务启动初始化ZK、注册所有服务节点信息-MasterRegister2.创建、运行服务节点&#xff0c;并管理服务节点-LeaderSelectorZkClient。3.典型场景-调度服务单体执行-DigitalEmpTask 总结参考 前言 Spring Boot 主备切换可以采用数…

mac电脑php命令如何设置默认的php版本

前提条件&#xff1a;如果mac电脑还没安装多个PHP版本&#xff0c;可以先看这篇安装一下 mac电脑运行多个php版本_mac 同时运行两个php-CSDN博客 第一部分&#xff1a;简单总结 #先解除现在默认的php版本 brew unlink php7.4#再设置的想要设置的php版本 brew link php8.1第二部…

python 多线程 守护线程

daemon线程&#xff1a;守护线程&#xff0c;优先级别最低&#xff0c;一般为其它线程提供服务。通常&#xff0c;daemon线程体是一个无限循环。如果所有的非daemon线程(主线程以及子线程&#xff09;都结束了&#xff0c;daemon线程自动就会终止。t.daemon 属性&#xff0c;设…

一、MOJO环境部署和安装

以Ubuntu系统为例。 安装mojo-CLI curl https://get.modular.com | MODULAR_AUTHmut_fe303dc5ca504bc4867a1db20d897fd8 sh - 安装mojo SDK modular auth mojo modular auth install mojo 查看mojo版本号 mojo --version 输入mojo指令&#xff0c;进入交互编程窗口

【UE Niagara学习笔记】02 - 制作燃烧的火焰

目录 效果 步骤 一、添加资产 二、制作材质 三、制作粒子 3.1 循环播放 3.2 粒子生成的数量 3.3 粒子的生命周期和初始大小 3.4 火焰高度 3.5 火焰范围 3.6 火焰颜色 效果 步骤 一、添加资产 1. 在虚幻商城中搜索“M5 VFX Vol2. Fire and Flames(Niagara)”…

单片机原理及应用:中断系统结构与控制寄存器

大家好啊&#xff0c;这几天因为考试断更了一段时间&#xff0c;现在放假了也可以恢复正常的更新速度了。今天我们来认识一下单片机的中断系统&#xff0c;这里可以说是我们学习单片机以来第一个核心功能&#xff0c;我们会分几期内容来深入了解中断系统的作用原理和应用方式。…

多模态推荐系统综述:二、特征交互 Fusion

二、Fusion 融合不同的多模态信息&#xff0c;与bridge相比&#xff0c;融合更关注项目之间的多模态内部关系。 它可以灵活地融合不同权重和焦点的多模态信息。 注意机制是应用最为广泛的特征融合。 2.1 粗粒度注意力。 一些模型应用注意力机制在粗粒度级别融合来自多种模式…

Rustdesk本地配置文件存在什么地方?

环境&#xff1a; rustdesk1.1.9 Win10 专业版 问题描述&#xff1a; Rustdesk本地配置文件存在什么地方&#xff1f; 解决方案&#xff1a; RustDesk 是一款功能齐全的远程桌面应用。 支持 Windows、macOS、Linux、iOS、Android、Web 等多个平台。 支持 VP8 / VP9 / AV1 …

e2studio开发三轴加速度计LIS2DW12(1)----轮询获取加速度数据

e2studio开发三轴加速度计LIS2DW12.1--轮询获取加速度数据 概述视频教学样品申请源码下载通信模式管脚定义IIC通信模式速率新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原…

Android studio调试

Android Studio连接手机详细教程(包含遇到的问题集)_android studio 连接手机-CSDN博客 可以创建虚拟机或直连真机或直连模拟器。 无法打开本地终端 Android studio Failed to start [powershell.exe] 利用Android studio的adb命令删除app应用 - 简书 利用ADB工具免root停用A…

MySQL之子查询、连接查询(内外)以及分页查询

一、案例&#xff08;接上一篇文章&#xff09; 09&#xff09;查询学过「张三」老师授课的同学的信息 -- 一共有两种方式 -- 第一种方式&#xff1a; SELECT s.*,c.cname,t.tname,sc.score FROMt_mysql_teacher t,t_mysql_course c,t_mysql_student s,t_mysql_score sc WHERE…

BabylonJS 6.0文档 Deep Dive 摄像机(二):摄像机碰撞

摄像机、网格碰撞和重力 你玩过第一人称射击游戏(FPS)吗&#xff1f;在本教程中&#xff0c;我们将模拟FPS的摄影机移动&#xff1a;摄影机位于地板上&#xff0c;与地面碰撞&#xff0c;并可能与场景中的任何对象碰撞。 如何实现? 为了实现这一功能&#xff0c;我们必须执…