program_efremova.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. from pathlib import Path
  2. import json
  3. import re
  4. import requests
  5. import time
  6. import os
  7. dictionary_filename = 'efremova.txt'
  8. dictionary_forms_filename = 'odict.csv'
  9. json_filename = 'data.json'
  10. def if_exist_dictionary(func):
  11. def wrapper(*original_args, **original_kwargs):
  12. file = Path(dictionary_filename)
  13. if not file.is_file():
  14. print('Файл {} не существует. Программа не может быть выполнена'.format(dictionary_filename))
  15. return
  16. func(*original_args, **original_kwargs)
  17. return wrapper
  18. def if_exist_json(func):
  19. def wrapper(*original_args, **original_kwargs):
  20. file = Path(json_filename)
  21. if not file.is_file():
  22. print('Файл {} не существует. Его нужно сгенерировать первоначально'.format(json_filename))
  23. return
  24. func(*original_args, **original_kwargs)
  25. return wrapper
  26. def if_exist_dictionary_forms(func):
  27. def wrapper(*original_args, **original_kwargs):
  28. file = Path(dictionary_forms_filename)
  29. if not file.is_file():
  30. print('Файл {} не существует. Функция не может быть выполнена'.format(dictionary_filename))
  31. return
  32. func(*original_args, **original_kwargs)
  33. return wrapper
  34. def function_execution_time(func):
  35. def wrapper(*original_args, **original_kwargs):
  36. start = time.time()
  37. func(*original_args, **original_kwargs)
  38. end = time.time()
  39. print('Время выполнения функции: {}\n'.format(time.strftime('%H:%M:%S', time.gmtime(end - start))))
  40. return wrapper
  41. def index_of(string, substring):
  42. try:
  43. index = string.index(substring)
  44. except ValueError:
  45. index = -1
  46. return index
  47. def save_json(dictionary):
  48. file = Path(json_filename)
  49. action = 'обновлен' if file.is_file() else 'создан'
  50. with open(json_filename, 'w', encoding='utf8') as outfile:
  51. json.dump(dictionary, outfile, ensure_ascii=False, indent=4)
  52. print('Файл {} {}'.format(json_filename, action))
  53. def read_json():
  54. file = Path(json_filename)
  55. with open(file, encoding='utf8') as f:
  56. dictionary = json.loads(f.read())
  57. print('Файл {} открыт'.format(json_filename))
  58. return dictionary
  59. @function_execution_time
  60. def remove_all_temporary_files():
  61. def remove(filename):
  62. if Path(json_filename).is_file():
  63. os.remove(json_filename)
  64. print('Файл {} удален'.format(json_filename))
  65. else:
  66. print('Файл {} не существует'.format(json_filename))
  67. remove(json_filename)
  68. print('Временных файлов больше нет')
  69. @function_execution_time
  70. @if_exist_dictionary
  71. def generated_json():
  72. file = Path(dictionary_filename)
  73. with open(file, encoding='utf8') as f:
  74. lines = f.read().splitlines()
  75. dictionary = {}
  76. for line in lines:
  77. word = line.split(' ', 1)[0]
  78. definition = line.split(' ', 1)[1]
  79. if not bool(re.match(r'(ж|м|ср|мн)\.(.*)$', definition) or re.match(r'(1\.|I) (ж|м|ср|мн)\.(.*)$', definition)):
  80. continue
  81. dictionary[word] = {'definition': definition}
  82. if word[-2:] in ['ая', 'ее', 'ие', 'ий', 'ое', 'ой', 'ые', 'ый', 'ье', 'ьи', 'ья', 'яя']:
  83. dictionary[word]['answerIsProbablyNotNoun'] = 'null'
  84. if bool(re.match(r'(мн)\.(.*)$', definition) or re.match(r'(1\.|I) (мн)\.(.*)$', definition)):
  85. dictionary[word]['answerNeedToIncludePlural'] = 'null'
  86. save_json(dictionary)
  87. @function_execution_time
  88. @if_exist_json
  89. def statistics():
  90. dictionary = read_json()
  91. count = 0
  92. count_check = 0
  93. count_need_check = 0
  94. count_need_check_404 = 0
  95. count_need_check_noun = 0
  96. count_need_check_not_noun = 0
  97. count_plural_check = 0
  98. count_plural_need_check = 0
  99. count_plural_check_need_include = 0
  100. count_plural_check_include = 0
  101. count_plural_check_exclude = 0
  102. count_with_capital_letter = 0
  103. for word, entry in dictionary.items():
  104. count += 1
  105. if 'answerIsProbablyNotNoun' in entry:
  106. count_check += 1
  107. if entry['answerIsProbablyNotNoun'] == 'null':
  108. count_need_check += 1
  109. if entry['answerIsProbablyNotNoun'] not in ['null', 'noun', 'not noun']:
  110. count_need_check_404 += 1
  111. if entry['answerIsProbablyNotNoun'] == 'noun':
  112. count_need_check_noun += 1
  113. if entry['answerIsProbablyNotNoun'] == 'not noun':
  114. count_need_check_not_noun += 1
  115. if 'answerNeedToIncludePlural' in entry:
  116. count_plural_check += 1
  117. if entry['answerNeedToIncludePlural'] == 'null':
  118. count_plural_need_check += 1
  119. if entry['answerNeedToIncludePlural'] == 'include':
  120. count_plural_check_include += 1
  121. if entry['answerNeedToIncludePlural'] == 'need include':
  122. count_plural_check_need_include += 1
  123. if entry['answerNeedToIncludePlural'] == 'exclude':
  124. count_plural_check_exclude += 1
  125. if word != word.lower():
  126. count_with_capital_letter += 1
  127. print('Всего существительных по Ефремовой: {}'.format(count))
  128. print('Подозрительные (возможно не сущ.):')
  129. print('\tвсего: {}'.format(count_check))
  130. print('\tне проверенные на сайтах: {}'.format(count_need_check))
  131. print('\tпроверено: {}'.format(count_check - count_need_check))
  132. print('\tиз них с ошибкой 404 и др.: {}'.format(count_need_check_404))
  133. print('\tопределено как сущ.: {}'.format(count_need_check_noun))
  134. print('\tопределено как не сущ.: {}'.format(count_need_check_not_noun))
  135. print('Слова во множественном числе по Ефремовой:')
  136. print('\tвсего: {}'.format(count_plural_check))
  137. print('\tнужно проверить: {}'.format(count_plural_need_check))
  138. print('\tпроверено: {}'.format(count_plural_check - count_plural_need_check))
  139. print('\tрекомендуется включить: {}'.format(count_plural_check_need_include))
  140. print('\tвключаем: {}'.format(count_plural_check_include))
  141. print('\tисключаем: {}'.format(count_plural_check_exclude))
  142. print('Слова с большой буквы по Ефремовой:')
  143. print('\tвсего: {}'.format(count_with_capital_letter))
  144. @function_execution_time
  145. @if_exist_json
  146. def print_list_of_words(key, answer, invert=False):
  147. def print_word():
  148. print(word)
  149. print('{} = {}'.format(key, entry[key]))
  150. print('-------------------------')
  151. dictionary = read_json()
  152. count = 0
  153. for word, entry in dictionary.items():
  154. if key in entry:
  155. if not invert:
  156. if entry[key] in answer:
  157. print_word()
  158. count += 1
  159. else:
  160. if entry[key] not in answer:
  161. print_word()
  162. count += 1
  163. print('Слов: {}'.format(count))
  164. @if_exist_json
  165. def print_list_of_words_capital():
  166. dictionary = read_json()
  167. count = 0
  168. for word, entry in dictionary.items():
  169. if word != word.lower():
  170. print(word)
  171. count += 1
  172. print('Слов: {}'.format(count))
  173. def check_word_in_wiktionary(word, html):
  174. answer = None
  175. if 'title="существительное">Существительное</a>' in html:
  176. answer = 'noun'
  177. if 'Существительное.' in html:
  178. answer = 'noun'
  179. if 'title="выступает в роли существительного">субстантивир.</span>' in html:
  180. answer = 'noun'
  181. if 'Существительное' in html and 'Прилагательное' not in html:
  182. answer = 'noun'
  183. if 'Существительное, одушевлённое, тип склонения по ' in html:
  184. answer = 'noun'
  185. if 'title="прилагательное">Прилагательное</a>' in html:
  186. answer = 'not noun'
  187. if 'title="причастие">Причастие</a>' in html:
  188. answer = 'not noun'
  189. if 'title="причастие">причастие</a>' in html:
  190. answer = 'not noun'
  191. if 'title="наречие">Наречие</a>' in html:
  192. answer = 'not noun'
  193. if 'title="деепричастие">деепричастие</a>' in html:
  194. answer = 'not noun'
  195. if 'Существительное' not in html and 'Прилагательное' in html:
  196. answer = 'not noun'
  197. if 'Существительное' not in html and 'прилагательного' in html:
  198. answer = 'not noun'
  199. if 'Существительное' not in html and 'Местоименное прилагательное' in html:
  200. answer = 'not noun'
  201. if 'Существительное' not in html and 'Притяжательное местоимение' in html:
  202. answer = 'not noun'
  203. if 'Существительное' not in html and 'Притяжательное прилагательное' in html:
  204. answer = 'not noun'
  205. if 'Существительное' not in html and 'Числительное' in html:
  206. answer = 'not noun'
  207. if 'Существительное' not in html and 'Порядковое числительное' in html:
  208. answer = 'not noun'
  209. if 'Существительное' not in html and 'Местоимение' in html:
  210. answer = 'not noun'
  211. if 'Существительное' not in html and 'Указательное местоимение' in html:
  212. answer = 'not noun'
  213. return answer
  214. def check_word_in_academic(word, html):
  215. answer = None
  216. regexp = r'</a><\/strong> — сущ\.(.*?)<\/p>\n<p class="src">' \
  217. r'<a href="\/\/dic\.academic\.ru\/contents.nsf\/dic_synonims\/">Словарь синонимов<\/a><\/p>'
  218. if re.search(re.escape(word) + regexp, html, re.S):
  219. answer = 'noun'
  220. return answer
  221. def check_word_in_goldlit(word, html):
  222. answer = None
  223. if '<title>Морфологический разбор слова: {}</title>'.format(word) not in html:
  224. return '404'
  225. if '<strong>Часть речи</strong>: прилагательное<br />' in html:
  226. answer = 'not noun'
  227. if '<strong>Часть речи</strong>: местоимение-существительное<br />' in html:
  228. answer = 'not noun'
  229. if '<strong>Часть речи</strong>: числительное' in html:
  230. answer = 'not noun'
  231. if '<strong>Часть речи</strong>: наречие' in html:
  232. answer = 'not noun'
  233. if '<strong>Часть речи</strong>: деепричастие' in html:
  234. answer = 'not noun'
  235. if '<strong>Часть речи</strong>: причастие' in html:
  236. answer = 'not noun'
  237. if '<strong>Часть речи</strong>: порядковое числительное' in html:
  238. answer = 'not noun'
  239. if '<strong>Часть речи</strong>: существительное<br />' in html:
  240. answer = 'noun'
  241. return answer
  242. def check_word_in_morfologija(word, html):
  243. answer = None
  244. if '<b>Часть речи:</b> прилагательное' in html:
  245. answer = 'not noun'
  246. if '<b>Часть речи:</b> наречие' in html:
  247. answer = 'not noun'
  248. if '<b>Часть речи:</b> местоимение' in html:
  249. answer = 'not noun'
  250. if '<b>Часть речи:</b> наречие' in html:
  251. answer = 'not noun'
  252. if '<b>Часть речи:</b> деепричастие' in html:
  253. answer = 'not noun'
  254. if '<b>Часть речи:</b> поряд. числительное' in html:
  255. answer = 'not noun'
  256. if '<b>Часть речи:</b> местоим. прил.' in html:
  257. answer = 'not noun'
  258. if '<b>Часть речи:</b> существительное' in html:
  259. answer = 'noun'
  260. return answer
  261. def check_word_in_site(word, url, function_check_html):
  262. answer = None
  263. response = requests.get(url + word.lower())
  264. if response.status_code == 200:
  265. answer_from_html = function_check_html(word, response.text)
  266. if answer_from_html is not None:
  267. answer = answer_from_html
  268. else:
  269. answer = str(response.status_code)
  270. print('word = {}'.format(word))
  271. print('answer = {}'.format(answer))
  272. print('-------------------------')
  273. return answer
  274. @function_execution_time
  275. @if_exist_json
  276. def check_words_on_site(url, function_check_html):
  277. dictionary = read_json()
  278. i = 0
  279. for word, entry in dictionary.items():
  280. if 'answerIsProbablyNotNoun' in entry and entry['answerIsProbablyNotNoun'] not in ['noun', 'not noun']:
  281. try:
  282. answer = check_word_in_site(word, url, function_check_html)
  283. except requests.exceptions.ConnectionError:
  284. print("Ошибка: ConnectionError")
  285. time.sleep(1)
  286. save_json(dictionary)
  287. except requests.exceptions.Timeout:
  288. print("Ошибка: Timeout")
  289. time.sleep(10)
  290. save_json(dictionary)
  291. if answer is not None:
  292. dictionary[word]['answerIsProbablyNotNoun'] = answer
  293. i += 1
  294. if i % 100 == 0:
  295. save_json(dictionary)
  296. save_json(dictionary)
  297. print('Проверка слов на {} завершена'.format(url))
  298. def check_plural_word_in_wiktionary(word, html):
  299. answer = None
  300. if '<title>{} — Викисловарь</title>'.format(word) in html:
  301. answer = 'need include'
  302. if 'формы ед. ч. не используются' in html:
  303. answer = 'include'
  304. else:
  305. if '— Викисловарь</title>'.format(word) in html:
  306. answer = 'exclude'
  307. return answer
  308. def check_plural_word_in_goldlit(word, html):
  309. answer = None
  310. if '<strong>Начальная форма</strong>: {}'.format(word.upper()) in html:
  311. answer = 'include'
  312. return answer
  313. def check_plural_in_academic(word, html):
  314. answer = None
  315. regexp = r'</a><\/strong> — сущ\.(.*?)<\/p>\n<p class="src">' \
  316. r'<a href="\/\/dic\.academic\.ru\/contents.nsf\/dic_synonims\/">Словарь синонимов<\/a><\/p>'
  317. if re.search(re.escape(word) + regexp, html, re.S):
  318. answer = 'include'
  319. return answer
  320. @function_execution_time
  321. @if_exist_json
  322. def check_plural_words_on_site(url, function_check_html):
  323. dictionary = read_json()
  324. i = 0
  325. for word, entry in dictionary.items():
  326. if 'answerNeedToIncludePlural' in entry and entry['answerNeedToIncludePlural'] not in ['exclude']:
  327. try:
  328. answer = check_word_in_site(word, url, function_check_html)
  329. except requests.exceptions.ConnectionError:
  330. print("Ошибка: ConnectionError")
  331. time.sleep(1)
  332. save_json(dictionary)
  333. except requests.exceptions.Timeout:
  334. print("Ошибка: Timeout")
  335. time.sleep(10)
  336. save_json(dictionary)
  337. if answer in ['need include','include', 'exclude']:
  338. dictionary[word]['answerNeedToIncludePlural'] = answer
  339. i += 1
  340. if i % 100 == 0:
  341. save_json(dictionary)
  342. save_json(dictionary)
  343. print('Проверка слов на {} завершена'.format(url))
  344. @function_execution_time
  345. @if_exist_json
  346. def define_words_as_nouns():
  347. dictionary = read_json()
  348. for word, entry in dictionary.items():
  349. if 'answerIsProbablyNotNoun' in entry and entry['answerIsProbablyNotNoun'] not in ['noun', 'not noun']:
  350. dictionary[word]['answerIsProbablyNotNoun'] = 'noun'
  351. save_json(dictionary)
  352. print('Все оставшиеся слова определены как сущестуительные')
  353. statistics()
  354. @function_execution_time
  355. @if_exist_json
  356. @if_exist_dictionary_forms
  357. def check_words_in_plural():
  358. file = Path(dictionary_forms_filename)
  359. with open(file) as f:
  360. dictionary_forms = f.read().splitlines()
  361. print('Файл {} открыт'.format(dictionary_forms_filename))
  362. dictionary = read_json()
  363. for word, entry in dictionary.items():
  364. if 'answerNeedToIncludePlural' in entry and entry['answerNeedToIncludePlural'] not in ['include', 'exclude']:
  365. is_initial_form = False
  366. is_as_form = False
  367. index_initial_form = -1
  368. index_as_form = -1
  369. for index, line in enumerate(dictionary_forms):
  370. if index_of(line, word + ',') == 0:
  371. is_initial_form = True
  372. if index_initial_form == -1:
  373. index_initial_form = index
  374. if index_of(line, ',' + word + ',') >= 0:
  375. is_as_form = True
  376. if index_initial_form != -1 and index_as_form == index_initial_form:
  377. index_as_form = index
  378. if index_as_form == -1:
  379. index_as_form = index
  380. if line.endswith(',' + word):
  381. is_as_form = True
  382. if index_initial_form != -1 and index_as_form == index_initial_form:
  383. index_as_form = index
  384. if index_as_form == -1:
  385. index_as_form = index
  386. answer = None
  387. if is_initial_form:
  388. answer = 'need include'
  389. if not is_initial_form and is_as_form:
  390. answer = 'exclude'
  391. if is_initial_form and is_as_form and index_as_form != index_initial_form:
  392. answer = 'exclude'
  393. print(word)
  394. if answer is not None:
  395. print('answer = {}'.format(answer))
  396. dictionary[word]['answerNeedToIncludePlural'] = answer
  397. print('-------------------------')
  398. save_json(dictionary)
  399. print('Проверка слов во множественном числе завершена')
  400. statistics()
  401. @if_exist_dictionary
  402. def main():
  403. menu = [
  404. {'text': 'Очистить временные файлы', 'function': remove_all_temporary_files},
  405. {'text': 'Сгенерировать файл {}'.format(json_filename), 'function': generated_json},
  406. {'text': 'Статистика', 'function': statistics},
  407. {'text': 'Список непроверенных подозрительных слов', 'function': print_list_of_words,
  408. 'params': {'key': 'answerIsProbablyNotNoun', 'answer': ['null']}},
  409. {'text': 'Список проверенных подозрительных слов с ошибкой 404 и др.', 'function': print_list_of_words,
  410. 'params': {'key': 'answerIsProbablyNotNoun', 'answer': ['null', 'noun', 'not noun'], 'invert': True}},
  411. {'text': 'Список непроверенных слов во мн. числе', 'function': print_list_of_words,
  412. 'params': {'key': 'answerNeedToIncludePlural', 'answer': ['null']}},
  413. {'text': 'Список рекомендуемых к включению слов во мн. числе', 'function': print_list_of_words,
  414. 'params': {'key': 'answerNeedToIncludePlural', 'answer': ['need include']}},
  415. {'text': 'Список включаемых проверенных слов во мн. числе', 'function': print_list_of_words,
  416. 'params': {'key': 'answerNeedToIncludePlural', 'answer': ['include']}},
  417. {'text': 'Список невключаемых проверенных слов во мн. числе', 'function': print_list_of_words,
  418. 'params': {'key': 'answerNeedToIncludePlural', 'answer': ['exclude']}},
  419. {'text': 'Список слов с большой буквы', 'function': print_list_of_words_capital},
  420. {'text': 'Проверить подозрительные слова на wiktionary.org', 'function': check_words_on_site,
  421. 'params': {'url': 'https://ru.wiktionary.org/wiki/', 'function_check_html': check_word_in_wiktionary}},
  422. {'text': 'Проверить подозрительные слова на dic.academic.ru', 'function': check_words_on_site,
  423. 'params': {'url': 'https://dic.academic.ru/searchall.php?SWord=',
  424. 'function_check_html': check_word_in_academic}},
  425. {'text': 'Проверить подозрительные слова на goldlit.ru', 'function': check_words_on_site,
  426. 'params': {'url': 'https://goldlit.ru/component/slog?words=', 'function_check_html': check_word_in_goldlit}},
  427. {'text': 'Проверить подозрительные слова на morfologija.ru', 'function': check_words_on_site,
  428. 'params': {'url': 'http://www.morfologija.ru/словоформа/', 'function_check_html': check_word_in_morfologija}},
  429. {'text': 'Оставшиеся непроверенные слова определить как существительные', 'function': define_words_as_nouns},
  430. {'text': 'Проверить слова во мн. числе', 'function': check_words_in_plural},
  431. {'text': 'Проверить слова во мн. числе на wiktionary.org', 'function': check_plural_words_on_site,
  432. 'params': {'url': 'https://ru.wiktionary.org/wiki/', 'function_check_html': check_plural_word_in_wiktionary}},
  433. {'text': 'Проверить слова во мн. числе на dic.academic.ru', 'function': check_plural_words_on_site,
  434. 'params': {'url': 'https://dic.academic.ru/searchall.php?SWord=',
  435. 'function_check_html': check_plural_in_academic}},
  436. {'text': 'Проверить слова во мн. числе на goldlit.ru', 'function': check_plural_words_on_site,
  437. 'params': {'url': 'https://goldlit.ru/component/slog?words=', 'function_check_html': check_plural_word_in_goldlit}},
  438. ]
  439. while True:
  440. for index, item in enumerate(menu):
  441. print('{} - {}'.format(index + 1, item['text']))
  442. try:
  443. command = int(input('Введите номер команды (нажмите Enter для выхода): '))
  444. except ValueError:
  445. break
  446. if command > len(menu) or command < 0:
  447. break
  448. if 'params' not in menu[command - 1]:
  449. menu[command - 1]['function']()
  450. else:
  451. menu[command - 1]['function'](**menu[command - 1]['params'])
  452. input("Нажмите Enter для продолжения...")
  453. def test():
  454. check_word_in_site('стуаввввввлья', 'https://goldlit.ru/component/slog?words=', check_plural_word_in_goldlit)
  455. if __name__ == '__main__':
  456. main()