[
  {
    "path": ".gitignore",
    "content": "build\ndist\nMANIFEST\ntextrank4zh/__pycache__\n*.pyc\ntest.py"
  },
  {
    "path": "HISTORY.md",
    "content": "### 2014\n\n主要功能的实现。\n\n### 2015-12\n\n更新到v0.2。\n\n接口有变化。\n\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Letian Sun\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# TextRank4ZH\n\nTextRank算法可以用来从文本中提取关键词和摘要（重要的句子）。TextRank4ZH是针对中文文本的TextRank算法的python算法实现。\n\n## 安装\n\n方式1：\n```\n$ python setup.py install --user\n```\n\n方式2：\n```\n$ sudo python setup.py install\n```\n\n方式3：\n```\n$ pip install textrank4zh --user\n```\n\n方式4：\n```\n$ sudo pip install textrank4zh\n```\n\nPython 3下需要将上面的python改成python3，pip改成pip3。\n\n\n## 卸载\n```plain\n$ pip uninstall textrank4zh\n```\n\n## 依赖\njieba >= 0.35  \nnumpy >= 1.7.1  \nnetworkx >= 1.9.1  \n\n## 兼容性\n在Python 2.7.9和Python 3.4.3中测试通过。\n\n\n## 原理\n\nTextRank的详细原理请参考：\n\n> Mihalcea R, Tarau P. TextRank: Bringing order into texts[C]. Association for Computational Linguistics, 2004.\n\n关于TextRank4ZH的原理和使用介绍：[使用TextRank算法为文本生成关键字和摘要](https://www.letiantian.xyz/p/101666.html)\n\n### 关键词提取\n将原文本拆分为句子，在每个句子中过滤掉停用词（可选），并只保留指定词性的单词（可选）。由此可以得到句子的集合和单词的集合。\n\n每个单词作为pagerank中的一个节点。设定窗口大小为k，假设一个句子依次由下面的单词组成：\n```\nw1, w2, w3, w4, w5, ..., wn\n```\n`w1, w2, ..., wk`、`w2, w3, ...,wk+1`、`w3, w4, ...,wk+2`等都是一个窗口。在一个窗口中的任两个单词对应的节点之间存在一个无向无权的边。\n\n基于上面构成图，可以计算出每个单词节点的重要性。最重要的若干单词可以作为关键词。\n\n\n### 关键短语提取\n参照[关键词提取](#关键词提取)提取出若干关键词。若原文本中存在若干个关键词相邻的情况，那么这些关键词可以构成一个关键词组。\n\n例如，在一篇介绍`支持向量机`的文章中，可以找到关键词`支持`、`向量`、`机`，通过关键词组提取，可以得到`支持向量机`。\n\n### 摘要生成\n将每个句子看成图中的一个节点，若两个句子之间有相似性，认为对应的两个节点之间有一个无向有权边，权值是相似度。\n\n通过pagerank算法计算得到的重要性最高的若干句子可以当作摘要。\n\n\n## 示例\n见[example](./example)、[test](./test)。\n\nexample/example01.py:\n\n```python\n#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport codecs\nfrom textrank4zh import TextRank4Keyword, TextRank4Sentence\n\ntext = codecs.open('../test/doc/01.txt', 'r', 'utf-8').read()\ntr4w = TextRank4Keyword()\n\ntr4w.analyze(text=text, lower=True, window=2)  # py2中text必须是utf8编码的str或者unicode对象，py3中必须是utf8编码的bytes或者str对象\n\nprint( '关键词：' )\nfor item in tr4w.get_keywords(20, word_min_len=1):\n    print(item.word, item.weight)\n\nprint()\nprint( '关键短语：' )\nfor phrase in tr4w.get_keyphrases(keywords_num=20, min_occur_num= 2):\n    print(phrase)\n\ntr4s = TextRank4Sentence()\ntr4s.analyze(text=text, lower=True, source = 'all_filters')\n\nprint()\nprint( '摘要：' )\nfor item in tr4s.get_key_sentences(num=3):\n    print(item.index, item.weight, item.sentence)  # index是语句在文本中位置，weight是权重\n```\n\n运行结果如下：\n```plain\n关键词：\n媒体 0.02155864734852778\n高圆圆 0.020220281898126486\n微 0.01671909730824073\n宾客 0.014328439104001788\n赵又廷 0.014035488254875914\n答谢 0.013759845912857732\n谢娜 0.013361244496632448\n现身 0.012724133346018603\n记者 0.01227742092899235\n新人 0.01183128428494362\n北京 0.011686712993089671\n博 0.011447168887452668\n展示 0.010889176260920504\n捧场 0.010507502237123278\n礼物 0.010447275379792245\n张杰 0.009558332870902892\n当晚 0.009137982757893915\n戴 0.008915271161035208\n酒店 0.00883521621207796\n外套 0.008822082954131174\n\n关键短语：\n微博\n\n摘要：\n摘要：\n0 0.0709719557171 中新网北京12月1日电(记者 张曦) 30日晚，高圆圆和赵又廷在京举行答谢宴，诸多明星现身捧场，其中包括张杰(微博)、谢娜(微博)夫妇、何炅(微博)、蔡康永(微博)、徐克、张凯丽、黄轩(微博)等\n6 0.0541037236415 高圆圆身穿粉色外套，看到大批记者在场露出娇羞神色，赵又廷则戴着鸭舌帽，十分淡定，两人快步走进电梯，未接受媒体采访\n27 0.0490428312984 记者了解到，出席高圆圆、赵又廷答谢宴的宾客近百人，其中不少都是女方的高中同学\n\n```\n\n## 使用说明\n\n类TextRank4Keyword、TextRank4Sentence在处理一段文本时会将文本拆分成4种格式：\n\n* sentences：由句子组成的列表。\n* words_no_filter：对sentences中每个句子分词而得到的两级列表。\n* words_no_stop_words：去掉words_no_filter中的停止词而得到的二维列表。\n* words_all_filters：保留words_no_stop_words中指定词性的单词而得到的二维列表。\n\n例如，对于：\n```\n这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足。答谢宴于晚上8点开始。\n```\n\n```python\n#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\nimport codecs\nfrom textrank4zh import TextRank4Keyword, TextRank4Sentence\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\ntext = \"这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足。答谢宴于晚上8点开始。\"\ntr4w = TextRank4Keyword()\n\ntr4w.analyze(text=text, lower=True, window=2)\n\nprint()\nprint('sentences:')\nfor s in tr4w.sentences:\n    print(s)                 # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_no_filter')\nfor words in tr4w.words_no_filter:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_no_stop_words')\nfor words in tr4w.words_no_stop_words:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_all_filters')\nfor words in tr4w.words_all_filters:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。\n```\n\n运行结果如下：\n```plain\nsentences:\n这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足\n答谢宴于晚上8点开始\n\nwords_no_filter\n这/间/酒店/位于/北京/东三环/里面/摆放/很多/雕塑/文艺/气息/十足\n答谢/宴于/晚上/8/点/开始\n\nwords_no_stop_words\n间/酒店/位于/北京/东三环/里面/摆放/很多/雕塑/文艺/气息/十足\n答谢/宴于/晚上/8/点\n\nwords_all_filters\n酒店/位于/北京/东三环/摆放/雕塑/文艺/气息\n答谢/宴于/晚上\n\n```\n\n\n## API\nTODO.\n\n类的实现、函数的参数请参考源码注释。\n\n## License\n[MIT](./LICENSE)\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "example/example01.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport codecs\nfrom textrank4zh import TextRank4Keyword, TextRank4Sentence\n\ntext = codecs.open('../test/doc/01.txt', 'r', 'utf-8').read()\ntr4w = TextRank4Keyword()\n\ntr4w.analyze(text=text, lower=True, window=2)   # py2中text必须是utf8编码的str或者unicode对象，py3中必须是utf8编码的bytes或者str对象\n\nprint( '关键词：' )\nfor item in tr4w.get_keywords(20, word_min_len=1):\n    print(item.word, item.weight)\n\nprint()\nprint( '关键短语：' )\nfor phrase in tr4w.get_keyphrases(keywords_num=20, min_occur_num= 2):\n    print(phrase)\n\ntr4s = TextRank4Sentence()\ntr4s.analyze(text=text, lower=True, source = 'all_filters')\n\nprint()\nprint( '摘要：' )\nfor item in tr4s.get_key_sentences(num=3):\n    print(item.index, item.weight, item.sentence)"
  },
  {
    "path": "example/example02.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\nimport codecs\nfrom textrank4zh import TextRank4Keyword, TextRank4Sentence\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\ntext = \"这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足。答谢宴于晚上8点开始。\"\ntr4w = TextRank4Keyword()\n\ntr4w.analyze(text=text, lower=True, window=2)\n\nprint()\nprint('sentences:')\nfor s in tr4w.sentences:\n    print(s)                 # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_no_filter')\nfor words in tr4w.words_no_filter:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_no_stop_words')\nfor words in tr4w.words_no_stop_words:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。\n\nprint()\nprint('words_all_filters')\nfor words in tr4w.words_all_filters:\n    print('/'.join(words))   # py2中是unicode类型。py3中是str类型。"
  },
  {
    "path": "setup.py",
    "content": "# -*- coding: utf-8 -*-\nfrom distutils.core import setup\nLONGDOC = \"\"\"\nPlease go to https://github.com/someus/TextRank4ZH for more info.\n\"\"\"\n\nsetup(\n    name='textrank4zh',\n    version='0.3',\n    description='Extract keywords and abstract Chinese article',\n    long_description=LONGDOC,\n    author='Letian Sun',\n    author_email='sunlt1699@gmail.com',\n    url='https://github.com/someus/TextRank4ZH',\n    license=\"MIT\",\n    classifiers=[\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: MIT License',\n        'Operating System :: OS Independent',\n        'Natural Language :: Chinese (Simplified)',\n        'Natural Language :: Chinese (Traditional)',\n        'Programming Language :: Python :: 2',\n        'Programming Language :: Python :: 2.7',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.4',\n        'Topic :: Text Processing',\n        'Topic :: Text Processing :: Linguistic',\n    ],\n    keywords='NLP,Chinese,Keywords extraction, Abstract extraction',\n    install_requires=['jieba >= 0.35', 'numpy >= 1.7.1', 'networkx >= 1.9.1'],\n    packages=['textrank4zh'],\n    package_dir={'textrank4zh':'textrank4zh'},\n    package_data={'textrank4zh':['*.txt',]},\n)"
  },
  {
    "path": "test/Segmentation_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport codecs\nfrom textrank4zh import Segmentation\n\nseg = Segmentation.Segmentation()\n\ntext = codecs.open('./doc/01.txt', 'r', 'utf-8', 'ignore').read()\ntext = \"视频里，我们的杰宝热情地用英文和全场观众打招呼并清唱了一段《Heal The World》。我们的世界充满了未知数。\"\n\nresult = seg.segment(text=text, lower=True)\n\nfor key in result:\n    print(key)\n\nprint(20*'#')\nfor s in result['sentences']:\n    print(s)\n\nprint(20*'*')\nfor s in result.sentences:\n    print (s)\n\nprint\nfor ss in result.words_no_filter:\n    print( '  '.join(ss) )\n\nprint\nfor ss in result.words_no_stop_words:\n    print( ' / '.join(ss) )\n\nprint\nfor ss in result.words_all_filters:\n    print (' | '.join(ss) )\n"
  },
  {
    "path": "test/TextRank4Keyword_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport codecs\nfrom textrank4zh import TextRank4Keyword\n\ntext = codecs.open('./doc/02.txt', 'r', 'utf-8').read()\n# text = \"世界的美好。世界美国英国。 世界和平。\"\n\ntr4w = TextRank4Keyword()\ntr4w.analyze(text=text,lower=True, window=3, pagerank_config={'alpha':0.85})\n\nfor item in tr4w.get_keywords(30, word_min_len=2):\n    print(item.word, item.weight, type(item.word))\n\nprint('--phrase--')\n\nfor phrase in tr4w.get_keyphrases(keywords_num=20, min_occur_num = 0):\n    print(phrase, type(phrase))"
  },
  {
    "path": "test/TextRank4Sentence_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport codecs\nfrom textrank4zh import TextRank4Sentence\n\ntext = codecs.open('./doc/03.txt', 'r', 'utf-8').read()\ntext = \"这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足。答谢宴于晚上8点开始。\"\ntr4s = TextRank4Sentence()\ntr4s.analyze(text=text, lower=True, source = 'all_filters')\n\nfor st in tr4s.sentences:\n    print(type(st), st)\n\nprint(20*'*')\nfor item in tr4s.get_key_sentences(num=4):\n    print(item.weight, item.sentence, type(item.sentence))"
  },
  {
    "path": "test/codecs_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\n\nimport codecs\ntext = codecs.open('./doc/01.txt', 'r', 'utf-8', 'ignore').read()\nprint( type(text) )  # in py2 is unicode, py3 is str"
  },
  {
    "path": "test/doc/01.txt",
    "content": "中新网北京12月1日电(记者 张曦) 30日晚，高圆圆和赵又廷在京举行答谢宴，诸多明星现身捧场，其中包括张杰(微博)、谢娜(微博)夫妇、何炅(微博)、蔡康永(微博)、徐克、张凯丽、黄轩(微博)等。\n\n30日中午，有媒体曝光高圆圆和赵又廷现身台北桃园机场的照片，照片中两人小动作不断，尽显恩爱。事实上，夫妻俩此行是回女方老家北京举办答谢宴。\n\n群星捧场 谢娜张杰亮相\n\n当晚不到7点，两人十指紧扣率先抵达酒店。这间酒店位于北京东三环，里面摆放很多雕塑，文艺气息十足。\n\n高圆圆身穿粉色外套，看到大批记者在场露出娇羞神色，赵又廷则戴着鸭舌帽，十分淡定，两人快步走进电梯，未接受媒体采访。\n\n随后，谢娜、何炅也一前一后到场庆贺，并对一对新人表示恭喜。接着蔡康永满脸笑容现身，他直言：“我没有参加台湾婚礼，所以这次觉得蛮开心。”\n\n曾与赵又廷合作《狄仁杰之神都龙王》的导演徐克则携女助理亮相，面对媒体的长枪短炮，他只大呼“恭喜！恭喜！”\n\n作为高圆圆的好友，黄轩虽然拍杂志收工较晚，但也赶过来参加答谢宴。问到给新人带什么礼物，他大方拉开外套，展示藏在包里厚厚的红包，并笑言：“封红包吧！”但不愿透露具体数额。\n\n值得一提的是，当晚10点，张杰压轴抵达酒店，他戴着黑色口罩，透露因刚下飞机所以未和妻子谢娜同行。虽然他没有接受采访，但在进电梯后大方向媒体挥手致意。\n\n《我们结婚吧》主创捧场\n\n黄海波(微博)获释仍未出席\n\n在电视剧《咱们结婚吧》里，饰演高圆圆母亲的张凯丽，当晚身穿黄色大衣出席，但只待了一个小时就匆忙离去。\n\n同样有份参演该剧，并扮演高圆圆男闺蜜的大左(微信号：dazuozone) 也到场助阵，28日，他已在台湾参加两人的盛大婚礼。大左30日晚接受采访时直言当时场面感人，“每个人都哭得稀里哗啦，晚上是吴宗宪(微博)(微信号：wushowzongxian) 主持，现场欢声笑语，讲了好多不能播的事，新人都非常开心”。\n\n最令人关注的是在这部剧里和高圆圆出演夫妻的黄海波。巧合的是，他刚好于30日收容教育期满，解除收容教育。\n\n答谢宴细节\n\n宾客近百人，获赠礼物\n\n记者了解到，出席高圆圆、赵又廷答谢宴的宾客近百人，其中不少都是女方的高中同学。\n\n答谢宴位于酒店地下一层，现场安保森严，大批媒体只好在酒店大堂等待。期间有工作人员上来送上喜糖，代两位新人向媒体问好。\n\n记者注意到，虽然答谢宴于晚上8点开始，但从9点开始就陆续有宾客离开，每个宾客都手持礼物，有宾客大方展示礼盒，只见礼盒上印有两只正在接吻的烫金兔子，不过工作人员迅速赶来，拒绝宾客继续展示。"
  },
  {
    "path": "test/doc/02.txt",
    "content": "如何在美国把贪官送进监狱——\n法律用美国的：被用来修理黑帮的美国联邦法律也能“顺便”对付中国贪官\n\n在美国起诉中国贪官，不可能适用中国自己的法律。所以，必须得搞清楚外逃贪官触犯美国法律的证据。贪官明明是在中国国内贪腐，还能触犯到美国的法律？没错。\n\n有先例可循。1994年—2001年，原中国银行开平支行三任行长许超凡、余振东和许国俊勾结贪污、挪用了4.85亿美元巨资。他们都逃向了美国。后来，余振东和二许分别在美国被起诉。以“二许案”为例，这两个巨贪触犯了多项美国联邦刑法，首当其冲的是《反勒索及受贿组织法》。该法律是美国在上个世纪70年代通过的，当时的立意是对付各种黑帮。由于黑帮犯罪常常是一套完整的步骤，所以这个法案把有组织犯罪作为一条完整的“产业链”做考虑。具体来说，二许在中国国内贪污后，后续有一系列涉及到美国的行为——通过各种办法洗钱；把赃款转移到美国；为转移非法所得开设空壳公司……这三个人用了拉斯维加斯的赌场洗钱。所以，最后都是在拉斯维加斯所在的内华达州被美联邦法院审判。\n\n除了“有组织犯罪”相关法条外，洗钱、伪造签证等贪官可能涉及到的触及美国法律行为都能被提起控诉。这里的美国法律主要指的是美国联邦法律，而不是州法律，所以这些贪官也是被联邦警察给抓获的。\n\n总之，在国内的贪污行为是“上游”，中国的检察官们没可能因为这些发生在中国的“上游”事件要求美国法院给中国贪官定罪；而美国法官也不可能运用中国的法律来做判决。不过，把赃款和人转移出去这个“下游”过程是有很大部分是在美国发生的，可能触犯到各种美国法律。严格说起来，要想在美国对贪官们治罪，那么得找到他们的贪污关联行为触犯到美国法律的证据。\n在美国坐牢的贪官许超凡和许国俊曾经通过拉斯维加斯的赌场洗钱在美国坐牢的贪官许超凡和许国俊曾经通过拉斯维加斯的赌场洗钱\n一般也在美国蹲监狱：美国法律对付中国贪官并不手软，他们可能被判得很重\n\n既然是运用美国法律判的，也得在美国服刑。而大家会担心，会不会“有组织犯罪”等罪名对付中国贪官太过温和、间接，对他们下手轻呢？其实不会。还是说“二许案”，他们一个判25年，另一个是22年。因为所涉及的犯罪基本在美国都是重罪。2009年，法制日报的报道《中行开平案八年追诉始末》分析道，“‘二许’此次在美国所获刑期，均已经超出我国刑法有期徒刑的最高量刑标准。”\n\n在二许坐满牢之后，他们面临着被美国驱逐出境。他们都是通过欺诈的手段获得了美国的签证。\n不过也有办法把贪官“换回”中国坐牢：中、美和嫌犯三方达成协议\n余振东被遣返回中国后被判处12年有期徒刑。余振东被遣返回中国后被判处12年有期徒刑。\n\n前文提到的余振东案里，余在美国被判入监144个月，但他现在处于中国的监狱中。这又是怎么回事呢？原来，余振东表示自愿接受遣返。余振东向美国方面递交《递解出境司法命令和放弃听证约定申请书》，承认自己在美所犯罪行应导致递解出境的法律后果，并且明确指定中国为其递解出境的接收国。当然，这种“自愿”是有前提条件的。因为中国也向美国的司法机关作出承诺，余振东在中国国内被宣判的刑期不会长于美国。而也因为余振东的自愿认罪，美国司法机关对他的判罚从轻。\n还可以追究共同犯罪的贪官家属刑责：贪官的家属倘若一起触犯了美国法律，也得受罚\n贪官背后往往有“贪内助”，而参与了犯罪的贪官家属也可能在美国被起诉贪官背后往往有“贪内助”，而参与了犯罪的贪官家属也可能在美国被起诉\n\n“二许案”中一共有四个人被追究刑责。因为，两个贪官的太太也没少参与触犯到美国法律的洗钱等行为。她们分别被判处监禁8年。除了大家能够想到的洗钱等常规动作外，这两对巨贪夫妻很“奇葩”的一点是，两位妻子先通过和美国人假结婚获得了美国公民资格。没有后顾之忧，真丈夫们开始疯狂地转移资金。等到逃跑时候，男人们也运用了假结婚的方式。所以在“二许案”的指控中，有一项是“护照、签证欺诈”。\n要做到以上这些，重要的还是中国官方的努力，争取美国的积极合作\n\n看起来，好像动用美国的司法体系来追究中国贪官的刑责并不难，也只需要美国方面的努力。那么，这是一条追诉逃美贪官的康庄大道？当然不是这样的。否则不会在2009年“二许案”宣判之后，暂时没有再出现过这样的案例。余振东案和“二许案”在当年都轰动一时，关系重大。因此是被当作大案要案在办。其时，恰逢中国和美国签署了《刑事司法互助协定》不久。所以这三个金融系统大蛀虫首当其冲被起诉了——几个巨贪被美国联邦警察逮捕就是中方努力的结果。中国也向美方提供了大量的证据，证明钱财是非法所得。找出财产转移链、挖出洗钱的细节……种种犯罪事实都需要经过繁琐的查证。另一方面，美国办案子也需要付出大量的司法成本，所以不能希冀美国的司法部门多么主动地去发现中国外逃贪官。\n\n当然，时代在前行。随着国内反腐的高涨，海外追逃也越来越得到重视。这次外交部条约法律司司长徐宏的发言，也给了大家一个期许。\n美国司法部关于“二许案”的通告美国司法部关于“二许案”的通告\n如何在美国打官司，向贪官要回钱——\n拿着刑事判决的结果来打民事官司追款相对容易\n\n对于民事诉讼追赃，《联合国反腐败公约》里有制度支持。而相对容易的一种形式就是拿着刑事判决去追赃。刑事判决对于财产的非法性是强有力的证明。所以，“二许案”后，中国银行在美国当地提起诉讼，追回了一些财产。\n\n尽管“二许案”的许多赃款并没有转移到美国，而是在加拿大，美国的这份刑事判决也有助于“苦主”在加拿大追偿。就在今年11月24日，加拿大的大不列颠哥伦比亚BC省法院正式开庭审理中国银行向许超凡妻子和母亲追赃的民事诉讼。\n\n一些学者认为，中国国内的刑事判决也是有助于发起民事诉讼法追赃的。不过一个现实是，中国的刑法不允许“缺席审判”，贪官不到位就没法动了，因此许多学者也提出中国应该建立起相关的制度来。\n不管刑事，直接打民事官司也可以，就是费时、费力、费钱\n\n民事诉讼相对于刑事诉讼来说要容易得多。所以被认为是一个非常好的向外逃贪官追责的路径。追回贪官的赃款，既挽回损失，还能够断了贪官的财源。\n\n当然，以上都是最理想的说法。实际情况难多了。所以公开报道的海外成功追赃的民事诉讼案例真是屈指可数。在美国，目前唯一公开的一起是前述的中国银行向“二许”追赃。但是情况特殊，并且真正的大头在加拿大，所以参考性不强。倒是有一起不在美国，在澳大利亚的民事诉讼追赃可以做参考。被诉方是原北京市城乡建设集团副总经理李化学。只是过程非常艰辛曲折，为了顺利起诉，中方不得不聘请了一名当地律师。付出和回报存疑。办案人员彭唯良检察官的原话是：“在国外打官司，经济上必须有坚强的后盾来支持。另外，由于语言上的障碍，有些我们想通过律师要达到的目的，律师不太了解，返工的次数比较多。”\n\n当然，这里需要说明的一点是，民事诉讼的主体也不宜是中国政府，而是具体的单位。所以在北京城乡集团的案子里，尽管检察官们为民事诉讼付出了大量的努力，但还得找来单位做原告。\n目前经验看，最省事、有效的是争取到美国司法部的最大限度合作\n陈水扁用非法所得在美国购买的房产陈水扁用非法所得在美国购买的房产\n\n说一个台湾地区的例子。陈水扁弊案爆发后，被美国司法部发现，陈家用“不法所得”在美国购买了两处房产。后来，由美国司法部出面进行没收。美国司法部也需要向法院提出诉讼。这其实是属于美国的一个“腐败政府国家资产追回”计划。这个案子最后的结果是，法院支持了美国司法部的请求，陈家房产被拍卖。而根据相关法律，拍卖所得美国是有权分得一部分的。\n\n由美国司法部出面提起诉讼，恐怕是最好的办法了。而这需要两点：第一，还是追赃国的申请和完整的证据；第二，则涉及到一个积极性问题。对追缴财产进行分享也是国际上一个比较流行的做法，可以大限度地调动赃款流向国的积极性。不失为一个参考。\n结语\n看来，在美国起诉贪官确实可行。但是，不管是追人还是追钱，都存在一个和美国的紧密合作问题，不然也是白搭。\n"
  },
  {
    "path": "test/doc/03.txt",
    "content": "据BI消息，Netflix 正准备在本月上线其最新的原创剧集《马可波罗》。而据纽约时报报道，《马可波罗》第一季 10 集的总投资高达 9000 万美元，这不仅创下了 Netflix 的最高电视剧投资记录，在全球电视剧制作成本的排名中也是数一数二的，仅次于 HBO 原创的《权利的游戏》。\n\n《马可波罗》在意大利、哈萨克斯坦、马来西亚等多国取景拍摄，数百名演员来自多个国家，电视剧把传奇冒险、战争、武术、性诱惑、政治阴谋等元素都融了进去，看起来会包含不少大家喜闻乐见的题材。Netflix 也为《马可波罗》的播出制定了庞大的市场营销计划。比如，Netflix 将携主要演员参加巴西的圣地亚哥国际动漫展，另外也会在墨西哥的一个大型购物中心展示《马可波罗》演出所用的服装和道具。\n\nNetflix 怎么会如此大手笔？毫无疑问 Netflix 对这部剧寄予了重望——Netflix 的海外市场。Netflix 现在已经进入全球 50 多个国家和地区，付费订户高达 5000 万人。由于在美国本土的增长开始下滑，寻求海外增长机会成为 Netflix 的当务之急。除了四处购买电影电视剧的全球版权等海外市场豪赌，Netflix 在影视内容上也有一场豪赌——鸿篇巨制的《马可波罗》。此剧由独立片商威斯坦公司制作，Netflix 掌握全球版权，将从 12 月 12 日开始在 Netflix 面向全球订户提供点播。\n\nNetflix 早期靠《纸牌屋》和《女子监狱》等原创剧一鸣惊人，但可惜的是，Netflix 并没有掌握《纸牌屋》等剧的海外版权。比如在德国和法国，观众可以在电视频道上收看该剧。不过，《纸牌屋》的成功仍然帮助 Netflix 提升了知名度。目前，Netflix 正在筹拍中的原创剧有不少，《马可波罗》成功与否可以在一定程度上验证 Netflix 的原创剧战略是否在海外市场是否有效。\n\n不过，一些媒体行业分析师预测，Netflix 的国际化将会遇到各国本地视频网站的狙击。此外 HBO 也是其最强劲的竞争对手。众所周知，HBO 在国际化方面已经先行一步。比如在中国市场，HBO 就刚刚与腾讯视频签订了独家播放权。而迄今为止，Netflix 尚未在亚洲任何一个国家展开业务。\n"
  },
  {
    "path": "test/doc/04.txt",
    "content": "京菜擅长烤、爆、烧、焖、涮，听起来豪爽，吃起来痛快。北京烤鸭是来京游玩必食的美味；西四缸瓦市一家名叫砂锅居的老店所烧的砂锅白肉名满京城，相传他们用的原汤已有二三百年历史；涮羊肉是最受北京人欢迎的冬令美食，其中阳坊涮肉连锁店以价格便宜，味道正宗而倍受青睐。可以以半份起卖，在全市有许多分店。除此之外，还有东来顺、又一顺、能仁居的涮羊肉名气也很大。\n北京风味小吃有600多年历史，包括汉民风味小吃、回民风味小吃和宫廷风味小吃等300多种。\n北京的各大饭店历来是名厨荟萃，如北京饭店的谭家菜、建国饭店的法式西餐都是别处不易享用到的佳肴；北京还有正宗的法式、美式、意式、俄式餐厅和日本料理、韩国烧烤以及越南、印尼、泰国风味的菜馆。若为省时实惠，还可以光顾街头小店，这里不乏北京特有的包子、饺子、面条及家常炒菜，当然，环境就不如大餐馆讲究了。 \n东直门内大街原是北京最富特色的餐饮一条街，大街南北两侧云集了各种风味的餐馆，多为24小时营业。但现在因为拆迁，这条路上的餐饮店多已搬迁。 "
  },
  {
    "path": "test/doc/05.txt",
    "content": "支持向量机（英语：Support Vector Machine，常简称为SVM）是一种监督式学习的方法，可广泛地应用于统计分类以及回归分析。\n\n支持向量机属于一般化线性分类器，也可以被认为是提克洛夫规范化（Tikhonov Regularization）方法的一个特例。这族分类器的特点是他们能够同时最小化经验误差与最大化几何边缘区，因此支持向量机也被称为最大边缘区分类器。\n\n支持向量机构造一个超平面或者多个超平面，这些超平面可能是高维的，甚至可能是无限多维的。在分类任务中，它的原理是，将决策面（超平面）放置在这样的一个位置，两类中接近这个位置的点距离的都最远。我们来考虑两类线性可分问题，如果要在两个类之间画一条线，那么按照支持向量机的原理，我们会先找两类之间最大的空白间隔，然后在空白间隔的中点画一条线，这条线平行于空白间隔。通过核函数，可以使得支持向量机对非线性可分的任务进行分类。一个极好的指南是C.J.C Burges的《模式识别支持向量机指南》。van der Walt和Barnard将支持向量机和其他分类器进行了比较。"
  },
  {
    "path": "test/jieba_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nimport sys\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n\nimport jieba.posseg as pseg\nwords = pseg.cut(\"我爱北京天安门.。；‘你的#\")\nfor w in words:\n    # print(w.word)\n    print('{0} {1}'.format(w.word, w.flag))\n    print(type(w.word))  # in py2 is unicode, py3 is str\n\n"
  },
  {
    "path": "test/util_test.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import print_function\n\nfrom textrank4zh import util\n\ndef testAttrDict():\n    r = util.AttrDict(a=2)\n    print( r )\n    print( r.a )\n    print( r['a'] )\n\ndef testCombine():\n    print(20*'*')\n    for item in util.combine(['a', 'b', 'c', 'd'], 2):\n        print(item)\n    print\n    for item in util.combine(['a', 'b', 'c', 'd'], 3):\n        print (item)\n\ndef testDebug():\n    import sys\n    print(sys.getdefaultencoding())\n    util.debug('你好')\n    util.debug(u'世界')\n\n\nif __name__ == \"__main__\":\n    testAttrDict()\n    testCombine()\n    testDebug()\n"
  },
  {
    "path": "textrank4zh/Segmentation.py",
    "content": "#-*- encoding:utf-8 -*-\n\"\"\"\n@author:   letian\n@homepage: http://www.letiantian.me\n@github:   https://github.com/someus/\n\"\"\"\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport jieba.posseg as pseg\nimport codecs\nimport os\n\nfrom . import util\n\ndef get_default_stop_words_file():\n    d = os.path.dirname(os.path.realpath(__file__))\n    return os.path.join(d, 'stopwords.txt')\n\nclass WordSegmentation(object):\n    \"\"\" 分词 \"\"\"\n    \n    def __init__(self, stop_words_file = None, allow_speech_tags = util.allow_speech_tags):\n        \"\"\"\n        Keyword arguments:\n        stop_words_file    -- 保存停止词的文件路径，utf8编码，每行一个停止词。若不是str类型，则使用默认的停止词\n        allow_speech_tags  -- 词性列表，用于过滤\n        \"\"\"     \n        \n        allow_speech_tags = [util.as_text(item) for item in allow_speech_tags]\n\n        self.default_speech_tag_filter = allow_speech_tags\n        self.stop_words = set()\n        self.stop_words_file = get_default_stop_words_file()\n        if type(stop_words_file) is str:\n            self.stop_words_file = stop_words_file\n        for word in codecs.open(self.stop_words_file, 'r', 'utf-8', 'ignore'):\n            self.stop_words.add(word.strip())\n    \n    def segment(self, text, lower = True, use_stop_words = True, use_speech_tags_filter = False):\n        \"\"\"对一段文本进行分词，返回list类型的分词结果\n\n        Keyword arguments:\n        lower                  -- 是否将单词小写（针对英文）\n        use_stop_words         -- 若为True，则利用停止词集合来过滤（去掉停止词）\n        use_speech_tags_filter -- 是否基于词性进行过滤。若为True，则使用self.default_speech_tag_filter过滤。否则，不过滤。    \n        \"\"\"\n        text = util.as_text(text)\n        jieba_result = pseg.cut(text)\n        \n        if use_speech_tags_filter == True:\n            jieba_result = [w for w in jieba_result if w.flag in self.default_speech_tag_filter]\n        else:\n            jieba_result = [w for w in jieba_result]\n\n        # 去除特殊符号\n        word_list = [w.word.strip() for w in jieba_result if w.flag!='x']\n        word_list = [word for word in word_list if len(word)>0]\n        \n        if lower:\n            word_list = [word.lower() for word in word_list]\n\n        if use_stop_words:\n            word_list = [word.strip() for word in word_list if word.strip() not in self.stop_words]\n\n        return word_list\n        \n    def segment_sentences(self, sentences, lower=True, use_stop_words=True, use_speech_tags_filter=False):\n        \"\"\"将列表sequences中的每个元素/句子转换为由单词构成的列表。\n        \n        sequences -- 列表，每个元素是一个句子（字符串类型）\n        \"\"\"\n        \n        res = []\n        for sentence in sentences:\n            res.append(self.segment(text=sentence, \n                                    lower=lower, \n                                    use_stop_words=use_stop_words, \n                                    use_speech_tags_filter=use_speech_tags_filter))\n        return res\n        \nclass SentenceSegmentation(object):\n    \"\"\" 分句 \"\"\"\n    \n    def __init__(self, delimiters=util.sentence_delimiters):\n        \"\"\"\n        Keyword arguments:\n        delimiters -- 可迭代对象，用来拆分句子\n        \"\"\"\n        self.delimiters = set([util.as_text(item) for item in delimiters])\n    \n    def segment(self, text):\n        res = [util.as_text(text)]\n        \n        util.debug(res)\n        util.debug(self.delimiters)\n\n        for sep in self.delimiters:\n            text, res = res, []\n            for seq in text:\n                res += seq.split(sep)\n        res = [s.strip() for s in res if len(s.strip()) > 0]\n        return res \n        \nclass Segmentation(object):\n    \n    def __init__(self, stop_words_file = None, \n                    allow_speech_tags = util.allow_speech_tags,\n                    delimiters = util.sentence_delimiters):\n        \"\"\"\n        Keyword arguments:\n        stop_words_file -- 停止词文件\n        delimiters      -- 用来拆分句子的符号集合\n        \"\"\"\n        self.ws = WordSegmentation(stop_words_file=stop_words_file, allow_speech_tags=allow_speech_tags)\n        self.ss = SentenceSegmentation(delimiters=delimiters)\n        \n    def segment(self, text, lower = False):\n        text = util.as_text(text)\n        sentences = self.ss.segment(text)\n        words_no_filter = self.ws.segment_sentences(sentences=sentences, \n                                                    lower = lower, \n                                                    use_stop_words = False,\n                                                    use_speech_tags_filter = False)\n        words_no_stop_words = self.ws.segment_sentences(sentences=sentences, \n                                                    lower = lower, \n                                                    use_stop_words = True,\n                                                    use_speech_tags_filter = False)\n\n        words_all_filters = self.ws.segment_sentences(sentences=sentences, \n                                                    lower = lower, \n                                                    use_stop_words = True,\n                                                    use_speech_tags_filter = True)\n\n        return util.AttrDict(\n                    sentences           = sentences, \n                    words_no_filter     = words_no_filter, \n                    words_no_stop_words = words_no_stop_words, \n                    words_all_filters   = words_all_filters\n                )\n    \n        \n\nif __name__ == '__main__':\n    pass"
  },
  {
    "path": "textrank4zh/TextRank4Keyword.py",
    "content": "#-*- encoding:utf-8 -*-\n\"\"\"\n@author:   letian\n@homepage: http://www.letiantian.me\n@github:   https://github.com/someus/\n\"\"\"\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport networkx as nx\nimport numpy as np\n\nfrom . import util\nfrom .Segmentation import Segmentation\n\nclass TextRank4Keyword(object):\n    \n    def __init__(self, stop_words_file = None, \n                 allow_speech_tags = util.allow_speech_tags, \n                 delimiters = util.sentence_delimiters):\n        \"\"\"\n        Keyword arguments:\n        stop_words_file  --  str，指定停止词文件路径（一行一个停止词），若为其他类型，则使用默认停止词文件\n        delimiters       --  默认值是`?!;？！。；…\\n`，用来将文本拆分为句子。\n        \n        Object Var:\n        self.words_no_filter      --  对sentences中每个句子分词而得到的两级列表。\n        self.words_no_stop_words  --  去掉words_no_filter中的停止词而得到的两级列表。\n        self.words_all_filters    --  保留words_no_stop_words中指定词性的单词而得到的两级列表。\n        \"\"\"\n        self.text = ''\n        self.keywords = None\n        \n        self.seg = Segmentation(stop_words_file=stop_words_file, \n                                allow_speech_tags=allow_speech_tags, \n                                delimiters=delimiters)\n\n        self.sentences = None\n        self.words_no_filter = None     # 2维列表\n        self.words_no_stop_words = None\n        self.words_all_filters = None\n        \n    def analyze(self, text, \n                window = 2, \n                lower = False,\n                vertex_source = 'all_filters',\n                edge_source = 'no_stop_words',\n                pagerank_config = {'alpha': 0.85,}):\n        \"\"\"分析文本\n\n        Keyword arguments:\n        text       --  文本内容，字符串。\n        window     --  窗口大小，int，用来构造单词之间的边。默认值为2。\n        lower      --  是否将文本转换为小写。默认为False。\n        vertex_source   --  选择使用words_no_filter, words_no_stop_words, words_all_filters中的哪一个来构造pagerank对应的图中的节点。\n                            默认值为`'all_filters'`，可选值为`'no_filter', 'no_stop_words', 'all_filters'`。关键词也来自`vertex_source`。\n        edge_source     --  选择使用words_no_filter, words_no_stop_words, words_all_filters中的哪一个来构造pagerank对应的图中的节点之间的边。\n                            默认值为`'no_stop_words'`，可选值为`'no_filter', 'no_stop_words', 'all_filters'`。边的构造要结合`window`参数。\n        \"\"\"\n        \n        # self.text = util.as_text(text)\n        self.text = text\n        self.word_index = {}\n        self.index_word = {}\n        self.keywords = []\n        self.graph = None\n        \n        result = self.seg.segment(text=text, lower=lower)\n        self.sentences = result.sentences\n        self.words_no_filter = result.words_no_filter\n        self.words_no_stop_words = result.words_no_stop_words\n        self.words_all_filters   = result.words_all_filters\n\n        util.debug(20*'*')\n        util.debug('self.sentences in TextRank4Keyword:\\n', ' || '.join(self.sentences))\n        util.debug('self.words_no_filter in TextRank4Keyword:\\n', self.words_no_filter)\n        util.debug('self.words_no_stop_words in TextRank4Keyword:\\n', self.words_no_stop_words)\n        util.debug('self.words_all_filters in TextRank4Keyword:\\n', self.words_all_filters)\n\n\n        options = ['no_filter', 'no_stop_words', 'all_filters']\n\n        if vertex_source in options:\n            _vertex_source = result['words_'+vertex_source]\n        else:\n            _vertex_source = result['words_all_filters']\n\n        if edge_source in options:\n            _edge_source   = result['words_'+edge_source]\n        else:\n            _edge_source   = result['words_no_stop_words']\n\n        self.keywords = util.sort_words(_vertex_source, _edge_source, window = window, pagerank_config = pagerank_config)\n\n    def get_keywords(self, num = 6, word_min_len = 1):\n        \"\"\"获取最重要的num个长度大于等于word_min_len的关键词。\n\n        Return:\n        关键词列表。\n        \"\"\"\n        result = []\n        count = 0\n        for item in self.keywords:\n            if count >= num:\n                break\n            if len(item.word) >= word_min_len:\n                result.append(item)\n                count += 1\n        return result\n    \n    def get_keyphrases(self, keywords_num = 12, min_occur_num = 2): \n        \"\"\"获取关键短语。\n        获取 keywords_num 个关键词构造的可能出现的短语，要求这个短语在原文本中至少出现的次数为min_occur_num。\n\n        Return:\n        关键短语的列表。\n        \"\"\"\n        keywords_set = set([ item.word for item in self.get_keywords(num=keywords_num, word_min_len = 1)])\n        keyphrases = set()\n        for sentence in self.words_no_filter:\n            one = []\n            for word in sentence:\n                if word in keywords_set:\n                    one.append(word)\n                else:\n                    if len(one) >  1:\n                        keyphrases.add(''.join(one))\n                    if len(one) == 0:\n                        continue\n                    else:\n                        one = []\n            # 兜底\n            if len(one) >  1:\n                keyphrases.add(''.join(one))\n\n        return [phrase for phrase in keyphrases \n                if self.text.count(phrase) >= min_occur_num]\n\nif __name__ == '__main__':\n    pass"
  },
  {
    "path": "textrank4zh/TextRank4Sentence.py",
    "content": "#-*- encoding:utf-8 -*-\n\"\"\"\n@author:   letian\n@homepage: http://www.letiantian.me\n@github:   https://github.com/someus/\n\"\"\"\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport networkx as nx\nimport numpy as np\n\nfrom . import util\nfrom .Segmentation import Segmentation\n\nclass TextRank4Sentence(object):\n    \n    def __init__(self, stop_words_file = None, \n                 allow_speech_tags = util.allow_speech_tags,\n                 delimiters = util.sentence_delimiters):\n        \"\"\"\n        Keyword arguments:\n        stop_words_file  --  str，停止词文件路径，若不是str则是使用默认停止词文件\n        delimiters       --  默认值是`?!;？！。；…\\n`，用来将文本拆分为句子。\n        \n        Object Var:\n        self.sentences               --  由句子组成的列表。\n        self.words_no_filter         --  对sentences中每个句子分词而得到的两级列表。\n        self.words_no_stop_words     --  去掉words_no_filter中的停止词而得到的两级列表。\n        self.words_all_filters       --  保留words_no_stop_words中指定词性的单词而得到的两级列表。\n        \"\"\"\n        self.seg = Segmentation(stop_words_file=stop_words_file,\n                                allow_speech_tags=allow_speech_tags,\n                                delimiters=delimiters)\n        \n        self.sentences = None\n        self.words_no_filter = None     # 2维列表\n        self.words_no_stop_words = None\n        self.words_all_filters = None\n        \n        self.key_sentences = None\n        \n    def analyze(self, text, lower = False, \n              source = 'no_stop_words', \n              sim_func = util.get_similarity,\n              pagerank_config = {'alpha': 0.85,}):\n        \"\"\"\n        Keyword arguments:\n        text                 --  文本内容，字符串。\n        lower                --  是否将文本转换为小写。默认为False。\n        source               --  选择使用words_no_filter, words_no_stop_words, words_all_filters中的哪一个来生成句子之间的相似度。\n                                 默认值为`'all_filters'`，可选值为`'no_filter', 'no_stop_words', 'all_filters'`。\n        sim_func             --  指定计算句子相似度的函数。\n        \"\"\"\n        \n        self.key_sentences = []\n        \n        result = self.seg.segment(text=text, lower=lower)\n        self.sentences = result.sentences\n        self.words_no_filter = result.words_no_filter\n        self.words_no_stop_words = result.words_no_stop_words\n        self.words_all_filters   = result.words_all_filters\n\n        options = ['no_filter', 'no_stop_words', 'all_filters']\n        if source in options:\n            _source = result['words_'+source]\n        else:\n            _source = result['words_no_stop_words']\n\n        self.key_sentences = util.sort_sentences(sentences = self.sentences,\n                                                 words     = _source,\n                                                 sim_func  = sim_func,\n                                                 pagerank_config = pagerank_config)\n\n            \n    def get_key_sentences(self, num = 6, sentence_min_len = 6):\n        \"\"\"获取最重要的num个长度大于等于sentence_min_len的句子用来生成摘要。\n\n        Return:\n        多个句子组成的列表。\n        \"\"\"\n        result = []\n        count = 0\n        for item in self.key_sentences:\n            if count >= num:\n                break\n            if len(item['sentence']) >= sentence_min_len:\n                result.append(item)\n                count += 1\n        return result\n    \n\nif __name__ == '__main__':\n    pass"
  },
  {
    "path": "textrank4zh/__init__.py",
    "content": "#-*- encoding:utf-8 -*-\nfrom __future__ import absolute_import\nfrom .TextRank4Keyword import TextRank4Keyword\nfrom .TextRank4Sentence import TextRank4Sentence\nfrom . import Segmentation\nfrom . import util\n\nversion = '0.2'"
  },
  {
    "path": "textrank4zh/stopwords.txt",
    "content": "?\n、\n。\n“\n”\n《\n》\n！\n，\n：\n；\n？\n啊\n阿\n哎\n哎呀\n哎哟\n唉\n俺\n俺们\n按\n按照\n吧\n吧哒\n把\n罢了\n被\n本\n本着\n比\n比方\n比如\n鄙人\n彼\n彼此\n边\n别\n别的\n别说\n并\n并且\n不比\n不成\n不单\n不但\n不独\n不管\n不光\n不过\n不仅\n不拘\n不论\n不怕\n不然\n不如\n不特\n不惟\n不问\n不只\n朝\n朝着\n趁\n趁着\n乘\n冲\n除\n除此之外\n除非\n除了\n此\n此间\n此外\n从\n从而\n打\n待\n但\n但是\n当\n当着\n到\n得\n的\n的话\n等\n等等\n地\n第\n叮咚\n对\n对于\n多\n多少\n而\n而况\n而且\n而是\n而外\n而言\n而已\n尔后\n反过来\n反过来说\n反之\n非但\n非徒\n否则\n嘎\n嘎登\n该\n赶\n个\n各\n各个\n各位\n各种\n各自\n给\n根据\n跟\n故\n故此\n固然\n关于\n管\n归\n果然\n果真\n过\n哈\n哈哈\n呵\n和\n何\n何处\n何况\n何时\n嘿\n哼\n哼唷\n呼哧\n乎\n哗\n还是\n还有\n换句话说\n换言之\n或\n或是\n或者\n极了\n及\n及其\n及至\n即\n即便\n即或\n即令\n即若\n即使\n几\n几时\n己\n既\n既然\n既是\n继而\n加之\n假如\n假若\n假使\n鉴于\n将\n较\n较之\n叫\n接着\n结果\n借\n紧接着\n进而\n尽\n尽管\n经\n经过\n就\n就是\n就是说\n据\n具体地说\n具体说来\n开始\n开外\n靠\n咳\n可\n可见\n可是\n可以\n况且\n啦\n来\n来着\n离\n例如\n哩\n连\n连同\n两者\n了\n临\n另\n另外\n另一方面\n论\n嘛\n吗\n慢说\n漫说\n冒\n么\n每\n每当\n们\n莫若\n某\n某个\n某些\n拿\n哪\n哪边\n哪儿\n哪个\n哪里\n哪年\n哪怕\n哪天\n哪些\n哪样\n那\n那边\n那儿\n那个\n那会儿\n那里\n那么\n那么些\n那么样\n那时\n那些\n那样\n乃\n乃至\n呢\n能\n你\n你们\n您\n宁\n宁可\n宁肯\n宁愿\n哦\n呕\n啪达\n旁人\n呸\n凭\n凭借\n其\n其次\n其二\n其他\n其它\n其一\n其余\n其中\n起\n起见\n起见\n岂但\n恰恰相反\n前后\n前者\n且\n然而\n然后\n然则\n让\n人家\n任\n任何\n任凭\n如\n如此\n如果\n如何\n如其\n如若\n如上所述\n若\n若非\n若是\n啥\n上下\n尚且\n设若\n设使\n甚而\n甚么\n甚至\n省得\n时候\n什么\n什么样\n使得\n是\n是的\n首先\n谁\n谁知\n顺\n顺着\n似的\n虽\n虽然\n虽说\n虽则\n随\n随着\n所\n所以\n他\n他们\n他人\n它\n它们\n她\n她们\n倘\n倘或\n倘然\n倘若\n倘使\n腾\n替\n通过\n同\n同时\n哇\n万一\n往\n望\n为\n为何\n为了\n为什么\n为着\n喂\n嗡嗡\n我\n我们\n呜\n呜呼\n乌乎\n无论\n无宁\n毋宁\n嘻\n吓\n相对而言\n像\n向\n向着\n嘘\n呀\n焉\n沿\n沿着\n要\n要不\n要不然\n要不是\n要么\n要是\n也\n也罢\n也好\n一\n一般\n一旦\n一方面\n一来\n一切\n一样\n一则\n依\n依照\n矣\n以\n以便\n以及\n以免\n以至\n以至于\n以致\n抑或\n因\n因此\n因而\n因为\n哟\n用\n由\n由此可见\n由于\n有\n有的\n有关\n有些\n又\n于\n于是\n于是乎\n与\n与此同时\n与否\n与其\n越是\n云云\n哉\n再说\n再者\n在\n在下\n咱\n咱们\n则\n怎\n怎么\n怎么办\n怎么样\n怎样\n咋\n照\n照着\n者\n这\n这边\n这儿\n这个\n这会儿\n这就是说\n这里\n这么\n这么点儿\n这么些\n这么样\n这时\n这些\n这样\n正如\n吱\n之\n之类\n之所以\n之一\n只是\n只限\n只要\n只有\n至\n至于\n诸位\n着\n着呢\n自\n自从\n自个儿\n自各儿\n自己\n自家\n自身\n综上所述\n总的来看\n总的来说\n总的说来\n总而言之\n总之\n纵\n纵令\n纵然\n纵使\n遵照\n作为\n兮\n呃\n呗\n咚\n咦\n喏\n啐\n喔唷\n嗬\n嗯\n嗳\na\nable\nabout\nabove\nabroad\naccording\naccordingly\nacross\nactually\nadj\nafter\nafterwards\nagain\nagainst\nago\nahead\nain't\nall\nallow\nallows\nalmost\nalone\nalong\nalongside\nalready\nalso\nalthough\nalways\nam\namid\namidst\namong\namongst\nan\nand\nanother\nany\nanybody\nanyhow\nanyone\nanything\nanyway\nanyways\nanywhere\napart\nappear\nappreciate\nappropriate\nare\naren't\naround\nas\na's\naside\nask\nasking\nassociated\nat\navailable\naway\nawfully\nb\nback\nbackward\nbackwards\nbe\nbecame\nbecause\nbecome\nbecomes\nbecoming\nbeen\nbefore\nbeforehand\nbegin\nbehind\nbeing\nbelieve\nbelow\nbeside\nbesides\nbest\nbetter\nbetween\nbeyond\nboth\nbrief\nbut\nby\nc\ncame\ncan\ncannot\ncant\ncan't\ncaption\ncause\ncauses\ncertain\ncertainly\nchanges\nclearly\nc'mon\nco\nco.\ncom\ncome\ncomes\nconcerning\nconsequently\nconsider\nconsidering\ncontain\ncontaining\ncontains\ncorresponding\ncould\ncouldn't\ncourse\nc's\ncurrently\nd\ndare\ndaren't\ndefinitely\ndescribed\ndespite\ndid\ndidn't\ndifferent\ndirectly\ndo\ndoes\ndoesn't\ndoing\ndone\ndon't\ndown\ndownwards\nduring\ne\neach\nedu\neg\neight\neighty\neither\nelse\nelsewhere\nend\nending\nenough\nentirely\nespecially\net\netc\neven\never\nevermore\nevery\neverybody\neveryone\neverything\neverywhere\nex\nexactly\nexample\nexcept\nf\nfairly\nfar\nfarther\nfew\nfewer\nfifth\nfirst\nfive\nfollowed\nfollowing\nfollows\nfor\nforever\nformer\nformerly\nforth\nforward\nfound\nfour\nfrom\nfurther\nfurthermore\ng\nget\ngets\ngetting\ngiven\ngives\ngo\ngoes\ngoing\ngone\ngot\ngotten\ngreetings\nh\nhad\nhadn't\nhalf\nhappens\nhardly\nhas\nhasn't\nhave\nhaven't\nhaving\nhe\nhe'd\nhe'll\nhello\nhelp\nhence\nher\nhere\nhereafter\nhereby\nherein\nhere's\nhereupon\nhers\nherself\nhe's\nhi\nhim\nhimself\nhis\nhither\nhopefully\nhow\nhowbeit\nhowever\nhundred\ni\ni'd\nie\nif\nignored\ni'll\ni'm\nimmediate\nin\ninasmuch\ninc\ninc.\nindeed\nindicate\nindicated\nindicates\ninner\ninside\ninsofar\ninstead\ninto\ninward\nis\nisn't\nit\nit'd\nit'll\nits\nit's\nitself\ni've\nj\njust\nk\nkeep\nkeeps\nkept\nknow\nknown\nknows\nl\nlast\nlately\nlater\nlatter\nlatterly\nleast\nless\nlest\nlet\nlet's\nlike\nliked\nlikely\nlikewise\nlittle\nlook\nlooking\nlooks\nlow\nlower\nltd\nm\nmade\nmainly\nmake\nmakes\nmany\nmay\nmaybe\nmayn't\nme\nmean\nmeantime\nmeanwhile\nmerely\nmight\nmightn't\nmine\nminus\nmiss\nmore\nmoreover\nmost\nmostly\nmr\nmrs\nmuch\nmust\nmustn't\nmy\nmyself\nn\nname\nnamely\nnd\nnear\nnearly\nnecessary\nneed\nneedn't\nneeds\nneither\nnever\nneverf\nneverless\nnevertheless\nnew\nnext\nnine\nninety\nno\nnobody\nnon\nnone\nnonetheless\nnoone\nno-one\nnor\nnormally\nnot\nnothing\nnotwithstanding\nnovel\nnow\nnowhere\no\nobviously\nof\noff\noften\noh\nok\nokay\nold\non\nonce\none\nones\none's\nonly\nonto\nopposite\nor\nother\nothers\notherwise\nought\noughtn't\nour\nours\nourselves\nout\noutside\nover\noverall\nown\np\nparticular\nparticularly\npast\nper\nperhaps\nplaced\nplease\nplus\npossible\npresumably\nprobably\nprovided\nprovides\nq\nque\nquite\nqv\nr\nrather\nrd\nre\nreally\nreasonably\nrecent\nrecently\nregarding\nregardless\nregards\nrelatively\nrespectively\nright\nround\ns\nsaid\nsame\nsaw\nsay\nsaying\nsays\nsecond\nsecondly\nsee\nseeing\nseem\nseemed\nseeming\nseems\nseen\nself\nselves\nsensible\nsent\nserious\nseriously\nseven\nseveral\nshall\nshan't\nshe\nshe'd\nshe'll\nshe's\nshould\nshouldn't\nsince\nsix\nso\nsome\nsomebody\nsomeday\nsomehow\nsomeone\nsomething\nsometime\nsometimes\nsomewhat\nsomewhere\nsoon\nsorry\nspecified\nspecify\nspecifying\nstill\nsub\nsuch\nsup\nsure\nt\ntake\ntaken\ntaking\ntell\ntends\nth\nthan\nthank\nthanks\nthanx\nthat\nthat'll\nthats\nthat's\nthat've\nthe\ntheir\ntheirs\nthem\nthemselves\nthen\nthence\nthere\nthereafter\nthereby\nthere'd\ntherefore\ntherein\nthere'll\nthere're\ntheres\nthere's\nthereupon\nthere've\nthese\nthey\nthey'd\nthey'll\nthey're\nthey've\nthing\nthings\nthink\nthird\nthirty\nthis\nthorough\nthoroughly\nthose\nthough\nthree\nthrough\nthroughout\nthru\nthus\ntill\nto\ntogether\ntoo\ntook\ntoward\ntowards\ntried\ntries\ntruly\ntry\ntrying\nt's\ntwice\ntwo\nu\nun\nunder\nunderneath\nundoing\nunfortunately\nunless\nunlike\nunlikely\nuntil\nunto\nup\nupon\nupwards\nus\nuse\nused\nuseful\nuses\nusing\nusually\nv\nvalue\nvarious\nversus\nvery\nvia\nviz\nvs\nw\nwant\nwants\nwas\nwasn't\nway\nwe\nwe'd\nwelcome\nwell\nwe'll\nwent\nwere\nwe're\nweren't\nwe've\nwhat\nwhatever\nwhat'll\nwhat's\nwhat've\nwhen\nwhence\nwhenever\nwhere\nwhereafter\nwhereas\nwhereby\nwherein\nwhere's\nwhereupon\nwherever\nwhether\nwhich\nwhichever\nwhile\nwhilst\nwhither\nwho\nwho'd\nwhoever\nwhole\nwho'll\nwhom\nwhomever\nwho's\nwhose\nwhy\nwill\nwilling\nwish\nwith\nwithin\nwithout\nwonder\nwon't\nwould\nwouldn't\nx\ny\nyes\nyet\nyou\nyou'd\nyou'll\nyour\nyou're\nyours\nyourself\nyourselves\nyou've\nz\nzero"
  },
  {
    "path": "textrank4zh/util.py",
    "content": "#-*- encoding:utf-8 -*-\n\"\"\"\n@author:   letian\n@homepage: http://www.letiantian.me\n@github:   https://github.com/someus/\n\"\"\"\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport os\nimport math\nimport networkx as nx\nimport numpy as np\nimport sys\n\ntry:\n    reload(sys)\n    sys.setdefaultencoding('utf-8')\nexcept:\n    pass\n    \nsentence_delimiters = ['?', '!', ';', '？', '！', '。', '；', '……', '…', '\\n']\nallow_speech_tags = ['an', 'i', 'j', 'l', 'n', 'nr', 'nrfg', 'ns', 'nt', 'nz', 't', 'v', 'vd', 'vn', 'eng']\n\nPY2 = sys.version_info[0] == 2\nif not PY2:\n    # Python 3.x and up\n    text_type    = str\n    string_types = (str,)\n    xrange       = range\n\n    def as_text(v):  ## 生成unicode字符串\n        if v is None:\n            return None\n        elif isinstance(v, bytes):\n            return v.decode('utf-8', errors='ignore')\n        elif isinstance(v, str):\n            return v\n        else:\n            raise ValueError('Unknown type %r' % type(v))\n\n    def is_text(v):\n        return isinstance(v, text_type)\n\nelse:\n    # Python 2.x\n    text_type    = unicode\n    string_types = (str, unicode)\n    xrange       = xrange\n\n    def as_text(v):\n        if v is None:\n            return None\n        elif isinstance(v, unicode):\n            return v\n        elif isinstance(v, str):\n            return v.decode('utf-8', errors='ignore')\n        else:\n            raise ValueError('Invalid type %r' % type(v))\n\n    def is_text(v):\n        return isinstance(v, text_type)\n\n__DEBUG = None\n\ndef debug(*args):\n    global __DEBUG\n    if __DEBUG is None:\n        try:\n            if os.environ['DEBUG'] == '1':\n                __DEBUG = True\n            else:\n                __DEBUG = False\n        except:\n            __DEBUG = False\n    if __DEBUG:\n        print( ' '.join([str(arg) for arg in args]) )\n\nclass AttrDict(dict):\n    \"\"\"Dict that can get attribute by dot\"\"\"\n    def __init__(self, *args, **kwargs):\n        super(AttrDict, self).__init__(*args, **kwargs)\n        self.__dict__ = self\n\n\ndef combine(word_list, window = 2):\n    \"\"\"构造在window下的单词组合，用来构造单词之间的边。\n    \n    Keyword arguments:\n    word_list  --  list of str, 由单词组成的列表。\n    windows    --  int, 窗口大小。\n    \"\"\"\n    if window < 2: window = 2\n    for x in xrange(1, window):\n        if x >= len(word_list):\n            break\n        word_list2 = word_list[x:]\n        res = zip(word_list, word_list2)\n        for r in res:\n            yield r\n\ndef get_similarity(word_list1, word_list2):\n    \"\"\"默认的用于计算两个句子相似度的函数。\n\n    Keyword arguments:\n    word_list1, word_list2  --  分别代表两个句子，都是由单词组成的列表\n    \"\"\"\n    words   = list(set(word_list1 + word_list2))        \n    vector1 = [float(word_list1.count(word)) for word in words]\n    vector2 = [float(word_list2.count(word)) for word in words]\n    \n    vector3 = [vector1[x]*vector2[x]  for x in xrange(len(vector1))]\n    vector4 = [1 for num in vector3 if num > 0.]\n    co_occur_num = sum(vector4)\n\n    if abs(co_occur_num) <= 1e-12:\n        return 0.\n    \n    denominator = math.log(float(len(word_list1))) + math.log(float(len(word_list2))) # 分母\n    \n    if abs(denominator) < 1e-12:\n        return 0.\n    \n    return co_occur_num / denominator\n\ndef sort_words(vertex_source, edge_source, window = 2, pagerank_config = {'alpha': 0.85,}):\n    \"\"\"将单词按关键程度从大到小排序\n\n    Keyword arguments:\n    vertex_source   --  二维列表，子列表代表句子，子列表的元素是单词，这些单词用来构造pagerank中的节点\n    edge_source     --  二维列表，子列表代表句子，子列表的元素是单词，根据单词位置关系构造pagerank中的边\n    window          --  一个句子中相邻的window个单词，两两之间认为有边\n    pagerank_config --  pagerank的设置\n    \"\"\"\n    sorted_words   = []\n    word_index     = {}\n    index_word     = {}\n    _vertex_source = vertex_source\n    _edge_source   = edge_source\n    words_number   = 0\n    for word_list in _vertex_source:\n        for word in word_list:\n            if not word in word_index:\n                word_index[word] = words_number\n                index_word[words_number] = word\n                words_number += 1\n\n    graph = np.zeros((words_number, words_number))\n    \n    for word_list in _edge_source:\n        for w1, w2 in combine(word_list, window):\n            if w1 in word_index and w2 in word_index:\n                index1 = word_index[w1]\n                index2 = word_index[w2]\n                graph[index1][index2] = 1.0\n                graph[index2][index1] = 1.0\n\n    debug('graph:\\n', graph)\n    \n    nx_graph = nx.from_numpy_matrix(graph)\n    scores = nx.pagerank(nx_graph, **pagerank_config)          # this is a dict\n    sorted_scores = sorted(scores.items(), key = lambda item: item[1], reverse=True)\n    for index, score in sorted_scores:\n        item = AttrDict(word=index_word[index], weight=score)\n        sorted_words.append(item)\n\n    return sorted_words\n\ndef sort_sentences(sentences, words, sim_func = get_similarity, pagerank_config = {'alpha': 0.85,}):\n    \"\"\"将句子按照关键程度从大到小排序\n\n    Keyword arguments:\n    sentences         --  列表，元素是句子\n    words             --  二维列表，子列表和sentences中的句子对应，子列表由单词组成\n    sim_func          --  计算两个句子的相似性，参数是两个由单词组成的列表\n    pagerank_config   --  pagerank的设置\n    \"\"\"\n    sorted_sentences = []\n    _source = words\n    sentences_num = len(_source)        \n    graph = np.zeros((sentences_num, sentences_num))\n    \n    for x in xrange(sentences_num):\n        for y in xrange(x, sentences_num):\n            similarity = sim_func( _source[x], _source[y] )\n            graph[x, y] = similarity\n            graph[y, x] = similarity\n            \n    nx_graph = nx.from_numpy_matrix(graph)\n    scores = nx.pagerank(nx_graph, **pagerank_config)              # this is a dict\n    sorted_scores = sorted(scores.items(), key = lambda item: item[1], reverse=True)\n\n    for index, score in sorted_scores:\n        item = AttrDict(index=index, sentence=sentences[index], weight=score)\n        sorted_sentences.append(item)\n\n    return sorted_sentences\n\nif __name__ == '__main__':\n    pass"
  }
]