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

Только что мы рассмотрели традиционные веб-клиенты и серверные приложения, потребляющие и генерирующие HTML-страницы. Всемирная паутина оказалась мощным способом объединять приложения и данные во многих форматах, не только HTML.

Модуль webbrowser

Начнем с небольшого сюрприза. Запустите сессию Python в окне терминала и введите следующую строку:

>>> import antigravity

Эта строка скрыто вызывает модуль стандартной библиотеки webbrowser и перенаправляет ваш браузер по просветительской ссылке. (Если вы по какой-то причине не видите ее, посетите сайт xkcd.)

Вы можете использовать этот модуль непосредственно. Эта программа загружает страницу главного сайта о Python в ваш браузер:

>>> import webbrowser

>>> url = 'http://www.python.org/'

>>> webbrowser.open(url)

True

Этот код откроет ее в новом окне:

>>> webbrowser.open_new(url)

True

А этот — на новой вкладке, если ваш браузер поддерживает вкладки:

>>> webbrowser.open_new_tab('http://www.python.org/')

True

Модуль webbrowser заставляет браузер делать всю работу.

API для Сети и Representational State Transfer

Зачастую данные доступны только внутри веб-страниц. Если вы хотите получить к ним доступ, вам нужно получить доступ к странице через браузер и прочитать ее. Если с момента вашего последнего визита авторы сайта внесли какие-нибудь изменения, местоположение и стиль данных могли измениться.

Вместо того чтобы публиковать веб-страницы, вы можете предоставить доступ к данным через веб-интерфейс программирования приложений (Application Programming Interface, API). Клиенты получают доступ к вашему сервису, делая запросы к URL, и получают ответы, содержащие статус и данные. Вместо HTML-страниц данные имеют формат, который удобнее использовать в других программах вроде JSON и XML (в главе 8 содержится более подробная информация о форматах).

Понятие «передача состояния представления» (Representational State Transfer, REST) было определено Роем Филдингом (Roy Fielding) в его докторской диссертации. Многие продукты имеют REST-интерфейс или интерфейс RESTful. На практике это часто означает, что они имеют веб-интерфейс — определения URL, предназначенные для доступа к веб-сервису.

Служба RESTful использует глаголы HTTP определенными способами, описанными далее:

• HEAD — получает информацию о ресурсе, но не его данные;

• GET — как подразумевает имя, GET получает данные ресурса с сервера. Это стандартный метод, используемый вашим браузером. В любое время, когда вы видите URL с вопросительным знаком (?), за которым следует несколько аргументов, вы можете распознать запрос GET. GET не должен использоваться для создания, изменения или удаления данных;

• POST — этот глагол обновляет данные на сервере. Он часто используется для HTML-форм и сетевых API;

• PUT — этот глагол создает новый ресурс;

• DELETE — этот глагол говорит сам за себя: DELETE удаляет. Мы за правдивость в рекламе!

Клиент RESTful также может запрашивать содержимое одного или нескольких типов с помощью заголовков запроса HTTP. Например, сложный сервис с интерфейсом REST может принимать и возвращать данные в строках JSON.

JSON

В главе 1 были показаны два фрагмента кода, с помощью которых мы получали информацию о популярных видео на YouTube, а в главе 8 мы узнали о JSON. JSON особенно хорошо подходит для создания веб-серверов и обмена данными. Этот формат наиболее популярен в сетевых API вроде OpenStack.

Поиск и выборка данных

Иногда вам нужно получить немного больше информации — рейтинг фильма, цену акции или доступность продукта, — но информация доступна только на HTML-страницах, при этом она окружена рекламой и посторонним контентом.

Вы можете извлечь необходимую информацию вручную, сделав следующее.

1. Введите URL в браузер.

2. Подождите, пока загрузится удаленная страница.

3. Просмотрите отображенную страницу на предмет необходимой информации.

4. Запишите ее где-нибудь.

5. Повторите процесс для связанных URL.

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

Если вам нужно мощное решение, объединяющее в себе возможности поиска и выборки данных, вам стоит загрузить Scrapy (http://scrapy.org/):

$ pip install scrapy

Scrapy — это фреймворк, а не модуль, в отличие от BeautifulSoup. Он имеет больше возможностей, но зачастую его трудно настроить. Чтобы узнать больше о Scrapy, прочтите документацию (http://scrapy.org/) или познакомьтесь с ним по адресу http://bit.ly/using-scrapy.

Получаем HTML-код с помощью BeautifulSoup

Если у вас уже есть HTML-данные с сайта и вы просто хотите извлечь оттуда данные, вам подойдет BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/). Анализировать HTML труднее, чем кажется. Это происходит потому, что большая часть HTML-кода на общедоступных веб-страницах технически некорректна: незакрытые теги, неправильная вложенность и прочие усложнения. Если вы пытаетесь написать свой HTML-анализатор с помощью регулярных выражений, которые мы рассматривали в главе 7, вы довольно скоро столкнетесь с подобным беспорядком.

Для того чтобы установить BeautifulSoup, введите следующую команду (не забудьте поставить в конце четверку, иначе pip попробует установить более старую версию и, возможно, выдаст ошибку):

$ pip install beautifulsoup4

Теперь воспользуемся им для того, чтобы получить все ссылки с веб-страницы. Элемент HTML a представляет собой ссылку, а href — ее атрибут, который представляет собой место назначения ссылки. В следующем примере мы определим функцию get_links(), которая делает грязную работу, и основную программу, которая получает один или несколько URL как аргументы командной строки:

def get_links(url):

····import requests

····from bs4 import BeautifulSoup as soup

····result = requests.get(url)

····page = result.text

····doc = soup(page)

····links = [element.get('href') for element in doc.find_all('a')]

····return links

if __name__ == '__main__':

····import sys

····for url in sys.argv[1:]:

········print('Links in', url)

········for num, link in enumerate(get_links(url), start=1):

············print(num, link)

········print()

Я сохранил эту программу под именем links.py, а затем запустил с помощью данной команды:

$ python links.py http://boingboing.net

Взгляните на первые несколько отображенных строк:

Links in http://boingboing.net/

1 http://boingboing.net/suggest.html

2 http://boingboing.net/category/feature/

3 http://boingboing.net/category/review/

4 http://boingboing.net/category/podcasts

5 http://boingboing.net/category/video/

6 http://bbs.boingboing.net/

7 javascript: void(0)

8 http://shop.boingboing.net/

9 http://boingboing.net/about

10 http://boingboing.net/contact

Упражнения

1. Если вы еще не установили Flask, сделайте это сейчас. Это также установит werkzeug, jinja2 и, возможно, другие пакеты.