分类 分布式 下的文章

项目地址:https://github.com/zhegexiaohuozi/seimi-render(Apache 2.0 开源)

从一个老问题说起

做爬虫、做数据采集、做内容聚合的同学,大概都绕不开一个场景:拿到一个 URL,我要的不是它 curl 出来的那段 HTML,而是「人在浏览器里看到的那一页」——JS 跑完之后的内容、登录态后面才能看到的页面、搜索结果里去掉广告的结构化结果。

这条路传统上有几个老掉牙的方案:

  • requests + BeautifulSoup:对 SPA 和动态页面直接歇菜,拿到的是空壳。
  • Selenium / Playwright:能跑,但每个任务要拉起一个完整浏览器进程,重、慢、不稳定,并发起来资源开销惊人。
  • 直接复用日常浏览器:有人图省事,挂个插件或用 puppeteer 连到自己平时用的 Chrome 上跑自动化。但这玩意儿是双向干扰的——自动化跑起来窗口一直在跳、标签页乱切,严重打扰你正常上网;反过来,你随手点个标签、关个页面、甚至切去别的网站,也会干扰甚至直接搞崩正在跑的采集流程。人和机器抢同一个浏览器,谁都别想舒服。
  • 商业渲染 API:能用,但贵、有限额、cookie 登录态完全没法自己掌控。
  • 搜索 API:贵,很贵。

而 2026 年大家又多了一个新需求:AI Agent 要读网页怎么办? Claude Code、Cursor、ZCode 这些 coding agent,本身没有「真实浏览器」这个能力,遇到「帮我看一下这个链接讲了什么」「帮我搜一下这个关键词」就卡住了——它们要么没有联网工具,要么只能用简陋的 fetch,拿不到 JS 渲染后的真实内容。

seimi-render 就是冲着这两个老痛点 + 一个新需求来的。

- 阅读剩余部分 -

本文将介绍如何使用SeimiCrawler将页面中信息提取为结构化数据并存储到数据库中,这也是大家非常常见的使用场景。数据抓取将以抓取博客园的博客为例。

建立基本数据结构

为了演示,简单起见只建立一个用来存储博客标题和内容两个主要信息的表即可。表如下:

CREATE TABLE `blog` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(300) DEFAULT NULL,
  `content` text,
  `update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

- 阅读剩余部分 -

Change log

v0.2.7

  • 内嵌http接口在可以接收单个Json形式Request基础上增加支持接收Json数组形式的多个Request
  • Request对象支持设置skipDuplicateFilter用来告诉seimi处理器跳过去重机制,默认不跳过
  • 增加定时调度使用Demo
  • 回调函数通过Request传递自定义参数值类型由Object改为String,方便明确处理
  • Fix:修复一个打日志的bug

- 阅读剩余部分 -

SeimiCrawler v0.1.0终于熬过了他漫漫的开发旅程,对外发布了,目前已经同步至中央maven库。dependency:

<dependency>
    <groupId>cn.wanghaomiao</groupId>
    <artifactId>SeimiCrawler</artifactId>
    <version>0.1.0</version>
</dependency>

简介

SeimiCrawler是一个敏捷的,支持分布式的爬虫开发框架,希望能在最大程度上降低新手开发一个可用性高且性能不差的爬虫系统的门槛,以及提升开发爬虫系统的开发效率。在SeimiCrawler的世界里,绝大多数人只需关心去写抓取的业务逻辑就够了,其余的Seimi帮你搞定。设计思想上SeimiCrawler受Python的爬虫框架Scrapy启发很大,同时融合了Java语言本身特点与Spring的特性,并希望在国内更方便且普遍的使用更有效率的XPath解析HTML,所以SeimiCrawler默认的HTML解析器是JsoupXpath,默认解析提取HTML数据工作均使用XPath来完成(当然,数据处理亦可以自行选择其他解析器)。

项目主页

SeimiCrawler主页