OOCDC 是一种基于维基百科数据的在线-离线结合的数据策展方法 (An Online-Offline Combined Data Curation Method Based on Wikipedia Data).
方法介绍
concept_dataset/
├── concept_data_info.json
├── data
├── extract_DEIE_data.py
├── index_cache.pkl
├── pipeline.py
├── postprocess.py
├── process_wikidump.py
├── search_wiki.py
└── utils.py
数据准备
首先下载维基百科官方发布的 dump 文件. 然后用 WikiExtractor 提取为 JSON 样式的文本, 这样就获得了离线的维基百科知识库 (详见附录). 文件保存到项目根目录下的 extract_wikipedia/zhwiki-20240820-pages-articles-json/AA/
目录.
文本知识库的预处理
此时得到的 AA/
目录下有 wiki00
~wiki43
共 44 个文件. 这 44 个文件的每一行都是一个 JSON 字符串, 代表一个维基百科词条页面, 包含页面 id, 页面链接, 标题和文本内容等信息.
为了阅读和处理的方便, 还需进行以下步骤:
- 这些文件是 Unicode 编码, 不可直接阅读, 因此首先通过
process_wikidump.unicode2utf8()
将其转换为 UTF-8 格式, 保存到AA_readable/
目录. - 这些文件中有相当一部分是繁体中文, 可以通过 OpenCC 库转换为简体. 这里使用
process_wikidump.batch_convert()
方法. 转换后的文件保存在AA_zh-hans/
目录下. - 由于这 44 个文件大小不一 (每个文件中存储的词条页面数量即 JSON 行数差异很大), 不利于之后建立索引进行快速查找, 因此采用
process_wikidump.rebalance_file_size()
方法来重新平衡各文件的权重. 例如每个文件保存 1000 个词条, 这样文件数量会从 44 个增加到 2701 个, 但相应得索引效率也将大大提升. 重平衡后的文件保存在AA_rebalanced/
目录下. - 通过
process_wikidump.build_index_cache()
方法建立知识库索引, 可以根据页面 id 直接定向到该页面文本所在的知识库存储文件.
文本知识库的预处理阶段主要通过 process_wikidump.py
中的三个函数完成:
wikidump_dir = '../extract_wikipedia/zhwiki-20240820-pages-articles-json/'
raw_file_dir = os.path.join(wikidump_dir, 'AA')
readable_file_dir = os.path.join(wikidump_dir, 'AA_readable')
converted_file_dir = os.path.join(wikidump_dir, 'AA_zh-hans')
rebalanced_file_dir = os.path.join(wikidump_dir, 'AA_rebalanced')
unicode2utf8(raw_file_dir, readable_file_dir)
batch_convert(readable_file_dir, converted_file_dir, conversion='t2s')
rebalance_file_size(converted_file_dir, rebalanced_file_dir, lines_per_file=1000, filename_index_length=4)
经过处理后的extract_wikipedia/zhwiki-20240820-pages-articles-json/AA/
目录如下:
.
└── extract_wikipedia
└── zhwiki-20240820-pages-articles-json
├── AA
├── AA_readable
├── AA_rebalanced
└── AA_zh-hans
搜索目标页面
在search_wiki.py
中定义了WikiSearcher
类, 该类实现了基于 MediaWiki API 搜索指定类别或关键词的维基百科页面的方法. 其中,
api_search_sr()
基于 API: Search(sr) 来搜索与目标查询词相关的页面.api_search_cm()
基于 API: Categorymembers(cm) 来搜索某个类别下的所有页面.
此外还有以下辅助功能:
aggregate_search_result()
方法聚合搜索结果(文章页面)并进行去重.search_categories_start_from_ckpt()
针对 cm 搜索量高, 耗时长, 存在终端风险的问题, 设计了 checkpoint 保存和继续搜索的功能.manual_edit_category_queue_ckpt()
用来人工编辑检查点. 适合在队列中出现大量无用信息的情况. 手工将队列中不需要搜索的类别删除, 以节约搜索时间.
需要注意的是, 本步骤得到的搜索结果只是页面的 id 以及关键词所在的片段(snippet), 而不是完整的文本页面. 因此后续步骤需要根据搜索到的页面 id 来获取真正的完整页面文本内容.
ws = WikiSearcher(endpoint=f'https://zh.wikipedia.org/w/api.php')
query = '"疫情"'
ws.api_search_sr(query=query)
categories = ['礦業']
ws.search_categories(categories)
ws.manual_edit_category_queue_ckpt('./data/api_search/bfs_search_20240830-120342', 'ckpt_category_queue_1701_interrupt.pkl')
ws.search_categories_start_from_ckpt('./data/api_search/bfs_search_20240830-120342', 'ckpt_category_visited_10250_interrupt.pkl', 'edited_ckpt_category_queue_1701_interrupt.pkl')
bfs_search_result = './data/api_search/bfs_search_20240830-120342'
ws.aggregate_search_result(bfs_search_result)
数据分发和后处理
在pipeline.py
中, 实现了根据爬取到的页面 id 获取知识库中完整页面内容, 并将其保存为数据集的过程.
postprocess.deliver_page_obj()
依据页面id, 将知识库中的页面对象转存到对应的类别数据集文件中.
在获得初步的数据集后, 对其中的每个样本(每个页面的文本内容)进行后处理.
postprocess.data_clear()
实现了数据清洗postprocess.data_truncate()
对每个页面文本根据关键词(可指定)提取出两个小片段(指定文本长度范围), 来避免原始页面文本过长的问题.
s_time = time.time()
gen_emptyset()
# 分发维基百科数据
wiki_KB_dir = '../extract_wikipedia/zhwiki-20240820-pages-articles-json/AA_rebalanced/'
search_res_dir = './data/api_search/'
concept_data_info_file = 'concept_data_info.json'
with open(concept_data_info_file, 'r', encoding='utf-8') as f:
concept_data_info = json.load(f)
print(f'> Delivering wikipedia data examples according to {concept_data_info_file}...\n')
# 建立索引
file_list, _ = get_file_list(wiki_KB_dir)
print(f'> All files in {wiki_KB_dir}:\n{file_list}\n')
start_page_ids = get_start_page_ids(wiki_KB_dir, file_list)
print(f'> First page\'s id in each file: \n{start_page_ids}\n')
if os.path.exists('index_cache.pkl'):
user_input_2 = input('Page index cache already exists. Generate it again? [y/n] ')
if user_input_2 in ['y', 'Y']:
build_index_cache(wiki_KB_dir, file_list)
else:
build_index_cache(wiki_KB_dir, file_list)
# 依次处理每个类型的数据
for concept_type in concept_data_info.keys(): # 1~20
print(f'> Processing {concept_type=}. Deduplicating page-ids in search results...')
all_page_ids = set() # 存储不重复的page_id
for source_file in concept_data_info[concept_type]['data_source']:
if source_file.startswith('api_srsearch'):
with open(os.path.join(search_res_dir, source_file), 'r', encoding='utf-8') as sr_search_res:
pages = json.load(sr_search_res)
for page in pages:
if page['ns'] == 0:
all_page_ids.add(page['pageid'])
elif source_file.startswith('bfs_search'):
page_id_file = os.path.join(search_res_dir, source_file, 'aggregated_page_id.pkl')
if not os.path.exists(page_id_file):
ws = WikiSearcher()
ws.aggregate_search_result(save_dir_path=os.path.join(search_res_dir, source_file))
with open(page_id_file, 'rb') as bfs_search_res:
page_ids = pickle.load(bfs_search_res) # bfs搜索的结果已经是page_id的列表
all_page_ids = all_page_ids | set(page_ids) # 取并集
print(f'Parsed {source_file}')
success_cnt = deliver_page_obj(wiki_KB_dir, list(all_page_ids), concept_type)
concept_data_info[concept_type]['data_size'] = success_cnt
with open('concept_data_info.json', 'w', encoding='utf-8') as f:
json.dump(concept_data_info, f, ensure_ascii=False, indent=4)
e_time = time.time()
dataset_path = './data/'
data_clear(dataset_path)
data_truncate(dataset_path, min_len=80, max_len=200)
generate_total_dataset(dataset_path)
效果展示
附录
Wikipedia dump 介绍
zhwiki dumps 下载: https://dumps.wikimedia.org/zhwiki/
dump 文件以 .bz2 压缩文件的形式存储, 对于 multistream 文件, 还附加一个 index.txt 索引文件.
zhwiki-20240820-pages-articles-multistream-index.txt.bz2
是中文维基百科的一个索引文件,通常与 pages-articles-multistream
数据库 dump 文件一起使用。
- 索引文件:它包含了维基百科文章在多流(multistream)压缩存档中的偏移量(offset)信息。每一行通常包括文章标题和在主数据文件中的位置偏移。
- 快速查找文章:这个索引文件允许用户快速定位并解压特定的维基百科文章,而不需要解压整个
pages-articles-multistream
数据文件。这在处理大规模数据集时非常实用,因为它大大减少了数据处理时间。
查看 index 索引文件的头部:
查看 index 索引文件的尾部:
统计行数:
可知本 dump 词条 id 达到 8838104, 总共含 451 万个页面(每个页面对应一个 id).
WikiExtractor 介绍
简介
WikiExtractor 是一个 Python 脚本, 可以从 Wikipedia database backup dump 中提取和清理文本. 例如 https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2 是英文维基 (enwiki) 最新的 dump 文件.
安装方法:
pip install wikiextractor
- 或直接从 GitHub 仓库安装(推荐).
普通提取
使用方法: https://blog.51cto.com/u_16213634/10169447
由于耗时较长, 为避免中断将程序挂起:
nohup python -m wikiextractor.WikiExtractor -b 100M -o ../zhwiki-20240820-pages-articles ~/resource/wiki-dump-zh/zhwiki-20240820-pages-articles-multistream.xml.bz2 >> stdout.txt 2> stderr.txt &
遇到巨量报 template error 的 warning, 查询 GitHub issue 似乎属于正常情况.
程序会生成指定大小的一系列文件, 存储提取出的文本:
最终总共生成了 25 个文件(wiki_00
~wiki_24
). 打开第一个文件 wiki_00
, 显示前几行:
可以发现和维基百科网页版中的"数学"词条是基本一致的(少数文本未正常提取):
JSON 样式提取
如果在命令中附加--json
可选参数, 还可以直接将文本提取为 JSON 格式. 需要注意的是, 这种方式直接提取出的文本是 Unicode 转义字符, 需要手动转为 UTF-8 编码.
总共产生 44 个文件(wiki_00
~wiki_43
). 转码后的文件示例如下(wiki_00
第一行):
MediaWiki API 介绍
MediaWiki Action API 是一个 RESTful 网络服务, 允许用户进行页面创建 认证, 解析, 搜索等各种维基动作. 其使用方法很简单, 就是通过 HTTP 在客户端向服务器发送各种请求然后获得标准格式 (JSON 等) 的响应. 请求由端点 (endpoint) 和一组参数组成, 有 GET 请求和 POST 请求.
使用所有端点的 URL 格式都是 http://example.org/w/api.php. 例如:
GET 请求
参见: https://www.mediawiki.org/wiki/API:Tutorial#
在 URL 的查询字符串加入 action
参数来告诉 API 要进行哪种行动. 最常用的行动是 action=query
, 这允许从 wiki 中获取数据. 在该参数后附加另一个参数来告诉要进行哪一种查询模式:
prop
: 获得页面的属性(properties)list
: 获得匹配某个特定标准的页面的列表meta
: 获得关于 wiki 和用户的元信息(meta information).
最后还要加上 format
参数来告诉 API 结果是何种形式. 推荐的格式是 format=json
.
API: Query (action=query)
参见: https://www.mediawiki.org/wiki/API:Query
Query 模块下有三种子模块:
- Meta information: 有关 wiki 和登录用户的元信息。 [[#API Meta]]
- Properties: 页面属性,包括页面修订和内容。 [[#API Properties]]
- Lists: 符合特定条件的页面列表。[[#API Lists]]
其余可选参数:
indexpageids
: 包括一个额外的 pageids 部分,列出所有返回的页面 ID。export
: 导出所有给定或生成的页面的当前修订版本。exportnowrap
: 返回导出 XML,而不将其包装在 XML 结果中(与 Special:Export 格式相同)。只能与查询+导出一起使用。exportschema
: 导出时以给定版本的 XML 转储格式为目标。只能与查询+导出一起使用。iwurl
: 如果标题是跨维基链接,是否获取完整 URL。continue
: 当有更多结果可用时,请使用它继续。有关如何继续查询的更多详细信息,请访问 https://www.mediawiki.org/wiki/Special:MyLanguage/API:Continue 。rawcontinue
: 返回原始 query-continue 数据以继续。titles
: 需要处理的标题列表。pageids
: 要处理的页面 ID 列表。revids
: 要处理的修订 ID 列表。请注意,几乎所有查询模块都会将修订 ID 转换为相应的页面 ID,并处理最新的修订。只有 prop=revisions 对其响应使用精确的修订版本。generator
: 通过执行指定的查询模块获取要处理的页面列表。- 可选值(选择其一): allcategories, alldeletedrevisions, allfileusages, allimages, alllinks, allpages, allredirects, allrevisions, alltransclusions, backlinks, categories, categorymembers, deletedrevisions, duplicatefiles, embeddedin, exturlusage, fileusage, images, imageusage, iwbacklinks, langbacklinks, links, linkshere, messagecollection, mostviewed, pageswithprop, prefixsearch, protectedtitles, querypage, random, recentchanges, redirects, revisions, search, templates, transcludedin, watchlist, watchlistraw, wblistentityusage, readinglistentries
- 注意:生成器参数名称必须以“g”为前缀,请参阅示例。
redirects
: 自动解析 query+titles、query+pageids 和 query+revids 以及 query+generator 返回的页面中的重定向。converttitles
: 如有必要,将标题转换为其他变体。仅当 wiki 的内容语言支持变体转换时才有效。支持变体转换的语言包括 ban、en、crh、gan、iu、ku、mni、sh、shi、sr、tg、tly、uz、wuu、zgh 和 zh。
API: Properties
- categories: 列出页面所属的所有类别。
- [[#API Categories (prop=categories)]]
- categoryinfo: 返回有关给定类别的信息。
- cirrusbuilddoc: Dump of a CirrusSearch article document from the database servers
- cirruscompsuggestbuilddoc: Dump of the document used by the completion suggester
- cirrusdoc: Dump of a CirrusSearch article document from the search servers
- contributors: Get the list of logged-in contributors and the count of logged-out contributors to a page.
- deletedrevisions: Get deleted revision information.
- duplicatefiles: List all files that are duplicates of the given files based on hash values.
- extlinks: Returns all external URLs (not interwikis) from the given pages.
- extracts:返回给定页面的纯文本或有限的 HTML 摘录。
- fileusage: Find all pages that use the given files.
- globalusage: Returns global image usage for a certain image.
- imageinfo: Returns file information and upload history.
- images: Returns all files contained on the given pages.
- info: 获取基本页面信息。
- iwlinks: Returns all interwiki links from the given pages.
- langlinks: Returns all interlanguage links from the given pages.
- links: Returns all links from the given pages.
- linkshere: Find all pages that link to the given pages.
- mmcontent: Get the description and targets of a spamlist
- pageimages: Returns information about images on the page, such as thumbnail and presence of photos.
- pageprops: Get various page properties defined in the page content.
- pageterms: Get the Wikidata terms (typically labels, descriptions and aliases) associated with a page via a sitelink.
- pageviews: Shows per-page pageview data (the number of daily pageviews for each of the last pvipdays days).
- redirects: Returns all redirects to the given pages.
- revisions: Get revision information.
- stashimageinfo: Returns file information for stashed files.
- templates: Returns all pages transcluded on the given pages.
- transcludedin: Find all pages that transclude the given pages.
- transcodestatus: Get transcode status for a given file page.
- videoinfo: Extends imageinfo to include video source (derivatives) information
- wbentityusage: Returns all entity IDs used in the given pages.
- flowinfo: Deprecated. Get basic Structured Discussions information about a page.
- description: Internal. Get a short description a.k.a. subtitle explaining what the target page is about.
- mapdata: Internal. Request all Kartographer map data for the given pages
API: Categories (prop=categories)
参见: https://www.mediawiki.org/wiki/API:Categories
prop=categories (cl)
clprop
clshow
cllimit
clcontinue
clcategories
cldir
例子: 获取 Albert Einstein 页面所属的类别列表:
https://en.wikipedia.org/w/api.php?action=query&prop=categories&titles=Albert%20Einstein&utf8=
{
"continue": {
"clcontinue": "736|Academic_staff_of_ETH_Zurich",
"continue": "||"
},
"query": {
"pages": {
"736": {
"pageid": 736,
"ns": 0,
"title": "Albert Einstein",
"categories": [
{
"ns": 14,
"title": "Category:1879 births"
},
{
"ns": 14,
"title": "Category:1955 deaths"
},
{
"ns": 14,
"title": "Category:19th-century German Jews"
},
...
API: Lists
参见: https://www.mediawiki.org/wiki/API:Lists
list 模块用来返回数据的聚合, 例如从 wiki 获取的页面或者单个页面中的链接.
在 URL 中通过 action=query&list=list1|list2
来使用 list API. 其中|
用来分割不同可选子模块.
- allcategories : 列出给定类别中的所有页面。
- alldeletedrevisions: 列出用户或命名空间中所有已删除的修订。
- allfileusage
- allimages
- alllinks: 列出指向给定命名空间的链接,按标题排序。
- allpages: 列出给定命名空间内符合特定条件的所有页面。
- allredirects
- alltransclusions
- allusers
- backlinks
- blocks
- categorymembers: 列出属于给定类别的页面。
- [[#API Categorymembers (list=categorymembers)]]
- deletedrevs
- embeddedin
- exturlusage
- filearchive
- imageusage
- iwbacklinks
- langbacklinks
- logevents
- pagepropnames: 列出 wiki 上使用的所有页面属性。
- pageswithprop: 列出使用给定页面属性的所有页面。
- prefixsearch: 对页面标题执行前缀搜索。
- protectedtitles
- querypage: 获取基于 QueryPage 的特殊页面提供的列表。
- random
- recentchanges
- search: 通过标题或内容文本匹配对 wiki 页面执行高级搜索。
- [[#API Search (list=search)]]
- tags
- usercontribs
- users
- watchlist
- watchlistraw
API: Categorymembers (list=categorymembers)
list=categorymembers (cm)
cmtitles
: 要枚举哪个类别(必需)。必须包含Category:
前缀。不能与cmpageid
一起使用。cmpageid
: 要枚举的类别的页面 ID。不能与cmtitle
一起使用。cmprop
: 包含哪些信息.cmnamespace
: 仅包含这些命名空间中的页面。请注意,可以使用cmtype=subcat
或cmtype=file
来代替cmnamespace=14
或cmnamespace=6
。cmtype
: 要包含哪种类型的类别成员。cmcontinue
: 当有更多结果可用时,请使用它继续。cmlimit
: 返回的最大页数。cmsort
: 排序依据的属性。]cmdir
: 排序方向.cmstart
cmend
cmstarthexsortkey
cmendhexsortkey
cmstartsortkeyprefix
cmendsortkeyprefix
API: Search (list=search)
参见: https://www.mediawiki.org/wiki/API:Search
list=search (sr)
使用维基百科的
list=search
API 时,最多只能获取 10,000 条搜索结果。这是由于 API 的限制,即使你尝试使用分页(通过continue
参数)获取更多结果,也无法突破这一上限。
-
srsearch
: 搜索与该值匹配的页面标题或内容。您可以使用搜索字符串来调用特殊搜索功能,具体取决于 wiki 的搜索后端实现的功能。 -
srnamespace
: 仅在这些名称空间内搜索。- 可选值:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 90, 91, 92, 93, 100, 101, 102, 103, 104, 105, 106, 107, 486, 487, 710, 711, 828, 829, 1198, 1199, 2600, 5500, 5501
, 默认值: 0
在维基百科中,内容被组织在不同的命名空间中,每个命名空间都有特定的用途。例如:
- 0(主命名空间或“Main”): 包含所有的条目内容(即百科全书的正文部分)。
- 1(讨论命名空间或“Talk”): 包含与主条目内容相关的讨论页面。
- 2(用户命名空间或“User”): 包含用户个人页面。
- 4(维基百科命名空间或“Wikipedia”): 包含维基百科项目相关的页面(如方针和指南)。
- 其他命名空间: 包括文件、模板、类别等。
- 可选值:
-
srlimit
: 总共返回多少页面- 设置为整数(1~500)或者
max
, 默认值 10
- 设置为整数(1~500)或者
-
sroffset
: 当有更多结果可用时,请使用它继续。有关如何继续查询的更多详细信息,请访问 https://www.mediawiki.org/wiki/Special:MyLanguage/API:Continue- 一个不小于 0 的整数, 默认值 0
-
srqiprofile
: 查询要使用的独立配置文件(影响排名算法)- 可选值(选择其一):
classic, classic_noboostlinks, empty, engine_autoselect, popular_inclinks, popular_inclinks_pv, wsum_inclinks, wsum_inclinks_pv
, 默认值:engine_autoselect
- 可选值(选择其一):
-
srwhat
: 进行何种搜索.- 可选值(选择其一):
nearmatch, text, title
- 可选值(选择其一):
-
srinfo
: 返回何种元数据.- 可选值:
rewrittenquery, suggestion, totalhits
, 默认值:totalhits|suggestion|rewrittenquery
- 可选值:
-
srprop
: 返回何种属性.- 可选值:
categorysnippet, extensiondata, isfilematch, redirectsnippet, redirecttitle, sectionsnippet, sectiontitle, size, snippet, timestamp, titlesnippet, wordcount, hasrelated, score
, 默认值:size|wordcount|timestamp|snippet
size
: 页面大小wordcount
: 页面词数timestamp
: 页面最后修改的时间戳snippet
: 添加页面片段, 并带有查询术语突出显示标记titlesnippet
: 添加页面标题, 并带有查询术语突出显示标记redirecttitle
: 添加匹配重定向的标题redirectsnippet
: 添加匹配重定向的标题, 并带有查询术语突出显示标记sectiontitle
sectionsnippet
isfilematch
: 添加一个布尔值, 指示搜索是否与文件内容匹配categorysnippet
: 添加匹配的类别名称, 并带有查询术语突出显示标记
- 可选值:
-
srinterwiki
: 在搜索中包含跨维基结果(如果有)。- 设置
srinterwiki
为true
时,你在某个语言版本的维基百科中搜索关键词时,不仅会得到该语言版本的搜索结果,还会得到其他语言版本的相关文章。这对研究多语言内容或需要跨语言比较时特别有用。
- 设置
-
srenablerewrites
: 启用内部查询重写。一些搜索后端可以将查询重写为另一个查询,这被认为可以提供更好的结果,例如通过纠正拼写错误。 -
srsort
: 设置返回结果的顺序- 可选值(选择其一):
create_timestamp_asc, create_timestamp_desc, incoming_links_asc, incoming_links_desc, just_match, last_edit_asc, last_edit_desc, none, random, relevance, user_random
, 默认值:relevance
- 可选值(选择其一):
匹配模式
精确匹配: 通过引号将搜索词括起来
"srsearch": "太阳能发电" # 只会匹配包含完整短语“太阳能发电”的页面
前缀匹配: 在搜索词后加上 “*
”, 可以匹配以指定前缀开头的所有词
"srsearch": "太阳*" # 将匹配“太阳能”、“太阳光”、“太阳辐射”等所有以“太阳”开头的词语
布尔运算符:
- AND: 结合多个关键词, 所有关键词都必须出现在结果中
- OR: 结合多个关键词, 任一关键词出现在结果中即可
- NOT: 排除包含某个关键词的结果
"srsearch": "太阳能 & 发电" # 匹配同时包含“太阳能”和“发电”的页面
"srsearch": "太阳能 | 光伏" # 匹配包含“太阳能”或“光伏”的页面
"srsearch": "太阳能 -光伏" # 匹配包含“太阳能”但不包含“光伏”的页面
通配符:
- 用法: 使用
*
或?
- 效果:
*
匹配零个或多个字符,?
匹配单个字符
"srsearch": "太阳?能" # 匹配“太阳”,“太阳光”等
锚定词搜索:
- 用法: 使用
intitle:
或intext:
- 效果: 仅在标题或内容中进行搜索
"srsearch": "intitle:太阳能" # 只搜索标题中包含“太阳能”的页面
嵌套查询:
- 用法: 结合圆括号
()
进行复杂的逻辑组合 - 效果: 控制搜索词之间的逻辑关系,允许更复杂的查询
"srsearch": "(太阳能 & 发电) | (光伏 & 发电)"
API: Meta
参见: https://www.mediawiki.org/wiki/Special:MyLanguage/API:Meta
API: Continue
参见: https://www.mediawiki.org/wiki/Special:MyLanguage/API:Continue
很多时候,您无法在一次 API 查询中获得所需的所有数据。发生这种情况时,API 将在结果中附加一个附加元素( continue
)以指示还有更多数据。
返回的元素将由两部分组成:
- 一部分是一个子元素,名字也为
continue
。如果有数据可以继续, 这通常有一个包含符号||
的关联值。 - 第二部分将是一个子元素(或多个子元素),其名字是查询中使用的 list 的缩写,以单词
continue
为前缀。(因此,例如,使用categorymembers
的查询的子元素将是cmcontinue
,使用allcategories
的查询的子元素将是accontinue
,使用protectedtitles
的查询的子元素将是ptcontinue
,等等)
要在 continue
元素存在时检索更多数据,您必须将第二个子元素作为参数添加到下一个 API 请求的 URL 中。例如,如果使用 allcategories
列表的查询包含其他结果,则下一个 API 查询应包含 accontinue=
作为参数,以及第一个查询结果中 accontinue
的值。要获取所有结果,可以重复此操作,直到 API 结果中没有 continue 元素,这表明没有更多数据与查询匹配。
当您使用 generator 和 properties 发出 API 请求时,API 结果可能会发出 continue 信号,因为到目前为止还有更多页面 properties 需要检索(在这种情况下,将返回同一组页面,但包含下一组属性),因为生generator 有更多页面,或者两者兼而有之。从 1.25 版开始,API 将返回 batchcomplete
元素,以指示当前“批次”页面的所有数据都已返回,并且 continue
元素不包含属性的延续数据,但可以包含生成器的延续数据。当将生成器与可能需要延续的 prop 模块一起使用时,这可以避免为数千个页面构建组合结果集。
例子
例如, 要搜索匹配"黑神话"的页面标题或者内容, HTTP GET 请求的 URL 是:
https://zh.wikipedia.org/w/api.php?action=query&list=search&srsearch=黑神话&utf8=&format=json
其中:
https://zh.wikipedia.org/w/api.php
: 主端点, 此处为中文维基action=query
: 从 wiki 获取数据list=search
: 取得满足标准的页面的列表srsearch=黑神话
: 指明要搜索的页面标题或内容utf8=
: 注意默认搜索结果不是 UTF8 编码format=json
: 指明响应是 JSON 格式
Python 代码:
import requests
S = requests.Session()
URL = "https://zh.wikipedia.org/w/api.php"
SEARCHPAGE = "黑神话"
PARAMS = {
"action": "query",
"format": "json",
"list": "search",
"srsearch": SEARCHPAGE
}
R = S.get(url=URL, params=PARAMS)
DATA = R.json()
# 以字典的形式访问json数据
if DATA['query']['search'][0]['title'] == SEARCHPAGE:
print("Your search page '" + SEARCHPAGE + "' exists on English Wikipedia")
得到的响应为:
{
"batchcomplete": "",
"continue": {
"sroffset": 10,
"continue": "-||"
},
"query": {
"searchinfo": {
"totalhits": 5062
},
"search": [
{
"ns": 0,
"title": "黑神话:悟空",
"pageid": 7170977,
"size": 46413,
"wordcount": 4798,
"snippet": "《\u003Cspan class=\"searchmatch\"\u003E黑\u003C/span\u003E\u003Cspan class=\"searchmatch\"\u003E神话\u003C/span\u003E:悟空》是一款由游戏科学开发和发行的动作角色扮演游戏,被媒体誉为中国首款“3A游戏”,游戏于2024年8月20日登入Windows(Steam、Epic Games、WeGame)及PlayStation 5平台,Xbox Series X/S版的发售日期待定。",
"timestamp": "2024-08-29T07:03:40Z"
},
{
"ns": 0,
"title": "希腊神话",
"pageid": 21511,
"size": 52399,
"wordcount": 7351,
"snippet": "希臘\u003Cspan class=\"searchmatch\"\u003E神話\u003C/span\u003E(英語:Greek mythology,希臘語:ελληνική μυθολογία)是原本语出古希腊人的一系列\u003Cspan class=\"searchmatch\"\u003E神话\u003C/span\u003E故事。这些\u003Cspan class=\"searchmatch\"\u003E神话\u003C/span\u003E讲述了宇宙的由来和本质,涉及各色神明、英雄及神秘生物,还谈及希腊人自身所参与的各种秘仪与宗教仪式的起源,它们又为何如此重要,因此希腊\u003Cspan class=\"searchmatch\"\u003E神話\u003C/span\u003E",
"timestamp": "2024-06-17T08:51:56Z"
},
...
]
}
}
其中:
batchcomplete
: 表示当前批次的所有数据均已返回ns
: 命名空间(namespace)