2017-09-08 2 views
1

@paultrmbrth의 제안에 따라 this 제안에 따라 코드를 개선했습니다. 내가 필요한 것은 thisthis과 비슷한 페이지의 데이터를 긁어 내고 csv 출력을 아래 그림과 같게 만드는 것입니다. enter image description here스크래핑 된 데이터를 올바른 형식으로 CSV 파일로 내보낼 수 있습니까?

는하지만 내 코드의 CSV 출력은 다음과 같이 좀 지저분하다 : 나는이 개 질문이 enter image description here

는, csv로 출력이 첫 번째 사진처럼 될 수 있다는 어쨌든이 있나요? 그리고 두 번째 질문은 영화 제목도 내용을 지우는 데 사용할 수있는 힌트를 주거나 제게 제공 해주시기 바랍니다. 문제는 완벽하게 Tarun Lalwani에 의해 해결되었다

UPDATE. 하지만 이제 CSV 파일의 헤더에는 처음으로 스크랩 된 URL 카테고리 만 포함됩니다. 예를 들어 References, Referenced in, Features, Featured in and Spoofed in 카테고리가 있고 Follows, Followed by, Edited from, Edited into, Spin-off, References, Referenced in, Features, Featured in, Spoofs and Spoofed in 카테고리를 가진 this webpage 카테고리를 가지고있는 this webpage을 긁으려고하면 CSV 출력 파일 헤더는 References, Referenced in, Features, Featured in and Spoofed in이라는 첫 번째 웹 페이지 카테고리 만 포함하게됩니다. 따라서 Follows, Followed by, Edited from, Edited into and Spoofs과 같은 두 번째 웹 페이지의 일부 카테고리는 출력 csv 파일에 포함되지 않습니다 헤더도 그 내용입니다. 여기

import scrapy 


class ExampleSpider(scrapy.Spider): 
    name = "example" 
    allowed_domains = ["imdb.com"] 
    start_urls = (
     'http://www.imdb.com/title/tt0093777/trivia?tab=mc&ref_=tt_trv_cnn', 
     'http://www.imdb.com/title/tt0096874/trivia?tab=mc&ref_=tt_trv_cnn', 
    ) 

    def parse(self, response): 
     item = {} 
     for cnt, h4 in enumerate(response.css('div.list > h4.li_group'), start=1): 
      item['Title'] = response.css("h3[itemprop='name'] a::text").extract_first() 
      key = h4.xpath('normalize-space()').get().strip() 
      if key in ['Follows', 'Followed by', 'Edited into', 'Spun-off from', 'Spin-off', 'Referenced in', 
         'Featured in', 'Spoofed in', 'References', 'Spoofs', 'Version of', 'Remade as', 'Edited from', 
         'Features']: 
       values = h4.xpath('following-sibling::div[count(preceding-sibling::h4)=$cnt]', cnt=cnt).xpath(
        'string(.//a)').getall(), 
       item[key] = values 
     yield item 

exporters.py 파일 : 나는 달성하기 위해 노력하고있어

try: 
    from itertools import zip_longest as zip_longest 
except: 
    from itertools import izip_longest as zip_longest 
from scrapy.exporters import CsvItemExporter 
from scrapy.conf import settings 


class NewLineRowCsvItemExporter(CsvItemExporter): 

    def __init__(self, file, include_headers_line=True, join_multivalued=',', **kwargs): 
     super(NewLineRowCsvItemExporter, self).__init__(file, include_headers_line, join_multivalued, **kwargs) 

    def export_item(self, item): 
     if self._headers_not_written: 
      self._headers_not_written = False 
      self._write_headers_and_set_fields_to_export(item) 

     fields = self._get_serialized_fields(item, default_value='', 
              include_empty=True) 
     values = list(self._build_row(x for _, x in fields)) 

     values = [ 
      (val[0] if len(val) == 1 and type(val[0]) in (list, tuple) else val) 
      if type(val) in (list, tuple) 
      else (val,) 
      for val in values] 

     multi_row = zip_longest(*values, fillvalue='') 

     for row in multi_row: 
      self.csv_writer.writerow([unicode(s).encode("utf-8") for s in row]) 

내가 모든 범주가 ​​CSV 출력 헤더에 있어야 할 것입니다
여기 내가 사용하는 코드입니다.

'Follows', 'Followed by', 'Edited into', 'Spun-off from', 'Spin-off', 'Referenced in', 
'Featured in', 'Spoofed in', 'References', 'Spoofs', 'Version of', 'Remade as', 'Edited from', 'Features' 

아무 도움이됩니다.

+1

한번에 한 가지만 질문하십시오. ers와 코멘트가 섞여 버립니다. –

+0

당신이 잘못 가고있는 곳을 이해하고 현재 문제를 재현 할 수 있도록 우리에게 더 많은 코드를 추가해야합니다. –

답변

3

당신은 CSV 부분의 경우

item = {} 
item['Title'] = response.css("h3[itemprop='name'] a::text").extract_first() 

이하로 사용하여 제목을 추출 할 수있는 여러 행으로 각 행을 분할 할 수있는 FeedExports을 만들어야합니다

from itertools import zip_longest 
from scrapy.contrib.exporter import CsvItemExporter 


class NewLineRowCsvItemExporter(CsvItemExporter): 

    def __init__(self, file, include_headers_line=True, join_multivalued=',', **kwargs): 
     super(NewLineRowCsvItemExporter, self).__init__(file, include_headers_line, join_multivalued, **kwargs) 

    def export_item(self, item): 
     if self._headers_not_written: 
      self._headers_not_written = False 
      self._write_headers_and_set_fields_to_export(item) 

     fields = self._get_serialized_fields(item, default_value='', 
              include_empty=True) 
     values = list(self._build_row(x for _, x in fields)) 

     values = [ 
      (val[0] if len(val) == 1 and type(val[0]) in (list, tuple) else val) 
      if type(val) in (list, tuple) 
      else (val,) 
      for val in values] 

     multi_row = zip_longest(*values, fillvalue='') 

     for row in multi_row: 
      self.csv_writer.writerow(row) 

그럼 당신은 할당해야 귀하의 설정에 피드 공급 업체

FEED_EXPORTERS = { 
    'csv': '<yourproject>.exporters.NewLineRowCsvItemExporter', 
} 

당신은 코드를 exporters.py 파일에 넣었습니다. 출력은 다음과 같이 요구한다

Exported Data

편집-1

필드와 그들의 순서는 당신이 당신의 settings.py

FEED_EXPORT_FIELDS = ['Title', 'Follows', 'Followed by', 'Edited into', 'Spun-off from', 'Spin-off', 'Referenced in', 
         'Featured in', 'Spoofed in', 'References', 'Spoofs', 'Version of', 'Remade as', 'Edited from', 
         'Features'] 

https://doc.scrapy.org/en/latest/topics/feed-exports.html#std:setting-FEED_EXPORT_FIELDS

FEED_EXPORT_FIELDS을 정의해야합니다 설정하려면
+0

@ TarunLalwani 감사합니다, 매력과 같은 작품! 그러나 행 만 포함 \t _Title_ _Spoofs_ _Follows_ \t _Referenced IN_ \t _Featured by_ \t _References_ _Followed IN_ 그리고 그것은 나에게이 오류 UnicodeEncodeError주고 '아스키'코덱이 문자를 인코딩 할 수를 유 '\ xf3'위치 2 : 범위 내에 있지 서수 (128) – haben

+0

파이썬이나 파이썬 3을 사용하고 계십니까? Python 2를 사용하고 있다면 python3을 사용해보십시오. –

+0

@ TarunLalwani 질문을 업데이트했습니다. 할 수 있으면 제발 도와주세요. – haben