如何在Python中分割大型维基百科转储.xml.bz2文件?

7
我正在尝试使用Python构建离线Wiktionary,使用Wikimedia转储文件(.xml.bz2)。我以this文章作为指南开始。它涉及许多语言,我想将所有步骤组合为一个单独的Python项目。我已经找到了几乎所有所需的库。现在唯一的障碍是有效地将大的.xml.bz2文件分割成多个较小的文件,以便在搜索操作期间更快地解析。
我知道Python中存在bz2库,但它仅提供压缩和解压缩操作。但我需要像命令行中的bz2recover一样的东西,可以将大文件拆分为多个较小的块。
另一个重要的问题是,分割不应该分割以<page>开头并以</page>结束的页面内容,这些内容在已压缩的XML文档中。
之前有没有可用于处理此情况的库,还是必须从头开始编写代码?(任何概述/伪代码都将非常有帮助)。
注意:我希望使生成的软件包跨平台兼容,因此无法使用特定于操作系统的命令。
3个回答

19

终于,我自己写了一个Python脚本:

import os
import bz2

def split_xml(filename):
    ''' The function gets the filename of wiktionary.xml.bz2 file as  input and creates
    smallers chunks of it in a the diretory chunks
    '''
    # Check and create chunk diretory
    if not os.path.exists("chunks"):
        os.mkdir("chunks")
    # Counters
    pagecount = 0
    filecount = 1
    #open chunkfile in write mode
    chunkname = lambda filecount: os.path.join("chunks","chunk-"+str(filecount)+".xml.bz2")
    chunkfile = bz2.BZ2File(chunkname(filecount), 'w')
    # Read line by line
    bzfile = bz2.BZ2File(filename)
    for line in bzfile:
        chunkfile.write(line)
        # the </page> determines new wiki page
        if '</page>' in line:
            pagecount += 1
        if pagecount > 1999:
            #print chunkname() # For Debugging
            chunkfile.close()
            pagecount = 0 # RESET pagecount
            filecount += 1 # increment filename           
            chunkfile = bz2.BZ2File(chunkname(filecount), 'w')
    try:
        chunkfile.close()
    except:
        print 'Files already close'

if __name__ == '__main__':
    # When the script is self run
    split_xml('wiki-files/tawiktionary-20110518-pages-articles.xml.bz2')

1
这很棒。如果您想使用每个块与维基解析工具,请确保在每个XML文件的末尾添加“mediawiki”的关闭标签。然后它就可以正常工作了。 </page> </mediawiki> - Andy Matteson
代码在Python 2中可以运行,但在Python 3中需要将比较替换为if b'</page>' in line - AlwaysNull

1

如果你有一个命令行工具,可以提供你所需要的功能,那么你总是可以使用subprocess模块来调用它。


但我想确保结果包是跨平台兼容的。 - user507139
抱歉,我忘了提到它。现在已经编辑了原始问题。 - user507139

0

你所提到的方法相当不正规 :)

我写了一个离线维基百科工具,只需完全解析转储文件即可。如果您从适当的bzip2解压缩器中将未压缩的xml导入stdin,则吞吐量是可用的。特别是对于wiktionary。

作为测试的简单方法,我只是压缩了每个页面并将其写入一个大文件中,并在cdb(小键值存储)中保存了偏移量和长度。这可能是您的有效解决方案。

请记住,mediawiki标记是我最近遇到的最可怕的东西。但是,在处理wiktionary的情况下,它可能是可行的。


1
虽然使用SAX方式解析整个转储可能更简单,但索引和搜索大文件的问题很困难。关于Mediawiki标记,这里可能会对您有所帮助。 ;) - user507139
1
使用xapian/lucene进行全文搜索(我也见过一个纯Python引擎),最终并不是很困难。顺便说一句,lucene真的很棒 :) 我几乎尝试了所有的解析器/渲染器,但仍然需要处理特定语言的hack和本地化、维基百科特定的hack以及许多其他问题。MediaWiki生态系统非常糟糕,可以说是做得不太好。 - sleeplessnerd
刚发现这个网址:http://pypi.python.org/pypi/wikidump/0.1.2,看起来它可能对你有所帮助。 - sleeplessnerd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接