Moli 使用教程:从命令行抓取到批量页面内容导出

安装 Moli,选择 Markdown 与语义树输出,用批处理脚本保存来源清单和失败记录,并判断页面等待、布局与非 HTML 数据的处理方式。

亿牛云技术团队2026年10月28日6 分钟阅读

临时整理一组网页时,不一定需要先创建完整爬虫项目。Moli 提供命令行读取页面材料的方式,适合把网页内容接到脚本、文档整理或后续提取流程里。

本文从单页 Markdown 开始,扩展为一个保留 URL 清单、内容文件和失败记录的批处理。重点是知道输出是什么、何时等待以及哪类响应不应该被当作网页正文处理,不罗列全部命令参数。

准备输入地址

先在浏览器找到下列页面并确认内容,再从地址栏复制完整地址。服务或仓库地址从相应账户设置、官方项目的接入说明或克隆菜单取得。不要从示例输出中反推真实地址。

  • MOLI_INSTALLER_URL:lexmount/moli 官方 Releases 中 moli-installer.sh 安装脚本的下载地址。
  • DOC_URL_1:Python 教程 introduction.html 页地址。
  • DOC_URL_2:同目录 controlflow.html 页地址。

在执行后续命令的同一个 Bash/WSL 终端中设置:

export MOLI_INSTALLER_URL='<paste-the-actual-moli-installer-url>'
export DOC_URL_1='<paste-the-actual-doc-url-1>'
export DOC_URL_2='<paste-the-actual-doc-url-2>'

下文 JSON 或任务参数中的 <变量名> 是待替换标记,提交前填写刚复制的实际值;JSON 不会自动展开环境变量。结果示例中的 example.16yun.cn 只表示来源字段的形状,不是本文部署的演示站。

安装与第一次读取

以下操作使用 Linux/macOS 的 Bash;Windows 用户可以通过 WSL 沿用流程。按照 Moli 官方安装说明,安装预编译版本:

curl --proto '=https' --tlsv1.2 -fsSL   "$MOLI_INSTALLER_URL" | sh
moli --version

安装器下载的是发布版本,因此升级后先记录实际版本,再判断本文参数是否仍适用。安装后找不到命令时,检查安装器提示的 PATH,而不是反复下载。

先抓取一个明确的文档页:

moli fetch --dump markdown --wait-until done   "$DOC_URL_1" > introduction.md

检查 introduction.md 是否包含目标标题和主要段落。命令退出成功、文件非空是第一层检查,还需要排除登录提示、错误页和导航主导的输出。

Markdown 与语义树分别适合什么

Markdown 适合正文阅读和进一步文本处理;语义树更适合查看页面结构和交互对象。遇到“内容好像缺了一块”时,可以换一种材料形式比较,而不是先认定模型或解析器失败。

moli fetch --dump semantic_tree_text --wait-selector body   "$DOC_URL_1" > introduction-tree.txt

--wait-selector body 只说明 body 已存在,不保证动态数据已完成。真实应用应该选择与任务相关的就绪元素。例如字段在某列表出现后才完整,就等待该列表的稳定标记;不要把 body 当成通用的页面完成条件。

Moli 的结构读取与布局计算是不同路径。Markdown 或 DOM 获取不应被理解成“完全不执行 JavaScript”;截图和坐标相关任务则需要考虑 --layout。本文批处理只读文本,不增加截图依赖。

批处理时保留每个输入的去向

新建 urls.txt,每行一个地址:

printf '%s\n' "$DOC_URL_1" "$DOC_URL_2" > urls.txt

再创建 export_pages.sh。脚本为每个输入分配编号,用临时文件接收输出;命令成功且内容非空后才移成正式文件。

#!/usr/bin/env bash
set -u
batch_dir=$(mktemp -d "./moli-output.XXXXXX")
printf 'id\turl\tfile\n' > "$batch_dir/index.tsv"
printf 'id\turl\texit_code\n' > "$batch_dir/failed.tsv"
index=0
while IFS= read -r url || [ -n "$url" ]; do
  [ -z "$url" ] && continue
  index=$((index + 1))
  name=$(printf 'page-%04d.md' "$index")
  if moli fetch --dump markdown --wait-until done "$url"       > "$batch_dir/$name.part" 2> "$batch_dir/$name.log"; then
    if [ -s "$batch_dir/$name.part" ]; then
      mv "$batch_dir/$name.part" "$batch_dir/$name"
      printf '%s\t%s\t%s\n' "$index" "$url" "$name" >> "$batch_dir/index.tsv"
    else
      printf '%s\t%s\tempty_output\n' "$index" "$url" >> "$batch_dir/failed.tsv"
    fi
  else
    code=$?
    printf '%s\t%s\t%s\n' "$index" "$url" "$code" >> "$batch_dir/failed.tsv"
  fi
done < urls.txt
printf '结果目录:%s\n' "$batch_dir"

执行:

bash export_pages.sh

每轮建立新目录,避免旧文件伪装成本次成功输出。TSV 的行数不包含标题行时,合格条数加失败条数应等于非空输入行数。脚本没有发现新 URL,也没有自动抓取文档附件;这些不是本轮任务范围。

每行 URL 必须是普通单行地址,输入中不能包含制表符或换行。来自用户系统的任意 URL 应先在服务边界验证,不直接把本地维护的清单接口当成公开抓取服务。

怎样解释导出的材料

index.tsv 把来源映射到文件,.log 保存每页命令诊断,.part 保留未被接受的材料。文件编号只是本批次位置,不是文档的长期身份。

如果输入重定向到新版文档,这份 TSV 仍保存请求地址,不能声称它已经记录最终地址。长期索引需要另外保留重定向关系、页面版本和观测时间;单次内容导出可以先明确这个边界。

Markdown 文件中出现标题层级、链接与代码围栏是预期结构。输出格式转换可能改变排版,不代表原始 HTTP 字节得到无损归档。需要长期证据留存时,另外保留原始响应与响应元信息。

什么时候需要交互或另一种下载方式

若内容需要点击后出现,Moli 的 --eval 可以执行页面表达式,但它不是完整业务工作流的替代品。使用时先确认能定位正确元素,再执行动作与等待。带 dump 时,表达式返回值不会自动变成正文输出;表达式执行失败也不应该被当成“没有匹配数据”。

遇到 RSS、JSON、PDF 或 WASM 等资源,先看响应类型。需要原始文件时,用对应下载或解析工具,不强迫它们经过 Markdown 转换。例如保存明确的文件 URL 可以使用:

curl --fail --location --output attachment.pdf   'https://example.16yun.cn/files/manual.pdf'

这里的附件地址是占位符,需换成真实资源。下载后检查 MIME、文件签名和内容,不只看扩展名。对于 API JSON,按字段解析;对于 PDF,选择适当文档提取器。这些输入有自己的数据合同。

常见问题与处理

文件为空。 先看对应日志和退出状态。若命令失败,处理加载或参数错误;若成功但为空,核对页面身份与输出模式。不要只在下游读文件时补空字符串。

动态内容缺失。 查看源站真正的就绪标记,调整等待条件;如果任务要求复杂登录、筛选或多次交互,考虑专用浏览器自动化流程,而非不断叠加固定等待。

语义树有字段,Markdown 没有。 比较格式转换是否丢失上下文。选择更适合目标字段的材料或单独提取字段,不把 Markdown 当成原始页面的完整拷贝。

批量结果不齐。 先对账 index 与 failed,再定位具体页。补采失败页时用新批次目录,合并时保留来源映射,避免编号相同的文件互相覆盖。

想截图却发现布局不对。 检查是否启用了布局相关能力,并核对页面就绪状态。文本导出任务的成功,不能推断截图和坐标操作也已正确。

命令行工具的优势是容易组合。只有把来源、内容与错误分别保存,组合后的流程才不会把一次失败隐藏成一份看似正常的文本文件。

需要企业代理方案?

我们可根据目标站点、并发规模与稳定性目标提供定制方案。