【问题标题】:Cleaning data scraped using Scrapy清理使用 Scrapy 抓取的数据
【发布时间】:2017-09-18 06:16:24
【问题描述】:

我最近开始使用 Scrapy,正在尝试清理一些我已经抓取并希望导出为 CSV 的数据,即以下三个示例:

  • 示例 1 – 删除某些文本
  • 示例 2 – 删除/替换不需要的字符
  • 示例 3 - 拆分逗号分隔文本

示例 1 数据如下所示:

我想要的文字,我不想要的文字

使用以下代码:

'Scraped 1': response.xpath('//div/div/div/h1/span/text()').extract()

示例 2 的数据如下所示:

- 但我想将其更改为 £

使用以下代码:

' Scraped 2': response.xpath('//html/body/div/div/section/div/form/div/div/em/text()').extract()

示例 3 数据如下所示:

Item 1,Item 2,Item 3,Item 4,Item 4,Item5 – 最终我想拆分 将其放入 CSV 文件中的单独列中

使用以下代码:

' Scraped 3': response.xpath('//div/div/div/ul/li/p/text()').extract()

我尝试过使用str.replace(),但似乎无法让它发挥作用,例如: 'Scraped 1': response.xpath('//div/div/div/h1/span/text()').extract((str.replace(",Text I don't want",""))

我正在研究这个问题,但如果有人能指出我正确的方向,我将不胜感激!

代码如下:

import scrapy
from scrapy.loader import ItemLoader
from tutorial.items import Product


class QuotesSpider(scrapy.Spider):
    name = "quotes_product"
    start_urls = [
        'http://www.unitestudents.com/',
            ]

    # Step 1
    def parse(self, response):
        for city in response.xpath('//select[@id="frm_homeSelect_city"]/option[not(contains(text(),"Select your city"))]/text()').extract(): # Select all cities listed in the select (exclude the "Select your city" option)
            yield scrapy.Request(response.urljoin("/"+city), callback=self.parse_citypage)

    # Step 2
    def parse_citypage(self, response):
        for url in response.xpath('//div[@class="property-header"]/h3/span/a/@href').extract(): #Select for each property the url
            yield scrapy.Request(response.urljoin(url), callback=self.parse_unitpage)


    # Step 3
    def parse_unitpage(self, response):
        for final in response.xpath('//div/div/div[@class="content__btn"]/a/@href').extract(): #Select final page for data scrape
            yield scrapy.Request(response.urljoin(final), callback=self.parse_final)

    #Step 4 
    def parse_final(self, response):
        unitTypes = response.xpath('//html/body/div').extract()
        for unitType in unitTypes: # There can be multiple unit types so we yield an item for each unit type we can find.
            l = ItemLoader(item=Product(), response=response)
            l.add_xpath('area_name', '//div/ul/li/a/span/text()')
            l.add_xpath('type', '//div/div/div/h1/span/text()')
            l.add_xpath('period', '/html/body/div/div/section/div/form/h4/span/text()')
            l.add_xpath('duration_weekly', '//html/body/div/div/section/div/form/div/div/em/text()')
            l.add_xpath('guide_total', '//html/body/div/div/section/div/form/div/div/p/text()')
            l.add_xpath('amenities','//div/div/div/ul/li/p/text()')
            return l.load_item()

但是,我得到以下信息?

value = self.item.fields[field_name].get(key, default)
KeyError: 'type'

【问题讨论】:

    标签: python web-scraping scrapy data-cleaning


    【解决方案1】:

    str.replace 的想法是正确的,尽管我建议使用 Python 're' 正则表达式库,因为它更强大。文档是一流的,您可以在那里找到一些有用的代码示例。

    我不熟悉 scrapy 库,但它看起来像 .extract() 返回一个字符串列表。如果您想使用 str.replace 或其中一个正则表达式函数来转换这些,您将需要使用列表推导:

    'Selector 1': [ x.replace('A', 'B') for x in response.xpath('...').extract() ]
    

    编辑:关于单独的列——如果数据已经用逗号分隔,只需将其直接写入文件!如果你想分割逗号分隔的数据做一些转换,你可以像这样使用str.split

    "A,B,C".split(",") # returns [ "A", "B", "C" ]
    

    在这种情况下,.extract() 返回的数据将是一个逗号分隔的字符串列表。如果您使用上述列表推导式,您将得到一个列表列表。

    如果您想要比在每个逗号上拆分更复杂的东西,您可以使用 python 的 csv 库。

    【讨论】:

    • 感谢您的帮助!不幸的是,仍然没有运气 - 'Scraped 1': [x.replace(",Your new room includes", "")] for x in response.xpath('//div/div/div/h1/span/text()').extract() 返回 {'type': ['Text I don't want']}。拆分也没有运气,因为没有属性错误。
    【解决方案2】:

    如果您提供了蜘蛛和项目定义,那么提供更具体的答案会容易得多。以下是一些通用指南。

    如果您想保持模块化并遵循 Scrapy 建议的项目架构和关注点分离,您应该清理和准备您的数据,以便通过Item Loadersinput and output processors 进一步导出。

    对于前两个示例,MapCompose 看起来很合适。

    【讨论】:

    • 感谢您在问题中添加的代码,尝试设置加载程序,但现在得到KeyError: 'type'
    猜你喜欢
    • 2013-05-23
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    相关资源
    最近更新 更多