DanLevy.net

Regex: от нуля до профи

Извлечение и парсинг URL-подобных строк одним регулярным выражением

Содержание

TL;DR: Переходите сразу к регулярному выражению на 120+ байт.

🚀 Введение

Извлечение URL из неструктурированного текста иногда напоминает утомительную игру в «сбей крота». Знаки препинания, скобки и неоднозначное форматирование только усложняют задачу. Независимо от того, пишете ли вы веб-скрапер, анализатор данных или чат-приложение, точное извлечение URL — критически важная задача.

В этом материале мы подойдём к задаче напрямую, используя гибкий двухэтапный подход. Наша цель — сначала захватить все потенциальные строки, выглядящие как URL, а последующей валидацией заняться отдельно.

💡 Примечание: Этот паттерн не предназначен для валидации URL! Он намеренно допускает лишнюю пунктуацию и опечатки.

🔍 Цель: Извлечение URL из текста

При извлечении URL из исходного текста двухэтапный подход работает надёжнее:

  1. Захватить всё, что выглядит как URL: Закинуть широкую сеть и отловить все строки, которые могут оказаться URL. Именно здесь вступает в игру наше регулярное выражение на 120+ байт.
  2. Валидация: После отлова кандидатов примените вторичные проверки (например, разрешение DNS или сверку с известными доменами), чтобы отсечь ложные срабатывания.

Визуализация проблемы

Термины extract и parse часто используют как синонимы, хотя они описывают разные процессы. Извлечение (extract) — это поиск и захват строк, которые могут оказаться URL, из большего объёма текста. Разбор (parse), в свою очередь, предполагает декомпозицию этих URL на составные части.

Под «разбором» или «частями URL» я подразумеваю следующие компоненты:

5 компонентов любого URL
URL anatomy, visualized

Нажмите, чтобы увидеть скриншот подстрокового совпадения в RegEx101.

Прежде чем углубляться в синтаксис регулярных выражений, используем визуальный инструмент, чтобы оценить, как наш шаблон захватывает множество совпадений:

Используем RegEx101.com для визуализации многострочных совпадений
Preview 'bulk' multi-line matches

Регулярное выражение весом 120+ байт

Ниже приведено компактное регулярное выражение, предназначенное для извлечения и разбора URL за один проход. Оно поддерживает различные протоколы, домены, пути, а также необязательные секции query и fragment.

Не переживайте — разберём всё по шагам!

Регулярное выражение для URL весом 120+ байт
const urlRegex = /([-.a-z0-9]+:\/{1,3})([^-\/\.[\](|)\s?][^`\/\s\]?]+)([-_a-z0-9!@$%^&*()=+;/~\.]*)[?]?([^#\s`?]*)[#]?([^#\s'"`\.,!]*)/gi;
// Совместимость: ES5+
// Тот же паттерн, разбитый по строкам для удобства чтения:
([-.a-z0-9]+:\/{1,3})
([^-\/\.[\](|)\s?][^`\/\s\]?]+)
([-_a-z0-9!@$%^&*()=+;/~\.]*)
[?]?([^#\s`?]*)
[#]?([^#\s'"`\.,!]*)
Делитесь самыми безумными регулярными выражениями, с которыми вы сталкивались (или писали сами), в комментариях ниже! 🚀

🧩 Пошаговый разбор

Разберём регулярное выражение на компоненты, чтобы понять, как оно работает:

1. Протокол (Группа 1): ([-.a-z0-9]+:/{1,3})

2. Домен (Группа 2): ([^-/.[](|)s?][^`/s]?]+)

3. Путь (Группа 3): ([-_a-z0-9!@$%^&*()=+;/~\.]*)

4. Запрос (Группа 4): [?]?([^#\s`?]*)

5. Фрагмент (Группа 5): [#]?([^#\s’”`.,!]*)

🛠️ Пример парсинга

Вот как применить этот сложный regex на практике с помощью JavaScript:

☑️ Следующие шаги

В зависимости от конкретной задачи может потребоваться доработать это регулярное выражение или добавить дополнительные этапы валидации и постобработки.

Разные проекты — разные требования

У проектов разные требования и уровни рисков безопасности:

  1. Веб-скрейпинг: Валидировать URL-адреса, проверяя их доступность и надёжность.
  2. Обработка данных: Извлекать URL из пользовательского контента с учётом требований безопасности.
  3. Анализ данных: Отсеивать дубликаты и нерелевантные ссылки для исследовательских или маркетинговых задач.
  4. Клиентские приложения: Автоматически оборачивать URL в гиперссылки в чатах и на форумах.

Постобработка и валидация

После первичного извлечения потенциальных URL-адресов примените дополнительные проверки:

📝 Итоги

Извлечение полуструктурированных строк — это, пожалуй, самая удовлетворительная часть владения регулярными выражениями.

Кратко резюмирую ключевые моменты:

Следуя этим шагам, вы сможете эффективно извлекать любые полуструктурированные строковые данные, закладывая основу для последующей обработки и валидации.

📚 Дополнительные материалы