{
  "version": "1.0.0",
  "exported_at": "2026-06-03T13:15:00.000Z",
  "project": {
    "name": "JP Indeed Job Scraper by URL cloud only",
    "description": "Best-effort Indeed Japan job scraper equivalent to the Octoparse URL-based template. It loops through supplied Indeed Japan URLs, detects Indeed/Cloudflare additional-verification pages to avoid timeout, and otherwise extracts job data from direct /viewjob pages and /jobs search-result pages. For accessible search-result pages it follows the Next pagination button until no enabled next link is found, then continues to the next input URL. Fields include keyword, job title, detail URL, company, description, location, salary, employment type, posted date, company rating, source page URL, and current time. Attached analysis and test run showed Indeed blocking automated access, so a blocker row is exported when verification is encountered.",
    "color": "bg-[#4589ff]",
    "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://jp.indeed.com/viewjob?jk=a712a92196703000&from=serp&vjs=3",
          "https://jp.indeed.com/jobs?q=%E5%96%B6%E6%A5%AD%E4%BC%81%E7%94%BB&l=%E6%9D%B1%E4%BA%AC%E9%83%BD&fromage=7&from=searchOnDesktopSerp&vjk=4cf874d4483b4b6a",
          "https://jp.indeed.com/viewjob?jk=29778f03d73922e7&from=serp&vjs=3"
        ],
        "color": "bg-[#4589ff]",
        "tags": [
          "indeed-japan",
          "input-urls",
          "cloudflare-aware"
        ]
      }
    },
    {
      "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": 45
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 792,
      "position_y": 220,
      "config": {
        "selector": "body",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 1128,
      "position_y": 220,
      "config": {
        "selector": "#cf-box-container, input[name='cf-turnstile-response'], h1#heading"
      }
    },
    {
      "block_id": "structured-export-2",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 1464,
      "position_y": 520,
      "config": {
        "rowSelector": "body",
        "fileName": "jp-indeed-job-url-scraper-cloud.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "キーワード",
            "selector": "(() => { try { return new URL(location.href).searchParams.get('q') || ''; } catch(e) { return ''; } })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "職位",
            "selector": "'BLOCKED_BY_INDEED_VERIFICATION'",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "仕事内容詳細ページリンク",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "会社名",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "職務内容詳細",
            "selector": "(() => { const h = document.querySelector('h1')?.innerText?.trim() || ''; const p = document.querySelector('#paragraph')?.innerText?.trim() || ''; return 'Indeed returned an additional verification / bot-detection page. ' + h + (p ? ' - ' + p : ''); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "勤務地",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "給料",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "雇用形態",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "投稿日",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "会社口コミランキング",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "PageUrl",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Current_Time",
            "selector": "new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1128,
      "position_y": 520,
      "config": {
        "selector": "[data-testid='jobsearch-JobComponent'], .jobsearch-JobComponent, div[data-jk], .job_seen_beacon, td.result",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 1632,
      "position_y": 800,
      "config": {
        "rowSelector": "[data-testid='jobsearch-JobComponent'], .jobsearch-JobComponent, div[data-jk], .job_seen_beacon, td.result",
        "fileName": "jp-indeed-job-url-scraper-cloud.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "キーワード",
            "selector": "(() => { try { return new URL(location.href).searchParams.get('q') || ''; } catch(e) { return ''; } })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "職位",
            "selector": "(() => { const s = ['h1[data-testid=\"jobsearch-JobInfoHeader-title\"]','h1.jobsearch-JobInfoHeader-title','h1','h2.jobTitle a span','h2.jobTitle span','[data-testid=\"job-title\"]','a[data-jk] span']; for (const q of s) { const el = ROW.querySelector(q); if (el && el.innerText.trim()) return el.innerText.replace(/\\s+-\\s+求人.*$/,'').trim(); } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "仕事内容詳細ページリンク",
            "selector": "(() => { const a = ROW.querySelector('a[href*=\"/viewjob\"], a[data-jk], h2.jobTitle a'); if (a && a.href) return a.href; const jk = ROW.getAttribute('data-jk') || ROW.querySelector('[data-jk]')?.getAttribute('data-jk'); if (jk) return 'https://jp.indeed.com/viewjob?jk=' + jk; const canonical = document.querySelector('link[rel=\"canonical\"]'); return canonical?.href || location.href; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "会社名",
            "selector": "(() => { const s = ['[data-testid=\"inlineHeader-companyName\"]','[data-testid=\"company-name\"]','.jobsearch-InlineCompanyRating div:first-child','.jobsearch-CompanyInfoContainer a','.companyName','span.companyName','[data-company-name=\"true\"]']; for (const q of s) { const el = ROW.querySelector(q); if (el && el.innerText.trim()) return el.innerText.trim(); } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "職務内容詳細",
            "selector": "(() => { const s = ['#jobDescriptionText','[data-testid=\"jobDescriptionText\"]','.jobsearch-jobDescriptionText','.job-snippet','.summary']; for (const q of s) { const el = ROW.querySelector(q); if (el && el.innerText.trim()) return el.innerText.trim(); } const global = document.querySelector('#jobDescriptionText, [data-testid=\"jobDescriptionText\"], .jobsearch-jobDescriptionText'); if (global && ROW.matches('[data-testid=\"jobsearch-JobComponent\"], .jobsearch-JobComponent')) return global.innerText.trim(); return ROW.innerText.trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "勤務地",
            "selector": "(() => { const s = ['[data-testid=\"job-location\"]','[data-testid=\"inlineHeader-companyLocation\"]','.companyLocation','.jobsearch-JobInfoHeader-subtitle div:last-child','div[data-testid=\"text-location\"]']; for (const q of s) { const el = ROW.querySelector(q); if (el && el.innerText.trim()) return el.innerText.trim(); } return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "給料",
            "selector": "(() => { const s = ['[data-testid=\"attribute_snippet_testid\"]','.salary-snippet-container','.metadata.salary-snippet-container','.jobsearch-JobMetadataHeader-item']; for (const q of s) { const els = Array.from(ROW.querySelectorAll(q)); for (const el of els) { const t = el.innerText.trim(); if (/円|万円|年収|月給|時給|日給/.test(t)) return t; } } const text = ROW.innerText || ''; const m = text.match(/((年収|月給|時給|日給)?\\s*[0-9,]+\\s*万?円\\s*(~|～|-|から)?\\s*[0-9,]*\\s*万?円?)/); return m ? m[0].trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "雇用形態",
            "selector": "(() => { const text = ROW.innerText || ''; const types = ['正社員','契約社員','派遣社員','アルバイト･パート','アルバイト・パート','業務委託','新卒','インターン','職業紹介']; return types.find(t => text.includes(t)) || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "投稿日",
            "selector": "(() => { const s = ['[data-testid=\"myJobsStateDate\"]','.date','.jobsearch-HiringInsights-entry--text','span[data-testid=\"myJobsStateDate\"]']; for (const q of s) { const el = ROW.querySelector(q); if (el && el.innerText.trim()) return el.innerText.trim(); } const text = ROW.innerText || ''; const m = text.match(/(\\d+日前|\\d+時間前|本日|たった今|Posted\\s+\\d+.*?ago)/); return m ? m[0] : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "会社口コミランキング",
            "selector": "(() => { const s = ['[aria-label*=\"評価\"]','[aria-label*=\"rating\"]','.ratingsDisplay','.ratingNumber','[data-testid=\"holistic-rating\"]']; for (const q of s) { const el = ROW.querySelector(q); if (el) { const t = (el.innerText || el.getAttribute('aria-label') || '').trim(); const m = t.match(/[0-5](\\.\\d)?/); if (m) return m[0]; } } const text = ROW.innerText || ''; const m = text.match(/\\b[0-5]\\.\\d\\b/); return m ? m[0] : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "PageUrl",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "Current_Time",
            "selector": "new Date().toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "element-exists-2",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 1968,
      "position_y": 800,
      "config": {
        "selector": "a[data-testid='pagination-page-next']:not([aria-disabled='true']), a[aria-label='Next Page']:not([aria-disabled='true']), a[aria-label='次へ']:not([aria-disabled='true']), a[aria-label*='Next']:not([aria-disabled='true'])"
      }
    },
    {
      "block_id": "click-1",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 2304,
      "position_y": 800,
      "config": {
        "selector": "a[data-testid='pagination-page-next']:not([aria-disabled='true']), a[aria-label='Next Page']:not([aria-disabled='true']), a[aria-label='次へ']:not([aria-disabled='true']), a[aria-label*='Next']:not([aria-disabled='true'])",
        "timeout": 15
      }
    },
    {
      "block_id": "wait-for-page-load-2",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 2640,
      "position_y": 800,
      "config": {
        "timeout": 45
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 2976,
      "position_y": 800,
      "config": {
        "duration": 2
      }
    },
    {
      "block_id": "wait-for-element-3",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 3312,
      "position_y": 800,
      "config": {
        "selector": "[data-testid='jobsearch-JobComponent'], .jobsearch-JobComponent, div[data-jk], .job_seen_beacon, td.result",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 1800,
      "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": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-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": "structured-export-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-2",
      "from_connector_id": "right",
      "to_block_id": "loop-continue-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "false",
      "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"
    },
    {
      "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-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-3",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-3",
      "from_connector_id": "right",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "false",
      "to_block_id": "loop-continue-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": 3512,
      "height": 876,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "wait-for-element-2",
          "wait-for-page-load-2",
          "sleep-1",
          "wait-for-element-3"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 1056,
      "position_y": 116,
      "width": 1496,
      "height": 876,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "element-exists-2",
          "click-1",
          "loop-continue-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 1392,
      "position_y": 416,
      "width": 488,
      "height": 576,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-2",
          "structured-export-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort Indeed Japan job scraper equivalent to the Octoparse URL-based template. It loops through supplied Indeed Japan URLs, detects Indeed/Cloudflare additional-verification pages to avoid timeout, and otherwise extracts job data from direct /viewjob pages and /jobs search-result pages. For accessible search-result pages it follows the Next pagination button until no enabled next link is found, then continues to the next input URL. Fields include keyword, job title, detail URL, company, description, location, salary, employment type, posted date, company rating, source page URL, and current time. Attached analysis and test run showed Indeed blocking automated access, so a blocker row is exported when verification is encountered.",
      "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 `#cf-box-container, input[name='cf-turnstile-response'], h1#heading`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 1328,
      "position_y": 200,
      "width": 340,
      "height": 152,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-structured-export-2",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (キーワード, 職位, 仕事内容詳細ページリンク, 会社名, 職務内容詳細). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 1664,
      "position_y": 500,
      "width": 340,
      "height": 126,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-2"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (キーワード, 職位, 仕事内容詳細ページリンク, 会社名, 職務内容詳細). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 1832,
      "position_y": 780,
      "width": 340,
      "height": 126,
      "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 `a[data-testid='pagination-page-next']:not([aria-disabled='true']), a[aria-label='Next Page']:not([aria-disabled='true'])`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 2168,
      "position_y": 780,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-2"
      }
    },
    {
      "id": "note-block-click-1",
      "element_type": "note",
      "title": "Note: Click",
      "content": "Pagination click — add waits after this block; the page reloads asynchronously.",
      "color": "#ee5396",
      "position_x": 2504,
      "position_y": 780,
      "width": 316,
      "height": 106,
      "z_index": 22,
      "data": {
        "block_id": "click-1"
      }
    },
    {
      "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": 2000,
      "position_y": 500,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    }
  ]
}