Open7

【解決?】wikiextractorでテキストにするときに、箇条書きの部分が消えてしまう

ピン留めされたアイテム
はるはる

多少の不具合はあるものの、extract.pyのcompact関数を、以下のように変更したら、箇条書きやインデント部分の欠損はなくなっていそうです。

確認済み不具合

  • {{lang-en|The Apothecary Diaries}}、{{lang-zh|药屋少女的呢喃}}のような部分が消えてしまう。
  • 見出し(登場人物、主人公)などが変なところに出力されたり、なくなったりする。

変更後のコード

def compact(text, mark_headers=False):
    """Deal with headers, lists, empty sections, residuals of tables.
    :param text: convert to HTML
    """

    page = []  # list of paragraph
    headers = {}  # Headers for unfilled sections
    emptySection = False  # empty sections are discarded
    listLevel = ''  # nesting of lists

    for line in text.split('\n'):

        if not line:
            continue
        # Handle section titles
        m = section.match(line)
        if m:
            title = m.group(2)
            lev = len(m.group(1))
            if Extractor.HtmlFormatting:
                page.append("<h%d>%s</h%d>" % (lev, title, lev))
            if title and title[-1] not in '!?':
                title += '.'

            if mark_headers:
                title = "## " + title

            headers[lev] = title
            # drop previous headers
            headers = { k:v for k,v in headers.items() if k <= lev }
            emptySection = True
            continue
        # Handle page title
        if line.startswith('++'):
            title = line[2:-2]
            if title:
                if title[-1] not in '!?':
                    title += '.'
                page.append(title)
        # handle indents
        elif line[0] == ':':
            page.append(line.lstrip(':*#;'))  # 変更点:コメントアウトを解除
        # handle lists
        elif line[0] in '*#;:':
            if Extractor.HtmlFormatting:
                i = 0
                for c, n in zip_longest(listLevel, line, fillvalue=''):
                    if not n or n not in '*#;:':
                        if c:
                            page.append(listClose[c])
                            listLevel = listLevel[:-1]
                            continue
                        else:
                            break
                    # n != ''
                    if c != n and (not c or (c not in ';:' and n not in ';:')):
                        if c:
                            # close level
                            page.append(listClose[c])
                            listLevel = listLevel[:-1]
                        listLevel += n
                        page.append(listOpen[n])
                    i += 1
                n = line[i - 1]  # last list char
                line = line[i:].strip()
                if line:  # FIXME: n is '"'
                    page.append(listItem[n] % line)
            else:
                page.append(line.lstrip(':*#;'))  # 変更点:リストの行を追加
        elif len(listLevel):
            for c in reversed(listLevel):
                page.append(listClose[c])
            listLevel = []

        # Drop residuals of lists
        elif line[0] in '{|' or line[-1] == '}':
            continue
        # Drop irrelevant lines
        elif (line[0] == '(' and line[-1] == ')') or line.strip('.-') == '':
            continue
        elif len(headers):
            if Extractor.keepSections:
                items = sorted(headers.items())
                for (i, v) in items:
                    page.append(v)
            headers.clear()
            page.append(line)  # first line
            emptySection = False
        elif not emptySection:
            page.append(line)
            # dangerous
            # # Drop preformatted
            # elif line[0] == ' ':
            #     continue

    return page
はるはる

起きた問題

wikiextractorで、xmlからテキスト化するときに、箇条書きの部分が消えてしまう。
--listsオプションを追加すると、箇条書きの部分がそのままらしい(参照:Python】Wikipedia のデータセットを取得し、文章を抽出する方法。)が、うまくいかない。

試したこと

pip install wikiextractor==3.0.4

をしたうえで、

wikiextractor --lists ファイル名


usage: wikiextractor [-h] [-o OUTPUT] [-b n[KMG]] [-c] [--html] [-l] [-ns ns1,ns2] [--templates TEMPLATES] [--no-templates] [--escapedoc] [--processes PROCESSES] [-q] [--debug] [-a] [-v] input wikiextractor: error: unrecognized arguments: --lists
WikiExtractor.pyをダウンロードした上で、

python3 -m wikiextractor.WikiExtractor --lists ファイル名


usage: WikiExtractor.py [-h] [-o OUTPUT] [-b n[KMG]] [-c] [--html] [-l] [-ns ns1,ns2] [--templates TEMPLATES] [--no-templates] [--escapedoc] [--processes PROCESSES] [-q] [--debug] [-a] [-v] input WikiExtractor.py: error: unrecognized arguments: --lists

python3 WikiExtractor.py  ファイル名.xml


Traceback (most recent call last): File "WikiExtractor.py", line 62, in <module> from .extract import Extractor, ignoreTag ImportError: attempted relative import with no known parent package
となります。

アドバイス募集

他のユーザーの投稿を許可しているので、よろしくお願いします。

環境

Python 3.10.12
WSL2
pip 22.0.2

はるはる

追加で試したこと(うまくいかず)

PythonのWikiExtractorで躓いた話で、.extractを消すと良いと書いてあったので、消して、もう一度、以下を実行

 python3 WikiExtractor.py --lists ファイル名.xml

Traceback (most recent call last): File "WikiExtractor.py", line 62, in <module> from extract import Extractor, ignoreTag ModuleNotFoundError: No module named 'extract'
WikiExtractor.pyがあるGitHubに、extract.pyがあるので、このファイルを、WikiExtractor.pyと同じディレクトリに置くと、エラーが消えました。
しかし、実行しても、以下になってしまいます。
usage: WikiExtractor.py [-h] [-o OUTPUT] [-b n[KMG]] [-c] [--html] [-l] [-ns ns1,ns2] [--templates TEMPLATES] [--no-templates] [--escapedoc] [--processes PROCESSES] [-q] [--debug] [-a] [-v] input WikiExtractor.py: error: unrecognized arguments: --lists

はるはる

追記(うまくいかず)

v3.0のバージョンをクローンし、extract.pyとWikiExtractor.pyを同じディレクトリに配置して、以下を実行しましたが、やはり、--listsは使えませんでした。

 python3 WikiExtractor.py --lists ファイル名.xml
はるはる

追記メモ

バージョン3.0でも3.04でも、WikiExtractor.pyの中に、listという記述が見当たらないので、それが原因の可能性がありそうです。

    parser.add_argument("input",
                        help="XML wiki dump file")
    groupO = parser.add_argument_group('Output')
    groupO.add_argument("-o", "--output", default="text",
                        help="directory for extracted files (or '-' for dumping to stdout)")
    groupO.add_argument("-b", "--bytes", default="1M",
                        help="maximum bytes per output file (default %(default)s)",
                        metavar="n[KMG]")
    groupO.add_argument("-c", "--compress", action="store_true",
                        help="compress output files using bzip")

    groupP = parser.add_argument_group('Processing')
    groupP.add_argument("--html", action="store_true",
                        help="produce HTML output, subsumes --links")
    groupP.add_argument("-l", "--links", action="store_true",
                        help="preserve links")
    groupP.add_argument("-ns", "--namespaces", default="", metavar="ns1,ns2",
                        help="accepted namespaces")
    groupP.add_argument("--templates",
                        help="use or create file containing templates")
    groupP.add_argument("--no-templates", action="store_false",
                        help="Do not expand templates")
    groupP.add_argument("--escapedoc", action="store_true",
                        help="use to escape the contents of the output <doc>...</doc>")
    default_process_count = cpu_count() - 1
    parser.add_argument("--processes", type=int, default=default_process_count,
                        help="Number of processes to use (default %(default)s)")

    groupS = parser.add_argument_group('Special')
    groupS.add_argument("-q", "--quiet", action="store_true",
                        help="suppress reporting progress info")
    groupS.add_argument("--debug", action="store_true",
                        help="print debug info")
    groupS.add_argument("-a", "--article", action="store_true",
                        help="analyze a file containing a single article (debug option)")
    groupS.add_argument("-v", "--version", action="version",
                        version='%(prog)s ' + version,
                        help="print program version")
はるはる

追記メモ

extract.pyの中にある、compact関数内の記述が原因の可能性がありそうです。
Bing AIによると、

compact関数では、箇条書き(リスト)やセクションヘッダーなどの一部の情報が削除される可能性があります。具体的には、以下のような動作をします:
:や;で始まる行(インデントや定義リストを示す)はスキップされます。
==や===で始まる行(セクションヘッダーを示す)は、ヘッダーのテキストだけが抽出され、その後の.が追加されます。

らしいです。
ということは、:や;で始まる行を考慮すれば良い可能性がある…?

はるはる

追記

以下の変更だけでも、リストが表示されるようになるかと思いますが、そうすると、;の行が表示されなくなったので、

elif line[0] == ':':
            page.append(line.lstrip(':*#;'))  # 変更点:コメントアウトを解除

以下も必要そうです。

else:
                page.append(line.lstrip(':*#;'))  # 変更点:リストの行を追加