Jobfinder-Telegram-Bot: KI-gestützter LinkedIn-, Indeed- und Monster-Scraper
Dies ist ein Miscellaneous, AI Chatbot, Multimodal AI-Bereich Automatisierungsworkflow mit 15 Nodes. Hauptsächlich werden Code, Filter, Airtable, Telegram, HttpRequest und andere Nodes verwendet. KI-basierter Telegram-Bot, der LinkedIn-, Indeed- und Monster-Stelleninformationen scrapet
- •Airtable API Key
- •Telegram Bot Token
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
- •Google Sheets API-Anmeldedaten
Verwendete Nodes (15)
{
"meta": {
"version": "2.0",
"instanceId": "workflow_job_scraper_telegram"
},
"tags": [
"telegram",
"job-scraping",
"sales",
"marketing",
"automation",
"ai"
],
"nodes": [
{
"id": "telegram_trigger",
"name": "Telegram Bot Trigger",
"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": "Command Filter",
"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": "Job Search Filter",
"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": "Send Welcome Message",
"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": "Parse Job Command",
"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": "Send Search Status",
"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 Jobs Scraper",
"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 Jobs Scraper",
"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 Jobs Scraper",
"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": "Process Jobs for 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": "Format Jobs Message",
"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": "Send Job Results",
"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": "Save to Google Tabellen",
"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": "Save to 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": "Log Usage Analytics",
"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": "Save to Google Sheets",
"type": "main",
"index": 0
},
{
"node": "telegram_airtable",
"type": "main",
"index": 0
}
]
]
}
},
"triggerCount": 1
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Fortgeschritten - Verschiedenes, KI-Chatbot, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
n8n Automation Expert | Template Creator | 2+ Years Experience
@tegarkaruniailhamHelping 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!"
Diesen Workflow teilen