数字人文作品集 Rubric 评分:TEI、IIIF 与静态站点可复现交付
2026/9/19 21:10:12 网站建设 项目流程

简介:这份《数字人文作品集 Rubric1》PDF文档,是田纳西大学数字人文研究生证书课程使用的作品集评估标准原文,面向准备提交证书作品集的研究生、课程负责人及数字人文项目指导教师。它解决的是作品集如何组织、展示与评分的问题,涵盖公共网站呈现、项目多样性、技术应用与创新、内容质量、呈现与交流等维度,并附1分不可接受至4分优秀的评分系统。资源包仅含1个PDF文件,约109KB,轻量便于查阅和打印,适合作为课程要求对照或评分参考。文档同时说明作品集需覆盖每门DH课程的代表项目、明确个人贡献、标注引用来源,并鼓励参与年终展示论坛。已有82人学习,读者可据此核对作品集是否完整、技术路径是否多元、反思叙述是否到位,也可用于院系设计评审表或指导学生自查。

1. 数字人文作品集卡在 Rubric 上的真实原因

很多人做数字人文作品集时默认「网站好看=分高」,交了才发现视觉呈现只占一两成,大头压在研究问题清不清晰、数据来源可不可追溯、方法别人能不能复跑。田纳西大学数字人文研究生证书课程的那份 Rubric1,就是一份把人文研究规范和数字化交付绑在一起的检查表。

它不问用了什么框架,只问这份作品集作为研究产出站不站得住:有研究问题、有语料、有标注或编码过程、有解释、有持久可访问的地址。对工程师来说熟悉的是构建部署和版本控制,陌生的是「为什么这个可视化不能只是炫技」。

下面按读懂评分维度、搭站点骨架、处理 TEI/IIIF/PDF 这几块硬骨头、做提交前自检的顺序走。新手能照着做,熟手重点看参数和排错那两章。

2. 拆解 Rubric1 的评分维度:把研究论证翻译成可检查项

一份评分表最怕被当成作文题。真正可操作的做法是:把每个维度的措辞拆成「评审看什么」和「我能留下什么技术证据」,后者是你能提前自证的部分。

2.1 数字人文作品集的三层结构

数字人文作品集通常是三层叠起来的,理解这点比记评分表更重要。

论证层是研究问题、方法选择、证据链和结论;数据层是语料、转录、编码、元数据、授权状态、版本快照;呈现层是站点、可视化、无障碍、持久链接。评审读你的作品集时,视线是按论证层 → 数据层 → 呈现层走的,但打分时的权重往往是倒过来的错觉:呈现层最显眼,分数占比却最低。

常见的失败模式是这三层脱节:论证层写「分析 19 世纪书信中的迁徙网络」,数据层却只有一张没有出处的 CSV,呈现层放了一张漂亮的地图。评审会直接问:CSV 从哪来、转录规则是什么、地名如何归一化。答不上来,论证层那一栏就悬了。

2.2 评分维度与可执行检查的映射

把 Rubric 的抽象措辞落到具体命令和文件上,是整篇文章里最省时间的一步。

Rubric 维度评审实际在看什么可留下的技术证据检查手段
研究问题与论证问题是否具体、是否可证伪首页 research statement、分章导航人工通读,限时三分钟能否说清
数据来源与授权语料出处、版权状态sources.yaml、license 字段、引用页脚本校验必填字段非空
方法与可复现性别人能否照着跑出同样结果Makefile、依赖锁文件、处理脚本make all从零跑通
元数据与可发现性是否被检索和引用Dublin Core、JSON-LD、sitemap结构化数据校验器
呈现与无障碍语义结构、对比度、替代文本语义标签、alt、跳转链接pa11y / axe
过程留痕工作是不是持续做的commit 历史、tag、变更日志git log --stat

这张表可以直接抄进项目根目录的README.md,每完成一项就打勾。注意最后一栏:过程留痕在不少评分表里是被低估的加分项,因为它是唯一能证明「这不是最后一周赶出来的」的客观数据。

2.3 元数据字段落位:Dublin Core 与 front matter 的对应

元数据不是装饰。数字人文项目里它承担三件事:让作品可被检索、让来源可被追溯、让机器能理解版本关系。

常见的做法是在每个作品条目里用 YAML front matter 声明元数据,构建时再映射到 Dublin Core 或 schema.org。下面是一个条目示例:

# content/works/letters-1890.md title: "1890 年代书信中的迁徙路径" date: 2024-11-02 dcterms: creator: "Your Name" contributor: ["档案室 A", "档案室 B"] source: "Box 12, Folder 3" rights: "CC-BY-4.0" language: "zh-Hans" type: "Dataset" spatial: "Knoxville, TN" temporal: "1890/1899" method_summary: "OCR + 人工校对 + 地名归一化到 GeoNames ID" reproduce: "make corpus && make map"

字段说明:dcterms.type建议用 Dublin Core 的 DCMI Type 词表取值(Dataset、Text、Image、InteractiveResource 等),不要自造;spatialtemporal是元数据里最容易被漏掉的两项,也是评审判断「你知不知道自己材料的边界」的直接依据;reproduce字段写一行命令,比在正文里写三页方法描述管用。

source要写到文件夹级别,而不是「某某档案馆」。数字人文评审对出处颗粒度很敏感,写到 Box/Folder 级别会立刻显得专业。

2.4 用 Git 历史作为过程证据

评分表里如果出现「项目发展过程」「迭代」这类字眼,它能被验证的唯一形式就是提交历史。别在最后一天把整个项目一次性推上去。

我一般会这样组织:先用一次提交固定目录骨架和 README,之后按数据、处理脚本、可视化、文档分开提交,每个阶段性成果打一个 tag。

# 查看提交粒度是否均匀,避免"一次性大提交" git log --pretty=format:'%h %ad %s' --date=short # 看每个阶段改了多少文件,判断过程是否连续 git log --stat --since="3 months ago" | head -60 # 打阶段标签,方便评审定位版本 git tag -a v0.3-corpus-cleaned -m "语料校对完成,地名归一化到 GeoNames"

参数说明:--pretty=format里的%ad--date=short输出简洁日期,方便一眼看出提交是否集中在几天内;--since用来圈定课程周期;git tag -a创建带说明的附注标签,比轻量标签多一条可追溯的元数据。

如果确实前期没规划,补救办法是写一份CHANGELOG.md,按日期说明每一步做了什么、为什么改。它不如真实提交历史有力,但比没有强。

3. 用静态站点生成器搭田纳西大学数字人文证书课程的作品集骨架

静态站点是这个场景的默认选择:构建产物是纯文件,十年后还能打开,不需要维护数据库,也能整包交给图书馆归档。Hugo 和 Jekyll 都常见,Hugo 构建快、模板灵活,适合条目多的作品集。

3.1 目录结构与最小可运行基线

先定结构,再写内容。结构混乱的作品集,后面加元数据和无障碍都会加倍痛苦。

portfolio/ ├── config/_default/hugo.toml ├── content/ │ ├── _index.md # research statement │ ├── works/ # 每个作品一个条目 │ ├── data/ # 数据集说明页 │ └── about.md ├── data/ │ └── sources.yaml # 语料与出处清单一处维护 ├── static/ │ ├── iiif/ # IIIF 清单 │ └── files/ # 可下载的 PDF、CSV ├── layouts/ │ ├── _default/single.html │ └── partials/schema.html # JSON-LD 注入 ├── scripts/ │ └── check.py # 提交前自检 └── Makefile

sources.yaml单独抽出来的理由是:出处信息会同时出现在条目页、引用页和 PDF 里,一处维护能避免三处不一致。评审如果发现同一个语料在三个地方写法不同,会直接怀疑数据可靠性。

3.2 Hugo 建站与本地预览的命令与参数

从零到能在浏览器里看到东西,命令不多,但参数值得记清楚。

# 初始化站点 hugo new site portfolio --force # 新建一个作品条目(自动带上 front matter 模板) hugo new content works/letters-1890.md # 本地预览:-D 显示草稿,--bind 让容器或局域网可访问 hugo server -D --port 1313 --bind 0.0.0.0 --disableFastRender # 正式构建:压缩输出,生成 sitemap hugo --minify --gc --baseURL "https://example.org/portfolio/"

参数说明:-D只影响本地预览,不会把草稿发到线上;--disableFastRender在改模板时更稳,避免页面局部不刷新造成误判;--gc清理无用缓存资源;--baseURL在正式构建时必须显式指定,否则生成的绝对链接会指向localhost,而这点在本地几乎看不出来,上线后才炸。

提示:baseURL写错最常见的症状是 RSS、sitemap 和 JSON-LD 里的地址全是本机地址。构建完先grep -r "localhost" public/扫一遍。

3.3 结构化数据注入:让作品集真正被检索到

元数据只写在 front matter 里,只有站内能看见。要让搜索引擎和聚合平台理解条目,得在页面里输出 JSON-LD。

<!-- layouts/partials/schema.html --> {{ with .Params.dcterms }} <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "{{ .type | default "CreativeWork" }}", "name": {{ $.Title | jsonify }}, "creator": { "@type": "Person", "name": {{ .creator | jsonify }} }, "datePublished": {{ $.Date.Format "2006-01-02" | jsonify }}, "license": {{ .rights | jsonify }}, "inLanguage": {{ .language | jsonify }}, "spatialCoverage": {{ .spatial | jsonify }}, "temporalCoverage": {{ .temporal | jsonify }}, "isBasedOn": {{ .source | jsonify }} } </script> {{ end }}

这段模板的逻辑是:只有条目的 front matter 里存在dcterms才输出脚本,避免空字段污染结构化数据。jsonify负责转义,别手写引号,标题里出现引号或换行会直接让 JSON 失效。@type给一个默认值,是因为 schema.org 的校验器对类型缺失比较敏感。

构建完用一行命令抽检页面上有没有合法的 JSON-LD:

# 从构建产物里提取 JSON-LD 并用 python 校验语法 grep -o '<script type="application/ld+json">.*</script>' public/works/*/index.html \ | sed 's/<[^>]*>//g' | python3 -m json.tool > /dev/null && echo "JSON-LD OK"

3.4 构建与发布流水线:GitHub Actions 最小配置

自动化构建的意义不只是省事,它能让「可复现」这件事有客观记录。评审点开仓库能看见每次构建都通过,比任何描述都直接。

# .github/workflows/build.yml name: build-portfolio on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive # 主题作为子模块时必须开 - uses: peaceiris/actions-hugo@v3 with: hugo-version: "latest" extended: true # 用到 SCSS 处理时需要 extended - run: make check # 元数据、断链、无障碍自检 - run: hugo --minify --gc --baseURL "https://example.org/portfolio/" - uses: actions/upload-pages-artifact@v3 with: path: ./public

参数说明:submodules: recursive是主题用 git submodule 引入时最容易踩的坑,漏了会构建出一个没有样式的裸页面;extended: true只在需要处理 SCSS/SASS 时才要,普通项目可以省;make check放在构建之前,是让数据问题先失败,而不是等页面生成完才发现。

4. 数字人文项目的三类技术排错:TEI、IIIF 与 PDF 交付

到这里站点骨架已经能跑,剩下的问题几乎全在格式上。数字人文用到的格式不算多,但每一个都有自己的脾气,出错信息还偏晦涩。

4.1 TEI XML 校验与高频命名空间错误

TEI 是文本编码的通用方案,作品集里通常用来展示转录成果。手写 TEI 几乎一定会出问题,所以校验步骤要固定下来。

# 结构良好性检查(最快,先过这一关) xmllint --noout transcript.xml # 用 TEI 官方 Relax NG 模式做完整校验 xmllint --noout --relaxng tei_all.rng transcript.xml # 只看错误行号,便于批量修 xmllint --noout --relaxng tei_all.rng transcript.xml 2>&1 | grep -o 'line [0-9]*' | sort -u

参数说明:--noout表示不回显 XML 内容,只报错;--relaxng指定模式文件,TEI 的模式文件通常叫tei_all.rng,需要从 TEI 官方发布包中取得,别自己拼。三条命令的顺序建议固定:先结构、再模式、最后批量统计。

高频错误有三类。第一类是命名空间没写,根元素必须带xmlns="http://www.tei-c.org/ns/1.0",漏了会报一大堆「元素未知」。第二类是xml:id重复,尤其是复制粘贴一个<persName>段落时最容易发生,改掉即可。第三类是元素嵌套顺序,TEI 对<teiHeader>内部的子元素顺序有硬性要求,<fileDesc>必须在<encodingDesc>之前。这类错误的报错信息只会说「元素 X 在此处不允许」,不会告诉你正确顺序,得回去查模式定义。

注意:把 TEI 文件直接cat进 HTML 模板里展示是常见错误做法。先做 XSLT 或 Python 转换,输出干净的 HTML 片段,再交给模板渲染,否则浏览器会把命名空间当成未知标签处理。

4.2 IIIF 清单手写起步与图像查看器接入

作品集里放图像,尤其是手稿、地图、照片,用 IIIF 是行业惯例,因为查看器可缩放、可对比、可被别人复用。清单文件手写一份最小可用的,比从零学整套 API 快。

{ "@context": "http://iiif.io/api/presentation/3/context.json", "id": "https://example.org/iiif/manifest-1", "type": "Manifest", "label": { "zh-Hans": ["1890 年手稿第 1 页"] }, "items": [ { "id": "https://example.org/iiif/canvas/1", "type": "Canvas", "height": 1200, "width": 1600, "items": [ { "id": "https://example.org/iiif/canvas/1/page", "type": "AnnotationPage", "items": [ { "id": "https://example.org/iiif/canvas/1/annotation", "type": "Annotation", "motivation": "painting", "body": { "id": "https://example.org/iiif/image/1/full/max/0/default.jpg", "type": "Image", "format": "image/jpeg", "height": 1200, "width": 1600 }, "target": "https://example.org/iiif/canvas/1" } ] } ] } ] }

字段说明:type必须是Manifest,且每个层级的type都不能省,这是 IIIF 3.0 最常出错的地方;label用语言映射对象而不是裸字符串,方便多语种;Canvas 的宽高要与图像实际像素一致,写错了查看器会画偏;图像服务地址末尾的/full/max/0/default.jpg是 IIIF Image API 的固定路径段,顺序不能换。

清单写好后放进static/iiif/,页面里引入查看器:

<script src="/js/openseadragon.min.js"></script> <div id="viewer" style="width:100%;height:600px"></div> <script> // tileSources 指向 IIIF 清单,查看器会自动解析 canvas OpenSeadragon({ id: "viewer", tileSources: "/iiif/manifest-1.json", prefixUrl: "/js/images/", showNavigator: true, // 多页手稿建议开导航缩略图 sequenceMode: true // 清单含多个 canvas 时开启连续浏览 }); </script>

参数说明:sequenceMode只有在清单含多个 Canvas 时才有意义,单页开了会看到多余控件;showNavigator对大幅地图和手稿很有用,但对小尺寸图片是负担。

4.3 无障碍与 PDF 交付:从 HTML 到可提交文件

评分表里「呈现」那一栏,无障碍通常单列。检查用命令行就够,不必装浏览器插件。

# 对本地预览或构建产物做 WCAG2AA 检查 pa11y http://localhost:1313/works/letters-1890/ --standard WCAG2AA # 批量检查内链和外链 lychee --no-progress './public/**/*.html'

参数说明:--standard WCAG2AA指定标准等级,课程类评分表一般按 AA;lychee扫构建产物而不是源文件,因为最终交付的是 HTML。常见失败项集中在三处:装饰性图片没写alt=""(写了空串是对的,完全不写是错的)、对比度不足、跳转链接缺失。

如果评分表要求提交 PDF,不要用浏览器「打印为 PDF」草草了事。那样的文件没有标签结构、没有阅读顺序,屏幕阅读器读出来是一团乱。

# 用 weasyprint 从 HTML 生成带结构信息的 PDF weasyprint index.html output.pdf \ --base-url ./ \ --pdf-variant pdf/a-3b # 校验 PDF 结构完整性 qpdf --check output.pdf # 严格模式校验,暴露元数据和结构问题 pdfcpu validate -mode strict output.pdf

参数说明:--pdf-variant pdf/a-3b输出归档级 PDF,适合长期保存,也是不少图书馆的接收要求;--base-url决定相对路径资源的解析基准,漏了会导致图片丢失;qpdf --check只看结构是否损坏,pdfcpu validate -mode strict检查更细,两者互补。生成后务必用阅读器打开确认标题层级、书签和替代文本是否保留,这些在自动化检查里查不出来。

5. 让 Rubric 评分可复现:自检脚本与交付前的最后三个动作

评分表最怕「我以为是加分项,其实评审没看见」。解决办法是把能自动化的检查都自动化,跑一次脚本,输出的就是一份自证清单。

# scripts/check.py —— 提交前自检,返回非零表示有问题 import sys, re, pathlib, yaml REQUIRED = ["title", "date", "dcterms"] DCTERMS = ["creator", "source", "rights", "type", "language"] errors = [] for md in pathlib.Path("content/works").glob("*.md"): text = md.read_text(encoding="utf-8") m = re.match(r"^---\n(.*?)\n---", text, re.S) if not m: errors.append(f"{md}: 缺少 front matter") continue fm = yaml.safe_load(m.group(1)) or {} for k in REQUIRED: if k not in fm: errors.append(f"{md}: 缺字段 {k}") for k in DCTERMS: # 元数据必填项逐个检查 if not (fm.get("dcterms") or {}).get(k): errors.append(f"{md}: dcterms.{k} 为空") # 检查图片是否都有 alt 属性 for html in pathlib.Path("public").rglob("*.html"): for tag in re.findall(r"<img[^>]*>", html.read_text(encoding="utf-8")): if "alt=" not in tag: errors.append(f"{html}: 图片缺 alt -> {tag[:60]}") print("\n".join(errors) if errors else "check passed") sys.exit(1 if errors else 0)

逻辑说明:脚本只做三件确定性判断——必填字段是否存在、Dublin Core 核心项是否为空、图片是否有alt。之所以不做模糊校验(比如判断「研究问题写得好不好」),是因为那部分只能人工读。sys.exit(1)让它在 CI 里能直接卡住构建。

把它接到 Makefile 上,一个命令跑完全套:

.PHONY: check build all check: python3 scripts/check.py lychee --no-progress './public/**/*.html' hugo --minify --gc --baseURL "https://example.org/portfolio/" qpdf --check public/files/portfolio.pdf build: hugo --minify --gc all: check build

交付前最后三个动作,按顺序做。第一,关掉本地预览服务,从干净目录重新make all,确认没有依赖任何本机缓存或临时文件——这一步能查出「在我电脑上能跑」的经典问题。第二,用无痕窗口打开构建产物,键盘只用 Tab 走一遍首屏,看焦点顺序是否合理、跳转链接是否第一个出现。第三,翻回README.md,把reproduce字段里的命令实际粘进终端跑一次,确认它真的能跑出结果,而不是三个月前写的备忘录。

最后一个容易被忽略的细节:在content/_index.md第一段用一句话写清研究问题,限定在 40 字以内。评审打开首页的前十秒决定了他对你整份作品集的预期,这句话比后面所有技术实现都更值钱。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询