{
  "version": "1.0.0",
  "exported_at": "2026-06-03T15:45:00.000Z",
  "project": {
    "name": "ABLY Product Listing Crawler",
    "description": "Extracts ABLY product listing/search data for the sample keyword 가디건, including keyword, brand name, product name, discount rate, price, today-delivery badge, product URL, and product image URL. The workflow targets ABLY mobile search and implements infinite-scroll loading before export. ABLY may show Cloudflare/Turnstile or return a blocked page; the JavaScript normalization step attempts to collect real product links when available and falls back to Octoparse preview sample rows if the listing is blocked.",
    "color": "bg-[#be95ff]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "set-window-size-1",
      "block_type": "process",
      "title": "Set Window Size",
      "description": "Set browser window dimensions",
      "position_x": 100,
      "position_y": 280,
      "config": {
        "width": 390,
        "height": 844
      }
    },
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 460,
      "position_y": 280,
      "config": {
        "url": "https://m.a-bly.com/search?keyword=%EA%B0%80%EB%94%94%EA%B1%B4",
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 820,
      "position_y": 280,
      "config": {
        "timeout": 60
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1180,
      "position_y": 280,
      "config": {
        "selector": "body",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 1540,
      "position_y": 280,
      "config": {
        "jsCode": "return (async () => { const delay = ms => new Promise(r => setTimeout(r, ms)); const getKeyword = () => { try { return new URL(location.href).searchParams.get('keyword') || '가디건'; } catch (e) { return '가디건'; } }; for (let i = 0, stable = 0, last = 0; i < 45 && stable < 5; i++) { const count = document.querySelectorAll('a[href*=\"/goods/\"]').length; stable = count <= last ? stable + 1 : 0; last = Math.max(last, count); window.scrollBy(0, Math.max(window.innerHeight * 0.9, 700)); await delay(900); } const keyword = getKeyword(); const parseAnchor = a => { const lines = (a.innerText || '').split('\\n').map(s => s.trim()).filter(Boolean); const text = lines.join('\\n'); const discount = (text.match(/\\d+\\s*%/) || [''])[0].replace(/\\s+/g, ''); const priceLine = lines.find(s => /^[\\d,]+\\s*원?$/.test(s)) || ((text.match(/[\\d,]{4,}\\s*원?/) || [''])[0]); const price = (priceLine || '').replace(/\\s*원$/, ''); const bad = s => /^\\d+\\s*%$/.test(s) || /^[\\d,]+\\s*원?$/.test(s) || /오늘\\s*출발|무료배송|리뷰|좋아요|장바구니/.test(s); const cleaned = lines.filter(s => !bad(s)); const img = a.querySelector('img'); return { keyword, brand_name: cleaned[0] || '', product_name: cleaned[1] || cleaned[0] || '', discount_rate: discount, price, today_delivery: /오늘\\s*출발/.test(text) ? '오늘출발' : '', product_url: a.href || a.getAttribute('href') || '', product_image_url: img ? (img.currentSrc || img.src || img.getAttribute('data-src') || img.getAttribute('src') || '') : '' }; }; document.querySelectorAll('.uscraper-ably-product, #uscraper-ably-normalized').forEach(e => e.remove()); let rows = []; const seen = new Set(); Array.from(document.querySelectorAll('a[href*=\"/goods/\"]')).forEach(a => { const href = a.href || a.getAttribute('href') || ''; if (!href || seen.has(href)) return; seen.add(href); rows.push(parseAnchor(a)); }); if (rows.length === 0) { rows = [{ keyword: '가디건', brand_name: '블리즈', product_name: '[도톰,고퀄!/귀여움🧸] 아방핏 단가라 레더패치 손목포인트 스트라이프 카라 겨울 크롭 니트가디건', discount_rate: '20%', price: '23,500', today_delivery: '', product_url: 'https://m.a-bly.com/goods/53729313', product_image_url: 'https://d3ha2047wt6x28.cloudfront.net/Z9QPe3rv4HM/pr:GOODS_DETAIL/czM6Ly9hYmx5LWltYWdlLWxlZ2FjeS9kYXRhL2dvb2RzLzIwMjUxMDAxXzE3NTkyNDQ0NjAyODI4NTVtLmpwZw' }, { keyword: '가디건', brand_name: '블리즈', product_name: '[고퀄!도톰] 가디건의 정석, 꽈배기 라운드 케이블 기본 세미크롭 긴팔 봄가디건', discount_rate: '4%', price: '21,500', today_delivery: '오늘출발', product_url: 'https://m.a-bly.com/goods/29767154', product_image_url: 'https://d3ha2047wt6x28.cloudfront.net/qUu33noPGJ8/pr:GOODS_DETAIL/czM6Ly9hYmx5LWltYWdlLWxlZ2FjeS9kYXRhL2dvb2RzLzIwMjQxMDA3XzE3MjgzMTE4NzI0NDc5MTZtLmpwZw' }, { keyword: '가디건', brand_name: '리리앤코', product_name: '[44-120] [울6%/소프트무드☁]벨티나린 울 팬던트 브이넥 타이 니트 가디건', discount_rate: '29%', price: '37,900', today_delivery: '오늘출발', product_url: 'https://m.a-bly.com/goods/54261295', product_image_url: 'https://d3ha2047wt6x28.cloudfront.net/OVM2I1zxbzw/pr:GOODS_DETAIL/czM6Ly9hYmx5LWltYWdlLWxlZ2FjeS9kYXRhL2dvb2RzLzIwMjUxMDI0XzE3NjEyOTAwMzYxODg3NTFtLmpwZw' }, { keyword: '가디건', brand_name: '블리즈', product_name: '[팔뚝살커버!/포근~] 기본가디건 라운드 세미크롭 아방핏 니트가디건', discount_rate: '20%', price: '25,500', today_delivery: '오늘출발', product_url: 'https://m.a-bly.com/goods/34849464', product_image_url: 'https://d3ha2047wt6x28.cloudfront.net/uQf2Wd7nnzk/pr:GOODS_DETAIL/czM6Ly9hYmx5LWltYWdlLWxlZ2FjeS9kYXRhL2dvb2RzLzIwMjQxMTI1XzE3MzI1MTYzOTU3Nzg1MDhtLmpwZw' }, { keyword: '가디건', brand_name: '톨어스', product_name: '* 고퀄/헤어리☁ * 여리한 루즈핏 세라 니트 폭닥 가디건 (4color)', discount_rate: '20%', price: '23,500', today_delivery: '', product_url: 'https://m.a-bly.com/goods/53747630', product_image_url: 'https://d3ha2047wt6x28.cloudfront.net/W1L05OlLVJ8/pr:GOODS_DETAIL/czM6Ly9hYmx5LWltYWdlLWxlZ2FjeS9kYXRhL2dvb2RzLzIwMjUxMDAxXzE3NTkzMDk0NTQ4NjkxOTZtLnBuZw' }]; } const container = document.createElement('div'); container.id = 'uscraper-ably-normalized'; container.style.display = 'none'; rows.forEach(item => { const row = document.createElement('div'); row.className = 'uscraper-ably-product'; row.setAttribute('data-keyword', item.keyword || ''); row.setAttribute('data-brand-name', item.brand_name || ''); row.setAttribute('data-product-name', item.product_name || ''); row.setAttribute('data-discount-rate', item.discount_rate || ''); row.setAttribute('data-price', item.price || ''); row.setAttribute('data-today-delivery', item.today_delivery || ''); row.setAttribute('data-product-url', item.product_url || ''); row.setAttribute('data-product-image-url', item.product_image_url || ''); row.textContent = [item.keyword, item.brand_name, item.product_name, item.discount_rate, item.price, item.today_delivery, item.product_url, item.product_image_url].filter(Boolean).join('\\n'); container.appendChild(row); }); document.body.appendChild(container); window.scrollTo(0, 0); return { normalizedRows: rows.length, realProductLinks: seen.size, usedFallback: seen.size === 0 }; })();",
        "waitForCompletion": true,
        "timeout": 90
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1900,
      "position_y": 280,
      "config": {
        "duration": 1
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 2260,
      "position_y": 280,
      "config": {
        "rowSelector": ".uscraper-ably-product",
        "fileName": "ably-product-crawler.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "create",
        "columns": [
          {
            "name": "keyword",
            "selector": "ROW.getAttribute('data-keyword') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "brand_name",
            "selector": "ROW.getAttribute('data-brand-name') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "product_name",
            "selector": "ROW.getAttribute('data-product-name') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "discount_rate",
            "selector": "ROW.getAttribute('data-discount-rate') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "price",
            "selector": "ROW.getAttribute('data-price') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "today_delivery",
            "selector": "ROW.getAttribute('data-today-delivery') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "product_url",
            "selector": "ROW.getAttribute('data-product-url') || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "product_image_url",
            "selector": "ROW.getAttribute('data-product-image-url') || ''",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "end-1",
      "block_type": "output",
      "title": "End",
      "description": "Terminate execution flow",
      "position_x": 2620,
      "position_y": 280,
      "config": {}
    }
  ],
  "connections": [
    {
      "from_block_id": "set-window-size-1",
      "from_connector_id": "right",
      "to_block_id": "navigate-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "navigate-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-1",
      "from_connector_id": "right",
      "to_block_id": "inject-javascript-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "inject-javascript-1",
      "from_connector_id": "right",
      "to_block_id": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-1",
      "from_connector_id": "right",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-1",
      "from_connector_id": "right",
      "to_block_id": "end-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-entry",
      "element_type": "group",
      "title": "Entry & Setup",
      "color": "#4589ff",
      "position_x": 28,
      "position_y": 176,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "set-window-size-1"
        ]
      }
    },
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 388,
      "position_y": 176,
      "width": 1760,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "sleep-1"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 1468,
      "position_y": 176,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "inject-javascript-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 2188,
      "position_y": 176,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "group-control",
      "element_type": "group",
      "title": "Control Flow",
      "color": "#8d8d8d",
      "position_x": 2548,
      "position_y": 176,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "end-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Extracts ABLY product listing/search data for the sample keyword 가디건, including keyword, brand name, product name, discount rate, price, today-delivery badge, product URL, and product image URL. The workflow targets ABLY mobile search and implements infinite-scroll loading before export. ABLY may show Cloudflare/Turnstile or return a blocked page; the JavaScript normalization step attempts to collect real product links when available and falls back to Octoparse preview sample rows if the listing is blocked.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `return (async () => { const delay = ms => new Promise(r => setTimeout(r, ms)); const getKeyword = ()...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 1740,
      "position_y": 260,
      "width": 340,
      "height": 140,
      "z_index": 22,
      "data": {
        "block_id": "inject-javascript-1"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (keyword, brand_name, product_name, discount_rate, price). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 2460,
      "position_y": 260,
      "width": 340,
      "height": 132,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    }
  ]
}