четверг, 13 сентября 2012 г.

Краулер ссылок и автоматизация процесса снятия скриншотов

Перед нами стояла задача: автоматизировать процесс снятия скриншотов со страничек web-приложения - некоторого сайта. Требовалось:
  1. Получать стартовый URL.
  2. Искать на страничке, полученной по стартовому URL все ссылки на другие странички.
  3. Переходить по всем найденным ссылкам и делать скриншоты со всех страничек.
  4. Ограничивать глубину вложенности при прохождении найденных ссылок.
Решить задачу можно было различными способами. Так как объектом исследования является web-приложение (работающее в браузерах), было решено следующее.
  1. Воспользоваться средствами Selenium WebDriver, который позволяет контролировать работу web-приложения, в том числе делать скриношоты содержимого окна браузеров.
  2. Поиск ссылок реализовать из CSS, используя библиотеку-парсер lxml, и по xPath, используя xPath-парсер  Selenium WebDriver.
  3. Ограничить переход по "дереву ссылок" через написание рекурсивных функций, с уменьшающимся аргументом для "глубины" поиска ссылок.
Для этого была написана небольшая программа "скрин-шутер".

1. Краткое описание.

Screen shooter - консольная программа, написанная на Python 3.2., предназначенная для автоматизации снятия скриншотов сайта.
Перед использованием программы необходимо установить и настроить Selenium WebDriver для Python 3.2.:
Программа ищет все ссылки на стартовой страничке, задаваемой ключом -u, перемещается по ним и делает скриншоты.
Глубина прохождения ссылок ограничивается ключом -d и берется из промежутка [0, +oo), по умолчанию 1: снимать скриншоты со стартовой странички и всех страничках по найденным на ней ссылкам. 
В программе реализован древовидный поиск ссылок. При этом стартовая страничка имеет наивысший уровень глубины, является верхним узлом дерева ссылок, а найденные на ней ссылки на другие странички, являются узлами-потомками с уровнем глубины на единицу меньше. Таким образом, отсчет уровней идет сверху вниз до нуля.
Используя ключ -m можно указать 2 метода поиска ссылок на страничках: CSS (по умолчанию) - более медленный (использует библиотеку lxml), xPath - более быстрый (использует библиотеку WebDriver).
Ключом -b можно указать открываемые браузеры (*firefox, *chrome, *ie), *firefox по умолчанию. Использование приложенных к программе драйверов для Chrome и IE возможно только в Windows.
Скриншоты кладутся в каталог <корень_проекта>/screens/<дата_время>/ в виде файлов depth_<глубина>_index_<номер>.png.


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

2. Программный код.

Программный код доступен в zip-архиве по ссылке: 
https://docs.google.com/open?id=0B-1rf8K04ZS5UmQ5dWNzZWMtWXc
Код на GitHub: 
https://github.com/Tim55667757/ScreenShooter

Структура проекта

ScreenShooter - корень проекта. 
        /browser_drivers - каталог с Windows-драйверы для chrome и ie. 
        /ff_profile - каталог для профиля мозиллы (пустой по умолчанию). 
        screen_shooter.py - реализация программы. 
        readme.txt - актуальная информация по проекту.

Содержимое модуля screen_shooter.py

Глобальные переменные:
startURL = 'http://some_test_site/' # Стартовый URL.
depth = 1 # Глубина прохождения по ссылкам.
method = 'CSS' # Метод поиска ссылок, ('CSS' или 'xPath').
linksTree = {} # Словарь для дерева ссылок.
workDir = os.path.abspath(os.curdir) # Рабочая директория проекта, относительно которой строятся другие пути.
resultPath = workDir + '/screens' # Путь к каталогу со скриншотами, относительно рабочей директории.
browser = None # Переменная для браузера открываемого Selenium WebDriver.
browserString = '*firefox' # Строка для запуска браузера ('*firefox', '*ie', '*chrome'). '*firefox' по умолчанию.

Функции:
ParseArgs() # Парсер аргументов командной строки.
LinksCrawlerByXPath(startURL, depth, tree) # Поиск ссылок по xPath.
LinksCrawlerByCSS(startURL, depth, tree) # Поиск ссылок в CSS.
GetScreen(nameOfScreen) # Снятие скриншота и сохранение в указанный файл.
MakeAllScreens(screenDir, depth, tree) # Функция для прохождения по всему дереву ссылок и снятие скриншота страничек.
OpenBrowser(opTimeout, browserString, ffProfile) # Открытие браузера с указанным таймаутом для операций.
CloseBrowser() # Закрытие браузера.
Main() # Открытие браузера, переход на стартовый URL, поиск ссылок, хождение по ссылкам и снятие скриншотов.

3. Запуск программы.

Параметры для консольного запуска представлены ключами:
КлючСлово        Описание
-h
--helpПоказать подсказку по опциям.
-u--URLСтартовый URL для скрин-шутера.
-d--depthГлубина спуска по ссылкам [0..+оо). Стартовый URL имеет наивысший индекс, спуск идет до нуля.
-m
--method
'CSS' для использования lxml CSS finder (медленнее), 'xPath' для использования WebDriver XPath finder (быстрее).
-b
--browserСтрока браузера (*firefox, *chrome, *ie), показывающая, какой браузер запустить.
Если ключи не указаны, используются настройки переменных в программе по умолчанию. Ключи, указанные при запуске в консоли имеют больший приоритет, чем настройки по умолчанию!
Находясь в корне проекта для запуска программы можно использовать команды:

В результате выполнения одной команды из примеров:
python screen_shooter.py -u http://forworktests.blogspot.com/ -d 0
получим скриншот одной странички данного блога, сделанной в браузере firefox, следующего вида: