{
  "version": "1.0.0",
  "exported_at": "2026-05-31T18:05:00.000Z",
  "project": {
    "name": "Das Ãrtliche Lead Scraper",
    "description": "Scrapes Das Örtliche business lead detail pages for keyword, location, page, URL, name, industry, address, phone, email, website, rating, and opening status. Uses a multi-URL navigation loop over pre-collected detail URLs from the Octoparse preview and skips unavailable/404 detail records. Phone extraction uses robust JS parsing because Das Örtliche embeds phone text in mixed detail-page content.",
    "color": "bg-[#4589ff]",
    "template_id": "ai-generated-dasoertliche-leads"
  },
  "blocks": [
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to each Das Örtliche detail URL",
      "position_x": 120,
      "position_y": 220,
      "config": {
        "urls": [
          "https://www.dasoertliche.de/?form_name=detail&id=2239131022875556661529&recuid=QQHAPE3EYJG6K7XRSVUOCME3YX5CNDSRUKFIEQOXGCNBP3NDAI&niceid=Caputo-Berlin-Neuk%C3%B6lln-Sanderstr&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=0",
          "https://www.dasoertliche.de/?form_name=detail&id=2239130995108556661529&recuid=TZBOA7HTSEIPWMPK4YG2YKWX36SENZSG6WP5EFXSFXLA3INZAI&niceid=Restaurant-und-Bierhaus-Xantener-Eck-Berlin-Wilmersdorf-Xantener-Str&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=1",
          "https://www.dasoertliche.de/?form_name=detail&id=2239130766190556661529&recuid=QXYMLRSMUG36JA7RDYJRAMLFYQVWQMCRLSFQQ2CKFVSBME5CAI&niceid=Gasthaus-Mutter-Hoppe-Berlin-Mitte-Rathausstr&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=2",
          "https://www.dasoertliche.de/?form_name=detail&id=2239129206051552605163&recuid=3XG4OKEUCOGP3275NYTU22KYTQKCMLQJMHJREPYYLIGOOAQ&niceid=A-A-American-Food-Concepts-GmbH-Berlin-Friedrichshain-Hedwig-Wachenheim-Str&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=3",
          "https://www.dasoertliche.de/?form_name=detail&id=2239130426727552605163&recuid=JPJEYRVMNOJWNH3LGXYRT72HBIMPIB5MPZCWNRZX2VNOCMLMAI&niceid=A-M-Indischer-Imbiss-by-Yummy-s-Kitchen-Berlin-Buckow-Rudower-Str&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=4",
          "https://www.dasoertliche.de/?form_name=detail&id=2239123892085552605163&recuid=GQYNURGDZZYRI7KVYX5IZBNFOXJKL7HHTQ5IB4V3VW4J5UYTAI&niceid=A-Magica-italienisches-Restaurant-Berlin-Prenzlauer-Berg-Greifenhagener-Str&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=5",
          "https://www.dasoertliche.de/?form_name=detail&id=2239130414066552605163&recuid=FMLZBQDBQJLAWWTK4X6N3H4CNLXKLUWHWAS2DKHNWG5BCAQ&niceid=A-MANO-GmbH-Co-KG-Berlin-Mitte-Strausberger-Platz&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=6",
          "https://www.dasoertliche.de/?form_name=detail&id=2239127247491552605163&recuid=HHK4WC4AKOKBPG3YK2GFZCSAPAAI46OYPE3XLJA2UNOZGNQ6AI&niceid=A-NAM-Restaurant-Berlin-Prenzlauer-Berg-Gleimstr&buc=2239&showbuc=0&verlNr=1126&kw=restaurant&ci=berlin&recFrom=1&pagePos=1&lastFormName=search_nat&hitno=7"
        ],
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for the detail page to finish loading",
      "position_x": 456,
      "position_y": 220,
      "config": {
        "timeout": 30,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Short delay for late-rendered detail content",
      "position_x": 792,
      "position_y": 220,
      "config": {
        "duration": 1,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check whether this URL contains a valid business detail record",
      "position_x": 1128,
      "position_y": 220,
      "config": {
        "selector": "#detail_box1 .addressblock h1",
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export Das Örtliche lead fields from the detail record",
      "position_x": 1464,
      "position_y": 520,
      "config": {
        "rowSelector": "#detail_box1 .addressblock",
        "fileName": "das-oertliche-lead-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "keyword",
            "selector": "(() => { const u = new URL(window.location.href); return u.searchParams.get('kw') || document.querySelector('#std_suchwort')?.value || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "location",
            "selector": "(() => { const u = new URL(window.location.href); return u.searchParams.get('ci') || document.querySelector('#std_ort')?.value || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "page",
            "selector": "(() => { const u = new URL(window.location.href); return u.searchParams.get('pagePos') || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "url",
            "selector": "window.location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "name",
            "selector": ".name h1",
            "attribute": "text"
          },
          {
            "name": "industry",
            "selector": "(() => { const txt = ROW.querySelector('.seoThemenLink')?.textContent || ''; const loc = (new URL(window.location.href)).searchParams.get('ci') || document.querySelector('#std_ort')?.value || ''; return txt.replace(new RegExp('\\\\s+in\\\\s+' + loc + '$', 'i'), '').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "address",
            "selector": "(() => { const el = ROW.querySelector('.det_address'); if (!el) return ''; const clone = el.cloneNode(true); clone.querySelectorAll('a, script, style').forEach(n => n.remove()); return clone.textContent.replace(/\\u00a0/g, ' ').replace(/\\s+/g, ' ').trim(); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "phone",
            "selector": "(() => { const clean = s => (s || '').replace(/\\u00a0/g, ' ').replace(/\\s+/g, ' ').trim(); const tel = document.querySelector('a[href^=\"tel:\"]'); if (tel) return clean(tel.getAttribute('href').replace(/^tel:/i, '')); const selectors = ['[itemprop=\"telephone\"]', '.det_phone', '.phone', '.telefon', '.tel', '.nr', '.number']; for (const sel of selectors) { const el = ROW.querySelector(sel) || document.querySelector(sel); const val = clean(el?.textContent); if (val && /\\d/.test(val) && !/Route|Routen|Gratis/i.test(val)) return val.replace(/^Telefon:\\s*/i, '').trim(); } const text = clean(document.body.innerText || document.body.textContent || ''); let m = text.match(/Telefon:\\s*([+()\\d][+()\\d\\s\\/-]{4,40}?)(?=\\s*(?:Gratis\\s+anrufen|mail@|[\\w.%+-]+@[\\w.-]+\\.[A-Z]{2,}|https?:\\/\\/|www\\.|Branche:|Durchschnittliche|Schreib|Jetzt|Weiterempfehlen|$))/i); if (m) return clean(m[1]); m = text.match(/Telefon:\\s*([^\\n\\r]{5,60})/i); if (m) return clean(m[1]).replace(/\\s*(Gratis\\s+anrufen|Branche:|Jetzt.*)$/i, '').trim(); return ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "email",
            "selector": "(() => { const a = ROW.querySelector('a.mail[href^=\"mailto:\"]'); return a ? a.getAttribute('href').replace(/^mailto:/i, '').trim() : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "website",
            "selector": "a.www",
            "attribute": "href"
          },
          {
            "name": "rating",
            "selector": "(() => { return ROW.querySelector('.inwords')?.textContent.replace(/\\s+/g, ' ').trim() || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "opening_status",
            "selector": "(() => { return ROW.querySelector('.det_times, .opnopen')?.textContent.replace(/\\s+/g, ' ').trim() || ''; })()",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue to the next detail URL after exporting a valid record",
      "position_x": 1800,
      "position_y": 520,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    },
    {
      "block_id": "loop-continue-2",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Skip unavailable detail pages and continue to the next URL",
      "position_x": 1128,
      "position_y": 520,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    }
  ],
  "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": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-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-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-1",
      "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": "loop-continue-2",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 116,
      "width": 992,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "sleep-1"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 1056,
      "position_y": 116,
      "width": 992,
      "height": 596,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "loop-continue-1",
          "loop-continue-2"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 1392,
      "position_y": 416,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Scrapes Das Örtliche business lead detail pages for keyword, location, page, URL, name, industry, address, phone, email, website, rating, and opening status. Uses a multi-URL navigation loop over pre-collected detail URLs from the Octoparse preview and skips unavailable/404 detail records. Phone extraction uses robust JS parsing because Das Örtliche embeds phone text in mixed detail-page content.",
      "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 `#detail_box1 .addressblock h1`. 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": 140,
      "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 (keyword, location, page, url, industry). 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-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"
      }
    },
    {
      "id": "note-block-loop-continue-2",
      "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": 1328,
      "position_y": 500,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-2"
      }
    }
  ]
}