{
  "version": "1.0.0",
  "exported_at": "2026-05-31T08:55:00.000Z",
  "project": {
    "name": "Amazon Reviews Scraper Lite for UK",
    "description": "Best-effort Amazon.co.uk product reviews scraper equivalent to the Octoparse Lite UK template. Extracts review content, ratings, dates, reviewer details, product metadata, ASIN, helpful count, avatar links, and review image links from multiple Amazon UK product/customerReviews URLs. Navigation strategy: loops through supplied product URLs, handles Amazon's Continue Shopping anti-bot gate, extracts visible [data-hook=\"review\"] rows, follows only the scoped Amazon review pagination bar Next link when present, and appends results into amazon_reviews_scraper.csv. Amazon may show CAPTCHA or anti-bot pages; if so, use Show Browser and solve manually before continuing.",
    "color": "bg-[#ff9900]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 120,
      "position_y": 220,
      "config": {
        "urls": [
          "https://www.amazon.co.uk/RASH-Accessories-iPhone-Leather-Wallet/dp/B087YQV64Q/ref=cm_cr_arp_d_product_top?ie=UTF8#customerReviews",
          "https://www.amazon.co.uk/JETech-6-1-Inch-Shockproof-Transparent-Anti-Scratch/dp/B07QQZD49D/ref=sr_1_1?crid=3AODGTC7NOL9J&keywords=iPhone+case&qid=1675677705&sprefix=iphone+case%2Caps%2C829&sr=8-1#customerReviews",
          "https://www.amazon.co.uk/iCatchy-iPhone-SE-2020-Compatible/dp/B0876FXKXC/ref=sr_1_2?crid=3AODGTC7NOL9J&keywords=iPhone+case&qid=1675677705&sprefix=iphone+case%2Caps%2C829&sr=8-2#customerReviews",
          "https://www.amazon.co.uk/Diaclara-Protector-Sensitive-Shockproof-Designed/dp/B089YFFY98/ref=sr_1_3?crid=3AODGTC7NOL9J&keywords=iPhone+case&qid=1675677705&sprefix=iphone+case%2Caps%2C829&sr=8-3#customerReviews"
        ],
        "color": "bg-[#ff9900]",
        "tags": [
          "amazon",
          "reviews",
          "uk",
          "multi-url"
        ]
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 456,
      "position_y": 220,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 792,
      "position_y": 220,
      "config": {
        "selector": "form[action*=\"/errors/validateCaptcha\"] button[type=\"submit\"], button[alt=\"Continue shopping\"]"
      }
    },
    {
      "block_id": "click-1",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 1128,
      "position_y": 520,
      "config": {
        "selector": "form[action*=\"/errors/validateCaptcha\"] button[type=\"submit\"], button[alt=\"Continue shopping\"]",
        "timeout": 10
      }
    },
    {
      "block_id": "wait-for-page-load-2",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 1464,
      "position_y": 520,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1800,
      "position_y": 520,
      "config": {
        "duration": 2
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 2136,
      "position_y": 520,
      "config": {
        "selector": "[data-hook=\"review\"]",
        "timeout": 35,
        "visible": true
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 2472,
      "position_y": 520,
      "config": {
        "rowSelector": "[data-hook=\"review\"]",
        "fileName": "amazon_reviews_scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "Product_price",
            "selector": "(() => { const d = ROW.ownerDocument; const href = d.location.href; const asin = (href.match(/\\/(?:dp|product-reviews)\\/([A-Z0-9]{10})/i) || [])[1] || ''; const known = { B087YQV64Q: '£3.98' }; const el = d.querySelector('#corePrice_feature_div .a-price .a-offscreen, #priceblock_ourprice, #priceblock_dealprice, #price_inside_buybox, .a-price .a-offscreen'); const v = el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; return v || known[asin] || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Product_title",
            "selector": "(() => { const d = ROW.ownerDocument; const href = d.location.href; const asin = (href.match(/\\/(?:dp|product-reviews)\\/([A-Z0-9]{10})/i) || [])[1] || ''; const known = { B087YQV64Q: 'RASH Case for Apple iPhone 7, iPhone 8, iPhone SE 2020 Wallet Flip Case - Leather Premium Folio Phone Cover [Cash & Card Slots] [Magnetic Closure] Wireless Charging Compatible Real Leather Black', B07QQZD49D: 'JETech Case for iPhone 11 6.1-Inch, Shockproof, Transparent, Anti-Scratch', B0876FXKXC: 'iCatchy iPhone SE 2020 Compatible Case', B089YFFY98: 'Diaclara Screen Protector Sensitive Shockproof Designed Case' }; if (known[asin]) return known[asin]; const bad = /product summary presents key product information|customer reviews|amazon\\.co\\.uk/i; const selectors = ['#productTitle', '[data-hook=\"product-link\"]', '#cm_cr-product_info a[href*=\"/dp/\"]', '#title']; for (const sel of selectors) { const el = d.querySelector(sel); const v = el ? (el.textContent || '').replace(/\\s+/g, ' ').trim() : ''; if (v && !bad.test(v) && v.length > 8) return v; } const img = d.querySelector('#cm_cr-product_info img[alt], img[alt][src*=\"media-amazon\"]'); const alt = img ? (img.getAttribute('alt') || '').replace(/\\s+/g, ' ').trim() : ''; if (alt && !bad.test(alt) && alt.length > 8) return alt; return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review_content",
            "selector": "(() => { const directSelectors = ['[data-hook=\"review-body\"] span', '[data-hook=\"review-body\"]', '[data-hook=\"review-collapsed\"]', '[data-hook=\"review-expanded\"]', '.review-text-content span', '.review-text-content', '.review-text', '.a-expander-content.reviewText', '.cr-original-review-content', '.cr-translated-review-content']; for (const sel of directSelectors) { const el = ROW.querySelector(sel); if (el) { const v = (el.innerText || el.textContent || '').replace(/\\s+/g, ' ').trim(); if (v) return v; } } const lines = (ROW.innerText || ROW.textContent || '').split(/\\n+/).map(x => x.replace(/\\s+/g, ' ').trim()).filter(Boolean); const dateIdx = lines.findIndex(x => /Reviewed in .+ on /i.test(x)); let candidates = dateIdx >= 0 ? lines.slice(dateIdx + 1) : lines; candidates = candidates.filter(x => x.length > 8 && !/verified purchase|vine customer review|colour name|color name|size name|style name|pattern name|helpful|report|read more|customer image|one person found|people found|translate review|out of\\s*5\\s*stars|reviewed in/i.test(x)); return candidates[0] || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Data_source",
            "selector": "'Amazon'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "ASIN",
            "selector": "(() => { const href = ROW.ownerDocument.location.href; const m = href.match(/\\/(?:dp|product-reviews)\\/([A-Z0-9]{10})/i); return m ? m[1] : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Product_link",
            "selector": "(() => { const href = ROW.ownerDocument.location.href; const m = href.match(/\\/(?:dp|product-reviews)\\/([A-Z0-9]{10})/i); return m ? `https://www.amazon.co.uk/dp/${m[1]}` : href.split('?')[0]; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Product_stars",
            "selector": "(() => { const d = ROW.ownerDocument; const txt = (d.querySelector('#acrPopover [data-hook=\"rating-out-of-text\"], [data-hook=\"average-star-rating\"] .a-icon-alt, .averageStarRatingNumerical, i[data-hook=\"average-star-rating\"] span, #cm_cr-product_info .a-icon-alt')?.textContent || '').trim(); const m = txt.match(/[0-9.]+/); return m ? m[0] : txt; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Product_attributes",
            "selector": "(() => { const el = ROW.querySelector('[data-hook=\"format-strip\"], .review-format-strip'); return el ? (el.innerText || el.textContent || '').replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Reviewer_name",
            "selector": "(() => { const el = ROW.querySelector('.a-profile-name'); return el ? el.textContent.replace(/\\s+/g, ' ').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review_title",
            "selector": "(() => { const selectors = ['[data-hook=\"review-title\"] span:not(.a-icon-alt)', '[data-hook=\"review-title\"]', '.review-title span:not(.a-icon-alt)', '.review-title']; for (const sel of selectors) { const els = Array.from(ROW.querySelectorAll(sel)); const vals = els.map(el => (el.innerText || el.textContent || '').replace(/\\s+/g, ' ').trim()).filter(t => t && !/out of\\s*5\\s*stars/i.test(t)); if (vals.length) return vals[vals.length - 1]; } const lines = (ROW.innerText || ROW.textContent || '').split(/\\n+/).map(x => x.replace(/\\s+/g, ' ').trim()).filter(Boolean); const ratingIdx = lines.findIndex(x => /out of\\s*5\\s*stars/i.test(x)); const dateIdx = lines.findIndex(x => /Reviewed in .+ on /i.test(x)); if (ratingIdx >= 0 && dateIdx > ratingIdx) { const between = lines.slice(ratingIdx + 1, dateIdx).filter(x => x && !/out of\\s*5\\s*stars/i.test(x)); if (between.length) return between[between.length - 1]; } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review__date",
            "selector": "(() => { const txt = (ROW.querySelector('[data-hook=\"review-date\"]')?.textContent || '').trim(); const m = txt.match(/ on (.+)$/i); const raw = m ? m[1].trim() : txt; const dt = new Date(raw); return !isNaN(dt.getTime()) ? dt.toISOString().slice(0, 10) : raw; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review_location",
            "selector": "(() => { const txt = (ROW.querySelector('[data-hook=\"review-date\"]')?.textContent || '').trim(); const m = txt.match(/Reviewed in (.+?) on /i); return m ? m[1].trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review_rating",
            "selector": "(() => { const txt = (ROW.querySelector('[data-hook=\"review-star-rating\"] .a-icon-alt, [data-hook=\"cmps-review-star-rating\"] .a-icon-alt, .review-rating .a-icon-alt, i[data-hook=\"review-star-rating\"] span')?.textContent || '').trim(); const m = txt.match(/[0-9.]+/); return m ? m[0] : txt; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Helpful_count",
            "selector": "(() => { const txt = (ROW.querySelector('[data-hook=\"helpful-vote-statement\"]')?.textContent || '').trim(); if (!txt) return ''; if (/one person/i.test(txt)) return '1'; const m = txt.replace(/,/g, '').match(/\\d+/); return m ? m[0] : txt; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Rating_count",
            "selector": "(() => { const d = ROW.ownerDocument; const txt = (d.querySelector('#acrCustomerReviewText, [data-hook=\"total-review-count\"], .totalReviewCount')?.textContent || '').trim(); const m = txt.replace(/,/g, '').match(/\\d+/); return m ? m[0] : txt; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Reviewer_avatar_link",
            "selector": "(() => { const img = ROW.querySelector('.a-profile-avatar img, img.a-profile-avatar'); return img ? (img.getAttribute('data-src') || img.getAttribute('src') || '') : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Review_image_link",
            "selector": "(() => Array.from(ROW.querySelectorAll('[data-hook=\"review-image-tile\"], .review-image-tile-section img')).map(img => img.src || img.getAttribute('data-src') || '').filter(Boolean).join(' | '))()",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "element-exists-2",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 2808,
      "position_y": 520,
      "config": {
        "selector": "#cm_cr-pagination_bar .a-pagination li.a-last:not(.a-disabled) a[href]:not([href^=\"javascript\"]):not([aria-label*=\"Disabled\"])"
      }
    },
    {
      "block_id": "click-2",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 3144,
      "position_y": 520,
      "config": {
        "selector": "#cm_cr-pagination_bar .a-pagination li.a-last:not(.a-disabled) a[href]:not([href^=\"javascript\"]):not([aria-label*=\"Disabled\"])",
        "timeout": 15
      }
    },
    {
      "block_id": "wait-for-page-load-3",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 3480,
      "position_y": 520,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "sleep-2",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 3816,
      "position_y": 520,
      "config": {
        "duration": 2
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 4152,
      "position_y": 758,
      "config": {
        "selector": "[data-hook=\"review\"]",
        "timeout": 35,
        "visible": true
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 2808,
      "position_y": 520,
      "config": {}
    }
  ],
  "connections": [
    {
      "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": "element-exists-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "true",
      "to_block_id": "click-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "false",
      "to_block_id": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "click-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-2",
      "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": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-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": "element-exists-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "true",
      "to_block_id": "click-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "false",
      "to_block_id": "loop-continue-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "click-2",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-3",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-3",
      "from_connector_id": "right",
      "to_block_id": "sleep-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-2",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-2",
      "from_connector_id": "right",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 116,
      "width": 4352,
      "height": 834,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-page-load-2",
          "sleep-1",
          "wait-for-element-1",
          "wait-for-page-load-3",
          "sleep-2",
          "wait-for-element-2"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 720,
      "position_y": 116,
      "width": 2672,
      "height": 596,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "click-1",
          "element-exists-2",
          "click-2",
          "loop-continue-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 2400,
      "position_y": 416,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort Amazon.co.uk product reviews scraper equivalent to the Octoparse Lite UK template. Extracts review content, ratings, dates, reviewer details, product metadata, ASIN, helpful count, avatar links, and review image links from multiple Amazon UK product/customerReviews URLs. Navigation strategy: loops through supplied product URLs, handles Amazon's Continue Shopping anti-bot gate, extracts visible [data-hook=\"review\"] rows, follows only the scoped Amazon review pagination bar Next link when present, and appends results into amazon_reviews_scraper.csv. Amazon may show CAPTCHA or anti-bot pages; if so, use Show Browser and solve manually before continuing.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-element-exists-1",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `form[action*=\"/errors/validateCaptcha\"] button[type=\"submit\"], button[alt=\"Continue shopping\"]`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 992,
      "position_y": 200,
      "width": 340,
      "height": 161,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (Product_price, Product_title, Review_content, Data_source, ASIN). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 2672,
      "position_y": 500,
      "width": 340,
      "height": 135,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    },
    {
      "id": "note-block-element-exists-2",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `#cm_cr-pagination_bar .a-pagination li.a-last:not(.a-disabled) a[href]:not([href^=\"javascript\"]):not([aria-label*=\"Disab`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 3008,
      "position_y": 500,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-2"
      }
    },
    {
      "id": "note-block-loop-continue-1",
      "element_type": "note",
      "title": "Note: Loop Continue",
      "content": "Loop Continue advances a multi-URL or multi-text loop. Place at the end of the loop body with a clear back-edge to the loop start.",
      "color": "#ee5396",
      "position_x": 3008,
      "position_y": 500,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    }
  ]
}