当前位置: 首页 > news >正文

使用Java调用Apache commons-text求解字符串相似性实战

目录

前言

一、字符串距离的几种计算方法

1、Levenshtein 距离

2、Overlap Coefficient计算

3、Q-gram Matching

4、余弦相似性计算

二、基于余弦相似性的基地名称对比

1、加载百科中的基地信息列表

2、设置忽略词列表 

3、将数据库地名和Excel进行对比

三、总结


前言

        在之前的一篇漂亮国的全球的基地博客中,我们曾经对漂亮国的全球基地进行了一些梳理。博文中使用的数据来源,重点是参考以为博主分享的KML的数据,同时针对其国内的基地部署信息,我们从互联网百科的数据中搜寻到一些。其实拿到这两份数据的时候,是存在一些问题的,比如,KML的数据它的基地名称都是英文的,而在互联网上公开的数据中,良莠不齐,有的是中文的,有的是英文,有的中英文都有,而且可能还存在同样的英文,它的描述不一样的情况,比如下面的场景:

XXX Air Base 空军基地 

XXX Air Station 航空站

        可能不同的信息来源,其主要的名称对应的真实位置表示的是同一个。再比如漂亮国驻小日子的基地列表。

Idesuna Jima Air Range 

FAC 6078 出砂岛炸射练习场 Idesuna Jima Range 训练 冲绳渡名喜村

        上面一行是从KML中解析出来的基地名称,而下面是从某百科中得到的数据。 当我们将句子的影响词(当出现在军事基地的领域中的某些特定词,如Air、Base、Station、Range等这些词去掉后)其主要的地点就是同一个,通过对比主要关键词的相似性,为我们实现将两个地名进行对齐,甚至可以设定一个阈值,当两个字符串的相似性超过多少(比如超过90%)就认为这是同一个地点,从而可以实现将基地的中文名和所驻地的国家、城市等信息进行一一匹配。从而减少人工对比的工作。

        随着现代技术的快速发展,文本相似度计算有很多种方法,甚至可以用大数据、自然语言处理还可以结合人工智能的方法来实现精确的文本相似性判断。但是本文不想实现那么复杂的架构,只想简单快速的解决两个地址的快速匹配问题。博客以Java编程为例,讲解了在Java中求解两个字符串的几种方法。通过求解编辑距离、Q-gram Matching、还有余弦相似性计算,通过对比不同的方法,调用Apache 的Common-text中基于余弦的字符相似性得到了比较比错的结果。算法比较简单,主要想说明两个字符串的不同距离的计算,对于更复杂的模型,大家感兴趣的可以搜索相关的科研论文来学习。

一、字符串距离的几种计算方法

        为了比较字符的相似性,我们通过通过对比距离(把两个字符串的距离计算出来,当然这个距离的计算是有讲究的,具体的算法就是我们说的距离算法,不同的距离算法,得到的值是不一样的)。因此这里我们打算讲将在Java当中,有哪些距离的计算方法以及如何编写相应的代码。

1、Levenshtein 距离

        计算将一个字符串转换为另一个字符串所需的最少单字符编辑操作(插入、删除或替换)的数量。在下面这个示例中,levenshteinDistance方法使用动态规划来计算两个字符串之间的Levenshtein Distance。calculateNormalizedLevenshteinDistance方法则使用这个距离和两个字符串长度的最大值来计算标准化的Levenshtein Distance。 main方法中给出了两个示例字符串s1和s2,并调用calculateNormalizedLevenshteinDistance方法来计算并打印它们的Normalized Levenshtein Distance。根据这个得分,你可以设定一个阈值来判断两个字符串是否相似。例如,如果Normalized Levenshtein Distance小于0.2(即80%的字符是匹配的),你可以认为这两个字符串是相似的。这个阈值可以根据你的具体需求进行调整。
 

package com.yelang.project;public class NormalizedLevenshteinDistance {// 计算Levenshtein Distancepublic static int levenshteinDistance(String s1, String s2) {int[][] dp = new int[s1.length() + 1][s2.length() + 1];for (int i = 0; i <= s1.length(); i++) {dp[i][0] = i;}for (int j = 0; j <= s2.length(); j++) {dp[0][j] = j;}for (int i = 1; i <= s1.length(); i++) {for (int j = 1; j <= s2.length(); j++) {int cost = (s1.charAt(i - 1) == s2.charAt(j - 1)) ? 0 : 1;dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + cost);}}return dp[s1.length()][s2.length()];}// 计算Normalized Levenshtein Distancepublic static double calculateNormalizedLevenshteinDistance(String s1, String s2) {int distance = levenshteinDistance(s1, s2);int maxLength = Math.max(s1.length(), s2.length());return (double) distance / maxLength;}public static void main(String[] args) {String s1 = "Camp Humphreys";String s2 = "United States Army Garrison-Humphreys";double normalizedDistance = calculateNormalizedLevenshteinDistance(s1, s2);System.out.println("Normalized Levenshtein Distance: " + normalizedDistance);}
}

        运行上述程序后,得到的结果如下,表示两个字符串的相似度是0.67:

Normalized Levenshtein Distance: 0.6756756756756757

2、Overlap Coefficient计算

        Overlap Coefficient是通过计算两个字符串的最长公共子序列的长度来求两者的相似度的。这种算法有弊有利,在主要的关键词不同而基地的信息完一致的情况下,比如xxx air base 和xx1 air base,通过计算得到的结果一定及其相似,因为这两个字符串的最长公共序列很长啊,计算机看起来就像是完全一致的。

package com.yelang.project;
public class OverlapCoefficient {// 计算最长公共子序列的长度public static int longestCommonSubsequence(String s1, String s2) {int len1 = s1.length();int len2 = s2.length();int[][] dp = new int[len1 + 1][len2 + 1];for (int i = 1; i <= len1; i++) {for (int j = 1; j <= len2; j++) {if (s1.charAt(i - 1) == s2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[len1][len2];}// 计算Overlap Coefficientpublic static double calculateOverlapCoefficient(String s1, String s2) {int lcsLength = longestCommonSubsequence(s1, s2);int minLength = Math.min(s1.length(), s2.length());return (double) lcsLength / minLength;}public static void main(String[] args) {String s1 = "Camp Humphreys";String s2 = "United States Army Garrison-Humphreys";double overlapCoefficient = calculateOverlapCoefficient(s1, s2);System.out.println("Overlap Coefficient: " + overlapCoefficient);}
}

        运行以上程序后,得到的结果是:

Overlap Coefficient: 0.8571428571428571

        它判定是85%的相似度,貌似看起来比第一种距离很接近真相,你换个词去测试就发现,这种算法其实很蠢。

3、Q-gram Matching

        Q-gram Matching是一种基于子串的字符串相似度计算方法,其中Q表示子串的长度。对于两个字符串,计算它们共有的Q-gram(长度为Q的连续子串)的数量,然后将这个数量除以两个字符串中Q-gram数量较少的那个, 得到相似度的比例。下面给出它的Java实现:

package com.yelang.project;
import java.util.HashSet;
import java.util.Set;
public class QGramMatching {/*** 在这个示例中,calculateQGrams方法接受一个字符串和一个整数Q,然后返回该字符串所有可能的Q-gram的集合。calculateQGramSimilarity方法接受两个字符串和一个整数Q,计算它们的Q-gram集合,并找出共有的Q-gram数量,然后计算相似度。main方法中给出了两个示例字符串s1和s2,以及Q-gram的长度Q,并调用calculateQGramSimilarity方法来计算并打印它们的Q-gram相似度。请注意,Q-gram的长度Q是一个参数,可以根据具体应用场景进行调整。较短的Q值可以捕捉到更细粒度的相似性,而较长的Q值则可以捕捉到更宽泛的相似性。此外,相似度的阈值可以根据实际需求设定,以判断两个字符串是否相似。*/// 计算字符串的Q-gram集合public static Set<String> calculateQGrams(String s, int q) {Set<String> qGrams = new HashSet<>();for (int i = 0; i <= s.length() - q; i++) {qGrams.add(s.substring(i, i + q));}return qGrams;}// 计算两个字符串的Q-gram相似度public static double calculateQGramSimilarity(String s1, String s2, int q) {Set<String> qGrams1 = calculateQGrams(s1, q);Set<String> qGrams2 = calculateQGrams(s2, q);// 计算两个集合的交集Set<String> intersection = new HashSet<>(qGrams1);intersection.retainAll(qGrams2);// 计算相似度double similarity = intersection.size() / (double) Math.min(qGrams1.size(), qGrams2.size());return similarity;}public static void main(String[] args) {String s1 = "Camp Humphreys";String s2 = "United States Army Garrison-Humphreys";// Misawa Air Range<==>Misawa Air Base:similar = 0.9058216273156766// Gun Training Area<==>Tsuken Jima Training Area:similar = 0.9202830114233174int q = 3; // Q-gram的长度double qGramSimilarity = calculateQGramSimilarity(s1, s2, q);System.out.println("Q-gram Similarity (Q=" + q + "): " + qGramSimilarity);}
}

        运行以上的程序,得到以下的执行结果:

Q-gram Similarity (Q=3): 0.5833333333333334

4、余弦相似性计算

        使用词嵌入(如word2vec或BERT)将单词转换为向量,并计算向量之间的余弦相似度。这里基于Apache 的common-text来进行余弦计算,看结果如何,首先在Pom.xml中引入以下资源。

<!-- 求解字符相似性 -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-text</artifactId><version>1.10.0</version>
</dependency>

        然后在Java中实现以下方法,请注意,这里是一种比较简单的方法,更精准的实现还要结合实际场景进行优化。

/**
*计算两个字符串的相似性
* @param args1
* @param args2
* @return
*/
private Double getSimilar(String args1,String args2) {Map<CharSequence, Integer> map = Arrays.stream(args1.split("")).collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));Map<CharSequence, Integer> map2 = Arrays.stream(args2.split("")).collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));CosineSimilarity cosineSimilarity = new CosineSimilarity();Double similar = cosineSimilarity.cosineSimilarity(map, map2);return similar;
}

        基于余弦的方法运行结果:

similar = 0.6726637889454885

        篇幅有限,这里不做很全面的覆盖测试,基于上面的代码,感兴趣的朋友和同学可以自己去做测试,根据不同的样例,得到的结果阈值比较令人想象不到,建议结合真实的数据进行测试,你会发现问题更大。如果要把这个应用于实战的话,建议不要采用上述模型,推荐采用TF-IDF(Term Frequency-Inverse Document Frequency)和余弦计算的方式。最后进行综合评分,将不同的相似度计算方法(如基于编辑的算法、基于令牌的方法、基于语义的方法)结合起来,并为每种方法分配一个权重,然后计算加权平均值。这样子计算出来的结果比较准确。更深入的内容,大家闲暇的时候可以自主实现。

二、基于余弦相似性的基地名称对比

        这里我们讲解如何把数据库中的基地列表信息和通过Excel表格整理的基地信息进行综合对比,通过余弦相似性和设置忽略词来提高准确度。作为一种参考的实现方案供大家参考。

1、加载百科中的基地信息列表

        要想将数据库中的基地信息和百科中的数据进行对比,首先要做的就是数据采集。通过把从百科采集的数据转换成excel,然后应用程序解析Excel数据,通过计算计算英文名称的相似性来进行对比。基础数据采集的方式,可以根据大家的熟悉程度,可以通过爬虫的形式进行介绍,也可以把表格直接复制到Exclel,直接进行Excle的读取成List列表后进行对比即可。这里我们以第二种方案来进行讲解。以下是从百科中节选的Excel中的数据列表。

管理设施代码基地英文名称基地中文名称用途驻地国家中文名驻地国家英文名驻地城市中文名
FAC 1054Camp Chitose千岁营通信日本Japan北海道千岁市
FAC 2001Misawa Air Base三泽空军基地航空基地日本Japan青森县三泽市
FAC 3013Yokota Air Base横田空军基地航空基地日本Japan东京都福生市
FAC 3016Fuchu Communications Station府中通讯站通信日本Japan东京都府中市
FAC 3019Tama Hills Recreation Center多摩之丘育乐中心娱乐日本Japan东京都稻城市
FAC 3048South Camp Drake AFN Transmitter Site南德雷克营美军电台转播站兵营日本Japan埼玉县和光市
FAC 3048Camp Asaka朝霞营兵营日本Japan埼玉县和光市
FAC 3049Tokorozawa Communications Station所泽通讯站通信日本Japan埼玉县所泽市
FAC 3056Owada Communication Site大和田通讯站通信日本Japan埼玉新座市
FAC 3162Yugi Communication Site由木通讯站通信日本Japan东京都八王子市
FAC 4100Sofu Communication Site祖生通讯站通信日本Japan山口县岩国市
FAC 5001Itazuke Auxiliary Airfield板付辅助飞行场空运货站日本Japan福冈市博多区
FAC 5073Sefurisan Liaison Annex脊振山辅助联络站通信日本Japan佐贺县神埼市
FAC 5091Tsushima Communication Site对马通讯站通信日本Japan长崎对马市
FAC 6004Okuma Rest Center奥间休息中心娱乐日本Japan冲绳国头村
FAC 6006Yaedake Communication Site八重岳通讯站通信日本Japan冲绳本部町
FAC 6022Kadena Ammunition Storage Area嘉手纳弹药储存区存储日本Japan冲绳恩纳村
FAC 6037Kadena Air Base嘉手纳空军基地航空基地日本Japan冲绳嘉手纳
FAC 6077Tori Shima Range鸟岛炸射练习场训练日本Japan冲绳久米岛
FAC 6078Idesuna Jima Range出砂岛炸射练习场训练日本Japan冲绳渡名喜村
FAC 6080Kume Jima Range久米岛炸射练习场训练日本Japan冲绳久米岛町
FAC 2070Shariki Communication Site车力通讯站通信日本Japan青森县津轻市
FAC 3004Akasaka Press Center (Hardy Barracks)赤坂新闻中心(哈迪军营)办公室日本Japan东京都港区
FAC 3067Yokohama North Dock横滨北坞港口设施日本Japan神奈川县横滨市

        上面只是一个示例,实际的表格有85条数据。

         我们需要将Excel中的数据进行导入到应用程序中,首先需要定义一个实体类:

package com.yelang.project.extend.militarytopics.domain;
import java.io.Serializable;
import com.yelang.framework.aspectj.lang.annotation.Excel;
import com.yelang.framework.aspectj.lang.annotation.Excel.Type;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class WebSiteMilitaryBase implements Serializable{private static final long serialVersionUID = -4620277223946004351L;@Excel(name = "设施管理代码", type = Type.IMPORT)private String manageCode;@Excel(name = "基地英文名称")private String enName;@Excel(name = "基地中文名称")private String cnName;@Excel(name = "用途")private String useTo;@Excel(name = "驻地国家中文名")private String cnCountry;@Excel(name = "驻地国家英文名")private String enCountry;@Excel(name = "驻地城市中文名")private String cnCity;
}

        然后定义Excel的读取方法,关键代码如下所示:

public void readJapanData() {try {File file = new File("C:/Users/Administrator/Desktop/基地/驻日美军基地.xlsx");FileInputStream fis = new FileInputStream(file);ExcelUtil<WebSiteMilitaryBase> util = new ExcelUtil<WebSiteMilitaryBase>(WebSiteMilitaryBase.class);List<WebSiteMilitaryBase> dataList = util.importExcel(fis);System.out.println(dataList.size());for(WebSiteMilitaryBase base : dataList) {System.out.println(base);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}
}

        运行一下代码,测试一下是否读取成功,如果在控制台中看到以下信息说明解析成功。

2、设置忽略词列表 

        其实忽略词和权重打分的作用是差不多的,忽略词就是在字符串中没有什么影响的词,这里需要注意的是要结合场景来说明。比如当前是均事领域,类似与Air base等这些在相关基地中的字符串中就可以忽略掉。忽略词设置好之后,在进行字符串的相似性计算时,需要把两个字符串进行忽略词替换。关键代码如下:

/**
* 去掉需要忽略的关键词
* @param source
* @return
*/
private String ignoreKeyWords(String source) {// Barracks 军营 Service Area 服务中心  Air Station 航空站 Air Base 空军基地 Camp 营地 Recreation Center 娱乐中心 Communications Station 通信站// Transmitter Site 发射站 Communication Site 通信站点 Training 训练 Airfield机场 Ammunition Depot 弹药库 Port 港口 Pier 码头 Dependent Housing 家属区// Depot 仓库 Landing Field 着陆场 Corps 兵团 Naval 海军String [] keyWords = {"Barracks","Service Area","Station","Air","Base","Camp","Area","Recreation Center","Communications","Station","Transmitter","Site","Communication","Training","Airfield","Annex","Ammunition","Port","Pier","Dependent","Housing","Depot","Storage","Range","Center","Landing Field","Corps","Naval","Marine"};for(String keyword : keyWords) {source = source.replace(keyword, "").trim();}return source;
}

3、将数据库地名和Excel进行对比

        在这里 ,我们需要将需要对比的数据从数据库中查询出来,然后跟Excel表格中的进行对比。经过忽略词的设置后,我们对比最后的计算结果,最后得到两个字符串的相似性。当两个字符串的相似度大于90%,我们即可认为是统一地点,当然这里最好需要人工审核。

@Test
public void evalJapanCosineSimilarity() {QueryWrapper<UsaMilitaryBase> queryWrapper = new QueryWrapper<UsaMilitaryBase>();queryWrapper.isNull("cn_name");//查询基地中文名为空的数据List<UsaMilitaryBase> dbList = this.militaryBaseService.list(queryWrapper);System.out.println(dbList.size());try {File file = new File("C:/Users/Administrator/Desktop/基地/驻日美军基地.xlsx");FileInputStream fis = new FileInputStream(file);ExcelUtil<WebSiteMilitaryBase> util = new ExcelUtil<WebSiteMilitaryBase>(WebSiteMilitaryBase.class);List<WebSiteMilitaryBase> excelDataList = util.importExcel(fis);System.out.println(excelDataList.size());int index = 0;for(WebSiteMilitaryBase base : excelDataList) {for(UsaMilitaryBase dbBase : dbList) {String dbEnName = dbBase.getEnName();dbEnName = ignoreKeyWords(dbEnName);String excelEnName = base.getEnName();excelEnName = ignoreKeyWords(excelEnName);Double similar = this.getSimilar(dbEnName, excelEnName);if(similar >= 0.85) {System.out.println(dbEnName + "<==>" + excelEnName + "\t similar = " + similar);System.out.println(base);index ++;}else {continue;}}}System.out.println(index);} catch (FileNotFoundException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}
}

        下面我们来执行上述的代码,看看最终符合我们条件的有多少?

 

Misawa<==>Misawa	 similar = 0.9999999999999998
WebSiteMilitaryBase(manageCode=FAC 2001, enName=Misawa Air Base, cnName=三泽空军基地, useTo=航空基地, cnCountry=日本, enCountry=Japan, cnCity=青森县三泽市)
Idesuna Jima<==>Idesuna Jima	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 6078, enName=Idesuna Jima Range, cnName=出砂岛炸射练习场, useTo=训练, cnCountry=日本, enCountry=Japan, cnCity=冲绳渡名喜村)
Kawakami<==>Kawakami	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 4083, enName=Kawakami Ammunition Depot, cnName=川上弹药库, useTo=存储, cnCountry=日本, enCountry=Japan, cnCity=广岛县东广岛市)
Hiro<==>Hiro	 similar = 1.0
WebSiteMilitaryBase(manageCode=FAC 4084, enName=Hiro Ammunition Depot, cnName=广弹药库, useTo=存储, cnCountry=日本, enCountry=Japan, cnCity=广岛县吴市)
Kure  6<==>Kure  No.6	 similar = 0.8660254037844386
WebSiteMilitaryBase(manageCode=FAC 4152, enName=Kure Pier No.6, cnName=吴市6号码头, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=广岛县吴市)
Torii<==>Torii	 similar = 0.9999999999999999
WebSiteMilitaryBase(manageCode=FAC 6036, enName=Torii Communications Station, cnName=鸟居通讯站, useTo=通信, cnCountry=日本, enCountry=Japan, cnCity=冲绳县读谷村)
Naha<==>Naha	 similar = 1.0000000000000002
WebSiteMilitaryBase(manageCode=FAC 6064, enName=Naha Port, cnName=那霸港湾设施, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=冲绳县那霸市)
Fleet Activities Chinhae KS<==>United States Fleet Activities Yokosuka	 similar = 0.8653323061113575
WebSiteMilitaryBase(manageCode=FAC 3099, enName=United States Fleet Activities Yokosuka, cnName=横须贺美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=神奈川县横须贺市)
Fleet Activities Chinhae KS (Yechon)<==>United States Fleet Activities Sasebo	 similar = 0.8560516500077061
WebSiteMilitaryBase(manageCode=FAC 5029, enName=United States Fleet Activities Sasebo, cnName=佐世保美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Fleet Activities Chinhae KS<==>United States Fleet Activities Sasebo	 similar = 0.8994681014529727
WebSiteMilitaryBase(manageCode=FAC 5029, enName=United States Fleet Activities Sasebo, cnName=佐世保美国舰队基地, useTo=港口设施, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Hiro<==>Hario	 similar = 0.8944271909999159
WebSiteMilitaryBase(manageCode=FAC 5119, enName=Hario Dependent Housing Area, cnName=针尾军眷住宅区, useTo=住宅, cnCountry=日本, enCountry=Japan, cnCity=长崎县佐世保市)
Fleet Activities Chinhae KS (Yongsan Garrison)<==>Makiminato  ( Kinser)	 similar = 0.8663164754169591
WebSiteMilitaryBase(manageCode=FAC 6056, enName=Makiminato Service Area (Camp Kinser), cnName=牧港补给地区(金瑟营), useTo=后勤, cnCountry=日本, enCountry=Japan, cnCity=冲绳县浦添市)
San Vito Dei Normanni<==>Makiminato  ( Kinser)	 similar = 0.8524007579586305
WebSiteMilitaryBase(manageCode=FAC 6056, enName=Makiminato Service Area (Camp Kinser), cnName=牧港补给地区(金瑟营), useTo=后勤, cnCountry=日本, enCountry=Japan, cnCity=冲绳县浦添市)
13

      可以很直观的看到,经过计算,有的地名已经完全匹配,比如Hiro<==>Hiro     similar = 1.0和Idesuna Jima<==>Idesuna Jima     similar = 1.0。这些数据可以认为是一个地点了。

三、总结

        以上就是本文的主要内容,博客以Java编程为例,讲解了在Java中求解两个字符串的几种方法。通过求解编辑距离、Q-gram Matching、还有余弦相似性计算,通过对比不同的方法,调用Apache 的Common-text中基于余弦的字符相似性得到了比较比错的结果。最后讲解了一个实际的案例,将之前我们采集的漂亮数据库数据和百科的数据进行对齐。为下一步做数据关联和挖掘打下坚实的基础。行文仓促,定有许多的不足之处,如有任何不当或者表达不准确的地方,还恳请各位专家和朋友在评论区留言平指正,不胜感激。

相关文章:

使用Java调用Apache commons-text求解字符串相似性实战

目录 前言 一、字符串距离的几种计算方法 1、Levenshtein 距离 2、Overlap Coefficient计算 3、Q-gram Matching 4、余弦相似性计算 二、基于余弦相似性的基地名称对比 1、加载百科中的基地信息列表 2、设置忽略词列表 3、将数据库地名和Excel进行对比 三、总结 前言…...

http request-01-XMLHttpRequest XHR 简单介绍

http 请求系列 http request-01-XMLHttpRequest XHR 简单介绍 http request-01-XMLHttpRequest XHR 标准 Ajax 详解-01-AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;入门介绍 Ajax XHR 的替代方案-fetch Ajax XHR 的替代方案-fetch 标准 Ajax 的替代方案…...

关于tresos Studio(EB)的MCAL配置之DIO

General Dio Development Error Detect开发者错误检测 Dio Flip Channel Api翻转通道电平接口Dio_FlipChannel是否启用 Dio Version Info Api决定Dio_GetVersionInfo接口是否启用&#xff0c;一般打开就行。 Dio Reverse Port Bits让端口的位&#xff08;通道&#xff09;进…...

【漫谈C语言和嵌入式003】1394总线

1394总线&#xff08;FireWire或IEEE 1394&#xff09;是一种高速串行总线标准&#xff0c;最初由苹果公司开发&#xff0c;并在1995年被IEEE&#xff08;电气与电子工程师协会&#xff09;批准为国际标准。它最初的目标是提供一种高性能、低延迟的数据传输方法&#xff0c;用于…...

python爬虫爬取某图书网页实例

文章目录 导入相应的库正确地设置代码的基础部分设置循环遍历遍历URL保存图片和文档全部代码即详细注释 下面是通过requests库来对ajax页面进行爬取的案例&#xff0c;与正常页面不同&#xff0c;这里我们获取url的方式也会不同&#xff0c;这里我们通过爬取一个简单的ajax小说…...

Linux 用户管理的基本概念、常用工具及操作流程

&#x1f600;前言 本篇博文是关于Linux 中用户管理的基本概念、常用工具及操作流程&#xff0c;并提供了一些实用的示例和注意事项。希望这些内容能帮助读者在日常工作中更加高效地管理 Linux 系统的用户账户&#xff0c;希望你能够喜欢&#x1f970; &#x1f3e0;个人主页&a…...

手撕C++入门基础

1.C介绍 C课程包括&#xff1a;C语法、STL、高阶数据结构 C参考文档&#xff1a;Reference - C Reference C 参考手册 - cppreference.com cppreference.com C兼容之前学习的C语言 2.C的第一个程序 打印hello world #define _CRT_SECURE_NO_WARNINGS 1 // test.cpp // …...

NPM版本控制策略:实现版本候选行为的指南

引言 在现代JavaScript项目中&#xff0c;依赖管理是确保应用稳定性和安全性的关键环节。NPM&#xff08;Node Package Manager&#xff09;作为Node.js的包管理器&#xff0c;提供了一套灵活的版本控制机制&#xff0c;允许开发者精确控制依赖包的版本。版本候选行为&#xf…...

问题集锦6

1.外调外围接口数据库没有变化 我已经修改完发到线上&#xff0c;看调用用代码释放更新了 or 自己掉测试环境试下 handledList 2.list每次写入最前面 List<Integer> snew ArrayList<>();s.add(1);s.add(2);s.add(0,0);System.out.println(s);3.集合 List<Inte…...

【研发日记】嵌入式处理器技能解锁(四)——TI C2000 DSP的Memory

文章目录 前言 背景介绍 Memory映射 RAM ROM 外设Register Memory分配 应用实例 总结 参考资料 前言 见《【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法》 见《【研发日记】嵌入式处理器技能解锁(二)——TI C2000 DSP的SCI(串口)通信》 见《…...

Ubuntu离线安装docker

查看操作系统版本&#xff1a; rootzyh-VMware-Virtual-Platform:~/install# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 24.04 LTS Release: 24.04 Codename: noble rootzyh-VMware-Virtual-Platform:~/install#…...

【抓耳挠腮,还是升职加薪,一起来画架构图!】

1. 焦头烂额 最近又遇到个焦头烂额的事情 &#xff0c;老板有了新想法&#xff0c;业务有所转向&#xff0c;需要新的方案设计 &#xff0c;架构设计&#xff0c;以进行后续实施。很快&#xff0c;第一次汇报来了&#xff0c; 由于前期准备时间短&#xff0c;模块拆分不清晰&a…...

算法的学习笔记—合并两个排序的链表(牛客JZ25)

&#x1f600;前言 在算法面试中&#xff0c;链表问题是经常遇到的考点之一&#xff0c;其中合并两个排序链表是一个非常经典的问题。本文将详细介绍如何通过递归和迭代两种方式实现两个有序链表的合并。 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 &#x1f600;合并…...

《虚拟之旅:开启无限可能的机器世界》简介:

1.Ubonto的介绍&#xff1a; Ubuntu 是一个流行的开源操作系统&#xff0c;基于 Linux 内核。 它具有以下一些特点和优势&#xff1a; 开源免费&#xff1a;任何人都可以免费使用、修改和分发。丰富的软件库&#xff1a;通过软件包管理器可以方便地安装各种应用程序。良好的…...

centos7 服务器搭建

1. 查看 centos 版本 cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)2 .查看 ip地址 ip addr sudo yum install net-tools -y 3. 是否能够上网 ping www.baidu.com ping 114.114.114.114 sudo systemctl restart network 4. DNS 更新DNS配置 编辑/etc/r…...

【Godot4自学手册】第四十五节用着色器(shader)制作水中效果

本节内容&#xff0c;主要学习利用着色器制作水波纹效果&#xff0c;效果如下&#xff1a; 一、搭建新的场景 首先我们新建场景&#xff0c;根节点选择Node2D&#xff0c;命名为Water&#xff0c;给根节点添加两个Tilemap节点&#xff0c;一个命名为Background主要用于绘制地…...

VMware Workstation Pro 安装 Ubuntu Server

这里写目录标题 VMware Workstation Pro 安装 Ubuntu Server1. 启动选项2. 系统语言3. 安装程序升级4. 键盘配置5. 安装类型6. 网卡配置7. 代理配置8. 系统镜像配置9. 硬盘配置10. 账户配置11. Ubuntu Pro 版本12. SSH 服务13. 推荐软件14. 安装成功15. 第一次重启报错16. 登录…...

智能化包括自动化与非自动化

智能化通常指的是系统或设备具备智能功能&#xff0c;以提高其自主性和效率。智能化可以分为自动化与非自动化两大类&#xff0c;每一类都有其独特的特点和应用场景。 一、自动化 自动化指的是系统能够在无需人为干预的情况下完成任务或操作。自动化系统通常依赖于预设的规则、…...

微前端架构的容器化部署:策略、实践与优势

随着微服务架构的兴起&#xff0c;微前端架构也成为现代Web应用开发的热门趋势。容器化技术&#xff0c;以其轻量级、可移植性和易于管理的特点&#xff0c;成为微前端部署的理想选择。本文将详细介绍微前端架构下应用容器化部署的策略、实践步骤以及这一方法的优势。 容器化技…...

面试题(网络、js、框架)

自我介绍 您好&#xff0c;面试官&#xff01;我叫[您的姓名]&#xff0c;非常荣幸能有机会参加这次面试。 在过去的 3 年里&#xff0c;我一直专注于前端开发领域&#xff0c;积累了丰富的实践经验。 在 Vue.js 项目中&#xff0c;我能够熟练运用组件化开发模式&#xff0c;实…...

C语言典型例题40

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 题目 例题3.8 运输公司对用户计算运费。路程&#xff08;以s表示&#xff0c;单位为千米&#xff09;&#xff0c;吨/千米运费越低。标准如下&#xff1a; s<250 没…...

【大模型部署及其应用 】使用 Ollama 和 Ollama WebUI 在本地运行 Llama 3

使用 Ollama 和 Ollama WebUI 在本地运行 Llama 3 目录 开始使用 Llama 3设置 Ollama WebUI访问 Ollama WebUI使用 Docker GenAI Stack 的 Llama 3骆驼 2 与 骆驼 3...

uniapp-部分文件中文乱码

一、问题 在开发时遇到&#xff0c;部分页面的中文显示乱码&#xff0c;如图 搜索了一下解决方法&#xff0c;这里记录一下 二、问题原因&#xff1a; 页面的编码格式不是 utf-8 造成的 三、解决方法 打开出现乱码页面选择编译器左上角的文件 > 以指定编码重新打开 选择U…...

Day41 | 647. 回文子串 516.最长回文子序列

语言 Java 647. 回文子串 回文子串 题目 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 思路 动规五部曲来分析 1.dp数组的含义&#x…...

全面解析Gerapy分布式部署:从环境搭建到定时任务,避开Crawlab的坑

Gerapy分布式部署 搭建远程服务器的环境 装好带docker服务的系统 Docker:容器可生成镜像&#xff0c;也可拉去镜像生成容器 示例&#xff1a;将一个环境打包上传到云端(远程服务器)&#xff0c;其他8个服务器需要这个环境直接向云端拉取镜像生成容器,进而使用该环境,比如有MYS…...

Springboot项目中使用druid实现多数据源和动态数据源,因数据库不可用导致的项目挂起的处理方案

Springboot项目中使用druid因数据库不可用导致的项目挂起的处理方案 在Spring Boot项目中使用Druid实现多数据源和动态数据源管理是一个常见的场景。通过合理的配置和错误处理机制&#xff0c;您可以有效地管理数据源&#xff0c;避免因数据库不可用而导致整个项目挂起。 1.…...

多线程 03:知识补充,静态代理与 Lambda 表达式的相关介绍,及其在多线程方面的应用

一、概述 记录时间 [2024-08-16] 前置知识&#xff1a;Java 基础篇&#xff1b;Java 面向对象 多线程 01&#xff1a;Java 多线程学习导航&#xff0c;线程简介&#xff0c;线程相关概念的整理 多线程 02&#xff1a;线程实现&#xff0c;创建线程的三种方式&#xff0c;通过多…...

机器学习中的距离概念

距离在机器学习中应用广泛&#xff0c;包括欧式距离、曼哈顿距离、内积距离和KL距离。 下面总结一下。 机器学习中的距离 欧式距离曼哈顿距离内积距离KL距离距离作为损失函数(MSE/MAE...)欧式距离与内积距离的联系☆距离的有效性 欧式距离 欧式距离&#xff08;Euclidean Dis…...

Java 如何判断map为null或者空

1.示例一 在Java中&#xff0c;如果我们想判断一个Map是否为null或者空&#xff08;即没有任何键值对&#xff09;&#xff0c;我们可以使用以下的方法。下面是一个完整的示例代码&#xff0c;展示了如何进行这样的判断&#xff1a; import java.util.HashMap; import java…...

终端用户视角下的性能测试,体验与度量的融合

传统的性能测试的度量标准是什么 响应时间&#xff08;Response Time&#xff09;&#xff1a; 这是从客户端发出请求到接收到完整响应所需的时间。响应时间是衡量系统性能的重要指标&#xff0c;特别是在面向用户的应用中&#xff0c;因为它直接影响用户体验。 而用户体验的度…...

KCP源码解析系列(二)KCP协议结构体

一、KCP协议包 1.1 kcp协议包 kcp中只有一种数据包&#xff0c;不管是数据还是控制信息&#xff0c;都用这个数据包来表示 0 4 5 6 8 (BYTE) ---------------------------- | conv |cmd|frg| wnd | ---------------------------- 8 | …...

微软运行库全集合:一站式解决兼容性问题

开发者在部署应用程序时经常遇到因缺少运行库而引发的兼容性问题。为了解决这一问题&#xff0c;电脑天空推荐微软常用运行库合集&#xff0c;一个集成了微软多个关键运行库组件的软件包。 &#x1f4da; 包含组件概览&#xff1a; Visual Basic Virtual Machine&#xff1a;…...

【 亿邦动力网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …...

算法笔记|Day26贪心算法IV

算法笔记|Day26贪心算法IV ☆☆☆☆☆leetcode 452. 用最少数量的箭引爆气球题目分析代码 ☆☆☆☆☆leetcode 435. 无重叠区间题目分析代码 ☆☆☆☆☆leetcode 763.划分字母区间题目分析代码 ☆☆☆☆☆leetcode 452. 用最少数量的箭引爆气球 题目链接&#xff1a;leetcode …...

CVPR2023《DNF: Decouple and Feedback Network for Seeing in the Dark》暗光图像增强论文阅读笔记

相关链接 论文链接 https://openaccess.thecvf.com/content/CVPR2023/papers/Jin_DNF_Decouple_and_Feedback_Network_for_Seeing_in_the_Dark_CVPR_2023_paper.pdf 代码链接 https://github.com/Srameo/DNF 摘要 RAW数据的独特属性在低光照图像增强方面展现出巨大潜力。…...

大厂进阶七:React状态管理全解析

前言&#xff1a; React 中用于状态管理的hook及库有&#xff1a;useState、useReducer、useContext、useReducer useContext和一些第三方的库如redux、mobx等。 1、useState 单一组件某个具体状态 2、useReducer 单一组件中多个状态管理&#xff0c;策略分发机制统一管理…...

【ocr识别003】flask+paddleocr+bootstrap搭建OCR文本推理WEB服务

1.欢迎点赞、关注、批评、指正&#xff0c;互三走起来&#xff0c;小手动起来&#xff01; 2.了解、学习OCR相关技术知识领域&#xff0c;结合日常的场景进行测试、总结。如本文总结的flaskpaddleocrbootstrap搭建OCR文本推理WEB服务应用示例场景。 文章目录 1.代码结构2.效果演…...

从零开始搭建 LVS 高性能集群 (DR模式)

从零开始搭建 LVS 高性能集群 &#xff08;DR模式&#xff09; 架构 本设计方案采用三台服务器构建集群&#xff0c;使用Linux Virtual Server (LVS) 作为负载均衡器&#xff0c;运行在直接路由 (DR) 模式下。集群中的每一台服务器都将运行相同的服务&#xff0c;以实现 高可用…...

Linux环境开发工具【yum与vim】

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 文章目录 1.Linux软件包管理器yum1.1 快速使用yum 2. Linux编辑器-vim的使用2.1 vim的基本…...

laravel GuzzleHttp Client 无法获取返回的错误信息

Client发送一些请求&#xff0c;当返回状态不是200的时候&#xff0c;无法获取完整错误信息 $client new Client([base_uri > $this->getUri()./order/aaaaaa,timeout > 30,verify > false]);try {$response $client->request(POST, , [headers > [Lang&g…...

XMOS 多路音频解码器

当谈及高性能音频解码器&#xff0c;XMOS 是一个不容忽视的名字。作为音频解决方案领域的领军者&#xff0c;XMOS 的多路音频解码器在音频处理技术中扮演着至关重要的角色。下面我们一起深入探讨 XMOS 多路音频解码器去了解这一技术的魅力。 设计背景&#xff1a;追求音频极致…...

XSS小游戏(题目+解析)

xss题目练习地址&#xff1a; xss小游戏 游戏界面 一、Ma Spaghet! 我将题目要求进行翻译: 题目的主要要求就是&#xff1a;弹出一个&#xff08;1337&#xff09;的弹窗 开始解题&#xff1a; Let’s Go! 首先&#xff0c;传个参数看看 发现参数直接显示在了 < h2 >…...

《Redis核心技术与实战》学习笔记4——AOF日志:宕机了,Redis如何避免数据丢失?

文章目录 AOF 日志是如何实现的&#xff1f;三种写回策略 日志文件太大了怎么办&#xff1f;AOF 重写会阻塞吗?小结 大家好&#xff0c;我是大白。 如果有人问你&#xff1a;“你会把 Redis 用在什么业务场景下&#xff1f;”我想你大概率会说&#xff1a;“我会把它当作缓存使…...

NextJs - 服务端/客户端组件之架构多样性设计

NextJs - 服务端/客户端组件之架构多样性设计 前言一. 架构设计1.1 SSR流式渲染常见错误设计之 - 根页面同步阻塞1.2 架构设计之 - 客户端组件依赖于服务端组件数据① 使用 Redux 完成数据共享 1.3 架构设计之 - 单页内的分步骤跳转① 如何做到服务端组件和客户端组件之间的切换…...

使用 Python 进行 PDF 文件加密

使用 Python 解密加密的 PDF 文件-CSDN博客定义一个名为的函数&#xff0c;该函数接受三个参数&#xff1a;输入的加密 PDF 文件路径input_pdf、输出的解密 PDF 文件路径output_pdf和密码password。https://blog.csdn.net/qq_45519030/article/details/141256661 在数字化时代…...

Spring Boot集成RabbitMQ

目录 1.RabbitMQ简介2.添加依赖3.配置RabbitMQ连接4.DirectExchange4.1 消费者4.2 生产者4.3 测试4.4 一个交换机对多个队列4.5 一个队列对多个消费者 5.FanoutExchange5.1 消费者5.2 生产者5.3 测试 6.TopicExchange6.1 消费者6.2 生产者 1.RabbitMQ简介 RabbitMQ是一个由Erl…...

OLED屏幕制造工艺流程

OLED屏幕制造工艺流程是一个复杂且精细的过程&#xff0c;涉及多个关键步骤以确保最终的显示效果和性能。以下是OLED屏幕制造工艺流程的主要步骤&#xff1a; 1. 衬底制作与准备 材料选择&#xff1a;OLED器件需要一个透明的导电衬底&#xff0c;通常使用玻璃或塑料材料。 清…...

knowLedge-VueCLI项目中环境变量的定义与使用

1. env 1.1简介 在 Vue CLI 创建的项目中&#xff0c;你可以通过 .env 文件来定义环境变量。Vue CLI 支持多种 .env 文件&#xff0c;它们根据文件名中的前缀来决定何时加载和使用这些环境变量。 以下是一些常见的 .env 文件及其用途&#xff1a; .env&#xff1a;在任何环境…...

【C#】 接口 继承

简介 继承是面向对象编程的核心特性之一&#xff0c;它允许我们创建一个类&#xff08;称为子类&#xff09;来继承另一个类&#xff08;称为基类&#xff09;的属性和方法。 作用 这样&#xff0c;我们可以重用代码&#xff0c;减少重复&#xff0c;并使我们的代码更加模块…...

Self-Supervised Learning(李宏毅老师系列)

自学参考&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding BERT 论文逐段精读 视频课 课件资料 笔记 一、概述 自监督学习模型与芝麻街~ 参数量 ELMO&#xff1a;94MBERT&#xff1a;340MGPT-2&#xff1a;1542MMegatron&…...