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

青海格尔木建设局网站页面设计感想

青海格尔木建设局网站,页面设计感想,wordpress设置2个网站吗,公众号编辑器免费模板Java文档搜索引擎总结项目介绍项目使用的技术栈前端页面展示后端逻辑部分索引部分搜索模块部分Web模块部分项目介绍 Java文档搜索引擎项目是一个SSM项目#xff0c;该项目的前端界面部分是由搜索页面和展示页面组成#xff0c;后端部分索引模块#xff08;ScanAnalysis、in… Java文档搜索引擎总结项目介绍项目使用的技术栈前端页面展示后端逻辑部分索引部分搜索模块部分Web模块部分项目介绍 Java文档搜索引擎项目是一个SSM项目该项目的前端界面部分是由搜索页面和展示页面组成后端部分索引模块ScanAnalysis、index、搜索模块Searcher、Web模块SearcherController。该项使用ansj第三方分词库进行分词该项目并没有使用爬虫程序来获取Java文档而是直接将Java文档下载下来将Java文档里面的内容进行分词保存到正排索引文件和倒排索引文件中。 项目使用的技术栈 HTML、CSS、JS、Ajax、SpringBoot、SpringMVC 前端页面展示 搜索页面 显示页面 后端逻辑部分 索引部分 索引部分底层实现了两个类ScanAnalysis类、Index类 ***ScanAnalysis类***用来扫描Java文档中的所有HTML文件将HTML文件的标题、url路径、正文保存到正排索引文件和倒排索引文件中。 ***Index类***底层实现了正排索引结构和倒排索引结构Index类是配合ScanAnalysis类一起使用的Index将HTML文件内容保存到正排索引和倒排索引结构中最终保存到正排索引文件和倒排索引文件中。 ScanAnalysis类的底层代码 public class ScanAnalysis {//要扫描的根路径private static final String PATH_ROOT D:\\知识复习思维导图Java和Java笔记\\project-warehouse\\jdk-8u351-docs-all\\docs\\api;//Java文档的网络地址 不同部分private static final String JAVA_PATN https://docs.oracle.com/javase/8/docs/api/;//索引对象private static Index index new Index();/*** 启动方法* 我们在进行扫描的时候我们会发现在进行扫描的时候效率是比较低的。* 该方法使用的是单线程的方式* 我们可以使用多线程的方式来提高效率*/public void run() {long ben1 System.currentTimeMillis();//保存每一个文档的路径ArrayListString arrayList new ArrayList();//1.获取每一个文档的路径scanPath(PATH_ROOT,arrayList);long ben System.currentTimeMillis();//2.对每一个html文件进行解析for (String pathChild:arrayList) {analysis(pathChild);}long end System.currentTimeMillis();System.out.println(解析所花费的时间:(end - ben)ms);//3.将索引保存的索引文档中index.saveFile();long end1 System.currentTimeMillis();System.out.println(整个程序的时间:(end1 - ben1) ms);}/*** 启动方法2我们对解析这个步骤使用多线程的方式来提高效率**/public void run2() {long ben1 System.currentTimeMillis();//保存每一个文档的路径ArrayListString arrayList new ArrayList();//1.获取每一个文档的路径scanPath(PATH_ROOT,arrayList);long ben System.currentTimeMillis();//2.对每一个html文件进行解析//我们创建一个有时光线程的线程池ExecutorService executorService Executors.newFixedThreadPool(15);//这个CountDownLatch对象是用来表明需要等待多少个任务才结束//因为我们要等到解析这个过程完成了在执行下一步CountDownLatch countDownLatch new CountDownLatch(arrayList.size());for (String pathChild:arrayList) {//将解析的工作提交倒线程池中executorService.submit(new Runnable() {Overridepublic void run() {analysis(pathChild);//完成一次解析任务就减一countDownLatch.countDown();}});}try {//等待任务结束如果没结束就阻塞等待countDownLatch.await();//关闭线程池executorService.shutdown();} catch (InterruptedException e) {e.printStackTrace();}long end System.currentTimeMillis();System.out.println(解析所花费的时间:(end - ben)ms);//3.将索引保存的索引文档中index.saveFile();long end1 System.currentTimeMillis();System.out.println(整个程序的时间:(end1 - ben1) ms);}/*** 对 HTML文件进行解析* 获取到题目、正文、url* param pathChild*/private void analysis(String pathChild) {File file new File(pathChild);//1.获取标题String title getTitle(file); // System.out.println(title);//2.获取正文String content getContents(file);//3.获取urlString url getUrl(file);System.out.println(url);//4.将标题、正文、url保存到索引中index.saveIndex(title,content,url);}/*** 获取url* param file* return*/private String getUrl(File file) {StringBuilder stringBuilder new StringBuilder();String str file.getAbsolutePath().substring(PATH_ROOT.length()1);for (int i 0; i str.length(); i) {char ch str.charAt(i);if (ch ! \\) {stringBuilder.append(ch);} else {stringBuilder.append(/);}}return JAVA_PATNstringBuilder.toString();}/*** 获取正文,这个比较麻烦我们需要去除标签和script/script里面的内容* 这里我们需要使用正则表达式* param file* return*/public String getContents(File file) {//获取到HTML里面的内容String content getcontentHtml(file);//使用正则表达式将script/script标签和里面的内容都替换掉//字符串中的replaceAll方法是支持正则表达式的content content.replaceAll(script.*?(.*?)/script, );//使用正则表达式去除其他标签content content.replaceAll(.*?, );//使用正则表达式去除连续的空格content content.replaceAll(\\s, );return content ;}/*** 获取到HTML文件的内容这人进行文件读取操作* 使用字符流进行读取* param f* return*/private String getcontentHtml(File f) {try(BufferedReader bufferedReader new BufferedReader(new FileReader(f),1024*1024)) {StringBuilder content new StringBuilder();while (true) {int ret bufferedReader.read();if (ret -1) {break;}char ch (char) ret;//去除换行if(ch \n || ch \r) {ch ;}content.append(ch);}return content.toString();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}/*** 获取标题* param file* return*/private String getTitle(File file) {return file.getName().replace(.html,);}/*** 扫描根路径获取该目录下的索引HTML文件的路径* 这里要使用的递归 和 文件操作* param pathRoot* param arrayList*/private void scanPath(String pathRoot, ArrayListString arrayList) {File file new File(pathRoot);//获取到该目录的以及文件对象File[] files file.listFiles();//遍历for (File file1:files) {if (file1.isFile()) {//是普通文件//我们要的是html文件所以还要进行处理if (file1.getAbsolutePath().endsWith(html)) {arrayList.add(file1.getAbsolutePath());System.out.println(file1.getAbsolutePath());}} else {//是目录进行递归scanPath(file1.getAbsolutePath(),arrayList);}}}public static void main(String[] args) {ScanAnalysis scanAnalysis new ScanAnalysis();//程序的入口scanAnalysis.run2();} } Index类的底层代码 public class Index {//正排索引的底层使用顺序表public ArrayListJavaDocModel arrayList new ArrayList();//倒排索引的底层使用HashMappublic HashMapString,ArrayListWeight map new HashMap();//创建两个锁private Object lock1 new Object();private Object lock2 new Object();//正排索引文件 和倒排索引文件保存的 根目录private static final String INDEX_SAVE_PATH D:\\知识复习思维导图Java和Java笔记\\project-warehouse\\jdk-8u351-docs-all\\;//线上环境 正排索引文件 和倒排索引文件保存的 根目录 // private static final String INDEX_SAVE_PATH // /project/java_doc_searcher_ssm/;//进行JSON格式化的 对象private ObjectMapper objectMapper new ObjectMapper();/*** 1.正排索引通过文档Id来获取文档对象* param docId* return*/public JavaDocModel getForwardIndex(Integer docId) {return arrayList.get(docId);}/*** 2.通过分词来获取相对应的一组文档的id,这里不仅仅获取到了id,还有权重有利于进行排序* param terim* return*/public ArrayListWeight getReverseIndex(String terim) {return map.get(terim);}/*** 3.将标题正文url* 保存到正排索引和倒排索引中*/public void saveIndex(String title,String content,String url){JavaDocModel javaDocModel new JavaDocModel();javaDocModel.setContent(content);javaDocModel.setTitle(title);javaDocModel.setUrl(url);//1.建立正排索引buildForwardIndex(javaDocModel);//2.建立倒排索引buildReverseIndex(javaDocModel);}/*** 建立倒排索引* 我们需要对文档的标题正文 进行分词* param javaDocModel*/private void buildReverseIndex(JavaDocModel javaDocModel) {//统计一个分词在标题和内容中出现多少次class Count{public Integer titleCount;public Integer contentCount;}//1.对文档标题 进行分词ListTerm terms ToAnalysis.parse(javaDocModel.getTitle()).getTerms();//用来统计词频HashMapString,Count hashMap new HashMap();//记录总的分词synchronized (lock1) {//遍历分词termsfor (Term term:terms) {//获取到分词结果String termName term.getName();Count myCount hashMap.get(termName);if (myCount null) {//没有Count newCount new Count();newCount.titleCount 1;newCount.contentCount 0;hashMap.put(termName,newCount);} else {//有titleCount加一myCount.titleCount 1;}}//2.对文档对象的正文进行分词terms ToAnalysis.parse(javaDocModel.getContent()).getTerms();//遍历分词termsfor (Term term:terms) {//获取到分词结果String termName term.getName();Count myCount hashMap.get(termName);if (myCount null) {//没有Count newCount new Count();newCount.contentCount 1;newCount.titleCount 0;hashMap.put(termName,newCount);} else {//有contentCount加一myCount.contentCount 1;}}//3.将hashMap 里的数据整合到 map 里面//遍历hashMapfor (Map.EntryString,Count entry:hashMap.entrySet()) {String key entry.getKey();Count val entry.getValue();//从倒排索引中获取value值ArrayListWeight weights map.get(key);if (weights null) {//没有创建新的ArrayListWeight newWeights new ArrayList();Weight weight new Weight();//设置文档Idweight.setDocId(javaDocModel.getDocId());//设置权重titleCount*20contentCountweight.setWeight(val.contentCount val.titleCount*20);newWeights.add(weight);map.put(key,newWeights);} else {//有的话直接添加Weight weight new Weight();//设置文档Idweight.setDocId(javaDocModel.getDocId());//设置权重titleCount*20contentCountweight.setWeight(val.contentCount val.titleCount*20);weights.add(weight);}}}}/*** 建立正排索引以顺序表的下标作为文档ID* 直接插入顺序表就行* param javaDocModel*/private void buildForwardIndex(JavaDocModel javaDocModel) {synchronized (lock2) {//插入docIdjavaDocModel.setDocId(arrayList.size());//直接插入顺序表尾部arrayList.add(javaDocModel);}}/*** 4.将正排索引结构 和 倒排索引结构 保存到 正排索引文件 和倒排索引文件中* 序列化的方法以JSON的格式保存*/public void saveFile() {//正排索引 和 倒排索引保存的目录File filePath new File(INDEX_SAVE_PATH);if (!filePath.exists()) {//创建目录filePath.mkdirs();}//正排索引文件对象File fileForwardIndex new File(INDEX_SAVE_PATHforward.txt);//倒排索引文件对象File fileReverseIndex new File(INDEX_SAVE_PATHreverse.txt);if (!fileForwardIndex.exists()) {//不存在创建正排索引文件try {fileForwardIndex.createNewFile();} catch (IOException e) {e.printStackTrace();}}if (!fileReverseIndex.exists()) {//不存在创建倒排索引文件try {fileReverseIndex.createNewFile();} catch (IOException e) {e.printStackTrace();}}try {//将正排索引结构转成JSON格式保存到正排索引文件中objectMapper.writeValue(fileForwardIndex,arrayList);//将倒排索引结构转成JSON格式保存到倒排索引文件中objectMapper.writeValue(fileReverseIndex,map);} catch (IOException e) {e.printStackTrace();}}/*** 5.加载正排 和 倒排 文件 将内容加载倒内存中* 反序列*/public void load() {long ben System.currentTimeMillis();//正排索引文件对象File fileForwardIndex new File(INDEX_SAVE_PATHforward.txt);//倒排索引文件对象File fileReverseIndex new File(INDEX_SAVE_PATHreverse.txt);try {//这里的 readValue方法用法要注意// 第二个参数是一个匿名内部类实现了TypeReference,目的就是 我们想要把JSON格式的字符串转成什么类型 告诉了 readValue方法//正排arrayList objectMapper.readValue(fileForwardIndex, new TypeReferenceArrayListJavaDocModel() {});//倒排map objectMapper.readValue(fileReverseIndex, new TypeReferenceHashMapString,ArrayListWeight() {});} catch (IOException e) {e.printStackTrace();}long end System.currentTimeMillis();System.out.println(加载文档的时间:(end - ben) ms);} } 搜索模块部分 搜索模块部分底层实现了Searcher类提供了searcher方法来搜索相关的文档。 Searcher类的底层代码 public class Searcher {//索引类private Index index new Index();//保存停用词表的数据结构private SetString stopWordsSet new HashSet();//停用词表的存放路径private static final String STOP_WORDS D:\\知识复习思维导图Java和Java笔记\\project-warehouse\\jdk-8u351-docs-all\\stop_words.txt;//线上环境 停用词表的存放路径 // private static final String STOP_WORDS // /project/java_doc_searcher_ssm/stop_words.txt;public Searcher() {//1.创建该类的时候加载一些索引文档index.load();//2.创建该类的时候加载停用词表loadStopWords();}/*** 加载停用词表*/private void loadStopWords() {long ben System.currentTimeMillis();//进行读操作try(BufferedReader bufferedReader new BufferedReader(new FileReader(STOP_WORDS)) ){while (true) {String str bufferedReader.readLine();if (str null) {break;}stopWordsSet.add(str);}} catch (IOException e) {e.printStackTrace();}long end System.currentTimeMillis();System.out.println(加载停用词表的时间:(end - ben) ms);}public ListResultReturnModenl searcher(String word) {//将查询词进行分词、ListTerm terms ToAnalysis.parse(word).getTerms();//我们通过分词结果可以得出有些分词是不合理的//我们要排除一些不合理的分词结果//这里我们使用停用词表进行过滤ListTerm newTerms new ArrayList();//保存过滤后的termfor (Term term:terms) {//分词内容String wordName term.getName();if (!stopWordsSet.contains(wordName)) {//不是停用词newTerms.add(term);}}//遍历newTerms获取要返回的数据ListArrayListWeight listList new ArrayList();for (Term term:newTerms) {//获取倒分词的内容String wordName term.getName();//通过倒排索引来获取倒相对应的文档对象ArrayListWeight reverseIndex index.getReverseIndex(wordName);//判断是否拿到if (reverseIndex null) {//没有拿到continue;}//将reverseIndex保存到 listList中listList.add(reverseIndex);}//合并listList中的数组并且进行去重//类似于合并多个有序数组并且最后的结果要有序ListWeight list sortArray(listList);//对list进行排序按照权重的大小由高到低排序Collections.sort(list, new ComparatorWeight() {Overridepublic int compare(Weight o1, Weight o2) {//降序return o2.getWeight() - o1.getWeight();}});//保存返回的数据ListResultReturnModenl results new ArrayList();//将数据进行封装for (Weight weight:list) {//通过正排索引找到文档对象JavaDocModel forwardIndex index.getForwardIndex(weight.getDocId());ResultReturnModenl resultReturnModenl new ResultReturnModenl();//设置标题resultReturnModenl.setTitle(forwardIndex.getTitle());//设置urlresultReturnModenl.setUrl(forwardIndex.getUrl());//设置摘要resultReturnModenl.setDesc(getDesc(forwardIndex.getContent(),newTerms));results.add(resultReturnModenl);}return results;}/**生成正文摘要* 由于docInfo对象里面是正文所以还要做一些处理* 摘要要包含 查询词 或者 查询词的一部分* 生成摘要的思路可以遍历查询词的分词找到对应位置* 就针对这个位置往前截取60个字符作为描述的开始然后从描述开始在截取160个字符* param content* param newTerms* return*/public String getDesc(String content, ListTerm terms) {//记录分词出现的位置int termIndex -1;for (Term term:terms) {//获取到分词内容String wordName term.getName();//将正文转成小写 使用toLowerCase()//此处需要的是全词匹配,在word前后都加一个空 在进行查找//这里的匹配不严谨更严谨的方法是使用 正则表达式//indexOf不支持正则表达式//Java提供了 Pattern 和 Matcher 这两个类 来实现正则表达式,自己学习一下//Pattern : 描述一个匹配规则//Matcher 负责进行具体的匹配工作//这里的做法把不是空格的转成空格content content.toLowerCase().replaceAll(\\bwordName\\b, wordName );termIndex content.toLowerCase().indexOf( wordName );if (termIndex ! -1 ) {//存在break;}}if (termIndex -1) {//所有的分词结果都不存在//返回正文的前160个字符if (content.length() 160) {return content;}return content.substring(0,160)...;}//程序如果到这里说明正文中有分词结果//判断是否要往前60个字符termIndex termIndex - 60 0?termIndex-60:0;String desc ;//保存正文摘要if (termIndex160 content.length()) {//从termIndex这个位置截到尾desc content.substring(termIndex);} else {desc content.substring(termIndex,160termIndex)...;}//在此处加上替换操作把描述中的 和 分词结果相同的部分//加上依次i标签可以使用 replaceAll 的方法来实现//者样在前端显示的时候可以标红//遍历分词结果for (Term term:terms) {//获取到结果String word term.getName();//注意此处要进行全字匹配,不区分大小写替换desc desc.replaceAll((?i) word ,i word /i);}return desc;}/*** 合并listList中的数组并且进行去重* 类似于合并多个有序数组并且最后的结果要有序* param listList* return*/private ListWeight sortArray(ListArrayListWeight listList) {class Pos{public Integer row 0;//行public Integer col 0;//列public Pos(Integer row, Integer col) {this.row row;this.col col;}}//使用优先级队列来解决该问题//创建优先级队列PriorityQueuePos pos new PriorityQueue(new ComparatorPos() {Overridepublic int compare(Pos o1, Pos o2) {//小根堆return listList.get(o1.row).get(o1.col).getDocId() - listList.get(o2.row).get(o2.col).getDocId();}});//将每一个数组按docId的大小升序排序for (ArrayListWeight weights:listList) {Collections.sort(weights, new ComparatorWeight() {Overridepublic int compare(Weight o1, Weight o2) {return o1.getDocId() - o2.getDocId();}});}//将每一个数组的第一个元素的位置放进来for (int i 0; i listList.size(); i) {pos.offer(new Pos(i,0));}ListWeight listResult new ArrayList();//保存最后返回的结果while (!pos.isEmpty()) {//从优先级队列出来的队首元素Pos pos1 pos.poll();if (listResult.size() 0) {//插入第一个元素listResult.add(listList.get(pos1.row).get(pos1.col));} else {//不是第一个要判断是否于前一个相同,相同权重相加if (listResult.get(listResult.size() - 1).getDocId() listList.get(pos1.row).get(pos1.col).getDocId()) {//文档相同权重相加listResult.get(listResult.size() - 1).setWeight(listResult.get(listResult.size() - 1).getWeight()listList.get(pos1.row).get(pos1.col).getWeight());} else {//不相同,添加到listResult中listResult.add(listList.get(pos1.row).get(pos1.col));}}if (pos1.col 1 listList.get(pos1.row).size()) {//这一行处理完了continue;}pos.offer(new Pos(pos1.row, pos1.col1));}return listResult;}public static void main(String[] args) {Searcher searcher new Searcher();} } Web模块部分 Web模块部分实现前后端的交互。 Web模块的代码 RestController public class SearcherController {AutowiredSearcher searcher ;RequestMapping(/searcher)public Object searcher(String word) {if (word null || word.trim().equals()) {return -1;}return searcher.searcher(word);}RequestMapping(/getword)public String getWord(String word) {System.out.println(word);return word;} }
http://www.dnsts.com.cn/news/118344.html

相关文章:

  • 免费网站服务器域名地方信息网站源码
  • 典型营销型网站有哪些南昌网站建设行业现状
  • 建设网站策划书新乡集团网站建设
  • 网站备案后证书wordpress小蜜蜂
  • 做竞价推广的网站要求官方网站建设ppt
  • 北京大兴网站制作推广公司网页设计文案
  • 鑫路网站建设下载官方购物网站
  • 渭南网站建设服务哈尔滨市做网站
  • 成都专业网站排名推广wordpress的主题说明
  • 网站由哪些部分组成找人搭建网站多少钱
  • 网站去哪里备案域名备案是什么意思?
  • 合肥全员核酸检测谷歌seo排名工具
  • 建设银行温州支行官方网站同程旅游
  • 周口建设网站的wordpress仿36kr氪主题
  • 素材品牌词类的网站怎么做优化
  • 商城网站类建设哪家好沈阳网络建网站个人
  • 嘉兴公司做网站wordpress tag列表页
  • 用什么语言能写网站吗江西工厂网站建设
  • 义乌专业做网站给别人做ppt的网站
  • 做摄影网站的目的网站建设小公司生存
  • 施工员证查询官方网站网站建设报价费用是多少
  • 网站无法备案wordpress个人博客毕业设计
  • 哪有网站建设明细报价表个人网站还用备案吗
  • 做网上竞彩网站合法吗最新新闻事件2023
  • 珠海网站建设网络公司wordpress简便安装
  • 分析网站的关键词网页版视频怎么下载
  • 龙岗网站 建设seo信科找片子有什么好的关键词推荐
  • 衡水网站建设套餐自建站网址
  • 免费网站开发合同范本做修车行业需要在哪个网站做推广
  • 数商云是干嘛的杭州seo首页优化软件