Всіх вітаю! У цій статті ми розберемо бібліотеку confusables та її функціонал. Також ми розглянемо, що таке омогліфи та як їх використовують.
Встановлення
Спершу варто встановити бібліотеку confusables.
Windows:
pip install confusablesMacOS:
pip3 install confusablesLinux:
pip install confusablesЩо таке омогліфи?
Омогліфи — це символи, які візуально дуже схожі на звичайні латинські, але насправді вони різні й мають різні Unicode-коди.
Бібліотека confusables дозволяє легко обробляти ці символи у коді, щоб розпізнати їх у рядках.
Чому ж ми намагаємося уникнути використання омогліфів? Справа у тому, що вони зазвичай використовуються, наприклад, для фішингу, бо інколи зловмисники замінюють деякі латинські символи у домені сайту, наприклад, на кириличні, тим самим створюючи новий, але схожий фальшивий домен.
Таким чином, користувач може думати, що перейшов на сайт відомої компанії, наприклад, Intel, але насправді один із символів не є латинським, а отже, це зовсім інший сайт.
Функціонал бібліотеки
Функція is_confusable()
Ця функція приймає у якості параметрів два рядки, де перший — написаний звичайними латинськими символами, а другий — омогліфами, схожими на латинські символи. Дана функція визначає, чи є ці два рядки такими, які потенційно можна зплутати між собою.
Ось приклад коду:
from confusables import is_confusable
original_string = "above"
similar_string = "аbovе"
strings_compare = is_confusable(original_string, similar_string)
print(strings_compare)Результат:
TrueВарто зазначити, що similar_string відрізняється від original_string тим, що у ній латинські символи a та e замінені на кириличні а та е, але це неможливо помітити без застосування якихось спеціальних інструментів.
Функція confusable_characters()
Ця функція приймає звичайний символ як параметр та повертає список усіх символів, схожих на нього, з якими його потенційно можна зплутати.
Пропоную поглянути на вміст списку символів, які схожі на латинський символ n:
from confusables import confusable_characters
confusable_list = confusable_characters("n")
print(confusable_list)Результат:
['𝑁', '𝚗', 'N', 'n', 'n', '𝙉', 'ν', '𝖭', '𝛮', 'Ṉ', 'ո', '𝓃', '𝒩', 'ň', 'ռ', 'ń', 'ṋ', 'ṇ', '𝗻', 'Ṇ', 'ǹ', 'ℕ', 'ɲ', '𝙣', '𝕹', 'ṅ', 'ṉ', 'በ', '𝘕', '𝓷', '𝙽', 'Ǹ', '𝚴', 'Ṅ', 'Ո', 'Ṋ', '𝐧', '𝘯', '𝗇', '∩', 'ᑎ', '𝝢', '𝜨', '𝒏', '𝞜', 'ⲛ', 'ñ', '𝐍', '𝕟', 'Ñ', 'ņ', 'Ⲛ', 'N', '𝓝', 'Ń', '𝖓', '𝉅', '𝔫', 'ቡ', '𝑛', 'ꓠ', 'Ν', 'Ň', '𝑵', 'Ņ', '𐔓', 'Ռ', 'ꓵ', '𝗡', 'Ɲ', '𝔑', '⋂']Тепер спробуємо використати цю функцію у більш цікавому прикладі:
from confusables import confusable_characters
char_list = confusable_characters("n")
word = "𝒩ame"
for i in char_list:
if i in word:
print(f"There's '{i}' in {word}")Результат:
There's '𝒩' in 𝒩ameТут ми створили список, що містить символи, схожі на символ n, який назвали char_list, та визначали, чи є у рядку змінної word якийсь із символів з нашого списку.
Як бачимо, наша програма визначила, що рядок у змінній word містить символ, який був у списку char_list.
Функція confusable_regex()
Дана функція приймає обов'язковий параметр у вигляді слова, яке ми хочемо знайти, та опціональний параметр include_character_padding, який визначає, чи потрібно звертати увагу на символи, такі як зірка, крапка, нижнє підкреслення та ін.
Далі функція автоматично створює регулярний вираз, який буде шукати у рядку задане слово та ігнорувати (чи ні) ті символи, які ми вже перерахували.
Приклад коду без опціонального параметра:
from confusables import confusable_regex
import re
sample_text = "A real treasure is only at the botto𝜧 of the eye"
word = "bottom"
generated_regex = confusable_regex(word)
compiled_regex = re.compile(generated_regex)
if compiled_regex.search(sample_text):
print(f"Found the variation of '{word}'")Тут нам потрібно було використати модуль re для роботи з регулярними виразами, бо за замовчуванням функція confusable_regex() створює регулярний вираз у текстовому форматі, а щоб використовувати його саме як справжній регулярний вираз, нам необхідно передати змінну generated_regex у функцію compile().
У кінці ми застосовуємо функцію search() з модуля re, щоб використати наш регулярний вираз та відшукати потрібне значення.
Варто зазначити, що створений регулярний вираз спокійно знайде задане слово, як би ми не намагалися його візуально змінити.
Функція normalize()
Ця функція приймає візуально видозмінене сторонніми символами слово та повертає усі варіанти того, як може виглядати це слово з використанням звичайних символів.
Ось приклад:
from confusables import normalize
word = "𝔅O𝝩𝝩Om"
normal_variants = normalize(word)
print(normal_variants)Результат:
['b0tt0m', "b0tto'm", 'b0ttom', "bo'tt0m", "bo'tto'm", "bo'ttom", 'bott0m', "botto'm", 'bottom']Як бачимо, тут ми маємо вже звичайні символи замість тих, що використовуються у слові "𝔅O𝝩𝝩Om".
Але нам треба використати лише латинські символи при пошуку нормальної форми слова, а тому є сенс встановити опціональний параметр prioritize_alpha у значення True, що автоматично дає функції зрозуміти, що ми шукаємо варіант з використанням лише латинських символів.
Ось ще один приклад:
from confusables import normalize
word = "𝔅O𝝩𝝩Om"
normal_variants = normalize(word, prioritize_alpha=True)
print(normal_variants)Результат:
['bottom']Отже, отримали відповідний результат.
Висновок
У даній статті ми з'ясували, що таке омогліфи та чому їх використовують і як працювати з ними за допомогою бібліотеки confusables.