Urllib.request.urlopen: примеры (PYTHON)

Функция urlopen из модуля urllib.request в Python
Раздел: HTTP-клиенты, URL
urllib.request.urlopen(url: str or urllib.request.Request, data: bytes=None, timeout: float=None, *, cafile: str=None, capath: str=None, cadefault: bool=False, context: ssl.SSLContext=None): urllib.response.addinfourl

Основные сведения о функции

Функция urllib.request.urlopen является частью стандартной библиотеки Python и предназначена для открытия сетевых ресурсов, идентифицируемых URL. Она служит основным инструментом для выполнения простых HTTP-запросов без использования сторонних библиотек. Ее часто применяют для получения данных с веб-страниц, доступа к API или загрузки файлов.

Сигнатура функции: urllib.request.urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *, cafile=None, capath=None, cadefault=False, context=None)

Аргументы:

  • url: Может быть строкой с URL или объектом urllib.request.Request. Это обязательный аргумент.
  • data: Необязательные данные для отправки на сервер. Если указан (обычно в виде объекта bytes), запрос становится POST. По умолчанию None (GET-запрос).
  • timeout: Таймаут операции в секундах. По умолчанию используется глобальный таймаут сокета.
  • cafile и capath: Пути к файлу или директории с сертификатами CA для проверки SSL. Используются при работе с HTTPS.
  • cadefault: Игнорируется.
  • context: Объект ssl.SSLContext, позволяющий задать параметры SSL/TLS.

Возвращаемое значение: Функция возвращает объект http.client.HTTPResponse (или его аналог для FTP, файлов). Этот объект поддерживает методы чтения (.read(), .readline()), предоставляет заголовки ответа (.getheaders(), .getheader()) и имеет атрибуты, такие как status, reason и url.

Базовые примеры применения

Пример простого GET-запроса для получения содержимого веб-страницы.

import urllib.request

with urllib.request.urlopen('https://httpbin.org/get') as response:
    html = response.read()
    print(f'Статус: {response.status}')
    print('Заголовки:', response.getheaders())
    print('\nПервые 200 символов тела ответа:')
    print(html[:200].decode('utf-8'))
Статус: 200
Заголовки: [('Date', '...'), ('Content-Type', 'application/json'), ...]

Первые 200 символов тела ответа:
{
  "args": {},
  "headers": {
    "Accept-Encoding": "identity",
    "Host": "httpbin.org",
    "User-Agent": "Python-urllib/3.11",
    "X-Amzn

Пример POST-запроса с отправкой данных.

import urllib.parse
import urllib.request

url = 'https://httpbin.org/post'
data = urllib.parse.urlencode({'key1': 'value1', 'key2': 'value2'}).encode()

with urllib.request.urlopen(url, data=data) as response:
    print(f'Статус: {response.status}')
    print(response.read().decode()[:150])
Статус: 200
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "key1": "value1",
    "key2": "value2"
  },
  "headers": {

Пример задания таймаута.

import urllib.request
import urllib.error

try:
    # Запрос к ресурсу, который отвечает долго
    with urllib.request.urlopen('https://httpbin.org/delay/5', timeout=2) as response:
        print(response.read())
except urllib.error.URLError as e:
    print(f'Ошибка таймаута: {e.reason}')
Ошибка таймаута: timed out

Альтернативные решения в Python

Модуль requests - популярная сторонняя библиотека с более простым и удобным API. Она автоматически обрабатывает кодировки, сессии, JSON. Ее предпочтительно использовать для сложных задач и в новых проектах из-за удобства.

Модуль http.client - низкоуровневый клиент HTTP из стандартной библиотеки. Функция urlopen сама использует его. Он дает максимальный контроль над запросом и ответом, но его код более многословен. Применяется, когда нужен полный контроль или когда использование сторонних библиотек невозможно.

Модуль aiohttp - асинхронный HTTP-клиент и сервер. Его выбирают для высокопроизводительных асинхронных приложений, где важно не блокировать поток выполнения.

Аналоги в других языках программирования

JavaScript (fetch API): Современный промис-ориентированный API для выполнения сетевых запросов.

fetch('https://httpbin.org/get')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Ошибка:', error));
{args: {…}, headers: {…}, origin: "...", url: "..."}

PHP (file_get_contents): Простая функция для чтения содержимого файла или URL в строку.

<?php
$homepage = file_get_contents('http://www.example.com/');
echo $homepage;
?>
<!doctype html><html>...</html>

Golang (net/http.Get): Использование стандартного пакета net/http.

package main
import (
    "fmt"
    "io/ioutil"
    "net/http"
)
func main() {
    resp, err := http.Get("https://httpbin.org/get")
    if err != nil { panic(err) }
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body)[:100])
}
{
  "args": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",

Java (java.net.HttpURLConnection): Базовый класс для HTTP-запросов.

import java.net.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://httpbin.org/get");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) { System.out.println(inputLine); }
        in.close();
    }
}
{
  "args": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    ...
  },
  ...
}

Распространенные ошибки и их обработка

Отсутствие обработки исключений для сетевых ошибок или HTTP-статусов, отличных от 200.

import urllib.request
import urllib.error

url = "https://httpbin.org/status/404"
try:
    with urllib.request.urlopen(url) as response:
        print(response.read())
except urllib.error.HTTPError as e:
    print(f'Ошибка HTTP {e.code}: {e.reason}')
Ошибка HTTP 404: NOT FOUND

Попытка декодировать бинарные данные (например, изображение) как строку UTF-8.

import urllib.request

# Загрузка изображения
with urllib.request.urlopen('https://httpbin.org/image/png') as response:
    image_data = response.read()  # Оставляем как bytes
    # Неправильно: text = image_data.decode('utf-8') - вызовет UnicodeDecodeError
    print(f'Получено {len(image_data)} байт бинарных данных.')
Получено 8090 байт бинарных данных.

Использование строки для параметра data вместо объекта bytes.

import urllib.request
import urllib.parse

url = 'https://httpbin.org/post'
data_str = 'key=value'
# data = data_str  # Вызовет TypeError: POST data should be bytes
# Правильно:
data_bytes = data_str.encode('utf-8')
with urllib.request.urlopen(url, data=data_bytes) as resp:
    print(resp.status)
200

Изменения в последних версиях Python

В Python 3.2 были добавлены аргументы cafile, capath и cadefault.

В Python 3.4.3 аргумент context стал доступен для всех версий, а не только при наличии ssl.

Начиная с Python 3.6, параметр context также поддерживается для FTP, FTPS и файловых URL.

В Python 3.10 в сигнатуре функции явно указаны cafile, capath, cadefault, context как keyword-only аргументы.

Версия Python 3.11 улучшила производительность модуля urllib.request.

Расширенные примеры использования

Использование контекста SSL для отключения проверки сертификата (только для тестирования).

Пример python
import urllib.request
import ssl

# НЕ БЕЗОПАСНО для production кода!
context = ssl._create_unverified_context()
url = 'https://expired.badssl.com/'  # Сайт с просроченным сертификатом
try:
    with urllib.request.urlopen(url, context=context) as response:
        print(f'Страница загружена. Статус: {response.status}')
except Exception as e:
    print(f'Ошибка: {e}')
Страница загружена. Статус: 200

Чтение ответа построчно для больших файлов.

Пример python
import urllib.request

url = 'https://filesamples.com/samples/document/txt/sample1.txt'
with urllib.request.urlopen(url) as response:
    # Декодируем поток байтов в поток строк
    for line_bytes in response:
        line = line_bytes.decode('utf-8').rstrip('\n\r')
        print(f'Прочитана строка: {line[:50]}...')  # Печатаем первые 50 символов
        break  # Прерываем после первой строки для примера
Прочитана строка: Lorem ipsum dolor sit amet, consectetur adipiscin...

Создание объекта Request для установки пользовательских заголовков перед вызовом urlopen.

Пример python
import urllib.request

url = 'https://httpbin.org/headers'
req = urllib.request.Request(url)
req.add_header('User-Agent', 'MyCustomAgent/1.0')
req.add_header('X-Custom-Header', 'TestValue')

with urllib.request.urlopen(req) as response:
    import json
    data = json.load(response)
    print('Полученные заголовки от сервера:')
    print(json.dumps(data['headers'], indent=2))
Полученные заголовки от сервера:
{
  "Accept-Encoding": "identity",
  "Host": "httpbin.org",
  "User-Agent": "MyCustomAgent/1.0",
  "X-Custom-Header": "TestValue"
}

Обработка перенаправлений (urlopen делает это автоматически, атрибут .url показывает итоговый URL).

Пример python
import urllib.request

# httpbin.org перенаправляет с /redirect/1 на /get
url = 'https://httpbin.org/redirect/1'
with urllib.request.urlopen(url) as response:
    print(f'Итоговый URL: {response.url}')
    print(f'Код статуса: {response.status}')
    # Заголовок 'Location' будет отсутствовать, т.к. перенаправление обработано
    print(f"Заголовок 'Location': {response.getheader('Location')}")
Итоговый URL: https://httpbin.org/get
Код статуса: 200
Заголовок 'Location': None

Работа с базовой аутентификацией (HTTP Basic Auth).

Пример python
import urllib.request
import base64

url = 'https://httpbin.org/basic-auth/user/passwd'
username = 'user'
password = 'passwd'

# Создаем заголовок Authorization
credentials = f'{username}:{password}'.encode()
base64_credentials = base64.b64encode(credentials).decode()
auth_header = f'Basic {base64_credentials}'

req = urllib.request.Request(url)
req.add_header('Authorization', auth_header)

with urllib.request.urlopen(req) as response:
    print(f'Успешная аутентификация. Статус: {response.status}')
    print(response.read().decode())
Успешная аутентификация. Статус: 200
{
  "authenticated": true,
  "user": "user"
}

питон urllib.request.urlopen function comments

En
Urllib.request.urlopen Open a URL