{
  "name": "[VICTOR] Google Maps Extractor",
  "nodes": [
    {
      "parameters": {
        "formTitle": "Google Maps Scraper",
        "formDescription": "Gere uma lista de leads a partir do Google Maps",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Termo da Busca",
              "placeholder": "dentista; petshop; ag\u00c3\u00aancia de marketing...",
              "requiredField": true
            },
            {
              "fieldLabel": "Cidade",
              "requiredField": true
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.2,
      "position": [
        -1504,
        784
      ],
      "id": "a819d1be-5ddd-4f10-8fb5-4aef65fe1d0a",
      "name": "On form submission"
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"bairros\": [\n    \"Batel\",\n    \"Centro\",\n    \"\u00c3gua Verde\",\n    \"Santa Felicidade\",\n    \"Cabral\"\n  ]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -1104,
        1008
      ],
      "id": "597cb649-4c64-43d0-8391-e4c0035bafc2",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "chatgpt-4o-latest",
          "mode": "list",
          "cachedResultName": "chatgpt-4o-latest"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        -1360,
        1024
      ],
      "id": "460dc58e-c037-4988-8dc9-430660f2f347",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "ebeb453d-bbaf-4e9e-b610-612337297b08",
              "leftValue": "={{ $json.website }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              }
            },
            {
              "id": "90d99c77-50b2-4d6f-90f5-8898313cb3c4",
              "leftValue": "={{ $json.website }}",
              "rightValue": "bit.ly",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "caf59970-6deb-4d13-a466-80faa63ad0a7",
              "leftValue": "={{ $json.website }}",
              "rightValue": "doctoralia",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "bfb3c998-981d-4ecb-b302-fc989e495780",
              "leftValue": "={{ $json.website }}",
              "rightValue": "whatsapp",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "8549d125-ff0a-404a-b27c-55fdcf95836d",
              "leftValue": "={{ $json.website }}",
              "rightValue": "instagram",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "5cdbd689-c1e6-4685-bee8-d44b54369eb5",
              "leftValue": "={{ $json.website }}",
              "rightValue": "facebook",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "6ec6a750-709b-474e-a98d-7263617e06fb",
              "leftValue": "={{ $json.website }}",
              "rightValue": "encurtador",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            },
            {
              "id": "c6befdb9-ba9c-4088-887f-f1473b3b9974",
              "leftValue": "={{ $json.website }}",
              "rightValue": "wa.me",
              "operator": {
                "type": "string",
                "operation": "notContains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -128,
        720
      ],
      "id": "c266fc07-b725-4320-b139-0cdc4ce8bebf",
      "name": "Tem Website?"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://google.serper.dev/maps",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-KEY"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $('On form submission').item.json['Termo da Busca'] }} no {{ $json.bairro }} - {{ $('On form submission').item.json.Cidade }}"
            },
            {
              "name": "hl",
              "value": "pt-br"
            }
          ]
        },
        "options": {
          "redirect": {
            "redirect": {}
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -688,
        784
      ],
      "id": "7945230d-5d80-4277-9a84-da96eff3db5d",
      "name": "Busca Google"
    },
    {
      "parameters": {
        "jsCode": "return items[0].json.output.bairros.map(bairro => {\n  return { json: { bairro } };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -912,
        784
      ],
      "id": "8d3bfe19-7196-4fb6-83dc-b7157f4a207b",
      "name": "Trata Dados"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -480,
        784
      ],
      "id": "9820446e-418a-4d60-b629-d7f8ec70fce8",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "SUA_PLANILHA_ID",
          "mode": "list",
          "cachedResultName": "Google Maps Scraper",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/SUA_PLANILHA_ID/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "P\u00c3\u00a1gina1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/SUA_PLANILHA_ID/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Telefone": "={{ \"'\" + $('Loop Over Items').item.json.phoneNumber }}",
            "Nome": "={{ $('Loop Over Items').item.json.title }}",
            "Bairro": "={{ $('Trata Dados').item.json.bairro }}",
            "Cidade": "={{ $('On form submission').item.json.Cidade }}",
            "Website": "={{ $('Loop Over Items').item.json.website }}",
            "E-mail": "={{ $json.emails[0] }}",
            "E-mail2": "={{ $json.emails[1] }}"
          },
          "matchingColumns": [
            "Telefone"
          ],
          "schema": [
            {
              "id": "Cidade",
              "displayName": "Cidade",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Bairro",
              "displayName": "Bairro",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Nome",
              "displayName": "Nome",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Telefone",
              "displayName": "Telefone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Website",
              "displayName": "Website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "E-mail",
              "displayName": "E-mail",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "E-mail2",
              "displayName": "E-mail2",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.6,
      "position": [
        416,
        480
      ],
      "id": "76c3d1b8-78e8-48c6-833f-425814e8b939",
      "name": "Add Row",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const input = $json.data || \"\";\n\n// Regex b\u00c3\u00a1sica para capturar e-mails\nconst regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nlet found = input.match(regex) || [];\n\n// Remove duplicados\nfound = [...new Set(found)];\n\n// Remove e-mails com extens\u00c3\u00b5es de imagem\nfound = found.filter(email => !email.match(/\\.(jpeg|jpg|png|gif|webp|svg)$/i));\n\n// Blacklist de dom\u00c3\u00adnios/termos \"fakes\"\nconst blacklist = [\n  \"exemplo.com\", \"example.com\", \"test.com\", \"teste.com\", \"email.com\", \"oj.com\", \"emailteste.com\", \"dominio.com\", \"meudominio.com\", \"domain.com\"\n];\n\n// Fun\u00c3\u00a7\u00c3\u00a3o para checar se o e-mail \u00c3\u00a9 fake\nfunction isFakeEmail(email) {\n  // Checa dom\u00c3\u00adnio na blacklist\n  const domain = email.split(\"@\")[1] || \"\";\n  return blacklist.some(bl => domain.toLowerCase().includes(bl))\n      || email.toLowerCase().includes(\"exemplo\")\n      || email.toLowerCase().includes(\"teste\")\n      || email.toLowerCase().includes(\"test\")\n      || email.toLowerCase().includes(\"sample\")\n      || email.toLowerCase().includes(\"fake\");\n}\n\n// Filtra e-mails reais\nfound = found.filter(email => !isFakeEmail(email));\n\n// Limita a 2 resultados (ajuste conforme quiser)\nconst emails = found.slice(0, 2);\n\nreturn {\n  json: {\n    emails\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        816,
        736
      ],
      "id": "457db866-fa8c-4eca-8972-ba9a3fdf1b2e",
      "name": "Extrai E-mails1",
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "67a46d8d-b923-4cec-85e9-0ba1cc6a343e",
              "leftValue": "={{ $json.error }}",
              "rightValue": "",
              "operator": {
                "type": "object",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        624,
        736
      ],
      "id": "0e326d28-4cc8-4bfc-a232-6df1dc8694ec",
      "name": "If Error Not Empty"
    },
    {
      "parameters": {
        "url": "={{ $json.website }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        448,
        720
      ],
      "id": "3ea9f5a1-0285-46c7-8545-49a77a0f69e3",
      "name": "Scrape Site1",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        240,
        688
      ],
      "id": "f0fc8a47-3a26-42be-91df-2a6be4f60407",
      "name": "Loop Over Items1"
    },
    {
      "parameters": {
        "fieldToSplitOut": "places",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        -224,
        944
      ],
      "id": "a61892e7-41d7-432e-b031-9d9aacf7d243",
      "name": "Split Out"
    },
    {
      "parameters": {
        "url": "=https://exemplo.com.br/",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -1168,
        96
      ],
      "id": "25ead42d-f10a-4765-8a55-45c9fd1d5d22",
      "name": "Scrape Site",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1424,
        96
      ],
      "id": "8c81ed27-8bd9-47b2-a5e7-c2a190396ab3",
      "name": "When clicking \u00e2\u20ac\u02dcExecute workflow\u00e2\u20ac\u2122"
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const input = $json.data || \"\";\n\n// Regex b\u00c3\u00a1sica para capturar e-mails\nconst regex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nlet found = input.match(regex) || [];\n\n// Remove duplicados\nfound = [...new Set(found)];\n\n// Remove e-mails com extens\u00c3\u00b5es de imagem\nfound = found.filter(email => !email.match(/\\.(jpeg|jpg|png|gif|webp|svg)$/i));\n\n// Blacklist de dom\u00c3\u00adnios/termos \"fakes\"\nconst blacklist = [\n  \"exemplo.com\", \"example.com\", \"test.com\", \"teste.com\", \"email.com\", \"oj.com\", \"emailteste.com\", \"dominio.com\", \"meudominio.com\", \"domain.com\"\n];\n\n// Fun\u00c3\u00a7\u00c3\u00a3o para checar se o e-mail \u00c3\u00a9 fake\nfunction isFakeEmail(email) {\n  // Checa dom\u00c3\u00adnio na blacklist\n  const domain = email.split(\"@\")[1] || \"\";\n  return blacklist.some(bl => domain.toLowerCase().includes(bl))\n      || email.toLowerCase().includes(\"exemplo\")\n      || email.toLowerCase().includes(\"teste\")\n      || email.toLowerCase().includes(\"test\")\n      || email.toLowerCase().includes(\"sample\")\n      || email.toLowerCase().includes(\"fake\");\n}\n\n// Filtra e-mails reais\nfound = found.filter(email => !isFakeEmail(email));\n\n// Limita a 2 resultados (ajuste conforme quiser)\nconst emails = found.slice(0, 2);\n\nreturn {\n  json: {\n    emails\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -896,
        96
      ],
      "id": "ed3fbb69-4756-48e3-93a6-5fc0b033240d",
      "name": "Extrai E-mails2",
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "timeout": {}
      },
      "type": "@apify/n8n-nodes-apify.apify",
      "typeVersion": 1,
      "position": [
        -944,
        -336
      ],
      "id": "8b7d97e7-4c8d-4e39-91a7-8f9efe78b43d",
      "name": "Run an Actor"
    },
    {
      "parameters": {
        "resource": "Default",
        "operation": "Scrape A Url And Get Its Content",
        "url": "https://www.exemplo.com.br/",
        "formats": [
          "markdown"
        ],
        "requestOptions": {}
      },
      "type": "n8n-nodes-firecrawl.fireCrawl",
      "typeVersion": 1,
      "position": [
        -1200,
        -336
      ],
      "id": "ad918ef8-9d79-4dd1-8261-164ca65774a9",
      "name": "Scrape A Url And Get Its Content",
      "credentials": {
        "fireCrawlApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Cidade para buscar os bairros: {{ $json.Cidade }}",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "message": "=Sua especialidade \u00c3\u00a9 geografia do Brasil. Sua miss\u00c3\u00a3o \u00c3\u00a9 encontrar o nome de bairros em cidades do Brasil. \n\nO usu\u00c3\u00a1rio te dar\u00c3\u00a1 o nome de uma cidade e voc\u00c3\u00aa deve listar o nome dos 5 principais bairros daquela cidade. \n\n# Importante:\n- Nunca invente informa\u00c3\u00a7\u00c3\u00b5es. Nunca mesmo."
            }
          ]
        },
        "batching": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.7,
      "position": [
        -1280,
        784
      ],
      "id": "644559d6-1cea-4c57-b145-3e9e498dd05b",
      "name": "Gera Bairros"
    },
    {
      "parameters": {
        "content": "## N\u00c3\u00b3s da Comunidade\nEsses n\u00c3\u00b3s s\u00c3\u00a3o do Firecrawl e Apify. S\u00c3\u00b3 v\u00c3\u00a3o funcionar se voc\u00c3\u00aa instalar os comunity-nodes",
        "height": 320,
        "width": 752
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1488,
        -464
      ],
      "id": "14e9fbf6-677c-4261-9194-2a536be5d79e",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Teste\nN\u00c3\u00b3s para testar scrape",
        "height": 320,
        "width": 816
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1488,
        -48
      ],
      "id": "532244ce-0438-4819-9067-513086d3fb07",
      "name": "Sticky Note1"
    }
  ],
  "connections": {
    "On form submission": {
      "main": [
        [
          {
            "node": "Gera Bairros",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Gera Bairros",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Gera Bairros",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Tem Website?": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Add Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Busca Google": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trata Dados": {
      "main": [
        [
          {
            "node": "Busca Google",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Tem Website?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extrai E-mails1": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Error Not Empty": {
      "main": [
        [
          {
            "node": "Extrai E-mails1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Site1": {
      "main": [
        [
          {
            "node": "If Error Not Empty",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [
          {
            "node": "Add Row",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape Site1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Row": {
      "main": [
        []
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Site": {
      "main": [
        [
          {
            "node": "Extrai E-mails2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u00e2\u20ac\u02dcExecute workflow\u00e2\u20ac\u2122": {
      "main": [
        [
          {
            "node": "Scrape Site",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape A Url And Get Its Content": {
      "main": [
        []
      ]
    },
    "Gera Bairros": {
      "main": [
        [
          {
            "node": "Trata Dados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "VERSAO_ID",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "ID_WORKFLOW",
  "tags": [
    {
      "createdAt": "2025-06-18T22:14:11.679Z",
      "updatedAt": "2025-06-18T22:14:11.679Z",
      "id": "ID_TAG",
      "name": "N8N Course"
    }
  ]
}