news 2026/10/14 20:26:36

webmagic-scripts 使用指南:用 JavaScript/Ruby 脚本零代码编写 WebMagic 爬虫

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
webmagic-scripts 使用指南:用 JavaScript/Ruby 脚本零代码编写 WebMagic 爬虫
  • 后端
  • 网页爬虫

【免费下载链接】webmagic

A scalable web crawler framework for Java.

项目地址:https://gitcode.com/gh_mirrors/we/webmagic
点击查看免费下载

webmagic-scripts 是 WebMagic 爬虫框架(Java)中的一个实验性子模块,它让你不写 Java 代码,只用一段简单的脚本(默认 JavaScript,也支持 Ruby/JRuby)即可完成页面抽取、链接发现与结果输出。本文以 webmagic-scripts/README.md 为主体,结合模块源码,完整讲解脚本 API、控制台命令行用法、多语言机制与底层执行原理,读完你既能直接运行别人写好的脚本,也能自己编写并流通一套抓取脚本。

一、设计目标:让爬虫脚本可编写、可流通

模块的目标非常明确:用简单脚本的方式编写爬虫,为一些常用场景提供"可流通"的脚本——如果已经有人写好了脚本,你直接使用即可,无需下载依赖、编写 Java 代码,也不需要经历编译打包流程。

从仓库结构看,该模块位于 webmagic-scripts,其 pom.xml 依赖webmagic-core、webmagic-extension,并通过maven-jar-plugin将主类配置为us.codecraft.webmagic.scripts.ScriptConsole,这正是"控制台一键运行"能力的来源。它同时引入jruby、jython、commons-cli等依赖,对应着多语言引擎支持与命令行参数解析。

二、快速上手:控制台运行一个抓取脚本

原文档提供了一个控制台版本(webmagic-console压缩包)。解压后,使用如下命令执行脚本:

java -jar -Dfile.encoding='utf-8' webmagic-console.jar -f 脚本文件名 [-l 语言,默认是javascript] [-t 线程数] [-s 抓取间隔,毫秒] url1 url2 …

各参数含义如下表:

参数含义默认值
-f脚本文件名(必填)无
-l脚本语言,javascript或rubyjavascript
-t抓取线程数1
-s两次请求之间的抓取间隔(毫秒)1000
位置参数起始 URL,可多个(url1 url2 …)无

例如,对仓库中自带的 js/github.js 脚本,可以这样执行:

java -jar -Dfile.encoding='utf-8' webmagic-console.jar -f github.js -t 2 -s 0 https://github.com/code4craft

该命令以 2 个线程、0 毫秒抓取间隔,从https://github.com/code4craft开始抓取 GitHub 仓库数据。注意-Dfile.encoding='utf-8'用于保证脚本文件以 UTF-8 编码读取,避免中文或特殊字符乱码。

从源码看,控制台入口 ScriptConsole.java 会依次完成:解析命令行参数 → 用ScriptProcessorBuilder构建ScriptProcessor→ 配置Site(设置sleepTime、重试次数 3,接受状态码集合200/404/403/500/502)→ 创建Spider并添加起始 URL →spider.run()启动抓取。若未提供任何 URL,程序会打印用法提示并以-1退出。

三、脚本 API:三个核心函数与 page 对象

脚本之所以"简单",是因为模块预先注入了少量开箱即用的辅助函数。JavaScript 的辅助函数定义在 js/defines.js:

function $(str){ return page.getHtml().$(str).toString(); } function xpath(str){ return page.getHtml().xpath(str).toString(); } function urls(str){ links = page.getHtml().links().regex(str).all(); page.addTargetRequests(links); }

即脚本中可直接使用三个全局函数:

  • $(cssSelector):按 CSS 选择器抽取页面元素并转为字符串;
  • xpath(xpathExpr):按 XPath 表达式抽取页面元素并转为字符串;
  • urls(regex):从当前页面所有链接中匹配正则,将命中的 URL 作为后续抓取目标(对应 WebMagic 的"目标请求"机制,实现自动翻页/发现新页面)。

Ruby 的辅助函数定义在 ruby/defines.rb,除xpath、urls外还额外提供了css函数;Python 的辅助函数定义在 python/defines.py,同样提供xpath、css、urls。

除了辅助函数,脚本运行环境中还注入了两个关键对象(见 ScriptProcessor.java 的process方法):

  • page:us.codecraft.webmagic.Page实例,可直接调用page.getUrl()、page.getHtml()、page.addTargetRequests(...)等 WebMagic 原生方法;
  • config:Site实例,用于在脚本中调整抓取配置。

在 JavaScript 中访问这些对象直接用page.xxx;在 Ruby 中则通过$page等全局变量(defines.rb 中的$page.getHtml()),两种语言的约定略有差异,使用时需注意。

四、实例解析:用 JavaScript 抓取 GitHub 仓库数据

原文档给出了抓取 GitHub 仓库数据的 JavaScript 脚本(即仓库中的 js/github.js):

var name=xpath("//h1[@class='entry-title public']/strong/a/text()") var readme=xpath("//div[@id='readme']/tidyText()") var star=xpath("//ul[@class='pagehead-actions']/li[1]//a[@class='social-count js-social-count']/text()") var fork=xpath("//ul[@class='pagehead-actions']/li[2]//a[@class='social-count']/text()") var url=page.getUrl().toString() if (name!=null){ println(name) println(readme) println(star) println(url) } urls("(https://github\\.com/\\w+/\\w+)") urls("(https://github\\.com/\\w+)")

逐行拆解:

  1. 字段抽取:用xpath(...)分别抽取仓库名(name)、README 正文(readme,通过 WebMagic 的tidyText()提取干净文本)、Star 数与 Fork 数;
  2. 页面 URL:page.getUrl().toString()拿到当前页面地址;
  3. 条件输出:只有当name != null(即命中仓库详情页而非个人主页)时才输出结果,借助 JavaScript 引擎自带的println打印到控制台;
  4. 链接发现:urls("(https://github\\.com/\\w+/\\w+)")匹配形如"用户/仓库"的详情页链接,urls("(https://github\\.com/\\w+)")匹配个人主页链接,两者共同驱动 Spider 自动扩散抓取范围。

这段脚本展示了脚本式爬虫的典型"抽取-输出-发现"三段式写法,无需任何 Java 类定义,直接交给控制台运行即可。

仓库中还提供了另一个 JavaScript 示例 js/oschina.js,它用$("div.BlogTitle h1")这种 CSS 写法抽取博客标题,并通过urls("http://my\\.oschina\\.net/flashsword/blog/\\d+")发现后续博客列表页,同时演示了脚本内定义config对象(可携带ua、sleepTime等配置项)的写法。

五、多语言支持:Ruby/JRuby 与语言参数

原文档说明,选用 JavaScript 是因为用户面广;选用 Ruby 则是因为Ruby 语法编写 DSL 更简洁。Ruby 版本(ruby/github.rb):

name= xpath "//h1[@class='entry-title public']/strong/a/text()" readme = xpath "//div[@id='readme']/tidyText()" star = xpath "//ul[@class='pagehead-actions']/li[1]//a[@class='social-count js-social-count']/text()" fork = xpath "//ul[@class='pagehead-actions']/li[2]//a[@class='social-count']/text()" url=$page.getUrl().toString() puts name,readme,star,fork,url unless name==nil urls "(https://github\\.com/\\w+/\\w+)" urls "(https://github\\.com/\\w+)"

Ruby 版本省略了函数调用括号,xpath "..."、urls "..."的写法更接近自然语言 DSL;输出使用 Ruby 的puts,条件输出使用unless name==nil。注意 Ruby 脚本中页面对象通过$page访问。

多语言通过-l参数区分。例如执行这个 Ruby 脚本:

java -jar -Dfile.encoding='utf-8' webmagic-console.jar -f github.rb -t2 -s0 -l ruby https://github.com/code4craft

从 Params.java 的源码看,语言别名映射为:

-l取值对应引擎
js、javascript、JavaScript、JSJavaScript
ruby、jruby、Ruby、JRubyJRuby

此外,虽然原文档只提到 JavaScript 与 Ruby,仓库中实际上还内置了Jython(Python)语言实现(Jython.java),并有示例脚本 python/oschina.py。同时,模块的 [pom.xml](https://link.gitcode.com/i/a1512246080de2e02b654296c0274dc0) 中还引入了 Kotlin 与 Groovy 支持([Github.kt](https://link.gitcode.com/i/6b9a9e42d296e437002be1031fdd38c3) 演示了 Kotlin 编写标准 PageProcessor 的写法,[Github.groovy](https://link.gitcode.com/i/d2cd080be00e479623eb64456304ad22) 演示了 Groovy DSL 风格配置Site` 与抽取规则的写法),可见多语言是其设计主线之一。

六、源码级原理:ScriptEngine、EnginePool 与执行链路

原文档说明"这部分使用 Java 的 ScriptEngine 机制完成"。深入源码可以看到完整的执行链路:

1. 处理器(ScriptProcessor):ScriptProcessor.java 实现 WebMagic 的PageProcessor接口。process(Page page)方法从ScriptEnginePool借出一个引擎,将page与config(即Site)注入ScriptContext.ENGINE_SCOPE,然后调用language.process(engine, defines, script, page)执行"辅助函数定义 + 用户脚本",最后把引擎归还池中。

2. 语言抽象(Language):Language.java 是抽象基类,每个实现类绑定三要素:引擎名称(engineName)、辅助函数定义文件(defineFile,如js/defines.js)、结果收集文件(gatherFile)。Javascript.java 直接engine.eval(defines + "\n" + script),把辅助函数和用户脚本拼接后整体求值;而 JRuby.java 会捕获求值返回的RubyHash,将其迭代写入page.getResultItems(),这就是 Ruby 脚本天然"以字典形式返回结果"的底层原因。

3. 引擎池(ScriptEnginePool):ScriptEnginePool.java 按线程数预创建 N 个ScriptEngine(通过ScriptEngineManager.getEngineByName(language.getEngineName())),用LinkedBlockingQueue维护,getEngine()出队、release()入队,并用AtomicInteger统计可用数量——这保证了多线程抓取时每个线程有独立脚本引擎,避免引擎状态互相污染。

4. 测试佐证:ScriptProcessorTest.java 分别用Javascript、JRuby、Jython三种语言加载 classpath 下的 oschina 脚本,配合Spider.create(pageProcessor)实际抓取并校验执行流程(该测试类标注@Ignore,属于需要联网环境的集成性测试)。

七、以库的形式集成:ScriptProcessorBuilder

除了控制台,脚本能力也能作为 Java 库直接嵌入自己的程序。构建器 ScriptProcessorBuilder.java 提供链式 API:

  • custom():创建构建器,默认语言为 JavaScript,默认线程数 1;
  • language(Language):指定语言(new Javascript()/new JRuby()/new Jython());
  • scriptFromFile(fileName):从文件系统读取脚本;
  • scriptFromClassPathFile(fileName):从 classpath 读取脚本(如js/oschina.js);
  • script(String):直接传入脚本源码字符串;
  • thread(int):设置引擎池线程数;
  • build():构建ScriptProcessor。

参考 ScriptProcessorTest.java 的用法:

ScriptProcessor pageProcessor = ScriptProcessorBuilder.custom() .language(new Javascript()) .scriptFromClassPathFile("js/oschina.js") .build(); pageProcessor.getSite().setSleepTime(0); Spider.create(pageProcessor).addUrl("http://my.oschina.net/flashsword/blog").setSpawnUrl(false).run();

build()后得到的是标准PageProcessor,可直接交给Spider.create(...)使用,与 WebMagic 原有 API 无缝衔接。

八、进阶:命令行参数解析与日志级别

控制台的参数解析由 CommandLineOption.java 实现(基于 commons-cli),实际支持 5 个选项:

选项作用
-l语言,交给Params.setLanguagefromArg做别名匹配
-f脚本文件路径
-s抓取间隔(毫秒),Integer.parseInt解析
-t线程数,Integer.parseInt解析
-g日志级别,交给 ConfigLogger.java 处理

-g可取值包括debug、info、warn、trace、off、error(大小写不敏感),通过设置 SLF4J root logger 的日志级别来控制控制台输出详略,便于排查脚本问题。

从 Params.java 还可确认各参数默认值:语言默认Javascript、线程数默认 1、抓取间隔默认 1000 毫秒,与 README 描述一致。

九、注意事项与实验状态

原文档明确指出:这个功能目前仍在实验阶段。因此在实际使用中需要了解以下前提与限制:

  • 依赖运行时环境:JavaScript 依赖 JDK 自带的 Nashorn 等 ScriptEngine 实现;Ruby、Python 支持依赖jruby、jython依赖包(见 pom.xml),引擎是否可用取决于你的 Java 版本与 classpath;
  • 脚本运行于沙箱之外:脚本本质是在 JVM 内直接求值,可访问注入的page、config对象,请勿运行来源不可信的脚本;
  • 实验性 API:辅助函数集合、结果收集方式(Ruby 的 Hash 返回、Python 的result字典)在不同语言间并不完全统一,升级 WebMagic 版本时脚本可能需要相应调整;
  • 控制台方式:仓库以webmagic-scriptsMaven 模块形式提供源码与构建配置,主类为ScriptConsole;如需控制台版 jar 包,可自行构建该模块获取。

总体而言,webmagic-scripts 以"脚本即爬虫"的思路大幅降低了 WebMagic 的使用门槛,让常用抓取场景沉淀为一行命令即可运行的脚本资产。无论是快速验证抽取规则、临时抓取数据,还是向团队流通标准化的抓取脚本,它都是一条值得尝试的轻量路径。

  • 后端
  • 网页爬虫

【免费下载链接】webmagic

A scalable web crawler framework for Java.

项目地址:https://gitcode.com/gh_mirrors/we/webmagic
点击查看免费下载

相关推荐

上一篇:为什么你的六足机器人走不稳?Hexapod5 的 5 个关键设计决策
下一篇:Altair桑基图终极指南:Python流量数据可视化与路径分析指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 20:26:24

去中心化组网:EasyTier

EasyTier:去中心化VPN的简单与高效 引言 在网络安全与隐私保护要求不断提高的今天,传统依赖中心化服务器的VPN方案存在单点故障、运维成本高以及潜在隐私风险等问题。EasyTier 是一个基于 Rust 开发的开源去中心化网格 VPN 项目,以相对简洁…

作者头像 李华
网站建设 2026/10/14 20:25:59

Vue3 + Canvas 实现类 Pixso 钢笔工具:贝塞尔曲线与路径编辑

1. 项目动机与整体设计思路钢笔工具这东西,我用一句话概括就是:看着是工具栏里一个不起眼的小图标,实际做起来是图形编辑器里最磨人的那块骨头。这次我用Vue3从头实现了一遍类Pixso的钢笔工具,核心功能包括路径创建、锚点拖拽、贝…

作者头像 李华
网站建设 2026/10/14 20:25:04

火萤视频桌面 2026 下载使用教程:停服之后它还能怎么用

火萤视频桌面是个把视频变成动态壁纸的工具:选一个视频文件,让它当你的桌面背景,动态地放着。 先说清它现在的状态,这一步很重要:最后版本是 v5.2.5.9,已经停止维护;原来那个域名也已经易主&am…

作者头像 李华
网站建设 2026/10/14 20:24:32

彻底卸载Node.js:Windows/macOS/Linux残留清理保姆级教程

你有没有碰到过这种情况:明明把Node.js卸载干净了,重装新版本后一运行node -v,显示的居然还是旧版本号,或者干脆各种npm、npx命令像幽灵一样反复横跳。说真的,Node.js的卸载比安装麻烦太多了——安装只需要一路Next&am…

作者头像 李华