Роман Сузи - Язык программирования Python
В этой таблице num обозначает номер сообщения (он не меняется на протяжении всей сессии), resp — ответ сервера, возвращается для любой команды, начинается с «+OK » для успешных операций (при неудаче возбуждается исключение poplib.proto_error). Параметр octets обозначает количество байт в принятых данных. uniqid — идентификатор сообщения, генерируемый сервером.
Работа с POP3–сервером состоит из трех фаз: идентификации, транзакций и обновления. На этапе идентификации сразу после создания POP3–объекта разрешены только команды USER, PASS (иногда APOP и RPOP). После идентификации сервер получает информацию о пользователе и наступает этап транзакций. Здесь уместны остальные команды. Этап обновления вызывается командой QUIT, после которой POP3–сервер обновляет почтовый ящик пользователя в соответствии с поданными командами, а именно — удаляет помеченные для удаления сообщения.
Модули для клиента WWW
Стандартные средства языка Python позволяют получать из программы доступ к объектам WWW как в простых случаях, так и при сложных обстоятельствах, в частности при необходимости передавать данные формы, идентификации, доступа через прокси и т.п.
Стоит отметить, что при работе с WWW используется в основном протокол HTTP, однако WWW охватывает не только HTTP, но и многие другие схемы (FTP, gopher, HTTPS и т.п.). Используемая схема обычно указана в самом начале URL.
Функции для загрузки сетевых объектов
Простой случай получения WWW–объекта по известному URL показан в следующем примере:
import urllib
doc = urllib.urlopen("http://python.onego.ru").read()
print doc[:40]
Функция urllib.urlopen() создает файлоподобный объект, который читает методом read(). Другие методы этого объекта: readline(), readlines(), fileno(), close() работают как и у обычного файла, а также есть метод info(), который возвращает соответствующий полученному с сервера Message–объект. Этот объект можно использовать для получения дополнительной информации:
>>> import urllib
>>> f = urllib.urlopen("http://python.onego.ru")
>>> print f.info()
Date: Sat, 25 Dec 2004 19:46:11 GMT
Server: Apache/1.3.29 (Unix) PHP/4.3.10
Content–Type: text/html; charset=windows–1251
Content–Length: 4291
>>> print f.info()['Content–Type']
text/html; charset=windows–1251
С помощью функции urllib.urlopen() можно делать и более сложные вещи, например, передавать web–серверу данные формы. Как известно, данные заполненной web–формы могут быть переданы на web–сервер с использованием метода GET или метода POST. Метод GET связан с кодированием всех передаваемых параметров после знака «?» в URL, а при методе POST данные передаются в теле HTTP–запроса. Оба варианта передачи представлены ниже:
import urllib
data = {"search»: "Python"}
enc_data = urllib.urlencode(data)
# метод GET
f = urllib.urlopen("http://searchengine.com/search" + "?" + enc_data)
print f.read()
# метод POST
f = urllib.urlopen("http://searchengine.com/search", enc_data)
print f.read()
В некоторых случаях данные имеют повторяющиеся имена. В этом случае в качестве параметра urllib.urlencode() можно использовать вместо словаря последовательность пар имя–значение:
>>> import urllib
>>> data = [("n", "1"), ("n", "3"), ("n", "4"), ("button", "Привет"),]
>>> enc_data = urllib.urlencode(data)
>>> print enc_data
n=1&n=3&n=4&button=%F0%D2%C9%D7%C5%D4
Модуль urllib позволяет загружать web–объекты через прокси–сервер. Если ничего не указывать, будет использоваться прокси–сервер, который был задан принятым в конкретной ОС способом. В Unix прокси–серверы задаются в переменных окружения http_proxy, ftp_proxy и т.п., в Windows прокси–серверы записаны в реестре, а в Mac OS они берутся из конфигурации Internet. Задать прокси–сервер можно и как именованный параметр proxies к urllib.urlopen():
# Использовать указанный прокси
proxies = {'http': 'http://www.proxy.com:3128'}
f = urllib.urlopen(some_url, proxies=proxies)
# Не использовать прокси
f = urllib.urlopen(some_url, proxies={})
# Использовать прокси по умолчанию
f = urllib.urlopen(some_url, proxies=None)
f = urllib.urlopen(some_url)
Функция urlretrieve() позволяет записать заданный URL сетевой объект в файл. Она имеет следующие параметры:
urllib.urlretrieve(url[, filename[, reporthook[, data]]])
Здесь url — URL сетевого объекта, filename — имя локального файла для помещения объекта, reporthook — функция, которая будет вызываться для сообщения о состоянии загрузки, data — данные для метода POST (если он используется). Функция возвращает кортеж (filepath, headers), где filepath — имя локального файла, в который закачан объект, headers — результат метода info() для объекта, возвращенного urlopen().
Для обеспечения интерактивности функция urllib.urlretrieve() вызывает время от времени функцию, заданную в reporthook(). Этой функции передаются три аргумента: количество принятых блоков, размер блока и общий размер принимаемого объекта в байтах (если он неизвестен, этот параметр равен–1).
В следующем примере программа принимает большой файл и, чтобы пользователь не скучал, пишет процент от выполненной загрузки и предполагаемое оставшееся время:
FILE = 'boost–1.31.0–9.src.rpm'
URL = 'http://download.fedora.redhat.com/pub/fedora/linux/core/3/SRPMS/' + FILE
def download(url, file):
import urllib, time
start_t = time.time()
def progress(bl, blsize, size):
dldsize = min(bl*blsize, size)
if size != -1:
p = float(dldsize) / size
try:
elapsed = time.time() - start_t
est_t = elapsed / p — elapsed
except:
est_t = 0
print "%6.2f %% %6.0f s %6.0f s %6i / %-6i bytes" % (
p*100, elapsed, est_t, dldsize, size)
else:
print "%6i / %-6i bytes" % (dldsize, size)
urllib.urlretrieve(URL, FILE, progress)
download(URL, FILE)
Эта программа выведет примерно следующее (процент от полного объема закачки, прошедшие секунды, предполагаемое оставшееся время, закачанные байты, полное количество байтов):
0.00 % 1 s 0 s 0 / 6952309 bytes
0.12 % 5 s 3941 s 8192 / 6952309 bytes
0.24 % 7 s 3132 s 16384 / 6952309 bytes
0.35 % 10 s 2864 s 24576 / 6952309 bytes
0.47 % 12 s 2631 s 32768 / 6952309 bytes
0.59 % 15 s 2570 s 40960 / 6952309 bytes
0.71 % 18 s 2526 s 49152 / 6952309 bytes
0.82 % 20 s 2441 s 57344 / 6952309 bytes
...
Функции для анализа URL
Согласно документу RFC 2396 URL должен строиться по следующему шаблону:
scheme://netloc/path;parameters?query#fragment
где
scheme
Адресная схема. Например: http, ftp, gopher.
netloc
Местонахождение в сети.
path
Путь к ресурсу.
params
Параметры.
query
Строка запроса.
frag
Идентификатор фрагмента.
Одна из функций уже использовалась для формирования URL — urllib.urlencode(). Кроме нее в модуле urllib имеются и другие функции:
quote(s, safe='/')
Функция экранирует символы в URL, чтобы их можно было отправлять на web–сервер. Она предназначена для экранирования пути к ресурсу, поэтому оставляет '/' как есть. Например:
>>> urllib.quote("[email protected]")
'rnd%40onego.ru'
>>> urllib.quote("a = b + c")
'a%20%3D%20b%20%2B%20c'
>>> urllib.quote("0/1/1")
'0/1/1'
>>> urllib.quote("0/1/1", safe="")
'0%2F1%2F1'
quote_plus(s, safe='')
Функция экранирует некоторые символы в URL (в строке запроса), чтобы их можно было отправлять на web–сервер. Аналогична quote(), но заменяет пробелы на плюсы.
unquote(s)
Преобразование, обратное quote_plus(). Пример:
>>> urllib.unquote('a%20%3D%20b%20%2B%20c')
'a = b + c'
unquote_plus(s)
Преобразование, обратное quote_plus(). Пример:
>>> urllib.unquote_plus('a+=+b+%2B+c')
'a = b + c'
Для анализа URL можно использовать функции из модуля urlparse:
urlparse(url, scheme='', allow_fragments=1)
Разбирает URL в 6 компонентов (сохраняя экранирование символов):
scheme://netloc/path;params?query#frag
urlsplit(url, scheme='', allow_fragments=1)
Разбирает URL в 6 компонентов (сохраняя экранирование символов):
scheme://netloc/path?query#frag
urlunparse((scheme, netloc, url, params, query, fragment))
Собирает URL из 6 компонентов.
urlunsplit((scheme, netloc, url, query, fragment))
Собирает URL из 5 компонентов.
Пример:
>>> from urlparse import urlsplit, urlunsplit
>>> URL = "http://google.com/search?q=Python"
>>> print urlsplit(URL)
('http', 'google.com', '/search', 'q=Python', '')
>>> print urlunsplit(