Book Pages

Тронутые плесенью страницы

Стареют книги… Нет, не переплет,
Не тронутые плесенью страницы,
А то, что там, за буквами, живет
И никому уж больше не приснится.

-- Вс. А. Рождественский. (1967)

Как бы ни менялись с годами веб-интерфейсы, основная схема навигации в информационном океане остается неизменной: от списка к элементам. Варианты:

  • каталог товаров и товары;
  • список новостей и новостные статьи;
  • результаты поиска в поисковой системе;
  • страны и отели в них...

Иерархия бывает многоуровневой, например:

  • страны -> города -> отели в городах;
  • категории товаров --> список товаров --> товары.

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

Соответственно, скрапер, чья цель — собрать всю имеющуюся информацию с сайта или его раздела, почти всегда двигается "сверху вниз":

  1. Идет по списку, собирая ссылки.
  2. Открывает каждый полученный адрес, чтобы собрать подробную информация о чем бы то ни было.

Чаще всего эти две задачи выполняются одновременно. Ведь, каталоги порой состоят из многих тысяч элементов. То есть, один процесс 1 идет по каталогу, собирает ссылки и складывает их в очередь, а второй снимает из той же очереди ссылку за ссылкой и обходит страницы. О многозадачности мы еще поговорим, а сейчас хотелось бы сосредоточиться на первой задаче — обходе каталога.

Каталоги почти никогда не ограничены одной страницей. Чтобы обойти все, краулер работает по стандартной схеме.

Pages Scrapping Algorithm

Как определить, остались ли еще страницы и каков адрес следующей? Технику "листания" продемонстрирую на мобильной версии сайта http://amazon.com2.

Amazon catalogue - mobile versdion

Итак, задача — написать код, способный безошибочно находить на этой и всех остальных страницах ссылку "Next". Судя по исходному коду страницы, навигация располагается в таблице, чей CSS-класс имеет недвусмысленное название paginationLinks.

Amazon pagination in firebug

Можно считать, что блок навигации найден. Осталось отыскать ссылку, которая ведет на следующую страницу. Это ничуть не сложнее. BeautifulSoup позволяет искать элемент по его внутреннему тексту при помощи регулярных выражений. Упрощенный код может выглядеть так:

import requests
from bs4 import BeautifulSoup
import re

USER_AGENT = 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16'

url = 'http://www.amazon.com/gp/aw/s/ref=mh_283155_dri_1_sa?rh=i%3Astripbooks%2Cn%3A283155%2Cn%3A283155&ie=UTF8&qid=1443857198&node=283155'
resp = requests.get(url, headers={'User-Agent': USER_AGENT})
soup = BeautifulSoup(resp.text)
table = soup.find('table', class_='paginationLinks')
link = table.find('a', text=re.compile(r'Next'), href=True)
next_page = link.get('href')

print "Next Page: %s" % next_page

Результат:

Next Page: 
/gp/aw/s/ref=is_pn_1/187-6401709-5391227?rh=n%3A283155&page=2&ie=UTF8&qid=1443871791

Если присмотреться к этому адресу, нетрудно заметить, что в нем есть параметр page с номером страницы. Что если подставить другой номер? Работает! Адрес:

http://www.amazon.com//gp/aw/s/ref=is_pn_6?rh=n%3A283155&page=12&ie=UTF8&qid=1443872580

выдает двенадцатую страницу. Теперь, зная, по какому правилу Amazon формирует переходы, мы можем вообще не извлекать адрес перехода на следующую страницу с текущей. Но тогда возникнет новая проблема: как определить, что страницы кончились?

В разделе, который мы рассматриваем, 120 страниц. На последней из них текст "Next" в навигационном блоке не является ссылкой: он располагается внутри "span"-а.

Amazon pagination - last page in firebug

Написать код, проверяющий "условие выхода", предоставляю читателю.

Ajax

Сложнее всего проходить каталоги, где "листалка" работает на AJAX-е. В этом случае перехода со страницы на страницу нет, вместо этого содержание одной и той же страницы обновляется JavaScript-ом. К примеру, в каталоге сайта http://flipkart.com кнопка "VIEW MORE" не содержит никаких ссылок.

Flipkart AJAX example

Что делать в этом случае?

Открываем вкладку Firebug "Сеть". Нажимаем на кнопку "VIEW MORE". В окне Firebug-а появляются адреса запросов, которые делает JavaScript, чтобы получить новое содержание.

Flipkart AJAX request

Копируем адрес запроса, открывает новое окно (или вкладку) Firefox-а, вставляем туда этот адрес и смотрим, что возвращается.

Flipkart AJAX request

Наш контент представляет собой "голый" HTML, без каких-либо украшательств. Но тем лучше для паука — не надо продираться через лишнюю разметку.


  1. Технически, это могут быть отдельные процессы в операционной системе, "нити" (threads) в рамках одного процесса или же программы, работающие на разных машинах. 

  2. Плагин для браузера User Agent Switcher позволяет менять в браузере идентификатор "User-Agent". Чтобы увидеть мобильную версию Amazon-а, я включил "iPhone 3.0"

social

Яндекс.Метрика