如何在Python中拆分大型Wikipedia .xml.bz2文件?

7 投票
3 回答
5436 浏览
提问于 2025-04-16 18:39

我正在尝试使用Python构建一个离线的维基词典,数据来源是维基媒体的转储文件(.xml.bz2格式)。我开始参考了这篇文章,里面涉及了多种语言。我想把所有步骤整合成一个完整的Python项目。目前我几乎找到了所有需要的库,唯一的问题就是如何有效地将这个大的.xml.bz2文件拆分成多个小文件,以便在搜索时能更快地解析。

我知道Python里有bz2库,但它只能进行压缩和解压缩操作。我需要的是一种能像命令行中的bz2recover那样,能够将大文件拆分成多个小块的工具。

还有一个重要的点是,拆分时不能把以<page>开头,以</page>结尾的页面内容拆开,这些内容是在被压缩的xml文档中。

有没有现成的库可以处理这种情况,还是说需要从头开始写代码?(任何大致的思路或伪代码都会很有帮助)。

注意:我希望最终的包能够跨平台兼容,所以不能使用特定于操作系统的命令。

3 个回答

0

你提到的方法其实有点不太靠谱 :)

我写过一个离线的维基百科工具,直接用Sax解析了整个数据包。如果你把解压后的xml文件通过合适的bzip2解压工具直接输入到程序里,处理速度还是可以的,特别是如果只是处理维基词典的话。

为了简单测试,我把每一页都压缩成一个大文件,并把每一页的起始位置和长度存储在一个小型的键值数据库里,这可能对你来说是个有效的解决方案。

不过要注意,mediawiki的标记语言真的是我见过的最糟糕的东西之一。但对于维基词典来说,处理起来可能还算可行。

1

好吧,如果你有一个命令行工具,它提供了你需要的功能,你可以通过使用 subprocess 模块来把它包装起来调用。

20

我终于自己写了一个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')

撰写回答