首页 文章 精选 留言 我的

精选列表

搜索[PD分离],共10006篇文章
优秀的个人博客,低调大师

HanLP代码与词典分离方案与流程

之前在spark环境中一直用的是portable版本,词条数量不是很够,且有心想把jieba,swcs词典加进来, 其他像ik,ansi-seg等分词词典由于没有词性并没有加进来. 本次修改主要是采用jar包方包将词典目录 data与hanlp.properties合成一个data.jar文件. 1. pom.xml 过滤资源文件的配置 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>${maven-jar-plugin.version}</version> <configuration> <excludes> <exclude>**/*.properties</exclude> </excludes> </configuration> </plugin> 这里把properties文件从jar包文件中去掉,因而结果文件是没有properties文件的. 可根据需要来确定是否把properties加入jar包中.由于我打算把hanlp.properties与词典目录写在一起 这里是要过滤掉hanlp.properties文件 2. 修改hanlp.properties文件 root= #将根目录置为空,或者注释掉root CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; scws.txt; jieba.txt; 现代汉语补充词库.txt; 全国地名大全.txt ns; 人名词典.txt; 机构名词典.txt; 上海地名.txt ns;data/dictionary/person/nrf.txt nrf; #增加更多的配置文件,这里增加了结巴分词,scws分词 #IOAdapter=com.hankcs.hanlp.corpus.io.FileIOAdapter IOAdapter=com.hankcs.hanlp.corpus.io.JarIOAdapter #修改IOAdapter,以便使用jar包形式加载词典 3. 修改HanLP.java if ( root.length() != 0 && !root.endsWith("/")) root += "/"; 当root的长度为0时,不用在root字符串后面添加'/' 4. 增加处理词典jar包的代码文件: JarIOAdapter.java package com.hankcs.hanlp.corpus.io; import java.io.*; /** * 基于普通文件系统的IO适配器 * * @author hankcs */ public class JarIOAdapter implements IIOAdapter { @Override public InputStream open(String path) throws FileNotFoundException { /* 采用第一行的方式加载资料会在分布式环境报错 改用第二行的方式 */ //return ClassLoader.getSystemClassLoader().getResourceAsStream(path); return JarIOAdapter.class.getClassLoader().getResourceAsStream(path); } @Override public OutputStream create(String path) throws FileNotFoundException { return new FileOutputStream(path); } } 在跑DemoStopWord时,发现 java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoStopWord 报错,原因是接口不统一导致. 修改 DMAG.java如下: public MDAG(File dataFile) throws IOException { BufferedReader dataFileBufferedReader = new BufferedReader(new InputStreamReader(IOAdapter == null ? new FileInputStream(dataFile) : //IOAdapter.open(dataFile.getAbsolutePath()) IOAdapter.open(dataFile.getPath()) , "UTF-8")); 即可. 5. 如何将词典与配置文件打成一个jar包 最好是把txt格式的文件做成bin或dat格式的文件,然后做成jar包,否则打包运行后无法再写成bin或dat格式文件. 简单的办法是跑一下示例,即可生成相应的bin或dat格式文件. java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoAtFirstSight java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoChineseNameRecognition java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoJapaneseNameRecognition java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoPinyin java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoPlaceRecognition java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoOrganizationRecognition java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoTokenizerConfig #命名实体识别,包括上面的人名,地名等 java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoTraditionalChinese2SimplifiedChinese java -cp .:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoStopWord 或者用以下shell脚本完成 :>a;while read cl; do echo $cl; echo "=========="$cl"=======" >>a;java -cp .:test.jar:hanlp-1.3.2.jar $cl 1>> a 2>&1;done < <(jar tvf test.jar | awk '$(NF)~"Demo"{print $(NF)}' | sed 's/.class$//;s/\//./g') 我们把data目录与hanlp.properties文件放在一个目录,比如xxx目录 cd xxx jar cvf data.jar . 即可生成data.jar包 6. 如何运行 [dxp@Flyme-SearchTag-32-220 makeNewDict]$ ls data.jar hanlp-1.3.2.jar README.md test test.jar [dxp@Flyme-SearchTag-32-220 makeNewDict]$ java -cp data.jar:hanlp-1.3.2.jar:test.jar com.hankcs.demo.DemoAtFirstSight 7. 在spark中应用 IDE如(intellij idea)中maven项目 引入以下依赖: <dependency> <groupId>com.hankcs</groupId> <artifactId>hanlp</artifactId> <version>1.3.2</version> <scope>system</scope> <systemPath>${LocalPath}/hanlp-1.3.2.jar</systemPath> </dependency> spark-submit提交任务时增加 --jar hanlp-1.3.2.jar,data.jar 转载自cicido的个人空间

优秀的个人博客,低调大师

计算与存储分离实践—swift消息系统

1. 相关背景 搜索事业部与计算平台事业部目前使用消息队列主要有以下三种场景: 1. 每天有上万张表需要通过Build Service来构建索引。这些表主要来自主搜索,IGRAPH,Rank Service等业务,且每个表包含的文档数差别很大。总数据量为PB级别,总文档数达万亿级。文档的大小不一,小到几十Byte大到几百KB。在Build Service内部,文档处理与索引构建需要一个消息队列来传送消息。因此在build时,容易产生突发大流量(几百G/秒,几千万条/秒)持续消息写入与读取。 2. 搜索的在线服务如主搜索查询服务,RankService打分服务或IGRAPH服务需要毫秒级的实时文档更新。这些服务引擎基本上是多行多列结构,即每一行是一个完整的服务单元,由多台机器组成,多行提升服务

优秀的个人博客,低调大师

前后分离模型之封装 Api 调用

Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过程结束的时候调用的接口。比如 jQuery Ajax 的 success 就是典型的回调参数。不过使用 jQuery 处理异步推荐使用 Promise 处理方式。 Promise 处理方式也是通过注册回调函数来完成的。jQuery 的 Promise 和 ES6 的标准 Promise 有点不一样,但在 then 上可以兼容,通常称为 thenable。jQuery 的 Promise 没有提供 .catch() 接口,但它自己定义的 .done()、.fail() 和 .always() 三个注册回调的方式也很有特色,用起来很方便,它是在事件的方式来注册的(即,可以注册多个同类型的处理函数,在该触发的时候都会触发)。 当然更直观的一点的处理方式是使用 ES2017 带来的 async/await 方式,可以用同步代码的形式来写异步代码,当然也有一些坑在里面。对于前端工程师来说,最大的坑就是有些浏览器不支持,需要进行转译,所以如果前端代码没有构建过程,一般还是就用 ES5 的语法兼容性好一些(jQuery 的 Promise 是支持 ES5 的,但是标准 Promise 要 ES6 以后才可以使用)。 关于 JavaScript 异步处理相关的内容可以参考 从小小题目逐步走进 JavaScript 异步调用 闲谈异步调用“扁平”化 从地狱到天堂,Node 回调向 async/await 转变 理解 JavaScript 的 async/await 从不用 try-catch 实现的 async/await 语法说错误处理 自己封装工具函数 在处理 Ajax 的过程中,虽然有现成的库(比如 jQuery.ajax,axios 等),它毕竟是为了通用目的设计的,在使用的时候仍然不免繁琐。而在项目中,对 Api 进行调用的过程几乎都大同小异。如果设计得当,就连错误处理的方式都会是一样的。因此,在项目内的 Ajax 调用其实可以进行进一步的封装,使之在项目内使用起来更方便。如果接口方式发生变化,修改起来也更容易。 比如,当前接口要求使用 POST 方法调用(暂不考虑 RESTful),参数必须包括 action,返回的数据以 JSON 方式提供,如果出错,只要不是服务器异常都会返回特定的 JSON 数据,包括一个不等于 0 的 code 和可选的 message 属性。 那么用 jQuery 写这么一个 Ajax 调用,大概是这样 const apiUrl = "http://api.some.com/"; jQuery .ajax(url, { type: "post", dataType: "json", data: { action: "login", username: "uname", password: "passwd" } }) .done(function(data) { if (data.code) { alert(data.message || "登录失败!"); } else { window.location.assign("home"); } }) .fail(function() { alert("服务器错误"); }); 初步封装 同一项目中,这样的 Ajax 调用,基本上只有 data 部分和 .done 回调中的 else 部分不同,所以进行一次封装会大大减少代码量,可以这样封装 function appAjax(action, params) { var deffered = $.Deferred(); jQuery .ajax(apiUrl, { type: "post", dataType: "json", data: $.extend({ action: action }, params) }) .done(function(data) { // 当 code 为 0 或省略时,表示没有错误, // 其它值表示错误代码 if (data.code) { if (data.message) { // 如果服务器返回了消息,那么向用户呈现消息 // resolve(null),表示不需要后续进行业务处理 alert(data.message); deffered.resolve(); } else { // 如果服务器没返回消息,那么把 data 丢给外面的业务处理 deferred.reject(data); } } else { // 正常返回数据的情况 deffered.resolve(data); } }) .fail(function() { // Ajax 调用失败,向用户呈现消息,同时不需要进行后续的业务处理 alert("服务器错误"); deffered.resolve(); }); return deferred.promise(); } 而业务层的调用就很简单了 appAjax("login", { username: "uname", password: "passwd" }).done(function(data) { if (data) { window.location.assign("home"); } }).fail(function() { alert("登录失败"); }); 更换 API 调用接口 上面的封装对调用接口和返回数据进行了统一处理,把大部分项目接口约定的内容都处理掉了,剩下在每次调用时需要处理的就是纯粹的业务。 现在项目组决定不用 jQuery 的 Ajax,而是采用 axios 来调用 API(axios 不见得就比 jQuery 好,这里只是举例),那么只需要修改一下 appAjax() 的实现即可。所有业务调用都不需要修改。 假设现在的目标环境仍然是 ES5,那么需要第三方 Promise 提供,这里拟用 Bluebird,兼容原生 Promise 接口(在 HTML 中引入,未直接出现在 JS 代码中)。 function appAjax(action, params) { var deffered = $.Deferred(); axios .post(apiUrl, { data: $.extend({ action: action }, params) }) .then(function(data) { ... }, function() { ... }); return deferred.promise(); } 这次的封装采用了 axios 来实现 Web Api 调用。但是为了保持原来的接口(jQuery Promise 对象有提供 .done()、.fail() 和 .always() 事件处理),appAjax 仍然不得不返回 jQuery Promise。这样,即使所有地方都不再需要使用 jQuery,这里仍然得用。 项目中应该用还是不用 jQuery?请阅读为什么要用原生 JavaScript 代替 jQuery? 去除 jQuery 就只在这里使用 jQuery 总让人感觉如芒在背,想把它去掉。有两个办法 修改所有业务中的调用,去掉 .done()、.fail() 和 .always(),改成 .then()。这一步工作量较大,但基本无痛,因为 jQuery Promise 本身支持 .then()。但是有一点需要特别注意,这一点稍后说明 自己写个适配器,兼容 jQuery Promise 的接口,工作量也不小,但关键是要充分测试,避免差错。 上面提到第 1 种方法中有一点需要特别注意,那就是 .then() 和 .done() 系列函数在处理方式上有所不同。.then() 是按 Promise 的特性设计的,它返回的是另一个 Promise 对象;而 .done() 系列函数是按事件机制实现的,返回的是原来的 Promise 对象。所以像下面这样的代码在修改时就要注意了 appAjax(url, params) .done(function(data) { console.log("第 1 处处理", data) }) .done(function(data) { console.log("第 2 处处理", data) }); // 第 1 处处理 {} // 第 2 处处理 {} 简单的把 .done() 改成 .then() 之后(注意不需要使用 Bluebird,因为 jQuery Promise 支持 .then()) appAjax(url, params) .then(function(data) { console.log("第 1 处处理", data); }) .then(function(data) { console.log("第 2 处处理", data); }); // 第 1 处处理 {} // 第 2 处处理 undefined 原因上面已经讲了,这里正确的处理方式是合并多个 done 的代码,或者在 .then() 处理函数中返回 data: appAjax(url, params) .then(function(data) { console.log("第 1 处处理", data); return data; }) .then(function(data) { console.log("第 2 处处理", data); }); 使用 Promise 接口改善设计 我们的 appAjax() 接口部分也可以设计成 Promise 实现,这是一个更通用的接口。既使用不用 ES2015+ 特性,也可以使用像 jQuery Promise 或 Bluebird 这样的三方库提供的 Promise。 function appAjax(action, params) { // axios 依赖于 Promise,ES5 中可以使用 Bluebird 提供的 Promise return axios .post(apiUrl, { data: $.extend({ action: action }, params) }) .then(function(data) { // 这里调整了判断顺序,会让代码看起来更简洁 if (!data.code) { return data; } if (!data.message) { throw data; } alert(data.message); }, function() { alert("服务器错误"); }); } 不过现在前端有构建工具,可以使用 ES2015+ 配置 Babel,也可以使用 TypeScript …… 总之,选择很多,写起来也很方便。那么在设计的时候就不用局限于 ES5 所支持的内容了。所以可以考虑用 Promise + async/await 来实现 async function appAjax(action, params) { // axios 依赖于 Promise,ES5 中可以使用 Bluebird 提供的 Promise const data = await axios .post(apiUrl, { data: $.extend({ action: action }, params) }) // 这里模拟一个包含错误消息的结果,以便后面统一处理错误 // 这样就不需要用 try ... catch 了 .catch(() => ({ code: -1, message: "服务器错误" })); if (!data.code) { return data; } if (!data.message) { throw data; } alert(data.message); } 上面代码中使用 .catch() 来避免 try ... catch ... 的技巧在从不用 try-catch 实现的 async/await 语法说错误处理中提到过。 当然业务层调用也可以使用 async/await(记得写在 async 函数中): const data = await appAjax("login", { username: "uname", password: "passwd" }).catch(() => { alert("登录失败"); }); if (data) { window.location.assign("home"); } 对于多次 .done() 的改造: const data = await appAjax(url, params); console.log("第 1 处处理", data); console.log("第 2 处处理", data); 小结 本文以封装 Ajax 调用为例,看似在讲述异步调用。但实际想告诉大家的东西是:如何将一个常用的功能封装起来,实现代码重用和更简洁的调用;以及在封装的过程中需要考虑的问题——向前和向后的兼容性,在做工具函数封装的时候,应该尽量避免和某个特定的工具特性绑定,向公共标准靠拢——不知大家是否有所体会。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册