MediaWiki
如果您想从Mediawiki导入文章,您可以创建页面的ML转储,然后使用Django管理命令来导入它。该管理命令不是django-wiki的一部分,但我们将向您展示如何为自己的Django应用程序构建一个命令。
在管理命令中,我们将使用lhtml库来解析MediaWiki的HTML和unidecode将非拉丁字符转换为assimmon(以便创建它们的slug)。最后,它使用pandoc将MediaWiki标记转换为GitHub Flatemax Markdown(在这种情况下,这在django-wiki中表现良好)。
对于lhtml和unidecode,您可以使用它们来安装 pip install lxml unidecode
对于pandoc,你可以从https://pandoc.org/installing.html下载(确保pandoc二进制文件在你的PATH中)。
以下代码片段应放在 <your-app>/management/commands/import_mediawiki_dump.py
:
from django.core.management.base import BaseCommand
from wiki.models.article import ArticleRevision, Article
from wiki.models.urlpath import URLPath
from django.contrib.sites.models import Site
from django.template.defaultfilters import slugify
import unidecode
from django.contrib.auth import get_user_model
import datetime
import pytz
from django.db import transaction
import subprocess
from lxml import etree
def slugify2(s):
return slugify(unidecode.unidecode(s))
def convert_to_markdown(text):
proc = subprocess.Popen(
["pandoc", "-f", "mediawiki", "-t", "gfm"],
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
)
proc.stdin.write(text.encode("utf-8"))
proc.stdin.close()
return proc.stdout.read().decode("utf-8")
def create_article(title, text, timestamp, user):
text_ok = (
text.replace("__NOEDITSECTION__", "")
.replace("__NOTOC__", "")
.replace("__TOC__", "")
)
text_ok = convert_to_markdown(text_ok)
article = Article()
article_revision = ArticleRevision()
article_revision.content = text_ok
article_revision.title = title
article_revision.user = user
article_revision.owner = user
article_revision.created = timestamp
article.add_revision(article_revision, save=True)
article_revision.save()
article.save()
return article
def create_article_url(article, slug, current_site, url_root):
upath = URLPath.objects.create(
site=current_site, parent=url_root, slug=slug, article=article
)
article.add_object_relation(upath)
def import_page(current_site, url_root, text, title, timestamp, replace_existing, user):
slug = slugify2(title)
try:
urlp = URLPath.objects.get(slug=slug)
if not replace_existing:
print("\tAlready existing, skipping...")
return
print("\tDestorying old version of the article")
urlp.article.delete()
except URLPath.DoesNotExist:
pass
article = create_article(title, text, timestamp, user)
create_article_url(article, slug, current_site, url_root)
class Command(BaseCommand):
help = "Import everything from a MediaWiki XML dump file. Only the latest version of each page is imported."
args = ""
def add_arguments(self, parser):
parser.add_argument("file", type=str)
@transaction.atomic()
def handle(self, *args, **options):
user = get_user_model().objects.get(username="root")
current_site = Site.objects.get_current()
url_root = URLPath.root()
tree = etree.parse(options["file"])
pages = tree.xpath('// *[local-name()="page"]')
for p in pages:
title = p.xpath('*[local-name()="title"]')[0].text
print(title)
revision = p.xpath('*[local-name()="revision"]')[0]
text = revision.xpath('*[local-name()="text"]')[-1].text
timestamp = revision.xpath('*[local-name()="timestamp"]')[0].text
timestamp = datetime.datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ")
timestamp_with_timezone = pytz.utc.localize(timestamp)
import_page(
current_site,
url_root,
text,
title,
timestamp_with_timezone,
True,
user,
)
使用
一旦Django应用程序提供了管理命令,您就可以从命令行调用它:
python manage.py import_mediawiki_dump <mediawiki-xml-dump-file>``
进一步工作和定制
请注意以下几点:
该脚本定义了一个
root
用户分配导入页面的所有者(您可以将其保留为无或添加您自己的用户)。每个页面的多次修订尚未实施。相反,脚本会尝试选择最新的文本 (
text = revision.xpath('*[local-name()="text"]')[-1].text
).因此,建议您在MediaWiki转储中只包含每篇文章的最新修订版。你能通过
True
或False
到import_page()
以替换或跳过现有页面。