mirror of
https://github.com/catdevnull/preciazo.git
synced 2024-11-22 14:16:19 +00:00
parsear name y imageUrl
This commit is contained in:
parent
08f62c78db
commit
925175ba9d
12 changed files with 146 additions and 21 deletions
2
db-datos/drizzle/0002_wild_amazoness.sql
Normal file
2
db-datos/drizzle/0002_wild_amazoness.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE precios ADD `name` text;--> statement-breakpoint
|
||||
ALTER TABLE precios ADD `image_url` text;
|
93
db-datos/drizzle/meta/0002_snapshot.json
Normal file
93
db-datos/drizzle/meta/0002_snapshot.json
Normal file
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"version": "5",
|
||||
"dialect": "sqlite",
|
||||
"id": "cbd90a60-7568-489f-ac45-95bd8818ffbd",
|
||||
"prevId": "a565621c-046e-4f4d-b505-104e2c4f2b6c",
|
||||
"tables": {
|
||||
"precios": {
|
||||
"name": "precios",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"ean": {
|
||||
"name": "ean",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"fetched_at": {
|
||||
"name": "fetched_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"precio_centavos": {
|
||||
"name": "precio_centavos",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"in_stock": {
|
||||
"name": "in_stock",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"warc_record_id": {
|
||||
"name": "warc_record_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"parser_version": {
|
||||
"name": "parser_version",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"image_url": {
|
||||
"name": "image_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,13 @@
|
|||
"when": 1703374278842,
|
||||
"tag": "0001_spotty_red_hulk",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "5",
|
||||
"when": 1703452301821,
|
||||
"tag": "0002_wild_amazoness",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -9,6 +9,8 @@ export const precios = sqliteTable("precios", {
|
|||
url: text("url").notNull(),
|
||||
warcRecordId: text("warc_record_id"),
|
||||
parserVersion: integer("parser_version"),
|
||||
name: text("name"),
|
||||
imageUrl: text("image_url"),
|
||||
});
|
||||
|
||||
export type Precio = typeof precios.$inferSelect;
|
||||
|
|
|
@ -55,14 +55,17 @@ export function getCarrefourProduct(html: string | Buffer): Precioish {
|
|||
|
||||
const precioCentavos = priceFromMeta(dom);
|
||||
|
||||
// const productLd = findJsonLd(dom, "Product");
|
||||
const ean = eanFromSeedState(dom);
|
||||
|
||||
const ld = getProductJsonLd(dom);
|
||||
const name = ld.name;
|
||||
const imageUrl = ld.image;
|
||||
const inStock =
|
||||
ld.offers.offers[0].availability === "http://schema.org/InStock";
|
||||
|
||||
return {
|
||||
name,
|
||||
imageUrl,
|
||||
ean,
|
||||
precioCentavos,
|
||||
inStock,
|
||||
|
|
|
@ -34,5 +34,10 @@ export function getCotoProduct(html: string | Buffer): Precioish {
|
|||
const ean = getEanFromText(dom);
|
||||
const precioCentavos = getPriceFromText(dom);
|
||||
|
||||
return { ean, precioCentavos };
|
||||
const name = dom.document.querySelector("h1.product_page")?.textContent;
|
||||
const imageUrl = dom.document.querySelector<HTMLImageElement>(
|
||||
".productImageZoom img"
|
||||
)?.src;
|
||||
|
||||
return { name, imageUrl, ean, precioCentavos };
|
||||
}
|
||||
|
|
|
@ -10,10 +10,14 @@ export function getDiaProduct(html: string | Buffer): Precioish {
|
|||
const precioCentavos = priceFromMeta(dom);
|
||||
|
||||
const ld = getProductJsonLd(dom);
|
||||
const name = ld.name;
|
||||
const imageUrl = ld.image;
|
||||
const inStock =
|
||||
ld.offers.offers[0].availability === "http://schema.org/InStock";
|
||||
|
||||
return {
|
||||
name,
|
||||
imageUrl,
|
||||
ean,
|
||||
precioCentavos,
|
||||
inStock,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/// <reference lib="dom" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
import { Database } from "bun:sqlite";
|
||||
import { drizzle } from "drizzle-orm/bun-sqlite";
|
||||
import * as schema from "db-datos/schema.js";
|
||||
|
@ -14,7 +12,7 @@ import pMap from "p-map";
|
|||
import { and, eq, sql } from "drizzle-orm";
|
||||
|
||||
const DEBUG = false;
|
||||
const PARSER_VERSION = 1;
|
||||
const PARSER_VERSION = 2;
|
||||
|
||||
const sqlite = new Database("sqlite.db");
|
||||
const db = drizzle(sqlite, { schema });
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import { error } from "@sveltejs/kit";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
import { db, schema } from "$lib/server/db";
|
||||
import { ilike, like, sql } from "drizzle-orm";
|
||||
const { precios } = schema;
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const q = db
|
||||
.select({ ean: schema.precios.ean })
|
||||
.from(schema.precios)
|
||||
.where(
|
||||
like(schema.precios.url, `https://diaonline.supermercadosdia.com.ar%`),
|
||||
)
|
||||
.groupBy(schema.precios.ean)
|
||||
.select({ ean: precios.ean, name: precios.name })
|
||||
.from(precios)
|
||||
.groupBy(precios.ean)
|
||||
.having(sql`max(length(name))`)
|
||||
.orderBy(sql`random()`)
|
||||
.limit(150);
|
||||
const precios = await q;
|
||||
return { precios };
|
||||
const res = await q;
|
||||
return { precios: res };
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{#each data.precios as product}
|
||||
<li>
|
||||
<a href={`/ean/${product.ean}`}>
|
||||
{product.ean}
|
||||
{product.name}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
import { error } from "@sveltejs/kit";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { eq, max } from "drizzle-orm";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
import { db, schema } from "$lib/server/db";
|
||||
const { precios } = schema;
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const precios = await db.query.precios.findMany({
|
||||
where: eq(schema.precios.ean, params.ean),
|
||||
});
|
||||
if (precios.length === 0) return error(404, "Not Found");
|
||||
const q = db
|
||||
.select()
|
||||
.from(precios)
|
||||
.where(eq(precios.ean, params.ean))
|
||||
.groupBy(precios.warcRecordId)
|
||||
.having(max(precios.parserVersion));
|
||||
const res = await q;
|
||||
if (res.length === 0) return error(404, "Not Found");
|
||||
|
||||
return { precios };
|
||||
const meta = res.find((p) => p.name);
|
||||
|
||||
return { precios: res, meta };
|
||||
};
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
{#if data.meta}
|
||||
<h1 class="text-3xl font-bold">{data.meta.name}</h1>
|
||||
<img src={data.meta.imageUrl} class="max-h-48" />
|
||||
{/if}
|
||||
|
||||
<ul>
|
||||
{#each data.precios as precio}
|
||||
<li>
|
||||
|
|
Loading…
Reference in a new issue