-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(scripts): scrape and save shows from vogue
This patch adds a Scrapy Python script to scrape show data and reviews from Vogue. Note that this approach only gets the first nine looks for each show. Vogue implements some JS-only pagination and thus Scrapy is unable to "load more" looks. I will look into a JS-based scraping solution that e.g. runs a headless browser, but for now, this works OK. This patch then adds a Node.js script that will import all those shows (that are saved from Vogue.com to JSON via Scrapy) to my Postgres database via the Prisma ORM. Closes: NC-644
- Loading branch information
1 parent
8c59494
commit 986e27d
Showing
8 changed files
with
94,405 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// Script to save the data scraped via `scripts/python/spiders/vogue.py` to the | ||
// Postgres database via the Prisma ORM for type safe data transformations. | ||
|
||
import fs from 'fs' | ||
import path from 'path' | ||
|
||
import { type Prisma, Sex, SeasonName, PrismaClient } from '@prisma/client' | ||
import ProgressBar from 'progress' | ||
|
||
import example from './vogue/resort-2024.json' | ||
|
||
const PATH = '../../../public/data/vogue/shows.json' | ||
|
||
type Show = (typeof example)[number] | ||
|
||
const vogue: Prisma.PublicationCreateInput = { | ||
name: 'Vogue', | ||
avatar: 'https://www.vogue.com/verso/static/vogue/assets/us/logo.svg', | ||
} | ||
|
||
const prisma = new PrismaClient({ | ||
datasources: { db: { url: process.env.DATABASE_URL } }, | ||
}) | ||
|
||
export async function save() { | ||
const json = fs.readFileSync(path.resolve(__dirname, PATH), 'utf8') | ||
const shows = JSON.parse(json) as Show[] | ||
const bar = new ProgressBar( | ||
'saving vogue shows [:bar] :rate/sps :current/:total :percent :etas', | ||
{ | ||
complete: '=', | ||
incomplete: ' ', | ||
width: 20, | ||
total: shows.length, | ||
}, | ||
) | ||
/* eslint-disable-next-line no-restricted-syntax */ | ||
for await (const show of shows) { | ||
await prisma.show.create({ data: getData(show) }) | ||
bar.tick() | ||
} | ||
} | ||
|
||
void save() | ||
|
||
////////////////////////////////////////////////////////////////// | ||
|
||
function caps(sentence: string): string { | ||
return sentence | ||
.split(' ') | ||
.map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`) | ||
.join(' ') | ||
} | ||
|
||
function getSeason(show: Show) { | ||
// e.g. "SPRING 2023 READY-TO-WEAR", "RESORT 2024" | ||
const [season, yr] = show.season.split(' ') | ||
let name: SeasonName | ||
switch (season) { | ||
case 'SPRING': | ||
name = SeasonName.SPRING | ||
break | ||
case 'RESORT': | ||
name = SeasonName.RESORT | ||
break | ||
case 'FALL': | ||
name = SeasonName.FALL | ||
break | ||
default: | ||
throw new Error(`Unknown season: ${season}`) | ||
} | ||
const year = Number(yr) | ||
if (Number.isNaN(year)) throw new Error(`Invalid year: ${year}`) | ||
return { name, year } | ||
} | ||
|
||
function getData(show: Show) { | ||
const season: Prisma.SeasonCreateInput = getSeason(show) | ||
let review: Prisma.ReviewCreateWithoutShowInput | undefined | ||
if (show.author_name && show.author_url) | ||
review = { | ||
title: show.title, | ||
subtitle: null, | ||
score: null, | ||
summary: null, | ||
content: show.content.join('\n'), | ||
url: show.url, | ||
date: show.date ? new Date(show.date) : null, | ||
author: { | ||
connectOrCreate: { | ||
where: { name: show.author_name }, | ||
create: { | ||
name: show.author_name, | ||
url: show.author_url, | ||
avatar: show.author_avatar, | ||
}, | ||
}, | ||
}, | ||
publication: { | ||
connectOrCreate: { where: { name: vogue.name }, create: vogue }, | ||
}, | ||
} | ||
let name = `${show.brand} ${caps(show.season)}` | ||
if (show.title.includes('Menswear')) name += ' Menswear' | ||
|
||
// TODO Vogue will list the same collection twice (once under "Menswear" and | ||
// again without "Menswear") if that collection is unisex. I can fix this by | ||
// looking for collections that have the same review content and other data, | ||
// and then merge those collections under the same unisex name. | ||
const collection: Prisma.CollectionCreateInput = { | ||
name, | ||
sex: show.title.includes('Menswear') ? Sex.MAN : Sex.WOMAN, | ||
season: { | ||
connectOrCreate: { | ||
where: { name_year: { name: season.name, year: season.year } }, | ||
create: season, | ||
}, | ||
}, | ||
} | ||
const looks: Prisma.LookCreateWithoutShowInput[] = show.looks.map((look) => { | ||
const image: Prisma.ImageCreateWithoutLookInput = { url: look.src } | ||
return { | ||
number: look.number, | ||
image: { connectOrCreate: { where: { url: image.url }, create: image } }, | ||
} | ||
}) | ||
const brand: Prisma.BrandCreateInput = { | ||
name: show.brand, | ||
description: null, | ||
tier: null, | ||
avatar: null, | ||
url: null, | ||
} | ||
const data: Prisma.ShowCreateInput = { | ||
name, | ||
url: show.url, | ||
description: null, | ||
criticReviewSummary: null, | ||
consumerReviewSummary: null, | ||
date: show.date ? new Date(show.date) : null, | ||
location: null, | ||
reviews: review ? { create: review } : undefined, | ||
season: { | ||
connectOrCreate: { | ||
where: { name_year: { name: season.name, year: season.year } }, | ||
create: season, | ||
}, | ||
}, | ||
collections: { connectOrCreate: { where: { name }, create: collection } }, | ||
looks: { create: looks }, | ||
brands: { connectOrCreate: { where: { name: brand.name }, create: brand } }, | ||
} | ||
return data | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
{ | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c", | ||
"title": "A.L.C. Resort 2024 Collection | Vogue", | ||
"content": [ | ||
"<p>Polish was the guiding idea behind Andrea Lieberman’s resort collection. “Whether it’s a holiday party or events, we are bringing a more sleek feeling to it, which is always kind of my first love and where I started,” Lieberman said. This was reflected in details as granular as the baguette-shaped rhinestones embellishing the satin dresses and the rectangular sequins on the compact knit dresses. Sharp edges, clean lines—but not simple.</p>", | ||
"<p>Lieberman has always prided herself on making real clothing with a few special details to make it stand out. This season, those core items include miles-long flared trousers paired with a black cropped blazer, several duchesse satin dresses and skirts with bijoux embellishments, strapless silhouettes in smart black going out tops and a raspberry ruffled mini dress. Nothing groundbreaking, but the collection is infinitely wearable and, yes, sleek.</p>" | ||
], | ||
"brand": "A.L.C.", | ||
"season": "RESORT 2024", | ||
"author_name": "Sarah Spellings", | ||
"author_url": "https://www.vogue.com/contributor/sarah-spellings", | ||
"author_avatar": "https://assets.vogue.com/photos/63e28ecedb8fe3439bbc31b5/1:1/w_90%2Cc_limit/undefined", | ||
"date": "June 11, 2023", | ||
"looks": [ | ||
{ | ||
"number": 1, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#1", | ||
"src": "https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_2560%2Cc_limit/00001-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_120,c_limit/00001-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_240,c_limit/00001-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_320,c_limit/00001-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_640,c_limit/00001-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_960,c_limit/00001-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_1280,c_limit/00001-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_1600,c_limit/00001-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_1920,c_limit/00001-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435ab117ea73b4611c52e/master/w_2240,c_limit/00001-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 2, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#2", | ||
"src": "https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_2560%2Cc_limit/00002-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_120,c_limit/00002-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_240,c_limit/00002-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_320,c_limit/00002-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_640,c_limit/00002-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_960,c_limit/00002-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_1280,c_limit/00002-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_1600,c_limit/00002-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_1920,c_limit/00002-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435abbbb79c09d48cdad9/master/w_2240,c_limit/00002-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 3, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#3", | ||
"src": "https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_2560%2Cc_limit/00003-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_120,c_limit/00003-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_240,c_limit/00003-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_320,c_limit/00003-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_640,c_limit/00003-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_960,c_limit/00003-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_1280,c_limit/00003-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_1600,c_limit/00003-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_1920,c_limit/00003-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435acc943a2672e3e7d37/master/w_2240,c_limit/00003-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 4, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#4", | ||
"src": "https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_2560%2Cc_limit/00004-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_120,c_limit/00004-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_240,c_limit/00004-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_320,c_limit/00004-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_640,c_limit/00004-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_960,c_limit/00004-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_1280,c_limit/00004-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_1600,c_limit/00004-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_1920,c_limit/00004-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435aee1122c2ab0dca909/master/w_2240,c_limit/00004-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 5, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#5", | ||
"src": "https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_2560%2Cc_limit/00005-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_120,c_limit/00005-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_240,c_limit/00005-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_320,c_limit/00005-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_640,c_limit/00005-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_960,c_limit/00005-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_1280,c_limit/00005-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_1600,c_limit/00005-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_1920,c_limit/00005-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435b00def6fd42956e337/master/w_2240,c_limit/00005-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 6, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#6", | ||
"src": "https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_2560%2Cc_limit/00006-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_120,c_limit/00006-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_240,c_limit/00006-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_320,c_limit/00006-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_640,c_limit/00006-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_960,c_limit/00006-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_1280,c_limit/00006-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_1600,c_limit/00006-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_1920,c_limit/00006-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435afed9500b6de5d4f87/master/w_2240,c_limit/00006-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 7, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#7", | ||
"src": "https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_2560%2Cc_limit/00007-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_120,c_limit/00007-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_240,c_limit/00007-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_320,c_limit/00007-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_640,c_limit/00007-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_960,c_limit/00007-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_1280,c_limit/00007-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_1600,c_limit/00007-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_1920,c_limit/00007-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435b1bbb79c09d48cdadb/master/w_2240,c_limit/00007-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 8, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#8", | ||
"src": "https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_2560%2Cc_limit/00008-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_120,c_limit/00008-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_240,c_limit/00008-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_320,c_limit/00008-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_640,c_limit/00008-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_960,c_limit/00008-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_1280,c_limit/00008-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_1600,c_limit/00008-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_1920,c_limit/00008-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435b4dc90cc14d7b8ffe5/master/w_2240,c_limit/00008-alc-resort-2024-credit-brand.jpg 2240w" | ||
}, | ||
{ | ||
"number": 9, | ||
"url": "https://www.vogue.com/fashion-shows/resort-2024/a-l-c/slideshow/collection#9", | ||
"src": "https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_2560%2Cc_limit/00009-alc-resort-2024-credit-brand.jpg", | ||
"srcset": "https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_120,c_limit/00009-alc-resort-2024-credit-brand.jpg 120w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_240,c_limit/00009-alc-resort-2024-credit-brand.jpg 240w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_320,c_limit/00009-alc-resort-2024-credit-brand.jpg 320w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_640,c_limit/00009-alc-resort-2024-credit-brand.jpg 640w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_960,c_limit/00009-alc-resort-2024-credit-brand.jpg 960w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_1280,c_limit/00009-alc-resort-2024-credit-brand.jpg 1280w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_1600,c_limit/00009-alc-resort-2024-credit-brand.jpg 1600w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_1920,c_limit/00009-alc-resort-2024-credit-brand.jpg 1920w, https://assets.vogue.com/photos/648435b2bbb79c09d48cdadd/master/w_2240,c_limit/00009-alc-resort-2024-credit-brand.jpg 2240w" | ||
} | ||
] | ||
} |
Oops, something went wrong.