如何在Python中拆分大型Wikipedia .xml.bz2文件?
我正在尝试使用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')