首页
文章分类
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
网上邻居
留言板
欣赏小姐姐
关于我
Search
登录
1
利用AList搭建家庭个人影音库
4,743 阅读
2
浅尝Restful Fast Request插件,一句话完成 逆向过程
4,218 阅读
3
完美破解The Economist付费墙
2,933 阅读
4
i茅台app接口自动化csharp wpf实现,挂机windows服务器每日自动预约
2,717 阅读
5
青龙面板基本使用并添加修改微信/支付宝步数脚本
2,154 阅读
Search
标签搜索
PHP
Laravel
前端
csharp
安卓逆向
JavaScript
Python
Java
爬虫
抓包
Git
winform
android
Fiddler
Vue
selenium
LeetCode
每日一题
简单题
docker
Hygge
累计撰写
98
篇文章
累计收到
450
条评论
首页
栏目
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
页面
网上邻居
留言板
欣赏小姐姐
关于我
用户登录
搜索到
65
篇与
的结果
2023-06-08
RecyclerView Adding Ripple Effect to RecyclerView item
实现recyclerView item长按的水波纹效果<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="m" type="cn.lisok.rf.model.SettingItemModel" /> </data> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/selectableItemBackground" android:clickable="true" android:focusable="true" android:paddingStart="40dp" android:paddingEnd="40dp" android:paddingBottom="8dp"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:layout_marginBottom="20dp" android:text="@{m.title,default=无障碍权限}" android:textColor="@color/black" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/textView" android:layout_marginTop="24dp" android:maxWidth="250dp" android:text="@{m.desc,default=`依次点击:无障碍 > 已下载的应用 > ❤️真实好友`}" android:visibility="@{m.desc == null ? android.view.View.GONE : android.view.View.VISIBLE}" /> <com.google.android.material.switchmaterial.SwitchMaterial android:id="@+id/power" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:layout_marginTop="8dp" android:layout_marginEnd="4dp" android:checked="true" android:visibility="@{m.showSwitch? android.view.View.VISIBLE: android.view.View.GONE}" /> </RelativeLayout> </layout>核心三行代码 添加给item的父布局android:background="?android:attr/selectableItemBackground" android:clickable="true" android:focusable="true"引用1.Adding Ripple Effect to RecyclerView item: https://stackoverflow.com/questions/30931889/adding-ripple-effect-to-recyclerview-item
2023年06月08日
315 阅读
0 评论
0 点赞
2023-05-07
【ACM】算法竞赛及OJ题面常用英文单词整理(更新ing)
本文转载自:https://blog.csdn.net/qq_36693514/article/details/108803092Aabbreviation [数学] 约分;activity on edge AOE网activity on vertex AOV网add, subtract, multiply and divide加减乘除adjacency list 邻接表(adjacency multilist 邻接多重表)adjacency matrix 邻接矩阵adjacent sequence elements相邻的元素串adjacent vertex 相邻顶点algebraic term代数项alphabetical order 字典序alternately rise and fall交替上升和下降Ambiguous 模糊不清ancestor 祖先anticlockwise 逆时针Approximate String Matching 模糊匹配Arbitrary Precision Arithmetic 高精度计算arc 弧arithmetic mean 算数平均值arithmetic progression 等差数列(geometric progression 等比数列)array 数组articulation point 连接点ascending lexicographical order 词典顺序升序排列ascending order升序(descending order降序)aspect ratio固定长宽比assemble 组合assess 评定,评估assigned adj指定的,赋值的augmenting path graph 增广路径图(augmenting path 增广路径)average search length 平均查找长度average temperature顺时针axis axes 轴Bbalance merging sort 平衡归并排序balance two-way merging 二路平衡归并排序Bandwidth Reduction 带宽压缩banlanced binary tree 平衡二叉树base 底边;幂的底数biconnected graph 重连通图bidirectional 双向的binary search tree 二叉查找树binary search 二分查找binary sort tree 二叉排序树binary 二进制bipartite graph 二部图Bishop主教(象)只斜走。格数不限不能越子。每方有两象,黑白格各占1个blank string 空白(空格)串block search 分块查找boundary界限Ccalculate计算Calendrical Calculations 日期carpet 地毯chariot 战车(中国象棋)checkmate (国际象棋) 将死; 输棋,将死; 败局; 败北,挫败;circular linked list 循环链表cirular queue 循环队列Clique 最大团clockwise order顺时针方向顺序(anticlockwise 逆时针)Coefficient 系数,率,程度Collinear 共线的column major order 以列为主的顺序分配columns列Combinatorial Problems 组合问题comma逗号common superstring公共父串compile v编译,汇编complete binary tree 完全二叉树complete graph 完全图composite numbers 合数Computational Geometry 计算几何concave 凹的connected component 连通分量(Connected Components 连通分支)consecutive 连续的constant n常数,常量 adj不变的,始终如一的,持续不断的Constrained and Unconstrained Optimization 最值问题Convex Hull 凸包coordinates坐标corrupt 腐烂,破坏counterclockwise 逆时针critical path 关键路径Cryptography 密码Cube root立方根DD is rounded to 2 decimal places D是精确到小数点后2位Data Structures 基本数据结构data type 数据类型decimal n小数 adj小数的,十进制的decimal 十进制decision tree 判定树Deck 甲板define v定义,明确,使规定deformed变形的Denominator分母denote 代表; 指代; 预示; 意思是;标志;象征dense graph 稠密图Deployed 部署depth 深度deque(double-ended queue) 双端列表descentdant 子孙destination 终点Determinants and Permanents 行列式diagonal对角(diagonally 斜对角线的)dial 钟面,拨打dialing 拨号音 打电话,拨电话号码( dial的现在分词 )Dictionaries 字典difference 差digital analysis method 数字分析法digital search tree 数字查找树digit位数;数字digraph(directed graph) 有向图Dimensional 尺寸diminishing increment sort 随小增量排序direct access file 直接存取文件directed acyclic graph 有向无环图directory structure 目录结构directory(计算机文件或程序的)目录;指导的咨询的; 管理的discrete Fourier transform 离散傅里叶变换disjoint 不相交的Distinct values 独一无二的值distinct 不同的;独一无二的division method 除法divisor 因子;分母doubly linked list 双向链表doubly linked tree 双链树Drawing Graphs Nicely 图的描绘Drawing Trees 树的描绘duplicated 复制;打印的duplicates 完全一样的东西,复制品( duplicate的名词复数 )EEdge and Vertex Connectivity 割边/割点Edge Coloring 边染色embed插入enable 启用Entry 进口equation方程式;等式equivalent equation同解方程;等价方程equivalent 相等的,等效的estimate 预测Eulerian Cycle / Chinese Postman Euler回路/中国邮路evaluate v评价,估价evaluated adj求···的值even偶数的excluding 排除,拒绝( exclude的现在分词); 驱逐;除…外,不包括execute v执行,完成executed 执行的;生效的exponent 指数;幂external sort 外部排序FFacility 设备,设施factorial 阶乘; 因子的,阶乘的Factoring and Primality Testing 因子分解/质数判定Feedback Edge/Vertex Set 最大无环子图Finite State Machine Minimization 有穷自动机简化fixed-aggregate data type 固定聚合数据类型foggiest idea概念folding method 折叠法follow by跟随,其后forest 森林formula n公式fraction:分数;小部分front 队头full binary tree 满二叉树Ggcd (greatest common divisor) 最大公约数generalized list 广义表Generating Graphs 图的生成Generating Partitions 划分生成Generating Permutations 排列生成Generating Subsets 子集生成geometric progression 等比数列grabh 图Graph Data Structures 图Graph Isomorphism 同构Graph Partition 图的划分Graph Problems — hard 图论-NP问题Graph Problems — polynomial 图论-多项式算法greatest integer最大整数grid网格;方格;(地图上的)坐标方格HHamiltonian Cycle Hamilton回路hash search 散列查找(hash table 散列表)head node 头结点(head pointer 头指针)heap sort 堆排序horizontal or vertical direction水平和垂直方向horizontally adv水平地 horizontal adj水平的Huffman tree 哈夫曼树IIdentifier n标识符,识别码immediate predecessor 直接前趋(immediate successor 直接后继)immediately allocating method 直接定址法improper fraction 假分数in the range of 在…范围内in the shape of a cross十字形incident edge 关联边indegree 入度indent n缩进indentical相同的Independent Set 独立集indexed file 索引文件indexed non-sequential file 索引非顺序文件(indexed sequential file 顺序)indicating adj指示的,标志的inequality不等式infinite 无限的initial adj最初的,词首的,开始的 n首字母initial node 初始结点initialization n初始化,赋初值 initialize v初始化inorder traversal 中序遍历insertion sort 插入排序insertion 插入integer 整数Interior 内部,本质internal sort 内部排序Interpret 解释,执行intersect v相交,交叉intersection 横断,横切; 交叉,相交; 交叉点,交叉线; [数] 交集;Intersection Detection 碰撞测试intersection横断;横切;交叉intersect相交intervals 间隔时间; 间隔( interval的名词复数 ); 区间Invade 侵略invalid 无效的inverted file 倒排文件irreparably 不能恢复地JJob Scheduling 工程安排justified adj合理的,合法化的KKd-Trees 线段树Knapsack Problem 背包问题Knight 骑士(马)每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有象棋中的“蹩马腿”限制。Llcm (Least Common Multiple) 最小公倍数left or right-justified 左对齐or右对齐lexicographically 字典序like terms ,similar terms同类项linear algebra 线性代数(linear equation线性方程linear linked list 线性链表)Linear Programming 线性规划linear structure 线性结构link field 链域 linked list 链表literal coefficient字母系数logarithm 对数logical structure 逻辑结构Longest Common Substring 最长公共子串loop环MMaintaining Line Arrangements 平面分割master file 主文件Matching 匹配Matrix Multiplication 矩阵乘法maximum matching 最大匹配meadow 草坪mean 平均值Medial-Axis Transformation 中轴变换Median and Selection 中位数memorable 值得纪念的; 显著的,难忘的; 重大的,著名的merge sort 归并排序mid-square method 平方取中法minimal adj最小限度的minimal volume最小体积minimum(cost)spanning tree 最小(代价)生成树mixed number 带分数mod v求余 modulus n系数,模数Motion Planning 运动规划motion多边形multi-dimentional array 多维数组multilinked list 多重链表multilist file 多重链表文件multiple adj多重的多样的,许多的 n倍数multiplication 乘法municipal 市政的NNearest Neighbor Search 最近点对查询negative ,positive 负 ,正Network Flow 网络流no special punctuation symbols or spacingrules 无特殊标点符号或间距的规则non-intersecting 非相交的; 不相交的;nonlinear structure 非线性结构notation 标记numerator分子numerical coefficient 数字系数Numerical Problems 数值问题OObesity 肥胖octal adj八进制的 binhex 十六进制odd and even 奇和偶optimal 最佳的optimally 最佳Orbit 轨道ordered pair 有序对(ordered tree 有序树)Ordinal 有次序的original equation原方程origin原点orthogonal list 十字链表Out degree 出度Over brim溢出overflow 上溢Overlapping 覆盖ox牛Ppalindrome 回文palindromic 回文的parallel 平行的parity property奇偶性partical order 偏序Pawn 禁卫军(兵)只能向前直走,每次只能走一格。但走第一步时,可以走一格或两格。兵的吃子方法与行棋方向不一样,它是直走斜吃,即如果兵的斜进一格内有对方棋子,就可以吃掉它而占据该格phyical structure 物理结构Pipe 管道Planarity Detection and Embedding 平面性检测和嵌入ploygon-shaped faces/ polygon多边形ployphase merging sort 多步归并排序Point Location 位置查询pointer field 指针域Polygon Partitioning 多边形分割positive and negative integers 正整数和负整数postorder traversal 后序遍历precision n精密,精确度精确predecessor 前趋prefix 前缀preorder traversal 先序遍历prime 质数Priority Queues 优先队列proceed 运行process v加工,处理 n程序,进程process a sequence of n distinct integers 处理一串n 个不同的整数profile 轮廓proper fraction真分数proportional 成比例的Protrusions 凸起物Pyramid 金字塔,渐增Qquadrant象限,四分之一圆Queen 皇后 横、直、斜都可以走,步数不受限制,但不能越子quotient 商Rradix sort 基数排序Random Number Generation 随机数生成random number method 随机数法Range Search 范围查询rat, ox, tiger, rabbit, dragon, snake,horse, sheep, monkey, rooster, dog pig十二生肖rate of convergence 收敛速度rear 队尾rectangular 矩形的,成直角的Relates 叙述,讲述replacement selection sort 置换选择排序respectively adj各自的,分别的,独自的robustness 鲁棒性Rook 战车 横竖均可以走,步数不受限,不能斜走。除王车易位外不能越子。rooster鸡root sign 根号round()四舍五入(当取舍位为5时,若取舍位数前的小数为奇数则直接舍弃,若为偶数则向上取舍)rounded to n decimal places 精确到小数点后n位row major order 以行为主的顺序分配Rows and columns 行与列SSatisfiability 可满足性scenario方案;(可能发生的)情况;search (sequential search) 线性查找(顺序查找)linearsearching 查找,线索segment 段;分割segment 环节; 部分;分段; 分割,划分;selection sort 选择排序semicolon n分号sequence n顺序,序列,连续serial 连续的; 连载的; 顺序排列的;series 连续的同类事物,系列series系列Set and String Problems 集合与串的问题Set Cover 集合覆盖Set Data Structures 集合Set Packing 集合配置Shape Similarity 相似多边形Shell 贝壳,脱壳shelter 遮蔽物Shortest Common Superstring 最短公共父串Shortest Path 最短路径simple cycle 简单回路(simple path 简单路径)Simplifying Polygons 多边形化简simultaneously 同时的single linked list 单链表sink 汇点solution n解决方案Solving Linear Equations 线性方程组source 源点spanning forest 生成森林spanning tree 生成树spares graph 稀疏图sparse matrix 稀疏矩阵specify 指定square root平方根square 平方,正方形,广场,方格Squared 平方Stack Overflow 堆栈溢出通常是您的程序陷入了无穷递归,或递归嵌套层数过多。statistical 统计的Steiner Tree Steiner树stem 词根String Matching 模式匹配strongly connected graph 强连通图subgraph 子图subsequent adj随后的,后来的substring 子串(subtree 子树)successor 后继sufficient 充足的;足够的;suffix 后缀Supervisor 监督人symmetric matrix 对称矩阵Ttail pointer 尾指针terminal node 终端结点Text Compression 压缩threaded binary tree 线索二叉树times乘Topological Sorting 拓扑排序toss 扔(硬币)Transitive Closure and Reduction 传递闭包transposed matrix 转置矩阵traversal of tree 树的遍历traversing binary tree 遍历二叉树traversing graph 遍历图tree index 树型索引triangle n三角形triangle inequality三角不等式Triangulation 三角剖分triple 三倍的,三方的,三部分的; 增至三倍;三倍的数[量]; 三个一组;Tromino 三格骨牌Troop 军队,组群truangular matrix 三角矩阵two adjacent sequence elements 两个相邻的元素串two-dimensional array二维数组two-dimensional 维数Uultimate 基本的,终极的unconnected graph 非连通图underflow 下溢undigraph(undirected graph) 无向图union 并集unique identifier唯一的标识符unordered pair 无序对(unordered tree 无序树)uppercase 大写字母盘;以大写字母印刷;大写字母的uppercase(Capital) 大写字母(Lowercase letters小写字母)Vvariable-aggregate data type 可变聚合数据类型variable变量Vertex Coloring 点染色(Vertex Cover 点覆盖)vertex n顶点,最高点vertical n垂直线,垂直面 adj垂直的,顶点的volume n数量,容量Voronoi Diagrams Voronoi图vulnerable 容易受到攻击的Wweakly connected graph 弱连通图weight 权weighted average 加权平均值weighted graph 加权图wooden planks 木板
2023年05月07日
184 阅读
0 评论
0 点赞
2023-05-01
Acw第 101 场周赛
总结太菜了,只能做简单题,复杂点的只能过样例 😭 ,加油吧4972. 解方程给定一个一元二次方程$$ ax^2 + bx + c = 0 $$保证给定方程有解,且恰好有两个不同的实数根。请你对该方程进行求解。一元二次方程求根公式为:$$ x = \frac{-b \pm \sqrt{b^2-4ac}}{2a} $$输入格式共一行,包含三个整数 a,b,c。输出格式共两行,第一行输出较大的根,第二行输出较小的根。结果保留六位小数。数据范围所有测试点满足 −1000≤a,b,c≤1000,保证给定方程有解,且恰好有两个不同的实数根。输入样例:1 30 200输出样例:-10.000000 -20.000000题解:这个比较简单,一次Ac#include <iostream> #include <cmath> #include <iomanip> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; double triangle = sqrt(pow(b, 2) - (4 * a * c)); double res1 = (-b + triangle) / (2 * a); double res2 = (-b - triangle) / (2 * a); if (res1 > res2) cout << fixed << setprecision(6) << res1 << endl << res2 << endl; else cout << fixed << setprecision(6) << res2 << endl << res1 << endl; return 0; }4973. 栈给定一个栈,初始时栈为空。你需要依次进行 n 个操作。每个操作给定一个由小写字母构成的非空字符串,随后进行判断:如果栈中已经包含该字符串,则将该字符串上升至栈顶,栈中其它元素的相对顺序保持不变。如果栈中还未包含该字符串,则将该字符串直接插入到栈的顶部。所有操作完成后,请你按照从栈顶到栈底的顺序,依次输出栈内所有元素。输入格式第一行包含整数 n。接下来 n 行,每行包含一个由小写字母构成的非空字符串。输出格式按照从栈顶到栈底的顺序,依次输出栈内所有元素。每个元素占一行。数据范围前 55 个测试点满足 1 ≤ n ≤ 10。所有测试点满足 1 ≤ n ≤ 2×10^5,每个给定字符串的长度范围 [1,10]。输入样例1:4 apple pear banana pear输出样例1:pear banana apple输入样例2:8 pen book eraser desk desk eraser book pen输出样例2:pen book eraser desk题解:自己题目让用stack来操作,但是需求不太好实现,就换成了vector题目中的输出样例可以过,当数据量大的时候就会Time Limit Exceeded#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<string> arr; string temp; for (int i = 0; i < n; ++i) { cin >> temp; vector<string>::iterator it = find(arr.begin(), arr.end(), temp); if (it != arr.end()) { arr.erase(it); arr.push_back(temp); } else { arr.push_back(temp); } } for (vector<string>::reverse_iterator it = arr.rbegin(); it != arr.rend(); it++) { cout << *it << endl; } return 0; }正解-逆向推导#include <iostream> #include <cstring> #include <algorithm> #include <unordered_set> using namespace std; const int N = 200010, M = 11; int n; char str[N][M]; int main() { scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%s", str[i]); unordered_set<string> hash; for (int i = n - 1; i >= 0; i -- ) if (!hash.count(str[i])) { puts(str[i]); hash.insert(str[i]); } return 0; }正解-正向做#include <iostream> #include <cstring> #include <algorithm> #include <unordered_map> using namespace std; const int N = 200010, M = 11; int n; int l[N], r[N], idx; char str[N][M]; unordered_map<string, int> pos; int insert(int k, int x) { l[x] = k, r[x] = r[k]; l[r[x]] = x, r[k] = x; } void remove(int k) { l[r[k]] = l[k]; r[l[k]] = r[k]; } int main() { l[0] = r[0] = 1; l[1] = r[1] = 0; idx = 2; scanf("%d", &n); for (int i = 0; i < n; i ++ ) { char* s = str[idx]; scanf("%s", s); if (pos.count(s)) { int k = pos[s]; remove(k); insert(0, k); } else { pos[s] = idx; insert(0, idx); idx ++ ; } } for (int i = r[0]; i != 1; i = r[i]) puts(str[i]); return 0; }4974. 最长连续子序列给定一个长度为 n 的整数序列 a1,a2,…,an。给定序列满足,任意两个相邻元素之差的绝对值不超过 1,即对于每个 1 ≤ i <= n,保证 | ai+1 − ai | ≤ 1。请你找到给定序列的一个尽可能长的连续子序列,要求该连续子序列应满足其中的最大元素与最小元素之差不超过 1。输出满足条件的最长连续子序列的长度。输入格式第一行包含整数 n。第二行包含 n 个整数 a1,a2,…,an。输出格式一个整数,表示满足条件的最长连续子序列的长度。数据范围前 6 个测试点满足 2 ≤ n ≤ 20。所有测试点满足 2 ≤ n ≤ 10^5,1 ≤ ai ≤ 10^5。输入样例1:5 1 2 3 3 2输出样例1:4输入样例2:11 5 4 5 5 6 7 8 8 8 7 6输出样例2:5题解:自己#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; const int N = 1e5 + 10; int n; int arr[N]; int main(int argc,char** argv){ int n; scanf("%d",&n); for(int i = 0; i < n; i++){ scanf("%d", &arr[i]); } int answer = 0; for(int i = 0; i < n; i++){ int startValue = arr[i]; int maxValue = startValue; int minValue = startValue; for(int start = i + 1;start < n; start++){ maxValue = arr[start] > maxValue ? arr[start] : maxValue; minValue = arr[start] < minValue ? arr[start] : minValue; int absValue = abs(maxValue - minValue); if(absValue <= 1){ answer = start - i + 1 > answer ? start - i + 1 : answer; }else{ break; } } } printf("%d",answer); }正解提取性质: 合法的序列中只会存在两个不同的元素,一个为x另一个就会为y,y=x+1 or y = x-1#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 100010; int n; int w[N], cnt[N]; int main() { scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &w[i]); int res = 0; for (int i = 0, j = 0, s = 0; i < n; i ++ ) { if (!cnt[w[i]]) s ++ ; cnt[w[i]] ++ ; while (s > 2) { cnt[w[j]] -- ; if (!cnt[w[j]]) s -- ; j ++ ; } res = max(res, i - j + 1); } printf("%d\n", res); return 0; }引用1.第 101 场周赛 竞赛 - AcWing弹幕里遇到一个很自信的同学 | AcWing第101场周赛:https://www.bilibili.com/video/BV1to4y1w71n/
2023年05月01日
218 阅读
0 评论
0 点赞
2023-05-01
Dev-C++开启对C++11的支持
做题的时候发现代码使用unordered_set后无法运行 并报错:dev c++提示[Error] #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.进行配置一下就好了
2023年05月01日
175 阅读
0 评论
0 点赞
2023-04-25
CCPC训练赛回顾
CCPC训练赛回顾时间:2023-04-25 6:30 ~ 8:30之前写算法一直用的Java,最近抽风= =,想从零开始学C++。比赛的时候前半段用的就是C++说下感受:借的电脑比赛的,只有裸机笔记本..没键鼠太麻烦了。C++还是不熟悉,题都过了一遍,不知道什么情况就是不能Ac,又换成Java过(一直没用,还好没忘!现在回顾才发现比赛的时候真是太愚蠢了!我感觉对我来说是三道简单题三道难题,关键是简单题耗时太长了,没空研究难题了呜呜呜。A. 不晔的幸运数字题目描述不晔认为1和6是幸运的数字,当一个正整数只包含1和6的时候,这个数就是幸运的。(如166、666都是幸运的数,而36、216不是)现在告诉你一个正整数a,请告诉不晔距离这个数字最近的幸运数字。输入描述输入共一行一个正整数a输出描述输出距离a最近的幸运数字(如果有两个幸运数字和a距离最近且相同,输出小的那一个)样例输入8样例输出6我的解答C++#include <iostream> #include <string> using namespace std; bool isLuckNum(int n) { for (char chr: to_string(n)) if (chr != '1' && chr != '6') return false; return true; } int main() { int a, aCopy; cin >> a; aCopy = a; int answer; while (1) { if (isLuckNum(aCopy)) { answer = aCopy; break; } aCopy++; } aCopy = a; while (1) { if (isLuckNum(aCopy)) { if (answer - a > aCopy - answer || answer - a == aCopy - answer) answer = aCopy; break; } aCopy--; } cout << answer << endl; return 0; }B.复杂去重题目描述现在有有1个长度为n的数组,求该数组中有几种数字。输入描述输入共两行。第一行一个正整数n,表示数组大小;第二行n个数为数组中元素。(1≤n≤1e3,1≤ai≤1e9)输出描述该数组中有几种数字(即数组去重后的大小)样例输入5 2 1 3 1 4样例输出4提示这题是乱序数据,但是n没有那么大了(暴力吧,少年)我的解答C++#include <iostream> #include <set> using namespace std; int main() { int n, temp; cin >> n; set<int> set1; for (int i = 0; i < n; i++) { cin >> temp; set1.insert(temp); } cout << set1.size() << endl; return 0; }Javaimport java.util.HashSet; import java.util.Set; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); Set set = new HashSet<Integer>(); for (int i = 0; i < n; i++) { int t = scanner.nextInt(); set.add(t); } System.out.println(set.size()); } }C.汉诺塔题目描述古老的汉诺塔问题是:用最少的步数将N个半径互不相等的圆盘从1号柱利用2号柱全部移动到3号柱,在移动过程中小盘永远在大盘上边。 现在再加上一个条件:不允许从1号柱直接把盘移动到3号柱, 也不允许从3号柱直接移动到1号柱。把盘按半径从小到大1——N进行编号。每种状态用N个整数表示, 第i个整数表示第i号盘所在的柱的编号。则N=2时的移动方案为(1,1)》(2,1)》(3,1)》(3,2)》(2,2)》(1,2)》(1,3)》(2,3) 》(3,3)初始状态为0步,变成求在某步数时的状态。输入描述输入文件的第一行为整数T(1<=T<=100),表示输入数据的组数。接下来的T行,每行有两个整数N,M(1<=N<=19, 0<=M<=移动N个圆盘需要的次数)输出描述输入文件一共T行对于每组输入数据,输出N个整数表示移动N个盘在M步时的状态,每两个数之间用一个空格隔开,行首和行末不要有多余的空格。样例输入3 2 0 2 1 2 2样例输出1 1 2 1 3 1D.数的反转题目描述输入一个整数,你所需要做的是将其反转,输出的仍然是一个整数输入描述第一行N表示将会有几个测试数据(N<=100);接下来的N行每行一个整数(每行得整数不超过100000000000)。输出描述输出反转之后的整数,每行一个。样例输入1 127样例输出721我的解答C++#include <iostream> #include <algorithm> #include <string> using namespace std; int main() { int n; string str; cin >> n; for (int i = 0; i < n; i++) { cin >> str; reverse(str.begin(), str.end()); int res = stoi(str); cout << res << endl; } return 0; }Javaimport java.util.Scanner; public class Main { static int reverseStr(String str) { StringBuilder sb = new StringBuilder(); for (int i = str.length() - 1; i >= 0; i--) { sb.append(str.charAt(i)); } return Integer.parseInt(sb.toString()); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); for (int i = 0; i < n; i++) { int t = scanner.nextInt(); System.out.println(reverseStr(t + "")); } } }E.拼音字母题目描述在很多软件中,输入拼音的首写字母就可以快速定位到某个词条。比如,在铁路售票软件中,输入: “bj”就可以定位到“北京”。怎样在自己的软件中实现这个功能呢?问题的关键在于:对每个汉字必须能计算出它的拼音首字母。GB2312汉字编码方式中,一级汉字的3755个是按照拼音顺序排列的。我们可以利用这个特征,对常用汉字求拼音首字母。GB2312编码方案对每个汉字采用两个字节表示。第一个字节为区号,第二个字节为区中的偏移号。为了能与已有的ASCII编码兼容(中西文混排),区号和偏移编号都从0xA1开始。我们只要找到拼音a,b,c,...x,y,z 每个字母所对应的GB2312编码的第一个汉字,就可以定位所有一级汉字的拼音首字母了(不考虑多音字的情况)。下面这个表给出了前述信息。请你利用该表编写程序,求出常用汉字的拼音首字母。a 啊 B0A1b 芭 B0C5c 擦 B2C1d 搭 B4EEe 蛾 B6EAf 发 B7A2g 噶 B8C1h 哈 B9FEj 击 BBF7k 喀 BFA6l 垃 C0ACm 妈 C2E8n 拿 C4C3o 哦 C5B6p 啪 C5BEq 期 C6DAr 然 C8BBs 撒 C8F6t 塌 CBFAw 挖 CDDAx 昔 CEF4y 压 D1B9z 匝 D4D1输入描述用户先输入一个整数n (n<100),表示接下来将有n行文本。接着输入n行中文串(每个串不超过50个汉字)。输出描述程序则输出n行,每行内容为用户输入的对应行的汉字的拼音首字母。字母间不留空格,全部使用大写字母。样例输入3 大家爱科学 北京天安门广场 软件大赛样例输出DJAKX BJTAMGC RJDSF.表格计算题目描述某次无聊中, atm 发现了一个很老的程序。这个程序的功能类似于 Excel ,它对一个表格进行操作。不妨设表格有 n 行,每行有 m 个格子。每个格子的内容可以是一个正整数,也可以是一个公式。公式包括三种:SUM(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的和。AVG(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的平均数。STD(x1,y1:x2,y2) 表示求左上角是第 x1 行第 y1 个格子,右下角是第 x2 行第 y2 个格子这个矩形内所有格子的值的标准差。标准差即为方差的平方根。方差就是:每个数据与平均值的差的平方的平均值,用来衡量单个数据离开平均数的程度。公式都不会出现嵌套。如果这个格子内是一个数,则这个格子的值等于这个数,否则这个格子的值等于格子公式求值结果。输入这个表格后,程序会输出每个格子的值。atm 觉得这个程序很好玩,他也想实现一下这个程序。输入描述第一行两个数 n, m 。接下来 n 行输入一个表格。每行 m 个由空格隔开的字符串,分别表示对应格子的内容。输入保证不会出现循环依赖的情况,即不会出现两个格子 a 和 b 使得 a 的值依赖 b 的值且 b 的值依赖 a 的值。输出描述输出一个表格,共 n 行,每行 m 个保留两位小数的实数。数据保证不会有格子的值超过 1e6 。样例输入3 2 1 SUM(2,1:3,1) 2 AVG(1,1:1,2) SUM(1,1:2,1) STD(1,1:2,2)样例输出1.00 5.00 2.00 3.00 3.00 1.48提示对于 30% 的数据,满足: n, m <= 5对于 100% 的数据,满足: n, m <= 50经验1.抓紧过一边C++的数据STL库2.对各种变量类型的范围要把控,知道什么题什么范围用什么变量最合适3.多刷题!
2023年04月25日
419 阅读
0 评论
0 点赞
2023-04-19
页面字体加密解决和csharp下的Ttf文件元信息混淆分析
页面字体加密解决和csharp下的Ttf文件元信息混淆分析1.前言之前获取获取未加密题目是通过安卓协议绕过题目解密,但需要多访问一个请求。打算重构一下旧项目,就研究一下解密问题。网上的文章都是基于python,javascript讨论实现的。对于csharp提取ttf元信息的文章 国内搜索引擎实在找不到资料,经过两天的google,还是淘到了...记录一下2.正文页面的字体文件为页头的AAEAAAAMAIAAAwBAQkFTRRuOGNgAAG+gAAAA5E9TLzKUGwCtAAABSAAAAGBWT1JHUavDeAAAcIQAAAN0Y21hcNpjHkAAAAKkAAACXGdseWY29gc2AAAG9AAAWFBoZWFkBmbCYQAAAMwAAAA2aGhlYQzu/tUAAAEEAAAAJGhtdHgQmAzYAAABqAAAAPpsb2NhABLFOAAABQAAAAH0bWF4cACmASsAAAEoAAAAIG5hbWWAs0JrAABfRAAAEDlwb3N0/4YAMgAAb4AAAAAgAAEAAAABAAD6ItY5Xw889QADA+gAAAAAz87zegAAAADP+IsO/Bj76AtwBxAAAAADAAIAAQAAAAAAAQAAA3D/iAH0A+j8GPtjC3AAAQAAAAAAAAAAAAAAAAAAAAEAAQAAAHwBKwApAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA9wBXgAFAAgCigJYAAAASwKKAlgAAAFeADIBRQAAAgsEAAAAAAAAACAAAAMq3zwQAAAAFgAAAABBREJFAYAAAf//A3D/iAH0BDEBLmAGAQcAAAAAAh8C3QAAACAABgPoAGQAMABEADgAMQA3AD8AZQA8ACQAPAA8ADMAMAAWACkAOAAxACkAPAAoADsAOgBDACoAJAA5ADUAUQAeAFgAPABRAF0ALAArADkAMgAuACIANQA3AD4AKABQAEMAIQBEACQAJwAlACwAXwA9ADYAIgAgACEAKQAlACQALwAsAC8AVQApACoAJwAqAC0AJQCKAC8AKAAoACoALwAvADsAJwA4AC4ALwArACUAXACjACIAIQAqAB8AMQAlACQAOwA5ADsAQQAqACAAKQA6ACcAMAAxADIAMQAxADAAPgArACoALABSADEAOAArAF0AOAAuAC0ALAA0ACgAAAAAAAEAAwABAAAADAAEAlAAAABcAEAABQAcVxFXFVcbVx5XIlcnVyxXL1c2VzhXPFdBV0ZXSVdNV1ZXWVdjV2VXZ1dpV3RXdleBV4pXkVefV6VXqFesV7FXs1e1V+JYClgWWE9Y2ljfWOJcvGfGa25seJ0q//8AAFcPVxRXF1cdVyBXJFcqVy5XMVc4VztXQVdFV0hXS1dSV1hXYldlV2dXaVdrV3ZXeFeHV4xXk1ekV6hXqleuV7NXtVfhWApYFlhPWNlY31jiXLxnxmtubHidKv//AAAAAAAAAAAAAAAAAAAAAAAAqOAAAKjzAAAAAAAAAAAAAAAAqP2o66i2AACo2QAAAAAAAAAAAACopAAAAACoiaiNAACoP6fwp7MAAKdhp3ajUZg/lQeTkGLmAAEAXABgAGIAagBsAHAAdgB6AHwAAACEAAAAhACGAIgAjACUAJYAAAAAAAAAkgAAAKIAtAC6AMQA3AAAANwA4AAAAAAA4gAAAAAAAADeAAAAAAAAAAAAAAAAAAAAAAABACkALwBVACQAXwA/AFAAdgAuAEcADgBhADEAJwAcAF0ADAAHABkAVABnAFYAMABeABsAPQBOADoAKwBXAFkAIQB0AD4ANgBbAHMARABgAFwAUwAWADIAbQBlAAsAUQBjABEAegAJAHkAKgBNAGwAIwBIABcAcQB3ACgALQBBABMAaABwAGYANwByABUAOwBDABQAbwAzAB4ACgAdAHsASwBaAEoADwAmACUAAwAiAGkAbgBGACwAGgAEAGoARQBrADgANQASADkAeABkACAAAAAAAAAAWAAAAHQAAACsAAAA3AAAATAAAAGMAAACOAAAApAAAALoAAADjAAAA7QAAAQcAAAEwAAABVgAAAX8AAAGyAAAB0gAAAfQAAAIgAAACRwAAAnoAAAKtAAACugAAAuoAAAMDAAADNQAAA2kAAAOLAAADpgAAA8oAAAPmAAAECQAABEEAAARgAAAEfgAABJoAAATGAAAE5QAABRkAAAVKAAAFYgAABYwAAAWtAAAFzAAABekAAAYJAAAGIgAABk0AAAZ/AAAGqgAABswAAAcFAAAHNwAAB3cAAAejAAAHxQAAB/cAAAgwAAAIZgAACI4AAAjHAAAI8wAACSAAAAleAAAJggAACagAAAnRAAAKCQAACkAAAAp/AAAKxgAACusAAAsRAAALRAAAC3cAAAvKAAAL8wAADBcAAAx4AAAMswAADMoAAAz6AAANJQAADVgAAA17AAANpwAADbkAAA35AAAOMQAADm8AAA6wAAAO5wAADy0AAA9eAAAPegAAD6wAAA/XAAAQFAAAEFcAABCIAAAQvAAAENgAABEzAAARXAAAEZcAABHaAAASHgAAElQAABKQAAASvwAAEu0AABMgAAATXgAAE5EAABPVAAAT/wAAFDUAABRjAAAUnwAAFPEAABVFAAAVjAAAFeMAABYUAAFAGT/iAOEA3AAAwAGAAkADAAP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G0ZNlBAijUlCGP7iASUJBUUECwII/qeJTjxjsAsLJgJzRFAkTz/9cxYVSRQHWB8gFhc/DjspJA80TAF524aTXBsdTYd6yj9ekgJ/bz/+vniRGbWPPx0JCQAAACUBwgABAAAAAAAAAEAAAAABAAAAAAABABkAbgABAAAAAAACAAcAQAABAAAAAAADACcARwABAAAAAAAEABkAbgABAAAAAAAFADYAhwABAAAAAAAGABYAUgABAAAAAAAHAGAAvQABAAAAAAAIABoCigABAAAAAAAJAMMBHQABAAAAAAAKAIAB4AABAAAAAAALABoCYAABAAAAAAANAjkCegABAAAAAAAOAC8DTwABAAAAAAAQABIAbgABAAAAAAARAAYAYgADAAEECQAAAIIEswADAAEECQABADIFNQADAAEECQACAA4OTQADAAEECQADAE4FZwADAAEECQAEADIFNQADAAEECQAFAGwFtQADAAEECQAGACwFfQADAAEECQAHAMAGIQADAAEECQAIADQJ+wADAAEECQAJAboG4QADAAEECQAKAQoImwADAAEECQALADQJpQADAAEECQANBHQJ2QADAAEECQAOAF4LhQADAAEECQAQACQFNQADAAEECQARAAwFnQADAAEIBAABAAgOWwADAAEIBAACAA4OTQADAAEIBAAEABwOWwADAAEIBAAQAA4OWwADAAEIBAARAAwFnUNvcHlyaWdodCA/MjAxNCBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZC4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5SZWd1bGFyMS4wMDA7QURCRTtTb3VyY2VIYW5TYW5zQ04tTm9ybWFsO0FET0JFU291cmNlIEhhbiBTYW5zIENOIE5vcm1hbFZlcnNpb24gMS4wMDA7UFMgMTtob3Rjb252IDEuMC43ODttYWtlb3RmLmxpYjIuNS42MTkzMFNvdXJjZSBpcyBhIHRyYWRlbWFyayBvZiBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZCBpbiB0aGUgVW5pdGVkIFN0YXRlcyBhbmQvb3Igb3RoZXIgY291bnRyaWVzLlJ5b2tvIE5JU0hJWlVLQSAoa2FuYSAmIGlkZW9ncmFwaHMpOyBQYXVsIEQuIEh1bnQgKExhdGluLCBHcmVlayAmIEN5cmlsbGljKTsgV2VubG9uZyBaSEFORyAoYm9wb21vZm8pOyBTYW5kb2xsIENvbW11bmljYXRpb24sIFNvby15b3VuZyBKQU5HICYgSm9vLXllb24gS0FORyAoaGFuZ3VsIGVsZW1lbnRzLCBsZXR0ZXJzICYgc3lsbGFibGVzKURyLiBLZW4gTHVuZGUgKHByb2plY3QgYXJjaGl0ZWN0LCBnbHlwaCBzZXQgZGVmaW5pdGlvbiAmIG92ZXJhbGwgcHJvZHVjdGlvbik7IE1hc2F0YWthIEhBVFRPUkkgKHByb2R1Y3Rpb24gJiBpZGVvZ3JhcGggZWxlbWVudHMpaHR0cDovL3d3dy5hZG9iZS5jb20vdHlwZS9Db3B5cmlnaHQgPzIwMTQgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAuaHRtbCAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4gIABDAG8AcAB5AHIAaQBnAGgAdAAgAKkAIAAyADAAMQA0ACAAQQBkAG8AYgBlACAAUwB5AHMAdABlAG0AcwAgAEkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkAC4AIABBAGwAbAAgAFIAaQBnAGgAdABzACAAUgBlAHMAZQByAHYAZQBkAC4AUwBvAHUAcgBjAGUAIABIAGEAbgAgAFMAYQBuAHMAIABDAE4AIABOAG8AcgBtAGEAbAAxAC4AMAAwADAAOwBBAEQAQgBFADsAUwBvAHUAcgBjAGUASABhAG4AUwBhAG4AcwBDAE4ALQBOAG8AcgBtAGEAbAA7AEEARABPAEIARQBWAGUAcgBzAGkAbwBuACAAMQAuADAAMAAwADsAUABTACAAMQA7AGgAbwB0AGMAbwBuAHYAIAAxAC4AMAAuADcAOAA7AG0AYQBrAGUAbwB0AGYALgBsAGkAYgAyAC4ANQAuADYAMQA5ADMAMABTAG8AdQByAGMAZQAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGkAbgAgAHQAaABlACAAVQBuAGkAdABlAGQAIABTAHQAYQB0AGUAcwAgAGEAbgBkAC8AbwByACAAbwB0AGgAZQByACAAYwBvAHUAbgB0AHIAaQBlAHMALgBSAHkAbwBrAG8AIABOAEkAUwBIAEkAWgBVAEsAQQAgiX9YWm28W1AAIAAoAGsAYQBuAGEAIAAmACAAaQBkAGUAbwBnAHIAYQBwAGgAcwApADsAIABQAGEAdQBsACAARAAuACAASAB1AG4AdAAgACgATABhAHQAaQBuACwAIABHAHIAZQBlAGsAIAAmACAAQwB5AHIAaQBsAGwAaQBjACkAOwAgAFcAZQBuAGwAbwBuAGcAIABaAEgAQQBOAEcAIF8gZYefmQAgACgAYgBvAHAAbwBtAG8AZgBvACkAOwAgAFMAYQBuAGQAbwBsAGwAIABDAG8AbQBtAHUAbgBpAGMAYQB0AGkAbwBuACDAsLPMzuS7pLLIzwDHdMFYACwAIABTAG8AbwAtAHkAbwB1AG4AZwAgAEoAQQBOAEcAIMelwhjGAQAgACYAIABKAG8AbwAtAHkAZQBvAG4AIABLAEEATgBHACCsFcj8xfAAIAAoAGgAYQBuAGcAdQBsACAAZQBsAGUAbQBlAG4AdABzACwAIABsAGUAdAB0AGUAcgBzACAAJgAgAHMAeQBsAGwAYQBiAGwAZQBzACkARAByAC4AIABLAGUAbgAgAEwAdQBuAGQAZQAgACgAcAByAG8AagBlAGMAdAAgAGEAcgBjAGgAaQB0AGUAYwB0ACwAIABnAGwAeQBwAGgAIABzAGUAdAAgAGQAZQBmAGkAbgBpAHQAaQBvAG4AIAAmACAAbwB2AGUAcgBhAGwAbAAgAHAAcgBvAGQAdQBjAHQAaQBvAG4AKQA7ACAATQBhAHMAYQB0AGEAawBhACAASABBAFQAVABPAFIASQAgZw2Q6GtjjLQAIAAoAHAAcgBvAGQAdQBjAHQAaQBvAG4AIAAmACAAaQBkAGUAbwBnAHIAYQBwAGgAIABlAGwAZQBtAGUAbgB0AHMAKQBoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwB0AHkAcABlAC8AQwBvAHAAeQByAGkAZwBoAHQAIACpACAAMgAwADEANAAgAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZAANAAoATABpAGMAZQBuAHMAZQBkACAAdQBuAGQAZQByACAAdABoAGUAIABBAHAAYQBjAGgAZQAgAEwAaQBjAGUAbgBzAGUALAAgAFYAZQByAHMAaQBvAG4AIAAyAC4AMAAgACgAdABoAGUAIAAiAEwAaQBjAGUAbgBzAGUAIgApADsAIAB5AG8AdQAgAG0AYQB5ACAAbgBvAHQAIAB1AHMAZQAgAHQAaABpAHMAIABmAGkAbABlACAAZQB4AGMAZQBwAHQAIABpAG4AIABjAG8AbQBwAGwAaQBhAG4AYwBlACAAdwBpAHQAaAAgAHQAaABlACAATABpAGMAZQBuAHMAZQAuACAAWQBvAHUAIABtAGEAeQAgAG8AYgB0AGEAaQBuACAAYQAgAGMAbwBwAHkAIABvAGYAIAB0AGgAZQAgAEwAaQBjAGUAbgBzAGUAIABhAHQAIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBwAGEAYwBoAGUALgBvAHIAZwAvAGwAaQBjAGUAbgBzAGUAcwAvAEwASQBDAEUATgBTAEUALQAyAC4AMAAuAGgAdABtAGwADQAKAFUAbgBsAGUAcwBzACAAcgBlAHEAdQBpAHIAZQBkACAAYgB5ACAAYQBwAHAAbABpAGMAYQBiAGwAZQAgAGwAYQB3ACAAbwByACAAYQBnAHIAZQBlAGQAIAB0AG8AIABpAG4AIAB3AHIAaQB0AGkAbgBnACwAIABzAG8AZgB0AHcAYQByAGUAIABkAGkAcwB0AHIAaQBiAHUAdABlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEwAaQBjAGUAbgBzAGUAIABpAHMAIABkAGkAcwB0AHIAaQBiAHUAdABlAGQAIABvAG4AIABhAG4AIAAiAEEAUwAgAEkAUwAiACAAQgBBAFMASQBTACwAIABXAEkAVABIAE8AVQBUACAAVwBBAFIAUgBBAE4AVABJAEUAUwAgAE8AUgAgAEMATwBOAEQASQBUAEkATwBOAFMAIABPAEYAIABBAE4AWQAgAEsASQBOAEQALAAgAGUAaQB0AGgAZQByACAAZQB4AHAAcgBlAHMAcwAgAG8AcgAgAGkAbQBwAGwAaQBlAGQALgAgAFMAZQBlACAAdABoAGUAIABMAGkAYwBlAG4AcwBlACAAZgBvAHIAIAB0AGgAZQAgAHMAcABlAGMAaQBmAGkAYwAgAGwAYQBuAGcAdQBhAGcAZQAgAGcAbwB2AGUAcgBuAGkAbgBnACAAcABlAHIAbQBpAHMAcwBpAG8AbgBzACAAYQBuAGQAIABsAGkAbQBpAHQAYQB0AGkAbwBuAHMAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEwAaQBjAGUAbgBzAGUALgANAAoAUgBlAGcAdQBsAGEAcmAdbpCe0U9TACAAQwBOACAATgBvAHIAbQBhAGwAAAAAAwAAAAAAAP+DADIAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACABEAAQAFgAEaWNmYmljZnRpZGVvcm9tbgAGREZMVABiY3lybABoZ3JlawBoaGFuaQBia2FuYQBibGF0bgBoAAQAFgAEaWNmYmljZnRpZGVvcm9tbgAGREZMVAAyY3lybAA4Z3JlawA4aGFuaQAya2FuYQAybGF0bgA4ABgAAAAAAB4AAAAAACQAAAAAACoAAAAAAAIABAAwADQAOAA8AAMABAAkACgALAAwAAIABAAoACwAJAAwAAMABAAcACAAGAAkAAH/uAABA0AAAf+IAAEAAAABADAAAQO4AAEAeAABAAADcADbAdoDYgHqA2IB6wNpAewDYgHuAosB7wOBAfIDYQH0A2gB9QNaAfYD0gH5A2IB+gNhAfsDYQH8A2EB/QNhAf4DYQH/A2ECAANhAgEDYQICA2ECAwNhAgQDYQIFA2ECCgMBAg8DAQK1A1ECtgNYArcDWAK4A1ECuQNRAroDWAK7A1ECvANYAr0DWAK+A1gCvwNRAsADWALBA1gCwgNRAsMDUQLEA1gCxQNRAsYDWALHA1gCyANYBJwFZASdBWQHGALoBxkCjgcaA1wHGwNiB70DXAe/A1wHwAKeB8IDoQfDA6EHxANcB8oC+AfLA2IHzAL6B80DYgfPA2IH0ANiB9EDYgfUAvgH1QNiB9YC+gfXAo4H2AKOB9kC+QfaA2IH3ANiB90DYgfeA2IH3wMhB+ADggfhA4IH4gOCB+MDegfkAwgH5QKgB+YDCAfnAwIH6QOoB+oDoQfrA6gH7AOoB+0DqAfuA6EH7wOoB/ADqAfxAyYH8gNOB/MDXAf1A1wH9gNiB/gDBgf5AwYH+gKeB/sDAgf8AqEH/QMCB/4C+Af/A2IIAAL6CAEDYggDA2IIBAL4CAUDYggGAvoIBwNiCAkDYggLA2gIDAMCCA0C+AgOAwIIEAMGCBEDYggTAvwIFQNiCBYDdQgXA2IIGANiCBwC+QghAvgIIgKeCCMDYggkA2IIJQMCCCYDYggoAyYIKQMmCEkC+XQrA1p0LQNidDcDYnQ4A2J0OQNodDoDYnQ7A2J0PANcdD0DYnQ+A2J0PwNidEADYnRIA2J0SQNidEoDYnRLA2J0TANidE0DYnROA2J0TwNidFADYnRRA1x0UgNidFMDYnRUA2J0VQNidFYDYnRXA2J0WAMOdFkDYnRaA2J0WwNidFwDXHRdA2J0XgNidF8DYnRgA2J0YQNidGgDAnRpA3x0agMCdGsDfHRsAwJ0bQOIdG4Ci3RvA4J0cAN8dHEDAXRyA4J0cwN8dHQDCXR1Awl0dgMCdHcClXR4ApV0eQMIdHoDAnR7A0l0fAL8dH0DAnR+AwJ0fwMCdIACjHSBAwJ0+QNfdPoDYXT+A1t0/wNbdQYDWHUHAwF1CAL6dQkDAXUKAwF1CwL6dQwC+nUNAwF1DgL6dQ8DAXUQAwF1jANcd1sFZHdcB1h3ZP+Id2X/iHdn/4h3aP+I根据【本文末 - 引用1】的分析,得知页面的字体文件与原版的区别在于 修改了每个图元数据的unicode因为图元数据是和原版一致的,所以大概思路为根据加密后的图元数据 去 原版字体中查询,将查询到的unicode替换掉混淆的unicode即可3.解决思路梳理3.1 原版字体建立Map解决思路就是根据原版字体文件 建立 map,后进行k,v翻转// 将原生字体key => value 反向映射 var swappedDict = new Dictionary<string, string>(); foreach (var swappedTempDict in Context.OriginFontsDictionary) { swappedDict[swappedTempDict.Value] = swappedTempDict.Key; }3.2 修改版字体建立Map将页面上的base64编码的ttf文件读取并建立 Mapvar keyHex = "uni" + kvp.Key.ToString("X").ToUpper(); var fontGlyph = font.GetGlyph(kvp.Value); var sb = new StringBuilder(); foreach (var fontGlyphGlyphPoint in fontGlyph.GlyphPoints) { sb.Append( $"{fontGlyphGlyphPoint.X}{fontGlyphGlyphPoint.Y}{(fontGlyphGlyphPoint.onCurve ? "1" : "0")}"); } unicodeAndContourPair[keyHex] = CommonUtil.GetMd5(sb.ToString()); /** * 数据类型如下: * Key = uniXXXX * Value = 每个 pt 标签的x,y,on属性拼接进行求Md5 * */3.3 建立正确的映射关系根据 修改版字体建立的Map 进行遍历// 遍历 unicodeAndContourPair 获取所有的 values 也就是 contour 下 pt标签的x,y,on属性加密后的md5 // 还记得吗? unicodeAndContourPaire的 values 都可以在 原版Map 也就是 swappedDict 的 Keys中找到 // swappedDict 中 values 就是真正字体的 unicode 值! // 遍历加密的 pair var keysList = new Dictionary<string, string>(); foreach (var keyValue in unicodeAndContourPair) { keysList[keyValue.Key] = swappedDict[keyValue.Value].Replace("uni", "\\u"); keysList[keyValue.Key] = Regex.Unescape(keysList[keyValue.Key]); } // 此时得到的 keysList 中 keys 为 加密的每个字的unicode, values为真正的字3.4 题目处理var questionTitle = questionNodes[0].SelectSingleNode("div[@class='Zy_TItle clearfix']/div").InnerText.Trim(); foreach (var c in questionTitle.ToCharArray()) { var temp = Convert.ToString(Convert.ToUInt32(c), 16).Replace("0x", "").ToUpper(); // 拿到当前字符的 unicode 编码 if (keysList.ContainsKey($"uni{temp}")) questionTitle = questionTitle.Replace(c + "", keysList[$"uni{temp}"]); }此时题目还是不可以直接用,结合易姐博客的文章经过查阅资料,我发现这种和普通汉字字形相同,但是 unicode 内码不同的字叫做康熙部首,它位于 unicode 的 2F00—2FDF 区段,当然它们和普通的汉字一一对应,出现此误码的原因可能是一些字体厂家没有把这两种编码的字形做区分那么再次对题目进行清洗,将康熙部首替换为正常汉字即可# 康熙部首替换表 KX_RADICALS_TAB = str.maketrans( # 康熙部首 "⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼髙⾽⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕⺠⻬⻩⻢⻜⻅⺟⻓", # 对应汉字 "一丨丶丿乙亅二亠人儿入八冂冖冫几凵刀力勹匕匚匸十卜卩厂厶又口囗土士夂夊夕大女子宀寸小尢尸屮山巛工己巾干幺广廴廾弋弓彐彡彳心戈戶手支攴文斗斤方无日曰月木欠止歹殳毋比毛氏气水火爪父爻爿片牙牛犬玄玉瓜瓦甘生用田疋疒癶白皮皿目矛矢石示禸禾穴立竹米糸缶网羊羽老而耒耳聿肉臣自至臼舌舛舟艮色艸虍虫血行衣襾見角言谷豆豕豸貝赤走足身車辛辰辵邑酉采里金長門阜隶隹雨青非面革韋韭音頁風飛食首香馬骨高高髟鬥鬯鬲鬼魚鳥鹵鹿麥麻黃黍黑黹黽鼎鼓鼠鼻齊齒龍龜龠民齐黄马飞见母长" )转为 c#:// 康熙部首 const string source = "⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼髙⾽⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕⺠⻬⻩⻢⻜⻅⺟⻓"; // 对应汉字 const string target = "一丨丶丿乙亅二亠人儿入八冂冖冫几凵刀力勹匕匚匸十卜卩厂厶又口囗土士夂夊夕大女子宀寸小尢尸屮山巛工己巾干幺广廴廾弋弓彐彡彳心戈戶手支攴文斗斤方无日曰月木欠止歹殳毋比毛氏气水火爪父爻爿片牙牛犬玄玉瓜瓦甘生用田疋疒癶白皮皿目矛矢石示禸禾穴立竹米糸缶网羊羽老而耒耳聿肉臣自至臼舌舛舟艮色艸虍虫血行衣襾見角言谷豆豕豸貝赤走足身車辛辰辵邑酉采里金長門阜隶隹雨青非面革韋韭音頁風飛食首香馬骨高高髟鬥鬯鬲鬼魚鳥鹵鹿麥麻黃黍黑黹黽鼎鼓鼠鼻齊齒龍龜龠民齐黄马飞见母长"; for (int i = 0; i < questionTitle.Length; i++) { int index = source.IndexOf(questionTitle[i]); if (index >= 0) { questionTitle = questionTitle.Remove(i, 1).Insert(i, target[index].ToString()); } }3.5 总结项目引入了 PresentationCore.dll,Typography.OpenFonttry { // 8. 提取当前页面加密的base64代码 var matchBase64 = Regex.Match(workPageResponse, @"font-cxsecret';src:url\('(.*?)'\)"); var fontBytes = Convert.FromBase64String(matchBase64.Groups[1].Value.Split(',')[1]); // 将字节写到目录的cache文件夹下 var fontFilename = $"{Path.GetRandomFileName()}.ttf"; var fontPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache", fontFilename); if (!Directory.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache"))) { Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache")); } File.WriteAllBytes(fontPath, fontBytes); var fontReader = new OpenFontReader(); var font = fontReader.Read(new MemoryStream(fontBytes)); var unicodeAndContourPair = new Dictionary<string, string>(); // 将原生字体key => value 反向映射 var swappedDict = new Dictionary<string, string>(); foreach (var swappedTempDict in Context.OriginFontsDictionary) { swappedDict[swappedTempDict.Value] = swappedTempDict.Key; } var families = Fonts.GetFontFamilies(fontPath); foreach (var family in families) { var typefaces = family.GetTypefaces(); foreach (var typeface in typefaces) { typeface.TryGetGlyphTypeface(out var glyph); var characterMap = glyph.CharacterToGlyphMap; foreach (var kvp in characterMap) { var keyHex = "uni" + kvp.Key.ToString("X").ToUpper(); var fontGlyph = font.GetGlyph(kvp.Value); var sb = new StringBuilder(); foreach (var fontGlyphGlyphPoint in fontGlyph.GlyphPoints) { sb.Append( $"{fontGlyphGlyphPoint.X}{fontGlyphGlyphPoint.Y}{(fontGlyphGlyphPoint.onCurve ? "1" : "0")}"); } unicodeAndContourPair[keyHex] = CommonUtil.GetMd5(sb.ToString()); } } } // 遍历加密的 pair var keysList = new Dictionary<string, string>(); foreach (var keyValue in unicodeAndContourPair) { keysList[keyValue.Key] = swappedDict[keyValue.Value].Replace("uni", "\\u"); keysList[keyValue.Key] = Regex.Unescape(keysList[keyValue.Key]); } var questionTitle = questionNodes[0].SelectSingleNode("div[@class='Zy_TItle clearfix']/div").InnerText.Trim(); foreach (var c in questionTitle.ToCharArray()) { var temp = Convert.ToString(Convert.ToUInt32(c), 16).Replace("0x", "").ToUpper(); if (keysList.ContainsKey($"uni{temp}")) questionTitle = questionTitle.Replace(c + "", keysList[$"uni{temp}"]); } // 康熙部首 const string source = "⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼髙⾽⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕⺠⻬⻩⻢⻜⻅⺟⻓"; // 对应汉字 const string target = "一丨丶丿乙亅二亠人儿入八冂冖冫几凵刀力勹匕匚匸十卜卩厂厶又口囗土士夂夊夕大女子宀寸小尢尸屮山巛工己巾干幺广廴廾弋弓彐彡彳心戈戶手支攴文斗斤方无日曰月木欠止歹殳毋比毛氏气水火爪父爻爿片牙牛犬玄玉瓜瓦甘生用田疋疒癶白皮皿目矛矢石示禸禾穴立竹米糸缶网羊羽老而耒耳聿肉臣自至臼舌舛舟艮色艸虍虫血行衣襾見角言谷豆豕豸貝赤走足身車辛辰辵邑酉采里金長門阜隶隹雨青非面革韋韭音頁風飛食首香馬骨高高髟鬥鬯鬲鬼魚鳥鹵鹿麥麻黃黍黑黹黽鼎鼓鼠鼻齊齒龍龜龠民齐黄马飞见母长"; for (var i = 0; i < questionTitle.Length; i++) { var index = source.IndexOf(questionTitle[i]); if (index >= 0) { questionTitle = questionTitle.Remove(i, 1).Insert(i, target[index].ToString()); } } } catch (Exception e) { Console.WriteLine(e); throw; }4.引用关于超星学习通网页版字体加密分析 (出处: 吾爱破解论坛):https://www.52pojie.cn/thread-1631357-1-1.htmlLayoutFarm/Typography: C# Font Reader (TrueType / OpenType / OpenFont / CFF / woff / woff2) , Glyphs Layout and Rendering (github.com):https://github.com/LayoutFarm/Typography研究学习通答题字体加密的随笔 - 易姐的博客 (shakaianee.top):https://shakaianee.top/archives/558/presentationcore.dll free download | DLL‑files.com (dll-files.com): https://www.dll-files.com/presentationcore.dll.html
2023年04月19日
253 阅读
1 评论
0 点赞
2023-03-31
山西省成人高考成绩批量查询工具
目标站点:https://gkpt.sxkszx.cn/Ck-student-web/#一、步骤分析1.登录的时候有个验证码需要过2.成绩查询是html解析,正则匹配一下就取出来了二、工具及源码技术点:网络爬虫,dataGridView导出为excel适合初学者入门学习和二次开发github链接:https://github.com/lisongkun/shanxi-adult-education-batch-query-score引用1.SunnyUI Github:https://github.com/yhuse/SunnyUI2.C# Winform中DataGridView导出为Excel看这一篇就够了,详细!!!(完整快速版):https://blog.csdn.net/Houoy/article/details/1060278793.Fluent HTTP:https://flurl.dev/docs/fluent-http/
2023年03月31日
285 阅读
0 评论
1 点赞
2023-02-17
homestead中如何切换某应用环境变量对应的版本?
在Homestead中切换PHP环境变量对应的版本可以通过以下步骤完成:登录到Homestead虚拟机中,可以使用如下命令登录:vagrant ssh执行以下命令查看Homestead中已经安装的PHP版本:update-alternatives --display php执行后,会列出Homestead中已经安装的PHP版本以及它们的路径。执行以下命令来切换PHP环境变量对应的版本:sudo update-alternatives --set php /usr/bin/phpX.X其中,X.X是你想要切换到的PHP版本号,比如如果你想切换到PHP 7.4版本,命令应该是:sudo update-alternatives --set php /usr/bin/php7.4切换成功后,执行以下命令查看PHP版本是否已经切换:php -v执行后,会显示当前PHP版本号,如果版本号是你想要的版本,则切换成功。
2023年02月17日
192 阅读
0 评论
0 点赞
2023-01-29
selenium爬虫如何防止被浏览器特征抓取反爬
前言爬网站的时候遇到了cf拦截,根据百度到的尝试添加参数还是无法跳过service = Service('msedgedriver.exe') options = Options() # 开启开发者模式 options.add_experimental_option('excludeSwitches', ['enable-automation']) # 禁用Blink运行时功能 options.add_argument('--disable-blink-features=AutomationControlled') driver = webdriver.Edge(service=service)undetected-chromedriverOptimized Selenium Chromedriver patch which does not trigger anti-bot services like Distill Network / Imperva / DataDome / Botprotect.io Automatically downloads the driver binary and patches it.Tested until current chrome beta versionsWorks also on Brave Browser and many other Chromium based browsers, some tweakingPython 3.6++**我主要使用的Edge,介绍说会自动下载Chrome,并没有体验到,于是自己安装了Chrome浏览器代码跟之前selenium的相差不大,成功解决了问题,再没出现过Cf拦截from pyquery import PyQuery as pq import re import time from undetected_chromedriver import ChromeOptions import undetected_chromedriver as uc options = ChromeOptions() options.add_argument('--headless') options.add_argument('--disable-gpu') driver = uc.Chrome(options=options) driver.get('http://...') html_source = driver.page_source doc = pq(html_source) titles = doc.find('tag')引用1.ultrafunkamsterdam/undetected-chromedriver:https://github.com/ultrafunkamsterdam/undetected-chromedriver2.Chrome Headless Detection (Round II):https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html3.selenium爬虫如何防止被浏览器特征抓取反爬,undetected_chromedriver他来了。:https://blog.csdn.net/wywinstonwy/article/details/118479162
2023年01月29日
876 阅读
0 评论
0 点赞
2023-01-18
Laravel+Scout+Elasticsearch实现中文分词搜索功能
一、准备工作1.配置机器ssh连接sudo apt update sudo apt install openssh-server # ssh二、Docker安装ElasticSearch2.1 安装说明在平时工作的时候,开发环境大多数会安装单机ElasticSearch,但生产环境基本会安装ElasticSearch集群版。不过中文搜索,会实现分词器集成,可以采用IK分词器。ElasticSearch采用Kibana实现数据可视化分析也是当前主流,所以我们除了安装ElasticSearch和IK分词器外,还需要安装Kibana。安装实践:1:ElasticSearch单机安装 2:IK分词器安装 3:Kibana安装 2.2 Docker安装ElasticSearch当前ElasticSearch已经到了8.0,新版本都有很多新特性,性能和功能都有大幅提升,我们建议使用较高版本,这里将采用8.6.0版本。 2.2.1 网络创建高版本安装Kibana的时候需要和ElasticSearch在同一网段内,所以采用docker安装首先要确认网段,为了方便操作,我们直接创建一个网络,创建脚本如下:sudo docker network create elastic-series2.2.2 ElasticSearch安装安装ElasticSearch脚本如下:sudo docker run -d \ --name elasticsearch \ -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ -e "discovery.type=single-node" \ -v es-data:/usr/share/elasticsearch/data \ -v es-plugins:/usr/share/elasticsearch/plugins \ --privileged \ --network elastic-series \ -p 9200:9200 \ -p 9300:9300 \ elasticsearch:8.6.0命令说明:-e "cluster.name=es-docker-cluster":设置集群名称-e "http.host=0.0.0.0":监听的地址,可以外网访问-e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小-e "discovery.type=single-node":非集群模式-v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定elasticsearch的数据目录-v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定elasticsearch的日志目录-v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定elasticsearch的插件目录--privileged:授予逻辑卷访问权--network elastic-series :加入一个名为elastic-series的网络中-p 9200:9200:端口映射配置Docker安装ElasticSearch下载可能会比较慢,需要耐心等待,效果如下:安装完成后,在浏览器中输入:http://192.168.211.128:9200/即可看到elasticsearch的响应结果:You can Generate a new password using/usr/share/elasticsearch/elasticsearch-setup-passwords auto/interactiveinteractive is where you will have to enter password for all user.auto will just print passwords on the shell.elseYou can turn off x-pack security in elasticsearch.yml2.2.2.1 关闭安全验证1.进入容器内部sudo docker exec -it -u root <container> bash2.安装Vim,为编辑文件做准备apt-get update apt-get install vim3.编辑config/elasticsearch.yml# 追加 xpack.security.enabled: false4.退出并重启容器exit sudo docker restart <container>刷新页面,得到正常响应 3 安装Kibana我们可以基于Http请求操作ElasticSearch,但基于Http操作比较麻烦,我们可以采用Kibana实现可视化操作。2.2.2.2 设置密码详见引用第九条三、Docker安装Kibana3.1 Kibana介绍Kibana 是一个免费且开放的用户界面,能够让您对 Elasticsearch 数据进行可视化,并让您在 Elastic Stack 中进行导航。您可以进行各种操作,从跟踪查询负载,到理解请求如何流经您的整个应用,都能轻松完成。Kibana 让您能够自由地选择如何呈现自己的数据。不过借助 Kibana 的交互式可视化,您可以先从一个问题出发,看看能够从中发现些什么。 可视化界面如下: 3.2 Kibana安装使用Docker安装Kibana非常简单,只需要执行如下命令即可,但是执行命令需要注意Kibana操作的ElasticSearch地址,因为Kibana是需要连接ElasticSearch进行操作的,命令如下:sudo docker run -d \ --name kibana \ -e ELASTICSEARCH_HOSTS=http://192.168.211.128:9200 \ --network elastic-series \ -p 5601:5601 \ kibana:8.6.0命令说明:--network elastic-series :加入一个名为elastic-series的网络中,与elasticsearch在同一个网络中-e ELASTICSEARCH_HOSTS=http://192.168.211.128:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch,也可以写IP地址实现访问。-p 5601:5601:端口映射配置安装的时候如果没有镜像,会下载镜像,效果如下:kibana安装会比较耗时间,也需要耐心等待下载安装完成,如果想实时知道服务安装运行的状态,可以通过查看日志实现,查看日志如下:docker logs -f kibana日志中如果出现了http://0.0.0.0:5601即可访问Kibana后台服务,日志如下:访问http://192.168.211.128:5601效果如下:可以点击Add integrations,添加示例数据,如下图,随意选一个即可,不选其实也是可以的。 3.3 Kibana中文配置我们发现Kibana是英文面板,看起来不是很方便,但Kibana是支持中文配置,所以我们可以把Kibana配置成中文版,便于我们操作。切换中文操作如下:#进入容器 docker exec -it kibana /bin/bash #进入配置文件目录 cd /usr/share/kibana/config #编辑文件kibana.yml vi kibana.yml #在最后一行添加如下配置 i18n.locale: zh-CN #保存退出 exit #并重启容器 docker restart kibana 等待Kibana容器启动,再次访问http://192.168.211.128:5601/效果如下: 四、IK分词器安装我们打开Kibana,点击开发工具,操作如下:输入如下操作,用于查询分词:上图测试代码如下:GET _analyze { "analyzer": "standard", "text": "过去无可挽回,未来可以改变" }表示使用standard对过去无可挽回,未来可以改变进行分词。分词:提取一句话或者一篇文章中的词语。我们在使用ElasticSearch的时候,默认用standard分词器,但standard分词器使用的是按空格分词,这种分词操作方法不符合中文分词标准,我们需要额外安装中文分词器。 4.1 IK分词器介绍IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始, IKAnalyzer已经推出了多个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。IK Analyzer则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。 ElasticSearch内核其实就是基于Lucene,所以我们可以直接在ElasticSearch中集成IK分词器,IK分词器集成ElasticSearch下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases 4.2 IK分词器配置下载安装包elasticsearch-analysis-ik-8.6.0.zip后,并解压,目录如下:我们只需要将上面ik拷贝到ElasticSearch的plugins目录中即可,但由于当前服务采用的是docker安装,所以需要将文件拷贝到docker容器的plugins目录才行。操作如下:#将ik文件夹拷贝到elasticsearch容器中 docker cp ik elasticsearch:/usr/share/elasticsearch/plugins #重启容器 docker restart elasticsearch操作效果如下: 4.3 分词测试IK分词器包含两种模式:ik_smart:最少切分ik_max_word:最细切分 前面使用默认的standard分词器,对中文分词非常难用,安装IK分词器后,我们可以使用IK分词器测试,测试代码如下:GET /_analyze { "analyzer": "ik_max_word", "text": "过去无可挽回,未来可以改变" }测试效果如下:我们可以发现对中文的分词效果是比较不错的,但也存在一些不足,比如无可挽回我们希望它是一个词,而可挽回我们希望它不被识别一个词,又该如何实现呢?自定义词典参考引用中的第2个链接五、Laravel集成使用的第三方包matchish/laravel-scout-elasticsearch:https://github.com/matchish/laravel-scout-elasticsearch名称版本php^8.0.2laravel/framework^9.19matchish/laravel-scout-elasticsearch^6.05.1 介绍Laravel Scout 为 Eloquent 模型 的全文搜索提供了一个简单的基于驱动程序的解决方案,通过使用模型观察者,Scout 将自动同步 Eloquent 记录的搜索索引。目前,Scout 附带 Algolia、MeiliSearch 和 MySQL / PostgreSQL (database) 驱动程序。此外,Scout 包括一个「collection」驱动程序,该驱动程序专为本地开发使用而设计,不需要任何外部依赖项或第三方服务。此外,编写自定义驱动程序很简单,你可以使用自己的搜索实现自由扩展 Scout。由于没有自带Elasticsearch的驱动,所以需要第三方包5.1 安装包和配置1.引入包composer require matchish/laravel-scout-elasticsearch2.env设置环境变量SCOUT_DRIVER=Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine ELASTICSEARCH_HOST=192.168.211.128:92003.config/app.php中配置provider'providers' => [ // Other Service Providers \Matchish\ScoutElasticSearch\ElasticSearchServiceProvider::class ],4.发布配置文件php artisan vendor:publish --tag config会新增config/elasticsearch.php文件5.2 更新模型1.更新模型<?php namespace App\Models; use App\Trait\DefaultDatetimeFormat; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; class Video extends Model { use DefaultDatetimeFormat, Searchable; protected $fillable = ['img', 'title', 'innerVideoHref', 'innerHref', 'viewNumber', 'likeNumber', 'helpInfo', 'type']; /** * Get the indexable data array for the model. * 我想只根据title来分词检索 * @return array */ public function toSearchableArray() { return $this->only(['title']); } /** * Get the index name for the model. * 指定索引的名称 * @return string */ public function searchableAs() { return 'videos_index'; } /** * 指定 搜索索引中存储的唯一ID * @return mixed */ public function getScoutKey() { return $this->id; } /** * 指定 搜索索引中存储的唯一ID的键名 * @return string */ public function getScoutKeyName() { return 'id'; } }2.修改config/elasticsearch.php<?php return [ 'host' => env('ELASTICSEARCH_HOST','192.168.211.128:9200'), 'indices' => [ 'mappings' => [ 'default' => [ 'properties' => [ 'id' => [ 'type' => 'keyword', ], ], ], // 与上一步的索引名称对应 'videos_index' => [ 'properties' => [ 'title' => [ 'type' => 'text', 'analyzer' => 'ik_max_word', 'search_analyzer' => 'ik_max_word', ], ], ], ], 'settings' => [ 'default' => [ 'number_of_shards' => 1, 'number_of_replicas' => 0, ], ], ], ];3.索引的批量导入php artisan scout:import5.3 使用场景:根据当前播放的视频名称,检索出来十个相关的视频作为推荐public function play($type, $id) { // 直接根据类型和视频ID进行查询 $video = Video::where('type', $type)->where('id', $id)->first(); $videoSeries = Video::search($video->title)->take(10)->get(); dd($videoSeries); }六、遇到的问题6.1 Kibana 服务器尚未准备就绪。在服务器上部署时,访问Kibana出现了查看日志docker logs kibana [2023-01-18T02:05:30.467+00:00][ERROR][elasticsearch-service] Unable to retrieve version information from Elasticsearch nodes. connect ECONNREFUSED 127.0.0.1:9200原因是创建容器时填写的sudo docker run -d \ --name kibana \ -e ELASTICSEARCH_HOSTS=http://127.0.0.1:9200 \ -p 5601:5601 \ kibana:8.6.0这里不可以使用127.0.0.1需要使用私有IP重新创建后即可正常访问6.2 无法访问在虚拟机上部署时按照步骤并开放端口是可以访问9200和5601端口在服务器上按照 创建网络 -> 创建elasticsearch、kibana容器设置网络 的步骤走下来 始终访问不了对应的端口不清楚原因,于是去掉了创建容器时的网络配置引用1.如何在 Ubuntu 20.04 启用 SSH :https://zhuanlan.zhihu.com/p/1457637892.你必须会的Docker安装ElasticSearch教程:https://juejin.cn/post/70741156903402864723.Install Kibana with Docker:https://www.elastic.co/guide/en/kibana/current/docker.html4.Elasticsearch_Installation_asking for username and password:https://stackoverflow.com/questions/71269878/elasticsearch-installation-asking-for-username-and-password5.Releases · medcl/elasticsearch-analysis-ik (github.com):https://github.com/medcl/elasticsearch-analysis-ik/releases6.matchish/laravel-scout-elasticsearch: Search among multiple models with ElasticSearch and Laravel Scout (github.com):https://github.com/matchish/laravel-scout-elasticsearch7.只需五步 集成新版 Elasticsearch7.9 中文搜索 到你的 Laravel7 项目:https://juejin.cn/post/68651885751143301268.php Laravel 使用elasticsearch+ik中文分词器搭建搜索引擎:https://blog.csdn.net/weixin_42701376/article/details/126782529?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-2-126782529-blog-109466440.pc_relevant_multi_platform_whitelistv4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-2-126782529-blog-109466440.pc_relevant_multi_platform_whitelistv4&utm_relevant_index=39.docker中设置elasticsearch、kibana用户名密码、修改密码:https://blog.csdn.net/IT_road_qxc/article/details/121858843
2023年01月18日
334 阅读
0 评论
1 点赞
1
...
3
4
5
...
7