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

Освойте парсинг веб-страниц с помощью Scrapy на Python

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

Что такое Scrapy?

Scrapy — это платформа сканирования и очистки веб-страниц с открытым исходным кодом для Python. Он предоставляет высокоуровневый API для быстрого и эффективного извлечения данных с веб-сайтов.

Некоторые ключевые особенности Scrapy:

  • Встроенная поддержка рекурсивного сканирования веб-сайтов и перехода по ссылкам.
  • Гибкий механизм извлечения данных с помощью селекторов CSS и выражений XPath.
  • Встроенная поддержка анализа содержимого HTML и XML.
  • Удобно для парсинга сайтов с большим количеством JavaScript за счет интеграции с такими браузерами, как Selenium.
  • Простой способ очистки данных с использованием асинхронного ввода-вывода для повышения производительности.
  • Экспортируйте очищенные данные в форматы JSON, CSV, XML.
  • Способен обрабатывать большие проекты парсинга, включающие тысячи запросов.
  • Расширяйте функциональность с помощью промежуточного программного обеспечения, расширений и конвейеров.
  • Широкий спектр готовых к использованию пауков с открытым исходным кодом для популярных веб-сайтов.

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

Создание вашего первого Scrapy Spider

Лучший способ понять Scrapy — создать простого паука. Давайте посмотрим, как создать паука, который собирает цитаты с сайта. http://quotes.toscrape.com.

Сначала установите Scrapy:

pip install scrapy

Затем создайте новый проект Scrapy под названием myquotes:

scrapy startproject myquotes

Это создаст myquotes каталог со следующим содержимым:

myquotes/
    scrapy.cfg
    myquotes/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py

Мы будем писать наш код внутри spiders/. Создайте нового паука под названием quotes_spider.py запустив:

cd myquotes
scrapy genspider quotes_spider quotes.toscrape.com

Это создаст файл quotes_spider.py с шаблонным кодом для нашего паука. Давайте изменим его, чтобы очистить кавычки:

import scrapy

class QuotesSpider(scrapy.Spider):
    name = ‘quotes‘
    allowed_domains = [‘quotes.toscrape.com‘]
    start_urls = [‘http://quotes.toscrape.com/‘]

    def parse(self, response):
        quotes = response.css(‘.quote‘)
        for quote in quotes:
            text = quote.css(‘.text::text‘).extract_first()
            author = quote.css(‘.author::text‘).extract_first()
            tags = quote.css(‘.tags .tag::text‘).extract()

            yield {
                ‘text‘: text,
                ‘author‘: author,
                ‘tags‘: tags
            }

Этот паук будет:

  • Сканировать сайт, начиная с start_urls.
  • Использовать parse() метод извлечения данных из ответа.
  • Найти все .quote элементы на странице и извлеките цитату text, authorи tags.
  • Получите словарь Python с извлеченными данными для каждой цитаты.

Чтобы запустить этого паука:

scrapy crawl quotes

Это соберет данные с веб-сайта котировок и выведет их на консоль. Вы также можете сохранить результаты в файл, передав -o filename.json.

Вот и все! Вы создали своего первого паука Scrapy. Далее давайте подробно рассмотрим некоторые ключевые понятия.

Обзор Scrapy-архитектуры

Scrapy построен на основе следующих основных компонентов:

Двигатель

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

Планировщик

Планировщик получает запросы от движка и ставит их в очередь для очистки загрузчиком. Он определяет приоритетность запросов на основе различных очередей и оптимизирует эффективность очистки.

Загрузчик

Загрузчик занимается загрузкой веб-страниц и передачей ответов обратно в движок. Он эффективно управляет несколькими одновременными запросами.

Spiders

Пауки — это основные компоненты, в которых вы реализуете логику очистки. Они начинают сканирование с определенных URL-адресов и анализируют ответы с помощью парсеров.

Конвейер элементов

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

Промежуточное ПО загрузчика

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

Промежуточное программное обеспечение паука

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

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

Понимание Scrapy Spiders

Паук — это компонент, который контролирует процесс очистки в Scrapy. Основными задачами пауков являются:

  • Начните сканирование с одного или нескольких определенных URL-адресов.
  • Следуйте ссылкам, чтобы рекурсивно очищать контент.
  • Анализируйте ответы с помощью синтаксических анализаторов, таких как селекторы CSS и XPath.
  • Возвращайте очищенные данные в виде диктовок, элементов или других объектов.

В Scrapy есть несколько типов встроенных пауков:

ПолзатьПаук

CrawlSpider используется для сканирования и очистки данных с нескольких веб-страниц в домене (или группе доменов). Он имеет полезные функции, такие как переход по ссылкам и правилам.

Например:

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class MySpider(CrawlSpider):

    name = ‘crawlspider‘ 

    allowed_domains = [‘example.com‘]

    start_urls = [‘http://www.example.com‘]

    rules = (
        Rule(LinkExtractor(allow=r‘Items/‘), callback=‘parse_item‘, follow=True),
    )

    def parse_item(self, response):
        # Scrape data and return Items here 
        pass

Этот паук начнет ползать из example.com, перейдите по всем ссылкам, совпадающим Items/ и позвонить parse_item() метод для очистки данных из каждого ответа.

XMLFeedSpider

XMLFeedSpider предназначен для извлечения данных из XML-каналов. Вы предоставляете ему URL-адреса каналов, а затем извлекаете данные из узлов с помощью XPath.

Например:

from scrapy.spiders import XMLFeedSpider


class MySpider(XMLFeedSpider):
    name = ‘xmlspider‘
    allowed_domains = [‘example.com‘]
    start_urls = [‘http://www.example.com/feed.xml‘]
    iterator = ‘iternodes‘ # This is actually unnecessary, since it‘s the default value
    itertag = ‘item‘

    def parse_node(self, response, node):
        # Extract data from <item> nodes using XPath
        pass 

Этот паук будет очищать данные из XML-канала, расположенного по адресу http://www.example.com/feed.xml.

Существуют и другие встроенные типы пауков, например CSVFeedSpider, SitemapSpider и т. д., предназначенные для разных целей. Вы можете даже создайте свои собственные классы пауков.

Селекторы для извлечения данных

Scrapy предоставляет селекторы для извлечения данных из ответов HTML и XML с использованием селекторов CSS или выражений XPath.

Например:

response.css(‘div.quote‘).extract() # Get all <div class="quote"> elements
response.xpath(‘//div‘) # Get all <div> elements

quote = response.css(‘div.quote‘)[0] 
quote.css(‘span.text::text‘).get() # Extract text from <span> inside first <div>
quote.xpath(‘./span/text()‘).get() # Alternative way with XPath

Вы даже можете выбрать данные из элемента и извлечь атрибуты:

for link in response.css(‘ul.links li a‘):
    link_name = link.xpath(‘./text()‘).get()
    link_url = link.xpath(‘./@href‘).get()

Это позволяет очень легко находить и извлекать нужные данные из ответов.

Обработка страниц JavaScript

По умолчанию пауки Scrapy не могут очищать страницы с большим количеством JavaScript, поскольку Scrapy видит только исходный HTML, возвращаемый сервером. Чтобы очистить динамический контент, загружаемый через JavaScript, вы можете интегрировать Scrapy с инструментом автоматизации браузера, например Драматург or Селен.

Самый простой способ - это использовать scrapy-playwright расширение, которое интегрирует Playwright со Scrapy.

Сначала установите его:

pip install scrapy-playwright

Затем включите его, добавив это промежуточное программное обеспечение:

DOWNLOADER_MIDDLEWARES = {
    ‘scrapy_playwright.middleware.PlaywrightMiddleware‘: 1,
}

Наконец, установите playwright=True в Request мета для рендеринга страниц с помощью Playwright:

yield scrapy.Request(url, meta={
    ‘playwright‘: True,
})

Playwright загрузит JavaScript на каждой странице перед передачей визуализированного HTML в Scrapy для очистки.

Это позволяет легко парсить современные веб-сайты JavaScript с помощью Scrapy и Playwright!

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

По умолчанию Scrapy выводит очищенные данные на консоль. Существует несколько способов хранения очищенных данных:

JSON, CSV, XML-каналы

Самый простой способ — сохранить очищенные элементы в файл с помощью команды -o флаг:

scrapy crawl quotes -o quotes.json

Это сохранит все очищенные элементы в файл JSON. CSV, JSONL, XML и другие форматы также поддерживаются.

Конвейер в базу данных

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

Например, конвейер MongoDB:

import pymongo

class MongoPipeline(object):

    collection_name = ‘quotes‘

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get(‘MONGO_URI‘),
            mongo_db=crawler.settings.get(‘MONGO_DATABASE‘)
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

Этот конвейер подключается к MongoDB и вставляет все очищенные элементы в коллекцию.

Пользовательские серверные хранилища

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

Некоторые популярные варианты хранения:

  • Scrapy Cloud – хранит очищенные элементы в облаке и предоставляет веб-интерфейс для доступа к данным.
  • Kafka — потоковая передача очищенных элементов в кластер Kafka.
  • Elasticsearch — индексируйте и запрашивайте очищенные элементы в Elasticsearch.

Советы по сканированию

Вот несколько советов по эффективному сканированию с помощью Scrapy:

  • Инициализировать allowed_domains атрибут, позволяющий ограничить сканирование одним доменом (или небольшой группой доменов).

  • Установите небольшой DOWNLOAD_DELAY примерно 1-2 секунды, чтобы избежать перегруженности сайтов.

  • Отключите файлы cookie, установив COOKIES_ENABLED = False если не требуется улучшение производительности.

  • Использовать CONCURRENT_REQUESTS настройка для регулировки количества одновременных запросов. Начните с низкого значения, например 8-16.

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

  • Используйте scrapy shell для быстрого интерактивного тестирования селекторов.

  • Отслеживайте статус и статистику парсинга с помощью веб-интерфейса Scrapyd.

  • Используйте такие услуги, как Прокси-сетка маршрутизировать запросы через резидентные прокси и избегать банов по IP.

Расширенные функции

Некоторые более продвинутые функции Scrapy:

Динамическое сканирование с помощью FormRequest

Используйте FormRequest и данные формы для имитации отправки HTML-форм:

data = {
  ‘search_query‘: ‘scraping‘ 
}

yield FormRequest(url=‘http://quotes.toscrape.com/search‘, formdata=data, callback=self.parse_search_results)

Постобработка с помощью Item Pipeline

Конвейеры предметов позволяют обрабатывать очищенные предметы. Полезно для:

  • Проверка и очистка данных
  • дедупликации
  • Хранение данных в базах данных
  • Отправка элементов в конечные точки API

Можно включить несколько конвейеров, заказав их через ITEM_PIPELINES установка.

HTTP-кеширование

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

HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 0  # Cache forever
HTTPCACHE_DIR = ‘cache‘
HTTPCACHE_IGNORE_HTTP_CODES = [500, 503, 504]  

Пользовательские промежуточные программы Spider

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

class UserAgentMiddleware:

    def process_request(self, request, spider):
      request.headers[‘User-Agent‘] = random_user_agent()

Распределенное сканирование с помощью Scrapyd и Scrapy Cloud

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

Заключение

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

Некоторые ключевые темы, которые мы рассмотрели, включали:

  • Архитектура Scrapy и основные компоненты, такие как пауки, конвейеры, промежуточное ПО и т. д.
  • Создание базовых пауков путем создания подклассов scrapy.Spider.
  • Использование выражений селектора для извлечения данных из HTML и XML.
  • Сканирование нескольких страниц с помощью таких пауков, как CrawlSpider.
  • Парсинг страниц JavaScript с помощью интеграции таких инструментов, как Playwright.
  • Хранение очищенных элементов в разных форматах или базах данных.
  • Следование лучшим практикам эффективного сканирования и избежания банов.
  • Расширенные функции, такие как промежуточное программное обеспечение, кэширование, распределенное сканирование и т. д.

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

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

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