2017-03-16 109 views
1

我想做一些XML文檔的交互式探索。我試圖使用lxml解析文檔,並使用find,findall和xpath方法進行查詢。然而PySpark扼流圈,當我嘗試創建元素的RDD的對象:lxml.Element對象的Spark Python RDD?

from lxml import etree 
from lxml.etree import XMLSyntaxError 
def get_root(xml): 
    xml_bytes = bytes(bytearray(xml, encoding = 'utf-8')) 
    try: 
    return [etree.XML(xml_bytes)] 
    except XMLSyntaxError: 
    return [] 

docs = [ 
    "<doc><tag name='hoo'>hah</tag><tag name='wah'>zoo</tag></doc>" 
    , "<doc><tag name='hoo'>yah</tag><tag name='wah'>woo</tag></doc>" 
] 
roots = [get_root(x)[0] for x in docs] 
roots 
    [<Element doc at 0x3b2280>, <Element doc at 0x3b2140>] 
docs_rdd = sc.parallelize(docs) 
roots_rdd = docs_rdd.flatMap(lambda d: get_root(d)) 
roots_rdd.count() 
    2 
roots_rdd.first() 
    Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "lxml.etree.pyx", line 1033, in lxml.etree._Element.__repr__ (src/lxml/lxml.etree.c:42268) 
    File "lxml.etree.pyx", line 881, in lxml.etree._Element.tag.__get__ (src/lxml/lxml.etree.c:40855) 
    File "apihelpers.pxi", line 15, in lxml.etree._assertValidNode (src/lxml/lxml.etree.c:12875) 
    AssertionError: invalid Element proxy at 62728864 

有人可以幫助我理解這是怎麼回事呢?

Python 2.7.x或3.5.x,Spark 1.6.x,lxml使用pip或pip3安裝。

在此先感謝!

回答

1

lxml對象不可序列化,不能在執行器和驅動程序之間傳遞或混洗。它可以很容易地複製,而無需使用星火可言:

from lxml import etree 
import pickle 

pickle.loads(pickle.dumps(etree.XML("<doc>foo</doc>"))) 
AssertionError       Traceback (most recent call last) 
... 
AssertionError: invalid Element proxy at ... 

,您仍然可以使用lxml解析和獲取序列化的Python對象:

from operator import attrgetter 

docs_rdd.flatMap(get_root).flatMap(lambda x: x).map(attrgetter("text")).collect() 
['hah', 'zoo', 'yah', 'woo']