导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2018/1/19 12:12:21
标题:
求各位DELPHI高手出马,封装一个结巴分词的DLL
浏览:6794
加入我的收藏
楼主:
这里有C语言的结巴分词 https://github.com/yanyiwu/cjieba ,小白多次尝试封装失败,求高手出马。
----------------------------------------------
-
作者:
2018/1/19 16:35:30
1楼:
话说,人家这个东西不是挺小巧的么? 有那么麻烦么? 用vc2017打的包, 有改动需求的话就自己改一下就可以了。
----------------------------------------------
--
作者:
2018/1/19 16:37:35
2楼:
这里是导出函数。 没有改约定的,默认统统都是cdcel
此帖子包含附件: 大小: 35.5K
----------------------------------------------
--
作者:
2018/1/19 17:31:58
3楼:
感谢楼上,我试试。我用vs2017打包失败,然后用GCC,打出来的不能用,只要是对C++不太懂
----------------------------------------------
-
作者:
2018/1/19 17:36:06
3楼:
ICTCLAS50.dll 或NLPIR.dl 用下就OK的拉。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/19 17:46:07
4楼:
@letianwuji 你说的这个有1个月授权限制呢,而且貌似经常不更新授权
----------------------------------------------
-
作者:
2018/1/19 19:49:24
5楼:
@badwood csdn上面有破解版,不需要授权key的dll,我发布的。 ICTCLAS50.dll 或NLPIR.dl这两个都有。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/19 22:00:32
6楼:
http://download.csdn.net/download/letianwuji/7184937 http://download.csdn.net/download/letianwuji/9430904
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/19 22:14:35
7楼:
10220f24e0925509c5fa45ea3495fd35
----------------------------------------------
-
作者:
2018/1/20 11:15:59
8楼:
@letianwuji 感谢分享,我下载了
----------------------------------------------
-
作者:
2018/1/20 12:57:38
9楼:
@letianwuji 能提供一下可用的接口PAS吗,sample/win32下的那个是自动导出的不能用呢。
----------------------------------------------
-
作者:
2018/1/20 14:31:18
10楼:
改了一个NLPIR.pas,正在测试
----------------------------------------------
-
作者:
2018/1/20 15:43:11
11楼:
请教,这一段C代码,改成pascal应该怎么写 typedef struct { const char* word; size_t len; } CJiebaWord; CJiebaWord* words = Cut(handle, s, len); CJiebaWord* x; for (x = words; x && x->word; x++) { printf("%*.*s\n", x->len, x->len, x->word); }
----------------------------------------------
-
作者:
2018/1/20 18:17:13
12楼:
type pjiebaword = ^tjiebaword; tjiebaword = record word: lpcstr; {$ifdef cpux64} len: uint64; {$else} len: uint; {$endif} end; var p, pwords: pjiebaword; begin pwords := cut(handle, s, len); p := pwords; while (nil != p) and (nil != p^.word) do begin showmessage(p^.word); inc(p); end; end;
----------------------------------------------
--
作者:
2018/1/20 19:06:53
13楼:
弱弱问一句,这里为什么不直接用pwords而要赋值给p?
----------------------------------------------
-
作者:
2018/1/20 20:30:51
14楼:
pwords是通过函数分配出来的内存入口指针,也就是数组的入口地址。 而p是用来遍历数组元素用的。如果不通过另一个变量来遍历数组的话,那分配出来的数组入口地址就丢失了,那么这段内存就无法回收了。
----------------------------------------------
--
作者:
2018/1/20 20:39:42
15楼:
受教了
----------------------------------------------
-
作者:
2018/1/20 23:32:08
16楼:
楼主,做成后分享出来哦 :)
----------------------------------------------
-
作者:
2018/1/21 8:17:10
17楼:
用c的.h文件,转换成pas文件就好的,有工具的。 C2PascalhConver
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/21 11:48:13
18楼:
关于12楼的代码 while (nil != p) and (nil != p^.word) do begin showmessage(p^.word); inc(p); end; 以文本‘南京市长江大桥’为例,输出的结果是 南京市长江大桥 京市长江大桥 市长江大桥 长江大桥 江大桥 大桥 桥 ========== 这是哪里不对?
----------------------------------------------
-
作者:
2018/1/21 12:03:53
19楼:
这是我做的结巴的接口。
----------------------------------------------
-
作者:
2018/1/21 12:06:40
20楼:
测试代码如下: var DICT_PATH, HMM_PATH, USER_DICT, IDF_PATH, STOP_WORDS_PATH: ansistring; Ahandle: Thandle; txtlen: cardinal; txt: ansistring; pw, words: pjiebaword; begin DICT_PATH := './dict/jieba.dict.utf8'; HMM_PATH := './dict/hmm_model.utf8'; USER_DICT := './dict/user.dict.utf8'; IDF_PATH := './dict/idf.utf8'; STOP_WORDS_PATH := './dict/stop_words.utf8'; Ahandle := NewJieba(PAnsiChar(DICT_PATH), PAnsiChar(HMM_PATH), PAnsiChar(USER_DICT), PAnsiChar(IDF_PATH), PAnsiChar(STOP_WORDS_PATH)); txt := '南京市长江大桥'; txtlen := length(txt); words := Cut(Ahandle, PAnsiChar(txt), txtlen); pw := words; while (nil <> pw) and (nil <> pw^.word) do begin Mdest.Lines.Append(pw^.len.tostring + ' ' + pw^.word); inc(pw); end; FreeWords(words); FreeJieba(Ahandle); ========== 运行结果就是18楼那样,如果用pw^.len来判断输出,则例句被分解为单字,没有Cjiega源码生成的DEMO.EXE中的效果。 不得不说,cjieba的初始化函数加载真的很慢,但为什么释放也很慢,就不懂了。
----------------------------------------------
-
作者:
2018/1/21 12:24:12
21楼:
找到原因了,输入的文本需要转为utf8编码,输出再解码,然后 循环按照pw^.len的长度自己截取字符串,和C里直接可以输出pw^.word不同。
----------------------------------------------
-
作者:
2018/1/21 14:29:57
22楼:
抽空写个Demo
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/21 16:48:34
23楼:
@badwood, 非常感谢分享! 关于“找到原因了,输入的文本需要转为utf8编码,输出再解码,然后 循环按照pw^.len的长度自己截取字符串,和C里直接可以输出pw^.word不同。”,可以给一段演示代码吗?谢谢。 @letianwuji, .pdf文件?
----------------------------------------------
-
作者:
2018/1/21 17:25:02
24楼:
演示如下: var DICT_PATH, HMM_PATH, USER_DICT, IDF_PATH, STOP_WORDS_PATH: ansistring; Ahandle: Thandle; txtlen: cardinal; txt,newtxt: ansistring; pw, words: pjiebaword; tag: RawByteString; begin DICT_PATH := './jiebadict/jieba.dict.utf8'; HMM_PATH := './jiebadict/hmm_model.utf8'; USER_DICT := './jiebadict/user.dict.utf8'; IDF_PATH := './jiebadict/idf.utf8'; STOP_WORDS_PATH := './jiebadict/stop_words.utf8'; Ahandle := NewJieba(PAnsiChar(DICT_PATH), PAnsiChar(HMM_PATH), PAnsiChar(USER_DICT), PAnsiChar(IDF_PATH), PAnsiChar(STOP_WORDS_PATH)); txt := trim(Msource.Text); txt := utf8encode(txt); txtlen := length(txt); words := Cut(Ahandle, PAnsiChar(txt), txtlen); newtxt := ''; pw := words; while (nil <> pw) and (nil <> pw^.word) do begin tag := UTF8Decode(leftstr(pw^.word, pw^.len)); newtxt := newtxt + tag + '/'; inc(pw); end; Mdest.Lines.Append(newtxt); FreeWords(words); FreeJieba(Ahandle);
----------------------------------------------
-
作者:
2018/1/21 17:52:06
25楼:
@badwood, 多谢!成功了,效果如下: 我/是/拖拉机/学院/手扶拖拉机/专业/的/。/不用/多久/,/我/就/会/升职/加薪/,/当上/CEO/,/走上/人生/巅峰/。/
----------------------------------------------
-
作者:
2018/1/21 17:59:59
26楼:
jieba初始化很慢,而且释放也特别慢,比源码里的命令行DEMO慢了很多。不知道是哪里有问题。 NLPIR好像无法加载自定义TXT词库,只看到一个个加的函数,也没找到禁用词库的设置。
----------------------------------------------
-
作者:
2018/1/21 18:00:55
26楼:
@badwood,这个dll即可以后有可能用得上,以感激您的名义,给这个论坛捐款¥100,非常微不足道,微不足道,微不足道,仅表心意。
----------------------------------------------
-
作者:
2018/1/21 18:06:07
27楼:
我不清楚官方demo的运行速度,不过这里,jieba dll库的官方例子: https://github.com/yanyiwu/cjieba/blob/master/demo.c 里面的注释说: // init will take a few seconds to load dicts. 也就是说,初始化(主要是载入词典)需要几秒钟的时间。我这里测试你的例子,时间差不多。
----------------------------------------------
-
作者:
2018/1/21 18:59:48
28楼:
初始化慢可以理解,但是释放也很慢啊,你测试没有?
----------------------------------------------
-
作者:
2018/1/21 21:05:58
29楼:
兰州既然都编译过人家的demo了。怎么不看看人家的注释呢? 人家不是已经告诉你了在初始化的时候需要等待几秒的时间来加载词典么? 至于为什么释放慢,那也和回收内存有关,兰州可以换个内存管理器看看。
----------------------------------------------
--
作者:
2018/1/21 21:44:04
30楼:
@badwood, FreeJieba(Ahandle)这句,我这里xe4测试执行很快的。只有初始化需要几秒。
----------------------------------------------
-
作者:
2018/1/22 10:06:12
31楼:
XE6/XE10 测试 ,FreeJieba 基本都是 13秒多,我简直懵逼了
----------------------------------------------
-
作者:
2018/1/22 12:06:31
32楼:
这么夸张?no idea...
----------------------------------------------
-
作者:
2018/1/22 12:12:31
32楼:
我也是醉了...以ICTCLAS50_Windows_32_C 破解版为例: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TCodeType = (CODE_TYPE_UNKNOWN,CODE_TYPE_ASCII,CODE_TYPE_GB, CODE_TYPE_UTF8, CODE_TYPE_BIG5); tagICTCLAS_Result = record iStartPos: integer; //开始位置 iLength: integer; //长度 szPOS: string;//词性 iPOS: integer; //词性ID iWordID : integer; //词ID iWordType: integer; //词语类型,用户词汇?(0-否,1-是) iWeight: integer;// 词语权重 end; PtagICTCLAS_Result = ^tagICTCLAS_Result; result_t = record start: integer; length: integer; {$IF Defined(POS_TAGGER) } iPOS: integer; sPos: array[0..POS_SIZE - 1] of char; {$IFEND} word_ID: integer; word_type: integer; weight: integer; end; Presult_t = ^result_t; TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; const dll = 'ICTCLAS50.dll'; implementation function ICTCLAS_Init(pszInitDir: pchar = nil): boolean; cdecl; external dll; function ICTCLAS_SetPOSmap(nPOSmap: integer): boolean; cdecl; external dll; function ICTCLAS_ParagraphProcess(const pszText: pchar;iLength: integer;pszResult: PAnsichar;codeType :TCodeType;bEnablePOS: boolean = false): integer; cdecl; external dll; function ICTCLAS_nativeProcAPara(sSrc:PByteArray;eCodeType:Integer;bPOStagged:Integer): PByteArray; cdecl; external dll; {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var nRstLen: integer; sSentence: pchar; sRst: pchar; eCt: TCodeType; nrc: pinteger; fc : PtagICTCLAS_Result; fca: Presult_t; nativeBytes : PByteArray; begin //var RtnStream :TMemoryStream; Str :String; //把字符串以byte方式,写入到流,不额外复制值。 //ReqStream.WriteBuffer(Str [1], length(Str )); if ICTCLAS_Init() then begin //showmessage('OK'); ICTCLAS_SetPOSmap(2);// (2:gb2312、GBK、gb18030) sSentence := pchar(memo1.Lines.Text); getmem(sRst, length(sSentence)*60);//开辟内存 ICTCLAS_ParagraphProcess(sSentence,length(sSentence),sRst,CODE_TYPE_GB,False); showmessage(sRst); end else showmessage('no'); end; end. delphi7编译...整个包有些不小,我传FTP
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/22 12:16:04
33楼:
链接: https://pan.baidu.com/s/1i7lEI4P 密码: qgmy
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/22 13:07:27
34楼:
@letianwuji 我用你的NLPIR.DLL 做了一个NLPIR.pas,可以用。 但目前测试导入自定义词库 NLPIR_ImportUserDict,但导入后是永久的,如果要更换自定义词库就很麻烦,貌似只能一个词一个词从库里删除,试过直接删pdat文件也不行。 另外,NLPIR_ImportKeyBlackList 导入禁用词库后如果词语和用户词库有重复,就不会生效,并且没有删除禁用词的方法…………
----------------------------------------------
-
作者:
2018/1/23 12:46:03
35楼:
不看官方手册的,是伐。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/23 18:07:54
36楼:
看过了,并没有找到我需要的资料,只得自己测试,不得不说,那份手册写的很粗略。
----------------------------------------------
-
作者:
2018/1/23 18:14:29
37楼:
5 .1 9 新词发现批量处理功能 注:从 2016 版本开始,该功能独立为关键词抽取组件,对应函数为: NWF_Batch_Start, NWF_Batch_AddFile, NWF_Batch_AddMem, NWF_Batch_Complete, NWF_Batch_GetResult, NWF_Result2UserDict() 请 访 问 : https://github.com/NLPIR-team/NLPIR/tree/master/NLPIR%20SDK/NewWordFinder
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2018/1/26 11:26:56
38楼:
@letianwuji NLPIR 2016版本有一个NLPIR_CleanUserWord()的函数,可以批量删除用户自定义词库。不过你破解的DLL版本里没有这个函数。 所以如果要修改、更换用户词库,只能用NLPIR_DelUsrWord一条条删除,如果词库较大,就比较麻烦了。
----------------------------------------------
-
作者:
2019/8/6 1:48:33
39楼:
好吧,我把最新版破解一遍...
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2019/8/8 14:30:59
40楼:
好贴,别沉了
----------------------------------------------
-