CrabNote螃蟹笔记

4、 进阶|N8N 爬虫技巧 & 热点资讯自动收集实战

4、 进阶|N8N 爬虫技巧 & 热点资讯自动收集实战

4、 进阶|N8N 爬虫技巧 & 热点资讯自动收集实战 4、 进阶|N8N 爬虫技巧 & 热点资讯自动收集实战 Modified September 28, 2025 Code block JSON Copy { "filter": { "conjunction": "or", "conditions": [ { "field name": "创建时间", "operator": "is", "value": ["Today"] }, { "field name": "创建时间", "operator": "is", "value": ["Yesterday"] } ] } } 获取日历列表 开始时间:{{ (Math.floor((Math.floor(Date.now()/1000) + 28800) / 86400) 86400 28800) }} 结束时间:{{ (Math.floor((Math.floor(Date.now()/1000) + 28800) / 86400) 86400 28800) + 604800 + 86399 }} 12、(可选)写入 Notion(知识库归档) 1)Notion Create Page:写元数据 2)HTTP PATCH /v1/blocks/{id}/children:把前面 Code 生成的 blocks 作为正文 children 追加 13、收尾 & 观测(可选) 1)Error Trigger:任何节点报错 → 飞书群/Slack 提醒(摘要 + trace id) 2)关键 Set 记录 trace id/source/cost ms/batch index 等,便于排错 六)可复制片段 1)北京时间格式化(表达式) Code block Plain Text Copy {{ new Date($json.pubDate || $json.date || $json.发布时间) .toLocaleString('zh CN',{ timeZone:'Asia/Shanghai', hour12:false }) .replace(/\//g,' ').replace(',','') }} 2)今日过滤(表达式) (见第 5 步「只保留今天」的代码,直接复制) 3)URL → MD5(Code) (见第 7 步,直接复制) 4)批处理限速(范式) 1)Split In Batches:batchSize = 20 2)批尾 Wait 1000ms → 回到 Split(直到 noItemsLeft) 5)HTTP 失败重试(设置) 1)勾 Retry on Fail 2)Max Tries = 3,Wait Between Tries (ms) = 1000 3)长页面抓取适当把 Timeout 提高到 20–30s 6)Firecrawl /search(HTTP Request → Query) • q={{$json.标题}}、limit=3、scrapeOptions={"formats":["markdown"]} • Header:Authorization: Bearer <key 7)HTML → 纯文本清洗(思路) • 去标签/脚本/SVG;段落化;超长文分段(1500–2000 字),便于 Notion children/LLM 8)“A−B 去重”(Merge → Combine by field) • fieldsToMatchString = {{$json['标题']}},joinMode = keepNonMatches(仅保留新标题) 七)常见坑(复盘清单) 1)只拿到摘要没正文:Firecrawl /search 记得带 scrapeOptions.formats:["markdown"] 2)批量触发 429:抓取/写入外包 Split + Wait;HTTP 勾 Retry 3)HTML 抽取空/乱:站点改版或选择器失效;走 Error Trigger 告警并回退到 Firecrawl/RSS 4)Notion 写失败:字段名/类型与 DB schema 不一致,或标题字段不是 title 类型 5)时区错位:课程内所有“今天/日期”统一按 Asia/Shanghai(表达式里已处理) 6)遇到文章创建时间不对,且有重复,从分页查询和标题匹配两个地方优化 八)补充 针对没有RSS源的,我们可以直接爬取网页,主要使用的就是FireCrawl这个工具 1. FireCrawl:http://firecrawl.dev/ 2. FireCrawl Github:https://github.com/mendableai/firecrawl 3. firecrawl参数说明:https://docs.firecrawl.dev/advanced scraping guide 节点安装: 获取日历列表 开始时间:{{ (Math.floor((Math.floor(Date.now()/1000) + 28800) / 86400) 86400 28800) }} 结束时间:{{ (Math.floor((Math.floor(Date.now()/1000) + 28800) / 86400) 86400 28800) + 604800 + 86399 }} 12、(可选)写入 Notion(知识库归档) 1)Notion Create Page:写元数据 2)HTTP PATCH /v1/blocks/{id}/children:把前面 Code 生成的 blocks 作为正文 children 追加 13、收尾 & 观测(可选) 1)Error Trigger:任何节点报错 → 飞书群/Slack 提醒(摘要 + trace id) 2)关键 Set 记录 trace id/source/cost ms/batch index 等,便于排错 六)可复制片段 1)北京时间格式化(表达式) 2)今日过滤(表达式) (见第 5 步「只保留今天」的代码,直接复制) 3)URL → MD5(Code) (见第 7 步,直接复制) 4)批处理限速(范式) 1)Split In Batches:batchSize = 20 2)批尾 Wait 1000ms → 回到 Split(直到 noItemsLeft) 5)HTTP 失败重试(设置) 1)勾 Retry on Fail 2)Max Tries = 3,Wait Between Tries (ms) = 1000 3)长页面抓取适当把 Timeout 提高到 20–30s 6)Firecrawl /search(HTTP Request → Query) • q={{$json.标题}}、limit=3、scrapeOptions={"formats":["markdown"]} • Header:Authorization: Bearer <key 7)HTML → 纯文本清洗(思路) • 去标签/脚本/SVG;段落化;超长文分段(1500–2000 字),便于 Notion children/LLM 8)“A−B 去重”(Merge → Combine by field) • fieldsToMatchString = {{$json['标题']}},joinMode = keepNonMatches(仅保留新标题) 七)常见坑(复盘清单) 1)只拿到摘要没正文:Firecrawl /search 记得带 scrapeOptions.formats:["markdown"] 2)批量触发 429:抓取/写入外包 Split + Wait;HTTP 勾 Retry 3)HTML 抽取空/乱:站点改版或选择器失效;走 Error Trigger 告警并回退到 Firecrawl/RSS 4)Notion 写失败:字段名/类型与 DB schema 不一致,或标题字段不是 title 类型 5)时区错位:课程内所有“今天/日期”统一按 Asia/Shanghai(表达式里已处理) 6)遇到文章创建时间不对,且有重复,从分页查询和标题匹配两个地方优化 八)补充 针对没有RSS源的,我们可以直接爬取网页,主要使用的就是FireCrawl这个工具 1. FireCrawl:http://firecrawl.dev/ 2. FireCrawl Github:https://github.com/mendableai/firecrawl 3. firecrawl参数说明:https://docs.firecrawl.dev/advanced scraping guide 节点安装: 增加节点凭证 再去firecrawl(https://www.firecrawl.dev/app/api keys)去复制apikey 主要使用这个方法 然后结合AI Agent来处理 提示词参考如下 json) 或任何形式的 markdown 格式。你的输出必须能直接被 JSON 解析器使用。 空结果: 如果根据规则没有找到任何新闻文章,必须返回一个空的数组 []。 唯一性: 确保返回结果中的文章是唯一的,去除任何重复的 URL。 示例 输入 Markdown (部分): Markdown ... 深度分析:新的全球贸易协定将如何影响市场 ... 观点 ... 了解我们的团队 ... 基础 URL: https://example news.com 期望的 JSON 输出: JSON { "title": "深度分析:新的全球贸易协定将如何影响市场", "url": "[https://example news.com/2025/08/15/analysis global trade deal" } ] 输入数据 基础 URL: {{ $json.data.metadata.url }} Markdown 内容: {{ $json.data.markdown }} Code block JavaScript Copy {{ (()= { const raw=$json['日期']||$json['pubDate']||$json['date']||$json['发布时间']||$json['time']; if(!raw) return false; let dt=new Date(raw); if(isNaN(dt)){ const s=String(raw).trim().replace(/[年\/\.]/g,' ').replace(/月/g,' ').replace(/日/g,''); const m=s.match(/(\d{4}) (\d{1,2}) (\d{1,2})/); if(!m)return false; dt=new Date( ); } const toBJ=d= new Date(d.getTime()+8 60 60000).toISOString().slice(0,10); return toBJ(dt)===toBJ(new Date()); })() }} Code block JSON Copy { "filter": {"conjunction": "or","conditions": [ {"field name": "创建时间","operator": "is","value": ["Today"]}, {"field name": "创建时间","operator": "is","value": ["Yesterday"]} ]}, "sort": [{"field name": "日期","order": "desc"}]} Code block JavaScript Copy // —— 通用清洗:可读标题(软清洗) + 匹配键(硬归一)—— function softClean(title) { let s = String(title || '').normalize('NFKC'); // 全/半角统一 Code block JavaScript Copy function softClean(title) { let s = String(title || '').normalize('NFKC'); s = s.replace(/[\u00A0\uFEFF\u200B \u200D\u2060\u00AD\u2000 \u200A\u202F\u205F\u3000]/g, ''); s = s.replace(/\s+/g, ' ').trim(); return s; Code block Plain Text Copy 把你收到的新闻信息都整理成干净的格式,内容需要总结为摘要,以下是新闻: 标题 :{{ $json['标题'] }} 内容:{{ $json['内容'] }} 日期:{{ $json['日期'] }} 链接:{{ $json['链接'] }} 媒体:{{ $json['媒体'] }} 注意:不要改变标题的值 Code block Plain Text Copy { "标题":"xxxx", Code block JavaScript Copy 日期:{{ $('筛选A减B 去重').item.json['日期'] }} 内容:{{ $json.output['内容'] }} 媒体:{{ $json.output['媒体'] }} 链接:{{ $json.output['链接'] }} 标题:{{ $json.output['标题'] }} Code block JSON Copy {"fields":{ "标题":"{{ $json['标题'] }}", "日期":"{{ (()= { const d = new Date($json['日期']); const tz = 'Asia/Shanghai'; const fmt = new Intl.DateTimeFormat('zh CN', { timeZone: tz, year:'numeric', month:'2 digit', day:'2 digit', hour:'2 digit', minute:'2 digit', second:'2 digit', hour12:false }).formatToParts(d).reduce((a,p)= (a[p.type]=p.value,a),{}); return ; })() }}", "内容":"{{$json['内容'].replace(/<[^ ]+ /g,'').replace(/[^\p{L}\p{N}\s]/gu,'').replace(/[\r\n\t]/g,' ')}}", "链接": {"text":"AI新闻原文","link":"{{ ($json['链接']||'').replace(/\n/g,'') }}"}, "媒体":"{{ $json['媒体'] }}" }} ``` 如果你在执行工作流的过程中报错了,那大概率是飞书的具体权限不行,把这个报错复制到飞书开放平台或者去问豆包,然后开启对应权限即可。 另外要注意⚠️,多维表格建立在云盘中,不然可能报下面这个错误 2)Split In Batches + Wait 包住(20 条/批,1s 间隔),避免风控 11、(可选)发送到飞书机器人 如果还想发到飞书群里面,那就要结合飞书机器人。也可以结合飞书里面的日历来看自己接下来的日程。 我们先开通日历功能权限,也和上面一样的道理,直接在飞书开发文档里面提问即可。 Agent详情 查询多维表格