Files
wallabicher/platforms/wallapop_platform.py
Omar Sánchez Pizarro 4111f57564 add abstraction ob platform and article + vinted
"

Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-10-10 14:58:27 +02:00

113 lines
4.1 KiB
Python

import requests
import logging
import time
import datetime
from platforms.base_platform import BasePlatform
from models.article import Article
REQUEST_RETRY_TIME = 5
class WallapopPlatform(BasePlatform):
"""Wallapop marketplace platform implementation"""
def __init__(self, item_monitor):
super().__init__(item_monitor)
self.logger = logging.getLogger(__name__)
def get_platform_name(self):
return "wallapop"
def create_url(self):
"""Create Wallapop API search URL"""
url = (
f"http://api.wallapop.com/api/v3/search"
f"?source=search_box"
f"&keywords={self._item_monitor.get_search_query()}"
f"&order_by=newest"
f"&language=es_ES"
)
# Only include latitude and longitude if both are not 0
if self._item_monitor.get_latitude() != 0 and self._item_monitor.get_longitude() != 0:
url += (
f"&latitude={self._item_monitor.get_latitude()}"
f"&longitude={self._item_monitor.get_longitude()}"
)
if self._item_monitor.get_min_price() != 0:
url += f"&min_sale_price={self._item_monitor.get_min_price()}"
if self._item_monitor.get_max_price() != 0:
url += f"&max_sale_price={self._item_monitor.get_max_price()}"
if self._item_monitor.get_max_distance() != 0:
url += f"&distance_in_km={self._item_monitor.get_max_distance()}"
if self._item_monitor.get_condition() != "all":
url += f"&condition={self._item_monitor.get_condition()}" # new, as_good_as_new, good, fair, has_given_it_all
return url
def get_request_headers(self):
"""Get Wallapop-specific headers"""
headers = super().get_request_headers()
headers['X-DeviceOS'] = '0'
return headers
def fetch_articles(self):
"""Fetch articles from Wallapop API"""
url = self.create_url()
while True:
try:
headers = self.get_request_headers()
response = requests.get(url, headers=headers)
response.raise_for_status()
break
except requests.exceptions.RequestException as err:
self.logger.error(f"Request Exception: {err}")
time.sleep(REQUEST_RETRY_TIME)
json_response = response.json()
json_items = json_response['data']['section']['payload']['items']
articles = self.parse_response(json_items)
return articles
def parse_response(self, json_items):
"""Parse Wallapop JSON response into Article objects"""
articles = []
for json_article in json_items:
article = self._parse_single_article(json_article)
if article:
articles.append(article)
return articles
def _parse_single_article(self, json_data):
"""Parse a single Wallapop article from JSON"""
try:
# Extract images with proper format
images = [img['urls']['medium'] for img in json_data['images'][:3]]
# Convert timestamp to datetime string
ts = int(json_data['modified_at'])
dt = datetime.datetime.fromtimestamp(ts / 1000)
modified_at = dt.strftime("%Y-%m-%d %H:%M:%S")
return Article(
id=json_data['id'],
title=json_data['title'],
description=json_data['description'],
price=json_data['price']['amount'],
currency=json_data['price']['currency'],
location=json_data['location']['city'],
allows_shipping=json_data['shipping']['user_allows_shipping'],
url="https://wallapop.com/item/" + json_data['web_slug'],
images=images,
modified_at=modified_at,
platform=self.get_platform_name()
)
except (KeyError, ValueError) as e:
self.logger.error(f"Error parsing Wallapop article: {e}")
return None