如何以正确的格式将抓取的数据导出到csv文件?

时间:2017-09-08 09:00:19

标签: python csv web-scraping scrapy

我根据@paultrmbrth的this建议改进了我的代码。我需要的是从类似于thisthis的页面中抓取数据,我希望csv输出如下图所示。enter image description here

但我的代码的csv输出有点乱,像这样: enter image description here

我有两个问题,无论如何,csv输出可能像第一张图片一样吗?而我的第二个问题是,我希望这部电影也要废弃,请给我一个提示或提供一个代码,我可以用来刮掉电影名称和内容。

更新
Tarun Lalwani完美地解决了这个问题。但是现在,csv文件的标题只包含第一个抓取的网址类别。例如,当我尝试抓取具有References, Referenced in, Features, Featured in and Spoofed in类别的this webpage和具有Follows, Followed by, Edited from, Edited into, Spin-off, References, Referenced in, Features, Featured in, Spoofs and Spoofed in类别的this webpage时,csv输出文件标题将仅包含第一个网页' s类别即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'   

我们将不胜感激。

2 个答案:

答案 0 :(得分:3)

您可以使用下面的

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

对于CSV部分,您需要创建一个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导出器

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

假设您将代码放在exporters.py文件中。输出将符合要求

Exported Data

修改-1

要设置字段及其顺序,您需要在FEED_EXPORT_FIELDS

中定义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

答案 1 :(得分:0)

要设置 csv 数据格式,最简单的方法之一是使用 excel 电源查询清理数据,请按照以下步骤操作:
1:用excel打开csv文件。
2:使用 ctrl+A
选择所有值 3:然后从插入中单击表并创建表。
4:创建表后,单击顶部菜单中的数据,然后选择来自表 5:知道它们会打开新的 excel 窗口电源查询。
6:选择任意列并点击拆分列
7:从分列中按分隔符选择,
8:知道选择分隔符,如逗号、空格等
9:最后一步选择高级选项,其中有两个选项分为行或列
10:您可以使用这些强大的查询进行所有类型的数据清理,这是根据您的需要设置数据格式的最简单方法