Compare commits

..

2 Commits

Author SHA1 Message Date
2c4dd12820 Merge branch 'dev' of https://git.23cm.cn/toom1996/spider into dev
# Conflicts:
#	internal/ingest/client.go
#	internal/ingest/hashid.go
2026-09-20 00:47:24 +08:00
fde57984e7 update 2026-09-20 00:44:47 +08:00
16 changed files with 3803 additions and 276 deletions

BIN
bin/spider Normal file

Binary file not shown.

BIN
bin/spider.exe Normal file

Binary file not shown.

View File

@ -6,7 +6,10 @@ import (
"my-spiders/internal/spider"
)
var theImpressionMaxCo int
var (
theImpressionMaxCo int
theImpressionMaxArticles int
)
var theImpressionCmd = &cobra.Command{
Use: "theimpression",
@ -18,6 +21,7 @@ var theImpressionCmd = &cobra.Command{
// 复用全局 -d/--debug 标志
isDebug := debug
s := spider.NewTheImpressionSpider(theImpressionMaxCo, IngestClient)
s.MaxArticles = theImpressionMaxArticles
s.Debug = isDebug
s.Run()
},
@ -26,4 +30,5 @@ var theImpressionCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(theImpressionCmd)
theImpressionCmd.Flags().IntVarP(&theImpressionMaxCo, "max-co", "m", 5, "最大并发数限制")
theImpressionCmd.Flags().IntVarP(&theImpressionMaxArticles, "max-articles", "n", 0, "最多抓取的街拍任务数(0=不限制,小批量试抓用)")
}

155
internal/fetch/fetch.go Normal file
View File

@ -0,0 +1,155 @@
// Package fetch 提供「全局并发限流 + 自动重试」的 HTTP GET,供各爬虫共用。
//
// 为什么需要它:
// - 此前 vogue / theimpression 各自实现了一份 request(),逻辑重复、错误被吞掉(失败只返回 ("", 0));
// - 更严重的是并发失控:vogue 在「品牌级」与「详情级」各开一层信号量,实际并发是 MaxCo²
// (如 5×5=25),与「最多 5 个并发」的本意不符。
//
// 本包用一个「全局信号量」统一约束进程内所有请求的并发上限,各爬虫共享同一个 Client
// 即可保证整体并发受控,不会因嵌套而放大。
package fetch
import (
"context"
"fmt"
"io"
"log"
"net/http"
"time"
)
const (
// DefaultTimeout 单次请求默认超时。
DefaultTimeout = 30 * time.Second
// DefaultMaxConcurrency 默认全局并发上限。
DefaultMaxConcurrency = 5
// DefaultRetries 默认重试次数(不含首次)。
DefaultRetries = 2
userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
acceptHeader = "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
)
// Options 构造 Client 的参数,零值字段自动回落默认。
type Options struct {
MaxConcurrency int // 全局并发上限(<=0 回落 5)
MinInterval time.Duration // 两次请求之间的最小间隔,全局限速(0 = 不限速)
Retries int // 失败重试次数,不含首次(<0 回落 2;0 表示不重试)
Backoff time.Duration // 重试基础退避,第 n 次等待 n*Backoff(<=0 回落 1s)
Timeout time.Duration // 单次请求超时(<=0 回落 30s)
}
// Client 带并发限流与重试的 HTTP 客户端。
type Client struct {
hc *http.Client
sem chan struct{} // 全局并发槽(跨所有调用方共享)
tick *time.Ticker // 非 nil 时按 MinInterval 全局限速
retries int
backoff time.Duration
}
// New 构造 Client。返回值实现了一个进程级共享的限流器,多个爬虫应复用同一个实例。
func New(opt Options) *Client {
if opt.MaxConcurrency <= 0 {
opt.MaxConcurrency = DefaultMaxConcurrency
}
if opt.Timeout <= 0 {
opt.Timeout = DefaultTimeout
}
if opt.Backoff <= 0 {
opt.Backoff = time.Second
}
if opt.Retries < 0 {
opt.Retries = DefaultRetries
}
c := &Client{
hc: &http.Client{Timeout: opt.Timeout},
sem: make(chan struct{}, opt.MaxConcurrency),
retries: opt.Retries,
backoff: opt.Backoff,
}
if opt.MinInterval > 0 {
c.tick = time.NewTicker(opt.MinInterval)
}
return c
}
// Close 停止内部限速计时器(未开启限速时为空操作)。
func (c *Client) Close() {
if c.tick != nil {
c.tick.Stop()
}
}
// Get 发起带限流与重试的 GET,返回响应体与最终 HTTP 状态码。
//
// 重试策略:网络错误 / 5xx / 429 会按「线性退避」重试(第 n 次等 n*Backoff);
// 其余 4xx 视为客户端错误(如 403 被反爬、404 页面不存在),不重试,直接返回。
// 调用方拿到非 nil error 时即可判定最终失败,无需再自行区分网络错误与状态码。
func (c *Client) Get(ctx context.Context, url string) ([]byte, int, error) {
// 全局限速:每次请求前消费一个 tick(ticker 通道容量为 1,不会无限堆积)。
if c.tick != nil {
select {
case <-c.tick.C:
case <-ctx.Done():
return nil, 0, ctx.Err()
}
}
// 全局并发上限:超过则在此排队,保证总量受控。
select {
case c.sem <- struct{}{}:
defer func() { <-c.sem }()
case <-ctx.Done():
return nil, 0, ctx.Err()
}
var lastErr error
var lastStatus int
for attempt := 0; attempt <= c.retries; attempt++ {
if attempt > 0 {
delay := c.backoff * time.Duration(attempt)
log.Printf("[fetch] 第 %d/%d 次重试 %s(等待 %s)", attempt, c.retries, url, delay)
select {
case <-time.After(delay):
case <-ctx.Done():
return nil, 0, ctx.Err()
}
}
body, status, err := c.do(ctx, url)
if err == nil && status == http.StatusOK {
return body, status, nil
}
lastErr, lastStatus = err, status
// 4xx(除 429 限流)不重试:重试也只会再次失败。
if status >= 400 && status < 500 && status != http.StatusTooManyRequests {
break
}
}
if lastErr == nil {
lastErr = fmt.Errorf("http %d", lastStatus)
}
return nil, lastStatus, lastErr
}
// do 执行单次请求。
func (c *Client) do(ctx context.Context, url string) ([]byte, int, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, 0, err
}
req.Header.Set("User-Agent", userAgent)
req.Header.Set("Accept", acceptHeader)
resp, err := c.hc.Do(req)
if err != nil {
return nil, 0, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, resp.StatusCode, err
}
return body, resp.StatusCode, nil
}

View File

@ -0,0 +1,128 @@
package fetch
import (
"context"
"net/http"
"net/http/httptest"
"sync"
"sync/atomic"
"testing"
"time"
)
func TestGetSuccess(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("ok"))
}))
defer srv.Close()
c := New(Options{MaxConcurrency: 1, Retries: 0})
defer c.Close()
body, code, err := c.Get(context.Background(), srv.URL)
if err != nil || code != http.StatusOK || string(body) != "ok" {
t.Fatalf("期望 200/ok,得到 code=%d body=%q err=%v", code, body, err)
}
}
// TestGetRetriesOn5xx 5xx 应重试到上限后失败(首次 + 2 次重试 = 3 次请求)。
func TestGetRetriesOn5xx(t *testing.T) {
var calls int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt32(&calls, 1)
w.WriteHeader(http.StatusInternalServerError)
}))
defer srv.Close()
c := New(Options{MaxConcurrency: 1, Retries: 2, Backoff: time.Millisecond})
defer c.Close()
_, code, err := c.Get(context.Background(), srv.URL)
if err == nil {
t.Fatal("500 最终应返回 error")
}
if code != http.StatusInternalServerError {
t.Fatalf("最终状态码应为 500,得到 %d", code)
}
if got := atomic.LoadInt32(&calls); got != 3 {
t.Fatalf("500 应请求 3 次(首次+2 重试),实际 %d", got)
}
}
// TestGetNoRetryOn4xx 4xx(非 429)不应重试。
func TestGetNoRetryOn4xx(t *testing.T) {
var calls int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt32(&calls, 1)
w.WriteHeader(http.StatusNotFound)
}))
defer srv.Close()
c := New(Options{MaxConcurrency: 1, Retries: 3, Backoff: time.Millisecond})
defer c.Close()
_, code, err := c.Get(context.Background(), srv.URL)
if err == nil || code != http.StatusNotFound {
t.Fatalf("404 应报错且状态码 404,得到 code=%d err=%v", code, err)
}
if got := atomic.LoadInt32(&calls); got != 1 {
t.Fatalf("404 不应重试(只请求 1 次),实际 %d", got)
}
}
// TestGetRetriesOn429 429(限流)应重试,后续成功则返回成功。
func TestGetRetriesOn429(t *testing.T) {
var calls int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if atomic.AddInt32(&calls, 1) == 1 {
w.WriteHeader(http.StatusTooManyRequests)
return
}
_, _ = w.Write([]byte("ok"))
}))
defer srv.Close()
c := New(Options{MaxConcurrency: 1, Retries: 2, Backoff: time.Millisecond})
defer c.Close()
body, code, err := c.Get(context.Background(), srv.URL)
if err != nil || code != http.StatusOK || string(body) != "ok" {
t.Fatalf("429 后重试应成功,得到 code=%d body=%q err=%v", code, body, err)
}
}
// TestConcurrencyLimit 并发上限不得被突破(修复 MaxCo² 回归的守门测试)。
func TestConcurrencyLimit(t *testing.T) {
var inflight, peak int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
n := atomic.AddInt32(&inflight, 1)
for {
old := atomic.LoadInt32(&peak)
if n <= old || atomic.CompareAndSwapInt32(&peak, old, n) {
break
}
}
time.Sleep(20 * time.Millisecond)
atomic.AddInt32(&inflight, -1)
_, _ = w.Write([]byte("ok"))
}))
defer srv.Close()
const limit = 2
c := New(Options{MaxConcurrency: limit, Retries: 0})
defer c.Close()
var wg sync.WaitGroup
for i := 0; i < 8; i++ {
wg.Add(1)
go func() {
defer wg.Done()
_, _, _ = c.Get(context.Background(), srv.URL)
}()
}
wg.Wait()
if m := atomic.LoadInt32(&peak); m > limit {
t.Fatalf("并发峰值不应超过 %d,实际 %d", limit, m)
}
}

View File

@ -1,171 +1,147 @@
// Package ingest 爬虫 → 后台 ingest 管线的客户端。
//
// 设计(与 backend_v2/internal/middleware/ingest_auth.go + handler/ingest_handler.go 对齐):
// - spider 不再直连数据库:品牌任务经 GET /admin/internal/crawl/brands 拉取,
// 抓取结果经 POST /admin/internal/ingest 上报,由后台 worker 异步下载图、补 season_code、写正式表。
// - 两个接口都走 HMAC-SHA256 验签(X-Signature / X-Timestamp / X-Nonce),
// 签名串 = HMAC_SHA256(secret, timestamp + "." + nonce + "." + bodyRaw)。
// - 时间戳容忍窗口默认 ±300s;nonce 由后台一次性去重防重放。
package ingest
import (
"bytes"
"context"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strconv"
"strings"
"time"
)
// Kind 取值(与 backend_v2/internal/dto/ingest.go 一致)。
const (
KindRunway = "runway" // 走秀(默认,需 brand_uid)
KindStreet = "street" // 街拍(无品牌,需 city/title)
)
// RunwayIngest 上送后端的单场载荷(JSON 字段与 dto.RunwayIngest 完全对齐)。
type RunwayIngest struct {
Kind string `json:"kind"` // runway | street,缺省 runway
BrandUID string `json:"brand_uid"` // 品牌编码 id(hashid),runway 必填
TitleEn string `json:"title_en"` // 英文标题(runway 优先;street 作为单标题)
TitleCn string `json:"title_cn"` // 中文标题(可空)
DescriptionEn string `json:"description_en"` // 英文描述(可空)
DescriptionCn string `json:"description_cn"` // 中文描述(可空)
Year uint16 `json:"year"` // 年份,如 2026
Season string `json:"season"` // spring / fall
CollectionType string `json:"collection_type"` // rtw / menswear / couture / resort / pre_fall
City string `json:"city"` // 地区/城市(street 用)
Images []string `json:"images"` // 铺平的主图 URL 列表(回退用)
Looks []RunwayLook `json:"looks,omitempty"` // 结构化「主图 + 细节图」分组(优先)
// Client 向后台 ingest 接口发送 HMAC 签名上报的客户端。
type Client struct {
Endpoint string
Secret string
HTTPClient *http.Client
}
// RunwayLook 一场秀中的一个 look:1 张主图 + 0..N 张细节图。
type RunwayLook struct {
Main string `json:"main"` // 主图(look)原始 URL
Details []string `json:"details"` // 细节图原始 URL 列表
// NewClient 创建上报客户端。endpoint 形如 http://host:8092/admin/internal/ingest。
func NewClient(endpoint, secret string) *Client {
return &Client{
Endpoint: endpoint,
Secret: secret,
HTTPClient: &http.Client{Timeout: 30 * time.Second},
}
}
// CrawlBrand 爬虫取任务接口返回的单个品牌。
// Submit 把一条走秀上报签名后 POST 到后台,返回 job_id(202 入队即返回)。
// 失败返回 error(网络/校验/服务端拒绝),调用方应记日志并继续,不中断整轮抓取。
func (c *Client) Submit(ctx context.Context, p RunwayIngest) (uint32, error) {
if c == nil || c.Endpoint == "" {
return 0, fmt.Errorf("ingest client 未配置")
}
body, err := json.Marshal(p)
if err != nil {
return 0, err
}
ts := strconv.FormatInt(time.Now().Unix(), 10)
nonce, err := newNonce()
if err != nil {
return 0, err
}
sig := Sign(c.Secret, ts, nonce, string(body))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.Endpoint, bytes.NewReader(body))
if err != nil {
return 0, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Signature", sig)
req.Header.Set("X-Timestamp", ts)
req.Header.Set("X-Nonce", nonce)
resp, err := c.HTTPClient.Do(req)
if err != nil {
return 0, err
}
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusAccepted {
return 0, fmt.Errorf("ingest http %d: %s", resp.StatusCode, string(raw))
}
var out struct {
JobID uint32 `json:"job_id"`
Status string `json:"status"`
}
if err := json.Unmarshal(raw, &out); err != nil {
// 202 但响应结构非预期:任务已入队,记日志后当作成功
log.Printf("[Ingest] 响应解析失败但已被接受: %s", string(raw))
return 0, nil
}
return out.JobID, nil
}
// newNonce 生成 16 字节随机十六进制串,作为一次性 X-Nonce 防重放。
func newNonce() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}
// CrawlBrand 后端抓取任务接口返回的单个品牌(brand_uid 已编码,name 为英文名)。
type CrawlBrand struct {
BrandUID string `json:"brand_uid"`
Name string `json:"name"`
}
// Client 入库管线客户端。
type Client struct {
endpoint string
secret string
http *http.Client
// crawlBrandsURL 由 ingest endpoint 推导抓取任务接口地址(把末尾 /ingest 换成 /crawl/brands)。
func (c *Client) crawlBrandsURL() string {
base := c.Endpoint
if i := strings.LastIndex(base, "/ingest"); i != -1 {
base = base[:i]
}
return strings.TrimRight(base, "/") + "/crawl/brands"
}
// NewClient 创建入库管线客户端。endpoint 形如 http://localhost:8092/admin/internal/ingest。
func NewClient(endpoint, secret string) *Client {
return &Client{
endpoint: endpoint,
secret: secret,
http: &http.Client{Timeout: 30 * time.Second},
}
}
// Submit 把一场走秀/街拍元数据 HMAC 签名后 POST 到后台 ingest,返回 job_id(202 Accepted)。
func (c *Client) Submit(ctx context.Context, p RunwayIngest) (string, error) {
body, err := json.Marshal(p)
if err != nil {
return "", fmt.Errorf("marshal payload: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpoint, bytes.NewReader(body))
if err != nil {
return "", fmt.Errorf("new request: %w", err)
}
c.signRequest(req, body)
req.Header.Set("Content-Type", "application/json")
resp, err := c.http.Do(req)
if err != nil {
return "", fmt.Errorf("do request: %w", err)
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusAccepted {
return "", fmt.Errorf("ingest submit unexpected status %d: %s", resp.StatusCode, string(respBody))
}
var out struct {
JobID string `json:"job_id"`
Status string `json:"status"`
}
_ = json.Unmarshal(respBody, &out)
return out.JobID, nil
}
// GetCrawlBrands 从后台拉取可抓取品牌任务(GET /admin/internal/crawl/brands)。
// brandID>0 时仅返回该品牌(单品牌调试)。
// GetCrawlBrands 拉取爬虫要抓取的品牌任务列表(HMAC 签名 GET,复用与上报相同的验签算法)。
// brandID>0 时只取该品牌(对应 --brand 单品牌调试)。返回 brand_uid(直接上送 ingest)+ 英文名。
func (c *Client) GetCrawlBrands(ctx context.Context, brandID uint) ([]CrawlBrand, error) {
url := strings.Replace(c.endpoint, "/ingest", "/crawl/brands", 1)
if brandID > 0 {
url += "?brand=" + strconv.FormatUint(uint64(brandID), 10)
if c == nil || c.Endpoint == "" {
return nil, fmt.Errorf("ingest client 未配置")
}
url := c.crawlBrandsURL()
if brandID > 0 {
url += fmt.Sprintf("?brand=%d", brandID)
}
// GET 无请求体,签名串的 body 部分为空(与后台 IngestAuth 验签一致)。
ts := NowTS()
nonce, err := newNonce()
if err != nil {
return nil, err
}
sig := Sign(c.Secret, ts, nonce, "")
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("new request: %w", err)
return nil, err
}
c.signRequest(req, nil)
resp, err := c.http.Do(req)
if err != nil {
return nil, fmt.Errorf("do request: %w", err)
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("crawl brands unexpected status %d: %s", resp.StatusCode, string(respBody))
}
var out struct {
Brands []CrawlBrand `json:"brands"`
}
if err := json.Unmarshal(respBody, &out); err != nil {
return nil, fmt.Errorf("decode crawl brands: %w", err)
}
return out.Brands, nil
}
// signRequest 对请求体做 HMAC-SHA256 签名并写入验签头。body 为 nil 时按空串处理(GET)。
func (c *Client) signRequest(req *http.Request, body []byte) {
ts := strconv.FormatInt(time.Now().Unix(), 10)
nonce := newNonce()
sig := sign(c.secret, ts, nonce, string(body))
req.Header.Set("X-Signature", sig)
req.Header.Set("X-Timestamp", ts)
req.Header.Set("X-Nonce", nonce)
}
// sign 复刻 backend_v2/internal/pkg/hmac.Sign:HMAC_SHA256(secret, ts + "." + nonce + "." + body)。
func sign(secret, ts, nonce, body string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts))
mac.Write([]byte("."))
mac.Write([]byte(nonce))
mac.Write([]byte("."))
mac.Write([]byte(body))
return hex.EncodeToString(mac.Sum(nil))
}
// newNonce 生成 16 字节随机十六进制串作为一次性 nonce。
func newNonce() string {
b := make([]byte, 16)
_, _ = rand.Read(b)
return hex.EncodeToString(b)
resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("crawl brands http %d: %s", resp.StatusCode, string(raw))
}
var out struct {
Brands []CrawlBrand `json:"brands"`
}
if err := json.Unmarshal(raw, &out); err != nil {
return nil, fmt.Errorf("crawl brands 解析失败: %w", err)
}
return out.Brands, nil
}

View File

@ -6,10 +6,9 @@ import (
"strings"
)
// 本文件是 backend_v2/internal/pkg/hashid 中「无类型编码(品牌等)」的忠实移植,
// 仅用于 spider 离线 Mock 模式下生成 brand_uid(真实上报路径下 brand_uid 直接来自后台接口,无需自编码)。
// 算法:SHA256(盐) 派生 4 个子密钥 → 32-bit 平衡 Feistel 网络 → base62 定长(minLen=8) 序列化。
// 默认盐与后台一致:hashid_secret 为空时后台走 "fashion-archive-default-salt-change-me"。
// 以下 Feistel + base62 编码与后台 internal/pkg/hashid 完全一致,
// 仅实现编码侧(爬虫只需把品牌数字主键编码为 brand_uid 上送,无需解码)。
// 盐值必须 == 后台 HASHID_SECRET,否则生成的 brand_uid 后台解码不出正确主键。
const (
hidAlphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
@ -19,7 +18,8 @@ const (
var hidKeys [4]uint32
// InitHashID 用部署级盐值初始化混淆密钥。盐为空时使用与后台相同的内置默认盐。
// InitHashID 用与后台 HASHID_SECRET 相同的盐值初始化编码密钥。
// secret 为空时回落后台内置默认盐(仅防顺序枚举,不安全)。
func InitHashID(secret string) {
if secret == "" {
secret = "fashion-archive-default-salt-change-me"
@ -30,12 +30,8 @@ func InitHashID(secret string) {
}
}
// feistel 32-bit 平衡 Feistel 网络(全局密钥版,品牌等无类型实体用)。
func feistel(v uint32, encrypt bool) uint32 {
return feistelK(v, encrypt, hidKeys)
}
func feistelK(v uint32, encrypt bool, k [4]uint32) uint32 {
// hidFeistel 32-bit 平衡 Feistel 网络,encrypt=true 加密。
func hidFeistel(v uint32, encrypt bool) uint32 {
const rounds = 8
l, r := uint16(v>>16), uint16(v&0xffff)
for i := 0; i < rounds; i++ {
@ -44,24 +40,22 @@ func feistelK(v uint32, encrypt bool, k [4]uint32) uint32 {
idx = rounds - 1 - i
}
round := func(h uint16) uint16 {
f := uint32(h)*0x9E3779B1 + k[idx%4]
f := uint32(h)*0x9E3779B1 + hidKeys[idx%4]
return uint16((f ^ (f >> 16)) & 0xffff)
}
if encrypt {
nl := r
nr := l ^ round(r)
nl, nr := r, uint16(l)^round(r)
l, r = nl, nr
} else {
nl := r ^ round(l)
nr := l
nl, nr := uint16(l)^round(l), l
l, r = nl, nr
}
}
return uint32(l)<<16 | uint32(r)
}
// numToBase62 把 32-bit 值序列化为定长(minLen)base62 串,高位在前。
func numToBase62(x uint32) string {
func encodeNum(n uint32) string {
x := hidFeistel(n, true)
var sb strings.Builder
for x > 0 {
sb.WriteByte(hidAlphabet[x%hidBase])
@ -81,7 +75,7 @@ func numToBase62(x uint32) string {
return out
}
// EncodeBrand 把数字品牌主键编码为对外 hashid 串(与后台 hashid.Encode 同算法、同盐)。
// EncodeBrand 把品牌数字主键编码为 hashid 串(与后台 brand_uid 同算法)。
func EncodeBrand(id uint32) string {
return numToBase62(feistel(id, true))
return encodeNum(id)
}

27
internal/ingest/hmac.go Normal file
View File

@ -0,0 +1,27 @@
package ingest
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strconv"
"time"
)
// Sign 与后台 internal/pkg/hmac.Sign 完全一致:
// HMAC_SHA256(secret, timestamp + "." + nonce + "." + body) 的十六进制串。
// bodyRaw 必须是请求体原始字节,确保与后台收到的字节严格一致。
func Sign(secret, timestamp, nonce, body string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(timestamp))
mac.Write([]byte("."))
mac.Write([]byte(nonce))
mac.Write([]byte("."))
mac.Write([]byte(body))
return hex.EncodeToString(mac.Sum(nil))
}
// NowTS 返回当前 Unix 秒字符串(X-Timestamp 用)。
func NowTS() string {
return strconv.FormatInt(time.Now().Unix(), 10)
}

View File

@ -0,0 +1,77 @@
package ingest
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strconv"
"testing"
"time"
)
// verify 是后台 internal/pkg/hmac.Verify 的逐字镜像,仅用于本测试验证「爬虫签名能被
// 后台同算法校验通过」这条契约——算法必须与后台保持一致。
func verify(secret, body, sig, ts, nonce string, ttl int) bool {
if sig == "" || ts == "" || nonce == "" {
return false
}
if ttl <= 0 {
ttl = 300
}
tsN, err := strconv.ParseInt(ts, 10, 64)
if err != nil {
return false
}
now := time.Now().Unix()
if diff := now - tsN; diff > int64(ttl) || diff < -int64(ttl) {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts))
mac.Write([]byte("."))
mac.Write([]byte(nonce))
mac.Write([]byte("."))
mac.Write([]byte(body))
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(sig))
}
func TestSignVerifyRoundtrip(t *testing.T) {
secret := "test-secret"
body := `{"brand_uid":"001DESke","title_en":"Fall 2024 Ready-to-Wear"}`
ts := strconv.FormatInt(time.Now().Unix(), 10)
nonce := "abc123nonce"
sig := Sign(secret, ts, nonce, body)
if !verify(secret, body, sig, ts, nonce, 300) {
t.Fatal("后台应当校验通过爬虫签名,但未通过")
}
// 篡改 body
if verify(secret, body+"x", sig, ts, nonce, 300) {
t.Fatal("body 被篡改后不应通过校验")
}
// 错误密钥
if verify("wrong", body, sig, ts, nonce, 300) {
t.Fatal("错误密钥不应通过校验")
}
// 过期时间戳
old := strconv.FormatInt(time.Now().Unix()-600, 10)
if verify(secret, body, Sign(secret, old, nonce, body), old, nonce, 300) {
t.Fatal("过期时间戳不应通过校验")
}
}
func TestEncodeBrandNonSequential(t *testing.T) {
// 相邻主键编码结果应互不相关(防顺序枚举),且同值稳定
a := EncodeBrand(108)
b := EncodeBrand(109)
if a == b {
t.Fatal("相邻 id 编码必须不同")
}
if EncodeBrand(108) != a {
t.Fatal("编码必须稳定(同输入同输出)")
}
if len(a) < 8 {
t.Fatalf("编码长度不应短于 minLen=8,实际 %d", len(a))
}
}

View File

@ -0,0 +1,74 @@
// Package ingest 爬虫侧入库客户端:把走秀元数据以 HMAC 签名 POST 到后台
// ingest 接口(:8092/admin/internal/ingest),替代原先直写 brand_runway 表。
//
// 与后台 internal/pkg/hmac、internal/pkg/hashid 保持同算法,使爬虫模块完全解耦
// 于后端代码(不再 import 后端 internal 包),双方仅通过「签名 + JSON 载荷」契约通信。
package ingest
import "strings"
// 入库类型(与后台 dto 保持一致)。
const (
KindRunway = "runway" // 走秀(默认,需 brand_uid)
KindStreet = "street" // 街拍(无品牌,需 city/title)
)
// RunwayIngest 与后台 dto.RunwayIngest 的 JSON 字段一一对应。
// 爬虫只传元数据 + 图片 URL 列表,图下载/OSS 由后台 worker 完成。
type RunwayIngest struct {
Kind string `json:"kind"` // runway | street,缺省 runway
BrandUID string `json:"brand_uid"` // 品牌 hashid(EncodeBrand 生成),runway 必填
TitleEn string `json:"title_en"` // 英文标题(优先;street 作为单标题)
TitleCn string `json:"title_cn"` // 中文标题(可空)
DescriptionEn string `json:"description_en"` // 英文描述(可空)
DescriptionCn string `json:"description_cn"` // 中文描述(可空)
Year uint16 `json:"year"` // 年份
Season string `json:"season"` // spring / fall
CollectionType string `json:"collection_type"` // rtw / menswear / couture / resort / pre_fall
City string `json:"city"` // 地区/城市(street 用)
Images []string `json:"images"` // 兼容旧 worker:铺平的主图 URL 列表
// Looks 结构化「主图 + 细节图」分组(Vogue 一个 gallery item = 1 主图 + N 细节图)。
// 结构化上报时优先用 Looks;为空时 worker 回退到 Images(全部视为主图)。
Looks []RunwayLook `json:"looks,omitempty"`
}
// RunwayLook 一场秀中的一个 look:1 张主图 + 0..N 张细节图。
type RunwayLook struct {
Main string `json:"main"` // 主图(look)原始 URL
Details []string `json:"details"` // 细节图原始 URL 列表
}
// ParseCollection 从 Vogue 标题推导 collection_type 与 season,供后台补 season_code。
//
// "Fall 2024 Ready-to-Wear" -> ("rtw", "fall")
// "Spring 2025 Menswear" -> ("menswear", "spring")
// "Resort 2024" -> ("resort", "")
// "Pre-Fall 2024" -> ("pre_fall", "")
// "Couture Fall 2024" -> ("couture", "fall")
func ParseCollection(title string) (collectionType, season string) {
t := strings.ToLower(title)
switch {
case strings.Contains(t, "resort"):
collectionType = "resort"
case strings.Contains(t, "pre-fall"), strings.Contains(t, "pre fall"):
collectionType = "pre_fall"
case strings.Contains(t, "couture"):
collectionType = "couture"
case strings.Contains(t, "menswear"), strings.Contains(t, "men's"):
collectionType = "menswear"
case strings.Contains(t, "ready"):
collectionType = "rtw"
default:
// 仅出现 spring/fall 而无明确品类词时,回落为 rtw(绝大多数季场秀)
if strings.Contains(t, "spring") || strings.Contains(t, "fall") {
collectionType = "rtw"
}
}
switch {
case strings.Contains(t, "spring"):
season = "spring"
case strings.Contains(t, "fall"):
season = "fall"
}
return collectionType, season
}

7
internal/spider/regex.go Normal file
View File

@ -0,0 +1,7 @@
package spider
import "regexp"
// yearRe 预编译的 4 位年份正则,供 vogue / theimpression 共用
// (预编译避免在每次解析时重新编译)。
var yearRe = regexp.MustCompile(`\b(19|20)\d{2}\b`)

View File

@ -4,10 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"regexp"
"strconv"
"strings"
"sync"
@ -15,6 +12,7 @@ import (
"github.com/PuerkitoBio/goquery"
"my-spiders/internal/fetch"
"my-spiders/internal/ingest"
)
@ -28,10 +26,11 @@ const (
// TheImpressionSpider The Impression 街拍采集器(对应 PHP 的 TheImpressionStreetCommand)
type TheImpressionSpider struct {
Client *http.Client
Ingest *ingest.Client // 入库管线客户端(nil = 无法入库,仅 Debug 输出)
MaxCo int // 最大并发数
Debug bool // Debug 模式:仅输出不入库
Fetcher *fetch.Client // 带全局并发限流 + 重试的 HTTP 客户端
Ingest *ingest.Client // 入库管线客户端(nil = 无法入库,仅 Debug 输出)
MaxCo int // 最大并发数
MaxArticles int // 小批量模式:最多抓取的街拍任务数(0=不限制)
Debug bool // Debug 模式:仅输出不入库
}
func NewTheImpressionSpider(maxCo int, ingestClient *ingest.Client) *TheImpressionSpider {
@ -41,9 +40,13 @@ func NewTheImpressionSpider(maxCo int, ingestClient *ingest.Client) *TheImpressi
return &TheImpressionSpider{
Ingest: ingestClient,
MaxCo: maxCo,
Client: &http.Client{
Timeout: 30 * time.Second,
},
// 全局并发上限 = maxCo;叠加 200ms 最小间隔做全局限速(替代原先的 time.Sleep)。
Fetcher: fetch.New(fetch.Options{
MaxConcurrency: maxCo,
MinInterval: 200 * time.Millisecond,
Retries: fetch.DefaultRetries,
Backoff: time.Second,
}),
}
}
@ -59,13 +62,13 @@ func (s *TheImpressionSpider) Run() {
// 1. 抓取 street-style 首页 banner(.parallax .mask-overlay)
bannerURL := TheImpressionBaseURL + "/street-style"
body, httpCode := s.request(bannerURL)
if httpCode != 200 || body == "" {
log.Printf("[错误] %s 请求失败, code: %d", bannerURL, httpCode)
bannerBody, bannerCode, bannerErr := s.Fetcher.Get(context.Background(), bannerURL)
if bannerErr != nil || bannerCode != 200 || len(bannerBody) == 0 {
log.Printf("[错误] %s 请求失败, code: %d, err: %v", bannerURL, bannerCode, bannerErr)
return
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(bannerBody)))
if err != nil {
log.Printf("[错误] 解析 %s 失败: %v", bannerURL, err)
return
@ -89,15 +92,15 @@ func (s *TheImpressionSpider) Run() {
"%s/wp-json/codetipi-zeen/v1/block?paged=%d&type=1&data%%5Bargs%%5D%%5Bcat%%5D=1",
TheImpressionBaseURL, i,
)
body, httpCode := s.request(listURL)
if httpCode != 200 || body == "" {
log.Printf("[错误] %s 请求失败, code: %d", listURL, httpCode)
listBody, listCode, listErr := s.Fetcher.Get(context.Background(), listURL)
if listErr != nil || listCode != 200 || len(listBody) == 0 {
log.Printf("[错误] %s 请求失败, code: %d, err: %v", listURL, listCode, listErr)
return
}
// 接口返回的是 JSON 数组,第 2 个元素(index 1)是包含文章的 HTML 片段
var arr []interface{}
if err := json.Unmarshal([]byte(body), &arr); err != nil {
if err := json.Unmarshal(listBody, &arr); err != nil {
log.Printf("[错误] %s JSON 解析失败: %v", listURL, err)
continue
}
@ -128,21 +131,21 @@ func (s *TheImpressionSpider) Run() {
})
}
// 小批量模式:仅抓取前 N 个街拍(用于试抓 / 控制入库量)。
if s.MaxArticles > 0 && len(tasks) > s.MaxArticles {
log.Printf("[Info] 小批量模式:仅抓取前 %d / %d 个街拍", s.MaxArticles, len(tasks))
tasks = tasks[:s.MaxArticles]
}
log.Printf("[Info] 共收集到 %d 个待抓取任务,开始执行...", len(tasks))
// 3. 并发抓取详情页
sem := make(chan struct{}, s.MaxCo)
// 3. 并发抓取详情页:不再自建信号量,HTTP 并发与频控统一由 s.Fetcher 承担。
var wg sync.WaitGroup
for _, t := range tasks {
sem <- struct{}{}
wg.Add(1)
go func(tk streetTask) {
defer func() {
<-sem
wg.Done()
}()
defer wg.Done()
s.getDetail(tk)
time.Sleep(200 * time.Millisecond) // 频控,防封 IP
}(t)
}
wg.Wait()
@ -158,13 +161,13 @@ func (s *TheImpressionSpider) getDetail(tk streetTask) {
return
}
body, httpCode := s.request(url)
if httpCode != 200 || body == "" {
log.Printf("[错误] %s 请求失败, code: %d", url, httpCode)
body, code, err := s.Fetcher.Get(context.Background(), url)
if err != nil || code != 200 || len(body) == 0 {
log.Printf("[错误] %s 请求失败, code: %d, err: %v", url, code, err)
return
}
doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
if err != nil {
log.Printf("[错误] 解析 %s 失败: %v", url, err)
return
@ -233,37 +236,15 @@ func (s *TheImpressionSpider) getDetail(tk streetTask) {
}
}
// request HTTP 请求封装(带浏览器 UA)
func (s *TheImpressionSpider) request(url string) (string, int) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", 0
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
req.Header.Set("Accept", "text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
resp, err := s.Client.Do(req)
if err != nil {
return "", 0
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", resp.StatusCode
}
return string(bodyBytes), resp.StatusCode
}
// parseYear 从标题中提取 4 位年份数字(对应 PHP 的 AppHelper::getYear)
// parseYear 从标题中提取 4 位年份(对应 PHP 的 AppHelper::getYear)。
// 提取不到时返回 0(未知年份),不再回退到「当前年份」——那会把旧街拍伪造成今年。
func (s *TheImpressionSpider) parseYear(title string) int {
re := regexp.MustCompile(`\b(19|20)\d{2}\b`)
match := re.FindString(title)
if match != "" {
y, _ := strconv.Atoi(match)
if m := yearRe.FindString(title); m != "" {
y, _ := strconv.Atoi(m)
return y
}
return time.Now().Year()
log.Printf("[Warning] 标题未含年份,按未知(0)处理: %s", title)
return 0
}
// streetCities 常见时装周城市(用于从街拍标题中粗提 city 字段)。

View File

@ -2,9 +2,7 @@ package spider
import (
"context"
"io"
"log"
"net/http"
"regexp"
"strconv"
"strings"
@ -13,6 +11,7 @@ import (
"github.com/tidwall/gjson"
"my-spiders/internal/fetch"
"my-spiders/internal/ingest"
)
@ -21,8 +20,15 @@ const (
VoguePlatform = "vogue"
)
// 预编译正则(避免每次调用都重新编译)。
// 列表页与详情页的内联 state 结束标记不同,故保留两条,勿轻易合并。
var (
showsStateRe = regexp.MustCompile(`(?s)window\.__PRELOADED_STATE__\s*=\s*(.*?);</script>`)
detailStateRe = regexp.MustCompile(`(?s)window\.__PRELOADED_STATE__\s*=\s*(.*?);<`)
)
type VogueSpider struct {
Client *http.Client
Fetcher *fetch.Client // 带全局并发限流 + 重试的 HTTP 客户端
Ingest *ingest.Client // 入库管线客户端(nil = 离线/Mock 模式)
MaxCo int // 最大并发数
BrandID uint // 客户端指定的品牌 ID(--brand,单品牌调试用)
@ -41,9 +47,14 @@ func NewVogueSpider(maxCo int, brandID uint, maxShows int, ingestClient *ingest.
MaxCo: maxCo,
BrandID: brandID,
MaxShows: maxShows,
Client: &http.Client{
Timeout: 30 * time.Second,
},
// 全局并发上限 = maxCo(单一信号量,避免「品牌级 × 详情级」叠加成 maxCo²);
// 再叠加 200ms 最小间隔做全局限速,替代原先散落在 goroutine 里的 time.Sleep。
Fetcher: fetch.New(fetch.Options{
MaxConcurrency: maxCo,
MinInterval: 200 * time.Millisecond,
Retries: fetch.DefaultRetries,
Backoff: time.Second,
}),
}
}
@ -57,7 +68,8 @@ func (s *VogueSpider) Run() {
log.Printf("[Info] 成功获取 %d 个品牌任务,开始执行...", len(tasks))
// 品牌级别的并发控制
// 品牌级并发:仅限制「同时在跑的品牌 goroutine 数」,避免一次性对巨量品牌开 goroutine;
// 真正的 HTTP 并发由 Fetcher 的全局信号量统一控制(修正此前两层信号量叠加成 MaxCo² 的问题)。
brandSem := make(chan struct{}, s.MaxCo)
var wg sync.WaitGroup
@ -140,24 +152,16 @@ func (s *VogueSpider) SpiderStart(task ingest.CrawlBrand) {
showsList = showsList[:s.MaxShows]
}
// 核心修复:限制该品牌下发布会详情页的抓取并发数
detailSem := make(chan struct{}, s.MaxCo)
// 详情页并发抓取:这里不再自建信号量,HTTP 并发与频控统一由 s.Fetcher 承担
// (避免与品牌级信号量叠加导致并发放大)。
var wg sync.WaitGroup
for _, list := range showsList {
detailSem <- struct{}{} // 超过 MaxCo 时会自动卡住等待
wg.Add(1)
go func(info gjson.Result) {
defer func() {
<-detailSem // 释放槽位
wg.Done()
}()
defer wg.Done()
s.getDetail(task.BrandUID, info)
// 频控:每次下载后稍作停顿,保护带宽并防封 IP
time.Sleep(200 * time.Millisecond)
}(list)
}
@ -166,17 +170,19 @@ func (s *VogueSpider) SpiderStart(task ingest.CrawlBrand) {
// getShowsList 获取品牌的发布会列表 JSON 数据
func (s *VogueSpider) getShowsList(url string) []gjson.Result {
body, httpCode := s.request(url)
if httpCode == 200 && body != "" {
re := regexp.MustCompile(`(?s)window\.__PRELOADED_STATE__\s*=\s*(.*?);</script>`)
matches := re.FindStringSubmatch(body)
if len(matches) > 1 {
collections := gjson.Get(matches[1], "transformed.runwayDesignerContent.designerCollections")
return collections.Array()
}
body, code, err := s.Fetcher.Get(context.Background(), url)
if err != nil {
log.Printf("[错误] 获取发布会列表失败 %s: %v", url, err)
return nil
}
if code != 200 || len(body) == 0 {
log.Printf("[Info] %s 返回异常, code: %d", url, code)
return nil
}
if m := showsStateRe.FindSubmatch(body); len(m) > 1 {
collections := gjson.GetBytes(m[1], "transformed.runwayDesignerContent.designerCollections")
return collections.Array()
}
log.Printf("[Info] %s 未找到数据.", url)
return nil
}
@ -191,20 +197,22 @@ func (s *VogueSpider) getDetail(brandUID string, info gjson.Result) {
requestURL := s.sourceURL(info)
log.Printf("正在匹配发布会详情 %s", requestURL)
body, httpCode := s.request(requestURL)
if httpCode != 200 || body == "" {
log.Printf("[Warning] %s 请求失败.", requestURL)
body, code, err := s.Fetcher.Get(context.Background(), requestURL)
if err != nil {
log.Printf("[Warning] %s 请求失败: %v", requestURL, err)
return
}
if code != 200 || len(body) == 0 {
log.Printf("[Warning] %s 返回异常, code: %d", requestURL, code)
return
}
re := regexp.MustCompile(`(?s)window\.__PRELOADED_STATE__\s*=\s*(.*?);<`)
matches := re.FindStringSubmatch(body)
matches := detailStateRe.FindSubmatch(body)
if len(matches) <= 1 {
return
}
imagesResult := gjson.Get(matches[1], "transformed.runwayGalleries.galleries.0.items")
imagesResult := gjson.GetBytes(matches[1], "transformed.runwayGalleries.galleries.0.items")
if !imagesResult.Exists() {
log.Printf("[Warning] %s 获取图片失败.", requestURL)
@ -279,36 +287,14 @@ func (s *VogueSpider) getTaskName(name string) string {
return strings.ToLower(r.Replace(name))
}
// HTTP 请求封装
func (s *VogueSpider) request(url string) (string, int) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", 0
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
resp, err := s.Client.Do(req)
if err != nil {
return "", 0
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", resp.StatusCode
}
return string(bodyBytes), resp.StatusCode
}
// parseYear 从标题中提取 4 位年份数字(如 Fall 2024 Ready-to-Wear -> 2024)
// parseYear 从标题中提取 4 位年份(如 Fall 2024 Ready-to-Wear -> 2024)。
// 提取不到时返回 0(未知年份),交由后端 season.Derive 处理(year=0 → season_code 为空);
// 绝不回退到「当前年份」——那会把旧秀伪造成今年,污染排序与去重。
func (s *VogueSpider) parseYear(title string) int {
re := regexp.MustCompile(`\b(19|20)\d{2}\b`)
match := re.FindString(title)
if match != "" {
y, _ := strconv.Atoi(match)
if m := yearRe.FindString(title); m != "" {
y, _ := strconv.Atoi(m)
return y
}
return time.Now().Year()
log.Printf("[Warning] 标题未含年份,按未知(0)处理: %s", title)
return 0
}

7
spider_batch.log Normal file
View File

@ -0,0 +1,7 @@
2026/09/11 20:20:20 [Info] 入库管线已启用 -> http://localhost:8092/admin/internal/ingest
2026/09/11 20:20:20 [Info] 成功获取 1 个品牌任务,开始执行...
2026/09/11 20:20:20 [Debug] 原始品牌名: Acne Studios; 格式化后: acne-studios
2026/09/11 20:20:20 [Command] brandName: acne-studios; spiderUrl: https://www.vogue.com/fashion-shows/designer/acne-studios
2026/09/11 20:20:23 [Info] 预检命中 82/82 个已爬取图集,跳过;待抓取 0 个
2026/09/11 20:20:23 [Info] 品牌 [acne-studios] 的图集均已爬取过,全部跳过
2026/09/11 20:20:23 [Info] Vogue 所有抓取任务已完成!

300
spider_gucci.log Normal file
View File

@ -0,0 +1,300 @@
2026/09/11 22:31:49 [Info] 入库管线已启用 -> http://localhost:8092/admin/internal/ingest
2026/09/11 22:31:49 [Info] 成功获取 1 个品牌任务,开始执行...
2026/09/11 22:31:49 [Debug] 原始品牌名: Gucci; 格式化后: gucci
2026/09/11 22:31:49 [Command] brandName: gucci; spiderUrl: https://www.vogue.com/fashion-shows/designer/gucci
2026/09/11 22:31:52 [Info] 小批量模式:仅抓取前 5 / 132 场发布会
2026/09/11 22:31:52 正在匹配发布会详情 https://www.vogue.com/fashion-shows/resort-2026/gucci/slideshow/collection
2026/09/11 22:31:52 正在匹配发布会详情 https://www.vogue.com/fashion-shows/fall-2026-ready-to-wear/gucci/slideshow/collection
2026/09/11 22:31:52 正在匹配发布会详情 https://www.vogue.com/fashion-shows/pre-fall-2026/gucci/slideshow/collection
2026/09/11 22:31:52 正在匹配发布会详情 https://www.vogue.com/fashion-shows/spring-2026-ready-to-wear/gucci/slideshow/collection
2026/09/11 22:31:52 正在匹配发布会详情 https://www.vogue.com/fashion-shows/resort-2027/gucci/slideshow/collection
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a0691752b1abbae6f2ec0/master/w_2560,c_limit/00001-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06916ed9876b786d0129/master/w_2560,c_limit/00002-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a0691dc15e1429d4cbe32/master/w_2560,c_limit/00003-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069417f832ce597658b5/master/w_2560,c_limit/00004-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a0695b9af6b72617d951d/master/w_2560,c_limit/00005-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06966ed9876b786d012f/master/w_2560,c_limit/00006-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06979bc95159c66b944e/master/w_2560,c_limit/00007-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a0698c73846e15adc725d/master/w_2560,c_limit/00008-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a0699711a23d1067ee9c7/master/w_2560,c_limit/00009-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069a2e1ccd0c8ce443f5/master/w_2560,c_limit/00010-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069b90e50c9dbb0acdb7/master/w_2560,c_limit/00011-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069c2e1ccd0c8ce443fb/master/w_2560,c_limit/00012-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069d4b2600279313e563/master/w_2560,c_limit/00013-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069e68044e9311f15e4f/master/w_2560,c_limit/00014-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a069fc73846e15adc7268/master/w_2560,c_limit/00015-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a0b9af6b72617d952b/master/w_2560,c_limit/00016-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a14951d452e0fbb3d4/master/w_2560,c_limit/00017-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a27062b9037631f4f2/master/w_2560,c_limit/00018-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a3b9af6b72617d9531/master/w_2560,c_limit/00019-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a49b03d4f210f1055c/master/w_2560,c_limit/00020-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a6f788445d7d512c44/master/w_2560,c_limit/00021-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a9c73846e15adc7271/master/w_2560,c_limit/00022-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06a82e1ccd0c8ce44403/master/w_2560,c_limit/00023-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06aa794b317cd75ee532/master/w_2560,c_limit/00024-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06ab68044e9311f15e55/master/w_2560,c_limit/00025-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06ad90e50c9dbb0acdbd/master/w_2560,c_limit/00026-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06ad7062b9037631f4f8/master/w_2560,c_limit/00027-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06ae9c325bba91fadf83/master/w_2560,c_limit/00028-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b0b9af6b72617d9537/master/w_2560,c_limit/00029-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b02e1ccd0c8ce4440a/master/w_2560,c_limit/00030-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b2794b317cd75ee53d/master/w_2560,c_limit/00031-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b4a232ba599921c1e0/master/w_2560,c_limit/00032-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b4752b1abbae6f2ed0/master/w_2560,c_limit/00033-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b52e1ccd0c8ce44410/master/w_2560,c_limit/00034-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b9f788445d7d512c52/master/w_2560,c_limit/00035-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06b941f668f57ef49467/master/w_2560,c_limit/00036-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06bbeda24b02d657c202/master/w_2560,c_limit/00037-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06bd2e1ccd0c8ce4441b/master/w_2560,c_limit/00038-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06bdc73846e15adc7280/master/w_2560,c_limit/00039-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06bf4b2600279313e56c/master/w_2560,c_limit/00040-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c2794b317cd75ee543/master/w_2560,c_limit/00041-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c14b2600279313e572/master/w_2560,c_limit/00042-gucci-resort-2027-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c359fff5e945637285/master/w_2560,c_limit/00043-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c468044e9311f15e60/master/w_2560,c_limit/00044-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c89b03d4f210f1057a/master/w_2560,c_limit/00045-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c69b03d4f210f10574/master/w_2560,c_limit/00046-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06c84b2600279313e578/master/w_2560,c_limit/00047-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06cab5b90ecd3cca014a/master/w_2560,c_limit/00048-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06cb4133fd6ba6df6104/master/w_2560,c_limit/00049-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06cc29abd45c193a1f13/master/w_2560,c_limit/00050-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06cd711a23d1067ee9dc/master/w_2560,c_limit/00051-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06ce794b317cd75ee551/master/w_2560,c_limit/00052-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d0752b1abbae6f2ed6/master/w_2560,c_limit/00053-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d26ed9876b786d0138/master/w_2560,c_limit/00054-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d22e1ccd0c8ce44426/master/w_2560,c_limit/00055-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d56ed9876b786d013e/master/w_2560,c_limit/00056-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d69c325bba91fadf91/master/w_2560,c_limit/00057-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d8a232ba599921c1e6/master/w_2560,c_limit/00058-gucci-resort-2027-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d8b5b90ecd3cca0150/master/w_2560,c_limit/00059-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06d929abd45c193a1f1c/master/w_2560,c_limit/00060-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06db68044e9311f15e6e/master/w_2560,c_limit/00061-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06deb5b90ecd3cca0156/master/w_2560,c_limit/00062-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [look] 主图 https://assets.vogue.com/photos/6a0a06dd59fff5e945637298/master/w_2560,c_limit/00063-gucci-resort-2027-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:53 [成功] 已上报待入库: Resort 2027 (共 63 个 look / 134 张图)
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29868b125d7500f38fa/master/w_2560,c_limit/00001-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29840e2eb8fb8bccd5c/master/w_2560,c_limit/00002-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2990536c0e58428ec57/master/w_2560,c_limit/00003-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29bec9e56390d3c0343/master/w_2560,c_limit/00004-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29d12fc8087a4b68a5c/master/w_2560,c_limit/00005-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29d187bff3f8a3480ee/master/w_2560,c_limit/00006-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f29fb978bd780db879bc/master/w_2560,c_limit/00007-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a13cdcc32ad45be22b/master/w_2560,c_limit/00008-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a18acfb60be7c39369/master/w_2560,c_limit/00009-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a2bc21d805bf329ada/master/w_2560,c_limit/00010-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a460f25b7e62d4c774/master/w_2560,c_limit/00011-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a616f926d4a2c164b5/master/w_2560,c_limit/00012-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a5b2d17b44b610cbde/master/w_2560,c_limit/00013-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a768b125d7500f38fc/master/w_2560,c_limit/00014-gucci-resort-2026-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a968b125d7500f38ff/master/w_2560,c_limit/00015-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2a9187bff3f8a3480f0/master/w_2560,c_limit/00016-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2acee3c01f48b80a774/master/w_2560,c_limit/00017-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2acd0d2baf7b176c7a3/master/w_2560,c_limit/00018-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2adb978bd780db879be/master/w_2560,c_limit/00019-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b02b79d44243efd1d4/master/w_2560,c_limit/00020-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b08acfb60be7c3936b/master/w_2560,c_limit/00021-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b112fc8087a4b68a5e/master/w_2560,c_limit/00022-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b48acfb60be7c3936d/master/w_2560,c_limit/00023-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b420306ddb341ea06e/master/w_2560,c_limit/00024-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b4211e2d9cc1fdbea3/master/w_2560,c_limit/00025-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b840e5bfe1996d16a7/master/w_2560,c_limit/00026-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b868b125d7500f3902/master/w_2560,c_limit/00027-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2b8bc21d805bf329adc/master/w_2560,c_limit/00028-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2bc24deb2471c247651/master/w_2560,c_limit/00029-gucci-resort-2026-credit-brand.jpg 附 4 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2bcab36f20de7af8494/master/w_2560,c_limit/00030-gucci-resort-2026-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2bd8acfb60be7c39370/master/w_2560,c_limit/00031-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2bf211e2d9cc1fdbea6/master/w_2560,c_limit/00032-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c0b2d17b44b610cbe1/master/w_2560,c_limit/00033-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c03650fb81757bca54/master/w_2560,c_limit/00034-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c268b125d7500f3904/master/w_2560,c_limit/00035-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c3b307fa7bf6d4e579/master/w_2560,c_limit/00036-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c46e92acc911d0cfdb/master/w_2560,c_limit/00037-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c512fc8087a4b68a60/master/w_2560,c_limit/00038-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c73650fb81757bca56/master/w_2560,c_limit/00039-gucci-resort-2026-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c8d4b2ea7c11de8806/master/w_2560,c_limit/00040-gucci-resort-2026-credit-brand.jpg 附 3 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2c9d4b2ea7c11de8808/master/w_2560,c_limit/00041-gucci-resort-2026-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/6826f2ca272f917535482261/master/w_2560,c_limit/00042-gucci-resort-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [成功] 已上报待入库: Resort 2026 (共 42 个 look / 127 张图)
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d36ae530252d0b9b77/master/w_2560,c_limit/00001-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d275300db6e628e0dd/master/w_2560,c_limit/00002-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d2d34aaf50ee468686/master/w_2560,c_limit/00003-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d7fffa071ef1933589/master/w_2560,c_limit/00004-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d842e63b8b62766929/master/w_2560,c_limit/00005-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8d8c6655877971ab0f7/master/w_2560,c_limit/00006-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8dbe86285b2183efd47/master/w_2560,c_limit/00007-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8dd113b585837febe90/master/w_2560,c_limit/00008-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8ddc6655877971ab0fd/master/w_2560,c_limit/00009-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8df162e29636a2cb982/master/w_2560,c_limit/00010-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e18bd473891a512fd0/master/w_2560,c_limit/00011-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e2d08063c920b9ed2c/master/w_2560,c_limit/00012-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e38bd473891a512fd7/master/w_2560,c_limit/00013-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e53fde453b99cbb31f/master/w_2560,c_limit/00014-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e65fee983aa5123289/master/w_2560,c_limit/00015-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8e79184b92f4dc52e07/master/w_2560,c_limit/00016-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8eb57966e4abfc21805/master/w_2560,c_limit/00017-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8eb3a8f05b89fdd7c6a/master/w_2560,c_limit/00018-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8eb113b585837febe96/master/w_2560,c_limit/00019-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8ee6ddeb3513db02afa/master/w_2560,c_limit/00020-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f0fffa071ef193358f/master/w_2560,c_limit/00021-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f0ea5539abc092d495/master/w_2560,c_limit/00022-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f2e86285b2183efd55/master/w_2560,c_limit/00023-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f442e63b8b62766934/master/w_2560,c_limit/00024-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f5fdeb03b5ba7ec72e/master/w_2560,c_limit/00025-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f6162e29636a2cb988/master/w_2560,c_limit/00026-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8f805db6c5acc229603/master/w_2560,c_limit/00027-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8fac6655877971ab10d/master/w_2560,c_limit/00028-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8fa3fde453b99cbb332/master/w_2560,c_limit/00029-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8fc113b585837febe9c/master/w_2560,c_limit/00030-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8ff3a8f05b89fdd7c70/master/w_2560,c_limit/00031-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e8fe75300db6e628e0e6/master/w_2560,c_limit/00032-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e900fdeb03b5ba7ec737/master/w_2560,c_limit/00033-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90242e63b8b6276693a/master/w_2560,c_limit/00034-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9045fee983aa5123292/master/w_2560,c_limit/00035-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e904d08063c920b9ed35/master/w_2560,c_limit/00036-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90519b858d5d66632c9/master/w_2560,c_limit/00037-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e907e0c3eaf5b25c089f/master/w_2560,c_limit/00038-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9098bd473891a512fe3/master/w_2560,c_limit/00039-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90a848a39800b805135/master/w_2560,c_limit/00040-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90c6ddeb3513db02b05/master/w_2560,c_limit/00041-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90e113b585837febea2/master/w_2560,c_limit/00042-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e90ee0c3eaf5b25c08a5/master/w_2560,c_limit/00043-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91017a5c0e47915fe34/master/w_2560,c_limit/00044-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e912848a39800b805140/master/w_2560,c_limit/00045-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91357966e4abfc21813/master/w_2560,c_limit/00046-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9141c150ac4fa847796/master/w_2560,c_limit/00047-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9166ddeb3513db02b0b/master/w_2560,c_limit/00048-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9179184b92f4dc52e16/master/w_2560,c_limit/00049-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91875300db6e628e0ec/master/w_2560,c_limit/00050-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91a8bd473891a512fee/master/w_2560,c_limit/00051-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91b1c150ac4fa84779c/master/w_2560,c_limit/00052-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91c42e63b8b62766940/master/w_2560,c_limit/00053-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91d113b585837febea8/master/w_2560,c_limit/00054-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e91f1c150ac4fa8477a2/master/w_2560,c_limit/00055-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e920fdeb03b5ba7ec74e/master/w_2560,c_limit/00056-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9219184b92f4dc52e1c/master/w_2560,c_limit/00057-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e923d08063c920b9ed45/master/w_2560,c_limit/00058-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e923d08063c920b9ed4b/master/w_2560,c_limit/00059-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e925d34aaf50ee468691/master/w_2560,c_limit/00060-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9265f1f1b829bc6bcce/master/w_2560,c_limit/00061-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9273a8f05b89fdd7c81/master/w_2560,c_limit/00062-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9293a8f05b89fdd7c87/master/w_2560,c_limit/00063-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e92a113b585837febeae/master/w_2560,c_limit/00064-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e92b05db6c5acc229612/master/w_2560,c_limit/00065-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e92dea5539abc092d4a5/master/w_2560,c_limit/00066-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e995c6655877971ab13e/master/w_2560,c_limit/00067-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e92ffdeb03b5ba7ec759/master/w_2560,c_limit/00068-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e933c6655877971ab125/master/w_2560,c_limit/00069-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e933fffa071ef193359d/master/w_2560,c_limit/00070-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9343fde453b99cbb343/master/w_2560,c_limit/00071-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 2 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e93819b858d5d66632dc/master/w_2560,c_limit/00072-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e93957966e4abfc2181f/master/w_2560,c_limit/00073-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9385fee983aa51232b0/master/w_2560,c_limit/00074-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e93c848a39800b805156/master/w_2560,c_limit/00075-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e93e75300db6e628e0fa/master/w_2560,c_limit/00076-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e93ed34aaf50ee4686a1/master/w_2560,c_limit/00077-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9b37fe60fdf8f629f89/master/w_2560,c_limit/00078-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9438bd473891a512ffa/master/w_2560,c_limit/00079-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e943848a39800b80515c/master/w_2560,c_limit/00080-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e948848a39800b805167/master/w_2560,c_limit/00081-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e948c6655877971ab130/master/w_2560,c_limit/00082-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:54 [look] 主图 https://assets.vogue.com/photos/69a6e9d1fffa071ef19335a6/master/w_2560,c_limit/00083-gucci-fall-2026-ready-to-wear-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:54 [成功] 已上报待入库: Fall 2026 Ready-to-Wear (共 83 个 look / 141 张图)
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb474a4ee5f94bd2271a/master/w_2560,c_limit/00001-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4788b582cdf7c3aff3/master/w_2560,c_limit/00002-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb46f7a2897adc1b49fe/master/w_2560,c_limit/00003-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb49f79c6e9267cef5ac/master/w_2560,c_limit/00004-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4a554ccac7d1e1f4b0/master/w_2560,c_limit/00005-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4a32c2e2d3bf98b10d/master/w_2560,c_limit/00006-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4d2dd0f37bf34746a9/master/w_2560,c_limit/00007-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4df4dd14a320411132/master/w_2560,c_limit/00008-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4d0bfa06b1dea5d12b/master/w_2560,c_limit/00009-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb4f43b90a2074d6181e/master/w_2560,c_limit/00010-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb51b06f3238a60b0225/master/w_2560,c_limit/00011-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb51f79c6e9267cef5ae/master/w_2560,c_limit/00012-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb52db59dc04636d13dd/master/w_2560,c_limit/00013-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb54752b433b219c544e/master/w_2560,c_limit/00014-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb54752b433b219c544f/master/w_2560,c_limit/00015-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb55b06f3238a60b0227/master/w_2560,c_limit/00016-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb576607436cdc76efb3/master/w_2560,c_limit/00017-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb57008045d04b846a0b/master/w_2560,c_limit/00018-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb58f4dd14a320411134/master/w_2560,c_limit/00019-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5a9378bbf43e259849/master/w_2560,c_limit/00020-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5c32c2e2d3bf98b110/master/w_2560,c_limit/00021-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5bbd4a8b9260dcf286/master/w_2560,c_limit/00022-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5ca226facb3a9f1175/master/w_2560,c_limit/00023-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5e88b582cdf7c3aff5/master/w_2560,c_limit/00024-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5f9378bbf43e25984c/master/w_2560,c_limit/00025-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb5f752b433b219c5451/master/w_2560,c_limit/00026-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb61a226facb3a9f1178/master/w_2560,c_limit/00027-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb63329a0224809638dd/master/w_2560,c_limit/00028-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb63f7a2897adc1b4a00/master/w_2560,c_limit/00029-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6343b90a2074d61820/master/w_2560,c_limit/00030-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb669378bbf43e25984e/master/w_2560,c_limit/00031-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb66f7a2897adc1b4a02/master/w_2560,c_limit/00032-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6743b90a2074d61822/master/w_2560,c_limit/00033-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb69dd32dc180f6b3561/master/w_2560,c_limit/00034-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6af79c6e9267cef5b0/master/w_2560,c_limit/00035-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6b176c2cf4dce76b8c/master/w_2560,c_limit/00036-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6ca0026000fda92320/master/w_2560,c_limit/00037-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/68d0eb6ca226facb3a9f117a/master/w_2560,c_limit/00038-gucci-spring-2026-ready-to-wear-credit-brand.jpg 附 0 张细节图
2026/09/11 22:31:55 [成功] 已上报待入库: Spring 2026 Ready-to-Wear (共 38 个 look / 38 张图)
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4adc46c427d039bde2/master/w_2560,c_limit/00001-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4af740689c42c1c802/master/w_2560,c_limit/00002-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4b5e97b8363f04de82/master/w_2560,c_limit/00003-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4d313e8fffafe175c8/master/w_2560,c_limit/00004-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4d78b18aebb7357852/master/w_2560,c_limit/00005-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b4e438959cabcb3b738/master/w_2560,c_limit/00006-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b50990c447c7554d0b0/master/w_2560,c_limit/00007-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b51438959cabcb3b73a/master/w_2560,c_limit/00008-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b51dc46c427d039bde4/master/w_2560,c_limit/00009-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b531c2b6ff4b63b38a7/master/w_2560,c_limit/00010-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b551810535ae4b59741/master/w_2560,c_limit/00011-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5524a46ebebe8e4fb9/master/w_2560,c_limit/00012-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b56180867a056740f58/master/w_2560,c_limit/00013-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b58f25c7fb049e2f391/master/w_2560,c_limit/00014-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b59234aad71fd57d1ff/master/w_2560,c_limit/00015-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b598d8b5b664f5f26e5/master/w_2560,c_limit/00016-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5b180867a056740f5a/master/w_2560,c_limit/00017-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5c1c2b6ff4b63b38a9/master/w_2560,c_limit/00018-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5da22c6f62ceacf159/master/w_2560,c_limit/00019-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5e504fbe9c49ee94a2/master/w_2560,c_limit/00020-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b5ff740689c42c1c806/master/w_2560,c_limit/00021-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b60234aad71fd57d202/master/w_2560,c_limit/00022-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b61e591e2b2f98159f5/master/w_2560,c_limit/00023-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b62313e8fffafe175ca/master/w_2560,c_limit/00024-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b632a6d46e3815fa1af/master/w_2560,c_limit/00025-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b655e97b8363f04de86/master/w_2560,c_limit/00026-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b65ebdcca4392e74a9d/master/w_2560,c_limit/00027-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b66bbc3962e1a82e882/master/w_2560,c_limit/00028-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b68180867a056740f5d/master/w_2560,c_limit/00029-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6824a46ebebe8e4fbb/master/w_2560,c_limit/00030-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b691810535ae4b59743/master/w_2560,c_limit/00031-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6bf740689c42c1c809/master/w_2560,c_limit/00032-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6b18715b0da0d8f6ba/master/w_2560,c_limit/00033-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6c75aa28c41b11352e/master/w_2560,c_limit/00034-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6e78b18aebb7357854/master/w_2560,c_limit/00035-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6ebbc3962e1a82e884/master/w_2560,c_limit/00036-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b6f78b18aebb7357856/master/w_2560,c_limit/00037-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b728d8b5b664f5f26e7/master/w_2560,c_limit/00038-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7175aa28c41b113531/master/w_2560,c_limit/00039-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b71bbc3962e1a82e886/master/w_2560,c_limit/00040-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b75f740689c42c1c80b/master/w_2560,c_limit/00041-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b75c1c3c6b90dcb55ad/master/w_2560,c_limit/00042-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b75313e8fffafe175cc/master/w_2560,c_limit/00043-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b77438959cabcb3b73e/master/w_2560,c_limit/00044-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b782a6d46e3815fa1b1/master/w_2560,c_limit/00045-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b79a22c6f62ceacf15c/master/w_2560,c_limit/00046-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7af25c7fb049e2f393/master/w_2560,c_limit/00047-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305bb754a4b7d4e38430d4/master/w_2560,c_limit/00048-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7cebdcca4392e74a9f/master/w_2560,c_limit/00049-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7d180867a056740f5f/master/w_2560,c_limit/00050-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7ec1c3c6b90dcb55af/master/w_2560,c_limit/00051-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b7f438959cabcb3b740/master/w_2560,c_limit/00052-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b8175aa28c41b113533/master/w_2560,c_limit/00053-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b815e97b8363f04de89/master/w_2560,c_limit/00054-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b82da9a25400a479980/master/w_2560,c_limit/00055-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b84f2904f35b853d113/master/w_2560,c_limit/00056-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b842a6d46e3815fa1b3/master/w_2560,c_limit/00057-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [look] 主图 https://assets.vogue.com/photos/69305b85f25c7fb049e2f395/master/w_2560,c_limit/00058-gucci-pre-fall-2026-credit-brand.jpg 附 1 张细节图
2026/09/11 22:31:55 [成功] 已上报待入库: Pre-Fall 2026 (共 58 个 look / 116 张图)
2026/09/11 22:31:55 [Info] Vogue 所有抓取任务已完成!

2810
spider_run.log Normal file

File diff suppressed because it is too large Load Diff