创建大型XML文件的索引

时间:2014-06-20 16:07:49

标签: python xml parsing indexing wikipedia

我有一个大的bz2文件格式wikipedia包含xml格式的文章转储。

从转储中获取文本并不困难。我使用以下代码来解析xml。我想知道是否有办法在读取后打开orignal bz2或xml文件并对其进行索引,以便我可以将各种行(例如,“Barack Obama”的文章)与该索引相关联,以及然后当需要那条线时我可以直接去它。

一种可能性是将bz2或xml文件拆分为更小的块然后索引这些块。有没有人对如何尽快找到特定的线路有任何想法?

import bz2
try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree
import re


def _get_namespace(tag):
    namespace = re.match("^{(.*?)}", tag).group(1)
    if not namespace.startswith("http://www.mediawiki.org/xml/export-"):
        raise ValueError("%s not recognized as MediaWiki database dump"
                         % namespace)
    return namespace

def extract_pages(f):
    elems = (elem for _, elem in etree.iterparse(f, events=["end"]))
    elem = next(elems)

    namespace = _get_namespace(elem.tag)
    ns_mapping = {"ns": namespace}
    page_tag = "{%(ns)s}page" % ns_mapping
    text_path = "./{%(ns)s}revision/{%(ns)s}text" % ns_mapping
    id_path = "./{%(ns)s}id" % ns_mapping
    title_path = "./{%(ns)s}title" % ns_mapping
    for elem in elems:
        if elem.tag == page_tag:
            text = elem.find(text_path).text
            if text is None:
                continue
            yield (int(elem.find(id_path).text),
                   elem.find(title_path).text,
                   text)
            elem.clear()
            if hasattr(elem, "getprevious"):
                while elem.getprevious() is not None:
                    del elem.getparent()[0]

if __name__ == "__main__":
    dictionary={}
    f = bz2.BZ2File("simplewiki.xml.bz2", 'rb')

    for pageid, title, text in extract_pages(f):
        print pageid

2 个答案:

答案 0 :(得分:1)

通过索引XML进行高效搜索的正确工具是XQuery - 一种可以使用多个高速索引数据库的语言。有可用的Python绑定,所以你可以从你的Python软件运行XQuery查询,但是你想要用XQuery编写实际的查询,而不是Python。

与SQL数据库一样,XQuery数据库具有查询优化器,但是如何编写查询仍然与索引的使用效率有很大关系(并且您可以控制索引 - 与索引仅ID属性,与全文相比带有词干的索引,以及之间的许多地方。)

如果您想要一个具有良好可视化支持的开源XQuery数据库来帮助您编写和调试代码,BaseX可能是一个很好的开始;它具有很好的用户界面,并且非常接近语言规范的尖端,不断添加新功能,因为W3C工作组提出了控制XQuery演进的新功能。 eXist是另一个维护良好的开源XQuery数据库,而MarkLogic可能是最受尊敬的商业XQuery实现之一。

如果您希望能够从Python运行查询,请参阅the list of available clients for BaseX

另请参阅the detailed documentation on indexes in BaseX,以确保编写查询以利用它们(并创建所需的索引)。

答案 1 :(得分:0)

XML文件不是数据库...因此使用它不可避免地是一种滥用并试图添加数据库功能,如"索引"在它之上只会让事情变得更糟糕恕我直言。此外,bz2文件的内容不可搜索。如果需要数据库,请将XML导入数据库。

对于涉及XML转储的大多数任务,mediawiki-utilities是最快的选择。仅仅为了说明的目的,要获得[[Barack Obama]]的文本,您可以执行与文档中的示例类似的操作,假设您下载了当前版本的转储:

from mw.xml_dump import Iterator

# Construct dump file iterator
dump = Iterator.from_file(open("example/dump.xml"))

# Iterate through pages
for page in dump:
    if page.title == "Barack Obama": continue
    # Iterate through a page's revisions
    for revision in page:

        print(revision.text)