Search
Implementujte vlastní, co nejlepší filtr.
Testy ke kroku 6:
Rozmyslete si, jaké vnitřní mechanismy byste chtěli ve svém filtru použít, podle čeho by se váš filtr měl rozhodovat mezi korektním emailem a spamem a jak by se dal takový filtr učit z dat.
Projděte si také sekci s několika tipy, které by se vám při konstrukci filtru mohly hodit.
Na tomto místě bychom vám rádi poskytli pár užitečných tipů ke konstrukci vlastních filtrů. Zdaleka ne vše, co je v této sekci uvedeno, budete nutně potřebovat. Např. nepředpokládáme, že budete využívat modul email nebo regulární výrazy (i když samozřejmě můžete).
email
Rozhodnete-li se vytvořit filtr, který potřebuje v textu emailu identifikovat jednotlivá slova či jiné důležité fráze, budete nejspíš provádět tzv. tokenizaci textu (Tokenization). Prostudujte si operace s řetězci, které lze dělat. Zvlášť bychom vás chtěli upozornit na následující:
short_str in long_str
Uvedený výčet berte pouze jako upozornění na metody, které by vám mohly být užitečné. Jednoduchý tokenizer může vypadat např. takto:
shortphrase = """ Lorem ipsum dolor sit amet consectetuer Aliquam orci wisi pretium Praesent. Lorem pellentesque ac ipsum Aenean Sed pretium Pellentesque adipiscing enim at. Nisl tempus tempor interdum dictumst wisi consequat id at eu platea. Volutpat adipiscing Curabitur pede Aenean interdum Nulla congue nibh pharetra Maecenas. Convallis aliquam leo leo nisl mi cursus nisl enim Nam leo. Duis nunc nulla leo augue nunc pretium sit Aenean Nam. """ # Replace dots with spaces shortphrase = shortphrase.translate(str.maketrans('.',' ')) # Transform the letters to lowercase and cut the string into tokens. tokens = shortphrase.lower().split() print(tokens)
['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetuer', 'aliquam', 'orci', 'wisi', 'pretium', 'praesent', 'lorem', 'pellentesque', 'ac', 'ipsum', 'aenean', 'sed', 'pretium', 'pellentesque', 'adipiscing', 'enim', 'at', 'nisl', 'tempus', 'tempor', 'interdum', 'dictumst', 'wisi', 'consequat', 'id', 'at', 'eu', 'platea', 'volutpat', 'adipiscing', 'curabitur', 'pede', 'aenean', 'interdum', 'nulla', 'congue', 'nibh', 'pharetra', 'maecenas', 'convallis', 'aliquam', 'leo', 'leo', 'nisl', 'mi', 'cursus', 'nisl', 'enim', 'nam', 'leo', 'duis', 'nunc', 'nulla', 'leo', 'augue', 'nunc', 'pretium', 'sit', 'aenean', 'nam'] >>>
V minulých cvičeních jsme si ukazovali, jak udělat čítač výskytů písmen nebo slov z obyčejného slovníku. Protože se toto využití slovníku vyskytuje poměrně často, obsahuje Python třídu collections.Counter, která je odvozena od slovníku (má tedy všechny jeho metody), ale zároveň má upravené chování:
collections.Counter
counter['neexistující klíč']
KeyError
get()
Oproti obyčejnému slovníku má také pár užitečných metod navíc:
Counter
Budeme-li pokračovat v předchozím příkladu, následující řádky
counter = Counter(tokens) print(counter) print() print(counter.most_common(10))
Counter({'leo': 4, 'pretium': 3, 'aenean': 3, 'nisl': 3, 'at': 2, 'enim': 2, 'nunc': 2, 'interdum': 2, 'nam': 2, 'pellentesque': 2, 'lorem': 2, 'aliquam': 2, 'ipsum': 2, 'wisi': 2, 'sit': 2, 'adipiscing': 2, 'nulla': 2, 'pharetra': 1, 'ac': 1, 'pede': 1, 'duis': 1, 'sed': 1, 'eu': 1, 'id': 1, 'praesent': 1, 'volutpat': 1, 'platea': 1, 'convallis': 1, 'congue': 1, 'dolor': 1, 'tempus': 1, 'nibh': 1, 'consequat': 1, 'cursus': 1, 'curabitur': 1, 'maecenas': 1, 'amet': 1, 'dictumst': 1, 'mi': 1, 'augue': 1, 'tempor': 1, 'orci': 1, 'consectetuer': 1}) [('leo', 4), ('pretium', 3), ('aenean', 3), ('nisl', 3), ('at', 2), ('enim', 2), ('nunc', 2), ('interdum', 2), ('nam', 2), ('pellentesque', 2)]
Často chceme procházet prvky slovníku (čítače) uspořádané podle hodnoty četnosti. Python používá k řazení funkci sorted(). Zkusme, co udělají následující příkazy:
sorted()
counter2 = Counter(counter.most_common(5)) sorted(counter2)
[('aenean', 3), ('at', 2), ('leo', 4), ('nisl', 3), ('pretium', 3)]
My ale chceme seznam seřadit podle četnosti tokenu. Musíme funkci sorted() dát najevo, aby používala druhý prvek z dvojice jako primární klíč k řazení. To lze udělat např. pomocí tzv. lambda funkce. (V tuto chvíli to můžete prostě brát jako recept, kterak slovník řadit nikoli podle klíče, ale podle hodnoty). Navíc bychom jí měli sdělit, že chceme, aby řadila sestupně:
sorted(counter2, key=lambda pair: (pair[1],pair[0]), reverse=True)
[('leo', 4), ('pretium', 3), ('nisl', 3), ('aenean', 3), ('at', 2)]
Pro pokročilejší nebo zvídavější studenty uveďme, že Python umožňuje pracovat s regulárními výrazy. Ty umožňují velmi flexibilně popsat vzor v řetězci a následně najít všechny části řetězce, které danému vzoru odpovídají, příp. řetězec podle nich rozdělit, atd. Použití takového regulárního výrazu k jednoduché tokenizaci může vypadat např. takto:
import re pattern = r"""(?im)[a-zA-Z\$]+[\w\d\$\-']*""" compiledre = re.compile(pattern) tokens = compiledre.findall(message) counter = Counter(tokens)
Nechcete-li s emaily pracovat jen jako s nestrukturovaným řetězcem a raději byste jej nějakým způsobem rozebrali na části a ty pak zpracovávali zvlášť, odkazujeme vás na modul ''email'' a jeho funkce:
email.message_from_string()
email.message_from_file()
Message.walk()
Úkol:
K čemu nám to bude:
Inspirujte se u jednoduchých filtrů z kroku 4. Vnitřní mechanismy vašeho spam filtru jsou zcela na vás.
Abychom mohli váš filtr úspěšně volat v testovacím skriptu, musí splňovat tyto specifikace.