我有一个大的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
答案 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)