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转储中只包含每篇文章的最新修订版。

  • 你能通过 TrueFalseimport_page() 以替换或跳过现有页面。