Скрапинг страниц с бесконечной прокруткой с помощью Scrapy и Splash
Здесь я расскажу вам о том, как настроить Scrapy с ВсплескВы можете использовать бесконечную прокрутку, добавлять динамический контент и решать распространенные проблемы со скраппингом. Давайте погрузимся в процесс и посмотрим, как это делается, шаг за шагом.
Зачем скрапировать контент с бесконечной прокруткой?
Бесконечная прокрутка часто встречается на сайтах электронной коммерции, в социальных сетях и новостных агрегаторах, где дополнительные элементы подгружаются по мере прокрутки страницы вниз. Обычный HTML-парсер не справится со скрапингом таких сайтов, потому что новый контент появляется только после прокрутки. Здесь помогают headless-браузеры, такие как Splash: они имитируют прокрутку и загружают динамический контент для эффективного скрапинга.
Основы Scrapy и Splash
Scrapy Это фреймворк с открытым исходным кодом для веб-скрапинга на Python, известный своей скоростью, простотой и расширяемостью. Он предоставляет структурированный способ организовывать код и извлекать информацию с веб-сайтов.
Всплеск Splash — это headless-браузер, специально созданный для скрапинга. Он умеет выполнять JavaScript и рендерить HTML-страницы. В связке со Scrapy через Scrapy-Splash он позволяет скрапить сайты, которые полагаются на JavaScript для загрузки контента, например сайты с бесконечной прокруткой.
Пропустите бесконечный скроллинг - получите данные
Ниже перечислены лучшие сайты с наборами данныхЕсли ваш проект слишком сложен и вы не хотите тратить время впустую, обратите на них внимание:
- Яркие данные — Настраиваемые и готовые наборы данных по различным отраслям.
- Statista — Подробная статистика и отчеты для бизнеса и исследований.
- Datarade — Маркетплейс премиальных data-продуктов от разных поставщиков.
- AWS Data Exchange Наборы данных сторонних поставщиков, интегрированные с сервисами AWS.
- Zyte — Веб-скрейпинг и пользовательские наборы данных, адаптированные под потребности бизнеса.
- Data & Sons — Открытая торговая площадка для покупки и продажи разнообразных наборов данных.
- Coresignal — Аналитика рынка труда с обширными данными о вакансиях и занятости.
- Oxylabs — Специализированные услуги по данным компаний и веб-скрейпингу.
- Bloomberg Enterprise Data Catalog — Финансовые данные для корпоративного использования.
- Kaggle — Бесплатные общедоступные наборы данных и инструменты для науки о данных.
Шаг 1: Настройка Scrapy с помощью Splash
Чтобы начать использовать Splash вместе со Scrapy, выполните следующие шаги первоначальной настройки.
1. Установите Scrapy-Splash Откройте терминал и установите пакет scrapy-splash:
pip install scrapy-splash
2. Запуск Splash в Docker Для работы Splash требуется Docker, поэтому убедитесь, что Docker установлен и запущен на вашей машине. Используйте следующую команду, чтобы загрузить образ Splash:
docker pull scrapinghub/splash
Затем запустите сервер Splash:
docker run -it -p 8050:8050 -. rm scrapinghub/splash
Теперь Splash будет доступен по адресу http://localhost:8050, готовый отрисовывать JavaScript для вашего Scrapy-паука.
Шаг 2: Написание Lua-скрипта для прокрутки
Функция Lua-скриптов в Splash позволяет управлять браузером, прокручивать страницу вниз и ждать загрузки нового содержимого. Следующий Lua-скрипт прокручивает страницу до самого низа, ожидает появления нового содержимого и повторяет этот процесс несколько раз.
Lua-скрипт для прокрутки
функция главная(splash, args)
splash:go(args.url)
splash:wait(args.wait)
местный scroll_to = splash:jsfunc('window.scrollTo')
местный get_body_height = splash:jsfunc([[
function() {
return document.body.scrollHeight;
}
]])
местный scroll_count = 0
для _ = 1, args.max_scrolls сделать
scroll_count = scroll_count + 1
scroll_to(0, get_body_height())
splash:wait(args.scroll_delay)
конец
возврат {
html = splash:html(),
scroll_count = scroll_count
}
конец
В этом сценарии:
- splash:go(args.url) загружает целевой URL.
- splash:wait(args.wait) делает паузу, чтобы начальные элементы страницы успели загрузиться.
- Цикл for прокручивает страницу несколько раз, ожидая некоторое время (args.scroll_delay) после каждого прокручивания, чтобы дать возможность загрузиться новому содержимому.
Шаг 3: Интеграция Lua-скрипта в Scrapy Spider
Когда Lua-скрипт готов, следующий шаг - настроить паука Scrapy для его запуска. Этот паук отправляет запрос через Splash на целевой сайт и передает Lua-скрипт.
Код паука
импорт scrapy
с сайта scrapy_splash импорт SplashRequest
класс InfiniteScrollSpider(scrapy.Spider):
имя = 'infinite_scroll_spider'
разрешенные_домены = ['example.com']
start_urls = ['http://example.com/target_page']
lua_script = """
function main(splash, args)
splash:go(args.url)
splash:wait(args.wait)
local scroll_to = splash:jsfunc('window.scrollTo')
local get_body_height = splash:jsfunc([[
function() {
return document.body.scrollHeight;
}
]])
local scroll_count = 0
for _ = 1, args.max_scrolls do
scroll_count = scroll_count + 1
scroll_to(0, get_body_height())
splash:wait(args.scroll_delay)
конец
return {
html = splash:html(),
scroll_count = scroll_count
}
end
"""
def start_requests(себя):
урожайность SplashRequest(
self.start_urls[0],
self.parse,
конечная точка='выполнить',
args={
'lua_source': self.lua_script,
'wait': 2,
'scroll_delay': 1,
'max_scrolls': 8
}
)
def разбор(self, response):
для пункт в response.css('.item-selector'):
урожайность {
'name': item.css('.name::text').get(),
'цена': item.css('.price::text').get()
}
Пояснение:
- Паук отправляет SplashRequest с lua_source, указывающим на Lua-скрипт.
- Такие аргументы, как wait, scroll_delay и max_scrolls, определяют поведение скрипта при прокрутке.
- Функция parse извлекает данные о товаре (название и цену) из каждой итерации прокрутки.
Шаг 4: Работа с пагинацией и кнопками "Загрузить еще"
На многих страницах с бесконечной прокруткой используется скрытая кнопка «Загрузить еще», которая срабатывает, когда пользователь прокручивает страницу до конца. Lua-скрипт в Splash может обрабатывать этот сценарий, нажимая кнопку «Загрузить еще», когда она появляется.
Модифицированный Lua-скрипт для кнопки «Загрузить еще»
function main(splash, args)
splash:go(args.url)
splash:wait(args.wait)
local scroll_to = splash:jsfunc('window.scrollTo')
local get_body_height = splash:jsfunc([[
function() {
возврат document.body.scrollHeight;
}
]])
local scroll_count = 0
для _ = 1, args.max_scrolls do
scroll_count = scroll_count + 1
scroll_to(0, get_body_height())
splash:wait(args.scroll_delay)
local load_more = splash:select('.load-more-button')
если load_more then
load_more:mouse_click()
splash:wait(1) end end
возврат splash:html() end
Здесь переменная load_more ищет кнопку "Загрузить еще" с помощью своего селектора. Если она найдена, она имитирует нажатие, ждет загрузки содержимого и повторяет прокрутку.
Шаг 5: Обход защиты от ботов
На страницах с бесконечной прокруткой часто применяют антибот-защиту, включая CAPTCHA, ограничение частоты запросов и блокировку IP-адресов. Способы обхода включают:
- Ротация доверенных лиц: Ротация IP-адресов помогает избежать обнаружения. Такие сервисы, как ZenRows и ScraperAPI, позволяют включить ротацию IP-адресов с минимальной настройкой.
- User-Agent Rotation: Чтобы избежать обнаружения, случайным образом меняйте строку User-Agent при каждом запросе.
- Безголовый браузер: Splash работает в headless-режиме, поэтому ваши запросы больше похожи на обычный пользовательский трафик.
Вот как можно реализовать ротацию прокси с помощью ZenRows:
импорт scrapy
класс InfiniteScrollSpider(scrapy.Spider):
имя = 'proxy_spider'
разрешенные_домены = ['example.com']
def start_requests(себя):
прокси = 'http://@api.zenrows.com:8001'
url = 'http://example.com/target_page'
урожайность scrapy.Request(
url,
callback=self.parse,
мета={'proxy': proxy}
)
def разбор(self, response):
Логика разбора #
Этот пример настраивает Scrapy на использование ZenRows в качестве прокси для каждого запроса.
Шаг 6: Собираем все вместе
Вот полный код Scrapy-паука для скрапинга сайтов с бесконечной прокруткой, с интеграцией Splash, Lua-скриптом и ротацией прокси:
импорт scrapy
с сайта scrapy_splash импорт SplashRequest
класс FullInfiniteScrollSpider(scrapy.Spider):
имя = 'full_infinite_scroll'
разрешенные_домены = ['example.com']
start_urls = ['http://example.com/target_page']
lua_script = """
function main(splash, args)
splash:go(args.url)
splash:wait(args.wait)
local scroll_to = splash:jsfunc('window.scrollTo')
local get_body_height = splash:jsfunc([[
function() {
return document.body.scrollHeight;
}
]])
for _ = 1, args.max_scrolls do
scroll_to(0, get_body_height())
splash:wait(args.scroll_delay)
local load_more = splash:select('.load-more-button')
if load_more then
load_more:mouse_click()
splash:wait(1)
end
end
return splash:html()
end
"""
def start_requests(себя):
урожайность SplashRequest(
self.start_urls[0],
self.parse,
конечная точка='выполнить',
args={
'lua_source': self.lua_script,
'wait': 2,
'scroll_delay': 1,
'max_scrolls': 10
}
)
def разбор(self, response):
для пункт в response.css('.item-selector'):
урожайность {
'name': item.css('.name::text').get(),
'цена': item.css('.price::text').get()
}
Заключение
При создании страниц с бесконечной прокруткой я считаю Scrapy в связке со Splash очень удобным решением. Это удачная связка, которая позволяет без труда справляться даже с самыми сложными динамическими сайтами. С помощью Splash я могу справляться с рендерингом на JavaScript, а Scrapy отлично подходит для извлечения данных. Lua-скрипты Splash позволяют взаимодействовать с элементами страницы и подгружать дополнительный контент так, как если бы страницу прокручивал пользователь.

