Python 是否将(所有)维基百科数据加载到mongodb?

Python 是否将(所有)维基百科数据加载到mongodb?,python,xml,mongodb,wikipedia,elementtree,Python,Xml,Mongodb,Wikipedia,Elementtree,在2013年Mongonic会议上,一位发言者提到他们使用维基百科的副本来测试全文搜索。我自己也尝试过复制它,但由于文件大小和格式的原因,我发现它并不重要 以下是我正在做的: $ wget http://download.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2 $ bunzip2 enwiki-latest-pages-articles.xml.bz2 $ python >>> impo

在2013年Mongonic会议上,一位发言者提到他们使用维基百科的副本来测试全文搜索。我自己也尝试过复制它,但由于文件大小和格式的原因,我发现它并不重要

以下是我正在做的:

$ wget http://download.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2
$ bunzip2 enwiki-latest-pages-articles.xml.bz2 
$ python
>>> import xml.etree.ElementTree as ET
>>> tree = ET.parse('enwiki-latest-pages-articles.xml')
Killed
当我尝试用标准xml解析器解析xml文件时,Python会在xml文件的大小上出错。对于如何将9GB XML文件转换为JSON-y文件(我可以将其加载到mongoDB中),有人有其他建议吗

更新1

根据下面Sean的建议,我还尝试了迭代元素树:

>>> import xml.etree.ElementTree as ET
>>> context = ET.iterparse('enwiki-latest-pages-articles.xml', events=("start", "end"))
>>> context = iter(context)
>>> event, root = context.next()
>>> for i in context[0:10]:
...     print(i)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '_IterParseIterator' object has no attribute '__getitem__'
>>> for event, elem in context[0:10]:
...     if event == "end" and elem.tag == "record":
...             print(elem)
...             root.clear()
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '_IterParseIterator' object has no attribute '__getitem__'
下面是
xmlutils

$ pip install xmlutils
$ xml2json --input "enwiki-latest-pages-articles.xml" --output "enwiki-latest-pages-articles.json"
xml2sql by Kailash Nadh (http://nadh.in)
    --help for help


Wrote to enwiki-latest-pages-articles.json
但内容只是一条记录。它没有迭代

xmltodict
,也很有希望,因为它使用迭代Expat做广告,对维基百科有好处。但它也在大约20分钟后耗尽了内存:

>>> import xmltodict
>>> f = open('enwiki-latest-pages-articles.xml')
>>> doc = xmltodict.parse(f)
Killed
更新3

这是对Ross在下面的回答的回应,对我的解析器进行建模:

错误是:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fast_iter
  File "iterparse.pxi", line 484, in lxml.etree.iterparse.__next__ (src/lxml/lxml.etree.c:112653)
  File "iterparse.pxi", line 537, in lxml.etree.iterparse._read_more_events (src/lxml/lxml.etree.c:113223)
  File "parser.pxi", line 596, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:83186)
lxml.etree.XMLSyntaxError: Extra content at the end of the document, line 22, column 1
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第2行,在fast\u iter中
文件“iterparse.pxi”,第484行,在lxml.etree.iterparse.\uu下一步(src/lxml/lxml.etree.c:112653)
文件“iterparse.pxi”,第537行,在lxml.etree.iterparse.读取更多事件(src/lxml/lxml.etree.c:113223)
文件“parser.pxi”,第596行,在lxml.etree中。\u raiseParserError(src/lxml/lxml.etree.c:83186)
lxml.etree.XMLSyntaxError:文档末尾第22行第1列的额外内容

您需要使用
iterparse
进行迭代,而不是将整个文件加载到内存中。关于如何转换为json甚至python对象以存储在db中,请参见:

更新 使用iterparse并保持低内存占用的示例:

尝试一种变体。在处理元素
elem
之后,它调用
elem.clear()
来删除子元素,并删除前面的同级元素

from lxml import etree

def fast_iter(context, func):
    # http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
    # Author: Liza Daly
    for event, elem in context:
        print(elem)
        elem.clear()
        while elem.getprevious() is not None:
            del elem.getparent()[0]
    del context

context = etree.iterparse( MYFILE, tag='item' )
fast_iter(context,process_element)

Daly的文章读得很好,尤其是在处理大型XML文件时。

以防万一2018年有人在这个问题上绊倒

现在,有一个单行命令可用(Node.js):


它是python配置中的某种东西还是硬件约束?如果这是一个硬件约束,云服务提供商可能值得为此任务进行研究。有一个可能对您有用的解决方案。只要超出您的可用内存,它就会被杀死,我不明白您为什么需要转换为JSON。@marabutt,我现在使用的是一个Amazon实例,但它没有9GB用于此任务,我希望在用更大的硬件攻击之前找到一个正确的答案。我只对转换成JSON感兴趣,这样我就可以将对象插入MongoDB。如果您知道一种直接从XML(希望是迭代的)执行此操作的方法,我洗耳恭听。=)更新1中的示例是使用
iterparse
而不是
parse
。我已经更新了-在更新1中,您有一个错误,这就是它失败的原因。不要通过执行
上下文[0:10]
来调用
\uuuu getitem\uuuu
——只需重复它。我认为这为我指明了正确的方向,但您能解释一下流程元素将采用什么形式吗?我正在用我尝试过的和不起作用的更新我的答案。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fast_iter
  File "iterparse.pxi", line 484, in lxml.etree.iterparse.__next__ (src/lxml/lxml.etree.c:112653)
  File "iterparse.pxi", line 537, in lxml.etree.iterparse._read_more_events (src/lxml/lxml.etree.c:113223)
  File "parser.pxi", line 596, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:83186)
lxml.etree.XMLSyntaxError: Extra content at the end of the document, line 22, column 1
from lxml import etree

def fast_iter(context, func):
    # http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
    # Author: Liza Daly
    for event, elem in context:
        print(elem)
        elem.clear()
        while elem.getprevious() is not None:
            del elem.getparent()[0]
    del context

context = etree.iterparse( MYFILE, tag='item' )
fast_iter(context,process_element)