爬虫进阶-反爬破解6(Nodejs+Puppeteer实现登陆官网+实现滑动验证码全自动识别)
一、Nodejs+Puppeteer实现登陆官网
1.环境说明
Nodejs——直接从官网下载最新版本,并安装
使用npm安装puppeteer:npm install puppeteer
npm install xxx -registry https://registry.npm.taobao.org
Chromium会自动下载,前提是网络通畅
2.实践操作:Nodejs+Puppeteer介绍
Puppeteer登录官网首页:
1.打开浏览器并访问首页
2.键入数据并访问登录后的页面
3.截图保留记录,存储成本地图片
const puppeteer = require("puppeteer")const sleep = time => new Promise(resolve => {setTimeout(resolve, time);
});(async() => {const browser = await puppeteer.launch({headless:false,//无头模式,默认是隐藏界面的,true.改成false,显示界面。slowMo:100 //设置浏览器每一步之间的时间间隔,单位毫秒defaultViewport:{width:1366, height:768},//默认的网页大小是800*800,可以自行设置});const page = await browser.newPage();await page.goto("http://shanzhi.spbeen.com/index");await sleep(3000);const login_link_button = await page.$('a.btn.btn-primary');await login_link_button.click()await sleep(2000);const username_input = await page.$('input#username');await username_input.type('demo1234');await sleep(2000);const password_input = await page.$('input#MemberPassword');await password_input.type('demo1234');await sleep(2000);const submit_button = await page.$("button.btn.btn-primary");await submit_button.click(); await sleep(2000);await page.screenshot({path:'shanzhi_login_index.png'});await sleep(2000);await browser.close();})();
3.总结:
Puppeteer有更多且更全的接口,可以快捷的操作网页
Puppeteer可以实现多种数据的存储,例如截图、pdf等
浏览器的标签页不要太多,容易卡电脑
二、nodejs+puppeteer实现滑动验证码全自动识别
1.滑动验证码破解方法
数据来源:滑动验证码的图片偏移
破解方法一:分析请求,用数据做正确的请求操作
破解方法二:浏览器实现滑动验证码
2.滑动验证码偏移计算方法
数据来源:滑动验证码的图片
方法一:相似度对比
方法二:像素的RGB值对比
方法三:调用经过数据训练过的机器学习模型
3.图片的预处理
数据来源:滑动验证码的图片
阶段一:缩放图片[将图片尺寸进行压缩]
阶段二:简化色彩[灰度处理]
阶段三:计算平均值或灰度平均值
4.实践操作:图形以及效果展示
// const puppeteer = require("puppeteer");//puppeteer启动的chromium会被知乎识别const puppeteer = require('puppeteer-extra');//消除特征 npm install puppeteer-extra
const StealthPlugin = require('puppeteer-extra-plugin-stealth'); //npm install puppeteer-extra-plugin-stealth
puppeteer.use(StealthPlugin()); //消除特征const Rembrant = require('rembrandt');//rembrandt算法库,导入使用 npm install rembrandt
const fs = require('fs');// nodejs 操作本地文件的库 npm install fs
var ssim = require('ssim');//ssim算法库,导入使用 npm install ssim// 睡眠函数,单位毫秒
const sleep = time => new Promise(resolve => {setTimeout(resolve, time);
});//程序的主体部分
(async() => {const browser = await puppeteer.launch({//启动浏览器headless:false,//无头模式,默认是隐藏界面的,true.改成false,显示界面。defaultViewport:{width:1366, height:768},//默认的网页大小是800*800,可以自行设置args: ['--disable-web-security','--disable-features=IsolateOrigins,site-per-process',]});const page = await browser.newPage();await page.goto("http://www.zhihu.com/signin");//点击“密码登录”,从“手机短信登陆”切换到“账号密码登录”const mima_button = await page.$('form.SignFlow.Login-content > div:nth-child(1) div:nth-child(2)');await mima_button.click;const username = await page.$('div.SignFlow-account input.Input');await username.type('18296198879');const password = await page.$('div.SignFlow-password input.Input');await password.type('demodemodemo');// 定位登录按钮,点击登录,弹出滑动验证码,开始验证const login_button = await page.$('button.Button.SignFlow-submitButton.Button--primary.Button--blue');await sleep(1000)await login_button.click()await sleep(1000);// 重复破解 滑块验证码 代码部分for (let num = 1; num < 1000; num++){await sleep(2000);console.log('----------------\n当前循环次数:',num);// 判断 验证码多次失败后,弹出的错误提示,需要点击之后才能继续验证// 判断依据 “失败过多,点此重试”,然后会恢复到等到滑块滑动的验证状态let yidun_msg = await page.$eval("span.yidun_tips_text.yidun-fallback_tip",el => el.innerHTML)if (yidun_msg = '失败过多,点此重试'){const yidun_tips = await page.$(".yidun_tips");await yidun_tips.click();};// 验证成功后,滑动验证码的框会隐藏// 如果滑动验证码隐藏了,则自动停止,并输出“验证成功,正常退出”let yidun_popup = await page.$('div.yidun_popup--light.yidun_popup');const yidun_popup_style = await page.evaluate(//根据yidun_popup标签,通过window窗口,计算出标签的style样式(x) => {return JSON.parse(JSON.stringify(window.getComputedStyle(x)))},yidun_popup);console.log('yidun_popup style.display:',yidun_popup_style.display);//输出样式值if(yidun_popup_style.display == 'none'){console.log("验证成功,正常退出");break;// 如果样式值为none,则表示验证成功了,使用break跳出for循环};// page.waitForSelector('.yidun_tips', {timeout:1000}).then((yidun_tips) => yidun_tips.click());//calculateDistance函数中的console.log内容全部输出在网页的开发者工具console栏【记得拉长延迟,慢慢看】calculateDistance = async (page) =>{var distance = await page.evaluate(() => {//将图片写入canvas,截取canvas的图片内容,通过toGrayBinary全部换成二维数组,进行像素RGB的对比toGrayBinary = (pixels, binary, value, sn) => {var r, g, b, g, avg = 0, len = pixels.length, s = '';for (var i = 0;i < len; i+= 4){avg += (.299 * pixels[i] + .587 * pixels[i+1]+.114*pixels[i+2]);}avg /= (len /4);for (var i=0;i<len;i+=4){r = .299*pixels[i],g = .587* pixels[i+1],b = .114*pixels[i+2];if (binary){if ((r+g+b)>=(value||avg)){g = 255;if (sn) s+= '1';} else { g = 0;if (sn) s+= '0';}g = (r+g+b) > (value || avg)?255:0;}else{g = r+g+b;}pixels[i] = g,};//将截取的canvas图片,转成base64,方便存储本地imgCanvasToBase64 = (img,width,height) => {let canvas3 = document.createElement("canvas");let context3 = canvas3.getContext("2d");canvas3.width = width;canvas3.height = height;context3.putImageData(img,0,0,0,0,width,height);let base64Img = canvas3.toDataURL('image/jpeg');return base64Img;};const smallbgimg = document.getElementByClassName('yidun_jigsaw')[0];//提取图片const smallcanvas = document.createElement('canvas');//创建画布const smallcontext = smallcanvas.getContext('2d');//设定2d界面console.log('smallbgimg:', smallbgimg, smallbgimg.naturalWidth, smallbgimg.naturalHeight);smallcontext.drawImage(smallbgimg,0,0,smallbgimg.naturalWidth, smallbgimg.naturalHeight);//写入图片到画布中//将图片亮度降低,颜色减弱【灰度处理】//从0,0位置,读取图片的宽高var pixels = smallcontext.getImageData(0,0,smallbgimg.naturalWidth, smallbgimg.naturalHeight);var pixeldata = pixels.data;//读取了图片,取出具体的数值data//循环设置,降低像素的RGB值。RGB分别是0,1,2//完整的值,是RGBA,A一直是1,所以不需要处理A,所以i每次增加4for (var i=0,len = pixeldata.length;i<len;i+=4){pixels.data[i] = pixels.data[i] - 95;//Rpixels.data[i+1] = pixels.data[i+1] - 55;//Gpixels.data[i+2] = pixels.data[i+2] -45;//B}smallcontext.putImageData(pixels,0,0); //把数据写回到画布中var minwidth = smallbgimg.naturalWidth;var maxwidth = 0;var minheight = smallbgimg.naturalHeight;var maxheight = 0;for (let i = 1;i<smallbgimg.naturalWidth;i++){let times=0;//因为缺口只会出现在中间位置,所以不用对比整个纵坐标,只需要对比中间位置即可//这里我们从上面45像素开始到下面55像素结束for (let j=1;i<smallbgimg.naturalHeight;j++){const smallimgData = smallcontext.getImageData(1*i,1*j,1,1).data:const r = smallimgData[0];const g = smallimgData[1];const b = smallimgData[2];if (r >0&g>0&b>0){//不含无色的长方形图片if(minwidth >i){minwidth=i;}if(maxheight<=j){maxheight=j;}if(maxwidth<i){maxwidth=i};if(minheight>j){minheight=j};};};};//maxheight = maxheight-12//minwidth = minwidth+2//minheight = minheight +2//maxwidth = maxwidth -2console.log("图片最大和最小宽高",minwidth,maxwidth,minheight,maxheight)var height = maxheight -minheight;var width = maxwidth - minwidth;var smallimg = smallcontext.getImageData(minwidth,minheight,width,height);var smallimgdata = smallimg.data;var smallimggb = toGratBinary(smallimgdata);//console.log('smallimggb',smallimggb)var small_img_canvas = imgCanvasToBase64(smallimg,width,height);console.log('smallimg canvas),small_img_canvas);//背景图转canvasconst bgimg = document.getElementsByClassName('yidun_bg-img')[0];console.log('bgimg',bgImg.naturalWidth,bgImg.naturalHeight);const convas = document.createElement('canvas');const context = canvas.getContext('2d');context.drawImage(bgImg,0,0,bgImg.naturalWidth,bgImg.naturalHeight);const contextBigimg = context.getImageData(1,1,bgImg.naturalWidth,bgImg.naturalHeight);var bigimg = imgCanvasToBase64(contextbigimg,bgImg.naturalWidth,bgImg.naturalHeight);console.log("bigimg canvas:",bigimg);var xAxis = [];var tmpmax = 0.0;var part_bigimg = {};//这个for循环,进行的就是图片二维数组的对比,找出最大的相似度//将截图的canvas图片,放入part_bigimg对象,方便返回并保存成本地图片for (let i = minwidth+width+2;i<bgImg.naturalWidth-width;i++){let times=0;i = minheight +2;const bigimg = context.getImageData(1*i,1*j,width,height);//根据小图的尺寸截取大图的部分内容,能得到小图同高不同宽的逐帧所有同尺寸图片const bigimgData = bigimg.data;const imggb = toGrayBinary(bigimgData);let similar = 0;for (let n=0,len = width*height;n<len;n++){if(smallimggb[n]==imggb[n]){similar++};}similar = (similar/(width*height))*100;var bigimg_part = imgCanvasToBase64(bigimg,width,height);part_bigimg[i] = bigimg_part;if (parseFloat(similar)>tmpmax){tmpmax = parseFloat(similar);console.log('yes:',i,j,width,height,similar,bigimg_part);xAxis = [];xAxis.push(i);} else if(parseFloat(similar)==tmpmax){console.log('yes:',i,j,width,height,similar,bigimg_part);xAxis.push(i);} else{console.log('error---',i,j,width,height,similsr,bigimg_part);};};return [xAxis[xAxis.length-1],small_img_canvas,part_bigimg];//返回多个参数,请修改这里});return distance;//这里不影响结果值的返回}//const distance = await calculateDistance(page);const adata = await calculateDistance(page);const distance = adata[0];const smallimg = adata[1];//base64的小图数据const part_bigimg = adata[2];//base64的截取大图特定部分的所有图片,用于对比小图// const distance, smallimg, part_bigimg = await calculateDistance(page);console.log('像素RGB值对比算法结果值:',distance);//小图存储地址, 保存到本地var small_img_path = './assets/smallimg.jpg';// console.log('smallimg:', smalling);var small_img_data = smallimg.replace("data:image/jpeg;base64,","")const smallimg_buffer = new Buffer.from(small_img_data,'base64');fs.writeFile(small_img_path, smallimg_buffer, function(err){//用fs写入文件//if(err) { console.log(err);}else{// console.log('写入成功!');//}});var maxdiff = 0.0;var offset_size = 0;var ssim_maxdiff = 0.0;var ssim_offset_size = 0;for (var partb in part_bigimg){//截取的所有大图, 保存本地var part_big_img_path = './assets/part_big/'+parseInt(partb)+'.jpg';var part_big_img_data = part_bigimg[partb].replace("data:image/jpeg;base64,","")const partbimg_buffer = new Buffer.from(part_big_img_data,'base64');fs.writeFile(part_big_img_path, partbimg_buffer, function(err){//用fs写入文件//if(err) { console.log(err);}else{// console.log('写入成功!');//}});//ssim算法 比较图片相似度//参数是base64转换成图片字节,也是通过路径读取到的图片内容const ssim_result = ssim(smallimg_buffer, partbimg_buffer);//console.log("ssim:",ssim_result,part_big_img_path);if (ssim_result>ssim_maxdiff){ssim_maxdiff = ssim_result;ssim_offset_size=parseInt(partb);}//randbrandt算法,参数是图片路径const rembrandt = new Rembrandt({imageA:small_img_path,imageB:part_big_img_path,thresholdType:Rembrandt.THRESHOLD_PIXELS//thresholdType:Rembrandt.THRESHOLD_PERCENT});let result = await rembrant.compare();let difference = result.percentageDifference*100;if (difference > maxdiff){maxdiff = difference;offset_size=parseInt(partb);}};console.log("{*}SSIM算法计算偏移结果值:", ssim_offset_size);console.log("rembrandt算法计算偏移结果值:", offset_size);await sleep(1000);// 拿到了滑动验证码的偏差值,开始使用鼠标移动滑块,定位到偏差值的具体位置。const _moveTrace = function* (dis) {//定义移动函数,从起始地址到目标地址,中间要计算出很多个坐标,结合延迟,达到缓慢的滑块效果let trace = [];let t0 = 0.2;let curr = 0;let step = 0;let a = 0.8;while (curr < dis){let t = t0 * (++step);curr = parseFloat((1/2*a*t*t).toFixed(2));trace.push(curr);};for (let i = 0;i<trace.length;++i){yield trace[i];};};const yidun_slider = await page.$(".yidun_slider");// 定位滑块标签位置const bounding_box = await yidun_slider.boundingBox();// 通过bounding_Box()函数,拿到标签的起始坐标,标签的左上角await page.mouse.move(bounding_box.x + bounding_box.width/2,bounding_box.y+bounding_box.height/2);//等待页面上,鼠标移动到标签的中间位置await page.mouse.down();//鼠标按住滑块let gen = _moveTrace(ssim_offset_size);for (let ret of gen){//循环读取_moveTrace返回的生成器的值,每次都挪动一点点。而且y轴【垂直方向】也需要加一个简单的偏移await page.mouse.move(bounding_box.x+ret,bounding_box.y+6);//移动鼠标};await page.mouse.move(bounding_box.x+ssim_offset_size,bounding_box.y+6);//把鼠标移动到目标位置上await.sleep(100);//睡眠100毫秒await page.mouse.up();//到了目标位置上,松开鼠标按键,完成滑块的拖动};await sleep(2000);await browser.close();})();
总结:
使用canvas进行图片的灰度处理、剪辑处理。
图片的对比,要查看算法函数的调用方法,注意数据类型要对上。
修改代码前,要详细阅读每一行代码,修改起来会更顺畅
三、滑动验证码之像素RGB对比算法实现
算法介绍:1.拿到小图,减弱图片颜色2.根据小图的宽高,截图同等宽高的对比图3.循环取出图片的所有RGB值并比较4.取出相似度最大的一个偏移值,做滑动操作
对比步骤:1.图片预处理2.逐个像素对比3.将相似度最大的偏移量进行滑动操作
图片预处理:1.颜色减弱2.宽高设定
相关文章:

爬虫进阶-反爬破解6(Nodejs+Puppeteer实现登陆官网+实现滑动验证码全自动识别)
一、NodejsPuppeteer实现登陆官网 1.环境说明 Nodejs——直接从官网下载最新版本,并安装 使用npm安装puppeteer:npm install puppeteer npm install xxx -registry https://registry.npm.taobao.org Chromium会自动下载,前提是网络通畅 2.实践操作…...

【Unity】RenderFeature笔记
【Unity】RenderFeature笔记 RenderFeature是在urp中添加的额外渲染pass,并可以将这个pass插入到渲染列队中的任意位置。内置渲染管线中Graphics 的功能需要在RenderFeature里实现,常见的如DrawMesh和Blit 可以实现的效果包括但不限于 后处理,可以编写…...

golang gin——controller 模型绑定与参数校验
controller 模型绑定与参数校验 gin框架提供了多种方法可以将请求体的内容绑定到对应struct上,并且提供了一些预置的参数校验 绑定方法 根据数据源和类型的不同,gin提供了不同的绑定方法 Bind, shouldBind: 从form表单中去绑定对象BindJSON, shouldB…...

办公技巧:Excel日常高频使用技巧
目录 1. 快速求和?用 “Alt ” 2. 快速选定不连续的单元格 3. 改变数字格式 4. 一键展现所有公式 “CTRL ” 5. 双击实现快速应用函数 6. 快速增加或删除一列 7. 快速调整列宽 8. 双击格式刷 9. 在不同的工作表之间快速切换 10. 用F4锁定单元格 1. 快速求…...

【jvm--方法区】
文章目录 1. 栈、堆、方法区的交互关系2. 方法区的内部结构3. 运行时常量池4. 方法区的演进细节5. 方法区的垃圾回收 1. 栈、堆、方法区的交互关系 方法区的基本理解: 方法区(Method Area)与 Java 堆一样,是各个线程共享的内存区…...

智慧楼宇3D数据可视化大屏交互展示实现了楼宇能源的高效、智能、精细化管控
智慧园区是指将物联网、大数据、人工智能等技术应用于传统建筑和基础设施,以实现对园区的全面监控、管理和服务的一种建筑形态。通过将园区内设备、设施和系统联网,实现数据的传输、共享和响应,提高园区的管理效率和运营效益,为居…...

算法题:摆动序列(贪心算法解决序列问题)
这道题是一道贪心算法题,如果前两个数是递增,则后面要递减,如果不符合则往后遍历,直到找到符合的。(完整题目附在了最后) 代码如下: class Solution(object):def wiggleMaxLength(self, nums):…...

接口自动化测试yaml+requests+allure技术,你学会了吗?
前言 接口自动化测试是在软件开发过程中常用的一种测试方式,通过对接口进行自动化测试,可以提高测试效率、降低测试成本。在接口自动化测试中,yaml、requests和allure三种技术经常被使用。 一、什么是接口自动化测试 接口自动化测试是指通…...

android 获取局域网其他设备ip
Android 通过读取本地Arp表获取当前局域网内其他设备信息_手机查看arp-CSDN博客...

angular中使用 ngModel 自定义组件
要创建一个自定义的 Angular 组件,并使用 ngModel 进行双向数据绑定,您可以按照以下步骤操作: 创建自定义组件:首先,使用 Angular CLI 或手动创建一个新的组件。在组件的模板中,添加一个输入元素或其他适合…...

kubernetes pod日志查看用户创建
目录 1.创建用户 1.1证书创建 1.2创建用户 1.3允许用户登陆 1.4切换用户 1.5删除用户 2.RBAC 1.创建用户 1.1证书创建 进入证书目录 # cd /etc/kubernetes/pki创建key # openssl genrsa -out user1.key 2048 Generating RSA private key, 2048 bit long modulus .....…...

HTML5+CSSday4综合案例二——banner效果
bannerCSS展示图: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wi…...

关于红包雨功能的探索
【高并发优化手段】基于Springboot项目 【红包雨功能的】环境部署(弹性伸缩、负载均衡、Redis读写分离、云服务器部署) jemeter压测【2万用户每秒5次请求在30秒内处理完请求】 【红包雨压测】提供2万用户30秒内5次请求的并发服务支持 使用工厂模式、策略…...

【已解决】Python打包文件执行报错:ModuleNotFoundError: No module named ‘pymssql‘
【已解决】Python打包文件执行报错:ModuleNotFoundError: No module named pymssql 1、问题2、原因3、解决 1、问题 今天打包一个 tkinter pymssql 的项目的时候,打包过程很顺利,但是打开软件的时候,报错 ModuleNotFoundError: …...

华为云云耀云服务器L实例评测|测试CentOS的网络配置和访问控制
目录 引言 1 理解几个基础概念 2 配置VPC、子网以及路由表 3 配置安全组策略和访问控制规则 3.1 安全组策略和访问控制简介 3.2 配置安全组策略 3.3 安全组的最佳实践 结论 引言 在云计算时代,网络配置和访问控制是确保您的CentOS虚拟机在云环境中安全运行的…...

CSP模拟51联测13 B.狗
CSP模拟51联测13 B.狗 文章目录 CSP模拟51联测13 B.狗题目大意题目描述输入格式输出格式样例样例 1inputoutput 思路 题目大意 题目描述 小G养了很多狗。 小G一共有 n n n\times n nn 条狗,在一个矩阵上。小G想让狗狗交朋友,一条狗狗最多只能交一个…...

GEO生信数据挖掘(七)差异基因分析
上节,我们使用结核病基因数据,做了一个数据预处理的实操案例。例子中结核类型,包括结核,潜隐进展,对照和潜隐,四个类别。本节延续上个数据,进行了差异分析。 差异分析 计算差异指标step12 加载…...

JAVA-SpringBoot入门Demo用IDEA建立helloworld
使用编辑器IDEA做SpringBoot项目最近几年比较红红,作为JAVA语言翻身的技术,用户量激增。由于java平台原来的占有率,相比net core在某些方面更有优势。 我把本次我下载完成后Maven项目的过程记录下来了,仅供参考! 安装J…...

Unity布料系统Cloth
Unity布料系统Cloth 介绍布料系统Cloth(Unity组件)组件上的一些属性布料系统的使用布料约束Select面板Paint面板Gradient Tool面板 布料碰撞布料碰撞碰撞适用 介绍 布料系统我第一次用是做人物的裙摆自然飘动,当时我用的是UnityChan这个unity官方自带的插件做的裙摆…...

漏电继电器 LLJ-630F φ100 导轨安装 分体式结构 LLJ-630H(S) AC
系列型号: LLJ-10F(S)漏电继电器LLJ-15F(S)漏电继电器LLJ-16F(S)漏电继电器 LLJ-25F(S)漏电继电器LLJ-30F(S)漏电继电器LLJ-32F(S)漏电继电器 LLJ-60F(S)漏电继电器LLJ-63F(S)漏电继电器LLJ-80F(S)漏电继电器 LLJ-100F(S)漏电继电器LLJ-120F(S)漏电继电器LLJ-125F(S…...

数据结构和算法(10):B-树
B-树:大数据 现代电子计算机发展速度空前,就存储能力而言,情况似乎也是如此:如今容量以TB计的硬盘也不过数百元,内存的常规容量也已达到GB量级。 然而从实际应用的需求来看,问题规模的膨胀却远远快于存储能…...

VR会议:远程带看功能,专为沉浸式云洽谈而生
随着科技的不断发展,VR技术已经成为当今市场上较为热门的新型技术之一了,而VR会议远程带看功能,更是为用户提供更加真实、自然的沉浸式体验。 随着5G技术的发展,传统的图文、视频这种展示形式已经无法满足消费者对信息真实性的需求…...

实验室管理系统LIMS
在数字化浪潮中,越来越多的企业开始有数字化转型的意识。对于实验室而言,数字化转型是指运用新一代数字技术,促进实验室业务、生产、研发、管理、服务、供应链等方面的转型与升级,实现实验室业务“人、机、料、法、环”的多维度发…...

开源ERP和CRM套件Dolibarr
什么是 Dolibarr ? Dolibarr ERP & CRM 是一个现代软件包,用于管理您组织的活动(联系人、供应商、发票、订单、库存、议程…)。它是开源软件(用 PHP 编写),专为中小型企业、基金会和自由职业…...

视频号双11激励政策,快来看一看
双十一即将来临,不少平台都公布了自己的双十一政策。这篇文章,我们来看看视频号推出的激励政策,看有哪些需要准备的。...

Maven最新版本安装及配置
Maven是一个Java项目管理和构建工具,它可以定义项目结构、项目依赖,并使用统一的方式进行自动化构建,是Java项目不可缺少的工具。 本章我们详细介绍如何使用Maven。 一、Maven是什么? 如果每一个项目都自己搞一套配置…...

探索ClickHouse——使用MaterializedPostgreSQL同步PostgreSQL数据库
安装PostgreSQL sudo apt install postgresql修改配置 sudo vim /etc/postgresql/14/main/postgresql.conf 解开并修改wal_level 的配置项 wal_level logical 重启服务 /etc/init.d/postgresql restartRestarting postgresql (via systemctl): postgresql.service AUTHENTI…...

《向量数据库指南》——向量数据库 有必要走向专业化吗?
向量数据库 有必要走向专业化吗? 向量数据库系统的诞生,来源于具体业务需求——想要高效处理海量的向量数据,就需要更细分、更专业的数据基础设施,为向量构建专门的数据库处理系统。 但这种路径是必须的吗? 从产品层面讲,如果传统数据库厂商不单独研发向量数据库,那么…...

你必须知道的数据查询途径!!
在当今信息爆炸的时代,我们每天都会面临海量的数据和信息。如何在这些繁杂的信息中快速、准确地找到自己需要的内容,也是当代一个非常重要的技能。下面,我将介绍几种你必须知道的企业数据信息查找途径。 1. 搜索引擎 搜索引擎是我们日常中…...

火焰原子吸收光谱法、容量法和电感耦合等离子体发射光谱法
声明 本文是学习GB-T 1871.5-2022 磷矿石和磷精矿中氧化镁含量的测定 火焰原子吸收光谱法、容量法和电感耦合等离子体发射光谱法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件描述了在磷矿石和磷精矿中测定氧化镁含量的火焰原子吸收…...