8
n8n 한국어amn8n.com

Telegram 로봇을 통해 일자리 찾기: AI 기반의 LinkedIn, Indeed, Monster 추출기

중급

이것은Miscellaneous, AI Chatbot, Multimodal AI분야의자동화 워크플로우로, 15개의 노드를 포함합니다.주로 Code, Filter, Airtable, Telegram, HttpRequest 등의 노드를 사용하며. AI 기반 Telegram 로봇을 통해 LinkedIn, Indeed, Monster의 직업 정보를 추출합니다.

사전 요구사항
  • Airtable API Key
  • Telegram Bot Token
  • 대상 API의 인증 정보가 필요할 수 있음
  • Google Sheets API 인증 정보
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "meta": {
    "version": "2.0",
    "instanceId": "workflow_job_scraper_telegram"
  },
  "tags": [
    "telegram",
    "job-scraping",
    "sales",
    "marketing",
    "automation",
    "ai"
  ],
  "nodes": [
    {
      "id": "telegram_trigger",
      "name": "Telegram 봇 트리거",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        260,
        200
      ],
      "parameters": {
        "updates": [
          "message"
        ]
      },
      "credentials": {
        "telegramApi": {
          "id": "telegram_bot_credentials",
          "name": "Job Scraper Bot"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "telegram_command_filter",
      "name": "명령어 필터",
      "type": "n8n-nodes-base.filter",
      "position": [
        480,
        200
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.message.text}}",
              "rightValue": "/start"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "job_search_filter",
      "name": "구직 검색 필터",
      "type": "n8n-nodes-base.filter",
      "position": [
        480,
        350
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "startsWith"
              },
              "leftValue": "={{$json.message.text}}",
              "rightValue": "/jobs"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "welcome_message",
      "name": "환영 메시지 전송",
      "type": "n8n-nodes-base.telegram",
      "position": [
        700,
        200
      ],
      "parameters": {
        "text": "🤖 **Job Scraper Bot Activated!** 🚀\n\n*Welcome to your personal job hunting assistant!*\n\n**Available Commands:**\n/jobs [keyword] [location] - Search for jobs\n/status - Check bot status\n/help - Show this help\n\n**Examples:**\n• `/jobs sales manager New York`\n• `/jobs marketing remote`\n• `/jobs developer San Francisco`\n\n*Let me find the perfect job opportunities for you!* 💼",
        "chatId": "={{$json.message.chat.id}}",
        "resource": "message",
        "operation": "sendMessage",
        "parseMode": "Markdown"
      },
      "credentials": {
        "telegramApi": {
          "id": "telegram_bot_credentials",
          "name": "Job Scraper Bot"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "parse_job_command",
      "name": "작업 명령어 파싱",
      "type": "n8n-nodes-base.code",
      "position": [
        700,
        350
      ],
      "parameters": {
        "jsCode": "// Parse Telegram job search command\nconst message = $input.first().json.message;\nconst text = message.text;\nconst chatId = message.chat.id;\nconst userId = message.from.id;\nconst userName = message.from.first_name || 'User';\n\n// Parse command: /jobs [keyword] [location]\nconst parts = text.split(' ');\nlet keyword = 'sales marketing';\nlet location = 'New York';\n\nif (parts.length >= 2) {\n  keyword = parts.slice(1, -1).join(' ') || 'sales marketing';\n  location = parts[parts.length - 1] || 'New York';\n}\n\n// If only one parameter, treat as keyword\nif (parts.length === 2) {\n  keyword = parts[1];\n  location = 'New York';\n}\n\n// Create search parameters\nconst searchParams = {\n  keyword: keyword,\n  location: location,\n  chatId: chatId,\n  userId: userId,\n  userName: userName,\n  timestamp: new Date().toISOString()\n};\n\nreturn [{\n  json: {\n    ...searchParams,\n    originalMessage: message,\n    searchQuery: `${keyword} in ${location}`\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "search_status_message",
      "name": "검색 상태 전송",
      "type": "n8n-nodes-base.telegram",
      "position": [
        920,
        350
      ],
      "parameters": {
        "text": "🔍 **Searching for Jobs...**\n\n*Keyword:* `{{$json.keyword}}`\n*Location:* `{{$json.location}}`\n\n*Please wait while I scan LinkedIn, Indeed, and Monster for the best opportunities...* ⏳",
        "chatId": "={{$json.chatId}}",
        "resource": "message",
        "operation": "sendMessage",
        "parseMode": "Markdown"
      },
      "credentials": {
        "telegramApi": {
          "id": "telegram_bot_credentials",
          "name": "Job Scraper Bot"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "linkedin_scraper_telegram",
      "name": "LinkedIn 채용 스크레이퍼",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1140,
        250
      ],
      "parameters": {
        "url": "https://api.brightdata.com/datasets/v3/trigger",
        "method": "POST",
        "options": {
          "retry": {
            "enabled": true,
            "maxTries": 3,
            "waitBetween": 2000
          },
          "timeout": 30000
        },
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "dataset_id",
              "value": "gd_lpfbbndm1xnopbrcr0"
            },
            {
              "name": "country",
              "value": "US"
            },
            {
              "name": "keyword",
              "value": "={{$json.keyword}}"
            },
            {
              "name": "location",
              "value": "={{$json.location}}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "indeed_scraper_telegram",
      "name": "Indeed 채용 스크레이퍼",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1140,
        350
      ],
      "parameters": {
        "url": "https://api.brightdata.com/datasets/v3/trigger",
        "method": "POST",
        "options": {
          "retry": {
            "enabled": true,
            "maxTries": 3,
            "waitBetween": 2000
          },
          "timeout": 30000
        },
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "dataset_id",
              "value": "gd_l4dx9j9sscpvs7no2"
            },
            {
              "name": "what",
              "value": "={{$json.keyword}}"
            },
            {
              "name": "where",
              "value": "={{$json.location}}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "monster_scraper_telegram",
      "name": "Monster 채용 스크레이퍼",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1140,
        450
      ],
      "parameters": {
        "url": "https://api.monster.com/job-search/v2/search",
        "method": "GET",
        "options": {
          "retry": {
            "enabled": true,
            "maxTries": 3,
            "waitBetween": 2000
          },
          "timeout": 30000
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{$json.keyword}}"
            },
            {
              "name": "where",
              "value": "={{$json.location}}"
            },
            {
              "name": "page",
              "value": "1"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "telegram_job_processor",
      "name": "Telegram용 작업 처리",
      "type": "n8n-nodes-base.code",
      "position": [
        1360,
        350
      ],
      "parameters": {
        "jsCode": "// Enhanced job processing with Telegram context\nconst items = $input.all();\nconst processedJobs = [];\nlet chatId, userName, searchQuery;\n\n// Get Telegram context from first item\nif (items.length > 0 && items[0].json.chatId) {\n  chatId = items[0].json.chatId;\n  userName = items[0].json.userName || 'User';\n  searchQuery = items[0].json.searchQuery || 'jobs';\n}\n\nfor (const item of items) {\n  const source = item.json;\n  \n  // Skip items that are just telegram context\n  if (source.chatId && !source.company_name && !source.jobkey && !source.jobId) {\n    continue;\n  }\n  \n  // Determine source platform\n  let platform = 'unknown';\n  if (source.company_name || source.job_title) {\n    platform = 'linkedin';\n  } else if (source.jobkey || source.jobtitle) {\n    platform = 'indeed';\n  } else if (source.jobId) {\n    platform = 'monster';\n  }\n  \n  // Standardize job data structure\n  const standardizedJob = {\n    platform: platform,\n    job_id: source.job_id || source.jobkey || source.jobId || '',\n    title: source.job_title || source.jobtitle || source.title || '',\n    company: source.company_name || source.company || source.companyName || '',\n    location: source.location || source.formattedLocation || '',\n    description: source.description || source.snippet || '',\n    salary: source.salary || source.salary_formatted || '',\n    url: source.url || source.link || '',\n    posted_date: source.date_posted || source.date || source.postDate || '',\n    scraped_at: new Date().toISOString(),\n    // Telegram context\n    telegram_chat_id: chatId,\n    telegram_user: userName,\n    search_query: searchQuery,\n    // Enhanced filtering\n    is_relevant: checkRelevance(source.job_title || source.title || '', source.description || source.snippet || ''),\n    experience_level: extractExperience(source.description || source.snippet || ''),\n    remote_option: checkRemote(source.description || source.snippet || ''),\n    salary_range: extractSalary(source.salary || source.salary_formatted || '')\n  };\n  \n  processedJobs.push({ json: standardizedJob });\n}\n\n// Filter and deduplicate\nconst filteredJobs = processedJobs.filter(job => job.json.is_relevant);\nconst uniqueJobs = [];\nconst seen = new Set();\n\nfor (const job of filteredJobs) {\n  const key = `${job.json.title}-${job.json.company}`.toLowerCase().replace(/[^a-z0-9]/g, '');\n  if (!seen.has(key) && uniqueJobs.length < 10) { // Limit to 10 jobs for Telegram\n    seen.add(key);\n    uniqueJobs.push(job);\n  }\n}\n\n// Add summary statistics\nif (uniqueJobs.length > 0 && chatId) {\n  const summary = {\n    json: {\n      telegram_chat_id: chatId,\n      telegram_user: userName,\n      search_query: searchQuery,\n      total_jobs_found: uniqueJobs.length,\n      platforms_searched: [...new Set(uniqueJobs.map(job => job.json.platform))],\n      remote_jobs: uniqueJobs.filter(job => job.json.remote_option).length,\n      search_timestamp: new Date().toISOString(),\n      is_summary: true\n    }\n  };\n  uniqueJobs.unshift(summary);\n}\n\nfunction checkRelevance(title, description) {\n  const text = (title + ' ' + description).toLowerCase();\n  const keywords = ['sales', 'marketing', 'business development', 'account manager', 'digital marketing', \n                   'marketing manager', 'sales representative', 'business analyst', 'account executive'];\n  return keywords.some(keyword => text.includes(keyword));\n}\n\nfunction extractExperience(description) {\n  const senior_keywords = ['senior', '5+ years', 'lead', 'principal', 'director'];\n  const entry_keywords = ['entry level', '0-2 years', 'junior', 'associate'];\n  const text = description.toLowerCase();\n  \n  if (senior_keywords.some(keyword => text.includes(keyword))) return 'senior';\n  if (entry_keywords.some(keyword => text.includes(keyword))) return 'entry';\n  return 'mid';\n}\n\nfunction checkRemote(description) {\n  return description.toLowerCase().includes('remote') || \n         description.toLowerCase().includes('work from home') ||\n         description.toLowerCase().includes('telecommute');\n}\n\nfunction extractSalary(salary) {\n  if (!salary) return 'Not specified';\n  // Clean and format salary information\n  return salary.replace(/[^0-9$,k-]/gi, '').substring(0, 50);\n}\n\nreturn uniqueJobs;"
      },
      "typeVersion": 2
    },
    {
      "id": "format_telegram_message",
      "name": "채용 정보 메시지 포맷팅",
      "type": "n8n-nodes-base.code",
      "position": [
        1580,
        350
      ],
      "parameters": {
        "jsCode": "// Format jobs for Telegram message\nconst items = $input.all();\nlet chatId, userName, summary;\nconst jobs = [];\n\n// Separate summary from jobs\nfor (const item of items) {\n  if (item.json.is_summary) {\n    summary = item.json;\n    chatId = item.json.telegram_chat_id;\n    userName = item.json.telegram_user;\n  } else {\n    jobs.push(item.json);\n  }\n}\n\nif (jobs.length === 0) {\n  return [{\n    json: {\n      telegram_chat_id: chatId,\n      telegram_message: `😞 **No Jobs Found**\\n\\n*Sorry ${userName}, I couldn't find any relevant job opportunities for your search.*\\n\\n*Try different keywords or locations!*`,\n      has_jobs: false\n    }\n  }];\n}\n\n// Create formatted message\nlet message = `🎯 **Job Search Results** 🎯\\n\\n`;\nmessage += `*Found ${summary.total_jobs_found} relevant opportunities*\\n`;\nmessage += `*Platforms: ${summary.platforms_searched.join(', ')}*\\n`;\nmessage += `*Remote jobs: ${summary.remote_jobs}*\\n\\n`;\nmessage += `───────────────────\\n\\n`;\n\n// Format individual jobs\nfor (let i = 0; i < Math.min(jobs.length, 5); i++) {\n  const job = jobs[i];\n  const platformIcon = {\n    'linkedin': '💼',\n    'indeed': '🔍', \n    'monster': '👹'\n  }[job.platform] || '💼';\n  \n  message += `${platformIcon} **${job.title}**\\n`;\n  message += `🏢 *${job.company}*\\n`;\n  message += `📍 ${job.location}\\n`;\n  \n  if (job.salary_range && job.salary_range !== 'Not specified') {\n    message += `💰 ${job.salary_range}\\n`;\n  }\n  \n  if (job.remote_option) {\n    message += `🌐 *Remote Available*\\n`;\n  }\n  \n  message += `📊 *${job.experience_level} level*\\n`;\n  \n  if (job.url) {\n    message += `🔗 [Apply Now](${job.url})\\n`;\n  }\n  \n  message += `\\n───────────────────\\n\\n`;\n}\n\nif (jobs.length > 5) {\n  message += `*... and ${jobs.length - 5} more jobs available!*\\n\\n`;\n}\n\nmessage += `⚡ *Use /jobs [keyword] [location] for new search*\\n`;\nmessage += `💾 *Jobs saved to Google Sheets & Airtable*`;\n\nreturn [{\n  json: {\n    telegram_chat_id: chatId,\n    telegram_message: message,\n    has_jobs: true,\n    job_count: jobs.length,\n    formatted_jobs: jobs.slice(0, 5)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "send_job_results",
      "name": "채용 결과 전송",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1800,
        350
      ],
      "parameters": {
        "text": "={{$json.telegram_message}}",
        "chatId": "={{$json.telegram_chat_id}}",
        "options": {
          "disable_web_page_preview": true
        },
        "resource": "message",
        "operation": "sendMessage",
        "parseMode": "Markdown"
      },
      "credentials": {
        "telegramApi": {
          "id": "telegram_bot_credentials",
          "name": "Job Scraper Bot"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "telegram_google_sheets",
      "name": "Google 시트에 저장",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1580,
        500
      ],
      "parameters": {
        "options": {
          "useAppend": true
        },
        "operation": "appendOrUpdate",
        "sheetName": "Telegram_Jobs",
        "documentId": "your_google_sheet_id",
        "authentication": "oAuth2",
        "columnToMatchOn": "job_id"
      },
      "typeVersion": 4
    },
    {
      "id": "telegram_airtable",
      "name": "Airtable에 저장",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1580,
        600
      ],
      "parameters": {
        "baseId": "your_airtable_base_id",
        "options": {
          "bulkSize": 10,
          "ignoreMissingColumns": true
        },
        "tableId": "telegram_jobs_table",
        "operation": "create",
        "authentication": "airtableTokenApi"
      },
      "typeVersion": 2
    },
    {
      "id": "usage_analytics",
      "name": "사용 분석 로깅",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1800,
        500
      ],
      "parameters": {
        "url": "https://hooks.zapier.com/hooks/catch/YOUR_WEBHOOK_ID/",
        "method": "POST",
        "options": {
          "timeout": 10000
        },
        "jsonBody": "={{ {\n  \"user_id\": $json.telegram_user,\n  \"chat_id\": $json.telegram_chat_id,\n  \"search_query\": $json.search_query,\n  \"jobs_found\": $json.job_count,\n  \"timestamp\": $json.search_timestamp,\n  \"platform\": \"telegram\",\n  \"workflow\": \"job_search\"\n} }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    }
  ],
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "saveManualExecutions": true
  },
  "updatedAt": "2025-09-05T11:41:00.000Z",
  "versionId": "2",
  "staticData": {},
  "connections": {
    "telegram_command_filter": {
      "main": [
        [
          {
            "node": "welcome_message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "job_search_filter": {
      "main": [
        [
          {
            "node": "parse_job_command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "parse_job_command": {
      "main": [
        [
          {
            "node": "search_status_message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "search_status_message": {
      "main": [
        [
          {
            "node": "linkedin_scraper_telegram",
            "type": "main",
            "index": 0
          },
          {
            "node": "indeed_scraper_telegram",
            "type": "main",
            "index": 0
          },
          {
            "node": "monster_scraper_telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "format_telegram_message": {
      "main": [
        [
          {
            "node": "send_job_results",
            "type": "main",
            "index": 0
          },
          {
            "node": "usage_analytics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "indeed_scraper_telegram": {
      "main": [
        [
          {
            "node": "telegram_job_processor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "monster_scraper_telegram": {
      "main": [
        [
          {
            "node": "telegram_job_processor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "telegram_trigger": {
      "main": [
        [
          {
            "node": "telegram_command_filter",
            "type": "main",
            "index": 0
          },
          {
            "node": "job_search_filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "linkedin_scraper_telegram": {
      "main": [
        [
          {
            "node": "telegram_job_processor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "telegram_job_processor": {
      "main": [
        [
          {
            "node": "format_telegram_message",
            "type": "main",
            "index": 0
          },
          {
            "node": "telegram_google_sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "telegram_airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 1
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

중급 - 기타, AI 챗봇, 멀티모달 AI

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
중급
노드 수15
카테고리3
노드 유형7
난이도 설명

일정 경험을 가진 사용자를 위한 6-15개 노드의 중간 복잡도 워크플로우

저자
n8n Automation Expert | Template Creator | 2+ Years Experience

n8n Automation Expert | Template Creator | 2+ Years Experience

@tegarkaruniailham

Helping business owners & marketers automate their processes with n8n. Specialist in custom workflows, API integrations, and template development. 📈 100+ successful automation projects 🔧 Premium n8n templates available 💡 Free consultation for custom automation Book a consultation for your business digital transformation!"

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34