MediaWiki 的 wikitext 标记的简单解析工具。
项目描述
维基文本解析器
用于MediaWiki的简单易用的 WikiText 解析库。
目的是允许用户轻松提取和/或操作维基文本中的模板、模板参数、解析器函数、表格、外部链接、维基链接、列表等。
<nav class="contents" id="table-of-contents">目录
</nav>安装
需要 Python 3.6+
点安装 wikitextparser
用法
>>> import wikitextparser as wtp
WikiTextParser 可以检测您的 wikitext 中的部分、解析器函数、模板、wiki 链接、外部链接、参数、表格、wiki 列表和评论。以下部分是其中一些功能的快速概述。
您可能还想查看测试模块以获取更多示例和可能的陷阱(预期失败)。
模板
>>> parsed = wtp.parse("{{text|value1{{text|value2}}}}")
>>> parsed.templates
[Template('{{text|value1{{text|value2}}}}'), Template('{{text|value2}}')]
>>> parsed.templates[0].arguments
[Argument("|value1{{text|value2}}")]
>>> parsed.templates[0].arguments[0].value = 'value3'
>>> print(parsed)
{{text|value3}}
pformat方法为模板返回一个漂亮打印的格式化字符串:
>>> parsed = wtp.parse('{{t1 |b=b|c=c| d={{t2|e=e|f=f}} }}')
>>> t1, t2 = parsed.templates
>>> print(t2.pformat())
{{t2
| e = e
| f = f
}}
>>> print(t1.pformat())
{{t1
| b = b
| c = c
| d = {{t2
| e = e
| f = f
}}
}}
Template.rm_dup_args_safe和Template.rm_first_of_dup_args方法可用于在模板调用中使用重复参数清理页面:
>>> t = wtp.Template('{{t|a=a|a=b|a=a}}')
>>> t.rm_dup_args_safe()
>>> t
Template('{{t|a=b|a=a}}')
>>> t = wtp.Template('{{t|a=a|a=b|a=a}}')
>>> t.rm_first_of_dup_args()
>>> t
Template('{{t|a=a}}')
模板参数:
>>> param = wtp.parse('{{{a|b}}}').parameters[0]
>>> param.name
'a'
>>> param.default
'b'
>>> param.default = 'c'
>>> param
Parameter('{{{a|c}}}')
>>> param.append_default('d')
>>> param
Parameter('{{{a|{{{d|c}}}}}}')
维基链接
>>> wl = wtp.parse('... [[title#fragmet|text]] ...').wikilinks[0]
>>> wl.title = 'new_title'
>>> wl.fragment = 'new_fragmet'
>>> wl.text = 'X'
>>> wl
WikiLink('[[new_title#new_fragmet|X]]')
>>> del wl.text
>>> wl
WikiLink('[[new_title#new_fragmet]]')
所有 WikiLink 属性都支持获取、设置和删除操作。
部分
>>> parsed = wtp.parse("""
... == h2 ==
... t2
... === h3 ===
... t3
... === h3 ===
... t3
... == h22 ==
... t22
... {{text|value3}}
... [[Z|X]]
... """)
>>> parsed.sections
[Section('\n'),
Section('== h2 ==\nt2\n=== h3 ===\nt3\n=== h3 ===\nt3\n'),
Section('=== h3 ===\nt3\n'),
Section('=== h3 ===\nt3\n'),
Section('== h22 ==\nt22\n{{text|value3}}\n[[Z|X]]\n')]
>>> parsed.sections[1].title = 'newtitle'
>>> print(parsed)
==newtitle==
t2
=== h3 ===
t3
=== h3 ===
t3
== h22 ==
t22
{{text|value3}}
[[Z|X]]
>>> del parsed.sections[1].title
>>>> print(parsed)
t2
=== h3 ===
t3
=== h3 ===
t3
== h22 ==
t22
{{text|value3}}
[[Z|X]]
表
提取表格的单元格值:
>>> p = wtp.parse("""{|
... | Orange || Apple || more
... |-
... | Bread || Pie || more
... |-
... | Butter || Ice cream || and more
... |}""")
>>> p.tables[0].data()
[['Orange', 'Apple', 'more'],
['Bread', 'Pie', 'more'],
['Butter', 'Ice cream', 'and more']]
默认情况下,值根据colspan和rowspan属性排列:
>>> t = wtp.Table("""{| class="wikitable sortable"
... |-
... ! a !! b !! c
... |-
... !colspan = "2" | d || e
... |-
... |}""")
>>> t.data()
[['a', 'b', 'c'], ['d', 'd', 'e']]
>>> t.data(span=False)
[['a', 'b', 'c'], ['d', 'e']]
调用 Table 的cells方法将表格单元格作为Cell对象返回。单元格对象提供了单独获取或设置每个单元格的属性或值的方法:
>>> cell = t.cells(row=1, column=1)
>>> cell.attrs
{'colspan': '2'}
>>> cell.set('colspan', '3')
>>> print(t)
{| class="wikitable sortable"
|-
! a !! b !! c
|-
!colspan = "3" | d || e
|-
|}
可以通过get_attr、set_attr、has_attr和 del_attr方法访问 Table、Cell 和 Tag 对象的 HTML 属性 。
列表
get_lists方法提供对 wikitext 中列表的访问。
>>> parsed = wtp.parse(
... 'text\n'
... '* list item a\n'
... '* list item b\n'
... '** sub-list of b\n'
... '* list item c\n'
... '** sub-list of b\n'
... 'text'
... )
>>> wikilist = parsed.get_lists()[0]
>>> wikilist.items
[' list item a', ' list item b', ' list item c']
sublists方法可用于获取当前列表的所有子列表或仅获取特定项目的子列表:
>>> wikilist.sublists()
[WikiList('** sub-list of b\n'), WikiList('** sub-list of b\n')]
>>> wikilist.sublists(1)[0].items
[' sub-list of b']
它还有一个可选的模式参数,其工作方式类似于列表,除了当前列表模式将作为前缀自动添加到其中:
>>> wikilist = wtp.WikiList('#a\n#b\n##ba\n#*bb\n#:bc\n#c', '\#')
>>> wikilist.sublists()
[WikiList('##ba\n'), WikiList('#*bb\n'), WikiList('#:bc\n')]
>>> wikilist.sublists(pattern='\*')
[WikiList('#*bb\n')]
使用 convert 方法将一种类型的列表转换为另一种类型。指定所需列表的起始模式有助于查找它们并提高性能:
>>> wl = wtp.WikiList(
... ':*A1\n:*#B1\n:*#B2\n:*:continuing A1\n:*A2',
... pattern=':\*'
... )
>>> print(wl)
:*A1
:*#B1
:*#B2
:*:continuing A1
:*A2
>>> wl.convert('#')
>>> print(wl)
#A1
##B1
##B2
#:continuing A1
#A2
各种各样的
parent和parents方法可用于分别访问节点的父节点或祖先节点:
>>> template_d = parse("{{a|{{b|{{c|{{d}}}}}}}}").templates[3]
>>> template_d.ancestors()
[Template('{{c|{{d}}}}'),
Template('{{b|{{c|{{d}}}}}}'),
Template('{{a|{{b|{{c|{{d}}}}}}}}')]
>>> template_d.parent()
Template('{{c|{{d}}}}')
>>> _.parent()
Template('{{b|{{c|{{d}}}}}}')
>>> _.parent()
Template('{{a|{{b|{{c|{{d}}}}}}}}')
>>> _.parent() # Returns None
如果查找特定类型的祖先,请使用可选的type_参数:
>>> parsed = parse('{{a|{{#if:{{b{{c<!---->}}}}}}}}')
>>> comment = parsed.comments[0]
>>> comment.ancestors(type_='ParserFunction')
[ParserFunction('{{#if:{{b{{c<!---->}}}}}}')]
要从其父对象中删除/移除任何对象,请使用del object[:]或del object.string。
remove_markup函数或plain_text方法可用于删除 wiki 标记:
>>> from wikitextparser import remove_markup, parse
>>> s = "'''a'''<!--comment--> [[b|c]] [[d]]"
>>> remove_markup(s)
'a c d'
>>> parse(s).plain_text()
'a c d'
与 mwparserfromhell 相比
mwparserfromhell是一个成熟且广泛使用的库,其用途与wikitextparser几乎相同。导致我创建wikitextparser的主要原因是mwparserfromhell在某些我需要它的情况下无法解析 wikitext。请参阅 mwparserfromhell 的问题40、42、88和其他相关问题。在许多情况下,wikitextparser可能能够为您提供更可接受的结果。
另请注意,wikitextparser仍在使用 0.xy 版本,这意味着API 不稳定,可能会在未来的版本中发生变化。
mwparserfromhell中的分词器是用 C 编写的。wikitextparser 中的分词主要是使用C 语言中的正则表达式库完成的。我没有严格比较这两个库的性能,即执行时间和内存使用情况。以我有限的经验,wikitextparser在实际情况下具有不错的性能,应该能够竞争,在某些情况下甚至可能几乎没有性能优势。
如果您有机会在性能或功能方面比较这些库,请通过在 github 上打开问题分享您的经验。
wikitextparser的一些独特功能是:提供对每个表格的单个单元格的访问、漂亮的打印模板、带有基本方法的 WikiList 类来处理列表,以及一些其他功能。
已知问题和限制
离线解析器不知道模板/参数的内容。例如,离线解析器无法知道标记[[{{z|a}}]]是否应该被视为 wikilink,这取决于{{z}}模板的内部工作。在这些情况下, wikitextparser 会尝试使用最佳猜测。[[{{z|a}}]]被视为 wikilink(为什么其他人会在 wikilink 标记中调用模板,即使它不是 wikilink,通常也不会造成任何伤害)。
本地化的命名空间名称是未知的,因此例如[[File:...]]链接被视为普通的维基链接。mwparserfromhell有类似的问题,请参阅#87和#136。作为一种解决方法,Pywikibot可用于确定命名空间。
Linktrails依赖于语言,不受支持。mwparserfromhell 也不支持。然而,鉴于轨迹模式并知道wikilink.span[1]是 wikilink 的结束位置,计算 WikiLink 的链接轨迹是可能的。
与外部链接相邻的模板永远不会被视为链接的一部分。实际上,这取决于模板的内容。示例:parse('http://example.com{{dead link}}').external_links[0].url == 'http://example.com'
有效扩展标签列表取决于 wiki 上安装的扩展。tags方法目前只支持英文维基百科上的那些。将来可能会添加一个配置选项来解决此问题。
wikitextparser目前不提供类似 ast.walk的方法来产生所有后代节点。