HTTP: доступ к веб-сайтам

http dostup k veb sajtam Сценарии на стороне клиента

Стандартная библиотека Python (то есть модули, устанавливаемые вместе с интерпретатором) содержит также поддержку протокола HTTP (Hypertext Transfer Protocol — гипертекстовый транспортный протокол) на стороне клиента — стандарта структуры сообщений и портов, используемых для передачи информации в World Wide Web. Вкратце, это тот протокол, который использует ваш веб-броузер (например, Internet Explorer, Firefox, Chrome или Safari) для получения веб-страниц и запуска приложений на удаленных серверах при веб-серфинге. По сути, он просто определяет порядок обмена байтами через порт 80.

Чтобы действительно понять, как передаются данные по протоколу HTTP, необходимо знать некоторые темы, относящиеся к выполнению сценариев на стороне сервера, рассматриваемые в главе 15 (например, как вызываются сценарии и какие схемы адресации используются в Интернете), поэтому данный раздел может оказаться менее полезным для читателей, не имеющих соответствующей подготовки. К счастью, основные интерфейсы HTTP в Python достаточно просты для начального их понимания даже на данном этапе, поэтому мы сейчас кратко их рассмотрим.

Стандартный модуль Python http.client в значительной мере автоматизирует использование протокола HTTP и позволяет сценариям получать веб-страницы, почти как в веб-броузерах. Как мы увидим в главе 15, модуль http.server позволяет также создавать веб-серверы для работы с другой стороны соединения. В частности, сценарий в примере 13.29 может получить любой файл с любого компьютера, на котором выполняется программа веб-сервера HTTP. Как обычно, файл (и строки заголовков описания) в конечном счете передается через стандартный порт сокета, но большая часть сложных деталей скрыта в модуле http. client (сравните с нашей реализацией диалога с HTTP-сервером через порт 80 с применением простых сокетов в главе 12).

Пример 13.29. PP4E\Internet\Other\http-getfile.py

получает файл с сервера HTTP (web) через сокеты с помощью модуля http. client; параметр с именем файла может содержать полный путь к каталогу и быть именем любого сценария CGI с параметрами запроса в конце, отделяемыми символом ?, для вызова удаленной программы; содержимое полученного файла или вывод удаленной программы можно сохранить в локальном файле, имитируя поведение FTP, или анализировать с помощью модуля str.find или html.parser; смотрите также описание метода http.client request(method, url, body=None, hdrs={});

import sys, http.client

showlines = 6

try:

servername, filename = sys.argv[1:] # аргументы командной строки? except:

servername, filename = ‘learning-python.com’, ‘/index.html’

print(servername, filename)

server = http.client.HTTPConnection(servername) # соединиться с httpсервером server.putrequest(‘GET’, filename) # отправить запрос и заголовки server.putheader(‘Accept’, ‘text/html’) # можно также отправить запрос POST server.endheaders() # как и имена файлов сценариев CGI

reply = server.getresponse() # прочитать заголовки+данные ответа

if reply.status != 200: # код 200 означает успех

print(‘Error sending request’, reply.status, reply.reason) else:

data = reply.readlines() # объект файла для получаемых данных

reply.close() # вывести строки с eoln в конце

for line in data[:showlines]: # чтобы сохранить, запишите в файл

print(line) # строки уже содержат \n,

# но являются строками bytes

Требуемые имена серверов и файлов можно передать в командной строке, переопределив тем самым значения по умолчанию, определенные в программном коде. Чтобы до конца понять этот сценарий, необходимо иметь представление протокола HTTP, но в общем он довольно прост для расшифровки. При выполнении на стороне клиента этот сценарий создает объект HTTP, который соединяется с сервером, посылает запрос GET и допустимые типы ответов, а затем читает ответ сервера. Подобно исходному тесту сообщения электронной почты, ответ сервера http обычно начинается с нескольких строк заголовков описания, за которыми следует содержимое запрошенного файла. Метод getfile объекта HTTP возвращает объект файла, из которого можно читать загруженные данные. Давайте получим с помощью этого сценария несколько файлов. Как и другие клиентские сценарии на языке Python, данный сценарий может выполняться на любом компьютере, где установлен Python и имеется соединение с Интернетом (в данном случае он выполняется на клиенте Windows). Если все пройдет хорошо, будут выведены несколько первых строк загруженного файла. В более реалистичном приложении получаемый текст можно было бы сохранить в локальном файле, проанализировать с помощью модуля Python html.parser (будет представлен в главе 19) и так далее. При запуске без аргументов сценарий просто загрузит начальную страницу HTML с сайта http://learning-python.com, который находится на сервере моего коммерческого провайдера:

C:\\PP4E\Internet\Other> http-getfile.py

learning-python.com /index.html

b'<HTML>\n’

b’ \n’

b'<HEAD>\n’

b"<TITLE>Mark Lutz’s Python Training Services</TITLE>\n"

b'<!mstheme><link rel="stylesheet" type="text/css" href="_themes/blends/ blen…’

b‘</HEAD>\n

Обратите внимание, что в Python 3.X данные поступают клиенту в виде строк типа bytes, а не str. Так как модуль html.parser, выполняющий анализ разметки HTML, с которым мы познакомимся в главе 19, требует текстовые строки str, а не строки bytes, вам наверняка придется решить, какую кодировку Юникода применить, чтобы обеспечить возможность анализа, — практически так же, как мы делали это при обработке почтовых сообщений выше. Как и прежде, для декодирования строки bytes в str можно было бы использовать кодировку по умолчанию, извлекать ее из настроек, предлагать сделать выбор пользователю, определять из заголовков или на основе анализа структуры байтов. Поскольку данные через сокеты всегда передаются в виде простых байтов, мы постоянно будем оказываться перед выбором при передаче через них текстовых данных. Поддержка Юникода подразумевает выполнение дополнительных действий, за исключением случаев, когда тип текста известен заранее или всегда имеет простую форму.

Имя сервера и файла, который должен быть получен, также можно указать в командной строке. В следующем примере показано применение этого сценария для получения файлов с двух разных веб-сайтов, имена которых указываются в командных строках (я обрезал некоторые из строк, чтобы уместить их по ширине страницы). Обратите внимание, что аргумент имени файла может содержать произвольный путь к удаленному каталогу с нужным файлом, как в последней из приведенных попыток:

C:\\PP4E\Internet\Other> http-getfile.py www.python.org /index.html www.python.org /index.html

b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://…………

b’\n’ b’\n’

b'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n’ b’\n’

b'<head>\n’

C:\\PP4E\Internet\Other> http-getfile.py www.python.org index.html www.python.org index.html

Error sending request 400 Bad Request

C:\\PP4E\Internet\Other> http-getfile.py www.rmi.net /~lutz www.rmi.net /~lutz

Error sending request 301 Moved Permanently

C:\\PP4E\Internet\Other> http-getfile.py www.rmi.net /~lutz/index.html www.rmi.net /~lutz/index.html b'<HTML>\n’ b’\n’ b'<HEAD>\n’ b"<TITLE>Mark Lutz’s Book Support Site</TITLE>\n" b'</HEAD>\n’

b‘<BODY BGCOLOR="#f1f1ff">\n

Обратите внимание на вторую и третью попытки в этом примере: в случае неудачи сценарий получает и выводит код ошибки HTTP, возвращаемый сервером (во второй попытке мы забыли добавить ведущий символ слэша, а в третьей — имя файла «index.html», совершенно необходимые для данного сервера и интерфейса). При использовании низкоуровневых интерфейсов HTTP необходимо точно указывать, что требуется получить.

Технически переменная filename в сценарии может ссылаться на простой статический файл веб-страницы или на программу сервера, генерирующую разметку HTML. Такие серверные программы обычно называются сценариями CGI — они являются темой глав 15 и 16. Пока лишь запомните, что если filename указывает на сценарий, то данная программа может запустить другую программу, находящуюся на удаленном сервере. В таком случае после символа ?, вслед за именем программы, можно также указать параметры (называемые строкой запроса), которые должны быть переданы удаленной программе.

В следующем примере мы передаем параметр language=Python сценарию CGI, с которым мы познакомимся в главе 15 (для этого примера нам также необходимо сначала запустить локальный веб-сервер на языке Python, используя сценарий, с которым мы впервые встретились в главе 1 и к которому еще вернемся в главе 15):

В другом окне

C:\\PP4E\Internet\Web> webserver.py

webdir ".", port 80

C:\\PP4E\Internet\Other> http-getfile.py localhost

/cgi-bin/languages.py?language=Python

localhost /cgi-bin/languages.py?language=Python b'<TITLE>Languages</TITLE>\n’

b'<H1>Syntax</H1><HR>\n’ b'<H3>Python</H3><P><PRE>\n’ b" print(‘Hello World’) \n"

b'</PRE></P><BR>\n’ b'<HR>\n’

В этой книге еще много будет говориться о разметке HTML, сценариях CGI и смысле запроса HTTP GET, использовавшегося в примере 13.29 (наряду с методом POST являющимся одним из способов форматирования информации, посылаемой серверу HTTP), поэтому сейчас мы опустим дополнительные детали.

Достаточно сказать, однако, что с помощью интерфейсов HTTP можно написать собственный веб-броузер и создать сценарии, использующие веб-сайты так, как если бы они были подпрограммами. Путем отправки параметров удаленным программам и анализа возвращаемых результатов можно заставить веб-сайты играть роль простых функций, выполняющихся в том же процессе (хотя и значительно более медленно и косвенно).

Использованная литература:

Марк Лутц — Программирование на Python, 4-е издание, II том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий