Вот подробное руководство объемом более 2000 слов по сбору с Fashionphile данных о подержанной моде:
Fashionphile — одна из крупнейших и самых популярных онлайн-площадок подержанной модной одежды. Благодаря таким люксовым брендам, как Chanel, Louis Vuitton, Hermès и другим, это настоящая сокровищница данных о моде высокого класса. В этом руководстве мы рассмотрим различные методы сбора списков продуктов Fashionphile в больших масштабах с помощью Python.
Зачем Scrape Fashionphile?
Вот некоторые из основных причин, по которым может потребоваться очистить данные от Fashionphile:
Исследования рынка – Fashionphile продает тысячи предметов роскоши от сотен дизайнерских брендов. Сбор этих данных дает ценную информацию о ценах на подержанном рынке, спросе, уровне запасов и многом другом. Это бесценная информация о рынке для ритейлеров предметов роскоши.
Мониторинг цен – Учитывая постоянно меняющиеся запасы, полезно отслеживать цены с течением времени для изучения цен. Веб-скрапинг позволяет осуществлять непрерывный мониторинг и отслеживание появления новых товаров на Fashionphile.
Инвентарный мониторинг – Реселлеры предметов роскоши, такие как Fashionphile, ежедневно получают новые партии товаров. Парсинг дает представление о новых товарах, которые перечислены по дизайнерам, категориям, ценам и т. д.
Ключевое слово исследований – Названия, описания и теги продуктов – это кладезь ключевых слов. Их можно извлечь с помощью парсинга веб-страниц и использовать для SEO и рекламных кампаний.
Конкурентное исследование – Понимание ассортимента, цен и рекламных акций такого конкурента, как Fashionphile, является ключевым моментом для любого реселлера предметов роскоши. Веб-скрапинг предоставляет данные, лежащие в основе этих идей.
Лидогенерация – Контактная информация продавцов элитной модной одежды может стать ценным источником информации для привлечения клиентов. В товарах указан город/штат продавца.
Таким образом, Fashionphile является основной мишенью для парсинга веб-страниц из-за большого количества высококачественных данных. Потенциальных вариантов использования множество.
Обзор веб-сайта Fashionphile
Прежде чем мы углубимся в код, давайте кратко разберемся, как устроен сайт Fashionphile:
Страницы продукта – У каждого продукта есть своя страница (например, https://www.fashionphile.com/p/chanel-lambskin-quilted-medium-double-flap-black-1007734) с такими деталями, как название, описание, цена, изображения, доставка и т. д.
Страницы категорий – Объявления можно просматривать по категориям (например, https://www.fashionphile.com/shop/chanel-bags) с нумерацией страниц.
Поиск страницы – Поисковые запросы выдают результаты с разбивкой на страницы (например, https://www.fashionphile.com/shop?search=chanel+classic+flap).
Sitemaps – В XML-картах сайта перечислены все URL-адреса продуктов для индексации поисковыми системами.
Эта структура вполне типична для любого сайта электронной коммерции. Ключевым моментом в этом случае является выяснение того, как извлечь структурированные данные из базового HTML.
Очистка данных страницы продукта
Начнем с извлечения подробностей из одной страницы продукта. Вот пример:
https://www.fashionphile.com/p/chanel-lambskin-quilted-medium-double-flap-black-1007734
Просматривая исходный код страницы, мы видим, что данные о продукте удобно доступны в виде объекта JSON внутри тега:
<script id="__NEXT_DATA__" type="application/json">
{
"props": {
"pageProps": {
...
"productPageReducer": {
"productData": {
"id": 1007734,
"title": "CHANEL Lambskin Quilted Medium Double Flap Black",
...
"price": 4795,
"images": [
"https://prod-images.fashionphile.com/016652c727c49d9ddeaae9f22efb7e1a/4b54909a5093afb22a592857bc5e586a.jpg",
...
]
}
}
}
}
}
</script>
Эти структурированные данные можно удобно извлечь с помощью селекторов CSS:
import json
from parsel import Selector
product_html = # fetch product page HTML
# Extract JSON object
json_data = Selector(product_html).css(‘script#__NEXT_DATA__::text‘).get()
# Deserialize JSON
data = json.loads(json_data)
# Drill down to product data
product = data[‘props‘][‘pageProps‘][‘productPageReducer‘][‘productData‘]
print(product[‘title‘])
print(product[‘price‘])
print(product[‘images‘])
Ключевые шаги:
- Используйте
Selector
извлечь<script>
тег, содержащий данные JSON - Десериализовать строку JSON в словарь Python с помощью
json.loads()
- Разверните вложенную структуру, чтобы получить подробную информацию о продукте.
И мы аккуратно извлекли основные данные о продукте! Тот же подход применим к любому URL-адресу продукта.
Этот метод JSON очень удобен по сравнению с прямым анализом HTML. Многие современные веб-сайты используют аналогичные структуры данных JSON со всеми базовыми данными о продуктах.
Сканирование списков категорий
Теперь, когда мы можем извлекать данные по отдельным продуктам, давайте посмотрим на сбор данных в масштабе.
Мы начнем с сканирования страниц категорий, которые содержат списки с разбивкой на страницы для дизайнера. Вот пример категории Chanel:
https://www.fashionphile.com/shop/chanel-bags
Эта страница содержит 72 продукта, размещенных на 4 страницах. Чтобы извлечь все списки, нам необходимо:
- Получить HTML-код страницы
- Извлечь общее количество страниц из HTML
- Просматривайте каждую страницу и извлекайте продукты.
Вот как это выглядит на Python:
import math
from parsel import Selector
category_url = ‘https://www.fashionphile.com/shop/chanel-bags‘
def scrape_products(html):
# Extract JSON data
json = Selector(html).css(‘script#__NEXT_DATA__::text‘).get()
# Get products array
data = json.loads(json)
products = data[‘props‘][‘pageProps‘][‘categoryPageReducer‘][‘categoryData‘][‘products‘]
return products
def get_total_pages(html):
# Extract pagination data
json = Selector(html).css(‘script#__NEXT_DATA__::text‘).get()
data = json.loads(json)
# Calculate pages
total_products = data[‘props‘][‘pageProps‘][‘categoryPageReducer‘][‘categoryData‘][‘totalProducts‘]
per_page = data[‘props‘][‘pageProps‘][‘categoryPageReducer‘][‘categoryData‘][‘productsPerPage‘]
total_pages = math.ceil(total_products / per_page)
return total_pages
# Fetch first page
first_page_html = # request first page
# Get products from page
products = scrape_products(first_page_html)
# Get total pages
total_pages = get_total_pages(first_page_html)
# Crawl remaining pages
for page in range(2, total_pages+1):
url = f‘{category_url}?page={page}‘
html = # fetch page HTML
page_products = scrape_products(html)
# Combine with master products list
products.extend(page_products)
print(len(products))
# Prints total products scraped across all pages
Ключевые шаги:
- Анализировать общее количество страниц из HTML первой страницы
- Перебирать каждую страницу, увеличивая
?page=
параметр - Извлекайте JSON продуктов с каждой страницы.
- Объедините все товары в один список
Этот метод постраничного сканирования можно применить к любой странице категории, поиска или отсортированных списков.
Используйте файлы Sitemap для сканирования всех URL-адресов продуктов
Теперь, когда мы можем извлекать продукты с отдельных страниц, нам нужен способ обнаружения всех URL-адресов продуктов для сканирования.
Один из простых вариантов — использовать карту сайта Fashionphile.
Файлы Sitemap предоставляют список всех URL-адресов веб-сайта для сканеров поисковых систем. Вот индекс карты сайта Fashionphile:
https://www.fashionphile.com/sitemap-index.xml
Этот XML-файл содержит ссылки на все отдельные файлы карты сайта. Сначала нам нужно проанализировать все перечисленные карты сайта:
import xml.etree.ElementTree as ET
sitemap_index = ‘https://www.fashionphile.com/sitemap-index.xml‘
# Parse XML
root = ET.fromstring(requests.get(sitemap_index).text)
# Get all sitemap URLs
sitemaps = [elem.text for elem in root.findall(‘./sitemap/loc‘)]
print(sitemaps)
Это распечатывает URL-адреса всех дополнительных файлов Sitemap, например:
[‘https://s3-us-west-2.amazonaws.com/fashionphile/sitemaps/category-sitemap1.xml‘,
‘https://s3-us-west-2.amazonaws.com/fashionphile/sitemaps/category-sitemap2.xml‘,
‘https://s3-us-west-2.amazonaws.com/fashionphile/sitemaps/category-sitemap3.xml‘,
...]
Затем мы можем просмотреть каждую вложенную карту сайта и извлечь URL-адреса продуктов:
product_urls = []
for sitemap in sitemaps:
# Parse XML
root = ET.fromstring(requests.get(sitemap).text)
# Get all product URLs
urls = [elem.text for elem in root.findall(‘./url/loc‘)]
# Add to master list
product_urls.extend(urls)
print(len(product_urls))
# Prints total product URLs
Таким образом, используя индекс карты сайта, мы можем собрать общий список из более чем 500 тысяч URL-адресов продуктов на Fashionphile!
Затем мы можем ввести это в наш код сканирования продуктов, чтобы получить свежие данные для каждого продукта, представленного на сайте.
Сканирование на основе исторических списков
Файлы Sitemap предоставляют самую актуальную информацию о объявлениях на Fashionphile.
Другой подход — использовать исторические данные очистки для управления сканированием.
Методика будет такой:
- Проведите масштабное исследование Fashionphile и сохраните списки товаров.
- В каждом последующем парсинге анализируйте все листинги на основе исторических данных.
- Для каждого исторического URL-адреса проверьте, возвращает ли он по-прежнему код состояния 200.
- If
200 OK
, очистить обновленные данные о продукте - If
404 Not Found
, удалить удаленное объявление из набора данных
- If
- Для любых новых объявлений добавьте в набор данных
Это позволяет синхронизировать очищенный набор данных с последними запасами и ценами на Fashionphile.
Вы даже можете отслеживать историю цен и другие тенденции с течением времени по мере обновления продуктов. Исторические данные обеспечивают более продвинутую аналитику.
Очистка данных в масштабе с помощью Scrapy
Все описанные до сих пор методы используют для парсинга базовые библиотеки Python, такие как Requests и Parsel.
Для крупномасштабных производственных операций можно использовать специальную среду веб-сканирования, например Scrapy Рекомендовано.
Scrapy дает несколько преимуществ:
- Мощное сканирование со встроенным планировщиком, загрузчиком, классами пауков и т. д.
- Асинхронный ввод-вывод для очень быстрого парсинга
- Встроенное кэширование, регулирование, файлы cookie, обработка прокси.
- конвейеры элементов для аккуратного хранения очищенных данных
- Обширная информация об отладке в журналах
- Удобный вывод при сканировании, например статистика и отчеты.
Вот простой Scrapy-паук для сканирования продуктов Fashionphile:
import scrapy
import json
class FashionphileSpider(scrapy.Spider):
name = ‘fashionphile‘
def start_requests(self):
yield scrapy.Request(url=‘https://www.fashionphile.com/shop/louis-vuitton-bags‘)
def parse(self, response):
# Extract JSON data
json_data = response.css(‘script#__NEXT_DATA__::text‘).get()
data = json.loads(json_data)
# Yield Product Items
for product in data[‘props‘][‘pageProps‘][‘categoryPageReducer‘][‘categoryData‘][‘products‘]:
yield {
‘title‘: product[‘title‘],
‘price‘: product[‘price‘],
‘url‘: product[‘url‘],
}
# Crawl to next page
next_page = response.css(‘a.next::attr(href)‘).get()
if next_page:
yield scrapy.Request(url=next_page, callback=self.parse)
Это реализует логику разбиения на страницы и анализ продукта более чистым способом.
Затем паук можно запустить для эффективного сканирования десятков тысяч объявлений:
scrapy crawl fashionphile -o products.json
В целом, Scrapy предоставляет очень масштабируемую платформу для парсинга веб-страниц.
Используйте прокси, чтобы избежать блокировки
Проблема с парсингом любого коммерческого сайта в больших масштабах неизбежно приводит к блокировке.
Fashionphile использует несколько механизмов защиты от царапин:
Ограничение скорости – Ограничивает количество запросов, отправленных с одного IP.
крышки – Требует решения CAPTCHA после определенного количества запросов.
Блокировка IP – Банит IP-адреса, выполняющие большие объемы запросов.
Ротация прокси — это эффективная стратегия, позволяющая избежать этих ограничений:
Общие прокси – Используйте прокси-сервисы, такие как BrightData, Oxylabs, Smartproxy и т. д., чтобы получить тысячи общих домашних и мобильных прокси.
Самостоятельные прокси – Для полностью частных прокси-серверов используйте инструменты управления прокси-серверами, такие как ProxyMesh, для координации серверов в центрах обработки данных.
Прокси-ротация – Ротация прокси по запросу или каждые несколько сотен запросов, чтобы постоянно использовать новые IP-адреса.
Вот пример использования прокси BrightData для каждого запроса Scrapy:
from scrapy import signals
class ProxyMiddleware:
def process_request(self, request, spider):
request.meta[‘proxy‘] = f‘http://{get_proxy()}‘
def process_response(self, request, response, spider):
return response
def process_exception(self, request, exception, spider):
return request
def get_proxy():
# Call BrightData API to get proxy
return proxy
class FashionphileSpider(scrapy.Spider):
custom_settings = {
‘DOWNLOADER_MIDDLEWARES‘: {
‘scrapy_proxies.RandomProxy‘: 100,
‘ProxyMiddleware‘: 500
}
}
# Rest of spider code
Ключевые детали:
- Включение
ProxyMiddleware
- Получение нового прокси перед каждым запросом
- Передача прокси через
request.meta
Это гарантирует, что каждый запрос использует другой IP-адрес и позволяет избежать каких-либо блокировок.
Заключение
Парсинг такого сайта, как Fashionphile, требует работы с современными страницами, отображаемыми на JavaScript, нумерацией страниц, прокси и многим другим.
Вот несколько важных выводов:
- Используйте структуры данных JSON вместо непосредственного анализа HTML.
- Разбивайте страницы по категориям/поиску для масштабирования данных.
- Используйте карты сайта или исторические данные, чтобы получить URL-адреса всех продуктов.
- Перейдите на Scrapy один раз в производственном масштабе
- Меняйте прокси, чтобы избежать защиты от ботов
Доступные данные невероятно ценны для исследования рынка, мониторинга конкурентов, привлечения потенциальных клиентов и многого другого.
Инжиниринговые усилия приносят дивиденды во всех случаях использования в бизнесе. В этом руководстве представлена схема создания собственного парсера Fashionphile.
Дайте мне знать, если у вас есть еще вопросы! Я рад помочь дать любые другие советы.