本文引用自: http://blog.chinaunix.net/uid-20726500-id-4820580.html

防止文章丢失才进行复制

PostgreSQL支持全文检索,其内置的缺省的分词解析器采用空格分词。因为中文的词语之间没有空格分割,所以这种方法并不适用于中文。要支持中文的全文检索需要额外的中文分词插件。网上查了下,可以给PG用的开源中文分词插件有两个:nlpbamboo和zhparser。但是nlpbamboo是托管在googlecode上的,而googlecode被封了,下载不方便。下面尝试采用zhparser进行中文的全文检索。

zhparser是基于Simple Chinese Word Segmentation(SCWS)中文分词库实现的一个PG扩展,作者是 amutu,源码URL为https://github.com/amutu/zhparser。

1. 安装

1.1 下载SCWS

http://www.xunsearch.com/scws/down/scws-1.2.2.tar.bz2

1.2 编译和安装SCWS

tar xvf scws-1.2.2.tar.bz2
cd scws-1.2.2
./configure
make install

1.3 下载zhparser

https://github.com/amutu/zhparser/archive/master.zip

1.4 编译和安装zhparser

确保PostgreSQL的二进制命令路径在PATH下,然后解压并进入zhparser目录后,编译安装zhparser。
SCWS_HOME=/usr/local make && make install

2 配置中文全文检索

连接到目标数据库进行中文全文检索的配置

2.1 安装zhparser扩展

点击(此处)折叠或打开

  1. -bash-4.1$ psql testdb
  2. psql (9.4.0)
  3. Type "help" for help.
  4. testdb=# create extension zhparser;
  5. CREATE EXTENSION

安装zhparser扩展后多一个叫“zhparser”的解析器

点击(此处)折叠或打开

  1. testdb=# \dFp
  2. List of text search parsers
  3. Schema | Name | Description
  4. ------------+----------+---------------------
  5. pg_catalog | default | default word parser
  6. public | zhparser |
  7. (2 rows)

zhparser可以将中文切分成下面26种token
点击(此处)折叠或打开

  1. testdb=# select ts_token_type('zhparser');
  2. ts_token_type
  3. -----------------------------------------
  4. (97,a,adjective)
  5. (98,b,"differentiation (qu bie)")
  6. (99,c,conjunction)
  7. (100,d,adverb)
  8. (101,e,exclamation)
  9. (102,f,"position (fang wei)")
  10. (103,g,"root (ci gen)")
  11. (104,h,head)
  12. (105,i,idiom)
  13. (106,j,"abbreviation (jian lue)")
  14. (107,k,head)
  15. (108,l,"tmp (lin shi)")
  16. (109,m,numeral)
  17. (110,n,noun)
  18. (111,o,onomatopoeia)
  19. (112,p,prepositional)
  20. (113,q,quantity)
  21. (114,r,pronoun)
  22. (115,s,space)
  23. (116,t,time)
  24. (117,u,auxiliary)
  25. (118,v,verb)
  26. (119,w,"punctuation (qi ta biao dian)")
  27. (120,x,unknown)
  28. (121,y,"modal (yu qi)")
  29. (122,z,"status (zhuang tai)")
  30. (26 rows)

2.2 创建使用zhparser作为解析器的全文搜索的配置

点击(此处)折叠或打开

  1. testdb=# CREATE TEXT SEARCH CONFIGURATION testzhcfg (PARSER = zhparser);
  2. CREATE TEXT SEARCH CONFIGURATION

2.3 往全文搜索配置中增加token映射

点击(此处)折叠或打开

  1. testdb=# ALTER TEXT SEARCH CONFIGURATION testzhcfg ADD MAPPING FOR n,v,a,i,e,l WITH simple;
  2. ALTER TEXT SEARCH CONFIGURATION

上面的token映射只映射了名词(n),动词(v),形容词(a),成语(i),叹词(e)和习用语(l)6种,这6种以外的token全部被屏蔽。词典使用的是内置的simple词典,即仅做小写转换。根据需要可以灵活定义词典和token映射,以实现屏蔽词和同义词归并等功能。

3.中文分词测试

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','南京市长江大桥');
  2. to_tsvector
  3. -------------------------
  4. '南京市':1 '长江大桥':2
  5. (1 row)

中文分词有最大匹配,最细粒度等各种常用算法。上面的分词结果没有把'长江大桥'拆成'长江'和'大桥'两个词,所以SCWS估计是采取的最大匹配的分词算法。
分词算法的优劣一般通过3个指标衡量。
效率:
  索引和查询的效率
召回率:
  提取出的正确信息条数 /  样本中的信息条数 
准确率:
  提取出的正确信息条数 /  提取出的信息条数
分词的粒度越粗,效率越高,但遗漏的可能性也会高一点,即召回率受影响。具体到上面的例子,用'南京&大桥'就没法匹配到。

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','南京市长江大桥') @@ '南京&大桥';
  2. ?column?
  3. ----------
  4. f
  5. (1 row)

效率,召回率和准确率3个指标往往不能兼顾,所以不能笼统的说最大匹配好还是不好。但是如果特别在乎召回率,SCWS也提供了一些选项进行调节。下面是scws命令可接受的参数。
http://www.xunsearch.com/scws/docs.php#utilscws

点击(此处)折叠或打开

  1. 1. **$prefix/bin/scws** 这是分词的命令行工具,执行 scws -h 可以看到详细帮助说明。
  2. ```
  3. Usage: scws [options] [[-i] input] [[-o] output]
  4. ```
  5. * _-i string|file_ 要切分的字符串或文件,如不指定则程序自动读取标准输入,每输入一行执行一次分词
  6. * _-o file_ 切分结果输出保存的文件路径,若不指定直接输出到屏幕
  7. * _-c charset_ 指定分词的字符集,默认是 gbk,可选 utf8
  8. * _-r file_ 指定规则集文件(规则集用于数词、数字、专有名字、人名的识别)
  9. * _-d file[:file2[:...]]_ 指定词典文件路径(XDB格式,请在 -c 之后使用)
  10. ```
  11. 自 1.1.0 起,支持多词典同时载入,也支持纯文本词典(必须是.txt结尾),多词典路径之间用冒号(:)隔开,
  12. 排在越后面的词典优先级越高。
  13. 文本词典的数据格式参见 scws-gen-dict 所用的格式,但更宽松一些,允许用不定量的空格分开,只有<词>是必备项目,
  14. 其它数据可有可无,当词性标注为“!”(叹号)时表示该词作废,即使在较低优先级的词库中存在该词也将作废。
  15. ```
  16. * _-M level_ 复合分词的级别:1~15,按位异或的 1|2|4|8 依次表示 短词|二元|主要字|全部字,缺省不复合分词。
  17. * _-I_ 输出结果忽略跳过所有的标点符号
  18. * _-A_ 显示词性
  19. * _-E_ 将 xdb 词典读入内存 xtree 结构 (如果切分的文件很大才需要)
  20. * _-N_ 不显示切分时间和提示
  21. * _-D_ debug 模式 (很少用,需要编译时打开 --enable-debug)
  22. * _-U_ 将闲散单字自动调用二分法结合
  23. * _-t num_ 取得前 num 个高频词
  24. * _-a [~]attr1[,attr2[,...]]_ 只显示某些词性的词,加~表示过滤该词性的词,多个词性之间用逗号分隔
  25. * _-v_ 查看版本

通过-M指定短词的复合分词,可以得到细粒度的分词。
默认是最大匹配:

点击(此处)折叠或打开

  1. [root@hanode1 tsearch_data]# scws -c utf8  -d dict.utf8.xdb  -r rules.utf8.ini "南京市长江大桥"
    南京市 长江大桥 
    +--[scws(scws-cli/1.2.2)]----------+
    | TextLen:   21                  |
    | Prepare:   0.0021    (sec)     |
    | Segment:   0.0003    (sec)     |
    +--------------------------------+

指定短词的复合分词,可以对长词再进行复合切分。

点击(此处)折叠或打开

  1. [root@hanode1 tsearch_data]# scws -c utf8  -d dict.utf8.xdb  -r rules.utf8.ini -M 1 "南京市长江大桥"
    南京市 南京 长江大桥 长江 大桥 
    +--[scws(scws-cli/1.2.2)]----------+
    | TextLen:   21                  |
    | Prepare:   0.0020    (sec)     |
    | Segment:   0.0002    (sec)     |
    +--------------------------------+

这样切分后"南京 & 大桥"也可以匹配。

甚至可以把重要的单字也切出来。

点击(此处)折叠或打开

  1. [root@hanode1 zhparser-0.1.4]# scws -c utf8  -d dict.utf8.xdb  -r rules.utf8.ini -M 5 "南京市长江大桥"
    南京市 南京 市 长江大桥 长江 大桥 江 桥 
    +--[scws(scws-cli/1.2.2)]----------+
    | TextLen:   21                  |
    | Prepare:   0.0020    (sec)     |
    | Segment:   0.0002    (sec)     |
    +--------------------------------+

这样切分后,"南京 & 桥"也可以匹配。

再变态一点,对短词和所有单字做复合切分。

点击(此处)折叠或打开

  1. [root@hanode1 zhparser-0.1.4]# scws -c utf8  -d dict.utf8.xdb  -r rules.utf8.ini -M 9 "南京市长江大桥"
    南京市 南京 南 京 市 长江大桥 长江 大桥 长 江 大 桥 
    +--[scws(scws-cli/1.2.2)]----------+
    | TextLen:   21                  |
    | Prepare:   0.0021    (sec)     |
    | Segment:   0.0003    (sec)     |
    +--------------------------------+

这样切分基本上可以不再遗漏匹配了,但是效率肯定受影响。
上面的选项是加在scws命令上的,也可以通过scws_set_multi()函数加到zhparser(libscws)上。
http://www.xunsearch.com/scws/docs.php#libscws:

点击(此处)折叠或打开

  1. 9. `void scws_set_multi(scws_t s, int mode)` 设定分词执行时是否执行针对长词复合切分。(例:“中国人”分为“中国”、“人”、“中国人”)。
  2. > **参数 mode** 复合分词法的级别,缺省不复合分词。取值由下面几个常量异或组合:
  3. >
  4. > - SCWS_MULTI_SHORT 短词
  5. > - SCWS_MULTI_DUALITY 二元(将相邻的2个单字组合成一个词)
  6. > - SCWS_MULTI_ZMAIN 重要单字
  7. > - SCWS_MULTI_ZALL 全部单字

修改zhparser.c,追加scws_set_multi()的调用
zhparser.c:

点击(此处)折叠或打开

  1. static void init(){
  2. char sharepath[MAXPGPATH];
  3. char * dict_path,* rule_path;
  4. if (!(scws = scws_new())) {
  5. ereport(ERROR,
  6. (errcode(ERRCODE_INTERNAL_ERROR),
  7. errmsg("Chinese Parser Lib SCWS could not init!\"%s\"",""
  8. )));
  9. }
  10. get_share_path(my_exec_path, sharepath);
  11. dict_path = palloc(MAXPGPATH);
  12. snprintf(dict_path, MAXPGPATH, "%s/tsearch_data/%s.%s",
  13. sharepath, "dict.utf8", "xdb");
  14. scws_set_charset(scws, "utf-8");
  15. scws_set_dict(scws,dict_path, SCWS_XDICT_XDB);
  16. rule_path = palloc(MAXPGPATH);
  17. snprintf(rule_path, MAXPGPATH, "%s/tsearch_data/%s.%s",
  18. sharepath, "rules.utf8", "ini");
  19. scws_set_rule(scws ,rule_path);
  20. scws_set_multi(scws ,SCWS_MULTI_SHORT|SCWS_MULTI_ZMAIN);//追加代码
  21. }

重新编译安装zhparser后,再restart PostgreSQL,可以看到效果。

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','南京市长江大桥');
  2. to_tsvector
  3. -------------------------------------------------------------------------
  4. '南京':2 '南京市':1 '大桥':6 '市':3 '桥':8 '江':7 '长江':5 '长江大桥':4
  5. (1 row)
  6. testdb=# select to_tsvector('testzhcfg','南京市长江大桥') @@ '南京 & 桥';
  7. ?column?
  8. ----------
  9. t
  10. (1 row)

tsquery也会被复合切分:

点击(此处)折叠或打开

  1. testdb=# select to_tsquery('testzhcfg','南京市长江大桥');
  2. to_tsquery
  3. -----------------------------------------------------------------------
  4. '南京市' & '南京' & '市' & '长江大桥' & '长江' & '大桥' & '江' & '桥'
  5. (1 row)

这可能不是我们需要的,tsquery切的太细会影响查询效率。做了个简单的测试,走gin索引,按这个例子对tsquery复合切分会比默认的最大切分慢了1倍。

点击(此处)折叠或打开

  1. testdb=# \d tb1
  2. Table "public.tb1"
  3. Column | Type | Modifiers
  4. --------+------+-----------
  5. c1 | text |
  6. Indexes:
  7. "tb1idx1" gin (to_tsvector('testzhcfg'::regconfig, c1))
  8. testdb=# insert into tb1 select '南京市长江大桥' from generate_series(1,10000,1);
  9. testdb=# explain analyze select count(*) from tb1 where to_tsvector('testzhcfg', c1) @@ '南京市 & 长江大桥'::tsquery;
  10. QUERY PLAN
  11. --------------------------------------------------------------------------------------------------------------------------------
  12. Aggregate (cost=348.53..348.54 rows=1 width=0) (actual time=6.077..6.077 rows=1 loops=1)
  13. -> Bitmap Heap Scan on tb1 (cost=109.51..323.53 rows=10001 width=0) (actual time=3.186..4.917 rows=10001 loops=1)
  14. Recheck Cond: (to_tsvector('testzhcfg'::regconfig, c1) @@ '''南京市'' & ''长江大桥'''::tsquery)
  15. Heap Blocks: exact=64
  16. -> Bitmap Index Scan on tb1idx1 (cost=0.00..107.01 rows=10001 width=0) (actual time=3.154..3.154 rows=10001 loops=1)
  17. Index Cond: (to_tsvector('testzhcfg'::regconfig, c1) @@ '''南京市'' & ''长江大桥'''::tsquery)
  18. Planning time: 0.117 ms
  19. Execution time: 6.127 ms
  20. (8 rows)
  21. Time: 6.857 ms
  22. testdb=# explain analyze select count(*) from tb1 where to_tsvector('testzhcfg', c1) @@ '南京市 & 南京 & 市 & 长江大桥 & 长江 & 大桥 & 江 & 桥'::tsquery;
  23. QUERY PLAN
  24. ------------------------------------------------------------------------------------------------------------------------------------------------
  25. -------------------------
  26. Aggregate (cost=396.53..396.54 rows=1 width=0) (actual time=10.823..10.823 rows=1 loops=1)
  27. -> Bitmap Heap Scan on tb1 (cost=157.51..371.53 rows=10001 width=0) (actual time=7.923..9.631 rows=10000 loops=1)
  28. Recheck Cond: (to_tsvector('testzhcfg'::regconfig, c1) @@ '''南京市'' & ''南京'' & ''市'' & ''长江大桥'' & ''长江'' & ''大桥'' & ''江''
  29. & ''桥'''::tsquery)
  30. Heap Blocks: exact=64
  31. -> Bitmap Index Scan on tb1idx1 (cost=0.00..155.01 rows=10001 width=0) (actual time=7.885..7.885 rows=10000 loops=1)
  32. Index Cond: (to_tsvector('testzhcfg'::regconfig, c1) @@ '''南京市'' & ''南京'' & ''市'' & ''长江大桥'' & ''长江'' & ''大桥'' & ''
  33. 江'' & ''桥'''::tsquery)
  34. Planning time: 0.111 ms
  35. Execution time: 10.879 ms
  36. (8 rows)
  37. Time: 11.586 ms

要回避这个问题可以做两套解析器,一套给tsvector用做复合切分;一套给tsquery用,不做复合切分。或者像上面测试例子中那样不对查询字符串做分词,由应用端直接输入tsquery(不过这样做会有别的问题,后面会提到)。

3.其它问题

3.1 '南大'被无视了

无意中发现一个奇怪的现象,'南大'被无视了:

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','南大') ;
  2. to_tsvector
  3. -------------
  4. (1 row)

'北大','东大'甚至'西大'都没问题:

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','南大 北大 东大 西大') ;
  2. to_tsvector
  3. ----------------------------
  4. '东大':2 '北大':1 '西大':3
  5. (1 row)

调查发现原因在于它们被SCWS解析出来的token类型不同:

点击(此处)折叠或打开

  1. testdb=# select ts_debug('testzhcfg','南大 北大 东大 西大') ;
  2. ts_debug
  3. -----------------------------------------
  4. (j,"abbreviation (jian lue)",南大,{},,)
  5. (n,noun,北大,{simple},simple,{北大})
  6. (n,noun,东大,{simple},simple,{东大})
  7. (n,noun,西大,{simple},simple,{西大})
  8. (4 rows)

'南大'被识别为j(简略词),而之前并没有为j创建token映射。现在加上j的token映射,就可以了。

点击(此处)折叠或打开

  1. testdb=# ALTER TEXT SEARCH CONFIGURATION testzhcfg ADD MAPPING FOR j WITH simple;
  2. ALTER TEXT SEARCH CONFIGURATION
  3. testdb=# select to_tsvector('testzhcfg','南大 北大 东大 西大') ;
  4. to_tsvector
  5. -------------------------------------
  6. '东大':3 '北大':2 '南大':1 '西大':4
  7. (1 row)

3.2 新词的识别

词典收录的词毕竟有限,遇到新词就不认识了。不断完善词典可以缓解这个问题,但不能从根本上避免。
'微信'没有被识别出来:

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','微信');
  2. to_tsvector
  3. ---------------
  4. '信':2 '微':1
  5. (1 row)
  6. testdb=# select to_tsvector('testzhcfg','微信') @@ '微信';
  7. ?column?
  8. ----------
  9. f
  10. (1 row)

虽然这个词没有被识别出来,但是我们只要对tsquery采用相同分词方法,就可以匹配。

点击(此处)折叠或打开

  1. testdb=# select to_tsvector('testzhcfg','微信') @@ to_tsquery('testzhcfg','微信');
  2. ?column?
  3. ----------
  4. t
  5. (1 row)

但是,利用拆开的单字做匹配,检索的效率肯定不会太好。SCWS还提供了一种解决方法(-U),可以对连续的闲散单字做二元切分。

点击(此处)折叠或打开

  1. [root@hanode1 zhparser-0.1.4]# scws -c utf8  -d dict.utf8.xdb  -r rules.utf8.ini -U "微信微博"
    微信 信微 微博
    +--[scws(scws-cli/1.2.2)]----------+
    | TextLen:   12                  |
    | Prepare:   0.0020    (sec)     |
    | Segment:   0.0001    (sec)     |
    +--------------------------------+

对zhparser,可以像之前那样,修改zhparser.c,通过调用scws_set_duality()函数设置这个选项。
http://www.xunsearch.com/scws/docs.php#libscws

点击(此处)折叠或打开

  1. 10. `void scws_set_duality(scws_t s, int yes)` 设定是否将闲散文字自动以二字分词法聚合。
  2. > **参数 yes** 如果为 1 表示执行二分聚合,0 表示不处理,缺省为 0。

但是二元切分也有缺点,会产生歧义词和无意义的词。而且如果这些连续的闲散单字真的是单字的话,二字聚合后就不能再做单字匹配了。

4. 总结

zhparser的安装和配置非常容易,分词效果也不错,可以满足一般的场景。如果有更高的要求需要做一些定制。

5. 参考

postgresql之全文搜索篇
http://www.postgresql.org/docs/9.4/static/textsearch.html
http://www.xunsearch.com/scws/docs.php
http://www.xunsearch.com/scws/api.php
http://amutu.com/blog/zhparser/
http://my.oschina.net/Kenyon/blog/82305?p=1#comments
http://blog.163.com/digoal@126/blog/static/163877040201252141010693/
http://francs3.blog.163.com/blog/static/405767272015065565069/
http://www.cnblogs.com/flish/archive/2011/08/08/2131031.html
http://wenku.baidu.com/link?url=wD7QgE8iNY-UshcSIWkVMUmpTa-dCsnYmn187XZhWuA5Hljt73raE25Wa8dFm_5IADD2T6y5Ur_JeCtouwszayjEUudLQN3pNJqZWN5ofFG
http://www.cnblogs.com/lvpei/archive/2010/08/04/1792409.html
http://blog.2ndquadrant.com/text-search-strategies-in-postgresql/
http://wenku.baidu.com/link?url=va4FRRibEfCdm731U420y5rxcnCDFTDY5Y7ElDbKdUNbusnEz8zLHt3bZlUaDqDQfLigkgycwdp4iWbRlvr2DV3P2bTeJlwipaNqNTughdK
http://jingyan.baidu.com/article/77b8dc7f2af94e6174eab6a2.html

PostgreSQL全文检索zhparser使用的更多相关文章

  1. postgresql全文检索语法

    第1章    全文检索语法 1.1 概述 查询引擎为文本数据类型提供~, ~*, LIKE和ILIKE操作符,并提供全文检索以识别自然语言文档,并通过相关性查询进行排序.查询引擎提供两种数据类型用于支 ...

  2. sphinx在c#.net平台下使用(一)

    Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个可以结合MySQL,PostgreSQL全文检索引擎.意图为其他应用提供高速.低空间占用.高结果 相关度的全文搜索功能.是做站内全文搜 ...

  3. 使用PostgreSQL进行全文检索

    * { color: #3e3e3e } body { font-family: "Helvetica Neue", Helvetica, "Hiragino Sans ...

  4. 见招拆招-PostgreSQL中文全文索引效率优化

    * { color: #3e3e3e } body { font-family: "Helvetica Neue", Helvetica, "Hiragino Sans ...

  5. PostgreSQL 与 MySQL 相比,优势何在?

    一. PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃.断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统 ...

  6. sphinx全文检索功能 | windows下测试 (一)

    前一阵子尝试使用了一下Sphinx,一个能够被各种语言(PHP/Python/Ruby/etc)方便调用的全文检索系统.网上的资料大多是在linux环境下的安装使用,当然,作为生产环境很有必要部署在* ...

  7. PHP+mysql数据库开发搜索功能:中英文分词+全文检索(MySQL全文检索+中文分词(SCWS))

    PHP+mysql数据库开发类似百度的搜索功能:中英文分词+全文检索 中文分词: a)   robbe PHP中文分词扩展: http://www.boyunjian.com/v/softd/robb ...

  8. postgresql编译安装与调试(二)

    接前文postgresql编译安装与调试(一),继续说说postgresql的编译安装与调试. 上一篇已经详细说明了如何在Linux系统上编译安装postgresql,这次我们在此基础上简单讲讲如何在 ...

  9. Sphinx 全文检索

    什么是全文检索: 全文检索是指以文档的全部文本信息作为检索对象的一种信息检索技术.检索的对象有可能是文章的标题,也有可能是文章的作者,也有可能是文章摘要或内容. 简介: Sphinx是由俄罗斯人And ...

随机推荐

  1. 上层建筑——DOM元素的特性与属性(dojo/dom-attr)

    上一篇返本求源中,我们从DOM基础的角度出发,总结了特性与属性的关系.本文中,我们来看看dojo框架是如何处理特性与属性的.dojo框架中特性的处理位于dojo/dom-attr模块属性的处理为与do ...

  2. div css仿京东订单流程图样式代码

    效果展示 http://hovertree.com/texiao/css/25/ 本效果适合PC,也适合移动端 手机扫描二维码查看效果: 效果图: 代码如下: <!DOCTYPE html> ...

  3. docker mysql

    创建mysql docker容器 github上有一个专门的docker-libary项目,里面有各种各样常用的docker镜像,可以做为学习的示例,今天研究下其中mysql镜像的用法,国内镜像dao ...

  4. winform 计算器

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  5. vmware 共享文件夹 win7 centos6

    1. 安装 vmware-tools 1). 右击虚拟机 -- 安装vmware-tools 2). 挂载 mnt /dev/cdrom /mnt 3). yum -y install gcc gcc ...

  6. jquery iframe高度自适应

    $(document).ready(function () { $("#test").load(function () { var thisheight = $(this).con ...

  7. CSS3伪类选择器

    first-line   设置首行样式 first-letter 设置首字母样式 before  在某元素前插入内容并设置内容样式 after 在某元素后插入内容并设置内容样式 <!DOCTYP ...

  8. 各种HTTP错误消息含义

    错误代码 错误消息 400 无法解析此请求. 401.1 未经授权:访问由于凭据无效被拒绝. 401.2 未经授权: 访问由于服务器配置倾向使用替代身份验证方法而被拒绝. 401.3 未经授权:访问由 ...

  9. yuv 图像里的stride和plane的解释

    stride可以翻译为:跨距 stride指在内存中每行像素所占的空间.如下图所示,为了实现内存对齐(或者其它的什么原因),每行像素在内存中所占的空间并不是图像的宽度. plane一般是以luma p ...

  10. Servlet小知识点

    1. Sevlet是一个java类,供以其他程序调用,不能独立运行,需要Servlet引擎(Servlet容器)来管理和调度. 2. 服务器启动后,一般只会创建一个Servlet实例对象,init方法 ...