На этом шаге мы рассмотрим особенности отправки данных по этому протоколу.
Модуль http.client позволяет получить информацию из Интернета по протоколам HTTP и HTTPS. Отправить запрос можно методами GET, POST и HEAD.
Для создания объекта соединения, использующего протокол HTTP, предназначен класс HTTPConnection. Его конструктор имеет следующий формат:
HTTPConnection(<Домен>[, <Порт>[, timeout[, source_address]]])
В первом параметре указывается название домена без протокола. Во втором параметре задается номер порта - если параметр не указан, используется порт 80. Номер порта можно также задать после названия домена через двоеточие. Пример создания объекта соединения:
>>> from http.client import HTTPConnection >>> con = HTTPConnection("test1.ru") >>> con2 = HTTPConnection("test1.ru", 80) >>> con3 = HTTPConnection("test1.ru:80")
После создания объекта соединения необходимо отправить запрос, возможно, с параметрами, вызвав метод request() класса HTTPConnection. Формат метода:
request (<Метод>, <Путь>[, body=None][, headers=<Заголовки>])
В первом параметре указывается метод передачи данных (GET, POST или HEAD). Второй параметр задает путь к запрашиваемому файлу или вызываемой программе, отсчитанный от корня сайта. Если для передачи данных используется метод GET, то после вопросительного знака можно указать передаваемые данные. В необязательном третьем параметре задаются данные, которые передаются методом POST, - допустимо указать строку, файловый объект или последовательность. Четвертый параметр задает в виде словаря HTTP-заголовки, отправляемые на сервер.
Получить объект результата запроса позволяет метод getresponse(). Он возвращает результат выполненного запроса, представленный в виде объекта класса HTTPResponse. Из него мы сможем получить ответ сервера.
Прочитать ответ сервера (без заголовков) можно с помощью метода read( [<Количество байт>]) класса HTTPResponse. Если параметр не указан, метод read() возвращает все данные, а при наличии параметра - только указанное количество байтов при каждом вызове. Если данных больше нет, метод возвращает пустую строку. Прежде чем выполнять другой запрос, данные должны быть получены полностью. Метод read() возвращает последовательность байтов, а не строку. Закрыть объект соединения позволяет метод close() класса HTTPConnection. Для примера отправим запрос методом GET и прочитаем результат.
>>> from http.client import HTTPConnection >>> from urllib.parse import urlencode >>> data = urlencode({"color": "Красный", "var": 15}, encoding="cp1251") >>> headers = { "User-Agent": "MySpider/1.0", "Accept": "text/html, text/plain, application/xml", "Accept-Language": "ru, ru-RU", "Accept-Charset": "windows-1251", "Referer": "/index.php" } >>> con = HTTPConnection("mail.ru") >>> con.request("GET", "/testrobots.php?%s" % data, headers=headers) >>> result = con.getresponse() # Создаем объект результата >>> print (result.read().decode("cp1251" )) # Читаем данные <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.14.1</center> </body> </html> >>> con.close() # Закрываем объект соединения
Теперь отправим данные методом POST. В этом случае в первом параметре метода request() задается значение "POST", а данные передаются через третий параметр. Размер строки запроса автоматически указывается в заголовке Content-Length. Пример отправки данных методом POST приведен ниже.
>>> from http.client import HTTPConnection >>> from urllib.parse import urlencode >>> data = urlencode({"color": "Красный", "var": 15}, encoding="cp1251") >>> headers = { "User-Agent": "MySpider/1.0", "Accept": "text/html, text/plain, application/xml", "Accept-Language": "ru, ru-RU", "Accept-Charset": "windows-1251", "Content-Type": "application/x-www-form-urlencoded", "Referer": "/index.php" } >>> con = HTTPConnection("mail.ru") >>> con.request("POST", "/testrobots.php?%s" % data, headers=headers) >>> result = con.getresponse() # Создаем объект результата >>> print (result.read().decode("cp1251" )) # Читаем данные <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.14.1</center> </body> </html> >>> con.close() # Закрываем объект соединения
Обратите внимание на заголовок Content-Type. Если в нем указано значение application/x-www-form-urlencoded, это означает, что отправлены данные формы. При наличии этого заголовка некоторые программные платформы автоматически производят разбор строки запроса. Например, в РНР переданные данные будут доступны через глобальный массив $_POST. Если же заголовок не указать, то данные через массив $_POST доступны не будут.
На следующем шаге мы продолжим изучение этого вопроса.