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

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

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

Преимущества использования Requests вместо Scrapy Request/Response

Хотя Scrapy предоставляет свои собственные объекты Request и Response, использование requests дает несколько преимуществ:

  • Более гибкое управление запросами: requests позволяет более детально контролировать параметры запроса, такие как заголовки, куки и тайм-ауты.
  • Простота использования: Синтаксис requests часто считается более интуитивным и простым для понимания, особенно для новичков.
  • Расширенные возможности: requests предлагает расширенные функции, такие как поддержка сессий, аутентификации и прокси.

Когда Requests полезен: динамический контент, API и обход защиты

requests особенно полезен в следующих сценариях:

  • Скрапинг сайтов с динамически подгружаемым контентом (JavaScript): Когда контент генерируется на стороне клиента с помощью JavaScript, Scrapy может не увидеть его. requests позволяет выполнить JavaScript код (обычно в связке с Selenium или Puppeteer) и получить итоговый HTML.
  • Взаимодействие с API: Многие веб-сайты предоставляют API для доступа к данным. requests упрощает отправку запросов к API и обработку ответов в формате JSON или XML.
  • Обход защиты от скрапинга: Некоторые сайты используют сложные методы защиты от скрапинга, такие как капчи, лимиты запросов и блокировка IP-адресов. requests позволяет более гибко управлять заголовками, куками и прокси, что помогает обходить эти защиты.

Установка и настройка: подготовка к работе с Requests

Установка библиотеки Requests

Установите библиотеку requests с помощью pip:

pip install requests

Настройка Scrapy проекта: добавление middleware

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

Импорт Requests в ваш Scrapy spider

Импортируйте библиотеку requests в ваш Scrapy spider:

import scrapy
import requests

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = ["http://example.com"]

    def parse(self, response):
        # Здесь будет код с использованием requests
        pass

Реализация: Использование Requests в Scrapy Spider

Отправка GET запросов с помощью Requests

Отправьте GET запрос с помощью requests.get():

import scrapy
import requests

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = ["http://example.com"]

    def parse(self, response):
        r = requests.get("http://example.com/api/data")
        # Дальнейшая обработка ответа

Обработка ответов Requests и извлечение данных

Получите данные из ответа:

r = requests.get("http://example.com/api/data")
if r.status_code == 200:
    data = r.json() # Если ответ в формате JSON
    # Или
    data = r.text # Если ответ в формате HTML или текста
    for item in data:
        yield {"item": item}
else:
    self.logger.error(f"Request failed with status code: {r.status_code}")

Отправка POST запросов с помощью Requests

Отправьте POST запрос с данными:

Реклама
import scrapy
import requests
import json

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = ["http://example.com"]

    def parse(self, response):
        payload = {"key1": "value1", "key2": "value2"}
        r = requests.post("http://example.com/api/post", data=json.dumps(payload))
        if r.status_code == 200:
            # Обработка успешного ответа
            pass
        else:
            self.logger.error(f"POST request failed with status code: {r.status_code}")

Передача заголовков и куки (cookies) с Requests

Добавьте заголовки и куки к запросу:

headers = {"User-Agent": "My Scrapy Bot"}
cookies = {"sessionid": "1234567890"}

r = requests.get("http://example.com", headers=headers, cookies=cookies)

Продвинутое использование: Обход ограничений и оптимизация

Использование прокси с Requests для обхода блокировок

Используйте прокси для маскировки вашего IP-адреса:

proxies = {"http": "http://proxy.example.com:8080", "https": "https://proxy.example.com:8080"}
r = requests.get("http://example.com", proxies=proxies)

Обработка ошибок и исключений при работе с Requests

Обрабатывайте возможные ошибки:

try:
    r = requests.get("http://example.com", timeout=10) # Добавлен таймаут
    r.raise_for_status()  # Raises HTTPError for bad responses (4XX, 5XX)
except requests.exceptions.RequestException as e:
    self.logger.error(f"Request failed: {e}")

Асинхронные запросы с Requests (библиотека grequests или asyncio)

Для повышения производительности используйте асинхронные запросы (например, с помощью grequests):

import grequests

urls = ["http://example.com", "http://example.org", "http://example.net"]

rs = (grequests.get(u) for u in urls)
responses = grequests.map(rs)

for response in responses:
    if response:
        print(response.status_code)
    else:
        print("Request failed")

Примеры и лучшие практики

Пример: Скрапинг сайта с динамически подгружаемым контентом

Предположим, есть сайт, где товары подгружаются при прокрутке страницы. Scrapy может не увидеть все товары сразу. Используйте requests в связке с Selenium для получения полного HTML:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import scrapy

class DynamicSpider(scrapy.Spider):
    name = "dynamic_spider"
    start_urls = ["http://example.com/dynamic_page"]

    def __init__(self):
        chrome_options = Options()
        chrome_options.add_argument("--headless")  # Запуск Chrome в фоновом режиме
        self.driver = webdriver.Chrome(options=chrome_options)
        super().__init__()

    def parse(self, response):
        self.driver.get(response.url)
        # Прокрутка страницы вниз для загрузки всего контента
        for _ in range(3): # Прокрутить 3 раза, можно настроить
             self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
             time.sleep(2) # Подождать пока подгрузится контент
        html = self.driver.page_source
        self.driver.quit()
        # Теперь можно использовать BeautifulSoup или Scrapy для парсинга html
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(html, 'html.parser')
        # Пример извлечения всех заголовков h2
        for h2 in soup.find_all('h2'):
            yield {"title": h2.text}

Рекомендации по эффективному использованию Requests в Scrapy

  • Избегайте блокировки Scrapy: Не блокируйте цикл обработки Scrapy, выполняя длительные операции синхронно. Используйте асинхронные запросы, где это возможно.
  • Управляйте куками и сессиями: Правильно обрабатывайте куки и сессии для поддержания состояния между запросами.
  • Обрабатывайте ошибки: Реализуйте надежную обработку ошибок и исключений, чтобы ваш парсер не останавливался при возникновении проблем.
  • Используйте прокси и User-Agent: Регулярно меняйте User-Agent и используйте прокси для обхода ограничений и блокировок.
  • Оптимизируйте запросы: Старайтесь отправлять только необходимые запросы и минимизируйте размер передаваемых данных.

Добавить комментарий