Простой Python — страница 33 из 66

Наконец, существует особая категория баз данных для полнотекстового поиска. Они индексируют все, поэтому вы легко можете найти то стихотворение, в котором говорится о ветряных мельницах и гигантских головках сыра. Вы можете увидеть популярные примеры таких баз данных с открытым исходным кодом и их Python API в табл. 8.7.


Таблица 8.7. Полнотекстовые базы данных
СайтPython API
Lucenepylucene
SolrSolPython
ElasticSearchpyes
Sphinxsphinxapi
Xapianxappy
WhooshНаписан на Python, уже содержит API

Упражнения

1. Присвойте строку 'This is a test of the emergency text system' переменной test1 и запишите переменную test1 в файл с именем test.txt.

2. Откройте файл test.txt и считайте его содержимое в строку test2. Совпадают ли строки test1 и test2?

3. Сохраните следующие несколько строк в файл books.csv. Обратите внимание на то, что, если поля разделены запятыми, вам нужно заключить поле в кавычки, если оно содержит запятую:

author,book

J R R Tolkien,The Hobbit

Lynne Truss,"Eats, Shoots & Leaves"

4. Используйте модуль csv и его метод DictReader, чтобы считать содержимое файла books.csv в переменную books. Выведите на экран значения переменной books. Обработал ли метод DictReader кавычки и запятые в заголовке второй книги?

5. Создайте CSV-файл books.csv и запишите его в следующие строки:

title,author,year

The Weirdstone of Brisingamen,Alan Garner,1960

Perdido Street Station,China Miéville,2000

Thud!Terry Pratchett,2005

The Spellman Files,Lisa Lutz,2007

Small Gods,Terry Pratchett,1992

6. Используйте модуль sqlite3, чтобы создать базу данных SQLite books.db и таблицу books, содержащую следующие поля: title (text), author (text) и year (integer).

7. Считайте данные из файла books.csv и добавьте их в таблицу book.

8. Считайте и выведите на экран графу title таблицы book в алфавитном порядке.

9. Считайте и выведите на экран все графы таблицы book в порядке публикации.

10. Используйте модуль sqlalchemy, чтобы подключиться к базе данных sqlite3 books.db, которую вы создали в упражнении 6. Как и в упражнении 8, считайте и выведите на экран графу title таблицы book в алфавитном порядке.

11. Установите сервер Redis и библиотеку Python redis (с помощью команды pip install redis) на свой компьютер. Создайте хеш redis с именем test, содержащий поля count (1) и name ('Fester Bestertester'). Выведите все поля хеша test.

12. Увеличьте поле count хеша test и выведите его на экран.

Глава 9. Распутываем Всемирную паутину

На французско-швейцарской границе располагается CERN — Институт исследования физики частиц, он может показаться хорошим убежищем для злодея из франшизы о Джеймсе Бонде. К счастью, его задача заключается не в получении мирового господства, а в том, чтобы понять принципы работы Вселенной. Это всегда приводило к тому, что CERN генерировал удивительные объемы данных, заставляя физиков и компьютерщиков держать темп.

В 1989 году английский ученый Тим Бернерс-Ли (Tim Berners-Lee) впервые внес предложение помочь распространять информацию внутри CERN и исследовательского сообщества. Он назвал его World Wide Web (Всемирная паутина) и довольно быстро выделил три основные идеи, которые должны были лечь в основу ее дизайна:

• HTTP (Hypertext Transfer Protocol, протокол передачи гипертекста) — спецификация для веб-клиентов и серверов для обмена запросами и ответами;

• HTML (Hypertext Markup Language, гипертекстовый язык разметки) — формат для представления результатов;

• URL (Uniform Resource Locator, единообразный локатор ресурса) — способ уникально обозначить сервер и ресурс на этом сервере.

В самом простом варианте использования веб-клиент (я думаю, что Бернерс-Ли был первым, кто употребил слово «браузер») соединяется с веб-сервером с помощью протокола HTTP, запрашивает URL и получает HTML.

Он написал первый браузер и сервер на компьютере NeXT, изобретенном небольшой компанией, которую основал Стив Джобс (Steve Jobs) во время своего отдыха от Apple Computer. Известность Всемирной паутины значительно возросла в 1993-м, когда группа студентов Иллинойсского университета (University of Illinois) выпустила браузер Mosaic (для Windows, Macintosh и Unix) и сервер NCSA httpd. Когда я загрузил их и начал создавать сайты, я даже не догадывался, что Всемирная паутина и Интернет станут частью повседневной жизни. В то время Интернет все еще был некоммерческим официально, в мире существовало всего 500 известных веб-серверов (http://home.web.cern.ch/about/birth-web). К концу 1994 года их количество увеличилось до 10 000. Интернет был открыт для коммерческого использования, и авторы браузера Mosaic основали компанию Netscape, чтобы писать коммерческие веб-приложения. Компания Netscape стала достоянием общественности как часть возникшего в то время интернет-безумия, и взрывной рост Всемирной паутины не остановился до сих пор.

Практически каждый язык программирования был использован для написания веб-клиентов и веб-серверов. Динамические языки Perl, PHP и Ruby стали особенно популярными. В этой главе я покажу вам, почему Python является особенно хорошим языком для работы в Интернете на любом из следующих уровней:

• клиенты для удаленного доступа;

• серверы, предоставляющие данные для сайтов и веб-API;

• веб-API и сервисы, позволяющие обмениваться данными другими способами, отличающимися от просматриваемых веб-страниц.

Выполняя упражнения в конце главы, мы создадим настоящий интерактивный сайт.

Веб-клиенты

Низкоуровневая система проводящих путей Интернета называется Transmission Control Protocol/Internet Protocol (протокол управления передачей/интернет-протокол), или просто TCP/IP (в подразделе «TCP/IP» раздела «Сети» главы 11 этот протокол рассматривается более подробно). Он перемещает байты между компьютерами, но не обращает внимания на то, что они значат. Это работа высокоуровневых протоколов — определений синтаксиса для некоторых целей. HTTP — это стандартный протокол для обмена данными в Сети.

Всемирная паутина — это клиент-серверная система. Клиент делает запрос серверу: он открывает соединение TCP/IP, отправляет URL и другую информацию с помощью HTTP и получает ответ.

Формат ответа также определяется протоколом HTTP. Он включает в себя статус запроса и (в том случае, если запрос выполнен успешно) данные и формат ответа.

Самый известный веб-клиент — это браузер. Он может создавать HTTP-запросы несколькими способами. Вы можете инициировать запрос вручную, написав URL в адресной строке или щелкнув на ссылке на веб-странице. Очень часто для отображения сайта используются возвращаемые данные: HTML-документы, файлы JavaScript, файлы CSS и изображения, — но данные могут быть любого типа, в том числе и не предназначенные для отображения.

Важный аспект HTTP — этот протокол не имеет состояния. Каждое создаваемое вами соединение HTTP не зависит от других. Это упрощает базовые операции, но усложняет другие. Рассмотрим несколько примеров таких усложнений.

• Кэширование. Удаленный контент, который не меняется, должен быть сохранен веб-клиентом и использован для того, чтобы не загружать его с сервера снова.

• Сессии. Интернет-магазин должен запоминать содержимое вашей корзины.

• Аутентификация. Сайты, которые требуют ваши имя пользователя и пароль, должны запоминать их, пока вы авторизованы.

Решения для этих усложнений включают в себя cookie, в которых сервер отправляет клиенту довольно специфическую информацию, позволяющую их распознать, когда клиент отправляет cookie назад.

Тестируем с telnet

HTTP — это протокол, основанный на тексте, поэтому вы можете вручную вводить его код во время тестирования. Древняя программа telnet позволяет вам подключиться к любому серверу и порту и вводить команды.

Запросим у любимого многими тестового сайта Google базовую информацию о его домашней странице. Введем следующее:

$ telnet www.google.com 80

Если на порте 80 по адресу google.com существует веб-сервер (я думаю, что это беспроигрышный вариант), telnet выведет на экран подтверждающую информацию, а затем отобразит пустую строку, которая является приглашением ввести что-то еще:

Trying 74.125.225.177…

Connected to www.google.com.

Escape character is '^]'.

Теперь введем настоящую команду HTTP для telnet, которую он отправит на веб-сервер Google. Самая распространенная команда HTTP (ее использует ваш браузер каждый раз, когда вы вводите URL в адресной строке) — это GET. Она позволяет получить содержимое заданного ресурса вроде HTML-файла и возвращает его клиенту. Для первой проверки мы используем команду HTTP HEAD, которая просто получает некую базовую информацию о ресурсе:

HEAD / HTTP/1.1

Конструкция HEAD / отправляет запрос HTTP HEAD глагол (команда), чтобы получить информацию о домашней странице (/). Добавьте дополнительный символ возврата каретки, чтобы отправить пустую строку, тогда удаленный сервер будет знать, что вы закончили и ждете ответа. Вы получите ответ вроде следующего (мы обрезали некоторые длинные строки с помощью многоточий, чтобы они не вываливались за пределы страницы):

HTTP/1.1 200 OK

Date: Sat, 26 Oct 2013 17:05:17 GMT

Expires: -1

Cache-Control: private, max-age=0

Content-Type: text/html; charset=ISO-8859-1

Set-Cookie: PREF=ID=962a70e9eb3db9d9:FF=0:TM=1382807117:LM=1382807117:S=y…

··expires=Mon, 26-Oct-2015 17:05:17 GMT;

··path=/;

··domain=.google.com

Set-Cookie: NID=67=hTvtVC7dZJmZzGktimbwVbNZxPQnaDijCz716B1L56GM9qvsqqeIGb…

··expires=Sun, 27-Apr-2014 17:05:17 GMT

Web Clients··|··219··path=/;

··domain=.google.com;

··HttpOnly

P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts…

Server: gws

X–XSS-Protection: 1; mode=block

X-Frame-Options: SAMEORIGIN

Alternate-Protocol: 80:quic

Transfer-Encoding: chunked

Так выглядят заголовки ответов HTTP и их значения. Некоторые из них, вроде Date или Content-Type, обязательны. Другие, наподобие Set-Cookie, используются для отслеживания вашей активности в течение нескольких посещений (мы поговорим об управлении состоянием немного позже). Когда вы делаете запрос HTTP HEAD, то получаете в ответ только заголовки. Если вы использовали команды HTTP GET или HTTP POST, также получите данные от домашней страницы (смесь HTML, CSS, JavaScript и всего прочего, что Google решит разместить на своей домашней странице).

Я не хочу, чтобы вы зависли в telnet. Чтобы его закрыть, введите следующее:

q

Стандартные веб-библиотеки Python

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

• http управляет всеми деталями клиент-серверного взаимодействия HTTP:

• client выполняет всю работу на стороне клиента;

• server помогает вам написать веб-сервер;

• cookies и cookiejar управляют cookies, которые сохраняют данные между посещениями;

• urllib работает на базе http:

• request обрабатывает клиентские запросы;

• response обрабатывает ответы сервера;

• parse разбивает URL на части.

Воспользуемся стандартной библиотекой, чтобы получить что-нибудь с сайта. URL в следующем примере возвращает случайную текстовую цитату — это что-то вроде печенья с предсказанием:

>>> import urllib.request as ur

>>> url = 'http://www.iheartquotes.com/api/v1/random'

>>> conn = ur.urlopen(url)

>>> print(conn)

Из официальной документации (http://bit.ly/httpresponse-docs) мы можем узнать, что conn является объектом класса HTTPResponse, содержащим несколько методов, и его метод read() предоставит нам информацию о веб-странице:

>>> data = conn.read()

>>> print(data)

b'You will be surprised by a loud noise.\r\n\n[codehappy]

http://iheartquotes.com/fortune/show/20447\n'

Этот небольшой фрагмент кода открыл соединение TCP/IP с удаленным сервером цитат, создал запрос HTTP и получил HTTP-ответ. Ответ содержит не только данные о странице (цитату). Одна из наиболее важных частей ответа — это код статуса HTTP:

>>> print(conn.status)

200

Значение 200 означает, что все прошло гладко. Существуют десятки кодов статуса HTTP, объединенных в пять диапазонов в соответствии с их первой цифрой (сотни):

• 1xx (информация). Сервер получил запрос, но имеет некоторую дополнительную информацию для клиента;

• 2xx (успех). Сработало, каждый код успеха, кроме 200, сообщает дополнительные детали;

• 3xx (перенаправление). Ресурс был перемещен, поэтому ответ возвращает клиенту новый URL;

• 4xx (ошибка клиента). Некоторые проблемы на стороне клиента вроде знаменитой ошибки 404 (ресурс не найден). Код 418 (I’m a teapot) был первоапрельской шуткой;

• 5xx (ошибка сервера). Код 500 — это общая ошибка. Вы можете встретить ошибку 502 (ошибочный шлюз), если произошел разрыв связи между веб-сервером и машинным интерфейсом.

Веб-серверы могут отправлять данные назад в том формате, который им нравится. Обычно это HTML (а также немного CSS и JavaScript), но в нашем примере с печеньем с предсказанием это простой текст. Формат данных указывается значением заголовка ответа HTTP Content-Type, который мы также видели в примере с google.com:

>>> print(conn.getheader('Content-Type'))

text/plain

Строка text/plain является MIME-типом и означает, что данные пришли в простом текстовом формате. MIME-тип для HTML, который отправил пример с google.com, — это text/html. В этой главе я покажу вам еще несколько MIME-типов.

Из любопытства взглянем, какие еще заголовки HTTP были нам отправлены:

>>> for key, value in conn.getheaders():

…·····print(key, value)

Server nginx

Date Sat, 24 Aug 2013 22:48:39 GMT

Content-Type text/plain

Transfer-Encoding chunked

Connection close

Etag "8477e32e6d053fcfdd6750f0c9c306d6"

X-Ua-Compatible IE=Edge,chrome=1

X-Runtime 0.076496

Cache-Control max-age=0, private, must-revalidate

Помните тот пример работы с telnet, который я показывал ранее? Теперь наша библиотека Python может разбирать заголовки этих HTTP-запросов и размещать их в словарь. Date и Server кажутся довольно очевидными, некоторые другие — нет. Полезно знать, что HTTP имеет набор стандартных заголовков вроде Content-Type и множество опциональных.

За пределами стандартной библиотеки: requests

В начале главы 1 вы увидели программу, которая получает доступ к YouTube API с помощью стандартных библиотек urllib.request и json. После него был другой пример, который использовал стороннюю библиотеку requests. Он был короче и проще для понимания.

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

Для начала вам нужно установить библиотеку requests в свое окружение Python. Из окна терминала (пользователи Windows должны ввести cmd, чтобы получить к нему доступ) введите следующую команду, чтобы установщик пакетов Python pip загрузил последнюю версию пакета и установил ее:

$ pip install requests

Если у вас возникли трудности, прочтите приложение Г, чтобы узнать подробности о том, как установить и использовать pip.

Переделаем предыдущий вызов сервиса с цитатами с помощью библиотеки requests:

>>> import requests

>>> url = 'http://www.iheartquotes.com/api/v1/random'

>>> resp = requests.get(url)

>>> resp

>>> print(resp.text)

I know that there are people who do not love their fellow man, and I hate

people like that!

····-Tom Lehrer, Satirist and Professor

[codehappy] http://iheartquotes.com/fortune/show/21465

Этот пример не сильно отличается от предыдущего, где использовалась библиотека urllib.request.urlopen, но он кажется чуть менее объемным.

Веб-серверы