【问题标题】:Empty file json as output in Scrapy空文件 json 作为 Scrapy 中的输出
【发布时间】:2016-08-10 09:17:25
【问题描述】:

我声明我已经阅读了一些关于同一问题的答案,但我无法解决我的问题。 我是 Python 新手,我正在尝试从 Aptoide 中提取有关应用程序和商店的数据,并且我想要输出结果为 .json 文件(或 csv),但我得到的文件是空的,我不知道原因。

这是我的代码:

    import scrapy

    from scrapy.spiders import CrawlSpider, Rule
    from scrapy.linkextractors import LinkExtractor
    from scrapy.contrib.spiders import CrawlSpider, Rule
    from scrapy.selector import HtmlXPathSelector

    class ApptoideItem(scrapy.Item):
        app_name = scrapy.Field()
        rating = scrapy.Field()
        security_status = scrapy.Field()
        good_flag = scrapy.Field()
        licence_flag = scrapy.Field()
        fake_flag = scrapy.Field()
        freeze_flag = scrapy.Field()
        virus_flag = scrapy.Field()
        five_stars = scrapy.Field()
        four_stars = scrapy.Field()
        three_stars = scrapy.Field()
        two_stars = scrapy.Field()
        one_stars = scrapy.Field()
        info = scrapy.Field()
        download = scrapy.Field()
        version = scrapy.Field()
        size = scrapy.Field()
        link = scrapy.Field()
        store = scrapy.Field()

class AppSpider(CrawlSpider):
    name = "second"
    allowed_domains = ["aptoide.com"]
    start_urls = [ "http://www.aptoide.com/page/morestores/type:top" ]

    rules = (
        Rule(LinkExtractor(allow=(r'\w+\.store\.aptoide\.com$'))),

        Rule(LinkExtractor(allow=(r'\w+\.store\.aptoide\.com/app/market')), callback='parse_item')
        )


def parse_item(self, response):

    item = ApptoideItem()
    item['app_name']= str(response.css(".app_name::text").extract()[0])
    item['rating']= str(response.css(".app_rating_number::text").extract()[0])
    item['security_status']= str(response.css("#show_app_malware_data::text").extract()[0])
    item['good_flag']= int(response.css(".good > div:nth-child(3)::text").extract()[0])
    item['licence_flag']= int(response.css(".license > div:nth-child(3)::text").extract()[0])
    item['fake_flag']= int(response.css(".fake > div:nth-child(3)::text").extract()[0])
    item['freeze_flag']= int(response.css(".freeze > div:nth-child(3)::text").extract()[0])
    item['virus_flag']= int(response.css(".virus > div:nth-child(3)::text").extract()[0])
    item['five_stars']= int(response.css("div.app_ratting_bar_holder:nth-child(1) > div:nth-child(3)::text").extract()[0])
    item['four_stars']= int(response.css("div.app_ratting_bar_holder:nth-child(2) > div:nth-child(3)::text").extract()[0])
    item['three_stars']= int(response.css("div.app_ratting_bar_holder:nth-child(3) > div:nth-child(3)::text").extract()[0])
    item['two_stars']= int(response.css("div.app_ratting_bar_holder:nth-child(4) > div:nth-child(3)::text").extract()[0])
    item['link']= response.url
    item['one_stars']= int(response.css("div.app_ratting_bar_holder:nth-child(5) > div:nth-child(3)::text").extract()[0])
    item['download']= int(response.css("p.app_meta::text").re('(\d[\w\.]*)')[0].replace('.', ''))
    item['version']= str(response.css("p.app_meta::text").re('(\d[\w\.]*)')[1])
    item['size']= str(response.css("p.app_meta::text").re('(\d[\w\.]*)')[2])
    item['store_name']= str(response.css(".sec_header_txt::text").extract()[0])
    item['info_store']= str(response.css(".ter_header2::text").extract()[0])
    yield item

我很确定问题是从未调用过 parse_item 方法,我不知道原因。第一条规则遵循商店,而第二条规则遵循商店中的应用程序。我觉得正则表达式的语法是对的。

设置是:

CLOSESPIDER_PAGECOUNT = 1000
CLOSESPIDER_ITEMCOUNT = 500
CONCURRENT_REQUESTS = 1
CONCURRENT_ITEMS = 1

BOT_NAME = 'nuovo'


SPIDER_MODULES = ['nuovo.spiders']
NEWSPIDER_MODULE = 'nuovo.spiders'

谁能找到问题并建议我解决方案?

【问题讨论】:

  • 您是否检查过您的 xpath 表达式是否通过 scrapy shell 工作?输出是否可能来自 JavaScript ?此外,scrapy 提供了一个名为 extract_first() 的方法,因此您无需摆弄索引。

标签: python json regex scrapy rule


【解决方案1】:

您的代码充满了错误,当您运行蜘蛛时,您可以保存日志并使用 grep 进行检查:

scrapy crawl spidername 2>&1 | tee crawl.log

我发现的几个错误:

  • 您的 ApptoideItem 缺少 store_name 等字段以及其他字段。
  • 您的整个int() 转换是不安全的,这意味着如果您的response.css 返回None,如果它什么也没找到,则会出现错误。

要解决第二点,我建议查看scrapy ItemLoaders,这将允许您为某些字段指定默认行为,例如将字段_flag 中的项目转换为布尔值等。
同样正如 cmets 中提到的@Jan,您应该使用 extract_first() 方法而不是 extract()[0],extract_first 允许您在未找到任何内容时指定默认属性,即 .extract_first(default=0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 2017-06-14
    • 2015-12-28
    • 2016-10-30
    • 2019-10-12
    相关资源
    最近更新 更多