Finds LinkedIn Profiles using natural language
工作流概述
这是一个包含18个节点的复杂工作流,主要用于自动化处理各种任务。
工作流源代码
{
"id": "UsBaGY83vnyZjRoB",
"meta": {
"instanceId": "d4e74e27d8d0aa53cd4bdff26f47c18bb91437db0b63a6ba8ec9f78df0e0234f",
"templateId": "2808",
"templateCredsSetupCompleted": true
},
"name": "TopSourcer - Finds LinkedIn Profiles using natural language",
"tags": [],
"nodes": [
{
"id": "16a5f4a2-6e00-40f5-bab7-35526550eacd",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
3240,
-280
],
"webhookId": "88c6a5cc-4b33-438c-ba85-2e075a276a78",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "f9ff2e4f-176b-453d-8743-cab4d9fd408d",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
1040,
-180
],
"webhookId": "475042df-7c36-4658-ab1c-ff55c237621f",
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "b988c049-2400-4a3a-b615-f4048832bd8d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
980,
-340
],
"parameters": {
"content": "Click \"Open Chat\" after activating the workflow.
Here, paste in a job description or describe your ideal candidate."
},
"typeVersion": 1
},
{
"id": "74cec892-07d6-4e7d-9c6f-becfb51241c8",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1300,
-300
],
"parameters": {
"width": 300,
"content": "Under \"Credential to connect with\" add your openAI API key. Find at: https://platform.openai.com/settings/organization/api-keys
"
},
"typeVersion": 1
},
{
"id": "940373af-ca88-44f1-b3c3-fb125ab6daf9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2800,
-360
],
"parameters": {
"width": 300,
"content": "For the first condition: {{ $json.start }} is less than 50, so change \"50\" to your desired number of results.
Each loop fetches the next page, returning 10 results per iteration."
},
"typeVersion": 1
},
{
"id": "c2bc0757-753b-4fee-b42b-65e5a0ff4750",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
3160,
-440
],
"parameters": {
"color": 5,
"width": 200,
"content": "Waits 5 seconds to avoid rate limiting by Google. While it's unlikely you'll be rate-limited since you're authenticated with your cookie, this is just a precaution."
},
"typeVersion": 1
},
{
"id": "9007b42b-1a79-4b98-9d75-71894d660c1d",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
3400,
-600
],
"parameters": {
"color": 4,
"width": 380,
"height": 280,
"content": "Get this Cookie-Editor. https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm
Do a google search --> click this extension --> Export --> Header string.
Then, open this node --> under Header Auth --> edit --> and under cookie value paste in your header string.
This is to perform an authenticated google search.
"
},
"typeVersion": 1
},
{
"id": "b1d2f9dd-227d-4372-89f8-e6d54e94f2fc",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
-320
],
"parameters": {
"content": "Connect your google sheets account and create a document."
},
"typeVersion": 1
},
{
"id": "df0fb397-55d0-41ec-a9df-2c39019ad68e",
"name": "Create a new sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1740,
-180
],
"parameters": {
"title": "={{ $('Generate a Boolean Search String').item.json.choices[0].message.content.sheet_name + ' ' + $now }}
",
"options": {},
"operation": "create",
"documentId": {
"__rl": true,
"mode": "list",
"value": "1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY/edit?usp=drivesdk",
"cachedResultName": "Candidates"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6wBRjmD77d71tAqP",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "678a0b65-de67-41f0-ada6-23cef1226228",
"name": "Add columns to new sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2220,
-180
],
"parameters": {
"columns": {
"value": {},
"schema": [
{
"id": "linkedin_url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "linkedin_url",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "={{ $('Create a new sheet').item.json.sheetId }}"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY/edit?usp=drivesdk",
"cachedResultName": "Candidates"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6wBRjmD77d71tAqP",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "767491ab-f7dd-4e23-816b-840bc24e5268",
"name": "set page number for google search",
"type": "n8n-nodes-base.code",
"position": [
2480,
-180
],
"parameters": {
"jsCode": "return [{ json: { start: 0 } }];
"
},
"typeVersion": 2
},
{
"id": "f76f28a5-8444-4ff9-b62c-0d94a07c6447",
"name": "Extracts all linkedin urls from the google http response",
"type": "n8n-nodes-base.code",
"position": [
3740,
-280
],
"parameters": {
"jsCode": "// Extract LinkedIn profile URLs from HTML
function extractLinkedInUrls(html) {
// First decode any encoded HTML entities
html = html.replace(/&/g, '&')
.replace(/\\u003d/g, '=')
.replace(/\\x22/g, '\"')
.replace(/\\x26/g, '&')
.replace(/\\x3e/g, '>')
.replace(/\\x3c/g, '<');
const patterns = [
// Standard LinkedIn URLs in href
/(?:https?:)?\/\/(?:[a-z]{2,}\.)?linkedin\.com\/in\/[a-zA-Z0-9._-]+(?:\/[a-z]{2})?/gi,
// URLs in encoded strings
/(?:\"url\"|url=)(?:[^\"&]*?)(?:https?:)?\/\/(?:[a-z]{2,}\.)?linkedin\.com\/in\/[a-zA-Z0-9._-]+(?:\/[a-z]{2})?/gi,
// URLs in JSON strings
/\"(?:https?:)?\/\/(?:[a-z]{2,}\.)?linkedin\.com\/in\/[a-zA-Z0-9._-]+(?:\/[a-z]{2})?\"/gi
];
const urls = new Set();
patterns.forEach(pattern => {
const matches = html.matchAll(pattern);
for (const match of matches) {
let url = match[0];
// Clean up the URL
url = url.replace(/^\"url\"|^url=|\"$/g, '') // Remove url= prefix and quotes
.replace(/^[\"']|[\"']$/g, '') // Remove surrounding quotes
.replace(/\\+/g, '') // Remove backslashes
.trim();
// Ensure URL has protocol
if (!url.startsWith('http')) {
url = 'https://' + url.replace(/^\/\//, '');
}
// Only include if it's a LinkedIn profile URL
if (url.includes('linkedin.com/in/')) {
// Clean the URL: remove tracking parameters and fragments
url = url.split(/[?#&]/)[0];
// Remove any trailing slashes
url = url.replace(/\/$/, '');
// Add to Set to remove duplicates
urls.add(url);
}
}
});
return Array.from(urls);
}
// Get the HTML from input
const html = $input.first().json.data;
// Extract URLs and create array of objects
const linkedInProfiles = extractLinkedInUrls(html)
.filter(url => !url.includes('google.com')) // Extra safety check to remove any Google URLs
.map(url => ({
linkedin_url: url
}));
// Return the array of objects directly
return linkedInProfiles;"
},
"typeVersion": 2
},
{
"id": "5a93c8f2-f55b-4d0e-92f8-0d86147f8d13",
"name": "Google Boolean Search",
"type": "n8n-nodes-base.httpRequest",
"position": [
3500,
-300
],
"parameters": {
"url": "https://www.google.com/search",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $('Generate a Boolean Search String').first().json.choices[0].message.content.search_string }}
"
},
{
"name": "start",
"value": "={{ $json.start }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "User-Agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"id": "5T6POWjsPfV558Ta",
"name": "Header Auth account"
}
},
"typeVersion": 4.2
},
{
"id": "37b4f264-34f0-47bb-9b1b-fa53beafb2a9",
"name": "Generate a Boolean Search String",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1320,
-180
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "You are an expert in Boolean search techniques for Google. When the user send a job description, generate a search string specifically for finding LinkedIn profiles. Your response must always follow this exact format:
site:linkedin.com/in [Boolean search string]
Create the Boolean search string using precise operators (AND, OR, \"\", *, -) to match the job requirements. Focus only on generating the search string - provide no additional commentary or explanations unless specifically requested.
Also return sheet_name (less than 100 char)"
},
{
"content": "={{ $json.chatInput }}"
}
]
},
"simplify": false,
"jsonOutput": true
},
"credentials": {
"openAiApi": {
"id": "EX7mky4RGLDD6udW",
"name": "OpenAi account"
}
},
"retryOnFail": false,
"typeVersion": 1.8
},
{
"id": "99041eff-f094-4c2a-a75a-4b01faf33d1b",
"name": "If desired results not reached",
"type": "n8n-nodes-base.if",
"position": [
2920,
-200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "da9f8de0-1e75-4ff3-9f81-8e911251416b",
"operator": {
"type": "number",
"operation": "lt"
},
"leftValue": "={{ $json.start }}",
"rightValue": 50
},
{
"id": "a891c085-7f49-4523-8610-40577b3ffd3b",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "d218a1e8-2959-4b7c-a84d-f8e0df82c5e7",
"name": "Appends the results to the sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
4040,
-280
],
"parameters": {
"columns": {
"value": {
"linkedin_url": "={{ $json.linkedin_url }}"
},
"schema": [
{
"id": "linkedin_url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "linkedin_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Full Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Full Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "First Name",
"type": "string",
"display": true,
"required": false,
"displayName": "First Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Headline",
"type": "string",
"display": true,
"required": false,
"displayName": "Headline",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Candidate Summary",
"type": "string",
"display": true,
"required": false,
"displayName": "Candidate Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Experiences Summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Experiences Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Education Summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Education Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Skills",
"type": "string",
"display": true,
"required": false,
"displayName": "Skills",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "City",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "City",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Country",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Country",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Criteria_Assessment",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Criteria_Assessment",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "overall_fit_score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "overall_fit_score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "score_justification",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "score_justification",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company",
"type": "string",
"display": true,
"required": false,
"displayName": "Company",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company Industry",
"type": "string",
"display": true,
"required": false,
"displayName": "Company Industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company Size",
"type": "string",
"display": true,
"required": false,
"displayName": "Company Size",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company LinkedIn URL",
"type": "string",
"display": true,
"required": false,
"displayName": "Company LinkedIn URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company Website",
"type": "string",
"display": true,
"required": false,
"displayName": "Company Website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Current Company Join Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Current Company Join Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Certifications",
"type": "string",
"display": true,
"required": false,
"displayName": "Certifications",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Courses Taken",
"type": "string",
"display": true,
"required": false,
"displayName": "Courses Taken",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Connections Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Connections Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Followers Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Followers Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Languages Spoken",
"type": "string",
"display": true,
"required": false,
"displayName": "Languages Spoken",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Projects",
"type": "string",
"display": true,
"required": false,
"displayName": "Projects",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date Created",
"type": "string",
"display": true,
"required": false,
"displayName": "Date Created",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "={{ $('Create a new sheet').first().json.sheetId }}"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1M9UUgw1wPZIBSoPiGTvNIgA19ERgOo5KmD9wx__Y8ZY/edit?usp=drivesdk",
"cachedResultName": "Candidates"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "6wBRjmD77d71tAqP",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "7a56e7d7-31f8-4115-b993-227bd7221c07",
"name": "Adds 10 to start - Go to next page",
"type": "n8n-nodes-base.code",
"position": [
4340,
-220
],
"parameters": {
"jsCode": "// Get the start value from 'Edit Fields2' node
const startValue =$('If desired results not reached').first().json.start;
// Add 10 to the start value
const start = startValue + 10;
// Return the new value
return [{ json: { start } }];
"
},
"typeVersion": 2
},
{
"id": "afe22fc0-c9c1-4aab-a11d-d91740f812bb",
"name": "Columns to add",
"type": "n8n-nodes-base.code",
"position": [
1980,
-180
],
"parameters": {
"jsCode": "return [{
json: {
\"linkedin_url\": \"\"
}
}];
"
},
"typeVersion": 2
}
],
"active": true,
"pinData": {},
"settings": {},
"versionId": "ce389fd9-7697-4e36-8346-6be9414aecf2",
"connections": {
"Wait": {
"main": [
[
{
"node": "Google Boolean Search",
"type": "main",
"index": 0
}
]
]
},
"Columns to add": {
"main": [
[
{
"node": "Add columns to new sheet",
"type": "main",
"index": 0
}
]
]
},
"Create a new sheet": {
"main": [
[
{
"node": "Columns to add",
"type": "main",
"index": 0
}
]
]
},
"Google Boolean Search": {
"main": [
[
{
"node": "Extracts all linkedin urls from the google http response",
"type": "main",
"index": 0
}
]
]
},
"Add columns to new sheet": {
"main": [
[
{
"node": "set page number for google search",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Generate a Boolean Search String",
"type": "main",
"index": 0
}
]
]
},
"If desired results not reached": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
],
[]
]
},
"Appends the results to the sheet": {
"main": [
[
{
"node": "Adds 10 to start - Go to next page",
"type": "main",
"index": 0
}
]
]
},
"Generate a Boolean Search String": {
"main": [
[
{
"node": "Create a new sheet",
"type": "main",
"index": 0
}
]
]
},
"set page number for google search": {
"main": [
[
{
"node": "If desired results not reached",
"type": "main",
"index": 0
}
]
]
},
"Adds 10 to start - Go to next page": {
"main": [
[
{
"node": "If desired results not reached",
"type": "main",
"index": 0
}
]
]
},
"Extracts all linkedin urls from the google http response": {
"main": [
[
{
"node": "Appends the results to the sheet",
"type": "main",
"index": 0
}
]
]
}
}
}
功能特点
- 自动检测新邮件
- AI智能内容分析
- 自定义分类规则
- 批量处理能力
- 详细的处理日志
技术分析
节点类型及作用
- Wait
- @N8N/N8N Nodes Langchain.Chattrigger
- Stickynote
- Googlesheets
- Code
复杂度评估
配置难度:
维护难度:
扩展性:
实施指南
前置条件
- 有效的Gmail账户
- n8n平台访问权限
- Google API凭证
- AI分类服务订阅
配置步骤
- 在n8n中导入工作流JSON文件
- 配置Gmail节点的认证信息
- 设置AI分类器的API密钥
- 自定义分类规则和标签映射
- 测试工作流执行
- 配置定时触发器(可选)
关键参数
| 参数名称 | 默认值 | 说明 |
|---|---|---|
| maxEmails | 50 | 单次处理的最大邮件数量 |
| confidenceThreshold | 0.8 | 分类置信度阈值 |
| autoLabel | true | 是否自动添加标签 |
最佳实践
优化建议
- 定期更新AI分类模型以提高准确性
- 根据邮件量调整处理批次大小
- 设置合理的分类置信度阈值
- 定期清理过期的分类规则
安全注意事项
- 妥善保管API密钥和认证信息
- 限制工作流的访问权限
- 定期审查处理日志
- 启用双因素认证保护Gmail账户
性能优化
- 使用增量处理减少重复工作
- 缓存频繁访问的数据
- 并行处理多个邮件分类任务
- 监控系统资源使用情况
故障排除
常见问题
邮件未被正确分类
检查AI分类器的置信度阈值设置,适当降低阈值或更新训练数据。
Gmail认证失败
确认Google API凭证有效且具有正确的权限范围,重新进行OAuth授权。
调试技巧
- 启用详细日志记录查看每个步骤的执行情况
- 使用测试邮件验证分类逻辑
- 检查网络连接和API服务状态
- 逐步执行工作流定位问题节点
错误处理
工作流包含以下错误处理机制:
- 网络超时自动重试(最多3次)
- API错误记录和告警
- 处理失败邮件的隔离机制
- 异常情况下的回滚操作