
Как IDEFICS2 отвечает на незы
15 июля 2025 г.Такие рыночные площадки, как eBay или Vinted, всегда являются интересной целью для различных актеров: от брендов, желающих контролировать рынок подержанного до скальперов, готовых получить что-то в продаже и перепродать его с целью получения прибыли.
Учитывая весь этот интерес к ним, эти рыночные площадки необходимы для защиты себя от ботов и мошеннической деятельности, становясь сложной целью для очистки.
В этом эпизоде лаборатории, нашей серии углубленных статей, мы сосредоточимся на Vinted, и мы посмотрим, как мы можем с этически соскрести его после изучения бэкэнда.
Что винтировано?
Визитявляется подержанным рынком, родившимся в 2008 году в Литве, где люди могут покупать и продавать подержанные вещи из 21 разных стран. Согласно аналогичному Wheb, на сайте почти три миллиона посещений,
С сотнями миллионов предметов, продающих на платформе, существует яркая экосистема продавцов и покупателей, и, как и на каждом эффективном рынке, люди пытаются заработать немного денег на платформе, покупая низкий и продавая в некоторых случаях, помогая ботам.
Чтобы смягчить трафик бота, платформа представила некоторые анти-ботские решения, такие как DataDome. В следующих главах мы увидим, как мы можем соскрести публичные данные с веб -сайта, используя его внутренние API и технику под названием «Factory Cookie».
Как работает винтированная анти-ботская система
Vinted имеет как веб -сайт, так и приложение, так что давайте посмотрим, как они оба работают, чтобы выбрать самый стабильный и простой подход для соскоба.
Сайт
Допустим, мы хотим, чтобы данные из определенной категории элементов на платформе. При просмотре веб -сайта мы видим, что внутренний API со следующей конечной точкой обрабатывает страницу этих элементов.
https://www.vinted.it/web/api/core/catalog/items?page=1&per_page=96&time=1745925814&search_text=&catalog_ids=1920&catalog_from=0&brand_ids=&status_ids=&color_ids=&material_ids
Конечно, если мы попытаемся скопировать этот URL и вставить его в новую вкладку браузера, мы получим сообщение об ошибке.
Это связано с тем, что нам нужен набор необходимых файлов cookie для разрешения, чтобы увидеть данные.
В частности, мы сосредоточены на:
access_token_web:Это токен авторизации, который длится два часа, как мы видим
копировав его в онлайн -отладчик JWT. rupresh_token_web:который является токеном, который используется в качестве параметра, когда нам нужно освежить токен Auth, который можно увидеть ранее
DataDome:Это токен, который мы получаем, когда проходим проверку безопасности DataDome. Его присутствие однозначно говорит нам, что звонки API, которые мы собираемся сделать, не будут работать, пока мы не получим действительный токен DataAdome, что может быть довольно сложным.
Мобильное приложение
Проверка трафика мобильного приложения с помощью HTTP Toolkit дала нам еще одну точку зрения на бэкэнд.
Конечная точка для извлечения продуктов для определенной категории - следующая
https://www.vinted.fr/api/v2/homepage/women?column_count=2&homepage_session_id=f2c89e7b-27b5-4d99-8e76-3e2bf1d55c23&version=3
И, если нам нужно получить больше элементов, нам нужно добавить следующий параметр URL -адреса
https://www.vinted.fr/api/v2/homepage/women?column_count=2&homepage_session_id=f2c89e7b-27b5-4d99-8e76-3e2bf1d55c23&next_page_token=feed_max_score:1&version=3
Как видите, нет традиционной концепции страницы, но чем больше времени мы называем эту конечную точку с одним идентификатором сеанса, тем больше элементов мы получаем.
В этом случае токен авторизации используется в заголовках запроса
У нас нет никакого обновления, и что еще более интересно, а не токен DataDome. Это означает, что при использовании веб -версии DataDome настроен для защиты конечной точки. Однако в мобильном приложении это не так. Раньше это не что -то невидимое: случается, что мобильные конечные точки не находятся под защитой бота, в основном по двум причинам:
Они обычно немного сложнее найти, поэтому неквалифицированные скребки не используют их, и владельцы веб -сайтов предпочитают не защищать их
Большая часть трафика поступает из приложения, и, поскольку эти анти-ботские системы выставляются в соответствии с запросом, используя их только для веб-сайта, а не для приложения заставляет компанию сэкономить много денег.
Из -за анализа веб -сайта и приложения, кажется, легче использовать конечные точки приложения, поскольку DataDome не защищает их, но нам все еще нужно выяснить, как получить токены авторизации.
Как получить токен разрешения
Это настоящая первая проблема, которую мы должны справиться для соскоба. Фактически, как осмотр веб -сайта, так и приложение, нет звонка ни одному эмитенту токена.
Не редко можно увидеть в некоторых приложениях призыв к конкретной конечной точке, которая выдает токен, который будет использоваться позже. В этих случаях все, что вам нужно сделать, это воспроизвести один и тот же вызов, захватить токен, а затем изменить заголовки запроса, чтобы включить его.
В винтированном случае токен, по -видимому, генерируется во время полета в бэкэнд: от первых вызовов, как на мобильных устройствах, так и на веб -сайте, мы видим токены в заголовках или в файлах cookie (в случае веб -сайта).
Хорошо, что токены, сгенерированные веб -сайтом, также могут быть использованы для приложения, и это заставило меня задуматься о решении для нашего скребка.
Фабрика печенья
Идея довольно проста: что, если я построю конечную точку API, которая, когда вы называете, возвращает мне действительный токен для использования в Vinted Mobile Endpoint?
Поэтому я могу позвонить в его сценарий, получить токен, а затем использовать конечную точку мобильного API Vinted для очистки данных.
Ну, это кажется блестящей идеей, но я до сих пор не понял, как генерировать эти токены, так как, когда я загружаю домашнюю страницу винтированных, куки генерируются в первую очередь без вызовов API.
Но что, если моя фабрика печенья делает то же самое?
Пример кода
Благодаря курсору я создал эту небольшую конечную точку API, работающую локально на моем Mac.
from fastapi import FastAPI
from pydantic import BaseModel
from playwright.async_api import async_playwright
import asyncio
app = FastAPI()
class RequestData(BaseModel):
url: str
cookie_name: str
async def get_cookie(url, cookie_name):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
await page.goto(url)
await page.wait_for_load_state('networkidle')
cookies = await context.cookies()
await browser.close()
for cookie in cookies:
if cookie['name'] == cookie_name:
return cookie['value']
return None
@app.post("/get-cookie")
async def get_cookie_endpoint(data: RequestData):
token = await get_cookie(data.url, data.cookie_name)
if token:
return {"cookie_value": token}
else:
return {"error": "Cookie not found"}
Этот простой API позволяет вамИзвлеките конкретный файл cookie с любого веб -сайтаИспользование драматурга и FASTAPI. Он управляет безголовым браузером хрома, посещает целевой URL и ищет печенье по имени.
Мы импортируем следующие пакеты:
FASTAPI: Используется для создания простого веб -API.
BaseModel: Pydantic Class для проверки входящих данных.
Playwright.async_api: Асинхронный API для автоматизации браузера.
асинсио: Требуется для работы асинхронных функций.
Затем мы инициализируем экземпляр приложения FASTAPI сapp = fastapi ()Полем Далее мы определяем модель пидантики под названиемRequestData,который ожидает две части информации в входящем запросе POST: URL -адрес посетить и название интересного нам файла cookie. Это помогает гарантировать, что API получает структурированный и действительный ввод от клиентов.
Основная функциональность заключается вget_cookieфункция Это асинхронная функция, которая принимает URL и имя печенья. Он использует Playwright для запуска безголового браузера Chromium, создает новый контекст браузера и ориентируется на заданный URL. После ожидания, пока страница завершит загрузку полностью, используя драматургNetworkIdleУстановите, что даже фоновый JavaScript урегулировал, он получает все файлы cookie, хранящиеся в контексте браузера.
Затем браузер закрыт, чтобы освободить ресурсы. Затем функция итерации по сравнению с собранными файлами cookie и возвращает значение того, которое соответствует предоставленному имени. Если куки не найден, он просто возвращаетсяНиктоПолем
Наконец, конечная точка Fastapi/get-cookieопределяется для обработки входящих запросов.
Когда запрос получен, Fastapi автоматически анализирует входящий JSON и отображает его наRequestDataмодель. Аget_cookieФункция затем вызывается с пропорциональнойURLиcookie_nameПолем Если найден соответствующий файл cookie, его значение возвращается как JSON.
Вы также можете найти весь сценарий вapp.pyФайл в репозитории лаборатории.
Как заставить API жить
Возьмите этот абзац с зерном соли, так как это не моя область.
Основываясь на моем исследовании, мы можем заставить наш API вживую, просто используя эту команду:
gunicorn app:app -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
Насколько я понял,Стрелобь, широко используемый сервер Python WSGI (интерфейс шлюза веб-сервера)-это то, что нам нужно для его запуска.
WSGI определяет простой, синхронный интерфейс между вашим кодом Python и веб -сервером, таким как стрелочный или UWSGI. В то время это стало основой для почти всех основных веб -приложений Python.
Приложение WSGI работает очень линейным образом: сервер получает запрос, передает его в ваше приложение, ожидает ответа и только затем переходит к следующему запросу.
Эта модель проста и надежна, но она такжеограничен одним запросом за один раз на работникаПолем Он отлично подходит для традиционных веб-приложений, которые рендеринг HTML или взаимодействие с базой данных, но он борется при обработке большого количества одновременных пользователей, долгоживущих соединений или обновлений в реальном времени.
Перенесемся на сегодняшний день, и у насАсги(Асинхронный интерфейс шлюза сервера). Он был представлен, чтобы привести Python в современную эруасинхронное программирование, включение таких вещей, как веб -токеты, длинные опросы и одновременные задачи без раскручивания новых потоков или процессов.
Asgi - это то, что позволяетFASTAPIВStarletteи более новые версии Django для поддержки высокопроизводительных асинхронных функций. В отличие от WSGI, приложения ASGI могут обрабатыватьнесколько запросов одновременноВ пределах одного работника, что делает их идеальными для API, потоковых данных и всего, что выигрывает от неблокирующего ввода-вывода (например, соскоба с драматургом).
В нашем случае мы объединяем оружие сUvicorn, сервер ASGI, на котором построен FASTAPI. Это спаривание дает нам лучшее из обоих миров: одушечный корень для надежного управления процессами и Uvicorn для высокопроизводительной асинхронной обработки.
Я не копал эту тему дальше, так как конечная точка, которую я создаю, для личного использования на моем Mac, но рассмотрите какие -либо проблемы безопасности и масштабируемости, прежде чем развернуть какое -либо подобное решение на публике.
Наконец -то соскребая винта
После понимания того, как получить токен Auth, соскребая данные из Vinted - это кусок пирога, если мы следуем некоторым уловкам. Я делюсь с вами полным кодом внутри файлаscraper.py,Но мы можем подвести итог кода в следующих шагах.
Называя API
С помощью следующего кода мы называем конечную точку API и храним токен Auth в переменной в нашем сценарии.
def get_bearer_token():
"""
Get bearer token by making a call to the local API
"""
url = "http://127.0.0.1:8000/get-cookie"
headers = {
"Content-Type": "application/json"
}
data = {
"url": "https://www.vinted.it",
"cookie_name": "access_token_web"
}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
token_data = response.json()
return token_data.get("cookie_value")
else:
print(f"Error getting token: {response.status_code}")
print(response.text)
return None
except Exception as e:
print(f"Exception when getting token: {str(e)}")
return None
Прежде чем соскребить первую страницу
Теперь мы можем настроить вызов API, чтобы получить первые элементы из категории женской одежды Vinted, создав случайную строку сеанса и анонимный идентификатор пользователя, и обновив заголовки новым токеном аутентификации.
if not homepage_session_id:
homepage_session_id = str(uuid.uuid4())
if not x_session_id:
x_session_id = str(uuid.uuid4())
# Generate a random x-anon-id
x_anon_id = str(uuid.uuid4())
url = "https://www.vinted.fr/api/v2/homepage/women"
# Query parameters
params = {
"column_count": 2,
"homepage_session_id": homepage_session_id,
"version": 3
}
# Add next_page_token if provided
if next_page_token:
params["next_page_token"] = next_page_token
# Headers from the curl command
headers = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "it-fr",
"authorization": f"Bearer {bearer_token}",
"connection": "keep-alive",
"host": "www.vinted.fr",
"short-bundle-version": "25.17.0",
"user-agent": "vinted-ios Vinted/25.17.0 (lt.manodrabuziai.fr; build:30160; iOS 18.4.1) iPhone17,2",
"x-app-version": "25.17.0",
"x-device-model": "iPhone17,2",
"x-device-uuid": "e121b6c28a0ae580f66635c1335acd24",
"x-anon-id": x_anon_id,
"x-session-id": x_session_id,
"x-icloud-identifier": "_e390798f99c3643239475f3ececd12f1"
}
Называя API и анализирует свои результаты.
После настройки заголовков мы можем перевернуть вызовы по конечной точке API и анализировать результаты.
В нашем случае я установил жесткую остановку после 100 вызовов или когда у нас кончились продукты для сокраски из определенной категории.
Это простой запрос на Python с некоторым анализом JSON, поэтому нет необходимости комментировать дальше.
Выводы
Идея этой статьи состоит в том, чтобы показать другую технику для соскоба, которая использует ферму Cookie, чтобы позволить нашим программам обойти аутентификацию API. Это также можно использовать при работе с анти-ботами, генерируя действительные файлы cookie для использования в сеансах. В этом случае это может быть гораздо сложнее, так как для его получения потребовалось бы более незамеченное и более человеческое браузер.
Весь созданный код предназначен только для образовательных целей и не должен использоваться для затопления винтированных или любого другого веб -сайта, который работает аналогичным образом с запросами.
Я надеюсь, что вам понравилось, и, пожалуйста, дайте мне знать в разделе комментариев.
Статья является частью«Лаборатория»серияПьерлуиджи ВинсгуерраПолем Проверьте егоПодмазочныйСтраница для получения дополнительных знаний о скребке.
Оригинал