ЁЯОп рдХрд╕реНрдЯрдорд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдпреЛрдЧреНрдп, рдбрд┐рдЯреЗрдХреНрд╢рди-рдкреНрд░рддрд┐рд░реЛрдзреА рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЬреЛ рд╕реНрд╡-рд╡рд┐рдХрд╕рд┐рдд Chromium рджреНрд╡рд╛рд░рд╛ рд╕рдВрдЪрд╛рд▓рд┐рдд рд╣реИ, рд╡реЗрдм рдХреНрд░реЙрд▓рд░ рдФрд░ рдПрдЖрдИ рдПрдЬреЗрдВрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ред ЁЯСЙрдЕрднреА рдЖрдЬрд╝рдорд╛рдПрдВ
рд╡рд╛рдкрд╕ рдмреНрд▓реЙрдЧ рдкрд░

рдХреИрд╕реЗ Scrapeless Scraping рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рд╕рд╛рде рдПрдХ Etsy рд╕реНрдХреНрд░реИрдкрд░ рдмрдирд╛рдПрдВ: рд╡реНрдпрд╛рдкрдХ рдЧрд╛рдЗрдб 2026 (Node.js)

James Thompson
James Thompson

Scraping and Proxy Management Expert

16-Apr-2026

рдореБрдЦреНрдп рдмрд╛рддреЗрдВ:

  • Scrapeless Scraping Browser рдПрдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдПрдЖрдИ рдмреНрд░рд╛рдЙрдЬрд░ рдЗрдиреНрдлреНрд░рд╛рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ, рдЬреЛ Etsy рдХреЗ DataDome рдПрдВрдЯреА-рдмреЙрдЯ рд▓реЗрдпрд░ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯрд┐рдВрдЧ, рдЖрд╡рд╛рд╕реАрдп рдкреНрд░реЙрдХреНрд╕реА рдФрд░ CAPTCHA рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рд╕рд╛рдл рдХрд░рддрд╛ рд╣реИред
  • рдПрдХ CONFIG рдмреНрд▓реЙрдХ рд╕реЗ рдЪрд╛рд░ рдбрд┐рд╕реНрдХрд╡рд░реА рдореЛрдб тАФ рдЙрддреНрдкрд╛рдж URL, рд╢реНрд░реЗрдгреА URL, рдХреАрд╡рд░реНрдб рдЦреЛрдЬ (рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд╕рд╛рде) рдФрд░ рджреБрдХрд╛рди URLред рдЗрдирдкреБрдЯреНрд╕ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░реЗрдВ, рд╡рд╣реА рдкрд╛рдЗрдкрд▓рд╛рдЗрдиред
  • рдЖрда рд╕рдВрд░рдЪрд┐рдд рдлрд╝рд┐рд▓реНрдЯрд░ (рдмрд┐рдХреНрд░реА рдкрд░, рдлреНрд░реА-рд╢рд┐рдкрд┐рдВрдЧ, рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп, рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдиреНрдпреВрдирддрдо/рдЕрдзрд┐рдХрддрдо рдХреАрдордд, рд╕реНрдерд┐рддрд┐, рдХреНрд░рдо рджреНрд╡рд╛рд░рд╛) рдХрд┐рд╕реА рднреА рдбрд┐рд╕реНрдХрд╡рд░реА рдореЛрдб рдХреЗ рд╕рд╛рде рдорд┐рд╢реНрд░рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдЦреЛрдЬ рдпрд╛ рд╢реНрд░реЗрдгреА URLs рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
  • рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдХреАрдорд╛ рдкреНрд░рддрд┐ рдЙрддреНрдкрд╛рдж 30+ рдлрд╝реАрд▓реНрдб рдХреЛ рдХрд╡рд░ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ variations, breadcrumbs, listedDate, reviews[].photos рдФрд░ рдЕрджреНрд╡рд┐рддреАрдп рд╡рд┐рдкрдгрди рд╕рдВрдХреЗрдд (isBestseller, isStarSeller, isFreeShipping, inStock, favoritesCount, рдкреНрд░рддрд┐-рд░рд┐рд╡реНрдпреВ рдЙрдк-рд╕реНрдХреЛрд░) рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
  • рдПрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рд▓реВрдк (рдбрд┐рдлрд╝реЙрд▓реНрдЯ maxRetries: 10, рдмрдврд╝рддрд╛ рдмреИрдХрдСрдлрд╝ 3 рд╕реЗрдХрдВрдб тЖТ 47 рд╕реЗрдХрдВрдб) рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рдмреАрдЪ рддрд╛рдЬрд╛ рд╕рддреНрд░ рдФрд░ рдЖрд╡рд╛рд╕реАрдп IP рдХреА рдУрд░ рдШреВрдорддрд╛ рд╣реИ, рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЕрд╕реНрдерд╛рдпреА 403s рдХреЛ рдЕрд╡рд╢реЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдкрд░рд┐рдЪрдп: рдПрдВрдЯреА-рдбрд┐рдЯреЗрдХреНрд╢рди рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рд╕рд╛рде рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ Etsy

Etsy рдИ-рдХреЙрдорд░реНрд╕ рдЦреБрдлрд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЦрдЬрд╛рдирд╛ рд╣реИ: рджреБрдХрд╛рди рдорд╛рд▓рд┐рдХреЛрдВ рдХреЗ рд▓рд┐рдП рддреБрд▓рдирд╛рддреНрдордХ рд╡рд┐рдХреНрд░реЗрддрд╛ рдореВрд▓реНрдп, рдПрдордПрд▓ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рднрд╛рд╡рдирд╛-рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдХреЙрд░реНрдкрд╕ рдФрд░ рдбреНрд░реЙрдкрд╢рд┐рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рдЪреЗ рдЦреЛрдЬ рд╕рднреА рдЙрд╕реА рд╕реВрдЪреАрдХрд░рдг рдкреГрд╖реНрдареЛрдВ рд╕реЗ рдкреНрд░рд╡рд╛рд╣рд┐рдд рд╣реЛрддреЗ рд╣реИрдВред рдЖрдзрд┐рдХрд╛рд░рд┐рдХ Etsy API рдХрд╛ рд╕реАрдорд┐рдд рдкрд╣реБрдВрдЪ рдФрд░ рд▓рдВрдмрд╛ рд╕реНрд╡реАрдХреГрддрд┐ рдЪрдХреНрд░ рд╣реИ, рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдбреЗрдЯрд╛ рдкреБрдирд░реНрд╡рд┐рдХреНрд░реЗрддрд╛ рдорд╣рдВрдЧреЗ рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдХрд╕реНрдЯрдо рд╕реНрдХреНрд░реИрдкрд░ рдХреЛ DataDome рдХреЗ рдЦрд┐рд▓рд╛рдл рдЪрд▓ рд░рд╣реЗ рд░рдЦрд░рдЦрд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдФрд░ Etsy рдХреЗ рдлреНрд░рдВрдЯрдПрдВрдб рдкрд░ рд▓рдЧрд╛рддрд╛рд░ CSS рд╡рд░реНрдЧ рдирд╛рдореЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИред

рдпрд╣ рдЧрд╛рдЗрдб рдПрдХ рдПрдХрд▓ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЪрд▓рддреА рд╣реИ рдЬреЛ Scrapeless Scraping Browser рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ рдЬреЛ рд╕рднреА рдХрдард┐рди рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкрд╣рд▓реЗ рд╣реА рд╕рдВрднрд╛рд▓ рд▓реЗрддреА рд╣реИ: рдПрдВрдЯреА-рдбрд┐рдЯреЗрдХреНрд╢рди рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░, рдЖрд╡рд╛рд╕реАрдп рдкреНрд░реЙрдХреНрд╕реА, рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдФрд░ рджреБрдХрд╛рди рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐-рдЙрддреНрдкрд╛рдж рд╕рдореГрджреНрдзрд┐ рдФрд░ рд╡рд╣ рдмрд╣реБ-рдкреВрдВрдЫ рд╡рд┐рд╕реНрддрд╛рд░ рддрдХрдиреАрдХ рдЬреЛ рдПрдХ рдПрдХрд▓ рдмреЗрд╕ рдХреАрд╡рд░реНрдб рд╕реЗ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдЕрдзрд┐рдХ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рдХрд░рддреА рд╣реИ рдЬрд┐рддрдирд╛ рдХрд┐ Etsy рдХреЗ рдкреНрд░рддрд┐-рдЦреЛрдЬ рдХреА рдЫрдд рд╕рд╛рдорд╛рдиреНрдпрддрдГ рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рд╡рд╣реА рд╕реНрдХреНрд░реИрдкрд░ рдЪрд╛рд░ рд╕реНрд╡рддрдВрддреНрд░ рдбрд┐рд╕реНрдХрд╡рд░реА рдореЛрдб рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ тАФ рдЗрд╕реЗ рдЙрддреНрдкрд╛рдж URL, рд╢реНрд░реЗрдгреА URL, рдХреАрд╡рд░реНрдб рдЦреЛрдЬ рдпрд╛ рджреБрдХрд╛рди URL рджреЗрдВ тАФ рдФрд░ рд╣рд░ рдЖрдЙрдЯрдкреБрдЯ рдкрдВрдХреНрддрд┐ рд╕реВрдЪреАрдХрд░рдг рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рд╡рд╣реА рд╕рдореГрджреНрдз 30-рдлреАрд▓реНрдб рд╕реНрдХреАрдорд╛ рд▓реЗ рдЖрддреА рд╣реИред


рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

Etsy рдбреЗрдЯрд╛ рдПрдХ рдмрд╣реБрдкрд░рдХрд╛рд░реА рд╕рдВрдкрддреНрддрд┐ рд╣реИ, рдЬреЛ рдЙрддреНрдкрд╛рдж рдЕрдиреБрд╕рдВрдзрд╛рди рд╕реЗ рд▓реЗрдХрд░ рдЙрдиреНрдирдд рдПрдЖрдИ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рддрдХ рдЙрдЪреНрдЪ-рдкреНрд░рднрд╛рд╡ рд╡рд╛рд▓реЗ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рдЪрд▓рд╛рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдкрд╛рдВрдЪ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреЗ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдЙрдкрдпреЛрдЧ рд╣реИрдВ, рд╕рднреА рдЙрд╕реА рдХреЛрдбрдмреЗрд╕ рд╕реЗ рдкреНрд░рд╛рдкреНрдп, рдЕрдХреНрд╕рд░ рдХреЗрд╡рд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде:

  1. рдбреНрд░реЙрдкрд╢рд┐рдкрд┐рдВрдЧ рдЕрдиреБрд╕рдВрдзрд╛рди рдФрд░ рдЙрддреНрдкрд╛рдж рдЦреЛрдЬрдирд╛ тАФ рдХреАрд╡рд░реНрдб-рдЦреЛрдЬ рдореЛрдбред рд╕реНрдХреНрд░реИрдкрд░ рдХреЛ "macram├й plant hanger" рдкрд░ expandStrategy: "keywords" рдХреЗ рд╕рд╛рде ["boho", "modern", "minimalist"] рдкрд░ рдЪрд▓рд╛рдПрдВ, maxProducts: 200 рд╕реЗрдЯ рдХрд░реЗрдВ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ favoritesCount ├Ч rating рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдо рджреЗрдВред рдЙрди рджреБрдХрд╛рдиреЛрдВ рдореЗрдВ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░реЗрдВ рдЬрд╣рд╛рдБ isStarSeller: true рд╣реИ рдФрд░ favoritesCount рдФрд╕рдд рд╕реЗ рдХрд╛рдлреА рдКрдкрд░ рд╣реИ тАФ рдпреЗ рдЖрдкрдХреЗ рдбреНрд░реЙрдкрд╢рд┐рдкрд┐рдВрдЧ рдЙрдореНрдореАрджрд╡рд╛рд░ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдореА CSV рдХреЛ Shopify рдпрд╛ рдПрдХ рдирд┐рдЬреА рдЖрдкреВрд░реНрддрд┐рдХрд░реНрддрд╛ рд╕реВрдЪреА рдореЗрдВ рдЫреЛрдбрд╝ рджреЗрдВред рдпрд╣реА рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд▓реЛрдЧ Etsy рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд░рд╛рдЬрд╕реНрд╡ рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рддреЗрдЬрд╝ рддрд░реАрдХрд╛ рд╣реИред
  2. рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдореВрд▓реНрдп рдирд┐рдЧрд░рд╛рдиреА тАФ рдЙрддреНрдкрд╛рдж-URL (рдкреНрд░рддреНрдпрдХреНрд╖-URL) рдореЛрдбред рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рд╕реВрдЪреА URL рдХреА рдПрдХ рд╕реВрдЪреА рдХреЛ startUrls рдореЗрдВ рд░рдЦреЗрдВ рдФрд░ рд╕реНрдХреНрд░реИрдкрд░ рдХреЛ рд░рд╛рдд рдореЗрдВ рдЪрд▓рд╛рдПрдБред рдкреНрд░рддреНрдпреЗрдХ JSON рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЛ рдЗрд╕рдХреА scrapedAt рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдХреЗ рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВ рдФрд░ рдХреАрдордд, originalPrice, discountPercent рдФрд░ рдЪрд▓рди рдореЗрдВ рд╕реНрдЯреЙрдХ рдХреЗ рдмреАрдЪ рдЕрдВрддрд░ рдХрд░реЗрдВред рдХреНрдпрд╛ рдореВрд▓реНрдп рдореЗрдВ 10% рд╕реЗ рдЕрдзрд┐рдХ рдЧрд┐рд░рд╛рд╡рдЯ рд╣реИ? рд╕реНрд▓реИрдХ рдЕрд▓рд╛рд░реНрдоред inStock true рд╕реЗ false рдореЗрдВ рдмрджрд▓рддрд╛ рд╣реИ? рдЖрдкреВрд░реНрддрд┐ рд╕рдВрдХреЗрдд рдХреЗ рд░реВрдк рдореЗрдВ рдЭрдВрдбрд╛ред рдЖрдк рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЬреЛ рдкреВрд░реНрдг рдореВрд▓реНрдп рдЗрддрд┐рд╣рд╛рд╕ рдмрдирд╛рддреЗ рд╣реИрдВ рд╡рд╣ рд╣рд░ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛-рдЦреБрдлрд┐рдпрд╛ рдбреИрд╢рдмреЛрд░реНрдб рдХрд╛ рдореБрдЦреНрдп рдЖрдзрд╛рд░ рд╣реИред
  3. рдХреАрд╡рд░реНрдб рдФрд░ рдкреНрд░рд╡реГрддреНрддрд┐ рдЕрдиреБрд╕рдВрдзрд╛рди тАФ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд╕рд╛рде рд╢реНрд░реЗрдгреА-URL рдореЛрдбред categoryUrl рдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ Etsy рд╢реНрд░реЗрдгреА рдХреА рдУрд░ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ (рдЬреИрд╕реЗ /c/bags-and-purses/wallets-and-money-clips/wallets), рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рдВрдпреЛрдЬрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ (filters.onSale: true, filters.condition: "new", filters.orderBy: "date_desc"), рдХреБрдЫ рд╕реМ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдореЗрдВ tags рдФрд░ materials рдХреЛ рдЦреАрдВрдЪреЗрдВ, рдЙрдирдХреА рдЖрд╡реГрддреНрддрд┐ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ favoritesCount рдХреЗ рдпреЛрдЧ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдордмрджреНрдз рдХрд░реЗрдВред рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдмрдирд╛рдИ рдЧрдИ рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реЗ рдЯреИрдЧ рд▓реЗрдХрд┐рди рдкреБрд░рд╛рдиреЗ рдореЗрдВ рдирд╣реАрдВ рдЖрдкрдХреЗ рдмрдврд╝рддреЗ рдЙрдк-рдирд┐рдЪреЗ рд╣реИрдВред
  4. рдПрдордПрд▓ рдФрд░ рдмрд╛рдЬрд╛рд░ рдЕрдиреБрд╕рдВрдзрд╛рди рдХреЗ рд▓рд┐рдП рд╕рдореАрдХреНрд╖рд╛ рд╕рдВрдЧреНрд░рд╣рдг тАФ рдХреАрд╡рд░реНрдб рдпрд╛ рд╢реНрд░реЗрдгреА рдореЛрдбред рдПрдХ рд╡рд░реНрдЯрд┐рдХрд▓ (рд╣реИрдВрдбрдореЗрдб рдореЛрдордмрддреНрддрд┐рдпрд╛рдБ, рдХрд╣реЗрдВ, рдпрд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЖрднреВрд╖рдг) рдореЗрдВ рд╣рдЬрд╛рд░реЛрдВ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдореЗрдВ reviews[] рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░реЗрдВ, reviews[].text рдХреЛ рдПрдХ рднрд╛рд╡рдирд╛ рд╡рд░реНрдЧреАрдХрд░рдгрдХрд░реНрддрд╛ рдореЗрдВ рдлреАрдб рдХрд░реЗрдВ рдФрд░ рдЙрдирдХреЗ рдЙрдкрд╕реНрдерд┐рдд рд╣реЛрдиреЗ рдкрд░ рд╕реБрдкрд░рд╡рд╛рдЗрдЬреНрдб рдЯреНрд░реЗрдирд┐рдВрдЧ рд▓реЗрдмрд▓ рдХреЗ рд░реВрдк рдореЗрдВ itemQuality / shipping / customerService рдЙрдк-рд░реЗрдЯрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдкреНрд░рддрд┐-рд░рд┐рд╡реНрдпреВ рдлрд╝реЛрдЯреЛ (reviews[].photos[]) рдЖрдкрдХреЛ рдПрдХ рд╕рдорд╛рди рдЫрд╡рд┐ рдХреЙрд░реНрдкрд╕ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЛ рджреГрд╢реНрдп рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
  5. рджреБрдХрд╛рди рдкреНрд░рджрд░реНрд╢рди рдмреЗрдВрдЪрдорд╛рд░реНрдХрд┐рдВрдЧ тАФ рджреБрдХрд╛рди-рдпреВрдЖрд░рдПрд▓ рдореЛрдбред рдмрд┐рдВрджреБ shopUrl рдХреЛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдХреА рджреБрдХрд╛рди рдкреГрд╖реНрда рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВ (рдЬреИрд╕реЗ https://www.etsy.com/shop/TexasValleyLeather), maxPagesPerQuery: 5 рд╕реЗрдЯ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдЙрдирдХреЗ рдкреВрд░реЗ рдХреИрдЯрд▓реЙрдЧ рдХреЛ рдкреГрд╖реНрдард╛рдВрдХрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдФрд░ рд╕реНрдХреНрд░реИрдкрд░ рдЙрди рд╕рднреА рд╕реВрдЪреАрдХрд░рдгреЛрдВ рдХреЛ рд╕рдВрдЦреНрдпрд╛рдмрджреНрдз рдХрд░реЗ рдЬреЛ рд╡рд╣ рджреБрдХрд╛рди рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдмреЗрдЪрддреА рд╣реИред рд╕рдорд╛рди рд╢реНрд░реЗрдгреА рдореЗрдВ рд╡рд┐рдХреНрд░реЗрддрд╛рдУрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ shop.totalSales, shop.openedYear, rating, reviewsCount рдФрд░ isStarSeller рджреНрд╡рд╛рд░рд╛ред

рдХреНрдпреЛрдВ рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕

рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЖрдкрдХреЗ рд╕реНрдХреНрд░реИрдкрд░ рдХреЛ рдПрдХ рдЙрддреНрдкрд╛рджрди-рдЧреНрд░реЗрдб рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдИрдЯреАрд╕реА рдХреЗ рдбреЗрдЯрд╛ рдбреЛрдо рдЪреЗрдХ рдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдХреЛрдбрд┐рдВрдЧ рдХреЗ рд╕рд╛рдл рдХрд░рддрд╛ рд╣реИ тАФ рдХреЛрдИ рд╕реНрдЯреЗрд▓реНрде рдкреНрд▓рдЧрдЗрдиреНрд╕, рдХреЛрдИ рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯ рдЯреНрдпреВрдирд┐рдВрдЧ, рдХреЛрдИ рдкреНрд░реЙрдХреНрд╕реА рд░реЛрдЯреЗрд╢рди рд╕реНрдХреНрд░рд┐рдкреНрдЯреНрд╕ рдирд╣реАрдВ рдЬреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред Puppeteer рдпрд╛ Playwright рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ WebSocket рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВ рдФрд░ рдЕрд╡рд╕рдВрд░рдЪрдирд╛ рдПрдВрдЯреА-рдмреЙрдЯ рд▓реЗрдпрд░ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рджреЗред

рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдЖрдкрдХреЛ рдорд┐рд▓рддрд╛ рд╣реИ:

  • рдПрдВрдЯреА-рдбрд┐рдЯреЗрдХреНрд╢рди рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯрд┐рдВрдЧ рдЬреЛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рд╕рддреНрд░реЛрдВ рдореЗрдВ рдЯрд┐рдХрд╛рдК рд░рд╣рддреА рд╣реИ
  • рд╕реНрдерд╛рдпреА рдкреНрд░реЙрдХреНрд╕реА
    195+ рджреЗрд╢реЛрдВ рдореЗрдВ (рдЕрд▓рдЧ рд╕реЗ US, GB, DE рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рдг)
  • рд╕реНрд╡рдЪрд╛рд▓рд┐рдд CAPTCHA рд╕рдорд╛рдзрд╛рди рдЬрдм рдИрдЯреАрд╕реА рдПрдХ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ
  • рд╕рддреНрд░ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдкрд┐рдЫрд▓реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЪрдпрдирдХрд░реНрддрд╛ рдЧрд┐рд░рд╛рд╡рдЯ рдХреА рд╕рдорд╕реНрдпрд╛ рдирд┐рд╡рд╛рд░рдг рдХреЗ рд▓рд┐рдП
  • WebSocket рдПрдВрдбрдкреЙрдЗрдВрдЯреНрд╕ рдЬреЛ Puppeteer рдФрд░ Playwright рдЬреИрд╕реЗ CDP-рдЖрдзрд╛рд░рд┐рдд рдврд╛рдВрдЪреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВ тАФ рдХреЛрдИ SDK рд╕реАрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ
  • рдПрдЖрдИ рдПрдЬреЗрдВрдЯ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░: рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ MCP рд╕рд░реНрд╡рд░ рдЬреИрд╕реЗ рдЯреВрд▓ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдирд┐рд╡рд╛рд░рдг рдФрд░ рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕реБрдЪрд╛рд░реВ рд░реВрдк рд╕реЗ рдПрдХреАрдХреГрдд рдХрд░рддрд╛ рд╣реИред

рд╕рдВрдпреЛрдЧ рдПрдХ-рд▓рд╛рдЗрди рдХрд╛ рдкрд░рд┐рд╡рд░реНрддрди рд╣реИ: puppeteer.connect() рдХреЛ рдПрдХ рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рдпреВрдЖрд░рдПрд▓ рдкрд░ рдЗрдВрдЧреАрдд рдХрд░реЗрдВ рди рдХрд┐ рд╕реНрдерд╛рдиреАрдп рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдкрд░ред рдмрд╛рдХреА рдХреЛрдб рдмрд┐рд▓реНрдХреБрд▓ рд╡рд╣реА рд░рд╣рддрд╛ рд╣реИ тАФ рдорд╛рдирдХ CDP, рдорд╛рдирдХ рдЪрдпрдирдХрд░реНрддрд╛, рдорд╛рдирдХ рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣ред рд╕рднреА рдбреЗрдЯрд╛ рдбреЛрдо рдЬрдЯрд┐рд▓рддрд╛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░, рдЖрдкрдХреЗ рдХреЛрдбрдмреЗрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд░рд╣рддреА рд╣реИред

app.scrapeless.com рдкрд░ рдирд┐рдГрд╢реБрд▓реНрдХ рдпреЛрдЬрдирд╛ рдореЗрдВ рдЕрдкрдирд╛ API рдХреБрдВрдЬреА рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред


рдкреВрд░реНрд╡рд╛рдкреЗрдХреНрд╖рд╛рдПрдБ рдФрд░ рд╕реНрдерд╛рдкрдирд╛

Node.js 18 рдпрд╛ рдирдпрд╛ред рдПрдХ рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ API рдХреБрдВрдЬреА (рдирд┐рдГрд╢реБрд▓реНрдХ рд╕реНрддрд░ рдЗрд╕ рдЧрд╛рдЗрдб рдореЗрдВ рд╕рдм рдХреБрдЫ рдХрд╡рд░ рдХрд░рддрд╛ рд╣реИ)ред рдХреБрдЫ Puppeteer рдХреА рдкрд░рд┐рдЪрд┐рддрддрд╛ рд╕рд╣рд╛рдпрдХ рд╣реЛрддреА рд╣реИред рд╕реНрдерд╛рдиреАрдп Chrome рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ тАФ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рдХреЗ рдХреНрд▓рд╛рдЙрдб рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИред

bash Copy
mkdir etsy-scrapeless-browserless && cd etsy-scrapeless-browserless
npm init -y
npm install puppeteer-core dotenv cheerio
npm install -D tsx typescript @types/node @types/cheerio

puppeteer-core рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдЪрд╛рд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ; cheerio рдкреНрд░рджрд░реНрд╢рд┐рдд HTML рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗ рд▓реЛрдб рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдкрд░ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИред рдмреНрд░рд╛рдЙрдЬрд╝рд░-рд╕рд╛рдЗрдб рд╕реНрдХреНрд░реЛрд▓рд┐рдВрдЧ рдФрд░ Node-рд╕рд╛рдЗрдб рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЛ рдЕрд▓рдЧ рдХрд░рдирд╛ рд╣рд░ рдПрдХреНрд╕рдЯреНрд░реИрдХреНрдЯрд░ рдХреЛ рдЯрд╛рдЗрдк рдФрд░ рд╕рд╣реЗрдЬреЗ рдЧрдП HTML рдлрд┐рдХреНрд╕реНрдЪрд░ рдХреЗ рдЦрд┐рд▓рд╛рдл рдпреВрдирд┐рдЯ-рдЯреЗрд╕реНрдЯ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдП рд░рдЦрддрд╛ рд╣реИред

.env:

Copy
SCRAPELESS_API_KEY=your_key_here

рдХрджрдо 1 тАФ рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВ

рдкреВрд░реЗ рд╕реНрдХреНрд░реИрдкрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдиреЗрдХреНрд╢рди рд╕рд╣рд╛рдпрдХред рдЯреЛрдХрди, рджреЗрд╢ рдФрд░ TTL рдХреЗ рд╕рд╛рде рдПрдХ WSS рдпреВрдЖрд░рдПрд▓ рдмрдирд╛рдПрдВ, рдлрд┐рд░ рдЗрд╕реЗ puppeteer.connect рдХреЛ рд╕реМрдВрдкреЗрдВред

ts Copy
import "dotenv/config";
import puppeteer, { type Browser, type Page } from "puppeteer-core";
import * as cheerio from "cheerio";

// рд╕рд╣рд╛рдпрдХ тАФ рдкреГрд╖реНрда рдХрд╛ рдкреВрд░рд╛ HTML рдЦреАрдВрдЪреЗрдВ рдФрд░ рдЗрд╕реЗ cheerio рдХреЗ рд╕рд╛рде рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред рдХреЙрд▓рд░
// рдХрд┐рд╕реА рднреА рдмреНрд░рд╛рдЙрдЬрд╝рд░-рд╕рд╛рдЗрдб рд╕реНрдХреНрд░реЛрд▓рд┐рдВрдЧ / waitForFunction рдХреЛ рдкрд╣рд▓реЗ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ
// рддрд╛рдХрд┐ рдЖрд▓рд╕реА рдХреНрд╖реЗрддреНрд░ рд╣рд╛рдЗрдбреНрд░реЗрдЯреЗрдб рд╣реЛ рд╕рдХреЗрдВред рдЗрд╕рдХреЗ рдмрд╛рдж, рдкрд╛рд░реНрд╕рд┐рдВрдЧ Node рдореЗрдВ рд░рд╣рддреА рд╣реИ:
// рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рд╣реБрдЖ, рдХреЛрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧрд┐рдлрд╛рдЗрдб рдореВрд▓реНрдпрд╛рдВрдХрди рдмреЙрдбреА рдирд╣реАрдВ, рдХреЛрдИ `__name` tsx рдЧрдбреНрдврд╛ рдирд╣реАрдВ, рдмрдЪрдд HTML рдлрд┐рдХреНрд╕реНрдЪрд░ рдХреЗ рдЦрд┐рд▓рд╛рдл
// рдпреВрдирд┐рдЯ-рдЯреЗрд╕реНрдЯ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред
async function parseWithCheerio(page: Page): Promise<cheerio.CheerioAPI> {
  const html = await page.content();
  return cheerio.load(html);
}

type ScraperInput = {
  proxyCountry: string;   // рдЬреИрд╕реЗ "US", "GB", "DE"
  sessionTTL: number;     // рд╕реЗрдХрдВрдб, 60тАУ900 рдХреА рдЕрдиреБрдорддрд┐; 600 рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╣реИ
};

function connectionURL(sessionName: string, cfg: ScraperInput): string {
  const token = process.env.SCRAPELESS_API_KEY;
  if (!token) throw new Error("SCRAPELESS_API_KEY is not set in .env");
  // рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рдбрд┐рдлреЙрд▓реНрдЯ рджреНрд╡рд╛рд░рд╛ рд╕рддреНрд░ рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдпреА рдЖрдИрдкреА рдкрд┐рди рдХрд░рддрд╛ рд╣реИ,
  // рдЗрд╕рд▓рд┐рдП рдПрдХ puppeteer.connect рдХреЗ рднреАрддрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЙрд╕реА 
  // рдЖрдЙрдЯрдмрд╛рдЙрдВрдб рдЖрдИрдкреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдПрдХ рдирдП рд╕рддреНрд░ (рдирдпрд╛ рдХрдиреЗрдХреНрд╢рди) рдХреЛ рдЦреЛрд▓рдиреЗ рд╕реЗ рдПрдХ рдирдпрд╛ рдЖрдИрдкреА рдорд┐рд▓рддрд╛ рд╣реИ,
  // рдЬрд┐рд╕ рдкрд░ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдЪрдХреНрд░ рдХреЛ рдПрдХ рдлреНрд▓реИрдЧ рдХрд┐рдП рдЧрдП рдЖрдИрдкреА рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рд░реВрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднрд░реЛрд╕рд╛ рд╣реЛрддрд╛ рд╣реИред
  const qs = new URLSearchParams({
    token,
    proxyCountry: cfg.proxyCountry,
    sessionTTL: String(cfg.sessionTTL),
    sessionName,
    sessionRecording: "true",
    // рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рдХреЛ рдкреВрд░реНрдг рдбреЗрд╕реНрдХрдЯреЙрдк рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯ рдХрд╛ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рджреЗрдВ тАФ UA, рд╕реНрдХреНрд░реАрди, рдЯрд╛рдЗрдордЬрд╝реЛрди
    // рдФрд░ рднрд╛рд╖рд╛ред рдХреЛрдИ рдореИрдиреБрдЕрд▓ setViewport / setUserAgent рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВред
    fingerprint: JSON.stringify({ platform: "Windows" }),
  });
  return `wss://browser.scrapeless.com/api/v2/browser?${qs.toString()}`;
}

async function openBrowser(sessionName: string, cfg: ScraperInput): Promise<Browser> {
  return puppeteer.connect({
    browserWSEndpoint: connectionURL(sessionName, cfg),
    defaultViewport: null,
  });
}

рдпрд╣ рдкреВрд░реА Scrapeless-рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рддрд╣ рдХреНрд╖реЗрддреНрд░ рд╣реИ - рдПрдХ WSS URL рдФрд░ рдПрдХ puppeteer.connectред рдЗрд╕реЗ рд╕реНрдХреЗрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рдд рдпрд╣ рд╣реИ: рдПрдХ puppeteer.connect рд╕рддреНрд░ рдЕрдкрдиреЗ рдЬреАрд╡рдирдХрд╛рд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдирд┐рд╡рд╛рд╕реА IP рд╕реЗ рдмрдВрдзрд╛ рд╣реЛрддрд╛ рд╣реИ (рдПрдХ рд╣реА рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╣реИрдВрдбрд▓ рдкрд░ api.ipify.org рдХреЛ рд▓рдЧрд╛рддрд╛рд░ рддреАрди рдмрд╛рд░ рд╣рд┐рдЯ рдХрд░рдХреЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ - рд╣рд░ рдмрд╛рд░ рд╡рд╣реА IP)ред рдПрдХ рддрд╛рдЬрд╛ рд╕рддреНрд░ рдЦреЛрд▓рдиреЗ рд╕реЗ рдПрдХ рдирдпрд╛ IP рдорд┐рд▓рддрд╛ рд╣реИред рдпрд╣ рд╡рд╣реА рдЖрдзрд╛рд░ рд╣реИ рдЬрд┐рд╕ рдкрд░ рдЪрд░рдг 8 рдореЗрдВ_retry рд▓реВрдк рдмрдирддрд╛ рд╣реИ - рдпрджрд┐ рдЗрд╕ рд╕рддреНрд░ рдХреЗ IP рдкрд░ рдПрдХ рдЕрдиреБрд░реЛрдз рдЕрд╡рд░реБрджреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рд╕рддреНрд░ рдХреЛ рдмрдВрдж рдХрд░рддреЗ рд╣реИрдВ, рдПрдХ рдирдпрд╛ рдЦреЛрд▓рддреЗ рд╣реИрдВ, рдПрдХ рдирдпрд╛ IP рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рд╕реЗ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред

Scrapeless Scraping Browser рдХрдиреЗрдХреНрд╢рди рдкрд░рдд рдкрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯ рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд░рдЦрддрд╛ рд╣реИ - UA, рд╕реНрдХреНрд░реАрди рдЖрдХрд╛рд░, рдЯрд╛рдЗрдордЬрд╝реЛрди рдФрд░ рднрд╛рд╖рд╛ рд╕рднреА fingerprint: { platform: "Windows" } WSS URL рдкрд░ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рджреНрд╡рд╛рд░рд╛ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдиреБрдЕрд▓ setViewport рдпрд╛ setUserAgent рдХреЙрд▓реНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЪрд░рдг 8 рдореЗрдВ_retry рд▓реВрдк рдКрдкрд░ рдХрд┐рд╕реНрдордд рдмреНрд▓реЙрдХреНрд╕ рдХреЛ рдЕрд╡рд╢реЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдмреНрд░рд╛рдЙрдЬрд╝рд░-рдкрдХреНрд╖ рдХреА рд╕реЗрдЯрдЕрдк рдПрдХ-рд▓рд╛рдЗрди tsx рд╕рдВрдЧрддрддрд╛ рд╕реНрдЯрдм рд╣реИ:

ts Copy
async function prepPage(page: Page): Promise<void> {
  // рдкреГрд╖реНрда.evaluate рдлрд╝рдВрдХреНрд╢рди рдирд┐рдХрд╛рдпреЛрдВ рдХреЗ рд╕рд╛рде "__name is not defined" рдХреЗ рдЕрдВрджрд░ рдХреНрд░реИрд╢ рди рд╣реЛрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП tsx-рдЗрдирдЬреЗрдХреНрдЯреЗрдб __name рд╣реЗрд▓реНрдкрд░ рдХреЛ рд╕реНрдЯрдм рдХрд░реЗрдВред
  await page.evaluateOnNewDocument(
    "(function(){ globalThis.__name = function(f){ return f; }; })()",
  );
}

рд╕рддреНрд░ рд╡рд╛рд░реНрдо-рдЕрдк

рдЦреЛрдЬ рдпрд╛ рджреБрдХрд╛рди рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╕реНрдХреНрд░реИрдкрд░ рдкрд╣рд▓реЗ рдПрдХ рдмрд╛рд░ Etsy рдХреА рд╣реЛрдордкреЗрдЬ рдХреЛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдПрдХ рд╡реИрдз рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕рддреНрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдЗрд╕ рдХрджрдо рдХреЗ рдмрд┐рдирд╛, /search рдФрд░ /shop рдПрдВрдбрдкреЙрдЗрдВрдЯреНрд╕ рдПрдХ рдардВрдбреЗ рд╕рддреНрд░ рдкрд░ 403 рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ:

ts Copy
const ETSY_COUNTRY_PATHS: Record<string, string> = {
  US: "", DE: "de/", GB: "uk/", FR: "fr/", IT: "it/", ES: "es/",
  NL: "nl/", CA: "ca/", AU: "au/", JP: "jp/", IN: "in/",
};

async function warmUpSession(page: Page, proxyCountry: string): Promise<void> {
  const path = ETSY_COUNTRY_PATHS[proxyCountry] ?? "";
  try {
    await page.goto(`https://www.etsy.com/${path}`, {
      waitUntil: "domcontentloaded",
      timeout: 30000,
    });
  } catch {
    // рдЯрд╛рдЗрдордЖрдЙрдЯ рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рддреНрд░реБрдЯрд┐ рдареАрдХ рд╣реИ тАФ рддрдм рддрдХ рдХреБрдХреАрдЬрд╝ рд╕реЗрдЯ рдХреА рдЬрд╛рддреА рд╣реИрдВред
  }
  await dismissEtsyConsent(page);
  await delay(1500);
}

рджреЗрд╢-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрде рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ: рдПрдХ DE рдкреНрд░реЙрдХреНрд╕реА etsy.com/de/ рдХреЛ рд╣рд┐рдЯ рдХрд░рдиреЗ рдкрд░ 200 рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдФрд░ рд╕рд╣реА рдХреНрд╖реЗрддреНрд░реАрдп рд╕рддреНрд░ рдХреБрдХреАрдЬрд╝ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ DE рдкреНрд░реЙрдХреНрд╕реА рдХреЗ рд╕рд╛рде etsy.com/ 403 рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдФрд░ рд╕рддреНрд░ рдмрдВрдж рд░рд╣рддрд╛ рд╣реИред US (64 рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ), DE (60 рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ) рдФрд░ GB (61 рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ) рдореЗрдВ рд╕рддреНрдпрд╛рдкрд┐рдд тАФ рддреАрдиреЛрдВ рдкрд╣рд▓реЗ рдкреНрд░рдпрд╛рд╕ рдореЗрдВ рдЦреЛрдЬ рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ рдЬрдм рд╡рд╛рд░реНрдордЕрдк рдкреНрд░реЙрдХреНрд╕реА рджреЗрд╢ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рд╕реНрдХреНрд░реИрдкрд░ рдкрд╣рд▓реЗ collectSearchResults рдХреЙрд▓ рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕рддреНрд░ рдореЗрдВ рдПрдХ рдмрд╛рд░ warmUpSession рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред


рдЪрд░рдг 2 тАФ рдЪрд╛рд░ рдЦреЛрдЬ рдореЛрдб

рд╕реНрдХреНрд░реИрдкрд░ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд╛рд░ рд╕реНрд╡рддрдВрддреНрд░ рддрд░реАрдХреЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдпреЗ рд╕рднреА рдПрдХ рд╣реА CONFIG рдмреНрд▓реЙрдХ рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВред рдЙрд╕ рдПрдХ рдХреЛ рдЪреБрдиреЗрдВ рдЬреЛ рдЕрдкрд╕реНрдЯреНрд░реАрдо рдкреНрд░рд╢реНрди рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдФрд░ startUrls, shopUrl, categoryUrl, рдпрд╛ searchQuery рдореЗрдВ рд╕реЗ рдПрдХ рд╣реА рд╕реЗрдЯ рдХрд░реЗрдВред рдпрджрд┐ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рд╕реЗрдЯ рд╣реИрдВ, рддреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╣реИ shopUrl тЖТ categoryUrl тЖТ searchQuery тЖТ startUrlsред

рдЙрддреНрдкрд╛рдж URL рдореЛрдб (рдкреНрд░рддреНрдпрдХреНрд╖-URL) тАФ рдЬреНрдЮрд╛рдд рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ, рд░рд╛рдд рдХреА рджреЛрдмрд╛рд░рд╛-рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ, рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рд╕реНрдиреИрдкрд╢реЙрдЯ:

ts Copy
const CONFIG: ScraperInput = {
  startUrls: [
    "https://www.etsy.com/listing/547491922/leather-walletwalletman-leather",
    "https://www.etsy.com/listing/1022283131/personalized-slim-wallet-fathers-day",
  ],
  maxProducts: 2,
  // ...рдЕрдиреНрдп рдбрд┐рдлрд╝реЙрд▓реНрдЯ
};

рд╢реНрд░реЗрдгреА URL рдореЛрдб тАФ рд╕рдВрд░рдЪрд┐рдд рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд╕рд╛рде рд╕рдВрдкреВрд░реНрдг рд╢реНрд░реЗрдгреА рдХреНрд░реЙрд▓:

ts Copy
const CONFIG: ScraperInput = {
  categoryUrl: "https://www.etsy.com/c/bags-and-purses/wallets-and-money-clips/wallets",
  filters: {
    onSale: true,
    freeShipping: true,
    minPrice: 20,
    maxPrice: 60,
    orderBy: "most_relevant",
  },
  maxPagesPerQuery: 2,
  maxProducts: 20,
};

рдХреАрд╡рд░реНрдб рдЦреЛрдЬ рдореЛрдб тАФ рд╡рд┐рд╢реЗрд╖ рдЦреЛрдЬ, рдкреНрд░рд╡реГрддреНрддрд┐ рдЕрдиреБрд╕рдВрдзрд╛рди, рдорд╛рддреНрд░рд╛ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкреБрд▓:

ts Copy
const CONFIG: ScraperInput = {
  searchQuery: "leather wallet",
  expandStrategy: "keywords",                   // "none" | "keywords" | "prices"
  expandKeywords: ["mens", "womens", "vintage"], // рдЬрдм рд╡рд┐рд╕реНрддрд╛рд░ = рдХреАрд╡рд░реНрдб рд╣реЛ рддрдм рдмреЗрд╕ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ
  maxProducts: 20,
};

рджреБрдХрд╛рди URL рдореЛрдб тАФ рдмреЗрдВрдЪрдорд╛рд░реНрдХрд┐рдВрдЧ / рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рджреБрдХрд╛рди рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ:

ts Copy
const CONFIG: ScraperInput = {
  shopUrl: "https://www.etsy.com/shop/TexasValleyLeather",
  maxPagesPerQuery: 5,
  maxProducts: 40,
};

рдЪрд╛рд░реЛрдВ рдореЛрдб рдЪрд░рдг 4тАУ6 рдореЗрдВ рдПрдХ рд╣реА рдкреНрд░рддрд┐-рд╕реВрдЪреА рд╕рдВрдкрддреНрддрд┐ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдЦрд┐рд▓рд╛рддреЗ рд╣реИрдВ рдФрд░ рдЪрд░рдг 8 рдореЗрдВ рдПрдХ рд╕рдорд╛рди 30-рдХреНрд╖реЗрддреНрд░ рд╕реНрдХреАрдорд╛ рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВред

рд╕рдВрд░рдЪрд┐рдд рдлрд╝рд┐рд▓реНрдЯрд░

рдЖрда рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝рд┐рд▓реНрдЯрд░ рдХреБрдВрдЬреА searchQuery рдпрд╛ categoryUrl рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрд┐рдд рд╣реЛрддреА рд╣реИрдВред рдЬрд┐рдирдореЗрдВ рд╕реЗ рднреА рд▓рд╛рдЧреВ рд╣реЛрдВ, рдЙрдиреНрд╣реЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВ, рдмрд╛рдХреА рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ:

рдХреБрдВрдЬреА рдорд╛рди рдкреНрд░рднрд╛рд╡
onSale true рдХреЗрд╡рд▓ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдмрд┐рдХреНрд░реА рдкрд░ рд╕реВрдЪреАрдмрджреНрдз рд╡рд╕реНрддреБрдПрдВ
freeShipping true рдХреЗрд╡рд▓ рдкреНрд░реЙрдХреНрд╕реА рджреЗрд╢ рдореЗрдВ рдореБрдлреНрдд рд╢рд┐рдкрд┐рдВрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╕реВрдЪреА
customizable true рдХреЗрд╡рд▓ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдЕрдиреБрдХреВрд▓рди рдпреЛрдЧреНрдп рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ
shipsTo ISO рдХреЛрдб рдЬреИрд╕реЗ "US" рдЙрд╕ рджреЗрд╢ рдореЗрдВ рднреЗрдЬрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ
minPrice / maxPrice рд╕рдВрдЦреНрдпрд╛ рдореВрд▓реНрдп рд╕реАрдорд╛ (Etsy рдХрд╛ рд╕реНрд╡рджреЗрд╢реА рдлрд╝рд┐рд▓реНрдЯрд░)
condition "new" | "vintage" Etsy рд╕реНрдерд┐рддрд┐ рдлрд╝рд┐рд▓реНрдЯрд░
orderBy "рд╕рдмрд╕реЗ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ" | "рддрд╛рд░реАрдЦ_desc" | "рдХреАрдордд_рдХрдо" | "рдХреАрдордд_рдЬреНрдпрд╛рджрд╛" | "рдЙрдЪреНрдЪрддрдо рд╕рдореАрдХреНрд╖рд╛рдПрдБ" рдкрд░рд┐рдгрд╛рдо рдХреНрд░рдордмрджреНрдзрддрд╛

рдкреЗрдЬрд┐рдиреЗрд╢рди рдирд┐рдпрдВрддреНрд░рдг

maxPagesPerQuery: N рд╕реЗрдЯ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдбрд┐рд╕реНрдХрд╡рд░реА URL рдкрд░ ?page=1..N рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдЗрд╕рдХреЗ рдмрд┐рдирд╛, рд╕реНрдХреНрд░реИрдкрд░ рд▓рдХреНрд╖рд┐рдд рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкреГрд╖реНрда рдХреЛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЬрдм maxProducts рдЕрджреНрд╡рд┐рддреАрдп рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдПрдХрддреНрд░ рд╣реЛ рдЬрд╛рддреА рд╣реИрдВ, рддреЛ рд░реБрдХ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм рдЖрдк рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рдирд┐рдд рдмрдбрд╝реЗ рд╕реНрдХреНрд░реИрдк рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдЬреИрд╕реЗ "рдЗрд╕ рд╢реНрд░реЗрдгреА рдХреЗ рдкрд╣рд▓реЗ 5 рдкреГрд╖реНрдареЛрдВ рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░реЗрдВ, рднрд▓реЗ рд╣реА рд╡рд╣ 200+ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рд╣реЛ"), рддрдм рд╕реНрдкрд╖реНрдЯ рдкреЗрдЬрд┐рдиреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред


рдЪрд░рдг 3 тАФ рдорд▓реНрдЯреА-рдХреНрд╡реЗрд░реА рд╡рд┐рд╕реНрддрд╛рд░ (Etsy "рдкрд░рд┐рдгрд╛рдо рд╕реАрдорд╛" рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╣рд▓)

Etsy рдХрд╛ рдЙрдкрднреЛрдХреНрддрд╛ UI рдкреЗрдЬрд┐рдиреЗрд╢рди рдХреЛ рдЕрдзрд┐рдХрд╛рдВрд╢ niches рдЦрддреНрдо рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣реА рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкреНрд░рддрд┐-IP рджрд░ рд╕реАрдорд╛ рдЙрдЪреНрдЪ рдЕрдиреБрд░реЛрдз рдорд╛рддреНрд░рд╛ рдХреЗ рддрд╣рдд рдЬрд▓реНрджреА рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИ тАФ рдХреЛрдИ рднреА рдПрдХрд▓ рдХреАрд╡рд░реНрдб рдХреЗрд╡рд▓ рдПрдХ рд░реИрдВрдХрд┐рдВрдЧ рд╕реНрд▓рд╛рдЗрд╕ рдХреЛ рд╣реА рд╕рддрд╣ рдкрд░ рд▓рд╛рддрд╛ рд╣реИред рдПрдХ рдирд┐рдЪ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдзрд╛рд░ рдХреНрд╡реЗрд░реА рдХреЛ рдПрдХ рдзреБрд░реА (рдХреАрд╡рд░реНрдб рдпрд╛ рдХреАрдордд рдмрдХреЗрдЯ) рдХреЗ рд╕рд╛рде рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ listingId рджреНрд╡рд╛рд░рд╛ рдбреЗрдбреБрдк рдХрд░реЗрдВред

"рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯ" рдХреЗ рд▓рд┐рдП, рдПрдХ рдХреАрд╡рд░реНрдб рд╡рд┐рд╕реНрддрд╛рд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд┐рдЦрддрд╛ рд╣реИ:

ts Copy
function searchUrlForQuery(query: string, page = 1, priceMin?: number, priceMax?: number) {
  const params = new URLSearchParams({ q: query });
  if (page > 1) params.set("page", String(page));
  if (priceMin !== undefined) params.set("min", String(priceMin));
  if (priceMax !== undefined) params.set("max", String(priceMax));
  return `https://www.etsy.com/search?${params.toString()}`;
}

type ExpandStrategy = "keywords" | "prices" | "none";

function multiQueryExpand(
  base: string,
  cfg: { expandStrategy: ExpandStrategy; expandKeywords: string[]; priceBuckets: [number, number][] }
) {
  if (cfg.expandStrategy === "keywords") {
    const queries = [base, ...cfg.expandKeywords.map((k) => `${k} ${base}`)];
    return queries.map((q) => searchUrlForQuery(q));
  }
  if (cfg.expandStrategy === "prices") {
    return cfg.priceBuckets.map(([min, max]) => searchUrlForQuery(base, 1, min, max));
  }
  return [searchUrlForQuery(base)];
}

["рдкреБрд░реБрд╖реЛрдВ", "рдорд╣рд┐рд▓рд╛рдУрдВ", "рд╡рд┐рдВрдЯреЗрдЬ"] рдХреЗ рдЦрд┐рд▓рд╛рдл "рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯ" рдЪрд╛рд░ рдЦреЛрдЬреЗрдВ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рдЙрдиреНрд╣реЗрдВ рдЪрд▓рд╛рдПрдБ, рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ URLs рдПрдХрддреНрд░ рдХрд░реЗрдВ, URL рдореЗрдВ рдирд┐рд╣рд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ ID рджреНрд╡рд╛рд░рд╛ рдбреЗрдбреБрдк рдХрд░реЗрдВ (/listing/1051861316/...)ред maxProducts рдХреЛ рдкрд░реНрдпрд╛рдкреНрдд рдКрдБрдЪрд╛ рд╕реЗрдЯ рдХрд░реЗрдВ (рдЕрдзрд┐рдХрд╛рдВрд╢рддрдГ рдХреБрдЫ рджрд░реНрдЬрди рд╕реЗ рд▓реЗрдХрд░ рдХреБрдЫ рд╕реМ рддрдХ) рддрд╛рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рднреА рд╡реЗрд░рд┐рдПрдВрдЯреНрд╕ рдореЗрдВ рдлреИрд▓ рд╕рдХреЗ тАФ рдпрджрд┐ рд▓рдХреНрд╖реНрдп рдЫреЛрдЯрд╛ рд╣реИ рддреЛ рд╕реНрдХреНрд░реИрдкрд░ рдкрд╣рд▓реЗ рдХреНрд╡реЗрд░реА рдХреЗ рдмрд╛рдж рдЬреЛ рдкрд░рд┐рдгрд╛рдо рд╣реИ, рдЙрд╕рдХреЗ рдмрд╛рдж рд╕реАрдзреЗ рд░реБрдХ рдЬрд╛рдПрдЧрд╛, рдбреЗрдбреБрдк рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рдо рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЫреЛрдбрд╝ рджреЗрдЧрд╛ред

рдХреАрдордд рдмрдХреЗрдЯрд┐рдВрдЧ рдЙрд╕реА рддрд░рд╣ рдХрд╛рдо рдХрд░рддреА рд╣реИ тАФ рд╡рд┐рднрд┐рдиреНрди рдмрдХреЗрдЯ рд╡рд┐рднрд┐рдиреНрди рд░реИрдВрдХрд┐рдВрдЧ рд╕реНрд▓рд╛рдЗрд╕ рдХреЛ рд╕рддрд╣ рдкрд░ рд▓рд╛рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ Etsy рдХрд╛ "рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдореЗрд▓" рдХреАрдордд рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдкрд░рд┐рдгрд╛рдо рд╕реЗрдЯ рдореЗрдВ рдЕрдиреНрдп рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ рд╣реИред


рдЪрд░рдг 4 тАФ рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрдЬ рд╕реЗ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ URLs рдПрдХрддреНрд░ рдХрд░реЗрдВ

рдкрд░рд┐рдгрд╛рдо рд╕рд╛рдЗрдбрдмрд╛рд░ рдХреЛ рдЗрддрдирд╛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВ рдХрд┐ рд▓реЗрдЬрд╝реА-рд▓реЛрдбреЗрдб рдХрд╛рд░реНрдбреНрд╕ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдлрд┐рд░ рд╣рд░ a[href*="/listing/"] рд▓рд┐рдВрдХ рдХреЛ div.listing-link рдХреЗ рдЕрдВрджрд░ рдкрдХрдбрд╝реЗрдВ (рдЬрдм Etsy A/B-рдЯреЗрд╕реНрдЯ рдХреНрд▓рд╛рд╕ рдирд╛рдо рдХрд░рддрд╛ рд╣реИ рддреЛ [data-listing-id] рдХреЗ рд░реВрдк рдореЗрдВ рдмреИрдХрдЕрдк рдкрд░)ред

ts Copy
type SearchHit = { listingId: string | null; url: string; title: string | null; rank: number };
const delay = (ms: number) => new Promise((r) => setTimeout(r, ms));

async function collectSearchResults(page: Page, searchUrl: string, target: number, pageTimeoutMs = 60000): Promise<SearchHit[]> {
  await page.goto(searchUrl, { waitUntil: "domcontentloaded", timeout: 60000 });
  await dismissEtsyConsent(page);
  await delay(2000);

  // Lazy-loaded рдХрд╛рд░реНрдбреНрд╕ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдмрд╛рд░ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВред рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд╕
  // рд╡рд░реНрддрдорд╛рди DOM рдХрд╛ рдПрдХ cheerio рд╕реНрдиреИрдкрд╢реЙрдЯ рд▓реЗрддрд╛ рд╣реИ тАФ рдЬреИрд╕реЗ рд╣реА рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ,
  // рд╣рдо рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВред
  for (let i = 0; i < 6; i++) {
    const $peek = await parseWithCheerio(page);
    if ($peek("[data-listing-id], div.listing-link").length >= target) break;
    await page.evaluate(() => window.scrollBy(0, 1200));
    await delay(900);
  }

  // Cheeriod рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рд░ DOM рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВ тАФ рдХреЛрдИ `page.evaluate` рд░рд╛рдЙрдВрдб-рдЯреНрд░рд┐рдк рдирд╣реАрдВ,
  // рдХреЛрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧрд┐рдлрд╛рдЗрдб рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреАрдЬрд╝ рдирд╣реАрдВ, рдмрд╕ рд╕реАрдзреЗ рд╕реЗрд▓реЗрдХреНрдЯрд░ рдЯреНрд░реИрд╡рд░реНрд╕рд▓ред
  const $ = await parseWithCheerio(page);
  let cards = $("div.listing-link");
  if (cards.length === 0) cards = $("[data-listing-id]");
  const hits: SearchHit[] = [];
  const seen = new Set<string>();
  cards.each((_, card) => {
    const link = $(card).find('a[href*="/listing/"]').first();
    if (!link.length) return;
    const href = link.attr("href") || "";
    const absolute = href.startsWith("http") ? href : `https://www.etsy.com${href.startsWith("/") ? "" : "/"}${href}`;
    const url = absolute.split("?")[0];
    if (!url || seen.has(url)) return;
    seen.add(url);
    const titleEl = $(card).find("h3").first();
    const title = titleEl.length ? titleEl.text().trim() : (link.attr("title") || null);
    const idMatch = url.match(/\/listing\/(\d+)/);
    const listingId = idMatch ? idMatch[1] : null;
    hits.push({ listingId, url, title, rank: hits.length + 1 });
  });
  return hits;
}

рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ page.evaluate рдкрд░ рд░рд╣рддреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рд╕рдХреНрд░рд┐рдп DOM рдХреНрд░рд┐рдпрд╛ рд╣реИ (Etsy рдХреА рд▓реЗрдЬрд╝реА-рд▓реЛрдб рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдирд╛), рд▓реЗрдХрд┐рди рд╣рд░ рдЯреБрдХрдбрд╝рд╛ рдкрд╛рд░реНрд╕рд┐рдВрдЧ Cheeriod рдкрд░ page.content() рд╕реНрдиреИрдкрд╢реЙрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЪрд▓рддрд╛ рд╣реИред рдпрд╣реА рдкреИрдЯрд░реНрди рд╕рднреА рдЫрд╣ рд╕рдореГрджреНрдзрд┐ рдирд┐рд╖реНрдХрд░реНрд╖рдгрдХрд░реНрддрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдЪрд░рдг 6-7 рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
dismissEtsyConsent рдХреЙрд▓ рдЙрди рдЧреИрд░-рдЕрдореЗрд░рд┐рдХреА рд╕рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬрд╣рд╛рдБ Etsy рдПрдХ "рдХреБрдХреАрдЬрд╝ рдФрд░ рдЧреЛрдкрдиреАрдпрддрд╛" рдЧреЗрдЯ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдкреГрд╖реНрда рдкреНрд░рд╕реНрддреБрдд рд╣реЛред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХрд┐рд╕реА рднреА рдмрдЯрди рдХреА рддрд▓рд╛рд╢ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕ рдкрд░ "рд╕рднреА рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ" / "рд╕рднреА рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ" / рдХреБрдЫ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд╕рдордХрдХреНрд╖ рд▓рд┐рдЦрд╛ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЙрд╕реЗ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИред

рдЪрд░рдг 5 тАФ рдкреНрд░рддреНрдпреЗрдХ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░реЗрдВ

Google Maps рдХреЗ рд╡рд┐рдкрд░реАрдд, Etsy рдХреЗ /listing/<id>/ рдпреВрдЖрд░рдПрд▓ рд╕реАрдзреЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдкрд░ рднреА рдкреВрд░рд╛ рдкреИрдирд▓ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рдХреНрд▓рд┐рдХ-рдереНрд░реВ рдЪрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ тАФ рд╕реНрдХреНрд░реИрдкрд░ рд╕реАрдзреЗ page.goto(listingUrl) рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, DataDome рдЗрд╕ рдЙрдкрдкрд░реНрдг рдкрд░ рддрд╛рдЬрд╝рд╛ рдкреНрд░реЙрдХреНрд╕реА рдЖрдИрдкреА рдХреЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕реЗ рдкрд░ HTTP 403 рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЪреЗрд╣рд░рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ, 403/429 рдкрд░ рддреЗрдЬреА рд╕реЗ рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдлреЗрдВрдХрддрд╛ рд╣реИ рдпрджрд┐ h1 рдХрднреА рдирд╣реАрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ тАФ рдЗрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд┐рддрд┐ рдмрд╛рд╣рд░реА рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рд▓реВрдк рдХреЛ рдирдпрд╛ рдЖрд╡рд╛рд╕реАрдп рдЖрдИрдкреА рдкрд░ рддрд╛рдЬрд╛ рд╕рддреНрд░ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЯреНрд░рд┐рдЧрд░ рдХрд░рддреА рд╣реИред

ts Copy
const resp = await page.goto(hit.url, { waitUntil: "domcontentloaded", timeout: 60000 });
const status = resp?.status() ?? 0;
if (status === 403 || status === 429) {
  throw new Error(`blocked: HTTP ${status} on ${hit.url}`);
}
await dismissEtsyConsent(page);
try {
  await page.waitForSelector("h1", { timeout: 15000 });
} catch {
  // 15 рд╕реЗрдХрдВрдб рдХреЗ рдмрд╛рдж рдХреЛрдИ h1 рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ DataDome рдЪреБрдиреМрддреА рдпрд╛ рдкреБрдирдГрдирд┐рд░реНрджреЗрд╢рди рдкреГрд╖реНрда рдХрд╛ рдЕрд░реНрде рд╣реИред
  // рдлреЗрдВрдХреЗрдВ рддрд╛рдХрд┐ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рд▓реВрдк рдПрдХ рдирдП рд╕рддреНрд░ рдХреЛ рдЦреЛрд▓реЗ (= рдирдпрд╛ рдЖрд╡рд╛рд╕реАрдп рдЖрдИрдкреА)ред
  throw new Error(`no h1 on ${hit.url} тАФ likely bot-challenge page`);
}
await delay(1500);

рдлрд┐рд░ рдкреВрд░реЗ рдкреГрд╖реНрда рдХреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдХреЗ рд▓реЗрдЬреА рд▓реЛрдбрд┐рдВрдЧ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░реЗрдВред рд╡рд┐рд╡рд░рдг, рд╕рд╛рдордЧреНрд░реА рдФрд░ рд╢рд┐рдкрд┐рдВрдЧ рдЕрдиреБрднрд╛рдЧ рд╕рднреА рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдкрд░ рд▓реЛрдб рд╣реЛрддреЗ рд╣реИрдВред

рдЪрд░рдг 6 тАФ рдЕрд╡рд▓реЛрдХрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдирд┐рдХрд╛рд▓реЗрдВ

Extractor рдХреА рдПрдХ рджреЛ-рдЪрд░рдгреАрдп рд╕рдВрд░рдЪрдирд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдиреАрдЪреЗ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ extractor рдореЗрдВ рджреЛрд╣рд░рд╛рдИ рдЬрд╛рддреА рд╣реИ: рдмреНрд░рд╛рдЙрдЬрд░-рд╕рд╛рдЗрдб (рд╕реНрдХреНрд░реЙрд▓ + waitForFunction рддрд╛рдХрд┐ рд▓реЗрдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╣рд╛рдЗрдбреНрд░реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ) тЖТ рдиреЛрдб-рд╕рд╛рдЗрдб (рдПрдХ рдмрд╛рд░ page.content() рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреГрд╖реНрда рдХрд╛ HTML рдЦреАрдВрдЪреЗрдВ рдФрд░ рдлрд┐рд░ cheerio рдХреЗ рд╕рд╛рде рдкрд╛рд░реНрд╕ рдХрд░реЗрдВ)ред рдпрд╣ рд╡рд┐рднрд╛рдЬрди рд╣рдореЗрдВ рдЬрдм рдЬрд░реВрд░рдд рд╣реЛ рддреЛ рд▓рд╛рдЗрд╡-DOM рд╡реНрдпрд╡рд╣рд╛рд░ рдФрд░ рдЬрдм рди рд╣реЛ рддреЛ рдЯрд╛рдЗрдк рдХреА рдЧрдИ, рдкрд░реАрдХреНрд╖рдг рдпреЛрдЧреНрдп рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

ts Copy
async function extractOverview(page: Page): Promise<Partial<EtsyProduct>> {
  // рдмреНрд░рд╛рдЙрдЬрд░-рд╕рд╛рдЗрдб: рднрд╛рдЧреЛрдВ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╡рд┐рд╡рд░рдг / рд╕рд╛рдордЧреНрд░реА / рд╢рд┐рдкрд┐рдВрдЧ
  // рд▓реЗрдЬреА-рд▓реЛрдб рд╣реЛ рдЬрд╛рдП, рдлрд┐рд░ рдЦрд░реАрдж-рдмреЙрдХреНрд╕ рдХреЗ "рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ" 
  // рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░ рдХреЗ рдЖрдЧреЗ рд╣рд╛рдЗрдбреНрд░реЗрдЯ рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВред
  await page.evaluate(`(function() {
    var step = 500, total = document.body.scrollHeight, current = 0;
    var iv = setInterval(function() {
      current += step;
      window.scrollTo(0, current);
      if (current >= total) clearInterval(iv);
    }, 200);
  })()`);
  await delay(3500);

  try {
    await page.waitForFunction(
      // рддрдм рддрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВ рдЬрдм рддрдХ рдХреЛрдИ рднреА рд╕рдВрднрд╛рд╡рд┐рдд рдореВрд▓реНрдпwrapper рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдорд╛рди рди рд╣реЛ
      // (рди рдХрд┐ "рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ" рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░ рдЬрд┐рд╕реЗ Etsy рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рд▓рд┐рдП рджрд┐рдЦрд╛рддрд╛ рд╣реИ)ред 
      // рдЦрд░реАрдж-рдмреЙрдХреНрд╕ wrapper рдкрд░ рдХреЗрд╡рд▓ рдХреИрд╕рд┐рдВрдЧ рд╕реЗ рд╡реНрдпрд╛рдкрдХ рдЬрд╛рд▓ рдбрд╛рд▓рдиреЗ рд╕реЗ рдзреАрдореЗ 
      // рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ рд╣рд┐рдЯ рджрд░ рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрддрд╛ рд╣реИ рдЬрд╣рд╛рдБ рдореВрд▓реНрдп рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ .currency-value рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддрд╛ рд╣реИред
      `(function(){
        var sels = [
          "[data-selector='price-only'] span.currency-value",
          "div[data-buy-box-region='price'] span.currency-value",
          "p[class*='price'] span.currency-value",
          "span.currency-value"
        ];
        for (var i = 0; i < sels.length; i++) {
          var el = document.querySelector(sels[i]);
          if (el && /^\\s*\\$?\\d/.test((el.textContent || '').trim())) return true;
        }
        return false;
      })()`,
      { timeout: 15000 },
    );
  } catch { /* extractor рдЗрд╕рдХреЗ рдиреАрдЪреЗ рдЕрдкрдирд╛ рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ */ }

  // рдиреЛрдб-рд╕рд╛рдЗрдб: рдПрдХ рдмрд╛рд░ рдкреНрд░рд╕реНрддреБрдд HTML рдЦреАрдВрдЪреЗрдВ рдФрд░ cheerio рдХреЗ рд╕рд╛рде рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред
  const $ = await parseWithCheerio(page);

  const title = $("h1").first().text().trim() || null;

  // рдореВрд▓реНрдп тАФ рддреАрди-рдЪрд░рдгреАрдп рд╢реНрд░реГрдВрдЦрд▓рд╛ред (1) рд╕реНрдкрд╖реНрдЯ `[data-selector='price-only']`
  // рдЙрдкрдкрд░реНрдг рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗрдВ рдЬрд┐рд╕реЗ Etsy рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддрд╛ рд╣реИ; (2) рдкрд╣рд▓реЗ
  // `span.currency-value` рдкрд░ рд╡рд╛рдкрд╕ рдЧрд┐рд░реЗрдВ рдЬрд┐рд╕рдХрд╛ рдкреВрд░реНрд╡рдЬ рд╕реНрдЯреНрд░рд╛рдЗрдХрдереНрд░реВ / рдореВрд▓-рдореВрд▓реНрдп
  // wrappers рдирд╣реАрдВ рд╣реИ; (3) рдЕрдВрддрд┐рдо рдЙрдкрд╛рдп рд╢рд░реАрд░-рдЯреЗрдХреНрд╕реНрдЯ regexред
  const isOriginalPriceWrapper = (el: any) =>
    $(el).closest("[class*='strikethrough'], [class*='original'], s, .wt-text-strikethrough").length > 0;
  let price: string | null = null;
  const priceOnly = $("[data-selector='price-only'] span.currency-value").first();
  if (priceOnly.length && /^\d/.test(priceOnly.text().trim())) {
    price = priceOnly.text().trim();
  }
  if (!price) {
    $("span.currency-value").each((_, el) => {
      if (price) return false;
      if (isOriginalPriceWrapper(el)) return;
      const t = $(el).text().trim();
      if (t && /^\d/.test(t)) price = t;
    });
  }
  if (!price) {
    const bodyPriceMatch = $("body").text().match(/(?:рдЕрдм\s+)?рдХреАрдордд:?\s*([$┬гтВм]?[\d.,]+)/i);
    if (bodyPriceMatch) price = bodyPriceMatch[1].trim();
  }

  // рд░реЗрдЯрд┐рдВрдЧ тАФ рдХреЛрдИ рднреА aria-label рдЬреЛ "рд╕рд┐рддрд╛рд░рд╛", "рд░реЗрдЯрд┐рдВрдЧ", рдпрд╛ "рдХрд┐рддрдирд╛" рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддрд╛ рд╣реИред
  let rating: number | null = null;
  $("[aria-label*='star' i], [aria-label*='rating' i]").each((_, n) => {
    if (rating !== null) return false;
    const a = $(n).attr("aria-label") || "";
    const rm = a.match(/(\d+(?:\.\d+)?)\s*(?:рдмрд╛рд╣рд░|рд╕рд┐рддрд╛рд░рд╛|рд░реЗрдЯрд┐рдВрдЧ)/i);
    if (rm) rating = parseFloat(rm[1]);
  });

Here is the translation of the provided English text into Hindi:

Copy
// рд╕реНрдерд┐рддрд┐ рдмреИрдЬ тАФ рдкреГрд╖реНрда рд╢рд░реАрд░ рдХреЛ regex рдХрд░реЗрдВред
const bodyText = $("body").text();
const isBestseller = /Bestseller/i.test(bodyText);
const isFreeShipping = /free shipping/i.test(bodyText);
const isStarSeller = /Star Seller/i.test(bodyText);
const inStock = !/out of stock|sold out/i.test(bodyText);

// рджреБрдХрд╛рди рд╕рд╛рдЗрдбрдХрд╛рд░ред
const shopLink = $("a[href*='/shop/']").first();
const shopName = shopLink.text().trim() || null;
const shopUrl = (shopLink.attr("href") || "").split("?")[0] || null;

return { title, _price_raw: price, rating, isBestseller, isFreeShipping, isStarSeller, inStock,
  shop: { name: shopName, url: shopUrl } } as Partial<EtsyProduct>;
}

_price_raw рдЙрдкрд╕рд░реНрдЧ рдПрдХ рдкрд╛рд░рдВрдкрд░рд┐рдХ рд╣реИ: рдиреАрдЪреЗ рдХреА enrichProduct рдЗрд╕реЗ extractNumber рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреЗрдЬрддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдЕрдВрддрд┐рдо JSON рдЬрд╛рд░реА рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрдЪреНрдЪреЗ-рд╕реНрдЯреНрд░рд┐рдВрдЧ рдлрд╝реАрд▓реНрдб рдХреЛ рдорд┐рдЯрд╛ рджреЗрддрд╛ рд╣реИред рд╕реНрдирд┐рдкреЗрдЯ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╣реИ тАФ рдкреВрд░реНрдг extractOverview рдХреЛ index.ts рдореЗрдВ currency, discountPercent, reviewsCount, favoritesCount, description, materials, itemDetails, shippingFrom, processingTime, tags, listedDate рдФрд░ рдмрд╛рдХреА рджреБрдХрд╛рди рдлрд╝реАрд▓реНрдб рдХреЛ рднреА рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдкреВрд░реЗ рдкреГрд╖реНрда рдореЗрдВ рд╡рд╣реА cheerio-рдкреНрд░рдердо рдкреИрдЯрд░реНрди рд╣реИ, рдХреЗрд╡рд▓ рдЕрдзрд┐рдХ рдЪрдпрдирдХрд░реНрддрд╛ рд╣реИрдВред

рдПрдХ рдЫреЛрдЯрд╛ рдореБрджреНрд░рд╛-рдЯреЙрд▓рд░реЗрдВрдЯ extractNumber рд╕рд╣рд╛рдпрдХ "$24.99", "24,99 тВм", рдпрд╛ "1,234" рдХреЛ рдПрдХ рд╕рд╛рдл рдирдВрдмрд░ рдореЗрдВ рдмрджрд▓рддрд╛ рд╣реИ тАФ Etsy рдореВрд▓реНрдп рд╕реНрдерд╛рдиреАрдп рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдкреНрд░реЛрдХреНрд╕реА рджреЗрд╢ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдк рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рдХрд┐ рдЖрдкрдХреЗ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдХреНрд╖реЗрддреНрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рд╣реЛрдВред

рдЪрд░рдг 7 тАФ рд╕рдореАрдХреНрд╖рд╛рдПрдВ, рдЫрд╡рд┐рдпрд╛рдВ, рджреБрдХрд╛рди рд╕рд╛рдЗрдбрдХрд╛рд░, рд╡рд┐рд╡рд┐рдзрддрд╛рдПрдВ, рдмреНрд░реЗрдбрдХреНрд░рдВрдм, рд╕рдВрдмрдВрдзрд┐рдд рдЦреЛрдЬреЗрдВ

рд╕рдореАрдХреНрд╖рд╛рдПрдВред Etsy рдХреЗ рд╕рдореАрдХреНрд╖рд╛ рдХрд╛рд░реНрдб div[data-review-region] рдореЗрдВ рд░рд╣рддреЗ рд╣реИрдВ (DOM рд╕рдВрд╢реЛрдзрдиреЛрдВ рдХреЗ рд▓рд┐рдП div[class*='review-card'] рдФрд░ div[class*='review-item'] рдмреИрдХрдЕрдк рдХреЗ рд░реВрдк рдореЗрдВ)ред рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВ, рдлрд┐рд░ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдб рдХреЛ рд▓реЗрдЦрдХ / рд░реЗрдЯрд┐рдВрдЧ / рдкрд╛рда / рддрд┐рдерд┐ plus рддреАрди рд╕рдм-рд░реЗрдЯрд┐рдВрдЧ рдореЗрдВ рдореИрдк рдХрд░реЗрдВред

ts Copy
async function extractReviews(page: Page, max: number): Promise<EtsyReview[]> {
  // рдмреНрд░рд╛рдЙрдЬрд╝рд░-рдкрдХреНрд╖: рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╕реБрд╕реНрдд рд╕рдореАрдХреНрд╖рд╛ рдХрд╛рд░реНрдб рд░реЗрдВрдбрд░ рд╣реЛрдВред
  for (let i = 0; i < 8; i++) {
    const found = await page.evaluate(
      `!!document.querySelector('[data-reviews-section], div#reviews, div[class*="reviews"]')`,
    );
    if (found) break;
    await page.evaluate(() => window.scrollBy(0, 700));
    await delay(700);
  }
  await delay(1500);

  // рдиреЛрдб-рдкрдХреНрд╖: рдЕрдм рд╣рд╛рдЗрдбреНрд░реЗрдЯреЗрдб рдкреГрд╖реНрда рдХреЛ cheerio рдХреЗ рд╕рд╛рде рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред
  const $ = await parseWithCheerio(page);
  const out: EtsyReview[] = [];

  $(
    "div[data-review-region], div[class*='review-card'], div[class*='review-item'], li[class*='review']",
  ).each((_, card) => {
    if (out.length >= max) return false;
    const $card = $(card);
    const cardText = $card.text();
    // рдХрдИ рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреЛ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рд╡рд╛рд▓реЗ рд╕рдордЧреНрд░ рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЛ рдЫреЛрдбрд╝реЗрдВред
    if (cardText.length > 6000) return;

    const author = $card.find("a[href*='/people/'], strong, p[class*='name']").first().text().trim() || null;

    // рд░реЗрдЯрд┐рдВрдЧ: рдкрд╣рд▓реЗ `data-rating` рд╡рд┐рд╢реЗрд╖рддрд╛, рдлрд┐рд░ aria-labelред
    let rating: number | null = null;
    const $starEl = $card.find("[aria-label*='star' i], [data-rating]").first();
    if ($starEl.length) {
      const dr = $starEl.attr("data-rating");
      if (dr) rating = parseFloat(dr);
      else {
        const rm = ($starEl.attr("aria-label") || "").match(/(\d+(?:\.\d+)?)/);
        if (rm) rating = parseFloat(rm[1]);
      }
    }

    // рдкрд╛рда: рд╕рдорд░реНрдкрд┐рдд рдЪрдпрдирдХрд░реНрддрд╛, рдлрд┐рд░ рдХрд╛рд░реНрдб рдореЗрдВ рд╕рдмрд╕реЗ рд▓рдВрдмрд╛ рдкреИрд░рд╛рдЧреНрд░рд╛рдлред
    let text: string | null =
      $card.find("p[class*='review-text'], div[class*='review-text'], div[id*='review-content']")
        .first().text().trim() || null;
    if (!text) {
      let longest = "";
      $card.find("p").each((_, p) => {
        const pt = $(p).text().trim();
        if (pt.length > longest.length && pt.length > 20) longest = pt;
      });
      text = longest || null;
    }

    // рддрд╛рд░реАрдЦ: рдкрд╣рд▓реЗ рд╕рдорд░реНрдкрд┐рдд рддрддреНрд╡, рдлрд┐рд░ рдПрдХ рдорд╣реАрдиреЗ рдХрд╛ рдирд╛рдо рдпрд╛ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ regexред
    let date: string | null =
      $card.find("span[class*='date'], time, p[class*='date']").first().text().trim() || null;
    if (!date) {
      const dm = cardText.match(/(\w{3,9}\s+\d{1,2},?\s+\d{4}|\d{1,2}\/\d{1,2}\/\d{2,4})/);
      if (dm) date = dm[1];
    }

    // рд╕рдм-рд░реЗрдЯрд┐рдВрдЧ - рдХрд╛рд░реНрдб рдХреЗ рдЕрдВрджрд░ рд▓реЗрдмрд▓ рдХрд┐рдП рдЧрдП рдкрдВрдХреНрддрд┐рдпрд╛рдБред рд▓реЗрдмрд▓ рдореЗрд▓ рдЦрд╛рдПрдВ, рдмрдЧрд▓ рдореЗрдВ рд╕рдВрдЦреНрдпрд╛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред
    const subRating = (label: string): number | null => {
      let val: number | null = null;
      $card.find("span, div, li").each((_, row) => {
        if (val !== null) return false;
        const t = $(row).text().toLowerCase();
        if (t.includes(label) && t.length < 60) {
          const sm = t.match(/(\d+(?:\.\d+)?)/);
          if (sm) val = parseFloat(sm[1]);
        }
      });
      return val;
    };

    // рд╕рдореАрдХреНрд╖рдХ-рджреНрд╡рд╛рд░рд╛ рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рддрд╕реНрд╡реАрд░реЗрдВ тАФ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд╕рдорд╛рди `il_fullxfull` рдЙрдиреНрдирдпрдиред
    const photos: string[] = [];
    const photoSeen = new Set<string>();
    $card.find("img[src*='etsystatic'], img[data-src*='etsystatic']").each((_, img) => {
      if (photos.length >= 6) return false;
      let psrc = $(img).attr("src") || $(img).attr("data-src") || "";
      if (!psrc) return;

This translation keeps the technical context intact while converting the content into Hindi.

hi Copy
psrc = psrc.replace(/il_\d+xN/, "il_fullxfull").replace(/_\d+x\d+\./, "_1024x1024.");
if (!photoSeen.has(psrc)) { photoSeen.add(psrc); photos.push(psrc); }
});

out.push({
  author, rating, text, date,
  itemQuality: subRating("рдЖрдЗрдЯрдо рдЧреБрдгрд╡рддреНрддрд╛"),
  shipping: subRating("рд╢рд┐рдкрд┐рдВрдЧ"),
  customerService: subRating("рдЧреНрд░рд╛рд╣рдХ рд╕реЗрд╡рд╛"),
  photos,
});
});

return out;
}

рдЪрд╛рд░ рдХрд╛рд░реНрдб-рдЪрдпрдирдХрд░реНрддрд╛ рд╡рд┐рдХрд▓реНрдк Etsy рдХреЗ рдЪрд▓ рд░рд╣реЗ A/B рд╕рдВрд╢реЛрдзрдиреЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░рддреЗ рд╣реИрдВ - [data-review-region] рд╡рд░реНрддрдорд╛рди рд╣реЙрдЯ рдЪрдпрдирдХрд░реНрддрд╛ рд╣реИ; [class*='review-card'], [class*='review-item'] рдФрд░ li[class*='review'] рдкреБрд░рд╛рдиреЗ рдФрд░ рдирдП рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ рдЬреЛ рдЦрд╛рддреЗ рдФрд░ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЕрднреА рднреА рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВред рд╢реАрд░реНрд╖ рдкрд░ рдХрд╛рд░реНрдбрдЯреЗрдХреНрд╕реНрдЯ рд▓рдВрдмрд╛рдИ рдЧрд╛рд░реНрдб рдЙрд╕ рдЕрдиреБрдкреНрд░рд╛рд╕рдХ рддрддреНрд╡реЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдЧрд▓рддреА рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╕рд╛рде рдХрдИ рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред

рдЪрд┐рддреНрд░ред Etsy рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдердВрдмрдиреЗрд▓ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЙрдиреНрд╣реЗрдВ рдкреВрд░реНрдг-рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП URL рдореЗрдВ рдЖрдХрд╛рд░ рдкреНрд░рддреНрдпрдп рдХреЛ рдмрджрд▓реЗрдВ: il_75x75 тЖТ il_fullxfull, рдпрд╛ _300x300.jpg тЖТ _1024x1024.jpgред рд╡рд╣реА рдЪрд┐рддреНрд░, рд▓реЗрдХрд┐рди рдЙрдЪреНрдЪ рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди, рдХреЛрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдЕрдиреБрд░реЛрдз рдирд╣реАрдВред

ts Copy
async function extractImages(page: Page, max: number): Promise<string[]> {
  const $ = await parseWithCheerio(page);
  const urls: string[] = [];
  const seen = new Set<string>();
  $("img[src*='etsystatic'], img[data-src*='etsystatic']").each((_, img) => {
    if (urls.length >= max) return false;
    let src = $(img).attr("src") || $(img).attr("data-src") || "";
    if (!src) return;
    // рдердВрдмрдиреЗрд▓ рдЖрдХрд╛рд░ рдкреНрд░рддреНрдпрдп рдХреЛ рд╕рдВрднрд╡ рд╣реЛ рддреЛ рдкреВрд░реНрдг рд░рд┐рдЬрд╝реЙрд▓реНрдпреВрд╢рди рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░реЗрдВред
    src = src.replace(/il_\d+xN/, "il_fullxfull").replace(/_\d+x\d+\./, "_1024x1024.");
    if (!seen.has(src)) { seen.add(src); urls.push(src); }
  });
  return urls;
}

img[data-src*='etsystatic'] рдкреИрдЯрд░реНрди рдЪрдпрдирдХрд░реНрддрд╛ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ - Etsy рд▓рд╛рдЬрд╝реА-рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ рдЧреИрд▓рд░реА рдердВрдмрдиреЗрд▓ рдХреЛ data-src рдХреЗ рдкреАрдЫреЗ рдФрд░ рдпрд╣ src рдХреЛ рддрдм рддрдХ рднрд░рддрд╛ рдирд╣реАрдВ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╡реЗ рджреГрд╢реНрдп рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдирд╣реАрдВ рдЖрддреЗред

рднрд┐рдиреНрдирддрд╛рдПрдВ, рдмреНрд░реЗрдбрдХреНрд░рдВрдм, рд╕рдВрдмрдВрдзрд┐рдд рдЦреЛрдЬреЗрдВред рддреАрди рдЕрддрд┐рд░рд┐рдХреНрдд рдПрдХреНрд╕рдЯреНрд░реИрдХреНрдЯрд░реНрд╕ рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдФрд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рдмрд╛рдж рдЪрд▓рддреЗ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ try/catch рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдПрдХ рдЫреВрдЯреЗ рд╣реБрдП рдЪрдпрдирдХрд░реНрддрд╛ рдПрдХ рдЦрд╛рд▓реА рд╕реВрдЪреА рдореЗрдВ рдШрдЯрд┐рдд рд╣реЛ рдЬрд╛рдП рдмрдЬрд╛рдп рдХрд┐ рдкрдВрдХреНрддрд┐ рдХреЛ рддреЛрдбрд╝рдиреЗ рдХреЗ:

  • extractVariations(page) тАФ рдЖрдХрд╛рд░ / рд░рдВрдЧ / рд╡реИрдпрдХреНрддрд┐рдХрд░рдг рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рдЦреАрдВрдЪрддрд╛ рд╣реИ рдЬреЛ рд╡рд┐рдХреНрд░реЗрддрд╛ рдЙрдЬрд╛рдЧрд░ рдХрд░рддрд╛ рд╣реИ, рдХреЗ рд░реВрдк рдореЗрдВ {name, options[]}[] рд╕реВрдЪреАред [data-selector*='variation'] рдЙрдк-рдЯреНрд░реА рдореЗрдВ <select> рддрддреНрд╡реЛрдВ рд╕реЗ рднрд░рддрд╛ рд╣реИред
  • extractBreadcrumbs(page) тАФ рд╢реНрд░реЗрдгреА рдорд╛рд░реНрдЧ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИ (рдЬреИрд╕реЗ ["Homepage", "Bags & Purses", "Wallets & Money Clips", "Wallets"]) рдПрдВрдХрд░ рдЯреИрдЧ рд╕реЗ рдЬреЛ ref=breadcrumb_listing рд▓рд╛рддреЗ рд╣реИрдВ рдЙрдирдХреЗ href рдореЗрдВред Etsy рдЗрдирдХреА рд▓рд┐рдкрдЯрдиреЗ рдореЗрдВ <nav aria-label="breadcrumb"> рдирд╣реАрдВ рд▓рдЧрд╛рддреА - рдпреЗ рд╕рд╛рдорд╛рдиреНрдп рд▓рд┐рдВрдХ рд╣реИрдВ рдЬрд┐рдирдореЗрдВ рдПрдХ рд╕рдВрджрд░реНрдн рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛрддрд╛ рд╣реИред
  • extractRelatedSearches(page) тАФ "рд╕рдВрдмрдВрдзрд┐рдд рдЦреЛрдЬреЛрдВ рдХрд╛ рдЕрдиреНрд╡реЗрд╖рдг рдХрд░реЗрдВ" рд▓рд┐рдВрдХ рдЬреЛ Etsy рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкреГрд╖реНрдареЛрдВ рдХреЗ рдиреАрдЪреЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреА рд╣реИред рдПрдХреНрд╕рдЯреНрд░реИрдХреНрдЯрд░ рдкреГрд╖реНрда рдХреЗ рдкреИрд░ рдкрд░ рд╡рд╛рдкрд╕ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд▓реЗрдЬрд╝реА-рд▓реЛрдбреЗрдб рдЯреИрдЧ рдЕрдиреБрднрд╛рдЧ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ, рд▓рд┐рдВрдХ рдкрд╛рда рдХреЛ рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗред Etsy A/B-рдЯреЗрд╕реНрдЯ рдЫрд╡рд┐-рдХреЗрд╡рд▓ рдЪрд┐рдкреНрд╕ (рдХреЛрдИ рдкрд╛рда рдирд╣реАрдВ) рдмрдирд╛рдо рдкрд╛рда-рд▓реЗрдмрд▓ рд╡рд╛рд▓реЗ рдЪрд┐рдкреНрд╕, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рдлрд╝реАрд▓реНрдб рдХреЛ рд▓рдЧрднрдЧ рдЖрдзреЗ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ рднрд░рдиреЗ рдХрд╛ рдЕрдиреБрдорд╛рди рдХрд░реЗрдВред

рд▓рд┐рд╕реНрдЯ рдХреА рдЧрдИ рддрд┐рдерд┐ рдФрд░ рджреБрдХрд╛рди рд╕реНрддрд░ рдХреБрд▓ extractOverview рдХреЗ рднреАрддрд░ рдЦреАрдВрдЪреА рдЬрд╛рддреА рд╣реИрдВ рдмреБрдирд┐рдпрд╛рджреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рдеред listedDate "Mon DD, YYYY" рдХреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ Etsy рдЖрдЗрдЯрдо рд╡рд┐рд╡рд░рдг рдХреЗ рдкрд╛рд╕ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ - рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗ рд╣рд╛рд▓рд┐рдпрд╛ рдкреБрдирдГ рд╕реВрдЪреАрдмрджреНрдз/рд╕реНрд╡рдд: рдирд╡реАрдиреАрдХрд░рдг рдХреА рддрд┐рдерд┐ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, рди рдХрд┐ рдореВрд▓ рдирд┐рд░реНрдорд╛рдг рддрд┐рдерд┐ред shop.reviewsCountShop рдХреЗрд╡рд▓ рддрдм рднрд░рд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм Etsy рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рджреБрдХрд╛рди рд╕реНрддрд░ рдкрд░ рднреЗрджрд┐рдд рдХрд░рддрд╛ рд╣реИ (рдХрдИ рд╕реВрдЪреА рд▓реЗрдЖрдЙрдЯ рдЗрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ - рд╡рд╣рд╛рдБ рдИрдорд╛рдирджрд╛рд░ рдЙрддреНрддрд░ рд╣реИ 'null')ред

рд╕рдореАрдХреНрд╖рдХ-рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рддрд╕реНрд╡реАрд░реЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореАрдХреНрд╖рд╛ рдХрд╛рд░реНрдб рдХреЗ рднреАрддрд░ рд╣реЛрддреА рд╣реИрдВред extractReviews рдЕрдм рдкреНрд░рддрд┐ рд╕рдореАрдХреНрд╖рд╛ 6 рддрд╕реНрд╡реАрд░реЗрдВ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЙрд╕реА il_fullxfull рдЕрдкрдЧреНрд░реЗрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рдХреЛрдб рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдпрд╛ рд╕рдореАрдХреНрд╖рд╛ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдЫрд╡рд┐ рдХреЙрд░реНрдкрд╕ рдорд┐рд▓рддрд╛ рд╣реИред

рдЪрд░рдг 8 - рдкреНрд░рддрд┐ рдЙрддреНрдкрд╛рдж рд╕рдореГрджреНрдзрд┐ рдФрд░ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ

рдПрдХ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рдирд╛ рд╕реАрдзрд╛ рд╣реИред рдПрдХ рд╕реМ рдПрдХ рдХреЗ рдмрд╛рдж рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рддрдм рд╣реИ рдЬрдм рдЕрд╕реНрдерд╛рдпреА рд╡рд┐рдлрд▓рддрд╛рдПрдВ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд▓рдЧрддреА рд╣реИрдВ - Etsy рдХрднреА-рдХрднреА рдПрдХ рдкреБрд░рд╛рдирд╛ рдХреИрд╢ рджреЗрддрд╛ рд╣реИ, h1 рдкреВрд░реА рдирд╣реАрдВ рд╣реЛрддреА, рдПрдХрд▓ рдкреНрд░реЙрдХреНрд╕реА рдЕрдиреБрд░реЛрдз рд╕рдордп рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпреЗ рд╕рднреА рдХреЛ рдкреИрдорд╛рдиреЗ рдкрд░ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рддреАрди рд╕реБрд░рдХреНрд╖рд╛рддреНрдордХ рдкрд░рддреЗрдВ рд╣реИрдВ:

рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрдкрд╛рдж рдХреЗ рд▓рд┐рдП рддрд╛рдЬрд╝рд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ред рдЬрдм рдЦреЛрдЬ рд╣рд┐рдЯ рдПрдХрддреНрд░рд┐рдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореГрджреНрдзрд┐ рдХреЗ рд▓рд┐рдП рдирдП Scrapeless рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╕рддреНрд░ рдХреЛ рдЦреЛрд▓реЗрдВред рд░рд╛рдЬреНрдп рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рдмреАрдЪ рд▓реАрдХ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕рддреНрд░-рд╕реНрддрд░реАрдп рддреНрд░реБрдЯрд┐ рджреМрдбрд╝ рдХреЗ рдмрд╛рдХреА рдХреЛ рдЦрд░рд╛рдм рдирд╣реАрдВ рдХрд░рддреА рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рддрд╛рдЬрд╝рд╛ рд╕рддреНрд░ рдПрдХ рдирдпрд╛ рдирд┐рд╡рд╛рд╕ IP рдШреБрдорд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЬрдм DataDome рдПрдХ IP рдкрд░ 403 рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ рдЕрдЧрд▓реА рдХреЛрд╢рд┐рд╢ рдПрдХ рдЕрд▓рдЧ рдкрд░ рдмреИрдарддреА рд╣реИред

cfg.maxRetries рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдкреНрд░рдпрд╛рд╕реЛрдВ рддрдХ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ 10) рдмрдврд╝рддреА рд╣реБрдИ рдмреИрдХрдСрдл рдХреЗ рд╕рд╛рдеред рдПрдХ рд╕реНрд╡рдЪреНрдЫ рд░рди рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдЙрддреНрдкрд╛рдж рдкрд╣рд▓реЗ рдкреНрд░рдпрд╛рд╕ рдкрд░ рд╕рдлрд▓ рд╣реЛрддреЗ рд╣реИрдВ; рдПрдХ рдЦрд░рд╛рдм-IP рд░рди рдкрд░, рд╕рддреНрд░ рдХреЛ рдПрдХ рд╕рд╛рдл рдирд┐рд╡рд╛рд╕реА IP рдкрд░ рдмреИрдардиреЗ рдореЗрдВ 3тАУ6 рдкреНрд░рдпрд╛рд╕ рд▓рдЧ рд╕рдХрддреЗ рд╣реИрдВред рдЙрдЪреНрдЪ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдмрдЬрдЯ 50% рд╣рд┐рдЯ рджрд░ рдФрд░ 100% рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ рд╣реИред

Copy
**рд╢реНрд░реЗрдгреАрдмрджреНрдз рддреНрд░реБрдЯрд┐ рд╡рд░реНрдЧреАрдХрд░рдгред** `categorizeError(err)` рд╣рд░ рдХрдЪреНрдЪреА рд╡рд┐рдлрд▓рддрд╛ (HTTP 403/404/429, `ERR_SSL_*`, `ERR_TUNNEL_*`, h1-рдорд┐рд╕рд┐рдВрдЧ, рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЯрд╛рдЗрдордЖрдЙрдЯ, WSS рд╣реИрдВрдбрд╢реЗрдХ) рдХреЛ рдЖрда `ScrapeErrorKind` рдорд╛рдиреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ `retryable: boolean` рдлреНрд▓реИрдЧ рд╣реЛрддрд╛ рд╣реИред рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдпреЛрдЧреНрдп рддреНрд░реБрдЯрд┐рдпрд╛рдБ рдмреИрдХрдСрдл рд▓реВрдк рдХреЛ рдлреАрдб рдХрд░рддреА рд╣реИрдВ; рдЧреИрд░-рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдпреЛрдЧреНрдп рддреНрд░реБрдЯрд┐рдпрд╛рдБ (рдЬреИрд╕реЗ рдХрд┐ рд╕реНрдЯреЗрд▓ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкрд░ HTTP 404) рддреБрд░рдВрдд рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИрдВред рдЬрдм рд╕рднреА рдкреНрд░рдпрд╛рд╕ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдЙрддреНрдкрд╛рдж `error: { kind, message, attempts }` рдХреЗ рд╕рд╛рде рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рдХреЛрдб рдпрд╣ рдЬрд╛рди рд╕рдХреЗ рдХрд┐ рдПрдХ рдкрдВрдХреНрддрд┐ рдЕрдЪрд╛рдирдХ рдЦрд╛рд▓реА рдХреНрдпреЛрдВ рдЖрдИред

```ts
// рдореБрдЦреНрдп рд▓реВрдк рдХреЗ рдЕрдВрджрд░, рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрдЬ рд╣рд┐рдЯ h рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ (i рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрдХреНрд░рдорд┐рдд):
const MAX_ATTEMPTS = cfg.maxRetries;   // рдбрд┐рдлрд╝реЙрд▓реНрдЯ 10
let p: EtsyProduct | null = null;
let lastError: ScrapeErrorInfo | null = null;
let attemptsUsed = 0;
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
  attemptsUsed = attempt;
  let eb;
  try {
    eb = await openBrowser(`etsy-enrich-${i}-${attempt}-${Date.now()}`, cfg);
  } catch (e: any) {
    lastError = categorizeError(new Error(`openBrowser рд╡рд┐рдлрд▓: ${e?.message ?? e}`));
    log(`    рдкреНрд░рдпрд╛рд╕ ${attempt}/${MAX_ATTEMPTS} тАФ ${lastError.kind}: ${lastError.message.slice(0, 120)}`);
    if (!lastError.retryable) break;
    if (attempt < MAX_ATTEMPTS) await delay(Math.max(cfg.retryInitialBackoffMs, 3000));
    continue;
  }
  try {
    p = await enrichProduct(eb, h, cfg);
    if (p.title) { lastError = null; break; }
    lastError = categorizeError(new Error(`no h1 on ${h.url} тАФ title was null`));
  } catch (e: any) {
    lastError = categorizeError(e);
    log(`    рдкреНрд░рдпрд╛рд╕ ${attempt}/${MAX_ATTEMPTS} тАФ ${lastError.kind}: ${lastError.message.slice(0, 120)}`);
    if (!lastError.retryable) break;   // рдЧреИрд░-рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдпреЛрдЧреНрдп: 404, рдЖрджрд┐ред рдЬрд▓реНрджреА рд╡рд┐рдлрд▓ред
  } finally {
    await eb.close().catch(() => {});
  }
  if (attempt < MAX_ATTEMPTS) {
    // рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдмрдврд╝рддреА рдмреИрдХрдСрдлред рдбрд┐рдлрд╝реЙрд▓реНрдЯ (3000, 1500, 500) рдХрд╛ рдкрд░рд┐рдгрд╛рдо
    // 5s, 8s, 12s, 17s, 23s, 30s, 38s, 47s, 57s рдХреЗ рдмреАрдЪ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХрд╛ рд╣реЛрддрд╛ рд╣реИред
    const backoff = cfg.retryInitialBackoffMs
      + attempt * (cfg.retryBackoffLinearMs + attempt * cfg.retryBackoffQuadraticMs);
    await delay(backoff);
  }
}
if (!p || !p.title) {
  p = emptyProduct(h.url);
  p.rank = h.rank;
  if (lastError) {
    p.error = { kind: lastError.kind, message: lastError.message.slice(0, 200), attempts: attemptsUsed };
  }
}
products.push(p);
// рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░рд╛рд▓ (рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп) тАФ рд▓рдЧрд╛рддрд╛рд░ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреЛ рддреЛрдбрд╝рддрд╛ рд╣реИ
// рдиреЗрд╡рд┐рдЧреЗрд╢рдиреЛрдВ рдХреЛ рддрд╛рдХрд┐ рд╕рддреНрд░ рдХрд╛ рдкреИрдЯрд░реНрди DataDome рдХреЗ рд▓рд┐рдП рдмреЛрдЯ рдХреЗ рдЖрдХрд╛рд░ рдХрд╛ рди рджрд┐рдЦреЗред
if (i < hits.length - 1) await delay(cfg.interProductDelayMs);

рдХреБрдЫ рд╡рд┐рд╡рд░рдг рдЬреЛ рдкреИрдорд╛рдиреЗ рдкрд░ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИрдВ: рд╕рддреНрд░ рдХрд╛ рдирд╛рдо рдЙрддреНрдкрд╛рдж рдЕрдиреБрдХреНрд░рдорд╛рдВрдХ i рдФрд░ Date.now() рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рддрд╛рдЬрд╝рд╛ рд╕рддреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рдЯрдХрд░рд╛рд╡ рди рд╣реЛ; openBrowser рдХреЛ рдЕрдкрдиреА рдЦреБрдж рдХреА try/catch рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЧрдпрд╛ рд╣реИ рддрд╛рдХрд┐ рд╡рд┐рдлрд▓ WSS рд╣реИрдВрдбрд╢реЗрдХ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдХреЛ рди рдЫреЛрдбрд╝ рджреЗ; eb.close() рдХреЛ .catch(() => {}) рдХреЗ рд╕рд╛рде рд╕рдорд╛рд╣рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рддреНрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдорд░ рдЪреБрдХрд╛ рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЖрдк рдЗрд╕реЗ рдмрдВрдж рдХрд░ рд░рд╣реЗ рд╣реЛрддреЗ рд╣реИрдВ; рдмрдврд╝рддреА рдмреИрдХрдСрдл рдЗрддрдиреА рдзреАрд░реЗ-рдзреАрд░реЗ рдмрдврд╝рддреА рд╣реИ рдХрд┐ рдЖрд╕рд╛рди рдЙрддреНрдкрд╛рдж рддреЗрдЬреА рд╕реЗ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдХрдард┐рди рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ DataDome рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрдИ рд╕реЗрдХрдВрдб рдХрд╛ рд╡рд┐рдВрдбреЛ рдорд┐рд▓рддрд╛ рд╣реИ; рдФрд░ рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░рд╛рд▓ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рд░реВрдк рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдмреНрд▓реЙрдХреЛрдВ рдХреЗ рдЕрд╡рд╕рд░ рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред

рдЖрда рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░

рд╣рд░ рд╡рд┐рдлрд▓ рдЙрддреНрдкрд╛рдж рдПрдХ error: { kind, message, attempts } рдСрдмреНрдЬреЗрдХреНрдЯ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИред kind рдлрд╝реАрд▓реНрдб рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рдХреЛрдб рдХреЛ рдпрд╣ рдмрддрд╛рддреА рд╣реИ рдХрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреИрд╕реЗ рджреЗрдиреА рд╣реИ рдмрд┐рдирд╛ рдореБрдХреНрдд-рдлреЙрд░реНрдо рд╕рдВрджреЗрд╢ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд┐рдП:

kind рдЯреНрд░рд┐рдЧрд░ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдпреЛрдЧреНрдп
blocked HTTP 403 рдпрд╛ 429 тАФ DataDome рдпрд╛ рджрд░ рд╕реАрдорд╛ тЬЕ рд╣рд╛рдБ
not-found HTTP 404 тАФ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рд╣рдЯрд╛ рджреА рдЧрдИ рдпрд╛ рдХрднреА рдЕрд╕реНрддрд┐рддреНрд╡ рдореЗрдВ рдирд╣реАрдВ рдереА тЭМ рдирд╣реАрдВ (рдЬрд▓реНрджреА рд╡рд┐рдлрд▓)
tls ERR_SSL_* / ERR_CERT_* тАФ рдЕрд╕реНрдерд╛рдпреА рдкреНрд░реЙрдХреНрд╕реА рд╣рд┐рдХрдк тЬЕ рд╣рд╛рдБ
network ERR_TUNNEL / ERR_CONNECTION_* / ERR_ABORTED тЬЕ рд╣рд╛рдБ
no-h1 рдкреГрд╖реНрда рд▓реЛрдб рд╣реБрдЖ рд▓реЗрдХрд┐рди <h1> рдХрднреА рдирд╣реАрдВ рдЖрдпрд╛ тАФ рд╕реЙрдлреНрдЯ рдЪреИрд▓реЗрдВрдЬ рдкреГрд╖реНрда тЬЕ рд╣рд╛рдБ
timeout рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЯрд╛рдЗрдордЖрдЙрдЯ pageTimeoutMs рд╕реЗ рдЕрдзрд┐рдХ тЬЕ рд╣рд╛рдБ
open-browser Scrapeless рдХреЗ рд▓рд┐рдП WSS рд╣реИрдВрдбрд╢реЗрдХ рд╡рд┐рдлрд▓ тЬЕ рд╣рд╛рдБ
unknown рдХреБрдЫ рдФрд░ тЬЕ рд╣рд╛рдБ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ)

рд╣рд░ рдЯрди рдХреЗ рдХреЛрдг рдХреЛ рдЯреНрдпреВрди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

рд╕рднреА рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдФрд░ рддрд╛рд▓рд┐рдХрд╛ рдорд╛рди ScraperInput рдкрд░ рд░рд╣рддреЗ рд╣реИрдВ тАФ рдХреБрдЫ рднреА рд╣рд╛рд░реНрдб-рдХреЛрдбреЗрдб рдирд╣реАрдВ рд╣реИред рдЬрдм рдЖрдкрдХреЛ рд╕рдЦреНрдд рдпреЛрдЬрдирд╛ рдкрд░ рдкреВрд░реНрд╡рд╛рдиреБрдореЗрдп рдереНрд░реВрдкреБрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рдпрд╛ рдХрдард┐рди рд▓рдХреНрд╖реНрдп рдкрд░ рдЕрдзрд┐рдХ рдЖрдХреНрд░рд╛рдордХ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ, рддрдм рдЗрдиреНрд╣реЗрдВ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░реЗрдВ:

CONFIG рдлрд╝реАрд▓реНрдб рдбрд┐рдлрд╝реЙрд▓реНрдЯ рднреВрдорд┐рдХрд╛
maxRetries 10 рдЙрддреНрдкрд╛рдж рдкрд░ рдХреБрд▓ рдкреНрд░рдпрд╛рд╕ рдЬреЛ рд╣рд╛рд░ рдорд╛рдирдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣реЛрддреЗ рд╣реИрдВ
retryInitialBackoffMs 3000 рдмрдврд╝рддреЗ-рдмреИрдХрдСрдл рдлрд╝рд╛рд░реНрдореВрд▓реЗ рдХрд╛ рдЖрдзрд╛рд░
retryBackoffLinearMs 1500 рд░реИрдЦрд┐рдХ рд╢рдмреНрдж
retryBackoffQuadraticMs 500 рджреНрд╡рд┐рдШрд╛рддреАрдп рд╢рдмреНрдж
interProductDelayMs 3000 рд▓рдЧрд╛рддрд╛рд░ рдЙрддреНрдкрд╛рдж рд╕рдВрд╡рд░реНрджреНрдзрдиреЛрдВ рдХреЗ рдмреАрдЪ рд░реБрдХрд╛ рд╣реБрдЖ
pageTimeoutMs 60000 page.goto рдЯрд╛рдЗрдордЖрдЙрдЯ
h1TimeoutMs 15000 waitForSelector("h1") рдЯрд╛рдЗрдордЖрдЙрдЯ
postLoadDelayMs 1500 h1 рджрд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдирд┐рд╖реНрдХрд░реНрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рдХреА рджреЗрд░реА

рдЖрдкрдХреЛ рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ

рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрдкрд╛рдж рдХреЗ рд▓рд┐рдП рдПрдХ рдлреНрд▓реИрдЯ JSON рдСрдмреНрдЬреЗрдХреНрдЯред рдЬрд╛рдирдмреВрдЭрдХрд░ рдЪреМрдбрд╝рд╛, рддрд╛рдХрд┐ рд╡рд╣реА рд╕реНрдХреНрд░реИрдкрд░ рдмрд┐рдирд╛ рджреВрд╕рд░реЗ рдЪрд░рдг рдХреЗ рд╣рд░ рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓реЗ рдХреЛ рдлреАрдб рдХрд░ рд╕рдХреЗред

"рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯ" рдЦреЛрдЬ рдкрд░ рдЗрд╕ рд╕рдЯреАрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╕реЗ рдЪрд▓рдиреЗ рд╡рд╛рд▓рд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд╣рд▓рд╛ рдкрд░рд┐рдгрд╛рдо:

json Copy
{
  "listingId": "547491922",
json Copy
{
  "title": "рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯтАврд╡реЙрд▓реЗрдЯтАврдкреБрд░реБрд╖ рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯтАврдорд┐рдирд┐рдорд▓рд┐рд╕реНрдЯ рд╡реЙрд▓реЗрдЯтАврд╡реНрдпрдХреНрддрд┐рдЧрдд рд╡реЙрд▓реЗрдЯтАврд▓реЗрджрд░ рдПрдирд┐рд╡рд░реНрд╕рд░реАтАврд╕реНрд▓рд┐рдо рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯтАврдкреБрд░реБрд╖ рд╡реЙрд▓реЗрдЯ",
  "url": "https://www.etsy.com/listing/547491922/leather-walletwalletman-leather",
  "rank": 1,
  "price": 5.52,
  "originalPrice": 68.99,
  "currency": "$",
  "discountPercent": 92,
  "inStock": false,
  "rating": 4.9,
  "reviewsCount": 929,
  "favoritesCount": 850,
  "isBestseller": false,
  "isFreeShipping": false,
  "isStarSeller": true,
  "tags": ["рдмреНрд░рд╛рдЗрдбреНрд╕рдореЗрдб рдЙрдкрд╣рд╛рд░", "рдЧroomsmen рдЙрдкрд╣рд╛рд░", "рд╢рд╛рджреА рдХреЗ рдЙрдкрд╣рд╛рд░", "рдПрдВрдЧреЗрдЬрдореЗрдВрдЯ рдЙрдкрд╣рд╛рд░"],
  "materials": [],
  "shop": {
    "name": "TexasValleyLeather",
    "url": "https://www.etsy.com/shop/TexasValleyLeather",
    "location": null,
    "totalSales": null,
    "openedYear": null,
    "reviewsCountShop": null
  },
  "images": [
    "https://i.etsystatic.com/15980284/r/il/2456a5/3164786673/il_fullxfull.3164786673_roeh.jpg",
    "... 4 рдФрд░ рдпреВрдЖрд░рдПрд▓"
  ],
  "variations": [
    { "name": "рд╡реНрдпрдХреНрддрд┐рдЧрддрдХрд░рдг", "options": ["рд╣рд╛рдБ, рдЙрддреНрдХреАрд░реНрдгрди рдЬреЛрдбрд╝реЗрдВ", "рдирд╣реАрдВ, рдзрдиреНрдпрд╡рд╛рдж"] },
    { "name": "рд░рдВрдЧ рд╡рд┐рдХрд▓реНрдк", "options": ["рдЪреЗрд╕реНрдЯрдирдЯ", "рдХрд╛рд▓рд╛", "рдЯреИрди"] }
  ],
  "breadcrumbs": ["рдореБрдЦрдкреГрд╖реНрда", "рдмреИрдЧ рдФрд░ рдкрд░реНрд╕", "рд╡реЙрд▓реЗрдЯ рдФрд░ рдкреИрд╕реЗ рдХреНрд▓рд┐рдк", "рд╡реЙрд▓реЗрдЯ"],
  "relatedSearches": ["рдкреБрд░реБрд╖реЛрдВ рдХреЗ рд▓рд┐рдП рд▓реЗрджрд░ рд╡реЙрд▓реЗрдЯ", "рд╕реНрд▓реАрдХ рдкреБрд░реБрд╖ рд╡реЙрд▓реЗрдЯ", "рдХрд╕реНрдЯрдо рд╕реНрд▓рд┐рдо рд▓реЗрджрд░ рдмрд┐рдлреЛрд▓реНрдб рд╡реЙрд▓реЗрдЯ"],
  "listedDate": "15 рдЕрдкреНрд░реИрд▓, 2026",
  "priceBucket": null,
  "reviews": [
    {
      "author": "рд▓рд┐рдЬ",
      "rating": 0,
      "text": "рдЬреИрд╕рд╛ рд╡рд░реНрдгрд┐рдд рдерд╛ рдФрд░ рддреЗрдЬреА рд╕реЗ рднреЗрдЬрд╛ рдЧрдпрд╛ред рдзрдиреНрдпрд╡рд╛рдж!",
      "date": "12 рдЕрдкреНрд░реИрд▓, 2026",
      "itemQuality": null,
      "shipping": null,
      "customerService": null,
      "photos": []
    },
    "... 9 рдФрд░ рд╕рдореАрдХреНрд╖рд╛рдПрдБ"
  ],
  "error": null,
  "scrapedAt": "2026-04-16T17:09:48.919Z"
}

рдПрдХ рд╕рдорд╛рди рдХрдиреЗрдХреНрд╢рди рд╣реЗрд▓реНрдкрд░, рд░рд┐рдЯреНрд░рд╛рдИ рдЯреИрдХреНрд╕реЛрдиреЛрдореА рдФрд░ рд╕рддреНрд░-рдкреНрд░рддрд┐-рд▓рдХреНрд╖реНрдп рдкреИрдЯрд░реНрди рд╡реНрдпрд╛рдкрдХ Scrapeless рдХреИрдЯрд╛рд▓реЙрдЧ рдореЗрдВ рдлреИрд▓рд╛ рд╣реБрдЖ рд╣реИ: рдЗрд╕ рдЧрд╛рдЗрдб рдХреЛ Scrapeless MCP Server рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝реЗрдВ рддрд╛рдХрд┐ Etsy рдбреЗрдЯрд╛ рдХреЛ рд╕реАрдзреЗ рдПрдХ AI рдПрдЬреЗрдВрдЯ рдХреЗ рдЯреВрд▓ рд╕рд░рдлреЗрд╕ рдореЗрдВ рд╡рд╛рдпрд░реНрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдпрд╛ рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда AI рдПрдЬреЗрдВрдЯреЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╡реНрдпрд╛рдкрдХ рд╕реНрд╡рдЪрд╛рд▓рди рдХрд╛рд░реНрдпрдкреНрд░рд╡рд╛рд╣реЛрдВ рдореЗрдВ рдХреИрд╕реЗ рдкреНрд▓рдЧ рд╣реЛрддреА рд╣реИред

proxyCountry рдХреЛ рдЙрд╕ рдорд╛рд░реНрдХреЗрдЯрдкреНрд▓реЗрд╕ рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд┐рди рдХрд░реЗрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЖрдк рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рдг рдЪрд╛рд╣рддреЗ рд╣реИрдВ, sessionRecording: "true" рд░рдЦрдХрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдХреЛрдИ рднреА рд╢реВрдиреНрдп рдкрдВрдХреНрддрд┐ рдХреЛ рдПрдВрдб-рдЯреВ-рдПрдВрдб рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдЕрдиреБрдкрд╕реНрдерд┐рдд рдлрд╝реАрд▓реНрдб (materials, shop.location, reviews[].itemQuality) рдХреЛ рдЫреВрдЯреА рдбреЗрдЯрд╛ рдмрдЧ рдХреЗ рдмрдЬрд╛рдп рдирд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЯреНрд░реАрдЯ рдХрд░реЗрдВ, рдФрд░ рдмрдврд╝рддреА рдмреИрдХрдСрдл рдХреЛ рдЕрд╕реНрдерд╛рдпреА 403s рдХреЛ рдЕрд╡рд╢реЛрд╖рд┐рдд рдХрд░рдиреЗ рджреЗрдВред рдпрд╣реА рдкреВрд░рд╛ рдкреНрд▓реЗрдмреБрдХ рд╣реИред


рдХреНрдпрд╛ рдЖрдк рдЕрдкрдиреЗ AI-рд╕рдВрдЪрд╛рд▓рд┐рдд рдбреЗрдЯрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВ?

рд╣рдорд╛рд░реЗ рд╕рдореБрджрд╛рдп рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВ рддрд╛рдХрд┐ рдПрдХ рдореБрдлреНрдд рдпреЛрдЬрдирд╛ рдХрд╛ рджрд╛рд╡рд╛ рдХрд░реЗрдВ рдФрд░ рдЙрди рдбреЗрд╡рд▓рдкрд░реНрд╕ рд╕реЗ рдЬреБрдбрд╝реЗрдВ рдЬреЛ Etsy рдЗрдВрдЯреЗрд▓рд┐рдЬреЗрдВрд╕ рдкрд╛рдЗрдкрд▓рд╛рдЗрдиреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд░рд╣реЗ рд╣реИрдВ: Discord ┬╖ Telegram.

app.scrapeless.com рдкрд░ рд╕рд╛рдЗрди рдЕрдк рдХрд░реЗрдВ рдореБрдлреНрдд Scraping Browser рд░рдирдЯрд╛рдЗрдо рдХреЗ рд▓рд┐рдП тАФ рдореБрдлреНрдд рдЯреНрд░рд╛рдпрд▓ рдкрд░ 100 рдШрдВрдЯреЗ рддрдХ рдХрд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд░рди тАФ рдФрд░ рдКрдкрд░ рджрд┐рдП рдЧрдП рдкреИрдЯрд░реНрди рдХреЛ Etsy рд╢реНрд░реЗрдгрд┐рдпреЛрдВ, рджреБрдХрд╛рдиреЛрдВ рдФрд░ рдХреАрд╡рд░реНрдб рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░реЗрдВ рдЬрд┐рдирдХреА рдЖрдкрдХреЗ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рд╢реНрди

рдХреНрдпрд╛ Etsy рд╕реЗ рдбреЗрдЯрд╛ рд╕реНрдХреНрд░реИрдк рдХрд░рдирд╛ рдХрд╛рдиреВрдиреА рд╣реИ?

рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрд▓рдмреНрдз рдбреЗрдЯрд╛ рдХреЛ рдореВрд▓реНрдп рдирд┐рдЧрд░рд╛рдиреА рдФрд░ рд╢реЛрдз рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░реИрдк рдХрд░рдирд╛ рдЖрдорддреМрд░ рдкрд░ рдХрд╛рдиреВрдиреА рд╣реИ, рдмрд╢рд░реНрддреЗ рдЖрдк Etsy рдХреА рдЙрдкрдпреЛрдЧ рдХреА рд╢рд░реНрддреЛрдВ рдХрд╛ рд╕рдореНрдорд╛рди рдХрд░реЗрдВ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рдиреЗ рд╕реЗ рдмрдЪреЗрдВред Scrapeless рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдкрдХреЗ рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдЧрддрд┐рд╡рд┐рдзрд┐ рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдЧрддрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рд░реНрд╡рд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХрд╛ рд╕рдореНрдорд╛рди рдХрд░рдиреЗ рдХреА рд╕реБрдирд┐рд╢реНрдЪрд┐рддрддрд╛ рджреЗрддрд╛ рд╣реИред

Scrapeless Etsy рдХреЗ DataDome рд╕реБрд░рдХреНрд╖рд╛ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ?

рдорд╛рдирдХ рдкреНрд░реЙрдХреНрд╕рд┐рдпреЛрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, Scrapeless рдкреВрд░рд╛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯ рдФрд░ TLS рд╣реИрдВрдбрд╢реЗрдХ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдЖрдкрдХрд╛ рд╕реНрдХреНрд░реИрдкрд░ рдПрдХ рдЕрд╕рд▓реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдЕрдкреНрд░рднреЗрджреНрдп рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЖрдк DataDome рдХреА sofisticaded рдмреЙрдЯ рдбрд┐рдЯреЗрдХреНрд╢рди рдХреЛ рдмрд┐рдирд╛ рдореИрдиреБрдЕрд▓ рд╕реНрдЯреАрд▓реНрде рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдмрд╛рдпрдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдкреНрд░рд╢реНрди 1: рдХреНрдпрд╛ Etsy рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЙрдХреНрд╕реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

рдЬреНрдпрд╛рдВ. рдмрд┐рдирд╛ рдПрдХ рдЖрд╡рд╛рд╕реАрдп рдкреНрд░реЙрдХреНрд╕реА рдХреЗ, DataDome рдЬрд▓реНрджреА рд╣реА рдбреЗрдЯрд╛ рд╕реЗрдВрдЯрд░ рдЯреНрд░реИрдлрд╝рд┐рдХ рдХреЛ рдЭрдВрдбреА рджрд┐рдЦрд╛рддрд╛ рд╣реИ тАФ рдлрд┐рдВрдЧрд░рдкреНрд░рд┐рдВрдЯ рдФрд░ IP-рдкреНрд░рддрд┐рд╖реНрдард╛ рд╕рдВрдпреЛрдЬрди рдЖрдорддреМрд░ рдкрд░ рдЕрд╕реНрд╡реАрдХреГрддрд┐ рдмрд╛рд▓реНрдЯреА рдореЗрдВ рд╕реНрдХреЛрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╕реАрдзреЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдЕрдиреБрд░реЛрдз /listing/ рдкреГрд╖реНрдареЛрдВ рдкрд░ HTTP 403 рдХреЗ рд╕рд╛рде рдПрдХ JavaScript рдЪреБрдиреМрддреА рдкреГрд╖реНрда рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред Scrapeless Scraping Browser рдореЗрдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЖрд╡рд╛рд╕реАрдп рдкреНрд░реЙрдХреНрд╕реА рд╣реЛрддреЗ рд╣реИрдВ тАФ рд╣рд░ рд╕рддреНрд░ рдЪреБрдиреЗ рд╣реБрдП рджреЗрд╢ рдореЗрдВ рдПрдХ рдЕрд▓рдЧ рдЖрд╡рд╛рд╕реАрдп IP рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░реВрдЯ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд▓рдЧрд╛рддрд╛рд░ рддрд╛рдЬрд╝рд╛ рд╕рддреНрд░реЛрдВ рджреНрд╡рд╛рд░рд╛ рдЕрджреНрд╡рд┐рддреАрдп рдЖрдЙрдЯрдмрд╛рдЙрдВрдб IPs (api.ipify.org рдкреНрд░реЙрдм) рд▓реМрдЯрд╛рдиреЗ рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рджреНрд╡рд╛рд░рд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдкреНрд░рд╢реНрди 2: рдореИрдВ рдкрд┐рдЫрд▓реЗ рд░рди рдореЗрдВ рд╕реНрдХреНрд░реИрдкрд░ рдиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛, рдХреИрд╕реЗ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ?

рдЗрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рд╣рд░ рд╕рддреНрд░ WSS URL рдкрд░ sessionRecording: "true" рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП Scrapeless рд╣рд░ рдкреГрд╖реНрда рдХрд╛ рдПрдХ рдкреВрд░реНрдг рд╡реАрдбрд┐рдпреЛ-рд╢реИрд▓реА рдХрд╛ рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рд╕рд╣реЗрдЬрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЙрдб рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдиреЗ рдЫреБрдЖ тАФ рд╕реНрдХреНрд░реЙрд▓ рд╕реНрдерд┐рддрд┐, DOM рд╕реНрдерд┐рддрд┐ рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдЧрддрд┐рд╡рд┐рдзрд┐ред рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рдХреЛ app.scrapeless.com тЖТ Scraping Browser тЖТ Sessions рдкрд░ рдЦреЛрдЬреЗрдВ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдпрд╛рд╕ (рдЬреИрд╕реЗ etsy-enrich-3-2-1713198231047) рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░реИрдкрд░ рд▓реЙрдЧ рджреНрд╡рд╛рд░рд╛ sessionName рдорд╛рди рд╕реЗ рдореЗрд▓ рдХрд░реЗрдВред

рдпрджрд┐ рдбреИрд╢рдмреЛрд░реНрдб "рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рдЕрд╕реНрд╡реАрдХреГрдд тАФ рд╕рддреНрд░ рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП 'рд╡реЗрдм рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ' рд╕рдХреНрд╖рдо рдХрд░реЗрдВ" рджрд┐рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдЕрдкрдиреЗ Scrapeless рдЦрд╛рддрд╛ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдкреГрд╖реНрда рдкрд░ рд╡реЗрдм рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдЯреЙрдЧрд▓ рдЪрд╛рд▓реВ рдХрд░реЗрдВред рдпрд╣ рд╣рд░ рдпреЛрдЬрдирд╛ рдкрд░ рдореБрдлреНрдд рд╣реИ; рдпрд╣ рдХреЗрд╡рд▓ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдмрдВрдж рд╣реИред рдПрдХ рдмрд╛рд░ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдкрд░, рд╕рднреА рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕рддреНрд░ рдЕрдкрдиреЗ рдЖрдк рд░рд┐рдХреЙрд░реНрдб рд╣реЛрддреЗ рд╣реИрдВ тАФ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдмрдВрдж рд╣реЛрдиреЗ рдХреЗ рджреМрд░рд╛рди рдЬреЛ рдкрд┐рдЫрд▓реЗ рд╕рддреНрд░ рдЪрд▓рд╛рдП рдЧрдП, рдЙрдиреНрд╣реЗрдВ рд░реЗрдЯреНрд░реЛрд╕реНрдкреЗрдХреНрдЯрд┐рд╡рд▓реА рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ред

рдкреБрдирд░рд╛рд╡рд▓реЛрдХрди рдпрд╣ рдЬрд╛рдирдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рддреЗрдЬрд╝ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдПрдХ рдкрдВрдХреНрддрд┐ title: null рдХреЗ рд╕рд╛рде рдХреНрдпреЛрдВ рд▓реМрдЯрд╛рдИ рдЧрдИред рд╕рддреНрд░ рдЦреЛрд▓реЗрдВ, рдЙрд╕ рд╕рдордп рддрдХ рдЯрд╛рдЗрдорд▓рд╛рдЗрди рдХреЛ рд╕реНрдХреНрд░рдм рдХрд░реЗрдВ рдЬрдм page.goto рдЪрд╛рд▓реВ рд╣реБрдЖ, рдФрд░ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рд╕рд░реНрд╡рд░ рдиреЗ рдЕрд╕рд▓реА рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ, DataDome рдЪреБрдиреМрддреА рдпрд╛ рдПрдХ рд╕реНрдЯреЗрд▓-рдпреВрдЖрд░рдПрд▓ рд░рд┐рдбрд╛рдпрд░реЗрдХреНрдЯ рд▓реМрдЯрд╛рдпрд╛ред

рдкреНрд░рд╢реНрди 3: рдХрднреА-рдХрднреА рд╕рдореАрдХреНрд╖рд╛рдПрдБ рдкреГрд╖реНрда рдХреЗ рдмрдЬрд╛рдп рдЖрдВрддрд░рд┐рдХ рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреНрдпреЛрдВ рд▓реЛрдб рд╣реЛрддреА рд╣реИрдВ?

рдирдП Etsy рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдХреБрдЫ рд╕рдореАрдХреНрд╖рд╛ рдмреИрдЪреЛрдВ рдХреЛ рдкреГрд╖реНрда рдХреЗ рд░реЗрдВрдбрд░ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдЖрдВрддрд░рд┐рдХ POST рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред рд╕реНрдХреНрд░реИрдкрд░ рдЗрд╕реЗ рд╕рдореАрдХреНрд╖рд╛рдУрдВ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдХреЗ рдФрд░ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдХреЗ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ тАФ рдЬрдм рдкрд╛рд░реНрд╕рд░ рдЪрд▓ рд░рд╣рд╛ рд╣реЛрддрд╛ рд╣реИ, рдХрд╛рд░реНрдб DOM рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВред рд╣рдЬрд╛рд░реЛрдВ рд╕рдореАрдХреНрд╖рд╛рдУрдВ рд╡рд╛рд▓реЗ рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдк рдкрд╣рд▓реЗ ~30 (рдпрд╛ рдЬреЛ рднреА рдЖрдк maxReviews рдкрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ) рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЧреНрд░рд╛рдлрд╝рдХреНрдпреВрдПрд▓ рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЛ рд╕реАрдзреЗ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рдиреЗ рдХреА рд╣реИ, рдЬреЛ рдпрд╣рд╛рдБ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИред

рдкреНрд░рд╢реНрди 4: рдХреНрд╖реЗрддреНрд░ рдФрд░ рдореБрджреНрд░рд╛ рд░рд┐рдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?

Etsy IP рджреНрд╡рд╛рд░рд╛ рд╕реНрдерд╛рдиреАрдпрдХреГрдд рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рд░рд┐рдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реИ (рдЬрд░реНрдорди IP рд╕реЗ etsy.de, рдлреНрд░реЗрдВрдЪ рд╕реЗ etsy.fr)ред рдХреАрдорддреЗрдВ рдФрд░ рдореБрджреНрд░рд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рднрд┐рдиреНрди рд╣реЛрддреА рд╣реИрдВред рд╕реНрдХреНрд░реИрдкрд░ рдХрд╛ extractNumber рд╣реЗрд▓реНрдкрд░ 1,234.56 (en-US) рдФрд░ 1.234,56 (de-DE) рдкреНрд░рд╛рд░реВрдк рджреЛрдиреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╕рднреА рд░рдиреЛрдВ рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ USD рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рдг рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ proxyCountry: "US" рдкрд░ рдкрд┐рди рдХрд░реЗрдВред

рдкреНрд░рд╢реНрди 5: рдореИрдВ рдореВрд▓реНрдп, рдмрд┐рдХреНрд░реА рдкрд░, рдореБрдлреНрдд рд╢рд┐рдкрд┐рдВрдЧ, рдпрд╛ рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреИрд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдБ?

рдЖрда filters.* рдХреБрдВрдЬрд┐рдпреЛрдВ рдХрд╛ рдХреЛрдИ рднреА рд╕рдВрдпреЛрдЬрди рд╕реЗрдЯ рдХрд░реЗрдВред рдпреЗ searchQuery рдФрд░ categoryUrl рдореЛрдб рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдФрд░ Etsy рдХреЗ URL рдкрд░ рд╕реАрдзреЗ рдПрдиреНрдХреЛрдб рд╣реЛрддреЗ рд╣реИрдВ:

ts Copy
const CONFIG: ScraperInput = {

categoryUrl: "https://www.etsy.com/c/bags-and-purses/wallets-and-money-clips/wallets",
filters: {
onSale: true, // тЖТ &is_on_sale=1
freeShipping: true, // тЖТ &free_shipping=1
customizable: true, // тЖТ &is_personalizable=1
shipsTo: "US", // тЖТ &ships_to=US (ISO рджреЗрд╢ рдХреЛрдб)
minPrice: 20, // тЖТ &min=20
maxPrice: 60, // тЖТ &max=60
condition: "vintage", // "рдирдпрд╛" | "рд╡рд┐рдВрдЯреЗрдЬ" (тЖТ &explicit=vintage)
orderBy: "price_asc", // "рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг" | "рджрд┐рдирд╛рдВрдХ_desc" | "price_asc" | "price_desc" | "рдЙрдЪреНрдЪрддрдо рд╕рдореАрдХреНрд╖рд╛рдПрдБ"
},
// ...
};

Copy
рджреЛ caveats рдЬрд┐рд╕рд╕реЗ рдЕрд╡рдЧрдд рд╣реЛрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ: `filters.minPrice` / `filters.maxPrice` рдкрд░ рдПрдХ `/search?q=...` URL DataDome-рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рд╣реИ (рдЫрд╛рдирдмреАрди рдХреА рдЧрдИ рдЦреЛрдЬ URLs рдХреЛ рдЕрд╕рд╛рдзрд╛рд░рдг рд░реВрдк рд╕реЗ 403'd рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ) рдЗрд╕рд▓рд┐рдП `expandStrategy: "prices"` рдЕрдм рдПрдХ рд╡реНрдпрд╛рдкрдХ рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб `priceBucket` рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯреИрдЧ рдХрд░рддрд╛ рд╣реИ - рд╡рд╣реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд░рд╛рджрд╛, рдХреЛрдИ URL-рдЫрд╛рдирдмреАрди рдмреНрд▓реЙрдХ рдирд╣реАрдВред `categoryUrl` рдкрд░ рдореВрд▓реНрдп рдлрд╝рд┐рд▓реНрдЯрд░ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

### Q6: рдХреНрдпрд╛ рдореИрдВ retries, timeouts рдФрд░ pacing рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдБ?

рд╣рд╛рдБред рдкреНрд░рддреНрдпреЗрдХ retry рдФрд░ pacing рдорд╛рди `ScraperInput` рдкрд░ рдПрдХ CONFIG рдлрд╝реАрд▓реНрдб рд╣реИ:

| рдлрд╝реАрд▓реНрдб | рдбрд┐рдлрд╝реЙрд▓реНрдЯ | рднреВрдорд┐рдХрд╛ |
|---|---|---|
| `maxRetries` | `10` | рдЙрддреНрдкрд╛рдж рдкрд░ рдХреБрд▓ рдкреНрд░рдпрд╛рд╕ рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рд╛рд░ рдорд╛рди рд▓реЗрдВ |
| `retryInitialBackoffMs` | `3000` | рдмрдврд╝рддреА рдмреИрдХрдСрдл рд╕реВрддреНрд░ рдХрд╛ рдЖрдзрд╛рд░ |
| `retryBackoffLinearMs` | `1500` | рд░реИрдЦрд┐рдХ рдкрдж |
| `retryBackoffQuadraticMs` | `500` | рдЧреБрдгрд╛рддреНрдордХ рдкрдж (5 рд╕ тЖТ 57 рд╕ рдХреА рдкреНрд░рдЧрддрд┐ рджреЗрддрд╛ рд╣реИ) |
| `interProductDelayMs` | `3000` | рд▓рдЧрд╛рддрд╛рд░ рдЙрддреНрдкрд╛рдж рд╕рдореГрджреНрдзрд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд╡рд┐рд░рд╛рдо |
| `pageTimeoutMs` | `60000` | `page.goto` рдЯрд╛рдИрдордЖрдЙрдЯ |
| `h1TimeoutMs` | `15000` | `waitForSelector("h1")` рдЯрд╛рдИрдордЖрдЙрдЯ |
| `postLoadDelayMs` | `1500` | `h1` рдкреНрд░рдХрдЯ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдирд┐рд╖реНрдХрд░реНрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рджреЗрд░реА |

рдХрдареЛрд░ Scrapeless рдпреЛрдЬрдирд╛рдПрдВ рдХрдо `interProductDelayMs` + рдХрдо `maxRetries` рд╕реЗ рд▓рд╛рдн рдЙрдард╛рддреА рд╣реИрдВ; рдХрдард┐рди рдПрдВрдЯреА-рдмреЙрдЯ рд▓рдХреНрд╖реНрдпреЛрдВ рдХреЛ рджреЛрдиреЛрдВ рдкрд░ рдЙрдЪреНрдЪ рдорд╛рдиреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

### Q7: рдореБрдЭреЗ рдХреМрди рд╕реЗ рд╡рд┐рдлрд▓рддрд╛ рд╢реНрд░реЗрдгрд┐рдпрд╛рдБ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реЛ рд╕рдХрддреА рд╣реИрдВ?

рд╣рд░ рдЙрддреНрдкрд╛рдж рдЬреЛ retry рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдПрдХ рд╕рдВрд░рдЪрд┐рдд `error: { kind, message, attempts }` рдлрд╝реАрд▓реНрдб рд▓реЗрдХрд░ рдЖрддрд╛ рд╣реИред рдЖрда рд╢реНрд░реЗрдгреАрдмрджреНрдз рдкреНрд░рдХрд╛рд░:

- `blocked` тАФ DataDome рд╕реЗ HTTP 403/429 рдпрд╛ рджрд░ рд╕реАрдорд╛ (retryable)
- `not-found` тАФ HTTP 404, рдкреБрд░рд╛рдиреЗ рдпрд╛ рд╣рдЯрд╛рдП рдЧрдП рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ (non-retryable тАФ рддреЗрдЬрд╝реА рд╕реЗ рд╡рд┐рдлрд▓)
- `tls` тАФ `ERR_SSL_*` / `ERR_CERT_*` рдкреНрд░реЙрдХреНрд╕реА TLS рдЭрдЯрдХрд╛ (retryable)
- `network` тАФ `ERR_TUNNEL` / `ERR_CONNECTION_*` / `ERR_ABORTED` (retryable)
- `no-h1` тАФ рдкреГрд╖реНрда рд▓реЛрдб рд╣реЛ рдЧрдпрд╛ рд▓реЗрдХрд┐рди `<h1>` рдХрднреА рдирд╣реАрдВ рдкреНрд░рдХрдЯ рд╣реБрдЖ, рд╕рдВрднрд╡рддрдГ рдПрдХ рдирд░рдо DD рдЪреБрдиреМрддреА рдкреГрд╖реНрда (retryable)
- `timeout` тАФ рдиреИрд╡рд┐рдЧреЗрд╢рди рдЯрд╛рдЗрдордЖрдЙрдЯ рдкрд╛рд░ рдХрд┐рдпрд╛ (retryable)
- `open-browser` тАФ Scrapeless рдХреЗ рд▓рд┐рдП WSS рд╣реИрдВрдбрд╢реЗрдХ рд╡рд┐рдлрд▓ (retryable)
- `unknown` тАФ рдХреБрдЫ рдФрд░ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ retryable)

рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рдХреЛрдб `kind: "not-found"` рдХреЛ "рдЗрд╕ URL рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ, рдЗрд╕реЗ рдХрднреА рдкреБрдирдГ рдХрддрд╛рд░рдмрджреНрдз рди рдХрд░реЗрдВ" рдФрд░ `kind: "blocked"` рдХреЛ "рдЗрд╕ рдПрдХ рдХреЛ рдЕрдЧрд▓реЗ рдШрдВрдЯреЗ рдореЗрдВ рдкреБрдирдГ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдЬрдм DataDome рдХреА IP рдкреНрд░рддрд┐рд╖реНрдард╛ рдЦрд┐рдбрд╝рдХреА рд░рд┐рд╕реЗрдЯ рд╣реЛрддреА рд╣реИ" рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рди рд╕рдХрддрд╛ рд╣реИред

рд╕реНрдХреНрд░реИрдкрд▓реЗрд╕ рдореЗрдВ, рд╣рдо рдХреЗрд╡рд▓ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрд▓рдмреНрдз рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬрдмрдХрд┐ рд▓рд╛рдЧреВ рдХрд╛рдиреВрдиреЛрдВ, рд╡рд┐рдирд┐рдпрдореЛрдВ рдФрд░ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдЧреЛрдкрдиреАрдпрддрд╛ рдиреАрддрд┐рдпреЛрдВ рдХрд╛ рд╕рдЦреНрддреА рд╕реЗ рдЕрдиреБрдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рдмреНрд▓реЙрдЧ рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рдХреЗрд╡рд▓ рдкреНрд░рджрд░реНрд╢рди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ рдХреЛрдИ рдЕрд╡реИрдз рдпрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЧрддрд┐рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рдо рдЗрд╕ рдмреНрд▓реЙрдЧ рдпрд╛ рддреГрддреАрдп-рдкрдХреНрд╖ рд▓рд┐рдВрдХ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╕рднреА рджреЗрдпрддрд╛ рдХреЛ рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рд╕рднреА рджреЗрдпрддрд╛ рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рдХрд░рддреЗ рд╣реИрдВред рдХрд┐рд╕реА рднреА рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдЧрддрд┐рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рд╕рдВрд▓рдЧреНрди рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЕрдкрдиреЗ рдХрд╛рдиреВрдиреА рд╕рд▓рд╛рд╣рдХрд╛рд░ рд╕реЗ рдкрд░рд╛рдорд░реНрд╢ рдХрд░реЗрдВ рдФрд░ рд▓рдХреНрд╖реНрдп рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреА рд╕реЗрд╡рд╛ рдХреА рд╢рд░реНрддреЛрдВ рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХрд░реЗрдВ рдпрд╛ рдЖрд╡рд╢реНрдпрдХ рдЕрдиреБрдорддрд┐рдпрд╛рдБ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рд▓реЗрдЦ

рд╕реВрдЪреА