При просмотре элементов веб–страницы все ее содержимое может быть разбито на контейнеры внутри контейнеров.
Для «выскребания» веб–страниц вам необходимо узнать немного побольше о различных типах элементов, которые могут встречаться в HTML–документе. Например, элемент <table> охватывает всю таблицу, которая содержит в себе элементы <tr> (строка таблицы), которые формируют строки, а строки, в свою очередь, имеют элементы <td> (данные таблицы) для каждой ячейки. Наиболее часто вы будете сталкиваться с элементом <div>, который, по сути, обозначает какой–либо блок контента. Легче всего понять эти элементы можно, используя панель разработчикавашего браузера, которая позволит вам посмотреть, из чего состоит код, лежащий в основе той или иной части веб–страницы.
Тэги работают как разделители, обозначая начало и конец определенного блока. Например, <em> означает начало выделенного курсивом текста, а тэг </em> означает конец этого блока. Все просто.
Рис 55. The International Atomic Energy Agency’s (IAEA) portal (news.iaea.org)
Пример: сбор информации о происшествиях в ядерной отрасли с использованием кода на языке Python
NEWS — это портал Международного агентства по атомной энергии (МАГАТЭ), посвященный происшествиям в ядерной отрасли по всему миру (и являющийся уверенным кандидатом в члены Клуба роковых названий!). На этой веб–странице происшествия представлены в виде простого, похожего на блог списка, который может быть легко извлечен.
Для начала создайте новый «скребок» на языке Python на сайте ScraperWiki, в результате чего вы получите почти пустую область текста, в которой будет находиться только вспомогательный код. В другом окне откройте браузер, откройте там сайт МАГАТЭи затем откройте в этом браузере панель разработчика. В режиме просмотра «Элементы» попытайтесь найти HTML–элементы заголовка одной из новостей. Панель разработчика браузера помогает связывать элементы веб–страницы с лежащим в их основе HTML–кодом.
Изучая эту страницу, вы поймете, что заголовки являются элементами <h4>, находящимися внутри элемента <table>. Каждое событие — это строка <tr>, которая также содержит описание и дату. Если мы хотим извлечь заголовки всех событий, мы должны найти способ, который позволит нам последовательно выбрать каждую строку таблицы и извлечь из них текст, находящийся внутри элементов, обозначающих заголовки.
Чтобы преобразовать этот процесс в код, мы должны понять для себя все все его шаги. Чтобы лучше понять, что это за этапы, давайте сыграем в простую игру. В окне ScraperWiki попробуйте написать для себя индивидуальные инструкции по каждому шагу, который вы собираетесь сделать в ходе написания этого «скребка», наподобие пунктов в кулинарном рецепте (отбейте каждую строку хэш–кодом, чтобы дать понять языку Python, что это не настоящий компьютерный код). Например:
# Просмотреть все строки в таблице
# Unicorn не должен выходить за левый край
Постарайтесь быть как можно более точным и не предполагайте, что программа что–либо знает о странице, которую вы пытаетесь «выскрести».
Теперь, когда вы написали свой первый псевдо–код, давайте сравним его с реальным кодом нашего первого «скребка»:
import scraperwiki
from lxml import html
В этой первой части мы импортируем имеющийся функционал из библиотек — кусочки ранее написанных кодов. scraperwiki предоставит нам возможность скачивать веб–сайты, а lxml является инструментом структурного анализа HTML– документов. Хорошая новость: если вы пишете код «скребка» на языке Python с помощью сайта ScraperWiki, эти две строки всегда будут одинаковыми.
url = »http://www–news.iaea.org/EventList.aspx»
doc_text = scraperwiki.scrape(url)
doc = html.fromstring(doc_text)
Далее код вводит имя (переменную): url и в качестве его значения устанавливает URL–адрес страницы МАГАТЭ. Это говорит «скребку» о том, что такой объект существует, и что мы хотим уделить ему внимание. Обратите внимание, что URL–адрес находится в кавычках, так как он является не частью программного кода, а строкой, последовательностью символов.
Затем мы используем переменную url в качестве вводной для функции scraperwiki.scrape. Эта функция будет выполнять некую определенную работу — в данном случае она будет загружать веб–страницу. Когда эта работа будет выполнена, ее результаты будут переданы другой переменной, doc_text. doc_text теперь будет содержать актуальный текст веб–сайта — не тот, который вы видите в браузере при посещении страницы, а исходный код, включая теги. Так как осуществлять структурный анализ такого текста не совсем просто, мы используем другую функцию, html.fromstring, для создания особого представления, в котором мы можем легко находить элементы, так называемую объектную модель документа (document object model, DOM).
for row in doc.cssselect(»#tblEvents tr»):
link_in_header = row.cssselect(»h4 a»).pop()
event_title = link_in_header.text
print event_title
На этом последнем этапе мы используем DOM для поиска каждой строки в нашей таблице и извлечения из нее заголовка события. Здесь используются две новые концепции: петля и выбор элементов (.cssselect). Петля делает то, что и подразумевается ее названием: она обходит список блоков, назначая каждому из них временное имя (в данном случае это строки) и затем выполняет для каждого из них намеченные действия.
Вторая новая концепция, выбор элементов, использует специальный язык для поиска элементов в документе. Для добавления к HTML–элементам информации о их расположении обычно используются CSS–селекторы, и их же можно использовать для точного отбора этих элементов на странице. В данном случае (строка 6) мы выбираем #tblEvents tr, вследствие чего каждый тэг <tr> в элементе таблицы будет сопоставляться с ID tblEvents (хэш здесь просто обозначает ID). В результате мы получим список элементов <tr>.
То же мы наблюдаем и в следующей строке (строка 7), в которой мы применяем другой селектор для поиска всех тэгов <a> (обозначающих гиперссылку) внутри <h4> (заголовок). Здесь мы хотим искать только один элемент (в каждой строке имеется только один заголовок), поэтому мы должны извлечь его из вершины списка, созданного нашим селектором с помощью функции .pop().
Обратите внимание, что некоторые элементы в DOM содержат настоящий текст, т. е. текст, не являющийся частью языка разметки, который мы можем извлечь, воспользовавшись кодом [element].text, размещенным в строке 8. И, наконец, в строке 9 мы направляем этот текст в консоль ScraperWiki. Если вы теперь запустите ваш «скребок», то в меньшем по размеру окошке начнут появляться названия событий с сайта МАГАТЭ.
Рис 56. A scraper in action (ScraperWiki)
Вы видите работу простейшего «скребка»: он загружает веб–страницу, преобразует ее в DOM и затем предоставляет вам возможность выбирать и извлекать определенные элементы. На основе данного шаблона вы можете попробовать решить остальные вопросы, используя документацию ScraperWiki и языка Python:
Можно ли найти адрес ссылки, находящейся в заголовке каждого события?
Можно ли выбрать небольшой контейнер, который содержит дату и место, используя CSS–имя его класса, и затем извлечь текст этого элемента?
ScraperWiki предлагает небольшую базу данных для каждого «скребка», в которую вы можете сохранить ваши результаты (код), скопируйте соответствующий пример из документов ScraperWiki и адаптируйте его так, чтобы он сохранял названия, ссылки и даты событий.
Список событий включает в себя много страниц, можно ли осуществить наш поиск по всем страницам, чтобы получить информацию и о старых событиях?
Когда вы будете решать эти проблемы, изучите ScraperWiki: в имеющихся на этом ресурсе «скребках» можно найти много полезных примеров, а зачастую и довольно интересных данных. Таким образом, вам не обязательно создавать свой «скребок» с нуля: просто выберите подходящий и адаптируйте его под свои задачи.