📑 查看全课大纲(第 11 / 26 节)
- 1.知识图谱和语音技术概述
- 2.典型知识库项目简介
- 3.知识图谱技术概览
- 4.典型应用案例
- 5.早期知识表示简介
- 6.基于语义网的知识表示框架
- 7.典型知识库项目的知识表示
- 8.基于本体工具的知识建模实践
- 9.面向非结构化数据的知识抽取
- 10.面向结构化数据的知识抽取
- 11.面向半结构化数据的知识抽取
- 12.实践:基于百科数据的知识抽取
- 13.面向文本的知识抽取
- 14.知识挖掘
- 15.从一个例子开始
- 16.图数据库介绍
- 17.什么是知识融合
- 18.知识融合的基本技术流程
- 19.典型知识融合工具简介
- 20.典型案例简介
- 21.LIMES实战演练
- 22.知识推理
- 23.语义搜索
- 24.知识问答
- 25.IBM watson Lite
- 26.行业知识图谱应用
面向半结构化数据的知识抽取
约 23 分钟
小象实战讲义 · 知识图谱
在构建知识图谱的过程中,除了从纯文本和结构化数据库中抽取知识,互联网上还存在着大量半结构化数据。这类数据介于结构化与非结构化之间,拥有一定的固定格式或模板,例如百科页面的信息框(infobox)、网页中的列表和表格。本节将系统讲解如何从半结构化数据中高效、准确地抽取知识,并形成标准化的 RDF 三元组,这是构建大规模开放域知识图谱(如 DBpedia)的关键技术。
💡 核心导读
- 半结构化数据的定义与来源:理解什么是半结构化数据,其典型代表(如维基百科、商品列表页)及其在知识抽取中的优势。
- 百科类知识抽取实践:深入剖析 DBpedia 和 Zhishi.me 的构建过程,学习如何从维基百科的页面结构(标题、摘要、信息框、分类、重定向等)中抽取并映射成 RDF 三元组。
- 网页包装器技术:掌握从普通 HTML 网页中抽取结构化信息的三种方法:手工编写 XPath/CSS 选择器、基于标注的包装器归纳学习以及无监督的自动抽取。
- Web Table 的实体链接:了解如何将网页表格中的单元格内容链接到知识库中的实体,解决表格数据缺乏上下文时的实体消歧问题。
半结构化数据概览
半结构化数据是指那些具有一定格式或结构,但结构不严格、不完全遵循固定模式的数据。与关系数据库的规整表格相比,它的结构更灵活;与纯文本相比,它又蕴含了可被机器识别的模式信息。
典型来源包括:
- 百科页面:如维基百科、百度百科。页面包含标题、摘要、信息框、分类标签、内部链接等结构化部分。
- 网页列表与详情页:如电商网站的商品列表、新闻网站的新闻摘要页。它们通常由后台模板生成,HTML 结构重复。
- 网页表格(Web Table):HTML 中的
<table>标签内容,呈现行、列结构。
抽取优势:由于存在显式的结构标记(如 HTML 标签、维基语法),抽取规则相对明确,准确率和效率通常高于从纯文本中抽取。
百科类知识抽取:以 DBpedia 为例
DBpedia 是从维基百科中抽取结构化信息的经典项目,它形成了一个大规模、多语言的关联数据集(Linked Data)。其核心思想是将维基百科页面的各个组成部分,按照预设的规则,映射到 RDF 词汇和三元组上。DBpedia 覆盖 127 种语言、约 2800 万个实体,包含数亿条三元组。
抽取内容与映射规则
以下以一个虚构的维基百科页面“Tim Berners-Lee”(蒂姆·伯纳斯-李)为例,说明 DBpedia 的抽取过程:
页面标题 → 实体标签
- 来源:页面标题 “Tim Berners-Lee”。
- 映射:生成三元组,使用
rdfs:label表示实体的可读标签。
@prefix dbr: <http://dbpedia.org/resource/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . dbr:Tim_Berners-Lee rdfs:label "Tim Berners-Lee"@en .摘要 → 实体描述
- 来源:页面首段(Short Abstract)和全文摘要(Long Abstract)。
- 映射:首段映射为
rdfs:comment,全文摘要映射为dbo:abstract。
@prefix dbo: <http://dbpedia.org/ontology/> . @prefix dbr: <http://dbpedia.org/resource/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . dbr:Tim_Berners-Lee rdfs:comment "Sir Timothy John Berners-Lee, also known as TimBL, is an English engineer and computer scientist..."@en . dbr:Tim_Berners-Lee dbo:abstract "Sir Timothy John Berners-Lee (born 8 June 1955), also known as TimBL, is an English engineer and computer scientist, best known as the inventor of the World Wide Web."@en .信息框(Infobox) → 实体类型与属性
- 来源:页面右侧的“信息框”模板,如
{{Infobox person}}。 - 映射:
- 模板名:映射为实体的类型(
rdf:type)。例如,Infobox person映射为dbo:Person。 - 属性-值对:信息框内的每一行(如
birth_date = {{Birth date and age|1955|6|8|df=y}})映射为一个属性三元组。属性名需要对齐到统一的 DBpedia 本体(dbo:)。
- 模板名:映射为实体的类型(
@prefix dbr: <http://dbpedia.org/resource/> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix dbo: <http://dbpedia.org/ontology/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . dbr:Tim_Berners-Lee rdf:type dbo:Person . dbr:Tim_Berners-Lee dbo:birthDate "1955-06-08"^^xsd:date . dbr:Tim_Berners-Lee dbo:birthPlace dbr:London .- 两级抽取策略:DBpedia 对 infobox 属性采用两层处理。第一层是 Generic Infobox Extraction(通用抽取,即 raw infobox properties)——直接保留 Wikipedia 中原有属性名(如
birthdate和dateOfBirth分别保留,不做映射),落在dbp:命名空间下,属性名会随维基模板漂移。第二层是 Mapping-based Infobox Extraction(基于映射的抽取)——在此基础上定义 DBpedia 本体(dbo:),通过人工规则将同义属性名对齐到统一本体属性(目前共有约 2795 个本体属性),这一二次对齐过程即本体对齐(Ontology Alignment)。
脚注:课件 P119 把这两层的名称标反了(将“保留原始属性名”标成 Mapping-based、将“定义 dbo: 本体做对齐”标成 Generic),此处按 DBpedia 官方口径更正。
- 来源:页面右侧的“信息框”模板,如
图片与分类层级
- 图片(Images):Wikipedia Commons 中的图片映射为
foaf:depiction。 - 分类层级:Wikipedia 分类系统中分类之间的父子关系映射为
skos:broader(上位)和skos:narrower(下位)。
- 图片(Images):Wikipedia Commons 中的图片映射为
分类与链接 → 主题与关联
- 分类(Categories):页面底部的分类标签(如
[[Category:Computer pioneers]])映射为实体的主题(dct:subject)。 - 内部链接(Wikilinks):正文中的
[[World Wide Web]]链接映射为dbo:wikiPageWikiLink,表示页面间的关联。
@prefix dct: <http://purl.org/dc/terms/> . @prefix dbr: <http://dbpedia.org/resource/> . @prefix dbo: <http://dbpedia.org/ontology/> . dbr:Tim_Berners-Lee dct:subject <http://dbpedia.org/resource/Category:Computer_pioneers> . dbr:Tim_Berners-Lee dbo:wikiPageWikiLink dbr:World_Wide_Web .- 分类(Categories):页面底部的分类标签(如
重定向与消歧 → 同义词与歧义处理
- 重定向(Redirects):如 “TimBL” 页面重定向到 “Tim Berners-Lee”。这表示两个名称指向同一实体,使用
owl:sameAs表示等价。 - 消歧页(Disambiguation):如 “Apple” 可能指水果或公司。消歧页列出了多个可能实体,使用
dbo:wikiPageDisambiguates关联。
@prefix owl: <http://www.w3.org/2002/07/owl#> . @prefix dbr: <http://dbpedia.org/resource/> . @prefix dbo: <http://dbpedia.org/ontology/> . dbr:TimBL owl:sameAs dbr:Tim_Berners-Lee . <http://dbpedia.org/resource/Apple_(disambiguation)> dbo:wikiPageDisambiguates <http://dbpedia.org/resource/Apple_Inc.> , <http://dbpedia.org/resource/Apple_(fruit)> .- 重定向(Redirects):如 “TimBL” 页面重定向到 “Tim Berners-Lee”。这表示两个名称指向同一实体,使用
从 DBpedia 到 Zhishi.me
Zhishi.me 是第一份中文大规模开放链接数据(Chinese Linking Open Data)项目,由东南大学研发。它采用了与 DBpedia 相似的思想,但数据源融合了中文维基百科、百度百科和互动百科,包含约 1000 万实体、2 亿三元组。
构建挑战与流程:
- 多源数据抽取:分别从三个百科站点抽取半结构化信息。
- 知识融合:这是核心难点,包括:
- 实体融合(主语对齐):判断不同来源的“清华大学”页面是否指向同一实体。通常利用别名、关键属性(如地址、创办时间)进行冲突检测与合并。
- 属性融合(谓语对齐):将“出生日期”、“生于”、“出生时间”等不同表述,对齐到统一的属性(如
dbo:birthDate)。 - 值融合(宾语对齐):对于同一实体的同一属性,不同来源可能给出不同值。采用“精确性原则”(选最具体的日期)或“大多数原则”进行裁决。
- 服务发布:提供 Linked Data 访问、SPARQL 端点、API 和数据快照(Dump)等多种访问方式。
以下是一个简化的 Python 示例,模拟从一段类似百科摘要的文本中,使用正则表达式抽取特定属性(如“始建时间”):
import re
# 模拟一段百科摘要文本
abstract_text = "灵隐寺,又名云林寺,位于浙江省杭州市西湖区,始建于东晋咸和元年(326年)。"
# 定义抽取“始建时间”的正则模板
pattern_construction = r'始建于([^,。]+?)(?=。|$)'
# 定义抽取“别名”的正则模板
pattern_alias = r'又名([^,。]+)'
match_con = re.search(pattern_construction, abstract_text)
match_alias = re.search(pattern_alias, abstract_text)
if match_con:
print(f"始建时间: {match_con.group(1)}") # 输出: 始建时间: 东晋咸和元年(326年)
if match_alias:
print(f"别名: {match_alias.group(1)}") # 输出: 别名: 云林寺网页包装器生成技术
对于非百科类的半结构化网页(如商品列表、企业黄页),我们需要一种通用的方法来抽取信息,这种方法被称为包装器(Wrapper)。包装器是一个程序,它能够根据网页的结构化模式,定位并抽取目标数据。
方法一:手工编写包装器
原理:人工分析网页 HTML 结构,编写 XPath 或 CSS 选择器表达式来定位元素。
- XPath:一种在 XML/HTML 文档中导航和选择节点的语言。
- CSS 选择器:一种用于选择 HTML 元素的模式。
示例:假设要抽取某电商列表页中第一个商品的价格。
- HTML 片段:
<div id="J_goodsList"> <ul> <li class="item">...<div class="p-price"><strong>3488</strong>元</div>...</li> <li class="item">...</li> </ul> </div> - 手工编写的 XPath:
//*[@id="J_goodsList"]/ul/li[1]/div/div[@class='p-price']/strong - 手工编写的 CSS 选择器:
#J_goodsList > ul > li:nth-child(1) > div > div.p-price > strong
优缺点:简单直接,适用于少量、稳定的页面。但维护成本高,页面结构一变就失效。
方法二:包装器归纳(有监督学习)
原理:通过标注少量训练样本(在网页上标记出要抽的数据),让算法自动学习出能够覆盖这些样本的、具有泛化能力的抽取规则(XPath)。
流程:
- 网页清洗与标注:清理不规范的 HTML,并人工标注出需要抽取的数据项。
- 包装器空间生成:为每个标注项生成其精确的 XPath,然后通过泛化算法(如自底向上合并、编辑距离计算)生成一组候选的、更通用的 XPath。
- 包装器评估与选择:用准确率(Precision)和召回率(Recall)评估候选包装器,选择综合性能最好的。
示例:假设标注了表格中两个“姓名”单元格 n1 和 n2。
- n1 的 XPath:
/html/body/table/tbody/tr[2]/td[1] - n2 的 XPath:
/html/body/table/tbody/tr[3]/td[1] - 泛化后的候选包装器 A:
/html/body/table/tbody/*/td[1](匹配所有行的第一列) - 泛化后的候选包装器 B:
//td(匹配所有 td 单元格) - 评估:包装器 A 能精确抽取出所有“姓名”,准确率高;包装器 B 会抽出所有单元格,噪声大。因此选择 A。
方法三:自动抽取(无监督学习)
原理:不需要人工标注。基于观察:同一网站中结构相似的页面通常由同一个后台模板生成。通过聚类算法将结构相似的网页分组,然后通过比较组内网页的 HTML 树结构差异,自动推断出模板和数据的边界,从而生成包装器。
代表工具:RoadRunner。 核心算法:把两个相似页面解析成标签序列,通过标记序列对齐(tag sequence alignment)做差,归纳出无并集(union-free)正则文法,识别出共同的模板部分和可变的数据部分,用通配符(如 #PCDATA 代表文本,(..)+ 代表重复结构)生成包装器。
优缺点:无需标注,适合大规模站点。但可能抽取出无关信息,且对网页相似度要求高。
以下是一个使用 Python 标准库 xml.etree.ElementTree,通过 ElementPath 从一段 HTML 中抽取信息的示例:
import xml.etree.ElementTree as ET
html_content = """<html><body>
<div id="J_goodsList">
<ul>
<li class="item"><div class="p-name">华为P10</div><div class="p-price"><strong>3488</strong>元</div></li>
<li class="item"><div class="p-name">iPhone 12</div><div class="p-price"><strong>5999</strong>元</div></li>
</ul>
</div>
</body></html>"""
root = ET.fromstring(html_content)
# 使用 ElementPath 定位商品名称和价格(等价于简化版 XPath)
names = [div.text for div in root.findall('.//div[@class="p-name"]')]
prices = [strong.text for strong in root.findall('.//div[@class="p-price"]/strong')]
for name, price in zip(names, prices):
print(f"商品: {name}, 价格: {price}元")
# 输出:
# 商品: 华为P10, 价格: 3488元
# 商品: iPhone 12, 价格: 5999元从 Infobox 属性字典到 RDF 三元组
前面介绍了 DBpedia 如何将 infobox 的每个属性-值对映射为 RDF 三元组。下面用 rdflib 演示这一过程:先将 Wikipedia infobox 解析为 Python 字典,再按映射规则转换为 RDF 三元组。
from rdflib import Graph, Namespace, Literal, RDF, RDFS, XSD
# 模拟从 Wikipedia infobox 模板解析出的属性字典
infobox = {
"name": "Tim Berners-Lee",
"birth_date": "1955-06-08",
"birth_place": "London",
}
# 定义 DBpedia 命名空间
DBR = Namespace("http://dbpedia.org/resource/")
DBO = Namespace("http://dbpedia.org/ontology/")
g = Graph()
person = DBR["Tim_Berners-Lee"]
# infobox 模板名 -> rdf:type
g.add((person, RDF.type, DBO.Person))
# 页面标题 -> rdfs:label
g.add((person, RDFS.label, Literal(infobox["name"], lang="en")))
# infobox 属性值 -> dbo: 属性三元组
g.add((person, DBO.birthDate, Literal(infobox["birth_date"], datatype=XSD.date)))
g.add((person, DBO.birthPlace, DBR[infobox["birth_place"]]))
# 验证:遍历图中的三元组
for s, p, o in g:
print(f"({s}) -> ({p}) -> ({o})")
print(f"共 {len(g)} 条三元组")Web Table 的实体链接
网页中的表格(Web Table)是一种特殊的半结构化数据。要理解其语义,需要将单元格中的文本链接(Link)到知识库中的特定实体,即实体链接(Entity Linking)。
挑战:表格缺乏丰富的上下文文本,但拥有行、列的结构化语境。
流程:
- 候选实体生成:对于单元格字符串“夏洛特”,通过字符串匹配在知识库中找到候选实体:夏洛特市(北卡罗来纳)、夏洛特市(伊利诺伊)、夏洛特黄蜂队等。
- 实体消歧:利用表格的行列上下文进行联合消歧。
- 同行数据:同一行的“夏洛特”和“迈克尔·乔丹”可能相关。“迈克尔·乔丹”作为篮球运动员,更可能链接到“夏洛特黄蜂队”(他曾是老板)。
- 同列数据:同一列的“洛杉矶”、“达拉斯”、“芝加哥”都是城市名,这提示该列可能为“城市”属性,从而帮助“夏洛特”消歧到城市实体。
- 构建与求解消歧图:将表格中所有单元格及其候选实体构建成一个图,节点包括字符串节点和实体节点,边表示它们之间的关联(如共现、语义相似度)。使用图算法(如 PageRank 的变种)进行全局推理,为每个单元格选择最合适的实体。
生成三元组:完成实体链接后,可以推导出表格隐含的关系。例如,一个“球员-国籍-俱乐部”表格,在链接实体后,可以生成 (里奥·梅西, 国籍, 阿根廷)、(卡卡, 效力于, AC米兰) 等三元组。
📝 动手练一练
- 概念辨析:面向半结构化数据的知识抽取,与面向纯文本的知识抽取(如关系抽取)相比,主要优势和挑战分别是什么?
- 动手构造:观察以下简化的维基百科信息框文本,请尝试设计规则,将其转换为 RDF 三元组(使用
dbo:前缀)。假设dbr:Python_(programming_language)是主体。
提示:{{Infobox programming language | name = Python | paradigm = Multi-paradigm: functional, object-oriented | designer = Guido van Rossum | first_release = 1991 }}paradigm可映射为dbo:programmingParadigm,designer可映射为dbo:designer,first_release可映射为dbo:releaseDate。
👉 点击查看参考答案
- 优势:半结构化数据具有显式的结构标记(HTML标签、维基语法),抽取规则更明确,准确率和效率通常更高,可大规模自动化处理。 挑战:需要处理不同网站或页面间结构差异(包装器维护),需要对抽取出的异构属性进行对齐与融合(本体匹配),且页面结构可能动态变化导致包装器失效。
- 三元组构造示例:
@prefix dbr: <http://dbpedia.org/resource/> . @prefix dbo: <http://dbpedia.org/ontology/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <http://dbpedia.org/resource/Python_(programming_language)> dbo:programmingParadigm "Multi-paradigm: functional, object-oriented"@en ; dbo:designer dbr:Guido_van_Rossum ; dbo:releaseDate "1991"^^xsd:gYear .
本章小结
本节深入探讨了从半结构化数据中抽取知识的核心方法。我们学习了如何将维基百科丰富的页面结构转化为标准的 RDF 知识,理解了 DBpedia 和 Zhishi.me 的构建精髓。同时,掌握了针对通用网页的包装器技术,从手工编写到自动学习,以及如何处理网页表格中的实体链接问题。这些技术是构建和扩展大规模知识图谱数据源的关键。
📋 行动清单
- 访问 DBpedia:打开 DBpedia 页面,搜索一个你熟悉的人物或概念,查看其被抽取出的 RDF 数据,直观感受从半结构化到结构化知识的转换。
- 练习 XPath:使用浏览器的开发者工具(F12),打开一个新闻或商品列表页,尝试在 Console 中使用
$x('你的XPath')来定位页面中的特定元素。 - 思考融合问题:如果想从豆瓣电影和 IMDb 两个网站抽取电影信息构建图谱,你会面临哪些“知识融合”方面的挑战?尝试列出 2-3 点。
—— 小象教研组
领取《小象 11GB VIP 课件资料包与大厂真题手册》
包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。
- ✔完整 Python / 数据分析 Jupyter 实战源码
- ✔大厂真实业务数据集与练习题
- ✔微信扫码添加顾问免费领取;想学什么,直接告诉顾问
微信扫码添加顾问