CoderCastrov logo
CoderCastrov
Парсер

5 полезных советов при работе с Python Scrapy

5 полезных советов при работе с Python Scrapy
просмотров
6 мин чтение
#Парсер
Table Of Content

Быстрые и простые советы, чтобы улучшить ваш опыт веб-парсинга с использованием Scrapy

В то время как существует несколько учебников по Python Scrapy, я замечаю, что большинство из них не охватывают эти низко висящие плоды, которые могут значительно улучшить опыт разработчика веб-парсинга.

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


TL;DR:

  • Во время разработки используйте HTTPCache
  • Всегда используйте AutoThrottle
  • Используйте API сайтов, если они доступны
  • Используйте bulk insert для операций записи в базу данных в пайплайнах элементов
  • Оберните целевой URL в Scraper API (аффилированная ссылка) в качестве прокси
  • Бонус: Логирование с цветным выводом

Без лишних слов, приступим!


Используйте HTTPCache

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

Чтобы избежать такого поведения, Scrapy предоставляет встроенное промежуточное ПО под названием HttpCacheMiddleware, которое кэширует каждый запрос, сделанный нашими пауками, вместе с соответствующим ответом.

Пример

Чтобы включить это, просто добавьте следующий код в файл settings.py вашего проекта Scrapy.

# Включить и настроить кэширование HTTP (по умолчанию отключено)
HTTPCACHE_ENABLED = True

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

Примечание: Не забудьте настроить HTTPCACHE_EXPIRATION_SECS в продакшене.

AutoThrottle

"Первое правило парсинга — не навредить сайту."

Обычно, чтобы снизить нагрузку на веб-сайты, которые мы парсим, мы бы настраивали DOWNLOAD_DELAY в нашем файле settings.py.

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

По сути, AutoThrottle будет регулировать задержки между запросами в соответствии с нагрузкой на веб-сервер, используя рассчитанную задержку от одного запроса. Задержка между запросами будет регулироваться таким образом, чтобы не превышать [AUTOTHROTTLE_TARGET_CONCURRENCY](http://doc.scrapy.org/en/latest/topics/autothrottle.html#std:setting-AUTOTHROTTLE_TARGET_CONCURRENCY).

Пример

Чтобы включить автоматическую регулировку скорости, просто добавьте это в файл настроек вашего проекта (settings.py):

# Проверьте доступные настройки, которые предоставляет это расширение [здесь](https://docs.scrapy.org/en/latest/topics/autothrottle.html#settings)!
# AUTOTHROTTLE_ENABLED (отключено по умолчанию)
AUTOTHROTTLE_ENABLED = True

Не только это, но вы также можете уменьшить вероятность блокировки сайта! Так просто.

Используйте API сайта

Одна из основных проблем, с которой сталкиваются при парсинге веб-сайтов, - это когда данные на сайтах динамически загружаются. Когда я только начинал, я естественным образом рассматривал использование HTTP API сайта, когда сталкивался с этой проблемой. Но это не идеально.

Сегодня многие веб-сайты предоставляют HTTP API для сторонних разработчиков, чтобы они могли использовать их данные без необходимости парсить веб-страницы. Фактически, это одна из лучших практик - всегда использовать API сайта, если оно доступно.

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

Как вы уже знаете, мы можем сохранять полученные данные в нашу базу данных с помощью каналов элементов в Scrapy.

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

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

Чтобы справиться с этим, мы будем использовать пакетную вставку (сохранение).

Пример

Вот пример того, как использовать массовую вставку с SQLAlchemy в вашем конвейере Scrapy:

ПРИМЕЧАНИЕ: Здесь мы используем [bulk_insert_mappings](https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.bulk_insert_mappings) вместо [bulk_save_objects](https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.bulk_save_objects), так как он принимает списки простых словарей Python, что приводит к меньшей нагрузке, связанной с созданием отображаемых объектов и присвоением им состояния, поэтому он быстрее. Проверьте сравнение здесь.

Приведенный выше код демонстрирует сценарий, когда вы работаете с Внешними ключами (FK). Если строки, которые нужно вставить, относятся только к одной таблице, то нет необходимости устанавливать return_defaults в значение True (источник).

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

Оговорка

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

Использование Proxy API

При парсинге крупных интернет-магазинов, таких как Amazon, вам часто потребуется использовать прокси-сервисы. Вместо создания собственной прокси-инфраструктуры, самым простым способом является использование API прокси, такого как Scraper API.

Давайте создадим вспомогательную функцию, которая принимает URL и преобразует его в URL Scraper API:

Для использования просто оберните URL, который вы хотите спарсить, с помощью только что созданной функции get_proxy_url.

# Пример в вашем spider.pyfrom example.utils import get_proxy_urldef start_requests(self):
        url = "https://ecommerce.example.com/products"
        yield scrapy.Request(url=get_proxy_url(url), callback=self.parse)

На мой взгляд, использование Scraper API было легким, а их бесплатный тариф позволяет парсить 1 000 веб-страниц в месяц. Ознакомьтесь с их ценами здесь.


Бонус: Логирование с цветами

Example of how colorized logging looks like in your terminal

"Как сделать так, чтобы логи были удобно заметными с помощью цветов?"

Во время разработки моих проектов на Scrapy я часто задавал себе один и тот же вопрос снова и снова. Представляем вам пакет [colorlog](https://github.com/borntyping/python-colorlog), который делает именно это!

После установки пакета в ваше виртуальное окружение просто добавьте следующий код в ваш settings.py, чтобы включить логирование с цветами:

import copy
from colorlog import ColoredFormatter
import scrapy.utils.log

color_formatter = ColoredFormatter(
    (
        '%(log_color)s%(levelname)-5s%(reset)s '
        '%(yellow)s[%(asctime)s]%(reset)s'
        '%(white)s %(name)s %(funcName)s %(bold_purple)s:%(lineno)d%(reset)s '
        '%(log_color)s%(message)s%(reset)s'
    ),
    datefmt='%y-%m-%d %H:%M:%S',
    log_colors={
        'DEBUG': 'blue',
        'INFO': 'bold_cyan',
        'WARNING': 'red',
        'ERROR': 'bg_bold_red',
        'CRITICAL': 'red,bg_white',
    }
)

_get_handler = copy.copy(scrapy.utils.log._get_handler)

def _get_handler_custom(*args, **kwargs):
    handler = _get_handler(*args, **kwargs)
    handler.setFormatter(color_formatter)
    return handler

scrapy.utils.log._get_handler = _get_handler_custom

_Источник: _https://stackoverflow.com/a/43317510/10067850


Заключение

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

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

Это все, что у меня есть на сегодня, и я надеюсь, что вы узнали что-то новое из этой статьи! Удачи и счастливого парсинга!


Опубликовано на jerrynsh.com

Как развернуть пауки Python Scrapy бесплатно в облаке

Прочитайте о советах по развертыванию и планированию запуска вашего парсера Scrapy в облаке бесплатно за 5 минут

medium.com

4 проблемы парсинга веб-сайтов, на которые следует обратить внимание

Прочитайте о уроках, извлеченных из парсинга сотен сайтов с помощью Python Scrapy

medium.com