通过 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 Sheets",
      "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": {
    "Command Filter": {
      "main": [
        [
          {
            "node": "Send Welcome Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Job Search Filter": {
      "main": [
        [
          {
            "node": "Parse Job Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Job Command": {
      "main": [
        [
          {
            "node": "Send Search Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Search Status": {
      "main": [
        [
          {
            "node": "LinkedIn Jobs Scraper",
            "type": "main",
            "index": 0
          },
          {
            "node": "Indeed Jobs Scraper",
            "type": "main",
            "index": 0
          },
          {
            "node": "Monster Jobs Scraper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Jobs Message": {
      "main": [
        [
          {
            "node": "Send Job Results",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Usage Analytics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Indeed Jobs Scraper": {
      "main": [
        [
          {
            "node": "Process Jobs for Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Monster Jobs Scraper": {
      "main": [
        [
          {
            "node": "Process Jobs for Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Bot Trigger": {
      "main": [
        [
          {
            "node": "Command Filter",
            "type": "main",
            "index": 0
          },
          {
            "node": "Job Search Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LinkedIn Jobs Scraper": {
      "main": [
        [
          {
            "node": "Process Jobs for Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Jobs for Telegram": {
      "main": [
        [
          {
            "node": "Format Jobs Message",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save to Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save to Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 1
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

这是一个中级难度的工作流,适用于Miscellaneous、AI Chatbot、Multimodal AI等场景。适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 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 上查看 →

分享此工作流