Last active
April 16, 2020 12:50
-
-
Save sorrat/64988f37e3c95bc6c019177c6f1453a6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Описание задачи: | |
На входе внешний файл html - там длинный текст. | |
Нужно показать список уникальных слов в этом тексте. | |
Так как слов много, то показываем только первые N по частоте встречаемости. | |
Нужно убрать html-теги и слова / словосочетания из стоп-списка (пример: а, как бы, да ну). | |
Имена формата "А. С. Пушкин" считаются одним словом. | |
Внешний файл html может быть любым. | |
""" | |
import re | |
import html | |
import argparse | |
from collections import Counter | |
from pprint import pprint | |
def read_file(path): | |
with open(path) as f: | |
return f.read() | |
def read_blacklist(path): | |
lines = [] | |
with open(path) as f: | |
for line in f: | |
line = line.strip() | |
if line: | |
lines.append(line) | |
return lines | |
def extract_article(html_text): | |
""" | |
Возвращается текст из тега 'body' без html-тегов. | |
Теги script, style и их содержимое исключаются полностью. | |
Остальные теги удаляются с сохранением содержания. | |
""" | |
body = re.findall(r'<body[^\>]*>(.*)<\/body>', html_text, flags=re.DOTALL | re.I)[0] | |
body = re.sub(r'<script.*?/script>', ' ', body, flags=re.DOTALL) | |
body = re.sub(r'<style.*?/style>', ' ', body, flags=re.DOTALL) | |
body = re.sub(r'<.*?>', ' ', body, flags=re.DOTALL) | |
return html.unescape(body) | |
def clean_article(text, blacklist): | |
""" | |
Очистка текста. | |
Удаление слов из стоп-списка. | |
""" | |
blacklist_pattern = r'(%s)' % '|'.join(blacklist) | |
return re.sub(blacklist_pattern, '', text, flags=re.I) | |
def extract_words(text): | |
""" | |
Разделение текста на отдельные слова. | |
""" | |
word_pattern = r'(?:\A|(?<=\s))(?:\b[^\W\d_]\.\s*?){0,2}\b[^\W\d_]\S*\b' | |
matches = re.finditer(word_pattern, text) | |
for m in matches: | |
yield m.group(0) | |
def normalize_words(words): | |
"""Приведение слов к единой форме""" | |
for w in words: | |
yield w.lower() | |
def count_words(html_path, blacklist_path): | |
blacklist = read_blacklist(blacklist_path) | |
html_text = read_file(html_path) | |
text = extract_article(html_text) | |
text = clean_article(text, blacklist) | |
words = extract_words(text) | |
words = normalize_words(words) | |
return Counter(words) | |
def cmdline_args(): | |
parser = argparse.ArgumentParser(description='Счётчик слов') | |
parser.add_argument('--number', '-n', | |
type=int, | |
required=True) | |
parser.add_argument('--html-path', '-f', | |
help='Файл с текстом', | |
required=True) | |
parser.add_argument('--blacklist-path', '-b', | |
help='Файл со списком стоп-словосочетаний') | |
return parser.parse_args() | |
if __name__ == '__main__': | |
args = cmdline_args() | |
counts = count_words( | |
args.html_path, | |
args.blacklist_path, | |
) | |
most_freq = counts.most_common(args.number) | |
pprint(most_freq) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment