URL: структура, разбор и парсинг для разработчиков
URL (Uniform Resource Locator) — строка, однозначно идентифицирующая ресурс в сети. Понимание структуры URL и умение корректно его разбирать критично для веб-разработки, парсинга, редиректов и интеграций. В этой статье разберём компоненты URL по RFC 3986, кодирование, парсинг в JavaScript и Python, типичные ошибки и инструменты для анализа.
Для быстрого разбора URL используйте URL Парсер на reChecker.
Структура URL по RFC 3986
Стандарт RFC 3986 определяет общую форму URL:
scheme:[//authority]path[?query][#fragment]
Полный пример:
https://user:pass@example.com:443/path/to/page?key=value&foo=bar#section
Компоненты URL
| Компонент | Описание | Пример |
|---|---|---|
| scheme (протокол) | Протокол доступа | https:, http:, ftp: |
| authority | Хост, порт, учётные данные | //example.com:443 |
| userinfo | Логин и пароль (редко используется) | user:pass@ |
| host | Домен или IP | example.com, 192.168.1.1 |
| port | Порт (опционально) | :443, :3000 |
| path | Путь к ресурсу | /path/to/page |
| query | Параметры запроса | ?key=value&foo=bar |
| fragment | Якорь (часть страницы) | #section |
Схема (протокол)
Определяет способ доступа к ресурсу. Часто используемые:
http:— HTTPhttps:— HTTPS (HTTP over TLS)ftp:— FTPmailto:— emailfile:— локальный файл
Протокол заканчивается двоеточием. После // начинается authority (для http/https).
Authority (хост и порт)
Authority включает хост и опционально порт. Для HTTP порт 80 опускается, для HTTPS — 443.
https://example.com → хост example.com, порт 443 (по умолчанию)
http://localhost:3000 → хост localhost, порт 3000
https://sub.example.com:8443 → хост sub.example.com, порт 8443
Path (путь)
Путь идентифицирует ресурс на сервере. Начинается с /. Сегменты разделяются слэшами.
/path/to/page
/api/v1/users
/
Пустой путь или отсутствие пути после домена обычно трактуется как /.
Query string (строка запроса)
Параметры после ? в формате key=value, разделённые &.
?q=search&page=1&lang=ru
Символы =, &, ?, # имеют специальное значение. Значения с пробелами, кириллицей или спецсимволами должны быть закодированы (percent-encoding).
Fragment (хеш)
Фрагмент указывает на часть документа (якорь). Не передаётся на сервер — обрабатывается клиентом.
#section-2
#top
URI, URL и URN
URI (Uniform Resource Identifier) — общий термин для идентификаторов ресурсов. URL — подмножество URI, указывающее местоположение и способ доступа. URN (Uniform Resource Name) — идентификатор по имени без указания местоположения (например, urn:isbn:0451450523). В веб-разработке чаще всего работают с URL; термины URL и URI нередко используют как синонимы.
URL encoding (percent-encoding)
Символы вне набора A-Za-z0-9-_.~ и зарезервированные :/?#[]@!$&'()*+,;= в определённых позициях кодируются как %XX, где XX — шестнадцатеричный код байта в UTF-8.
| Символ | Кодирование |
|---|---|
| Пробел | %20 или + (в form data) |
| Кириллица «П» | %D0%9F (UTF-8) |
& | %26 |
= | %3D |
При парсинге URL браузер и сервер автоматически декодируют значения. При формировании URL вручную необходимо кодировать параметры через encodeURIComponent (JavaScript) или urllib.parse.quote (Python).
Абсолютные и относительные URL
Абсолютный URL
Содержит схему и authority. Полная ссылка на ресурс.
https://example.com/page
http://localhost:3000/api
Относительный URL
Относится к текущему документу или базовому URL.
| URL | Базовый URL | Результат |
|---|---|---|
page | https://example.com/ | https://example.com/page |
/page | https://example.com/path/ | https://example.com/page |
../page | https://example.com/a/b/ | https://example.com/a/page |
?q=1 | https://example.com/ | https://example.com/?q=1 |
При парсинге относительных URL нужен базовый URL для разрешения. В JavaScript new URL(path, base) решает эту задачу.
Парсинг URL в JavaScript
Конструктор URL
Современный API — конструктор URL:
const url = new URL('https://example.com/path?key=value#hash');
url.protocol; // "https:"
url.hostname; // "example.com"
url.port; // ""
url.pathname; // "/path"
url.search; // "?key=value"
url.hash; // "#hash"
url.origin; // "https://example.com"
url.href; // полный URL
URLSearchParams для query string
const url = new URL('https://example.com/search?q=hello&page=2');
url.searchParams.get('q'); // "hello"
url.searchParams.get('page'); // "2"
url.searchParams.get('missing'); // null
url.searchParams.forEach((value, key) => {
console.log(key, value);
});
// q hello
// page 2
Разрешение относительных URL
const base = 'https://example.com/path/';
const relative = '../other?q=1';
const resolved = new URL(relative, base);
// "https://example.com/other?q=1"
Изменение параметров
const url = new URL('https://example.com/page?q=old');
url.searchParams.set('q', 'new');
url.searchParams.set('page', '1');
url.searchParams.delete('oldParam');
url.href; // "https://example.com/page?q=new&page=1"
Парсинг URL в Python
urllib.parse
Стандартная библиотека urllib.parse:
from urllib.parse import urlparse, parse_qs
url = 'https://example.com/path?key=value&foo=bar#section'
parsed = urlparse(url)
parsed.scheme # 'https'
parsed.netloc # 'example.com'
parsed.path # '/path'
parsed.query # 'key=value&foo=bar'
parsed.fragment # 'section'
Разбор query string
from urllib.parse import parse_qs, parse_qsl
query = 'key=value&foo=bar&foo=baz'
parse_qs(query) # {'key': ['value'], 'foo': ['bar', 'baz']}
parse_qsl(query) # [('key', 'value'), ('foo', 'bar'), ('foo', 'baz')]
Сборка URL
from urllib.parse import urlunparse, urlencode
components = ('https', 'example.com', '/path', '', 'key=value', '')
urlunparse(components) # 'https://example.com/path?key=value'
params = {'q': 'поиск', 'page': 1}
urlencode(params) # 'q=%D0%BF%D0%BE%D0%B8%D1%81%D0%BA&page=1'
Разрешение относительных URL
from urllib.parse import urljoin
base = 'https://example.com/path/'
urljoin(base, '../other?q=1') # 'https://example.com/other?q=1'
Типичные ошибки при парсинге
Игнорирование ошибок
Некорректный URL вызывает исключение. Обрабатывайте ошибки:
try {
const url = new URL(input);
// работа с url
} catch {
// некорректный URL
}
Ручной разбор через regex
Регулярные выражения плохо справляются со всеми edge cases URL (кодирование, нестандартные схемы, IPv6). Используйте встроенные парсеры.
Неверное кодирование параметров
При добавлении параметров кодируйте значения:
// Неправильно
const url = `https://example.com/search?q=${userInput}`;
// Правильно
const url = `https://example.com/search?q=${encodeURIComponent(userInput)}`;
Путаница encodeURI и encodeURIComponent
encodeURI— для целого URL, не кодирует;/?:@&=+$,#encodeURIComponent— для значений параметров, кодирует почти всё
Для query-параметров всегда используйте encodeURIComponent.
Двойное кодирование
Если значение уже закодировано, повторное кодирование исказит данные. Проверяйте источник.
URL Парсер reChecker
Сервис URL Парсер на reChecker позволяет:
- Разобрать URL на компоненты: протокол, хост, порт, путь, query string, хеш
- Получить таблицу параметров query string с ключами и значениями
- Проверить валидность URL
- Увидеть закодированную и декодированную форму
Инструмент подходит для:
- Разработчиков — отладка URL, проверка структуры
- SEO-специалистов — анализ параметров в URL страниц
- Тестировщиков — проверка корректности сформированных ссылок
Вставьте URL в поле и нажмите «Анализировать» — результат отображается в виде таблицы с разбором каждого компонента. Поддерживаются URL с кириллицей, параметрами и фрагментами.
Практические сценарии
Извлечение домена из ссылки
const url = new URL('https://sub.example.com/path?q=1');
const domain = url.hostname; // "sub.example.com"
Добавление параметра к текущему URL
const url = new URL(window.location.href);
url.searchParams.set('utm_source', 'newsletter');
window.history.replaceState({}, '', url);
Проверка, является ли ссылка внутренней
const link = new URL(href, window.location.origin);
const isInternal = link.origin === window.location.origin;
Парсинг UTM-меток
const url = new URL(pageUrl);
const utm = {
source: url.searchParams.get('utm_source'),
medium: url.searchParams.get('utm_medium'),
campaign: url.searchParams.get('utm_campaign'),
};
Специальные случаи
IPv6: URL с IPv6-адресом заключает хост в квадратные скобки: http://[::1]:8080/. Конструктор URL и urllib.parse корректно обрабатывают такой формат.
Пустой path: URL https://example.com имеет path / (корневой). При разборе pathname вернёт /.
Множественные ?: В query string только первый ? разделяет path и query. Символ ? в значении параметра кодируется как %3F.
Пустые значения: Параметр key= имеет пустое значение. URLSearchParams.get('key') вернёт '', а не null.
Безопасность и валидация
При приёме URL от пользователя (формы, API) необходима валидация:
- Протокол: разрешайте только
http:иhttps:для веб-ссылок, чтобы предотвратитьjavascript:илиdata:инъекции - Хост: проверяйте, что домен не указывает на внутренние ресурсы (SSRF)
- Длина: слишком длинные URL могут вызывать проблемы на сервере или в логах
function isSafeUrl(href) {
try {
const url = new URL(href);
return ['http:', 'https:'].includes(url.protocol);
} catch {
return false;
}
}
FAQ
Что такое RFC 3986?
RFC 3986 — стандарт, определяющий синтаксис URI (и URL как подмножество). Описывает схему, authority, path, query и fragment, а также правила кодирования и разрешения относительных ссылок.
Чем отличается path от query string?
Path (/path/to/page) идентифицирует ресурс на сервере. Query string (?key=value) передаёт дополнительные параметры запроса. Path обычно стабилен для одного типа ресурса; query меняется в зависимости от параметров (фильтры, пагинация, UTM).
Как правильно парсить query string с несколькими значениями для одного ключа?
В JavaScript URLSearchParams.getAll('key') возвращает массив всех значений. В Python parse_qs возвращает словарь, где каждому ключу соответствует список значений.
Почему fragment (хеш) не отправляется на сервер?
Фрагмент предназначен для клиентской навигации внутри документа (якоря). Браузер не включает его в HTTP-запрос. Сервер получает URL без части после #.
Какой инструмент использовать для разбора URL?
URL Парсер reChecker — бесплатный онлайн-инструмент для разбора URL на компоненты. Показывает протокол, хост, порт, путь, параметры query string и хеш в удобной таблице. Поддерживает кириллические URL и отображает закодированную/декодированную форму. Для кодирования и декодирования параметров используйте URL Encoder reChecker.