class TestRemoveLists(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_lists(self): text = "=== 航空 ===\n*[[南昌昌北国际机场]]\n*[[赣州黄金机场]]\n*[[景德镇罗家机场]]\n*[[九江庐山机场]]\n*[[吉" \ "安井冈山机场]]\n*[[宜春明月山机场]]\n*[[上饶三清山机场]]" expected = "=== 航空 ===\n[[南昌昌北国际机场]]\n[[赣州黄金机场]]\n[[景德镇罗家机场]]\n[[九江庐山机场]]\n[[吉安井" \ "冈山机场]]\n[[宜春明月山机场]]\n[[上饶三清山机场]]" actual = self.cleaner._remove_lists(text) self.assertEqual(expected, actual) text = "=== 散文 ===\n{{Main article|散文}}\n#[[散文]]是一种没有严格的韵律和篇幅限制的文学形式,与[[韵文]]相对。中国" \ "的散文从先秦[[诸子散文]]发展而来,代有散文[[名家]][[名作]]。其中历史散文和[[赋]]体以及奏议文告等[[应用文]]体," \ "对后代产生了深远影响。\n#[[应用文]]是針對特定需求而有的文體,例如公告、廣告等。\n#[[小品文]]是从作者的观点来讨论" \ "某一议题。\n#[[文言文]],常指非八股文的文體。\n#[[骈文]]是句式多為四六句及對仗的文言文文體。\n#[[随笔]],兼有議" \ "論和抒情兩種特性的散文。\n#[[笔记]]\n#[[遊记]]" expected = "=== 散文 ===\n{{Main article|散文}}\n[[散文]]是一种没有严格的韵律和篇幅限制的文学形式,与[[韵文]]相对。" \ "中国的散文从先秦[[诸子散文]]发展而来,代有散文[[名家]][[名作]]。其中历史散文和[[赋]]体以及奏议文告等[[应用" \ "文]]体,对后代产生了深远影响。\n[[应用文]]是針對特定需求而有的文體,例如公告、廣告等。\n[[小品文]]是从作者的" \ "观点来讨论某一议题。\n[[文言文]],常指非八股文的文體。\n[[骈文]]是句式多為四六句及對仗的文言文文體。\n[[随笔" \ "]],兼有議論和抒情兩種特性的散文。\n[[笔记]]\n[[遊记]]" actual = self.cleaner._remove_lists(text) self.assertEqual(expected, actual)
def main(): pathWikiXML = os.path.join(PATH_WIKI_XML, FILENAME_WIKI) pathArticles = os.path.join(PATH_CSV, FILENAME_ARTICLES) pathArticlesRedirect = os.path.join(PATH_CSV, FILENAME_REDIRECT) pathTemplateRedirect = os.path.join(PATH_CSV, FILENAME_TEMPLATE) templateCount = 0 articleCount = 0 totalCount = 0 redirectCount = 0 with open(pathArticles, 'w') as output_file: cw = csv.writer(output_file, delimiter='\t') cw.writerow(['Title', 'Text']) cleaner = Cleaner() for title, text in tqdm(iterate(pathWikiXML)): totalCount += 1 text = cleaner.clean_text(text) #cleaned_text, links = cleaner.build_links(text) if text.startswith("REDIRECT"): redirectCount += 1 elif text.startswith("TEMPLATE"): templateCount += 1 else: articleCount += 1 with open(pathArticles, 'a') as output_file: cw = csv.writer(output_file, delimiter='\t') cw.writerow([title, text]) print("Total pages: {:,}".format(totalCount)) print("Template pages: {:,}".format(templateCount)) print("Article pages: {:,}".format(articleCount)) print("Redirect pages: {:,}".format(redirectCount))
class TestRemoveResources(unittest.TestCase): def setUp(self): self.cleaner = Cleaner() def test_remove_file_link_normal(self): text = '[[File:Portrait of Milton Friedman.jpg|right|thumb|upright|[[米爾頓·傅利曼]]是芝加哥學派最知名的經濟學家。]]' expected = '' actual = self.cleaner._remove_file_links(text) self.assertEqual(expected, actual) text = ']]\n[[File:Nicaea icon.jpg|thumb|230px|羅馬帝國的[[政教合一]]]]\n[[' expected = ']]\n\n[[' actual = self.cleaner._remove_file_links(text) self.assertEqual(expected, actual) def test_remove_file_link_unfinished(self): text = '[[File:Diagram of sentence.png|thumb|科刑流程圖]' expected = '[[File:Diagram of sentence.png|thumb|科刑流程圖]' actual = self.cleaner._remove_file_links(text) self.assertEqual(expected, actual) def test_remove_file_link_not_exist(self): text = '[File:Emile Durkheim.jpg|thumb|180px|[[爱米尔·涂尔干]]]' expected = '[File:Emile Durkheim.jpg|thumb|180px|[[爱米尔·涂尔干]]]' actual = self.cleaner._remove_file_links(text) self.assertEqual(expected, actual) def test_remove_image_link_normal(self): text = '[[Image:Transistorer (croped).jpg|thumb|upright|幾個不同大小的電晶體]]' expected = '' actual = self.cleaner._remove_image_links(text) self.assertEqual(expected, actual)
class TestRemoveChoices(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_choice(self): text = "例如,[[全球資訊網]]是在[[歐洲核子研究組織]]由-{A|zh:[[蒂姆·伯纳斯-李]];zh-cn:[[蒂姆·伯纳斯-李]];zh-tw:[[提" \ "姆·柏納-李]];zh-hk:[[添·柏納-李]];}-創始與發展成功的,原先設計目标為向組織內部和全世界的物理學者提供資訊傳播服務。" \ "廣受歡迎的[[arXiv]]網站也是在類似狀況下創立的。" expected = "例如,[[全球資訊網]]是在[[歐洲核子研究組織]]由[[蒂姆·伯纳斯-李]]創始與發展成功的,原先設計目标為向組織內部和全" \ "世界的物理學者提供資訊傳播服務。廣受歡迎的[[arXiv]]網站也是在類似狀況下創立的。" actual = self.cleaner._remove_choices(text) self.assertEqual(expected, actual) text = "廣州非常國會取消軍政府,改總裁-{制}-為總統制" expected = "廣州非常國會取消軍政府,改總裁制為總統制" actual = self.cleaner._remove_choices(text) self.assertEqual(expected, actual) text = "一种-{zh-tw:[[自由軟體]];zh-hk:[[自由軟件]];zh-cn:[[自由软件]]}-計劃" expected = "一种[[自由軟件]]計劃" actual = self.cleaner._remove_choices(text) self.assertEqual(expected, actual) text = "一种-{zh-tw:[[自由軟體]]}-計劃" expected = "一种[[自由軟體]]計劃" actual = self.cleaner._remove_choices(text) self.assertEqual(expected, actual)
class TestRemoveTemplates(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_templates(self): text = "'''数学'''是利用符号语言研究[[數量]]<ref name=\"OED\">{{cite web |url=http://oed.com/view/Entry/114974" \ " |title=mathematics, ''n.'' |publisher=Oxford University Press |work=Oxford English Dictionary |ye" \ "ar=2012 |accessdate=2012-07-16 |quote=The science of space, number, quantity, and arrangement, who" \ "se methods involve logical reasoning and usually the use of symbolic notation, and which includes " \ "geometry, arithmetic, algebra, and analysis.}}{{en}}</ref>、[[数学结构|结构]]<ref name=\"Kneebone\">{" \ "{cite book |title=Mathematical Logic and the Foundations of Mathematics: An Introductory Survey |p" \ "ublisher=Dover |author=Kneebone, G.T. |year=1963 |pages=[http://books.google.com/books?id=tCXxf4vb" \ "XCcC&pg=PA4 4] |isbn=0-486-41712-3 |quote=Mathematics ... is simply the study of abstract struc" \ "tures, or formal patterns of connectedness.}}{{en}}</ref>、[[变化]]<ref name=\"LaTorre\">{{cite book" \ " |title=Calculus Concepts: An Informal Approach to the Mathematics of Change |publisher=Cengage Le" \ "arning |author=LaTorre, Donald R., John W. Kenelly, Iris B. Reed, Laurel R. Carpenter, and Cynthia" \ " R Harris |year=2011 |pages=[http://books.google.com/books?id=1Ebu2Tij4QsC&pg=PA2 2] |isbn=1-4" \ "390-4957-2 |quote=Calculus is the study of change—how things change, and how quickly they change.}" \ "}{{en}}</ref><ref name=\"Ramana\">{{cite book |title=Applied Mathematics |publisher=Tata McGraw–Hi" \ "ll Education |author=Ramana |year=2007 |page=[http://books.google.com/books?id=XCRC6BeKhIIC&pg" \ "=SA2-PA10 2.10] |isbn=0-07-066753-5 |quote=The mathematical study of change, motion, growth or dec" \ "ay is calculus.}}{{en}}</ref>以及[[空间 (数学)|空间]]<ref name=OED/>等概念的一門[[学科]],从某种角度看屬於" \ "[[形式科學]]的一種。數學透過[[抽象化]]和[[逻辑|邏輯]][[推理]]的使用,由[[計數]]、[[计算|計算]]、[[量度]]和對物" \ "體[[形狀]]及[[運動 (物理學)|運動]]的觀察而產生。[[数学家|數學家]]們拓展這些概念,為了公式化新的[[猜想]]以及從選定" \ "的[[公理]]及[[定義]]中建立起[[严谨 (数学)|嚴謹]]推導出的定理。<ref>Jourdain</ref>" expected = "'''数学'''是利用符号语言研究[[數量]]<ref name=\"OED\"></ref>、[[数学结构|结构]]<ref name=\"Kneebone\"" \ "></ref>、[[变化]]<ref name=\"LaTorre\"></ref><ref name=\"Ramana\"></ref>以及[[空间 (数学)|空间]]<re" \ "f name=OED/>等概念的一門[[学科]],从某种角度看屬於[[形式科學]]的一種。數學透過[[抽象化]]和[[逻辑|邏輯]][[推" \ "理]]的使用,由[[計數]]、[[计算|計算]]、[[量度]]和對物體[[形狀]]及[[運動 (物理學)|運動]]的觀察而產生。[[数学" \ "家|數學家]]們拓展這些概念,為了公式化新的[[猜想]]以及從選定的[[公理]]及[[定義]]中建立起[[严谨 (数学)|嚴謹]]" \ "推導出的定理。<ref>Jourdain</ref>" actual = self.cleaner._remove_templates(text) self.assertEqual(expected, actual) text = "亚里士多德死后,整个哲学界陷入了独立时期,称为{{link-en|希腊化哲学|Hellenistic_philosophy}}时期。因为整个社会" \ "和政治陷入混乱。这段时期产生了[[斯多葛学派]]和[[伊壁鸠鲁学派]],以及[[皮浪主义|怀疑主义派]]、[[新柏拉图主义|新柏" \ "拉图派]]和{{le|新毕达哥拉斯主义|Neopythagoreanism}}。这些学派的共同特点是伦理化。斯多葛学派主要是顺应自然和自制" \ "。伊壁鸠鲁学派则是把快乐作为生活的本质和善的标准。而新柏拉图派和新毕达哥拉斯派都是带有[[宗教]]主义的哲学,并逐渐产" \ "生融化[[基督教]]和希腊哲学于一体的理论,即为后来的[[基督教哲学]]。" expected = "亚里士多德死后,整个哲学界陷入了独立时期,称为希腊化哲学时期。因为整个社会和政治陷入混乱。这段时期产生了[[斯多葛" \ "学派]]和[[伊壁鸠鲁学派]],以及[[皮浪主义|怀疑主义派]]、[[新柏拉图主义|新柏拉图派]]和新毕达哥拉斯主义。这些学" \ "派的共同特点是伦理化。斯多葛学派主要是顺应自然和自制。伊壁鸠鲁学派则是把快乐作为生活的本质和善的标准。而新柏拉图" \ "派和新毕达哥拉斯派都是带有[[宗教]]主义的哲学,并逐渐产生融化[[基督教]]和希腊哲学于一体的理论,即为后来的[[基督" \ "教哲学]]。" actual = self.cleaner._remove_templates(text) self.assertEqual(expected, actual) def test_remove_quotes(self): text = "He announced, \"The answer was 'Yes!{{' \"}} or {{\" '}}Yes!" expected = "He announced, \"The answer was 'Yes!'\" or \"'Yes!" actual = self.cleaner._remove_templates(text) self.assertEqual(expected, actual)
class TestBuildLinks(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_build_links(self): text = "[[印欧语系|西方语言]]中“數學”(μαθηματικά)一詞源自於[[古希臘語]]的μάθημα(máthēma),其" \ "有“學習”、“學問”、“[[科學]]”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μα" \ "θηματικός(mathēmatikós),意思為''和學習有關的''或''用功的'',亦會被用來指''數學的''。其在[[英语]]中" \ "表面上的複數形式,及在[[法语]]中的表面複數形式''les mathématiques'',可溯至[[拉丁文]]的中性複數''mathe" \ "matica'',由[[西塞罗]]譯自希臘文複數τα μαθηματικά(ta mathēmatiká),此一希臘語被[[亚里士多德]]拿來指" \ "「[[萬物皆數]]」的概念。" expected = "西方语言中“數學”(μαθηματικά)一詞源自於古希臘語的μάθημα(máthēma),其有“學習”、“學問”、“科" \ "學”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μαθηματικός(mathēmatikós)," \ "意思為''和學習有關的''或''用功的'',亦會被用來指''數學的''。其在英语中表面上的複數形式,及在法语中的表面複數" \ "形式''les mathématiques'',可溯至拉丁文的中性複數''mathematica'',由西塞罗譯自希臘文複數τα μαθηματικά(t" \ "a mathēmatiká),此一希臘語被亚里士多德拿來指「萬物皆數」的概念。" actual, links = self.cleaner.build_links(text) self.assertEqual(expected, actual) def test_no_links(self): text = "西方语言中“數學”(μαθηματικά)一詞源自於古希臘語的μάθημα(máthēma),其有“學習”、“學問”、“科" \ "學”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μαθηματικός(mathēmatikós)," \ "意思為''和學習有關的''或''用功的'',亦會被用來指''數學的''。其在英语中表面上的複數形式,及在法语中的表面複數" \ "形式''les mathématiques'',可溯至拉丁文的中性複數''mathematica'',由西塞罗譯自希臘文複數τα μαθηματικά(t" \ "a mathēmatiká),此一希臘語被亚里士多德拿來指「萬物皆數」的概念。" expected = "西方语言中“數學”(μαθηματικά)一詞源自於古希臘語的μάθημα(máthēma),其有“學習”、“學問”、“科" \ "學”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μαθηματικός(mathēmatikós)," \ "意思為''和學習有關的''或''用功的'',亦會被用來指''數學的''。其在英语中表面上的複數形式,及在法语中的表面複數" \ "形式''les mathématiques'',可溯至拉丁文的中性複數''mathematica'',由西塞罗譯自希臘文複數τα μαθηματικά(t" \ "a mathēmatiká),此一希臘語被亚里士多德拿來指「萬物皆數」的概念。" text, links = self.cleaner.build_links(text) actual, links = self.cleaner.build_links(text) self.assertEqual(expected, actual) self.assertEqual(id(actual), id(text)) def test_category(self): text = "2004年6月28日 [[User:Shizhao|Shizhao]] [[MediaWiki:Categoryarticlecount]]被保护" expected = "2004年6月28日 Shizhao Categoryarticlecount被保护" text, links = self.cleaner.build_links(text) actual, links = self.cleaner.build_links(text) self.assertEqual(expected, actual) text = "[[Category:未被普遍承認的歷史國家]]" expected = "未被普遍承認的歷史國家" text, links = self.cleaner.build_links(text) actual, links = self.cleaner.build_links(text) self.assertEqual(expected, actual) text = "柏拉圖的著作(其中大多數都是對話錄)曾經被以好幾種不同方式出版過;因此對於柏拉圖著作的命名和引用也有數種不同的" \ "方式。有獨立條目的柏拉圖對話錄介紹可以在[[:Category:柏拉圖對話錄]]找到。" expected = "柏拉圖的著作(其中大多數都是對話錄)曾經被以好幾種不同方式出版過;因此對於柏拉圖著作的命名和引用也有數種不同" \ "的方式。有獨立條目的柏拉圖對話錄介紹可以在柏拉圖對話錄找到。" text, links = self.cleaner.build_links(text) actual, links = self.cleaner.build_links(text) self.assertEqual(expected, actual)
class TestIterate(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() self.current_path = os.path.dirname(os.path.abspath(__file__)) self.sample_file_path = os.path.join(self.current_path, 'wikis', 'zhwiki-test-pages.xml') def read_target(self, name): path = os.path.join(self.current_path, 'targets', name + '.txt') with codecs.open(path, 'r', 'utf8') as reader: target = reader.read() return target def save_temp(self, name, text): path = os.path.join(self.current_path, 'targets', name + '.tmp') with codecs.open(path, 'w', 'utf8') as writer: writer.write(text) def test_broken(self): broken_files = ['zhwiki-broken-%d.xml' % i for i in range(1, 5)] for broken_file in broken_files: path = os.path.join(self.current_path, 'wikis', broken_file) for _ in iterate(path): self.assertTrue(False) def test_clean(self): targets = { '数学': 'Mathematics', '哲学': 'Philosophy', '文學': 'Literature', } for target_title, target in targets.items(): found = False for title, text in iterate(self.sample_file_path): if title == target_title: found = True text = self.cleaner.clean_text(text) actual, _ = self.cleaner.build_links(text) expected = self.read_target(target) if actual != expected: self.save_temp(target, actual) self.assertEqual(expected, actual, target) else: text = self.cleaner.clean_text(text) self.cleaner.build_links(text) self.assertTrue(found)
class TestRemoveRefs(unittest.TestCase): def setUp(self): self.cleaner = Cleaner() def test_remove_ref_type_1(self): text = '數學有着久遠的歷史。它被認為起源於[[人|人類]]早期的生產活動:[[中國]]古代的[[六藝|六艺]]之一就有「數」<ref>《' \ '周礼·地官司徒·保氏》:「保氏掌谏王恶而养国子以道。乃教之六艺:一曰五礼,二曰六乐,三曰五射,四曰五驭,五曰六书,六' \ '曰九数。」东汉的郑玄在他的《周礼注疏·地官司徒·保氏》中引郑司农(郑众)所言:「九数:方田、粟米、差分、少广、商功、' \ '均输、方程、赢不足、旁要,今有重差、夕桀、勾股也。」</ref>,數學一詞在西方有[[希腊]]语[[詞源]]{{lang|el|μαθημα' \ 'τικός}}(mathematikós),意思是“学问的基础”,源于{{lang|el|μάθημα}}(máthema,“[[科学]],知识,学问”)。' expected = '數學有着久遠的歷史。它被認為起源於[[人|人類]]早期的生產活動:[[中國]]古代的[[六藝|六艺]]之一就有「數」,數學' \ '一詞在西方有[[希腊]]语[[詞源]]{{lang|el|μαθηματικός}}(mathematikós),意思是“学问的基础”,源于' \ '{{lang|el|μάθημα}}(máthema,“[[科学]],知识,学问”)。' actual = self.cleaner._remove_refs(text) self.assertEqual(expected, actual) def test_remove_ref_type_2(self): text = '这些新的哲学运动伴随着欧洲宗教和政治的剧变同时出现:[[宗教改革]]和[[封建制度_(歐洲)|封建制]]的衰落。虽然参与宗教' \ '改革的神学家们对哲学没有直接的兴趣,他们打破了神学和知识权威的传统基础。同时还伴随着[[信仰主义]]和[[怀疑主义]]的' \ '复兴,体现在[[德西德里乌斯·伊拉斯谟|伊拉斯谟]],[[米歇尔·德·蒙泰涅|蒙泰涅]]和{{le|弗朗西斯科·桑切斯|Francisco' \ ' Sanches|桑切斯}}等思想家身上<ref name=\"scepticism\"/><ref name=\"copleston\"/><ref name=\"' \ 'reformation\"/>。同时,[[民族国家]]政治上逐步的[[中央集权]]的过程得到了世俗政治哲学的响应,如[[尼可罗·' \ '马基亚维利]](常被描述为第一个现代政治思想家,或者是现代政治思想形成的关键点<ref name=\"Internet Encyclopedia ' \ 'of Philosophy\"/>)、[[托马斯·莫尔]]、[[德西德里乌斯·伊拉斯谟|伊拉斯谟]]、[[尤斯图斯·利普修斯]]、[[让·博丹]]' \ '和[[胡果·格老秀斯]]等的著作<ref name=\"renaissance5\"/><ref name=\"renaissance6\"/><ref name=\"amencps' \ '-25\" group=\"a\"/><ref name=\"brencps-25\" group=\"b\"/><ref name=\"cnencps-25\" group=\"d\"/>' expected = '这些新的哲学运动伴随着欧洲宗教和政治的剧变同时出现:[[宗教改革]]和[[封建制度_(歐洲)|封建制]]的衰落。虽然参与' \ '宗教改革的神学家们对哲学没有直接的兴趣,他们打破了神学和知识权威的传统基础。同时还伴随着[[信仰主义]]和[[怀疑' \ '主义]]的复兴,体现在[[德西德里乌斯·伊拉斯谟|伊拉斯谟]],[[米歇尔·德·蒙泰涅|蒙泰涅]]和{{le|弗朗西斯科·' \ '桑切斯|Francisco Sanches|桑切斯}}等思想家身上。同时,[[民族国家]]政治上逐步的[[中央集权]]的过程得到了世俗' \ '政治哲学的响应,如[[尼可罗·马基亚维利]](常被描述为第一个现代政治思想家,或者是现代政治思想形成的关键点)、' \ '[[托马斯·莫尔]]、[[德西德里乌斯·伊拉斯谟|伊拉斯谟]]、[[尤斯图斯·利普修斯]]、[[让·博丹]]和[[胡果·格老秀斯]]' \ '等的著作' actual = self.cleaner._remove_refs(text) self.assertEqual(expected, actual) def test_remove_ref_multiline(self): text = '[[史前史|史前]]的人類就已嘗試用自然的法則來衡量物質的多少、時間的長短等抽象的數量關係,比如[[时间单位]]有[[日]]、' \ '[[季節]]和[[年]]等。[[算术|算術]]([[加法|加]][[減法|減]][[乘法|乘]][[除法|除]])也自然而然地產生了。古代的石' \ '碑及泥版亦證實了當時已有[[几何学|幾何]]的知識<ref>{{Cite web \n |url= http://web.ptes.tp.edu.tw/big6/civ' \ 'il/babylonian-03.htm\n |title= 數學\n |accessdate=2013-10-06\n |publisher= 台北市立北投國小\n}}</ref>。' expected = '[[史前史|史前]]的人類就已嘗試用自然的法則來衡量物質的多少、時間的長短等抽象的數量關係,比如[[时间单位]]有[[日' \ ']]、[[季節]]和[[年]]等。[[算术|算術]]([[加法|加]][[減法|減]][[乘法|乘]][[除法|除]])也自然而然地產生了。' \ '古代的石碑及泥版亦證實了當時已有[[几何学|幾何]]的知識。' actual = self.cleaner._remove_refs(text) self.assertEqual(expected, actual)
class TestRemoveEmphasis(unittest.TestCase): def setUp(self): self.cleaner = Cleaner() def test_remove_html(self): text = '<text xml:space="preserve">' expected = '' actual = self.cleaner._remove_htmls(text) self.assertEqual(expected, actual)
class TestRemoveTitles(unittest.TestCase): def setUp(self): self.cleaner = Cleaner() def test_remove_titles(self): text = "== 研究 ==" expected = '研究' actual = self.cleaner._remove_titles(text) self.assertEqual(expected, actual) text = "===馬克思主義意義下的「民族」===" expected = '馬克思主義意義下的「民族」' actual = self.cleaner._remove_titles(text) self.assertEqual(expected, actual) text = "====主觀意識來定義====" expected = '主觀意識來定義' actual = self.cleaner._remove_titles(text) self.assertEqual(expected, actual)
def load_files(self): cleaner = Cleaner() i = 0 for title, text in iterate( 'wiki/simplewiki-20191120-pages-articles.xml'): if i >= self.files_number: break cleaned_text = cleaner.clean_text(text)[:self.characters_per_file] cleaned_fragment, _ = cleaner.build_links(text) self.texts.append(title) word_tokens = self.pattern.sub(' ', cleaned_text.lower()).split(' ') cleaned_text = [ PorterStemmer().stem(w) for w in word_tokens if w not in self.stop_words ] self.file_dictionaries.append(Counter(cleaned_text)) self.bag_of_words = self.bag_of_words.union(set(cleaned_text)) i += 1
class TestRemoveEmphasis(unittest.TestCase): def setUp(self): self.cleaner = Cleaner() def test_remove_emphasis_bold(self): text = "'''游戏工具编程'''是指采用各种开发工具进行开发修改[[电脑]]、[[电视]][[游戏]]的过程。主要的开发工具有以下几大类" expected = '游戏工具编程是指采用各种开发工具进行开发修改[[电脑]]、[[电视]][[游戏]]的过程。主要的开发工具有以下几大类' actual = self.cleaner._remove_emphasises(text) self.assertEqual(expected, actual) def test_remove_emphasis_italic(self): text = "'''臺灣藍鵲'''([[學名]]:''{{lang|la|Urocissa caerulea}}''),又稱'''臺灣暗藍鵲'''、'''紅嘴山鵲'''、" \ "'''長尾山娘'''([[臺灣閩南語羅馬字拼音方案|閩南語]]:{{Unicode|Tn̂g-bué Suann-niû}})或'''長尾陣仔''',為臺" \ "灣特有種鳥類。臺灣從[[臺灣清治時期|清領時期]]開始就有文獻紀載臺灣藍鵲的資料。1862年,鳥畫家[[约翰·古尔德]]根據英" \ "國博物學家[[郇和]]寄來的臺灣鳥類標本發表了一篇文章,命名並詳述16種新發現的台灣品種,其中就包含臺灣藍鵲。" expected = '臺灣藍鵲([[學名]]:{{lang|la|Urocissa caerulea}}),又稱臺灣暗藍鵲、紅嘴山鵲、長尾山娘([[臺灣閩南語羅馬' \ '字拼音方案|閩南語]]:{{Unicode|Tn̂g-bué Suann-niû}})或長尾陣仔,為臺灣特有種鳥類。臺灣從[[臺灣清治時期|清' \ '領時期]]開始就有文獻紀載臺灣藍鵲的資料。1862年,鳥畫家[[约翰·古尔德]]根據英國博物學家[[郇和]]寄來的臺灣鳥類' \ '標本發表了一篇文章,命名並詳述16種新發現的台灣品種,其中就包含臺灣藍鵲。' actual = self.cleaner._remove_emphasises(text) self.assertEqual(expected, actual)
class TestRemoveNewlines(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_newlines(self): text = "{{quote|一個民族是一個由歷史所造成的、穩定的人類社群。它是以共同語言、地域、經濟生活、以及表現於一個共同文化的心理" \ "機制為基礎的。|Stalin 1994, 20 <sup>3</sup>}}\n\n有些學者則否認這些客觀特質可以被用來當作定義民族" \ "的[[充分條件]],甚至是[[必要條件]](e.g., Canovan 1996; Gellner 1983; Hobsbawm 1992; Renan 1994)。" expected = "{{quote|一個民族是一個由歷史所造成的、穩定的人類社群。它是以共同語言、地域、經濟生活、以及表現於一個共同文化的" \ "心理機制為基礎的。|Stalin 1994, 20 <sup>3</sup>}}\n有些學者則否認這些客觀特質可以被用來當作定" \ "義民族的[[充分條件]],甚至是[[必要條件]](e.g., Canovan 1996; Gellner 1983; Hobsbawm 1992; Renan 1994)。" actual = self.cleaner._remove_continuous_newlines(text) self.assertEqual(expected, actual)
def load_files(self, dictionary_size=20000): cleaner = Cleaner() i = 0 for title, text in iterate( 'wiki/simplewiki-20191120-pages-articles.xml'): if i >= self.files_number: break cleaned_text = cleaner.clean_text(text)[:self.characters_per_file] cleaned_fragment, _ = cleaner.build_links(text) self.texts.append(title) word_tokens = self.pattern.sub(' ', cleaned_text.lower()).split(' ') cleaned_text = [ PorterStemmer().stem(w) for w in word_tokens if w not in self.stop_words ] self.file_dictionaries.append(Counter(cleaned_text)) self.bag_of_words = self.bag_of_words.union(set(cleaned_text)) i += 1 self.dictionary = {w: 0 for w in self.bag_of_words} for file in self.file_dictionaries: for word in self.bag_of_words: if word in file.keys(): self.dictionary[word] += 1 if len(self.dictionary) > dictionary_size: self.dictionary = Counter( self.dictionary).most_common(dictionary_size) self.bag_of_words = [] for (word, num) in self.dictionary: self.bag_of_words.append(word) self.nw_vector.append(num) else: self.bag_of_words = list(self.dictionary.keys()) self.nw_vector = list(self.dictionary.values())
class TestRemoveComments(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_comments_normal(self): text = "[[面包]]是德国饮食的重要组成部分。德国出产近600种面包和1,200种糕点和[[圆面包]]。德国[[奶酪]]的生产数量占到全欧" \ "洲的近三分之一{{refTag|name=IG|1=[https://books.google.com/books?id=sjW9adVFS2kC&pg=PA113 The " \ "Complete Idiot's Guide to Cheeses of the World - Steve Ehlers, Jeanette Hurt<!-- Bot generated " \ "title -->]. pp. 113-115.}}。2012年,超过99%在德国生产的肉类为猪肉、鸡肉和牛肉。香肠在德国极为普遍,生产种类" \ "近1,500种,包括[[德国油煎香肠|油煎香肠]]、[[巴伐利亚白香肠|白香肠]]和[[德國咖哩香腸|咖喱香肠]]等" expected = "[[面包]]是德国饮食的重要组成部分。德国出产近600种面包和1,200种糕点和[[圆面包]]。德国[[奶酪]]的生产数量占到" \ "全欧洲的近三分之一{{refTag|name=IG|1=[https://books.google.com/books?id=sjW9adVFS2kC&pg=PA113" \ " The Complete Idiot's Guide to Cheeses of the World - Steve Ehlers, Jeanette Hurt]. pp. " \ "113-115.}}。2012年,超过99%在德国生产的肉类为猪肉、鸡肉和牛肉。香肠在德国极为普遍,生产种类近1,500种," \ "包括[[德国油煎香肠|油煎香肠]]、[[巴伐利亚白香肠|白香肠]]和[[德國咖哩香腸|咖喱香肠]]等" actual = self.cleaner._remove_comments(text) self.assertEqual(expected, actual)
class TestRemoveLangs(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_remove_langs_normal(self): text = "[[印欧语系|西方语言]]中“數學”({{lang-el|μαθηματικά}})一詞源自於[[古希臘語]]的{{lang|el|μάθημα}}({" \ "{lang|la|máthēma}}),其有“學習”、“學問”、“[[科學]]”,以及另外還有個較狹義且技術性的意思-「數學研究」," \ "即使在其語源內。其形容詞{{lang|el|μαθηματικός}}({{lang|la|mathēmatikós}}),意思為''和學習有關的''或" \ "''用功的'',亦會被用來指''數學的''。其在[[英语]]中表面上的複數形式,及在[[法语]]中的表面複數形式''{{lang|f" \ "r|les mathématiques}}'',可溯至[[拉丁文]]的中性複數''{{lang|la|mathematica}}'',由[[西塞罗]]譯自希臘" \ "文複數{{lang|el|τα μαθηματικά}}({{lang|la|ta mathēmatiká}}),此一希臘語被[[亚里士多德]]拿來指「[[萬" \ "物皆數]]」的概念。" expected = "[[印欧语系|西方语言]]中“數學”(μαθηματικά)一詞源自於[[古希臘語]]的μάθημα(máthēma),其" \ "有“學習”、“學問”、“[[科學]]”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μα" \ "θηματικός(mathēmatikós),意思為''和學習有關的''或''用功的'',亦會被用來指''數學的''。其在[[英语]]中" \ "表面上的複數形式,及在[[法语]]中的表面複數形式''les mathématiques'',可溯至[[拉丁文]]的中性複數''mathe" \ "matica'',由[[西塞罗]]譯自希臘文複數τα μαθηματικά(ta mathēmatiká),此一希臘語被[[亚里士多德]]拿來指" \ "「[[萬物皆數]]」的概念。" actual = self.cleaner._remove_langs(text) self.assertEqual(expected, actual)
class TestCleanText(unittest.TestCase): def setUp(self): self.maxDiff = None self.cleaner = Cleaner() def test_case_1(self): text = "[[印欧语系|西方语言]]中“數學”({{lang-el|μαθηματικά}})一詞源自於[[古希臘語]]的{{lang|el|μάθημα}}({" \ "{lang|la|máthēma}}),其有“學習”、“學問”、“[[科學]]”,以及另外還有個較狹義且技術性的意思-「數學研究」," \ "即使在其語源內。其形容詞{{lang|el|μαθηματικός}}({{lang|la|mathēmatikós}}),意思為''和學習有關的''或" \ "''用功的'',亦會被用來指''數學的''。其在[[英语]]中表面上的複數形式,及在[[法语]]中的表面複數形式''{{lang|f" \ "r|les mathématiques}}'',可溯至[[拉丁文]]的中性複數''{{lang|la|mathematica}}'',由[[西塞罗]]譯自希臘" \ "文複數{{lang|el|τα μαθηματικά}}({{lang|la|ta mathēmatiká}}),此一希臘語被[[亚里士多德]]拿來指「[[萬" \ "物皆數]]」的概念。" expected = "西方语言中“數學”(μαθηματικά)一詞源自於古希臘語的μάθημα(máthēma),其有“學習”、“學問”、“科" \ "學”,以及另外還有個較狹義且技術性的意思-「數學研究」,即使在其語源內。其形容詞μαθηματικός(mathēmatikós)," \ "意思為和學習有關的或用功的,亦會被用來指數學的。其在英语中表面上的複數形式,及在法语中的表面複數" \ "形式les mathématiques,可溯至拉丁文的中性複數mathematica,由西塞罗譯自希臘文複數τα μαθηματικά(t" \ "a mathēmatiká),此一希臘語被亚里士多德拿來指「萬物皆數」的概念。" actual = self.cleaner.clean_text(text) actual, links = self.cleaner.build_links(actual) self.assertEqual(expected, actual) def test_case_3(self): text = "例如,[[全球資訊網]]是在[[歐洲核子研究組織]]由-{A|zh:[[蒂姆·伯纳斯-李]];zh-cn:[[蒂姆·伯纳斯-李]];zh-tw:[[提" \ "姆·柏納-李]];zh-hk:[[添·柏納-李]];}-創始與發展成功的,原先設計目标為向組織內部和全世界的物理學者提供資訊傳播服務。" \ "廣受歡迎的[[arXiv]]網站也是在類似狀況下創立的。" expected = "例如,全球資訊網是在歐洲核子研究組織由蒂姆·伯纳斯-李創始與發展成功的,原先設計目标為向組織內部和全世界的物理學" \ "者提供資訊傳播服務。廣受歡迎的arXiv網站也是在類似狀況下創立的。" actual = self.cleaner.clean_text(text) actual, links = self.cleaner.build_links(actual) self.assertEqual(expected, actual) def test_case_4(self): text = "亚里士多德死后,整个哲学界陷入了独立时期,称为{{link-en|希腊化哲学|Hellenistic_philosophy}}时期。因为整个社会" \ "和政治陷入混乱。这段时期产生了[[斯多葛学派]]和[[伊壁鸠鲁学派]],以及[[皮浪主义|怀疑主义派]]、[[新柏拉图主义|新柏" \ "拉图派]]和{{le|新毕达哥拉斯主义|Neopythagoreanism}}。这些学派的共同特点是伦理化。斯多葛学派主要是顺应自然和自制" \ "。伊壁鸠鲁学派则是把快乐作为生活的本质和善的标准。而新柏拉图派和新毕达哥拉斯派都是带有[[宗教]]主义的哲学,并逐渐产" \ "生融化[[基督教]]和希腊哲学于一体的理论,即为后来的[[基督教哲学]]。" expected = "亚里士多德死后,整个哲学界陷入了独立时期,称为希腊化哲学时期。因为整个社会和政治陷入混乱。这段时期产生了斯多葛学" \ "派和伊壁鸠鲁学派,以及怀疑主义派、新柏拉图派和新毕达哥拉斯主义。这些学派的共同特点是伦理化。斯多葛学派主要是顺应" \ "自然和自制。伊壁鸠鲁学派则是把快乐作为生活的本质和善的标准。而新柏拉图派和新毕达哥拉斯派都是带有宗教主义的哲学," \ "并逐渐产生融化基督教和希腊哲学于一体的理论,即为后来的基督教哲学。" actual = self.cleaner.clean_text(text) actual, links = self.cleaner.build_links(actual) self.assertEqual(expected, actual)
def setUp(self): self.cleaner = Cleaner()
def setUp(self): self.maxDiff = None self.cleaner = Cleaner() self.current_path = os.path.dirname(os.path.abspath(__file__)) self.sample_file_path = os.path.join(self.current_path, 'wikis', 'zhwiki-test-pages.xml')
from wiki_dump_reader import Cleaner, iterate import pickle from nltk.corpus import stopwords from nltk.stem import PorterStemmer from collections import Counter import re cleaner = Cleaner() files_number = 50002 i = 0 titles = [] bag_of_words = set() file_dictionaries = [] pattern = re.compile('[^a-z0-9]+') stop_words = set(stopwords.words('english')) for title, text in iterate('wiki/simplewiki-20191120-pages-articles.xml'): if i >= files_number: break titles.append(title) cleaned_text = cleaner.clean_text(text) # cleaned_fragment, _ = cleaner.build_links(cleaned_text) # f = open(f'wiki/files/{i}.txt', "w") # f.write(cleaned_fragment) # f.close() i += 1
from wiki_dump_reader import Cleaner, iterate from text_cleaner import Cleaner as MyCleaner import string, re, os, sys from tqdm import tqdm cleaner = Cleaner() my_cleaner = MyCleaner() lines = [] brk = 40000 print("Extracting text from xml ...") for title, text in tqdm(iterate('raw/wiki/rowiki-latest-pages-articles.xml')): #if brk<=0: # break #brk-=1 text = cleaner.clean_text(text) cleaned_text, links = cleaner.build_links(text) # get text lines.extend(cleaned_text.splitlines()) print("Cleaning extracted text ...") sys.stdout.flush() cleaned_lines, stats = my_cleaner.process(lines, min_line_length=30, disable_pbar=False) my_cleaner.print_stats(stats) print("Post-cleaning extracted text ...") forbidden_in = ["٭", "*", "†", "sp.", " f.", ".org", "oraș în", "localitate în", "comună în", "sat în", ".com", ".it", "o.o.", "px", ".jpg", ".gif", " n. ", ".bmp", "\\", "(n.", "\\left", "\\right", "(d.", " ", "::", "[[", "//", ", un ora", "este un municipiu", "este o comun", "este un ora", "{{", "Period", "from:", "till:", "BackgroundColors", "canvas:", "color:", "width:", "align:", "fontsize:", "pos:", "File", "##", "==", "image:", "ISBN", "\\over", "\\math", "style", "border", "background", "Wikipedia", "id:", "bar:", "ImageSize", "height:", "DateFormat", "text:", "orientation:", "format:", "position:", "columns:", "id:", "value:", "legend:", "ScaleMajor", "increment:", "ScaleMinor", "increment:", "REDIRECT"] forbidden_startswith = ["redirect", "Reședințe", "Locuri", "Sedii municipale", "Orașe", "Orase", "Actori", "Actri", "Localit", "Municipii", "Pagina", "List", "Secole", "Limbi", ":", "«",".",";","?","!","#"] + [x for x in string.punctuation] forbidden_endswith = ["Descoperă",")","}","?)","aici",".ro","-lea",";"]
# Dependencies # pip install wiki-dump-reader # pip install tqdm from wiki_dump_reader import Cleaner, iterate from tqdm import tqdm import re cleaner = Cleaner() output = open('bn_wiki.txt', 'w') for title, text in tqdm(iterate('bnwiki-latest-pages-articles.xml')): text = cleaner.clean_text(text) cleaned_text, _ = cleaner.build_links(text) cleaned_text = re.sub(r'[A-Za-z]', '', cleaned_text) # print(cleaned_text) output.write(cleaned_text + "\n") output.close()
def setUp(self): self.maxDiff = None self.cleaner = Cleaner()
def run(self): """Cleans the text gotten from wikipedia. Returns: True if the stage execution succeded, False otherwise. """ self.logger.info("Starting text cleaning...") input_file_path = join(constants.TMP_PATH, "{}.raw.txt".format(self.parent.topic)) output_file_path = join(constants.TMP_PATH, "{}.clean.txt".format(self.parent.topic)) cleaner = Cleaner() with open(input_file_path, "r") as file: text = file.read() text = re.sub(' ', '', text) self.logger.info( "Cleaning the markup and applying token-wise operations") lemmatizer = WordNetLemmatizer() articles = text.split("<<article_end>>") for i in range(len(articles)): article = articles[i] # Removing special tokens article = re.sub('<<article_start>>', '', article) # Removing wikipedia markup article = cleaner.clean_text(article) # Removing left out > article = re.sub(">", '', article) # Openning up [[...]] article = re.sub('\[{2}(.*?)(\|[\w\s\|]*)?\]{2}', '\\1', article) # Removing | article = re.sub('\|', ' ', article) tokens = word_tokenize(article) for j in range(len(tokens)): token = tokens[j] token = token.lower() token = token.encode("ascii", "ignore") token = token.decode() token = lemmatizer.lemmatize(token) tokens[j] = token article = " ".join(tokens) articles[i] = "<<article_start>> {} <<article_end>>".format( article) text = " ".join(articles) self.logger.info("Changing years to <<year>>") text = re.sub(' \d{4}(\-\d+|s)?', ' <<year>>', text) self.logger.info("Changing numbers to <<number>>") text = re.sub(' \d[\d\.,%]*(st|nd|rd|th| %)?', ' <<number>>', text) text = re.sub('<<number>>\-[\d\.,%]+', '<<number>>', text) self.logger.info("Section title formatting") text = re.sub('==+(.*?)==+', '<<section_title_start>> \\1 <<section_title_end>>', text) self.logger.info("Removing extra white-spaces") text = re.sub('\s\s+', ' ', text) with open(output_file_path, "w") as file: file.write(text) num_tokens = len(text.split(" ")) self.logger.info( "Saved the cleaned text. Contains ~ {} tokens".format( num_tokens)) return True