precios de mercadona por zona: qué cambia según el código postal

en cataluña, una botella de 2 litros de cola hacendado cuesta 1,10 €. en madrid o en sevilla, 0,80 €.
desde el 14 de septiembre tengo un programa que lee cada día los precios de mercadona por zona, los de todos los productos de la tienda online. el 6 de octubre leyó 743.112, repartidos en 174 zonas, unos 4.270 por zona. es un proyecto personal, sin ninguna relación con mercadona.
qué es una zona de mercadona
cada pedido de la tienda online lo prepara un almacén, y el almacén decide el catálogo y los precios. cuando escribes el código postal en la web, el servidor responde con una cabecera, X-Customer-Wh, que dice qué almacén te toca: bcn1, mad3, svq1 o un número.
para encontrarlos todos, el programa pregunta por códigos postales. los candidatos salen de geonames, y prueba 300 al día. va primero por el primer código de cada provincia, luego por el segundo, y así el mapa cubre todo el país pronto en lugar de ir de álava a zaragoza. si la tienda responde 404, es que no reparte ahí, y no se vuelve a preguntar hasta pasados 90 días.
en la web y aquí lo llamo zona. para el análisis, cada zona recibe la provincia que más se repite entre sus códigos postales. cataluña son las 21 zonas de las provincias 08, 17, 25 y 43. canarias tiene 17, y la península, 144.
el catálogo de mercadona en 6 consultas
el buscador de la tienda funciona con algolia, y cada almacén tiene un índice por idioma, como products_prod_bcn1_ca. el programa lee el índice en catalán. una consulta vacía devuelve 1.000 resultados como mucho, y un almacén tiene unos 4.300. por eso mercapy, la librería de python que hace el trabajo, parte el catálogo.
primero pide un solo resultado, con el recuento de productos de cada categoría superior. después reparte las categorías, de la más grande a la más pequeña, en grupos que no pasen de 1.000, y hace una consulta por grupo con un filtro OR. si un grupo devuelve más de 1.000, porque los recuentos se han movido entre una consulta y otra, lo parte en dos. desde la versión 2.3.0, del 4 de octubre, un almacén sale en 6 peticiones. antes hacían falta 27.
tres almacenes fallaban desde el primer día porque su índice en catalán no tiene categorías por las que filtrar. para esos, la librería parte por franjas de un campo numérico del índice, score, y divide por la mitad cualquier franja que pase de 1.000.
al final, el programa cuenta los productos únicos y los compara con el total que declara algolia. si no cuadran, la recogida queda como degradada y no toca nada. una recogida a medias no puede hacer desaparecer ningún producto, y para que un producto deje de constar en una zona tiene que faltar dos días seguidos.
la hora también cuenta. mercadona cambia los precios entre las 2 y las 4 de la madrugada. de los 296 cambios nacionales que pude fechar, 272 cayeron en esa franja, y por eso el día de recogida empieza a las 5. antes, cada almacén esperaba 24 horas desde el último éxito. como el cron pasa cada dos horas, cada día iba dos horas más tarde, hasta que se saltaba uno. hasta el 4 de octubre se perdieron así 147 de 2.141 días de almacén, un 7 %.
solo se guarda lo que cambia
si copiara el catálogo entero cada día, a unos 1,6 kb por producto, serían más de 1 gb de json diario, casi todo repetido.
el programa usa tres tablas. product_state tiene una fila por producto y zona con el precio actual. product_version solo añade una fila cuando el producto cambia en esa zona. cada estado recuerda también qué versión estaba vigente al final del día anterior, y los cambios de hoy se calculan contra esa.
el 5 de octubre había 820.298 versiones, y la mayoría decían lo mismo, porque un producto se lee igual en casi todos los almacenes. resúmenes distintos, solo 19.128. ahora cada resumen se guarda una sola vez, en una tabla cuya clave es el hash del json, y las versiones apuntan a ella. la tabla de versiones pasó de 1,6 gb a 172 mb, más 32 mb de resúmenes. la base de datos entera, de 2.096 mb a 735 mb.
antes probé timescaledb, pg-xpatch, diferencias hacia delante y hacia atrás, y lz4. timescaledb ocupaba menos, pero perdía el índice único de versión abierta y la clave foránea desde product_state. pg-xpatch perdió filas sin avisar en una copia por lotes.

qué precio se compara
un producto tiene varios precios: el de estantería, el anterior si está rebajado y el precio por kilo o por litro. los cambios comparan uno solo, tracked_price.
en los productos de tamaño fijo es el precio de estantería. en los de peso variable, como el pescado o la carne al corte, es el precio por kilo. en los datos que miré para decidirlo había 370 productos de peso variable que se vendían en dos almacenes o más. 156 tenían el mismo precio por kilo con precios de cesta distintos, y solo 3 tenían un precio por kilo distinto de verdad. una merluza de 12,77 € en sevilla y de 17,14 € en barcelona vale 11,50 €/kg en los dos sitios. solo cambia el peso de la pieza.
en los productos de pescadería que se compran a peso, mercadona publica como precio el precio por kilo multiplicado por el tamaño, o por 99 cuando no hay tamaño. una gamba congelada era el producto más caro de la base de datos, a 3.663 €. no afectaba a ninguna comparación, porque esos productos se siguen por el precio por kilo, pero la tienda muestra el precio de un paso, de 0,15 a 0,4 kg, y ahora el programa también.
las rebajas van aparte. la api de mercadona tiene un campo que debería decir si un precio ha bajado, y en 397.000 estados guardados no ha valido nunca true. el programa reconoce una rebaja por el precio anterior tachado al lado, y la guarda como reducción marcada. una bajada observada es un precio seguido más bajo que el del final de ayer, en la misma zona. si un día hay dos recogidas, los cambios se vuelven a calcular contra la misma base, y dos recogidas la misma tarde no pueden fabricar una bajada y una subida.
un solo precio en la península, salvo en cataluña
de los 4.861 productos que se vendían en al menos 20 zonas peninsulares el 6 de octubre, solo 32 tenían precios distintos según la zona. no llega al 1 %.
29 de esos 32 son bebidas con azúcar: 8 tamaños de coca-cola, 3 de cola hacendado, 4 monster, 2 red bull, 6 batidos y bebidas de leche hacendado, la energética hacendado, 2 preparados lácteos con cereales, la horchata y 2 tónicas hacendado. todas cuestan más en las 21 zonas catalanas y en ninguna otra. las versiones zero tienen el mismo precio en todas partes.

es el impuesto catalán sobre las bebidas azucaradas envasadas, que es de 0,10 € por litro si la bebida tiene entre 5 y 8 gramos de azúcar por 100 ml, y de 0,15 € si tiene más. en la cola hacendado de 2 litros, la diferencia es de 0,30 €, justo 0,15 € por litro. en la coca-cola de 2 litros es de 0,37 €, y en el monster de medio litro, de 0,10 €. esas ya no salen tan redondas.
de los 32, los otros 3 son dos productos de limón y las pechugas de pollo enteras congeladas.
canarias, la fruta más cara
hay 82 productos de fruta y verdura que se venden en canarias y en al menos 20 zonas peninsulares. comparando la mediana de cada sitio, 64 son más caros allí y 5, más baratos. el brócoli vale 5,80 €/kg en las 17 zonas canarias, igual desde el 14 de septiembre, y 2,70 €/kg en las otras 157.
tres semanas, y casi todo sube
cogí las 71 zonas con una recogida completa el 14 de septiembre y el 6 de octubre. me quedé con 3.526 productos vendidos por unidad, los que se venden en al menos 30 de esas zonas y no tenían ningún precio tachado ninguno de los dos días. un producto cuenta como subida si ha subido en la mayoría de sus zonas.
90 han subido. 2 han bajado, la leche semidesnatada y la desnatada hacendado, 1 céntimo cada una y en las 71 zonas. ninguno de los 92 ha cambiado de tamaño.
el número depende del día de inicio. si empiezo a contar el 15 o el 16 de septiembre, las subidas son 78 y 59. las bajadas siguen siendo las mismas 2.

la fruta de temporada va más deprisa. el 14 de septiembre, el melón piel de sapo valía 0,70 €/kg en la península. el 21 pasó a 0,90, el 29 a 1,35 y el 6 de octubre a 2,20, en las 144 zonas peninsulares.
lo que aún falta
la web que lo mostrará, en catalán, aún no es pública. pondrás tu código postal y verás el precio de cada producto en tu zona y cómo ha cambiado desde el 14 de septiembre.
todo esto sale de tres semanas de datos. la idea es dejar el programa recogiendo cada día durante años, y la recogida es lo primero que hice porque un precio que no se lee hoy ya no se puede recuperar.