перейти к содержанию

Полное руководство по парсингу веб-страниц с помощью Scrapy на Python

Добро пожаловать в мой мега-урок по парсингу веб-страниц с помощью Scrapy!

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

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

Так что пристегнитесь и приступим к уборке!

Почему стоит выбирать Scrapy для парсинга веб-страниц?

В Python есть несколько отличных библиотек для парсинга веб-страниц, таких как BeautifulSoup, Selenium и т. д. Но вот несколько ключевых причин, по которым я рекомендую Scrapy как лучший выбор:

Скорость – Scrapy чрезвычайно быстр, поскольку может отправлять асинхронные запросы и очищать несколько страниц одновременно. Тесты показывают генерацию Scrapy 5000+ запросов в минуту на скромном оборудовании. Такое распараллеливание делает его идеальным для парсинга больших сайтов.

Мощные инструменты извлечения – Scrapy Selectors с использованием CSS, XPath, RegEx и т. д. значительно упрощает извлечение текста и данных. Вам не нужно анализировать беспорядочный HTML — просто выявите шаблоны.

Батареи в комплекте – Scrapy обеспечивает поддержку нумерации страниц, запросов регулирования, файлов cookie, прокси и т. д. Это избавляет вас от необходимости заново изобретать колесо.

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

БиблиотекаСкоростьМасштабируемостьПоддержка JavascriptКривая обучения
ScrapyОчень быстроПрекрасноЧерез расширенияУмеренная
КрасивыйСупЗамедлятьНе оченьНетЛегко
СеленЗамедлятьУмереннаяПрекрасноТрудный

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

Далее позвольте мне рассказать вам, как начать работу со Scrapy.

Установка Scrapy

Scrapy написан исключительно на Python и имеет минимальные зависимости. Установить:

pip install scrapy

Вот и все! Scrapy автоматически установит пакеты Python, такие как Twisted, Parsel и т. д.

После установки вы можете проверить, запустив:

scrapy version

Это распечатает текущую установленную версию. На момент написания последней стабильной версией является 2.7.1.

Установив Scrapy, вы готовы создать свой первый проект!

Создание нового проекта Scrapy

Scrapy организует очистку кода в «Проекты», состоящие из пауков, конвейеров и т. д. Чтобы создать новый проект:

scrapy startproject myproject

Это порождает myproject каталог со следующей структурой:

myproject
├── myproject/
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders/
│       └── __init__.py
└── scrapy.cfg

Поначалу эта планировка может показаться сложной. Но это помогает организовать крупные проекты и обеспечивает разделение задач. Вот что делает каждый файл/папка:

  • пауки/ – Где находится наш парсинг-код (пауки)
  • элементы.py – Определяет типы данных для очищенных данных
  • трубопроводы.py – Занимается обработкой/хранением данных
  • settings.py – Обеспечивает конфигурацию времени выполнения
  • промежуточное ПО.py – Реализует пользовательское промежуточное программное обеспечение загрузчика.
  • скраппи.cfg – Конфигурация развертывания Scrapy.

Пока не беспокойтесь обо всех файлах. В основном мы будем работать с пауками в папке ./spiders.

Давайте узнаем, как работают пауки Scrapy!

Анатомия лоскутного паука

Пауки — это классы, которые определяют логику очистки сайта (или группы сайтов). Вот ключевые компоненты паука:

  • имя – Уникальный идентификатор паука
  • разрешенные_домены – Список доменов, разрешенных для парсинга
  • start_urls – Список URL-адресов, с которых можно начать сканирование.

Основная логика парсинга написана внутри двух методов:

  • анализировать () – Извлекает данные из ответов
  • запрос() – Генерирует запросы на переход по ссылкам

Когда мы запускаем паука, Scrapy вызывает parse() метод для загруженного ответа каждого запрошенного нами URL-адреса.

Ассоциация parse() метод анализирует ответ с помощью селекторов и дает:

  • Извлеченные данные
  • Дополнительные URL-адреса для очистки путем создания объектов запроса.

Это позволяет рекурсивно сканировать страницы по ссылкам. Теперь давайте посмотрим это в действии!

Наш первый паук

Давайте напишем простого паука, который будет собирать списки товаров с сайта book.toscrape.com.

Сначала мы создадим шаблон паука с именем books_spider.py с помощью:

scrapy genspider books_spider books.toscrape.com

Это создает паука с предварительно заполненными URL-адресами:

import scrapy

class BooksSpider(scrapy.Spider):
    name = ‘books_spider‘
    allowed_domains = [‘books.toscrape.com‘]
    start_urls = [‘http://books.toscrape.com/‘]

    def parse(self, response):
        pass

Теперь давайте заполним parse() метод извлечения названия и цены продукта:

    def parse(self, response):
        for product in response.css(‘article.product_pod‘):

            title = product.css(‘h3 > a::attr(title)‘).get()
            price = product.css(‘.price_color::text‘).get()

            yield {
                ‘title‘: title,
                ‘price‘: price
            }

Мы тут:

  • Прокрутите product_pod элементы
  • Извлеките название и цену с помощью селекторов CSS.
  • Получите словарь Python с очищенными данными

Вот и все! Наш первый небольшой веб-скребок готов. Давайте запустим:

scrapy crawl books_spider

При этом будут просканированы URL-адреса, начиная с books.toscrape.com, и извлечены названия и цены в файл JSON.

Теперь, когда у нас есть основы, давайте научимся парсить страницы с разбивкой на страницы.

Обработка нумерации страниц в Scrapy

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

Вот как наш книжный паук может обрабатывать нумерацию страниц:

class BooksSpider(scrapy.Spider):

  # ...

  def parse(self, response):

    # Scraping logic..  

    next_page = response.css(‘li.next a::attr(href)‘).get()

    if next_page is not None:
        yield response.follow(next_page, callback=self.parse) 

Сначала мы извлекаем URL-адрес следующей страницы с помощью селектора CSS. Тогда мы yield еще один запрос к Scrapy:

  • next_page URL
  • Обратный вызов как self.parse снова

Это заставляет Scrapy рекурсивно вызывать parse() на каждом ответе страницы, пока не перестанут быть найдены следующие страницы. Довольно аккуратно!

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

Хранение очищенных данных

По умолчанию Scrapy возвращает извлеченные данные с помощью генераторов. Мы можем хранить их в файлах/базах данных следующим образом:

1. Экспорт кормов

Например, чтобы экспортировать очищенные данные в виде файла JSON:

from scrapy.exporters import JsonItemExporter

class BooksSpider(scrapy.Spider):

  # ..spider code

  def close(self, reason):  
      jsonFile = open(‘books.json‘, ‘wb‘)
      exporter = JsonItemExporter(jsonFile)
      exporter.start_exporting()

      for item in self.scraped_items: 
          exporter.export_item(item)

      exporter.finish_exporting()
      jsonFile.close()

Scrapy предоставляет встроенные средства экспорта в форматы JSON, CSV и XML.

2. Трубопроводы

Для расширенного хранения вы можете написать Item Pipelines. Несколько примеров конвейеров:

  • Проверка скопированных данных
  • Дедупликация повторяющихся элементов
  • Храните данные в базах данных
  • Загрузить изображения в облачное хранилище

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

Теперь, когда мы знаем основы пауков и парсинга страниц, давайте углубимся.

Настройка параметров Scrapy

Scrapy использует файл настроек для управления поведением и функциональностью во время выполнения. Некоторые ключевые настройки включают в себя:

ПОЛЬЗОВАТЕЛЬ_АГЕНТ – Строка User-Agent браузера для отправки с запросами. Рандомизация помогает избежать обнаружения.

ROBOTSTXT_OBEY – Следует ли соблюдать правила файла robots.txt. Установите значение False, чтобы игнорировать.

COOKIES_ENABLED – Включить ли обработку файлов cookie. Отключите очистку без головы.

CONCURRENT_REQUESTS – Максимальное количество одновременных запросов для отправки. Уменьшите это значение, чтобы избежать дросселирования.

ЗАГРУЗИТЬ_DELAY – Задержка в секундах ожидания перед отправкой каждого запроса. Увеличение скорости очистки дроссельной заслонки.

аддонов – Диктофон, содержащий дополнения и расширения, включенные для проекта.

Есть еще много настроек для настройки функциональности Scrapy. Рекомендую освоить основные настройки для настройки поведения очистки.

Теперь давайте рассмотрим некоторые удобные инструменты для отладки пауков Scrapy.

Отладка пауков с помощью Scrapy Shell

Scrapy предоставляет невероятно полезный инструмент под названием Scrapy Shell для тестирования ответов и селекторов.

Чтобы попробовать это, запустите:

scrapy shell "http://books.toscrape.com" 

Вы попадете в оболочку Python с загруженным и ограниченным ответом:

In [1]: response.css(‘title‘)
Out[1]: [<Selector xpath=‘descendant-or-self::title‘ data=‘<title>All products</title>‘>]

In [2]: response.xpath(‘//h1/text()‘)
Out[2]: [<Selector xpath=‘//h1/text()‘ data=‘All products‘>]

Оболочка позволяет интерактивно тестировать селекторы CSS/XPath и видеть, как Scrapy анализирует ответы.

Я широко использую его почти во всех своих проектах по парсингу, чтобы точно настроить извлечение без повторного запуска пауков. Часто он выявляет 90% проблем с селектором еще до того, как я напишу код синтаксического анализа!

Научившись использовать оболочку, вы значительно повысите свою производительность. Scrapy превратил отладку в удовольствие 🙂

Использование прокси и пользовательских агентов

Во время парсинга сайты часто блокируют вас, если вы:

  • Перегрузить сервер слишком большим количеством запросов
  • Не используйте заголовки запросов в стиле браузера.

Вот две простые настройки для предотвращения блоков:

1. Ротация пользовательских агентов

Установить USER_AGENT настройка ротации случайных пользовательских агентов:

USER_AGENT = ‘RandomUserAgentMiddleware‘ #Rotating user-agent middleware

Это варьирует User-Agent заголовок, чтобы ваш трафик выглядел более человечным.

2. Используйте ротацию прокси

Чтобы предотвратить блокировки по IP, вы можете маршрутизировать запросы через прокси:

class ProxyMiddleware:

  def process_request(self, request, spider):
    request.meta[‘proxy‘] = random.choice(PROXIES)

Здесь мы случайным образом назначаем прокси из списка каждому запросу. Это распределяет нагрузку по IP, чтобы избежать банов.

И это лишь малая часть возможностей смешивания и сопоставления компонентов Scrapy!

Давайте теперь решим общую задачу — очистку динамических веб-сайтов на основе JavaScript.

Парсинг JavaScript-сайтов

Основным ограничением Scrapy является то, что он видит только статический HTML-контент, изначально возвращаемый веб-сайтами.

Современные сайты в значительной степени полагаются на JavaScript для отображения контента. Чтобы их очистить, нам нужно анализировать JavaScript и дождитесь динамической загрузки сайта.

Scrapy обеспечивает интеграцию с такими инструментами, как Всплеск и Драматург для рендеринга страниц JavaScript.

Вот как вы можете настроить Scrapy для использования Splash:

SPLASH_URL = ‘http://localhost:8050‘ #Running Splash instance

DOWNLOADER_MIDDLEWARES = {
    ‘scrapy_splash.SplashCookiesMiddleware‘: 723,
    ‘scrapy_splash.SplashMiddleware‘: 725,
    ‘scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware‘: 810,
}

SPIDER_MIDDLEWARES = {
    ‘scrapy_splash.SplashDeduplicateArgsMiddleware‘: 100,
}

DUPEFILTER_CLASS = ‘scrapy_splash.SplashAwareDupeFilter‘ 

Мы добавляем классы промежуточного программного обеспечения, необходимые для интеграции Splash.

Чтобы очистить страницу, теперь вы можете запросить ее через Splash:

yield SplashRequest(url, args={‘wait‘: 3})

Это отобразит страницу с 3-секундным ожиданием перед извлечением HTML. Гораздо мощнее, чем Selenium!

Рекомендации по сканированию, позволяющие избежать банов

За годы парсинга веб-страниц я на собственном горьком опыте усвоил некоторые ключевые передовые методы. Вот несколько советов:

  • Уважение robots.txt и проверьте политику сайта перед парсингом
  • Установите разумный DOWNLOAD_DELAY от 2+ секунд
  • Отключите файлы cookie, если в этом нет крайней необходимости.
  • Используйте прокси и чередуйте пользовательские агенты при каждом запросе.
  • Избегайте слишком быстрого соскабливания – ограничьтесь <100 запросов/мин
  • Анализируйте собранные данные и быстро выявляйте регрессии
  • Повторите попытку в распространенных случаях сбоя, например при ошибке 500.

Соблюдение стандартов и вежливое сканирование помогают избежать целенаправленной блокировки. Освоение Scrapy с учетом этих принципов поможет вам далеко продвинуться!

На этом мы подошли к концу нашего путешествия по веб-парсингу Scrapy! Давайте подведем итоги некоторыми ключевыми выводами.

Основные выводы

  • Scrapy предоставляет очень быструю и мощную платформу для масштабного парсинга веб-страниц.
  • Он упрощает общие задачи парсинга благодаря библиотекам и инструментам, входящим в комплект поставки.
  • Пауки абстрагируются от сложности рекурсивного сканирования страниц.
  • Собранные данные можно экспортировать и хранить в удобных для пользователя форматах, таких как CSV/JSON.
  • Модуль «Настройки» и командная оболочка помогают настраивать поведение и отлаживать парсеры.
  • Использование плагинов, таких как Splash, позволяет обрабатывать сайты с большим количеством JavaScript.
  • Соблюдение стандартов и передового опыта помогает избежать сбоев скрепера.

Надеюсь, вы нашли это руководство полезным! Не стесняйтесь обращаться, если у вас есть еще вопросы. Я всегда рад помочь другим любителям парсинга веб-страниц.

Теперь ваша очередь создать что-то потрясающее с помощью Scrapy 🙂 Приятного кодирования!

Присоединяйтесь к беседе

Ваш электронный адрес не будет опубликован. Обязательные поля помечены * *