我自己撸了个免费爬虫工具:批量提取公司邮箱,LLM直接解析,无需充钱

0 阅读4分钟

一、写在前面的吐槽

做外贸、做调研、找客户,经常需要从一堆公司官网上提取联系方式。打开某度一搜"在线爬虫",好家伙,全是收费的——要么限制URL数量,要么导出要会员,要么爬个几十条就让你充钱。

不就是发个HTTP请求、解析个HTML吗?这点东西收费几百块一年?我这暴脾气一上来,干脆自己撸一个

于是就有了今天要分享的这个在线爬虫工具——完全免费,支持批量URL,还带LLM智能提取


二、工具入口

在线地址:agent.linkedshine.com/tools(备选域名:ai.kpoda.com/tools

目前提供了两种模式,满足不同场景需求:

模式适用场景核心能力
简版爬虫快速扫一眼公司是干啥的、有没有邮箱自动提取公司简介 + 邮箱地址
完整版爬虫我想自定义提取任意信息LLM意图驱动,你写什么它就提取什么

下面逐一介绍。


三、简版爬虫:零配置,一键提取

适合"我就想快速看看这些公司有没有联系方式"的场景。

使用步骤:

  1. 打开简版爬虫页面
  2. 输入URL列表(一行一个,最多10个),或者直接上传CSV/TXT文件
  3. 点「开始爬取」
  4. 等几秒,结果就出来了

输出什么?

  • 每页的公司简介(自动识别 meta description / about 页面 / 正文最长段落)
  • 所有页面中提取到的邮箱地址(自动去重、一键复制全部)

真·零门槛,连"意图"都不用填。


四、完整版爬虫:LLM驱动的智能提取

这是重头戏。简版只能提取简介和邮箱,完整版则支持你自己定义要提取什么

比如你写一句:

"提取公司名称、联系电话、邮箱、公司地址、主要产品、成立年份"

LLM就会从爬下来的页面内容中,一一为你提取出这些字段。

高级配置:

  • 并发数 1~5 可调(批量多URL并行处理,快得飞起)
  • 抓取模式 可选 HTTP优先 / 仅浏览器 / 仅HTTP(灵活应对不同网站)
  • 文件上传 支持 CSV / XLSX / XLS / TXT,Excel里有一列表格URL直接导入

结果展示也做得不错:

  • 汇总卡片(总数 / 成功 / 失败 / 耗时)
  • 联系信息聚合面板(邮箱、电话、地址全部汇总,一键复制)
  • 每个URL展开详情:页面标题、置信度百分比、结构化提取字段
  • 支持表格视图切换
  • 支持CSV导出

五、后台任务系统:不阻塞,不丢失

两种模式共用一套后台异步任务系统

  • 提交任务后不用干等着,可以去干别的事
  • 底部可展开的任务面板,实时显示进度条、成功/失败计数
  • 所有历史任务都保留,随时回来查看结果
  • 任务状态:pending → running → success / failed

每2秒自动轮询进度,体验拉满。


六、技术亮点(给想自己实现的朋友参考)

这一节简单说说底层是怎么做的,放点核心代码,感兴趣的朋友可以参考。这节是给技术同学看的,纯用工具的朋友可以直接跳过。

6.1 三层爬虫引擎

层级引擎特点
第一层HTTP抓取(fetch + Cheerio)速度快,资源消耗低
第二层浏览器抓取(Playwright)能执行JS,应对SPA页面
第三层LLM Agent(AI驱动)智能意图理解 + 结构化提取

HTTP 模式走的是标准 fetch + cheerio 解析,速度最快。配置了 User-Agent 随机轮换、指数退避重试:

// 内置 8 个真实浏览器 User-Agent
const DEFAULT_USER_AGENTS = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/124',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Chrome/124',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0',
  // ... 更多 UA
]

// 随机获取一个 UA
private getRandomUserAgent(): string {
  const index = Math.floor(Math.random() * this.userAgents.length)
  return this.userAgents[index]
}

// 指数退避重试
for (let attempt = 0; attempt <= maxRetries; attempt++) {
  try {
    const response = await fetch(url, {
      headers: { 'User-Agent': this.getRandomUserAgent() },
    })
    if (!response.ok) throw new Error(`HTTP ${response.status}`)
    return await response.text()
  } catch (err) {
    if (attempt === maxRetries) break
    // 指数退避: delay * 2^attempt
    await sleep(minDelay * Math.pow(2, attempt))
  }
}

HTTP 抓取失败(比如遇到 Cloudflare 防护、需要 JS 渲染的页面),自动降级到 Playwright 浏览器模式

// 检测 Cloudflare 挑战页面
private isCloudflareChallenge(html: string): boolean {
  const markers = ['just a moment', 'checking your browser', 'cloudflare',
                    'cf-ray', 'cdn-cgi/challenge-platform']
  return markers.filter(m => html.toLowerCase().includes(m)).length >= 2
}

// 检测反爬错误,触发降级
private isAntiScrapingError(errMsg: string): boolean {
  const keywords = ['403', 'forbidden', 'bot detected', 'captcha',
                    'cloudflare', 'blocked', '429', 'unusual traffic']
  return keywords.some(k => errMsg.toLowerCase().includes(k))
}

6.2 浏览器反检测

Playwright 模式下做了完整的反检测注入,隐藏自动化特征:

await page.addInitScript(() => {
  // 覆盖 navigator.webdriver,防止被检测为自动化工具
  Object.defineProperty(navigator, 'webdriver', {
    get: () => false,
  })

  // 模拟 window.chrome 对象
  window.chrome = { runtime: {} }

  // 覆盖 permissions API
  const originalQuery = navigator.permissions.query.bind(navigator.permissions)
  navigator.permissions.query = (parameters) =>
    parameters.name === 'notifications'
      ? Promise.resolve({ state: Notification.permission })
      : originalQuery(parameters)
})

// 拦截图片/样式/字体请求,提升性能
await page.route('**/*', (route) => {
  const type = route.request().resourceType()
  if (['image', 'stylesheet', 'font'].includes(type)) {
    route.abort()
  } else {
    route.continue()
  }
})

6.3 LLM 智能提取

完整版的核心是 LLM 驱动的结构化提取。将页面正文、联系方式、JSON-LD 结构化数据一起喂给大模型,让它按意图提取:

export async function extractFromPage(
  page: PageContent,
  intent: string,
): Promise<ExtractionResult> {
  const prompt = `## 提取意图
${intent}

## 页面信息
URL: ${page.url}
标题: ${page.title}
描述: ${page.description}

## 已抓取到的联系方式
${contactsBlock}

## 结构化数据(JSON-LD + OpenGraph,高置信度)
${structuredBlock}

## 页面正文(截断至 ${maxTextLength} 字)
${page.text.slice(0, maxTextLength)}`

  const { object } = await generateObject({
    model,
    schema: ExtractionResultSchema,  // Zod Schema 约束输出
    temperature: 0.1,                // 低温度保证确定性
    prompt,
  })

  // 过滤 LLM 幻觉:只保留原始链接集中存在的 URL
  const validHrefs = new Set(page.links.map(l => l.href))
  return {
    ...object,
    relevantLinks: object.relevantLinks.filter(u => validHrefs.has(u)),
  }
}

6.4 智能缓存

已爬过的 URL 结果缓存 30 天,同域名重复请求直接跳过,避免重复劳动。


七、总结

这个爬虫工具的核心优势:

  1. 完全免费,支持批量URL处理
  2. 两种模式覆盖从简单到复杂的所有场景
  3. LLM智能提取,你想提取什么就写什么
  4. 自动降级,HTTP不行就上浏览器
  5. 后台任务,不阻塞、不丢失
  6. 结果可视化,聚合面板 + 表格 + CSV导出

在线体验地址:agent.linkedshine.com/tools(备选:ai.kpoda.com/tools

目前还在持续迭代中,后续计划加入整站爬取、定时任务等功能。如果你也用得上,欢迎来体验和提建议!

用得好的话,点个赞/收藏让我看到,我会持续更新功能;

遇到问题欢迎评论区留言,我都会回的。

欢迎点赞收藏,后续更新不迷路~