Что такое Sitemap и зачем он нужен для парсинга?
Sitemap — это XML-файл, содержащий список URL-адресов сайта, предназначенный для информирования поисковых систем о структуре и доступных страницах. Для парсинга Sitemap предоставляет структурированный и полный список всех URL, что позволяет избежать необходимости обхода всего сайта вручную.
Преимущества использования Sitemap Spider
- Полнота: Sitemap содержит практически все важные URL сайта.
- Структурированность: XML формат обеспечивает удобный и предсказуемый способ извлечения URL.
- Эффективность: Избегаем перебора всех ссылок на сайте, фокусируясь только на целевых страницах.
- Актуальность: Sitemap часто обновляется, отражая изменения на сайте.
Недостатки и ограничения Sitemap Spider
- Неполные Sitemap: Некоторые сайты могут предоставлять неполные Sitemap, пропуская отдельные страницы.
- Устаревшие данные: Sitemap может содержать устаревшие или неработающие URL.
- Сложность структуры: Sitemap может быть сложным и содержать несколько файлов или индексов, требующих дополнительной обработки.
- Зависимость от доступности Sitemap: Если Sitemap недоступен или возвращает ошибки, парсинг невозможен.
Создание Scrapy проекта и установка зависимостей
Создание нового Scrapy проекта
Создайте новый проект Scrapy с помощью команды:
scrapy startproject my_project
cd my_project
Настройка файла settings.py
В settings.py настройте основные параметры Scrapy:
# settings.py
BOT_NAME = 'my_project'
SPIDER_MODULES = ['my_project.spiders']
NEWSPIDER_MODULE = 'my_project.spiders'
# Configure item pipelines
ITEM_PIPELINES = {
'my_project.pipelines.MyProjectPipeline': 300,
}
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'ru-RU,en;q=0.5',
}
ROBOTSTXT_OBEY = False позволяет игнорировать robots.txt (использовать с осторожностью).
Разработка Sitemap Spider: Практический пример
Определение структуры Sitemap и целевых URL
Предположим, что Sitemap сайта содержит URL следующего вида:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/product1</loc>
<lastmod>2023-10-26</lastmod>
</url>
<url>
<loc>https://example.com/product2</loc>
<lastmod>2023-10-25</lastmod>
</url>
</urlset>
Наша цель — извлечь URL продуктов (https://example.com/product1, https://example.com/product2).
Написание spider’а для разбора Sitemap
Создайте spider sitemap_spider.py:
import scrapy
from scrapy.spiders import SitemapSpider
class MySitemapSpider(SitemapSpider):
name = 'my_sitemap_spider'
sitemap_urls = ['https://example.com/sitemap.xml']
sitemap_rules = [('/product/', 'parse_product')]
def parse_product(self, response: scrapy.http.Response):
"""Parses product pages."""
title = response.css('h1::text').get()
price = response.css('.price::text').get()
yield {
'url': response.url,
'title': title,
'price': price,
}
Здесь sitemap_urls содержит список Sitemap URL. sitemap_rules — список правил, определяющих, какие URL и каким методом обрабатывать. В данном случае, все URL, содержащие /product/, будут обработаны методом parse_product.
Реализация логики парсинга контента со страниц (Item pipelines)
Создайте items.py для определения структуры данных:
# items.py
import scrapy
class ProductItem(scrapy.Item):
url = scrapy.Field()
title = scrapy.Field()
price = scrapy.Field()
В pipelines.py определите, что делать с извлеченными данными:
# pipelines.py
class MyProjectPipeline:
def process_item(self, item: ProductItem, spider) -> ProductItem:
"""Processes each scraped item."""
# Example: Save to file
with open('output.txt', 'a') as f:
f.write(f"{item['url']} - {item['title']} - {item['price']}\n")
return item
Обработка ошибок и исключений
Добавьте обработку ошибок в spider:
import scrapy
from scrapy.spiders import SitemapSpider
class MySitemapSpider(SitemapSpider):
name = 'my_sitemap_spider'
sitemap_urls = ['https://example.com/sitemap.xml']
sitemap_rules = [('/product/', 'parse_product')]
def parse_product(self, response: scrapy.http.Response):
"""Parses product pages, handling potential errors."""
try:
title = response.css('h1::text').get()
price = response.css('.price::text').get()
yield {
'url': response.url,
'title': title,
'price': price,
}
except Exception as e:
self.logger.error(f"Error parsing {response.url}: {e}")
Настройка и запуск Sitemap Spider
Запуск spider’а из командной строки
Запустите spider из командной строки:
scrapy crawl my_sitemap_spider
Сохранение результатов парсинга (CSV, JSON, база данных)
Для сохранения в JSON используйте команду:
scrapy crawl my_sitemap_spider -o output.json
Для сохранения в CSV:
scrapy crawl my_sitemap_spider -o output.csv
Для сохранения в базу данных, нужно настроить соответствующий pipeline.
Настройка параллельности и оптимизация скорости парсинга
В settings.py настройте параллельность:
# settings.py
CONCURRENT_REQUESTS = 32 # Adjust as needed
DOWNLOAD_DELAY = 0 # Adjust as needed
CONCURRENT_REQUESTS — количество параллельных запросов.
DOWNLOAD_DELAY — задержка между запросами (в секундах). Уменьшайте DOWNLOAD_DELAY осторожно, чтобы не перегрузить сервер.
Продвинутые техники и решения проблем
Обработка Sitemap с несколькими файлами или индексами
Если Sitemap содержит индекс (sitemapindex вместо urlset), используйте:
from scrapy.spiders import SitemapSpider
class MySitemapSpider(SitemapSpider):
name = 'my_sitemap_spider'
sitemap_urls = ['https://example.com/sitemap_index.xml'] # Sitemap index
sitemap_rules = [('/product/', 'parse_product')]
Scrapy автоматически обработает все Sitemap, указанные в индексе.
Обход защиты от парсинга (User-Agent, задержки, прокси)
- User-Agent: Измените User-Agent в
settings.py:
# settings.py
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
- Задержки: Используйте
DOWNLOAD_DELAYиRANDOMIZE_DOWNLOAD_DELAY. - Прокси: Используйте прокси-серверы для обхода блокировок. Можно использовать middleware для случайного выбора прокси из списка.
Динамическая загрузка контента (Selenium integration)
Если контент загружается динамически (JavaScript), интегрируйте Scrapy с Selenium:
- Установите Selenium и драйвер для браузера (например, ChromeDriver).
- Используйте Selenium в вашем spider для загрузки страниц и получения HTML.
# Example with Selenium
from selenium import webdriver
import scrapy
class MySeleniumSpider(scrapy.Spider):
name = 'my_selenium_spider'
start_urls = ['https://example.com']
def __init__(self):
self.driver = webdriver.Chrome() # Or Firefox, etc.
def parse(self, response):
self.driver.get(response.url)
# Wait for content to load (e.g., using WebDriverWait)
html = self.driver.page_source
# Parse html with BeautifulSoup or Scrapy selectors
# ...
self.driver.quit()