2017-09-26 10 views
2

ウェブサイトからデータをスクラップできますが、XMLでエクスポートする必要があります。この目的のためにエクスポートされたXMLにスキーマで属性を追加する

私はそうのようなシリアライザを定義した:

class Person(scrapy.Item): 
    Name = scrapy.Field(serializer=serialize_name) 
    Location = scrapy.Field() 

そしてそうのようなXMLExportPipeline:

class XmlExportPipeline(object): 

def __init__(self): 
    self.files = {} 

@classmethod 
def from_crawler(cls, crawler): 
    pipeline = cls() 
    crawler.signals.connect(pipeline.spider_opened, signals.spider_opened) 
    crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) 
    return pipeline 


def spider_opened(self, spider): 
    file = open('%s_people.xml' % spider.name, 'w+b') 
    self.files[spider] = file 
    self.exporter = XmlItemExporter(file, item_element='Person', root_element='People') 
    self.exporter.start_exporting() 


def spider_closed(self, spider): 
    ... 


def process_item(self, person, spider): 
    self.exporter.export_item(person) 
    return person 

これは動作し、私にそのようなXMLファイルを提供します:

<?xml version="1.0" encoding="utf-8"?> 
<People><Person><Name>Bob</Name><Location>NYC</Location></Person></People> 

タグに属性を追加するにはどうすればよいですか?たとえば、私が望むならば、

<Person Age="25" Likes="Programming"> 

どうすればいいですか?

また、出力XMLがフォーマットされていないのはなぜですか?like it is supposed to be?タグの値をCDATAに変換することはできますか?

答えて

1

XmlItemExporterのデフォルトの実装では、このためライン(scrapy/exporters.py:173)のこれを許可しない:

self.xg.startElement(name, {}) 

この二番目の引数は、それぞれの新しい要素の属性を含むようになっています。回避策は、XmlItemExporterの独自のサブクラスを実装し、この引数を追加することです。この例では

from scrapy.exporters import six, is_listlike, XmlItemExporter 

class AttrXmlItemExporter(XmlItemExporter): 

    def _export_xml_field(self, name, serialized_value, depth): 
     # Custom code: 
     attrs = {} 
     if isinstance(serialized_value, dict): 
      serialized_value = serialized_value.copy() 
      attr_keys = [k for k in serialized_value.keys() if k.startswith('_')] 
      attrs = {k[1:]: serialized_value.pop(k) for k in attr_keys} 

     # Default implementation (except for startElement call) 
     self._beautify_indent(depth=depth) 
     self.xg.startElement(name, attrs) 
     if hasattr(serialized_value, 'items'): 
      self._beautify_newline() 
      for subname, value in serialized_value.items(): 
       self._export_xml_field(subname, value, depth=depth + 1) 
      self._beautify_indent(depth=depth) 
     elif is_listlike(serialized_value): 
      self._beautify_newline() 
      for value in serialized_value: 
       self._export_xml_field('value', value, depth=depth + 1) 
      self._beautify_indent(depth=depth) 
     elif isinstance(serialized_value, six.text_type): 
      self._xg_characters(serialized_value) 
     else: 
      self._xg_characters(str(serialized_value)) 
     self.xg.endElement(name) 
     self._beautify_newline() 

、キー開始アンダー(_)と属性として表示される辞書(すなわち、サブ辞書である)である任意の項目値。

たとえば、アイテム:

yield { 
    'name': 'Sample', 
    'rating': { 
     '_rating': '4.5', 
     '_max': '5', 
    }, 
} 

としてXMLにレンダリングされます:

<item> 
    <nam>Sample</name> 
    <rating rating="4.5" max="5"> 
    </rating> 
</item> 

は、しかし、それ自己閉鎖要素にする方法を考え出したていません。属性としてマークされている値はすべて、文字列であるである必要があります。

+0

お手数をおかけしていただきありがとうございます。これは間違いなく助かります。 – Zalarox

関連する問題