使用 Mistral AI、LinkedIn 和 Google Sheets 自动化职位搜索与简历定制
高级
这是一个Personal Productivity, AI Summarization领域的自动化工作流,包含 46 个节点。主要使用 Set, Code, Html, Sort, Wait 等节点。 使用 Mistral AI、LinkedIn 和 Google Sheets 自动化职位搜索与简历定制
前置要求
- •Google 账号和 Gmail API 凭证
- •Google Drive API 凭证
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
使用的节点 (46)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"meta": {
"instanceId": "b8bca2081b6c394c24ae4b81e9aa6d613d549c27564693b18550c263bcbb0c03",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "e08473bb-0b75-4ceb-81c0-92be71165fb4",
"name": "Mistral Cloud Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
"position": [
-1968,
2048
],
"parameters": {
"model": "mistral-small-latest",
"options": {}
},
"typeVersion": 1
},
{
"id": "6716f4ea-2529-4665-bdfa-8943a8cd5ffc",
"name": "HTML2",
"type": "n8n-nodes-base.html",
"position": [
-1056,
2368
],
"parameters": {
"options": {},
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "Title",
"cssSelector": "div h1"
},
{
"key": "Company",
"cssSelector": "div span a"
},
{
"key": "Location",
"cssSelector": "div span[class*='topcard__flavor topcard__flavor--bullet']"
},
{
"key": "Description",
"cssSelector": "div.description__text.description__text--rich"
},
{
"key": "Job ID",
"attribute": "data-semaphore-content-urn",
"cssSelector": "a[data-item-type='semaphore']",
"returnValue": "attribute"
},
{
"key": "Salary",
"cssSelector": "div.salary.compensation__salary"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "01e0b4e5-4b4d-4102-8a67-a1c0ab90717a",
"name": "分离输出",
"type": "n8n-nodes-base.splitOut",
"position": [
-880,
1920
],
"parameters": {
"options": {},
"fieldToSplitOut": "jobs"
},
"typeVersion": 1
},
{
"id": "7214a29b-f4d2-456a-a77e-15938361a61e",
"name": "遍历项目",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-400,
2080
],
"parameters": {
"options": {}
},
"executeOnce": true,
"typeVersion": 3
},
{
"id": "244d669c-b275-47ce-ade8-bf33dd5761f5",
"name": "发送消息",
"type": "n8n-nodes-base.gmail",
"position": [
528,
2000
],
"webhookId": "2a252ec0-2b36-4a2a-a502-9adf5e5c9752",
"parameters": {
"sendTo": "[YOUR_EMAIL_ADDRESS]",
"message": "=<p style=\"font-family: Arial, sans-serif; color: #333333;\">\\n Dear Job Seeker,<br><br>\\n This daily digest summarizes the results of your automated job search. The Top 5 job matches found in today's run are detailed below, with comprehensive analysis available in your tracking sheet.\\n</p>\\n\\n<div style=\"margin-top: 20px;\">\\n <h3 style=\"font-family: Arial, sans-serif; color: #0077b5; border-bottom: 2px solid #eeeeee; padding-bottom: 5px;\">\\n 🏆 Top 5 Job Matches\\n </h3>\\n\\n {{ $json.data.map((item, index) => {\\n // Safely replace newlines in Improvements\\n const improvements = item.Improvements ? item.Improvements.replace(/\\n/g, '<br>').replace(/\"/g, '"') : 'N/A';\\n \\n // Choose alternating background color\\n const bgColor = index % 2 === 0 ? '#f4f4f4' : '#ffffff';\\n \\n // Determine score color for visual emphasis\\n const score = parseInt(item.Score) || 0;\\n const scoreColor = score >= 80 ? 'green' : (score >= 60 ? 'orange' : 'red');\\n\\n // Extract the first improvement point\\n const topImprovement = improvements.split('<br>')[0] || 'No specific top improvement listed.';\\n\\n return `\\n <div style=\"border: 1px solid #dddddd; padding: 15px; margin-bottom: 20px; border-radius: 8px; background-color: ${bgColor};\">\\n <h4 style=\"margin-top: 0; color: #333333;\">\\n ${index + 1}. ${item.Title} @ ${item.Company}\\n </h4>\\n <p style=\"margin: 5px 0; font-family: Arial, sans-serif; font-size: 14px;\">\\n <strong>Match Score:</strong> <strong style=\"color: ${scoreColor}; font-weight: bold;\">${item.Score}/100</strong>\\n | <strong>Location:</strong> ${item.Location}\\n | <strong>Salary:</strong> ${item['Salary '] || 'N/A'}\\n </p>\\n <p style=\"margin: 10px 0; font-family: Arial, sans-serif;\">\\n <a href=\"${item.Link}\" style=\"color: #0077b5; text-decoration: none; font-weight: bold;\">[View Job & Apply]</a>\\n </p>\\n \\n <div style=\"margin-top: 15px; padding: 10px; border-top: 1px dashed #cccccc;\">\\n <h5 style=\"color: #555555; margin-bottom: 5px; font-size: 14px;\">Top Resume Improvement Action:</h5>\\n <span style=\"font-size: 13px; color: #555; white-space: pre-wrap;\">${topImprovement}</span>\\n </div>\\n </div>\\n `;\\n }).join('') }}\\n</div>\\n\\n<p style=\"font-family: Arial, sans-serif; color: #333333; margin-top: 30px;\">\\n Access the full, filterable list and detailed notes for all jobs (including full cover letters, red flags, and more) here:<br>\\n <a href=\"[YOUR_GOOGLE_SHEET_LINK]\" style=\"color: #0077b5; text-decoration: none; font-weight: bold; font-size: 16px; display: inline-block; margin-top: 8px;\">\\n 🚀 Open Job Search Tracking Sheet\\n </a>\\n</p>\\n<p style=\"font-family: Arial, sans-serif; color: #333333; margin-top: 20px;\">\\n Best of luck with your job search!\\n</p>",
"options": {
"appendAttribution": false
},
"subject": "Job Match Results"
},
"typeVersion": 2.1
},
{
"id": "e1a36beb-28ad-40c6-b534-28c9e84a5b9c",
"name": "结构化输出解析器",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-1824,
2048
],
"parameters": {
"jsonSchemaExample": "{\n\t\"keyword\": \"Maintenance Manager\",\n\t\"location\": \"Los Angeles\",\n\t\"experiencelevel\": \"Mid-Senior Level\",\n\t\"remote\": \"No\",\n\t\"alternatekeyword\": \"Engineering Manager\",\n\t\"alternatekeyword1\": \"Engineering Manager\",\n\t\"alternatekeyword2\": \"Engineering Manager\"\n\n}"
},
"typeVersion": 1.3
},
{
"id": "933481cf-5018-489b-8679-43faf6c21791",
"name": "合并",
"type": "n8n-nodes-base.merge",
"position": [
-1248,
1888
],
"parameters": {
"numberInputs": 4
},
"typeVersion": 3.2
},
{
"id": "92eda0a2-50f8-43e8-946b-52014ad79eeb",
"name": "Mistral Cloud Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
"position": [
-192,
2624
],
"parameters": {
"model": "mistral-large-latest",
"options": {}
},
"typeVersion": 1
},
{
"id": "65b3a2cd-d78b-4f44-9bd1-16be870bf431",
"name": "简历解析",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-1968,
1840
],
"parameters": {
"text": "=You are a resume review AI Agent.\\n\\nUse {{ $json.text }} to provide the following outputs;\\n-Keyword, main job title. Pick the top single job title based on this resume. This must not include the word \"and\". Focus on the industry or job area relevant in the resume.\\n-Alternate Keyword, list other possible job titles. Only list the top 3. This must not include the word \"and\". \\n-Location of Job Desired, if no desired location is provided use the current address city.\\n-Experience Level, Pick one of the following Internship, Entry Level, Associate, Mid-Senior Level, Director, Executive\\n-Remote, Choose one, On-Site, Hybrid, Remote. If not specified respond \"On-Site\".",
"options": {},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.2
},
{
"id": "7a0078d7-8566-465c-ae95-6287ec352ca3",
"name": "职位匹配 AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-192,
2208
],
"parameters": {
"text": "=You are a precise job-matching and content generation expert. Your task is to analyze a resume against a job description, compute a match score, provide actionable feedback, and draft a cover letter.\\n\\nReturn **EXACTLY ONE JSON** object wrapped in ```json fences, followed by the line END_OF_JSON. Do NOT include any introductory or concluding prose.\\n\\nINPUT DATA\\njob_description: {{ $json.Description }}\\nmy_resume: {{ $('Extract from Resume1').item.json.text }}\\n\\nTASKS\\n1) JOB ANALYSIS: Extract and structure the following data from the job_description.\\n2) RESUME ANALYSIS: Extract and structure the following data from the my_resume.\\n3) MATCH SCORING (integer 0–100): Calculate the score based on the weighted categories provided below. Deduct up to 10 points for issues listed in red_flags.\\n - Skills/Tools overlap: 40 points\\n - Relevant experience & seniority: 25 points\\n - Responsibilities alignment: 15 points\\n - Education/Certs fit: 10 points\\n - Domain/industry fit: 5 points\\n - Logistics (location/work auth/availability): 5 points\\n4) SCORE EXPLANATION: For each category, provide 1–3 *concise* evidence bullets. Quote short, relevant fragments (escape quotes) and cite \"JD\" or \"Resume\".\\n5) GAPS & SUGGESTIONS: Identify missing/weak requirements and list 1–2 concrete upskilling steps for each.\\n6) COVER LETTER: Generate a professional, highly-tailored cover letter (150–220 words, 2–4 paragraphs). Focus on concrete impacts. **Must use JSON-safe formatting:** escape all double quotes as \\\" and use \\n for newlines. Omit greeting and signature.\\n\\nSTRICT FORMATTING RULES\\n- All array elements must be **short phrases (≤ 140 characters)**, single line, with NO markdown, line breaks, asterisks, or list indicators. Summarize long paragraphs.\\n- Ensure all key-value pairs adhere strictly to the schema below.\\n\\nSCHEMA\\n```json\\n{\\n \\\"job_analysis\\\": {\\n \\\"title\\\": \\\"\\\",\\n \\\"company\\\": \\\"\\\",\\n \\\"must_have_skills\\\": [],\\n \\\"nice_to_have_skills\\\": [],\\n \\\"responsibilities\\\": [],\\n \\\"years_of_experience\\\": \\\"\\\",\\n \\\"education_certifications\\\": \\\"\\\",\\n \\\"location_constraints\\\": \\\"\\\",\\n \\\"domain_industry_focus\\\": \\\"\\\",\\n \\\"tech_stack\\\": [],\\n \\\"measurable_kpis\\\": [],\\n \\\"relocation_requirement\\\": \\\"\\\"\\n },\\n \\\"resume_analysis\\\": {\\n \\\"core_skills\\\": [],\\n \\\"tools_tech\\\": {\\n \\\"programming_languages\\\": [],\\n \\\"frontend_technologies\\\": [],\\n \\\"backend_technologies\\\": [],\\n \\\"databases_devops\\\": []\\n },\\n \\\"years_of_experience_key_areas\\\": {},\\n \\\"accomplishments_with_metrics\\\": [],\\n \\\"education_certs\\\": [],\\n \\\"domains\\\": [],\\n \\\"roles_titles\\\": [],\\n \\\"leadership_collaboration\\\": [],\\n \\\"location_work_auth\\\": \\\"\\\"\\n },\\n \\\"match_score\\\": 0,\\n \\\"score_explanation\\\": [\\n { \\\"category\\\": \\\"Skills/Tools overlap (40 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] },\\n { \\\"category\\\": \\\"Relevant experience depth & seniority (25 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] },\\n { \\\"category\\\": \\\"Responsibilities alignment (15 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] },\\n { \\\"category\\\": \\\"Education/Certs fit (10 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] },\\n { \\\"category\\\": \\\"Domain/industry fit (5 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] },\\n { \\\"category\\\": \\\"Logistics (location, work auth, availability) (5 points)\\\", \\\"score\\\": 0, \\\"evidence\\\": [] }\\n ],\\n \\\"red_flags\\\": [],\\n \\\"gaps_and_suggestions\\\": [\\n { \\\"gap\\\": \\\"\\\", \\\"suggestion\\\": \\\"\\\" }\\n ],\\n \\\"cover_letter\\\": \\\"\\\"\\n}",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "676d5633-9739-4c84-8607-836941b42162",
"name": "简历分析 AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-192,
2416
],
"parameters": {
"text": "=You are a ruthless resume editor. Your sole output must be a crisp, numbered list of actionable resume changes to maximize job fit.\\n\\nInputs:\\n\\njob_description: {{ $json.Description }}\\n\\nmy_resume: {{ $('Extract from Resume1').item.json.text }}\\n\\nSTRICT OUTPUT RULES:\\n\\nOutput a numbered list only; start with the highest-impact change.\\n\\nEach point must be a single line of 14 words or less.\\n\\nEach line must start with one of the following tags: [ADD], [REMOVE], [REWRITE], [ORDER], [QUANTIFY], [KEYWORDS], [FORMAT], [FOCUS].\\n\\nAll points must be based on genuine gaps against the job_description. Do not invent experience.\\n\\nInclude a final, single line for keywords: 'Missing keywords: term1, term2, ...' (list only if any).\\n\\nNo intros, explanations, code fences, bullet points, or any extra text.",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "5f720ba5-cccd-4428-a948-d74dbd02e9ba",
"name": "获取职位搜索表中的行",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1024,
1584
],
"parameters": {
"options": {},
"sheetName": "[YOUR_SHEET_NAME]",
"documentId": "[YOUR_SPREADSHEET_ID]"
},
"executeOnce": true,
"typeVersion": 4.7
},
{
"id": "6d15572d-5eb3-4959-b8ae-df09c4746d27",
"name": "在职位搜索表中追加或更新行",
"type": "n8n-nodes-base.googleSheets",
"position": [
112,
2416
],
"parameters": {
"columns": {
"value": {
"Link": "={{ $('Edit Fields2').item.json['Apply Link'] }}",
"Score": "={{ $('Edit Fields3').item.json.match_score }}",
"Title": "={{ $('Edit Fields3').item.json.job_analysis.title }}",
"Skills": "={{ $('Edit Fields3').item.json.resume_analysis.core_skills.join('\\n') }}",
"Company": "={{ $('Edit Fields2').item.json.Company }}",
"Salary ": "={{ $('Edit Fields2').item.json.Salary }}",
"Location": "={{ $('Edit Fields2').item.json.Location }}",
"Red Flags": "={{ $('Edit Fields3').item.json.red_flags.map((flag, index) => `${index + 1}. ${flag}`).join('\\n') }}",
"Cover Letter": "={{ $('Edit Fields3').item.json.cover_letter }}",
"Improvements": "={{ $json.output }}",
"Relocation Requirement": "={{ $('Edit Fields3').item.json.job_analysis.relocation_requirement }} "
},
"schema": [
{
"id": "Link",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Title",
"type": "string",
"display": true,
"required": false,
"displayName": "Title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company",
"type": "string",
"display": true,
"required": false,
"displayName": "Company",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Location",
"type": "string",
"display": true,
"required": false,
"displayName": "Location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Score",
"type": "string",
"display": true,
"required": false,
"displayName": "Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cover Letter",
"type": "string",
"display": true,
"required": false,
"displayName": "Cover Letter",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Skills",
"type": "string",
"display": true,
"required": false,
"displayName": "Skills",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Improvements",
"type": "string",
"display": true,
"required": false,
"displayName": "Improvements",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Red Flags",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Red Flags",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Relocation Requirement",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Relocation Requirement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Salary ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Salary ",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Link"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": "[YOUR_SHEET_NAME]",
"documentId": "[YOUR_SPREADSHEET_ID]"
},
"typeVersion": 4.7
},
{
"id": "fe0bc527-e772-4c99-9566-aef4cadefc55",
"name": "从简历中提取信息",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-2112,
1840
],
"parameters": {
"options": {},
"operation": "pdf"
},
"typeVersion": 1
},
{
"id": "571dd21c-635a-4198-9013-37670859bcf0",
"name": "下载简历",
"type": "n8n-nodes-base.googleDrive",
"position": [
-1872,
1584
],
"parameters": {
"fileId": "[YOUR_RESUME_DRIVE_URL]",
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "90041e96-9f01-497c-bea3-1c8cb1d4cf1d",
"name": "定时触发器",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-2048,
1584
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 12,
"triggerAtMinute": 45
}
]
}
},
"typeVersion": 1.2
},
{
"id": "65c5c979-8b77-47c5-856b-68a6d8e24203",
"name": "数据集比较",
"type": "n8n-nodes-base.compareDatasets",
"position": [
-624,
2000
],
"parameters": {
"options": {},
"fuzzyCompare": true,
"mergeByFields": {
"values": [
{
"field1": "Link",
"field2": "Apply Link"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "a80f67f7-8dde-45f7-ba11-74db416877ea",
"name": "LinkedIn 搜索 URL",
"type": "n8n-nodes-base.code",
"position": [
-1616,
1696
],
"parameters": {
"jsCode": "let url = \"https://www.linkedin.com/jobs/search/?f_TPR=r86400\"\\n\\nconst keyword = $input.first().json.output.keyword\\nconst location = $input.first().json.output.location\\nconst experienceLevel = $input.first().json.output.experiencelevel\\nconst remote = $input.first().json.output.remote\\n\\n\\n\\nif (keyword != \"\") {\\n url += `&keywords=${keyword}`;\\n}\\n\\nif (location != \"\") {\\n url += `&location=${location}`;\\n}\\n\\nif (experienceLevel !== \"\") {\\n // Transform experience levels to LinkedIn codes\\n // Internship -> 1, Entry level -> 2, Associate -> 3\\n // Mid-Senior level -> 4, Director -> 5, Executive -> 6\\n const transformedExperiences = experienceLevel\\n .split(\",\")\\n .map((exp) => {\\n switch (exp.trim()) {\\n case \"Director\": return \"5\";\\n case \"Mid-Senior Level\": return \"4\";\\n case \"Internship\": return \"1\";\\n case \"Entry Level\": return \"2\";\\n case \"Associate\": return \"3\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_E=${transformedExperiences.join(\",\")}`;\\n}\\n\\nif (remote.length != \"\") {\\n // Transform remote options to LinkedIn codes\\n // On-Site -> 1, Remote -> 2, Hybrid -> 3\\n const transformedRemote = remote\\n .split(\",\")\\n .map((e) => {\\n switch (e.trim()) {\\n case \"Remote\": return \"2\";\\n case \"Hybrid\": return \"3\";\\n case \"On-Site\": return \"1\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_WT=${transformedRemote.join(\",\")}`;\\n}\\n\\n\\n\\n\\nreturn {url}\\n"
},
"typeVersion": 2
},
{
"id": "361256c2-5e01-4195-bc02-c8d7071a9356",
"name": "LinkedIn 搜索 URL5",
"type": "n8n-nodes-base.code",
"position": [
-1616,
1840
],
"parameters": {
"jsCode": "let url = \"https://www.linkedin.com/jobs/search/?f_TPR=r86400\"\\n\\nconst keyword = $input.first().json.output.alternatekeyword\\nconst location = $input.first().json.output.location\\nconst experienceLevel = $input.first().json.output.experiencelevel\\nconst remote = $input.first().json.output.remote\\n\\n\\n\\nif (keyword != \"\") {\\n url += `&keywords=${keyword}`;\\n}\\n\\nif (location != \"\") {\\n url += `&location=${location}`;\\n}\\n\\nif (experienceLevel !== \"\") {\\n // Transform experience levels to LinkedIn codes\\n // Internship -> 1, Entry level -> 2, Associate -> 3\\n // Mid-Senior level -> 4, Director -> 5, Executive -> 6\\n const transformedExperiences = experienceLevel\\n .split(\",\")\\n .map((exp) => {\\n switch (exp.trim()) {\\n case \"Director\": return \"5\";\\n case \"Mid-Senior Level\": return \"4\";\\n case \"Internship\": return \"1\";\\n case \"New Grad\": return \"3\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_E=${transformedExperiences.join(\",\")}`;\\n}\\n\\nif (remote.length != \"\") {\\n // Transform remote options to LinkedIn codes\\n // On-Site -> 1, Remote -> 2, Hybrid -> 3\\n const transformedRemote = remote\\n .split(\",\")\\n .map((e) => {\\n switch (e.trim()) {\\n case \"Remote\": return \"2\";\\n case \"Hybrid\": return \"3\";\\n case \"On-Site\": return \"1\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_WT=${transformedRemote.join(\",\")}`;\\n}\\n\\n\\n\\nreturn {url}\\n"
},
"typeVersion": 2
},
{
"id": "454faa82-eee8-4faa-b9e9-c6832452fbc6",
"name": "LinkedIn 搜索 URL6",
"type": "n8n-nodes-base.code",
"position": [
-1616,
1984
],
"parameters": {
"jsCode": "let url = \"https://www.linkedin.com/jobs/search/?f_TPR=r86400\"\\n\\nconst keyword = $input.first().json.output.alternatekeyword1\\nconst location = $input.first().json.output.location\\nconst experienceLevel = $input.first().json.output.experiencelevel\\nconst remote = $input.first().json.output.remote\\n\\n\\n\\nif (keyword != \"\") {\\n url += `&keywords=${keyword}`;\\n}\\n\\nif (location != \"\") {\\n url += `&location=${location}`;\\n}\\n\\nif (experienceLevel !== \"\") {\\n // Transform experience levels to LinkedIn codes\\n // Internship -> 1, Entry level -> 2, Associate -> 3\\n // Mid-Senior level -> 4, Director -> 5, Executive -> 6\\n const transformedExperiences = experienceLevel\\n .split(\",\")\\n .map((exp) => {\\n switch (exp.trim()) {\\n case \"Director\": return \"5\";\\n case \"Mid-Senior Level\": return \"4\";\\n case \"Internship\": return \"1\";\\n case \"Entry Level\": return \"2\";\\n case \"New Grad\": return \"3\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_E=${transformedExperiences.join(\",\")}`;\\n}\\n\\nif (remote.length != \"\") {\\n // Transform remote options to LinkedIn codes\\n // On-Site -> 1, Remote -> 2, Hybrid -> 3\\n const transformedRemote = remote\\n .split(\",\")\\n .map((e) => {\\n switch (e.trim()) {\\n case \"Remote\": return \"2\";\\n case \"Hybrid\": return \"3\";\\n case \"On-Site\": return \"1\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_WT=${transformedRemote.join(\",\")}`;\\n}\\n\\n\\n\\n\\nreturn {url}\\n"
},
"typeVersion": 2
},
{
"id": "b109d1ed-191b-4d6d-a1a9-40add6168f5b",
"name": "LinkedIn 搜索 URL7",
"type": "n8n-nodes-base.code",
"position": [
-1616,
2128
],
"parameters": {
"jsCode": "let url = \"https://www.linkedin.com/jobs/search/?f_TPR=r86400\"\\n\\nconst keyword = $input.first().json.output.alternatekeyword2\\nconst location = $input.first().json.output.location\\nconst experienceLevel = $input.first().json.output.experiencelevel\\nconst remote = $input.first().json.output.remote\\n\\n\\n\\nif (keyword != \"\") {\\n url += `&keywords=${keyword}`;\\n}\\n\\nif (location != \"\") {\\n url += `&location=${location}`;\\n}\\n\\nif (experienceLevel !== \"\") {\\n // Transform experience levels to LinkedIn codes\\n // Internship -> 1, Entry level -> 2, Associate -> 3\\n // Mid-Senior level -> 4, Director -> 5, Executive -> 6\\n const transformedExperiences = experienceLevel\\n .split(\",\")\\n .map((exp) => {\\n switch (exp.trim()) {\\n case \"Director\": return \"5\";\\n case \"Mid-Senior Level\": return \"4\";\\n case \"Internship\": return \"1\";\\n case \"New Grad\": return \"3\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_E=${transformedExperiences.join(\",\")}`;\\n}\\n\\nif (remote.length != \"\") {\\n // Transform remote options to LinkedIn codes\\n // On-Site -> 1, Remote -> 2, Hybrid -> 3\\n const transformedRemote = remote\\n .split(\",\")\\n .map((e) => {\\n switch (e.trim()) {\\n case \"Remote\": return \"2\";\\n case \"Hybrid\": return \"3\";\\n case \"On-Site\": return \"1\";\\n default: return \"\";\\n }\\n })\\n .filter(Boolean);\\n url += `&f_WT=${transformedRemote.join(\",\")}`;\\n}\\n\\n\\n\\n\\nreturn {url}\\n"
},
"typeVersion": 2
},
{
"id": "e11488d7-d8c2-4924-a092-b67db957ecee",
"name": "从 LinkedIn 获取职位",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1440,
1696
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 3000
},
{
"id": "f4e30a7b-74ed-426d-a73c-9edef904edee",
"name": "从 LinkedIn 获取职位3",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1440,
1840
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 3000
},
{
"id": "a0af0c7d-d6e5-47bc-a92b-dc8ae23736fc",
"name": "从 LinkedIn 获取职位",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1440,
1984
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 3000
},
{
"id": "1b86a6e1-e74b-45e5-a044-7061a4217c53",
"name": "从 LinkedIn 获取职位5",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1440,
2128
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 3000
},
{
"id": "1e4498be-6780-4dd8-8229-1916a31b6779",
"name": "等待1",
"type": "n8n-nodes-base.wait",
"position": [
-1056,
2192
],
"webhookId": "1f33d10b-6071-480b-865b-835b93a7841d",
"parameters": {
"amount": 3
},
"typeVersion": 1.1
},
{
"id": "cb0aa113-f1ec-42ad-b0da-afc039c7ba27",
"name": "HTTP 请求",
"type": "n8n-nodes-base.httpRequest",
"position": [
-880,
2192
],
"parameters": {
"url": "={{ $json.jobs }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 5
},
{
"id": "c61f2149-3375-44eb-8d2c-4abfcec7ecea",
"name": "HTML3",
"type": "n8n-nodes-base.html",
"position": [
-1056,
1920
],
"parameters": {
"options": {},
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "jobs",
"attribute": "href",
"cssSelector": "ul.jobs-search__results-list li div a[class*=\"base-card\"]",
"returnArray": true,
"returnValue": "attribute"
}
]
}
},
"retryOnFail": true,
"typeVersion": 1.2
},
{
"id": "ba3ae6dd-5525-46e6-8afd-64f370a6707c",
"name": "遍历项目3",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-1232,
2144
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "c60ca1ba-ce73-4769-a71b-46729ed0ec68",
"name": "编辑字段2",
"type": "n8n-nodes-base.set",
"position": [
-880,
2368
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "240418dc-3349-48d5-ba59-3aa590d71950",
"name": "Description",
"type": "string",
"value": "={{ $json.Description.replaceAll(/\\s+/g, \" \")}}"
},
{
"id": "7b24938f-8b47-488d-9f65-54d036dcffd5",
"name": "Job ID",
"type": "string",
"value": "={{ $json['Job ID'].split(\":\").last() }}"
},
{
"id": "d6addada-9e01-464f-a768-c19f6224c491",
"name": "Apply Link",
"type": "string",
"value": "={{ \"https://www.linkedin.com/jobs/view/\"+ $json['Job ID'].split(\":\").last() }}"
},
{
"id": "21c89d3a-c8b6-44eb-9719-9ae5716a7c76",
"name": "Title",
"type": "string",
"value": "={{ $json.Title }}"
},
{
"id": "da713845-9a81-486e-bff2-1613105e424d",
"name": "Company",
"type": "string",
"value": "={{ $json.Company }}"
},
{
"id": "1a9a31dd-8d51-4f35-b6b6-ca8a348de5d7",
"name": "Location",
"type": "string",
"value": "={{ $json.Location }}"
},
{
"id": "f5b6b114-3896-4fef-b63c-202bf0e194d6",
"name": "Salary",
"type": "string",
"value": "={{ $json.Salary }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "627c9f8a-0f9c-4583-b15f-6fbd63fa99e1",
"name": "编辑字段",
"type": "n8n-nodes-base.set",
"position": [
96,
2208
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{ (() => {\\n // 0) Read model output from AI Agent node\\n const raw = String(($('Job Matching AI Agent1').item.json.output ?? ''));\\n\\n // 1) Strip code fences\\n let s = raw\\n .replace(/`{2,3}(?:json)?\\s*/gi, '')\\n .replace(/\\s*`{3}\\s*$/gi, '');\\n\\n // 1b) Normalize curly quotes (Gemini sometimes emits them)\\n s = s.replace(/[\\u201C\\u201D]/g, '\"').replace(/\\u2019/g, \"'\");\\n\\n // 2) Cut at END_OF_JSON if present\\n const endIdx = s.indexOf('END_OF_JSON');\\n if (endIdx !== -1) s = s.slice(0, endIdx);\\n\\n // 3) Extract first complete { ... } by brace counting\\n const start = s.indexOf('{');\\n if (start < 0) return {};\\n let depth = 0, inStr = false, esc = false, end = -1;\\n for (let i = start; i < s.length; i++) {\\n const ch = s[i];\\n if (inStr) {\\n if (esc) { esc = false; }\\n else if (ch === '\\\\') { esc = true; }\\n else if (ch === '\"') { inStr = false; }\\n } else {\\n if (ch === '\"') inStr = true;\\n else if (ch === '{') depth++;\\n else if (ch === '}') { depth--; if (depth === 0) { end = i + 1; break; } }\\n }\\n }\\n if (end < 0) return {};\\n\\n const cleaned = s.slice(start, end).trim();\\n\\n try {\\n return JSON.parse(cleaned); // JSON mode expects an OBJECT\\n } catch (e) {\\n // As a last resort, return an empty object to keep the run alive\\n return {};\\n }\\n})() }\\n"
},
"typeVersion": 3.4
},
{
"id": "9b639e1e-8eef-43fb-a457-dbd5cdbef864",
"name": "获取工作表中的行",
"type": "n8n-nodes-base.googleSheets",
"position": [
-192,
2000
],
"parameters": {
"options": {},
"sheetName": "[YOUR_SHEET_NAME]",
"documentId": "[YOUR_SPREADSHEET_ID]"
},
"typeVersion": 4.7
},
{
"id": "1f464b53-ccf2-45ad-8990-6c801912cebc",
"name": "排序",
"type": "n8n-nodes-base.sort",
"position": [
-16,
2000
],
"parameters": {
"options": {},
"sortFieldsUi": {
"sortField": [
{
"order": "descending",
"fieldName": "Score"
}
]
}
},
"typeVersion": 1
},
{
"id": "1e005421-67ec-4144-a705-1149443a73af",
"name": "限制1",
"type": "n8n-nodes-base.limit",
"position": [
160,
2000
],
"parameters": {
"maxItems": 5
},
"typeVersion": 1
},
{
"id": "02e430ca-d7d5-4ae2-ae72-99c51a613962",
"name": "聚合",
"type": "n8n-nodes-base.aggregate",
"position": [
336,
2000
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "201a41c3-5476-4b63-875e-34a245561231",
"name": "便签11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1824,
1424
],
"parameters": {
"color": 5,
"width": 192,
"height": 144,
"content": "## 更新"
},
"typeVersion": 1
},
{
"id": "c6c9dce9-3c79-4945-812e-4e5bcfad1437",
"name": "便签12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1008,
1424
],
"parameters": {
"color": 5,
"width": 176,
"height": 144,
"content": "## 更新"
},
"typeVersion": 1
},
{
"id": "84e3a6d4-21a6-4781-8961-53c162eb9084",
"name": "便签13",
"type": "n8n-nodes-base.stickyNote",
"position": [
288,
2432
],
"parameters": {
"color": 5,
"width": 176,
"height": 144,
"content": "## 创建"
},
"typeVersion": 1
},
{
"id": "e330aea3-2d21-4647-a691-807e24aff418",
"name": "便签14",
"type": "n8n-nodes-base.stickyNote",
"position": [
512,
1776
],
"parameters": {
"color": 5,
"width": 272,
"height": 192,
"content": "## 更新"
},
"typeVersion": 1
},
{
"id": "2417ee79-3ee9-4d9c-ac44-f10911b26148",
"name": "便签15",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
1904
],
"parameters": {
"color": 4,
"width": 320,
"height": 80,
"content": "仅关注前 5 个结果。如果您希望每封邮件显示更多结果,请将 Limit 节点更改为所需的输出数量。"
},
"typeVersion": 1
},
{
"id": "9f744607-6ba2-49a8-9ee4-14d14cffb8ac",
"name": "便签16",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
1984
],
"parameters": {
"color": 7,
"width": 976,
"content": ""
},
"typeVersion": 1
},
{
"id": "68df2a48-8d51-45f8-8d92-baea1f928d88",
"name": "便签17",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1648,
1632
],
"parameters": {
"color": 7,
"width": 336,
"height": 672,
"content": "## 职位抓取"
},
"typeVersion": 1
},
{
"id": "c9f349a1-cfa2-4884-a7da-4d3cd7bfc92a",
"name": "便签18",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1648,
2320
],
"parameters": {
"color": 4,
"width": 320,
"height": 176,
"content": "职位抓取是通过匹配您简历的 4 个关键职位标题实现的。\\n\\n提示:首次运行时搜索所有职位可能更有益。移除 \"r86400\" 以列出所有可用职位。首次成功运行后重新添加 \"r86400\" 以仅搜索过去 24 小时的职位。"
},
"typeVersion": 1
},
{
"id": "f749941b-3679-4fe3-9975-0f51a2138f31",
"name": "便签19",
"type": "n8n-nodes-base.stickyNote",
"position": [
-656,
1584
],
"parameters": {
"width": 400,
"height": 320,
"content": "# 描述"
},
"typeVersion": 1
},
{
"id": "0d8031cf-bda3-4e70-a717-9bc56634e91c",
"name": "便签20",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
2176
],
"parameters": {
"color": 7,
"width": 512,
"height": 608,
"content": ""
},
"typeVersion": 1
},
{
"id": "178064f1-34fb-4668-a92a-2b2dadbd42ae",
"name": "便签21",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
2640
],
"parameters": {
"color": 4,
"width": 208,
"height": 80,
"content": "想要个性化定制?请查看 AI 提示以获取个人指导。"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"HTML2": {
"main": [
[
{
"node": "Edit Fields2",
"type": "main",
"index": 0
}
]
]
},
"HTML3": {
"main": [
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "HTML3",
"type": "main",
"index": 0
}
]
]
},
"Sort1": {
"main": [
[
{
"node": "Limit1",
"type": "main",
"index": 0
}
]
]
},
"Wait1": {
"main": [
[
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
]
]
},
"Limit1": {
"main": [
[
{
"node": "Aggregate1",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Loop Over Items3",
"type": "main",
"index": 0
}
]
]
},
"Aggregate1": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields2": {
"main": [
[
{
"node": "Loop Over Items3",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields3": {
"main": [
[
{
"node": "Resume Analysis AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request1": {
"main": [
[
{
"node": "HTML2",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Get row(s) in sheet1",
"type": "main",
"index": 0
}
],
[
{
"node": "Job Matching AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"Download Resume1": {
"main": [
[
{
"node": "Extract from Resume1",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items3": {
"main": [
[
{
"node": "Compare Datasets1",
"type": "main",
"index": 1
}
],
[
{
"node": "Wait1",
"type": "main",
"index": 0
}
]
]
},
"Compare Datasets1": {
"main": [
[],
[],
[],
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Resume Breakdown1": {
"main": [
[
{
"node": "LinkedIn Search URL7",
"type": "main",
"index": 0
},
{
"node": "LinkedIn Search URL",
"type": "main",
"index": 0
},
{
"node": "LinkedIn Search URL5",
"type": "main",
"index": 0
},
{
"node": "LinkedIn Search URL6",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger1": {
"main": [
[
{
"node": "Download Resume1",
"type": "main",
"index": 0
},
{
"node": "Get row(s) in Job Search1",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Search URL": {
"main": [
[
{
"node": "Fetch jobs from LinkedIn",
"type": "main",
"index": 0
}
]
]
},
"Extract from Resume1": {
"main": [
[
{
"node": "Resume Breakdown1",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet1": {
"main": [
[
{
"node": "Sort1",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Search URL5": {
"main": [
[
{
"node": "Fetch jobs from LinkedIn3",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Search URL6": {
"main": [
[
{
"node": "Fetch jobs from Linkedin",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Search URL7": {
"main": [
[
{
"node": "Fetch jobs from LinkedIn5",
"type": "main",
"index": 0
}
]
]
},
"Job Matching AI Agent1": {
"main": [
[
{
"node": "Edit Fields3",
"type": "main",
"index": 0
}
]
]
},
"Fetch jobs from LinkedIn": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Fetch jobs from Linkedin": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 2
}
]
]
},
"Mistral Cloud Chat Model": {
"ai_languageModel": [
[
{
"node": "Resume Breakdown1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Resume Breakdown1",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Fetch jobs from LinkedIn3": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Fetch jobs from LinkedIn5": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 3
}
]
]
},
"Get row(s) in Job Search1": {
"main": [
[
{
"node": "Compare Datasets1",
"type": "main",
"index": 0
}
]
]
},
"Mistral Cloud Chat Model4": {
"ai_languageModel": [
[
{
"node": "Resume Analysis AI Agent1",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Job Matching AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Resume Analysis AI Agent1": {
"main": [
[
{
"node": "Append or update row in Job Search1",
"type": "main",
"index": 0
}
]
]
},
"Append or update row in Job Search1": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 个人效率, AI 摘要总结
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
其他
LinkedIn职位搜索
LinkedIn职位搜索:自动匹配简历(GPT/Gemini)+求职信生成器+Telegram提醒
If
Set
Code
+13
33 节点Hojjat Jashnniloofar
个人效率
灵活新闻聚合器 - 多源集成、AI分析和可设置频道
多源新闻策展系统,集成Mistral AI分析、摘要和自定义频道
If
Set
Xml
+32
120 节点Hybroht
内容创作
WordPress博客自动化专业版(深度研究)v2.1市场
使用GPT-4o、Perplexity AI和多语言支持自动化SEO优化的博客创建
If
Set
Xml
+27
125 节点Daniel Ng
内容创作
(Duc)深度研究市场模板
集成PerplexityAI研究和OpenAI内容的多层级WordPress博客生成器
If
Set
Xml
+28
132 节点Daniel Ng
人工智能
文件夹和子文件夹中PDF文件的文档审查
使用Mistral AI和OneDrive进行嵌套PDF文档摘要分析
If
Set
Merge
+12
50 节点Jordan Hoyle
文档提取