大师兄的Python学习笔记(二十九): 爬虫(十)

大师兄的Python学习笔记(二十八): 爬虫(九)
大师兄的Python学习笔记(三十): 爬虫(十一)

十一、Scrapy框架

  • 基于Twisted的异步处理框架,是纯Python实现的爬虫框架。
  • 功能强大、爬取效率高,是目前使用最广泛的爬虫框架。
  • 模块间的耦合度低,扩展能力强,扩展组件多,几乎可以应对所有的反爬网站。
1. Scrapy的安装
  • Scrapy库依赖Twisted 14.0、lxml 3.4、pyOpenSSL 0.14等库,在安装Scrapy之前,需要先安装依赖库,之后再安装Scrapypip install scrapy
  • 如果你安装了Anaconda,可以跳过依赖库安装,直接使用conda install scrapy
2. Scrapy的架构
组件 功能
Scrapy Engine
引擎
处理整个系统的数据流、触发事务,是整个框架的核心。
Items
项目
定义爬取结果的数据结构,爬取的数据会被赋值成该Item对象。
Scheduler
调度器
接收引擎发过来的请求并将其加入其队列中,在引擎再次请求时将请求提供给引擎。
Downloader
下载器
下载网页内容,并将网页内容返回给爬虫。
Spiders
爬虫
定义了爬取的逻辑和网页的解析规则,主要负责解析响应并生成提取结果和新的请求。
Item Pipeline
项目管道
负责处理由爬虫从网页抽取的项目,主要任务是清洗、验证和存储数据。
Downloader Middlewares
下载器中间件
位于引擎和下载器之间的Hook框架,主要处理引擎和下载器之间的请求及响应。
Spider Middlewares
爬虫中间件
位于引擎和爬虫间的Hook框架,主要处理向爬虫输入的响应和输出的结果及新的请求。
3. Scrapy的数据流
  • Scrapy的数据流由引擎控制,流程如下:

(1) 引擎打开网站,找到该网站的爬虫,并向该爬虫请求第一个要爬取的URL。
(2) 引擎爬虫中获取到第一个要爬取的URL,并通过调度器以Request的形式调度。
(3) 引擎调度器请求下一个要爬取的URL。
(4) 调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载器中间件转发给下载器下载。
(5) 页面下载完毕,下载器生成页面的Response,并通过下载器中间件发送给引擎
(6) 引擎从下载器中接收到Response,并将其通过爬虫中间件发送给爬虫处理。
(7) 爬虫处理Response,并返回提取到的项目及新的Request给引擎
(8) 引擎将爬虫返回的项目项目管道,并将新的Request调度器
不断重复(2)至(8),直到调度器中没有更多的Request,引擎关闭网站,爬取结束。

4. Scrapy的项目结构
  • 项目创建后,文件夹结构如下:

scrapy.cfg
project/
 __init__.py
 items.py
 pipelines.py
 settings.py
 middlewares.py
 spiders/
  __init__.py
  spider1.py
  spider2.py
  ... ...

文件 功能
scrapy.cfg 项目配置文件,定义了项目的配置文件路径、部署相关信息等内容。
items.py 定义项目的数据结构,所有项目的定义都可以放在这里。
pipelines.py 定义项目管道的实现,所有的项目管道都可以放在这里。
settings.py 定义项目的全局配置。
middlewares.py 定义爬虫中间件和下载器中间件的实现。
spiders 所有爬虫的实现,每个爬虫是一个文件。
5. 运行Scrapy
5.1 创建项目
  • Scrapy项目需要再命令行使用scrapy命令生成。
  • 使用scrapy startproject <projectname>创建。
5.2 创建爬虫
  • 爬虫必须继承scrapy.Spider
  • 可以在项目文件夹中使用scrapy genspider <spider_name> <domain>生成爬虫。
# -*- coding: utf-8 -*-
>>>import scrapy

>>>class DoubanSpider(scrapy.Spider):
>>>    name = 'douban'
>>>    allowed_domains = ['movie.douban.com']
>>>    start_urls = ['https://movie.douban.com/chart']

>>>    def parse(self, response):
>>>        pass
  • 生成的类包含了三个属性:nameallowed_domainsstart_urls
  • 生了一个方法:parse()
属性和方法 功能
name 爬虫名
allowed_domains 允许爬取的域名。
start_urls 爬虫启动时爬取的url列表,定义初始请求。
parse() 负责解析返回的响应,提取数据或进一步生成要处理的请求。
5.3 创建Item
  • Item是保存爬取数据的容器,使用方法类似字典。
  • 创建Item需要继承scrapy.Item类。
  • 需要定义类型为scrapy.Field的字段。
  • 编辑items.py:
>>># -*- coding: utf-8 -*-

>>># Define here the models for your scraped items
>>>#
>>># See documentation in:
>>># https://doc.scrapy.org/en/latest/topics/items.html

>>>import scrapy

>>>class ProjectSampleItem(scrapy.Item):
>>>    # define the fields for your item here like:
>>>    url = scrapy.Field()
>>>    title = scrapy.Field()
>>>    actors = scrapy.Field()
>>>    rating = scrapy.Field()
5.4 解析Response并复制Item
  • 可以使用爬虫的parse(response)解析response,并将解析结果赋值给Item。
  • 可以使用CSS或Xpath选择器。
  • 修改爬虫的·parse()·函数:
  • 此外,还需要修改爬虫的request header。
# -*- coding: utf-8 -*-
>>>import scrapy

>>>class DoubanSpider(scrapy.Spider):
>>>    name = 'douban'
>>>    allowed_domains = ['https://movie.douban.com/']
>>>    start_urls = ['https://movie.douban.com/chart//']

>>>    def start_requests(self):
>>>        yield scrapy.Request("https://movie.douban.com/chart",
>>>                      headers={
>>>                          'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"})

>>>    def parse(self, response):
>>>        films = response.css('.article .item')

>>>        for film in films:
>>>            item = ProjectSampleItem()
>>>            item['url'] = film.css('a::attr(href)').extract_first()
>>>            item['title'] = (film.css('a::text').extract())[2].strip('\n /')
>>>            item['actors'] = film.css('.pl::text').extract_first()
>>>            item['rating'] = film.css('.rating_nums::text').extract_first()
>>>            yield item
5.5 运行爬虫
  • 在项目目录使用scrapy crawl <spider>运行爬虫。
  • 如果一切顺利,运行爬虫后再控制台会显示爬取结果:
D:\project_sample>scrapy crawl douban
... ...
2020-09-09 10:30:32 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/chart> (referer: None)
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-09-04(美国网络) / 2020-09-11(中国大陆) / 刘亦菲 / 甄子丹 / 巩俐 / 李连杰 / 李截 / '
           '安柚鑫 / 马泰 / 赵家玲 / 郑佩佩 / 温明娜 / 曾晓童 / 袁文忠 / 唐辰瀛 / 道阿·茂阿 / 黄谷悦 / 尼尔森·李 '
           '/ 李勋 / 饶雪晶 / 袁之正 / 仁成外桥 / 加里·扬...',
 'rating': '4.7',
 'title': '花木兰',
 'url': 'https://movie.douban.com/subject/26357307/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-07-15(韩国) / 姜栋元 / 李贞贤 / 权海骁 / 李来 / 金敏载 / 具教焕 / 金度允 / 李艺媛 / '
           '文宇振 / 韩国 / 延尚昊 / 115分钟 / 釜山行2:半岛 / 动作 / 惊悚 / 延尚昊 Sang-ho Yeon / 韩语 '
           '/ 英语 / 粤语',
 'rating': '5.1',
 'title': '釜山行2:半岛',
 'url': 'https://movie.douban.com/subject/30299515/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-08-28(美国点映) / 2020-09-04(美国) / 杰西·普莱蒙 / 杰西·巴克利 / 托妮·科莱特 / '
           '大卫·休里斯 / 盖伊·博伊德 / 哈德莉·罗宾逊 / 格斯·伯尼 / 艾比·奎因 / 蔻碧·米纳菲 / 安东尼·格拉索 / '
           '泰迪·库卢卡 / 杰森·拉尔夫 / 奥利弗·普莱特...',
 'rating': '7.3',
 'title': '我想结束这一切',
 'url': 'https://movie.douban.com/subject/30129061/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-09-03(中国大陆网络) / 许君聪 / 刘奔 / 龚小钧 / 杨蕊嘉 / 田璐 / 程汉 / 杨迪 / 邓宛千 / '
           '张钧涵 / 陈铮 / 中国大陆 / 周润泽 / 84分钟 / 剧情 / 喜剧 / 动作 / 朱子奇 Ziqi Zhu / 周润泽 '
           'Runze Zhou / 汉语普通话',
 'rating': '6.0',
 'title': '东北往事:我叫刘海柱',
 'url': 'https://movie.douban.com/subject/35141706/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-07-29(韩国) / 郑雨盛 / 郭度沅 / 柳演锡 / 安古斯·麦克菲登 / 徐东甲 / 李南希 / 金重熙 / '
           '柳秀荣 / 李泰亨 / 申正根 / 廉晶雅 / 金容琳 / 金明坤 / 张光 / 李在勇 / 安内相 / 孙钟学 / 白龙 / '
           '寇比·法兰奇 / 斯科特·洛威尔 / 克里斯汀·达尔顿...',
 'rating': '5.8',
 'title': '铁雨2:首脑峰会',
 'url': 'https://movie.douban.com/subject/30479644/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-07-02(匈牙利) / 2020-08-25(加拿大网络) / 2020-09-25(美国) / 杰西卡·查斯坦 / '
           '科林·法瑞尔 / 约翰·马尔科维奇 / 吉娜·戴维斯 / 陈冲 / 戴安娜·西尔弗斯 / 科曼 / 艾恩·格拉法德 / '
           '杰丝·威克斯勒 / 埃夫卡·科瓦拉西尤斯 / 安妮·比萨比亚...',
 'rating': '4.9',
 'title': '艾娃',
 'url': 'https://movie.douban.com/subject/30289869/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-06-24(韩国) / 刘亚仁 / 朴信惠 / 全裴修 / 李铉旭 / 苏熙静 / 韩国 / 赵一亨 / 98分钟 / '
           '#活着 / 动作 / 惊悚 / 灾难 / 赵一亨 Il Cho / 马特·奈勒 Matt Naylor / 韩语',
 'rating': '5.6',
 'title': '#活着',
 'url': 'https://movie.douban.com/subject/34462775/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2019-12-04(海南电影节) / 2020-07-27(上海电影节) / 2020-08-27(中国大陆网络) / '
           '2021-03-25(中国大陆) / 张晓晨 / 隋咏良 / 上白 / 刘泳希 / 萧子墨 / 赵健 / 中国大陆 / 李云波 / '
           '92分钟 / 动作 / 悬疑 / 武侠 / 李云波 Yunbo Li / 汉语普通话',
 'rating': '5.1',
 'title': '无名狂',
 'url': 'https://movie.douban.com/subject/27131969/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-08-14(美国) / 杰米·福克斯 / 约瑟夫·高登-莱维特 / 多米尼克·菲什巴克 / 罗德里戈·桑托罗 / '
           '考特尼·万斯 / 艾米·兰德克 / 机关枪凯利 / 泰特·弗莱彻 / 阿伦·马尔多纳多 / 安德烈·沃德·哈蒙德 / '
           '可亚娜·西蒙妮·辛普森 / C.J.勒布朗...',
 'rating': '5.6',
 'title': '超能计划',
 'url': 'https://movie.douban.com/subject/30330875/'}
2020-09-09 10:30:32 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/chart>
{'actors': '2020-08-28(美国) / 麦茜·威廉姆斯 / 安雅·泰勒-乔伊 / 艾莉丝·布拉加 / 安东尼奥·班德拉斯 / 查理·希顿 '
           '/ 海皮·安德森 / 亨利·扎格 / 布鲁·亨特 / 莎拉·贝纳尼 / 美国 / 约什·布恩 / 98分钟 / 新变种人 / 动作 '
           '/ 科幻 / 恐怖 / 约什·布恩...',
 'rating': None,
 'title': '新变种人',
 'url': 'https://movie.douban.com/subject/26389321/'}
2020-09-09 10:30:32 [scrapy.core.engine] INFO: Closing spider (finished)
2020-09-09 10:30:32 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 525,
 'downloader/request_count': 2,
 'downloader/request_method_count/GET': 2,
 'downloader/response_bytes': 10137,
 'downloader/response_count': 2,
 'downloader/response_status_count/200': 1,
 'downloader/response_status_count/403': 1,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2020, 9, 9, 2, 30, 32, 810781),
 'item_scraped_count': 10,
 'log_count/DEBUG': 12,
 'log_count/INFO': 9,
 'response_received_count': 2,
 'robotstxt/request_count': 1,
 'robotstxt/response_count': 1,
 'robotstxt/response_status_count/403': 1,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 1,
 'scheduler/enqueued/memory': 1,
 'start_time': datetime.datetime(2020, 9, 9, 2, 30, 32, 379758)}
2020-09-09 10:30:32 [scrapy.core.engine] INFO: Spider closed (finished)
5.6 爬取子页面
  • 需要在爬虫中使用scrapy.Request(url,callback)函数。
  • url可以传递子页面的请求URL。
  • callback是用于解析的回调函数。
  • 首先在settings.py中加入request header:
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
  • 修改items.py
>>>import scrapy

>>>class ProjectSampleItem(scrapy.Item):
>>>    # define the fields for your item here like:
>>>    url = scrapy.Field()
>>>    title = scrapy.Field()
>>>    director = scrapy.Field()
>>>    actors = scrapy.Field()
  • 修改爬虫
>>># -*- coding: utf-8 -*-
>>>import scrapy
>>>from project_sample.items import ProjectSampleItem

>>>class DoubanSpider(scrapy.Spider):
>>>    name = 'douban'
>>>    allowed_domains = ['movie.douban.com']
>>>    start_urls = ['https://movie.douban.com/chart']

>>>    def parse(self, response):
>>>        # 爬取排行页并跳转爬取子页面
>>>        films = response.css('.article .item')

>>>        for film in films:
>>>            next = film.css('a::attr(href)').extract_first()
>>>            url = response.urljoin(next)
>>>            yield scrapy.Request(url=url,callback=self.parse_sub)

>>>    def parse_sub(self,response):
>>>        # 爬取子页面
>>>        item = ProjectSampleItem()
>>>        item['url'] = response.url
>>>        item['title'] = response.css('#content span::text').extract_first()
>>>        item['actors'] = response.css('.actor .attrs a::text').extract()
>>>        item['director'] = response.css('#info span .attrs a::text').extract_first()
>>>        yield item
  • 运行后成功爬取
D:\project_sample>scrapy crawl douban
... ...
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/34462775/>
{'actors': ['刘亚仁', '朴信惠'],
 'director': '赵一亨',
 'title': '#活着 #살아있다',
 'url': 'https://movie.douban.com/subject/34462775/'}
2020-09-09 11:18:48 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/subject/27131969/> (referer: https://movie.douban.com/chart)
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/35141706/>
{'actors': ['许君聪', '刘奔', '龚小钧', '杨蕊嘉', '田璐', '程汉', '杨迪', '邓宛千', '张钧涵', '陈铮'],
 'director': '周润泽',
 'title': '东北往事:我叫刘海柱',
 'url': 'https://movie.douban.com/subject/35141706/'}
2020-09-09 11:18:48 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/subject/30129061/> (referer: https://movie.douban.com/chart)
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/30479644/>
{'actors': ['郑雨盛',
            '郭度沅',
            '柳演锡',
            '安古斯·麦克菲登',
            '徐东甲',
            '李南希',
            '金重熙',
            '柳秀荣',
            '李泰亨',
            '申正根',
            '廉晶雅',
            '金容琳',
            '金明坤',
            '张光',
            '李在勇',
            '安内相',
            '孙钟学',
            '白龙',
            '寇比·法兰奇',
            '斯科特·洛威尔',
            '克里斯汀·达尔顿',
            '金胜泰',
            '郑镇珏',
            '俞成柱',
            '金重基',
            '申秀妍',
            '沈熙燮'],
 'director': '杨宇硕',
 'title': '铁雨2:首脑峰会 강철비2: 정상회담',
 'url': 'https://movie.douban.com/subject/30479644/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/26389321/>
{'actors': ['麦茜·威廉姆斯',
            '安雅·泰勒-乔伊',
            '艾莉丝·布拉加',
            '安东尼奥·班德拉斯',
            '查理·希顿',
            '海皮·安德森',
            '亨利·扎格',
            '布鲁·亨特',
            '莎拉·贝纳尼',
            'Colbi Gannett',
            'Tony Saquett',
            'Thomas Kee',
            'Mickey Gilmore',
            'Jeffrey Corazzini'],
 'director': '约什·布恩',
 'title': '新变种人 The New Mutants',
 'url': 'https://movie.douban.com/subject/26389321/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/30330875/>
{'actors': ['杰米·福克斯',
            '约瑟夫·高登-莱维特',
            '多米尼克·菲什巴克',
            '罗德里戈·桑托罗',
            '考特尼·万斯',
            '艾米·兰德克',
            '机关枪凯利',
            '泰特·弗莱彻',
            '阿伦·马尔多纳多',
            '安德烈·沃德·哈蒙德',
            '可亚娜·西蒙妮·辛普森',
            'C.J.勒布朗',
            'CG刘易斯',
            '约瑟夫·波利昆',
            'Jazzy De Lisser',
            '凯西·奈斯泰德',
            '珍妮特·罗斯·阮',
            '吉姆·克洛克',
            '乔恩·阿兹',
            '戴恩·罗兹',
            '怀尔德·韦恩',
            '贾斯汀·贾木什',
            '戈登·德克海默',
            '卢克·霍克斯',
            '彼得·詹梅斯',
            '托尼·查普曼·斯蒂尔',
            '约书亚·萨达索'],
 'director': '亨利·朱斯特',
 'title': '超能计划 Project Power',
 'url': 'https://movie.douban.com/subject/30330875/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/30289869/>
{'actors': ['杰西卡·查斯坦',
            '科林·法瑞尔',
            '约翰·马尔科维奇',
            '吉娜·戴维斯',
            '陈冲',
            '戴安娜·西尔弗斯',
            '科曼',
            '艾恩·格拉法德',
            '杰丝·威克斯勒',
            '埃夫卡·科瓦拉西尤斯',
            '安妮·比萨比亚',
            '克里斯托弗·J·多米格',
            'Janelle Feigley',
            'Rob Lévesque',
            'Omar Khan',
            'Matt Lindquist',
            'Nadezhda Russo',
            'Lin Hultgren'],
 'director': '泰特·泰勒',
 'title': '艾娃 Ava',
 'url': 'https://movie.douban.com/subject/30289869/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/27131969/>
{'actors': ['张晓晨', '隋咏良', '上白', '刘泳希', '萧子墨', '赵健'],
 'director': '李云波',
 'title': '无名狂',
 'url': 'https://movie.douban.com/subject/27131969/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/30129061/>
{'actors': ['杰西·普莱蒙',
            '杰西·巴克利',
            '托妮·科莱特',
            '大卫·休里斯',
            '盖伊·博伊德',
            '哈德莉·罗宾逊',
            '格斯·伯尼',
            '艾比·奎因',
            '蔻碧·米纳菲',
            '安东尼·格拉索',
            '泰迪·库卢卡',
            '杰森·拉尔夫',
            '奥利弗·普莱特',
            '弗雷德里克·沃丁',
            '瑞恩·斯蒂尔'],
 'director': '查理·考夫曼',
 'title': "我想结束这一切 I'm Thinking of Ending Things",
 'url': 'https://movie.douban.com/subject/30129061/'}
2020-09-09 11:18:48 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/subject/30299515/> (referer: https://movie.douban.com/chart)
2020-09-09 11:18:48 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/subject/26357307/> (referer: https://movie.douban.com/chart)
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/30299515/>
{'actors': ['姜栋元', '李贞贤', '权海骁', '李来', '金敏载', '具教焕', '金度允', '李艺媛'],
 'director': '延尚昊',
 'title': '釜山行2:半岛 부산행2-반도',
 'url': 'https://movie.douban.com/subject/30299515/'}
2020-09-09 11:18:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/subject/26357307/>
{'actors': ['刘亦菲',
            '甄子丹',
            '巩俐',
            '李连杰',
            '李截',
            '安柚鑫',
            '马泰',
            '赵家玲',
            '郑佩佩',
            '温明娜',
            '曾晓童',
            '袁文忠',
            '唐辰瀛',
            '道阿·茂阿',
            '黄谷悦',
            '尼尔森·李',
            '李勋',
            '饶雪晶',
            '袁之正',
            '仁成外桥',
            '加里·扬',
            '欧文·邝',
            '乌特卡什·安邦德卡尔',
            '钱姆·艾希勒珀拉',
            '大卫·T·林',
            '詹森·郑',
            'Jun Yu'],
 'director': '妮琪·卡罗',
 'title': '花木兰 Mulan',
 'url': 'https://movie.douban.com/subject/26357307/'}
2020-09-09 11:18:48 [scrapy.core.engine] INFO: Closing spider (finished)
2020-09-09 11:18:48 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 4349,
 'downloader/request_count': 12,
 'downloader/request_method_count/GET': 12,
 'downloader/response_bytes': 244117,
 'downloader/response_count': 12,
 'downloader/response_status_count/200': 12,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2020, 9, 9, 3, 18, 48, 623165),
 'item_scraped_count': 10,
 'log_count/DEBUG': 22,
 'log_count/INFO': 9,
 'request_depth_max': 1,
 'response_received_count': 12,
 'robotstxt/request_count': 1,
 'robotstxt/response_count': 1,
 'robotstxt/response_status_count/200': 1,
 'scheduler/dequeued': 11,
 'scheduler/dequeued/memory': 11,
 'scheduler/enqueued': 11,
 'scheduler/enqueued/memory': 11,
 'start_time': datetime.datetime(2020, 9, 9, 3, 18, 47, 281069)}
2020-09-09 11:18:48 [scrapy.core.engine] INFO: Spider closed (finished)
5.7 保存结果到文件
  • 使用Scrapy的Feed Exports功能可以直接将抓取结果导出文件, 命令行指令是scrapy crawl <spider> -o <filename>
  • 支持csv、xml、pickle、marshal等多种格式,还支持ftp和s3等远程输出。
D:\project_sample>scrapy crawl douban -o douban.json
... ...
D:\project_sample>type douban.json
[
{"url": "https://movie.douban.com/subject/30289869/", "title": "\u827e\u5a03 Ava", "actors": ["\u6770\u897f\u5361\u00b7\u67e5\u65af\u5766", "\u79d1\u6797\u00b7\u6cd5\u745e\u5c14", "\u7ea6\u7ff0\u00b7\u9a6c\u5c14\u79d1\u7ef4\u5947", "\u5409\u5a1c\u00b7\u6234\u7ef4\u65af", "\u9648\u51b2", "\u6234\u5b89\u5a1c\u00b7\u897f\u5c14\u5f17\u65af", "\u79d1\u66fc", "\u827e\u6069\u00b7\u683c\u62c9\u6cd5\u5fb7", "\u6770\u4e1d\u00b7\u5a01\u514b\u65af\u52d2", "\u57c3\u592b\u5361\u00b7\u79d1\u74e6\u62c9\u897f\u5c24\u65af", "\u5b89\u59ae\u00b7\u6bd4\u8428\u6bd4\u4e9a", "\u514b\u91cc\u65af\u6258\u5f17\u00b7J\u00b7\u591a\u7c73\u683c", "Janelle Feigley", "Rob L\u00e9vesque", "Omar Khan", "Matt Lindquist", "Nadezhda Russo", "Lin Hultgren"], "director": "\u6cf0\u7279\u00b7\u6cf0\u52d2"},
{"url": "https://movie.douban.com/subject/34462775/", "title": "#\u6d3b\u7740 #\uc0b4\uc544\uc788\ub2e4", "actors": ["\u5218\u4e9a\u4ec1", "\u6734\u4fe1\u60e0"], "director": "\u8d75\u4e00\u4ea8"},
{"url": "https://movie.douban.com/subject/30330875/", "title": "\u8d85\u80fd\u8ba1\u5212 Project Power", "actors": ["\u6770\u7c73\u00b7\u798f\u514b\u65af", "\u7ea6\u745f\u592b\u00b7\u9ad8\u767b-\u83b1\u7ef4\u7279", "\u591a\u7c73\u5c3c\u514b\u00b7\u83f2\u4ec0\u5df4\u514b", "\u7f57\u5fb7\u91cc\u6208\u00b7\u6851\u6258\u7f57", "\u8003\u7279\u5c3c\u00b7\u4e07\u65af", "\u827e\u7c73\u00b7\u5170\u5fb7\u514b", "\u673a\u5173\u67aa\u51ef\u5229", "\u6cf0\u7279\u00b7\u5f17\u83b1\u5f7b", "\u963f\u4f26\u00b7\u9a6c\u5c14\u591a\u7eb3\u591a", "\u5b89\u5fb7\u70c8\u00b7\u6c83\u5fb7\u00b7\u54c8\u8499\u5fb7", "\u53ef\u4e9a\u5a1c\u00b7\u897f\u8499\u59ae\u00b7\u8f9b\u666e\u68ee", "C.J.\u52d2\u5e03\u6717", "CG\u5218\u6613\u65af", "\u7ea6\u745f\u592b\u00b7\u6ce2\u5229\u6606", "Jazzy De Lisser", "\u51ef\u897f\u00b7\u5948\u65af\u6cf0\u5fb7", "\u73cd\u59ae\u7279\u00b7\u7f57\u65af\u00b7\u962e", "\u5409\u59c6\u00b7\u514b\u6d1b\u514b", "\u4e54\u6069\u00b7\u963f\u5179", "\u6234\u6069\u00b7\u7f57\u5179", "\u6000\u5c14\u5fb7\u00b7\u97e6\u6069", "\u8d3e\u65af\u6c40\u00b7\u8d3e\u6728\u4ec0", "\u6208\u767b\u00b7\u5fb7\u514b\u6d77\u9ed8", "\u5362\u514b\u00b7\u970d\u514b\u65af", "\u5f7c\u5f97\u00b7\u8a79\u6885\u65af", "\u6258\u5c3c\u00b7\u67e5\u666e\u66fc\u00b7\u65af\u8482\u5c14", "\u7ea6\u4e66\u4e9a\u00b7\u8428\u8fbe\u7d22"], "director": "\u4ea8\u5229\u00b7\u6731\u65af\u7279"},
{"url": "https://movie.douban.com/subject/35141706/", "title": "\u4e1c\u5317\u5f80\u4e8b\uff1a\u6211\u53eb\u5218\u6d77\u67f1", "actors": ["\u8bb8\u541b\u806a", "\u5218\u5954", "\u9f9a\u5c0f\u94a7", "\u6768\u854a\u5609", "\u7530\u7490", "\u7a0b\u6c49", "\u6768\u8fea", "\u9093\u5b9b\u5343", "\u5f20\u94a7\u6db5", "\u9648\u94ee"], "director": "\u5468\u6da6\u6cfd"},
{"url": "https://movie.douban.com/subject/27131969/", "title": "\u65e0\u540d\u72c2", "actors": ["\u5f20\u6653\u6668", "\u968b\u548f\u826f", "\u4e0a\u767d", "\u5218\u6cf3\u5e0c", "\u8427\u5b50\u58a8", "\u8d75\u5065"], "director": "\u674e\u4e91\u6ce2"},
{"url": "https://movie.douban.com/subject/26389321/", "title": "\u65b0\u53d8\u79cd\u4eba The New Mutants", "actors": ["\u9ea6\u831c\u00b7\u5a01\u5ec9\u59c6\u65af", "\u5b89\u96c5\u00b7\u6cf0\u52d2-\u4e54\u4f0a", "\u827e\u8389\u4e1d\u00b7\u5e03\u62c9\u52a0", "\u5b89\u4e1c\u5c3c\u5965\u00b7\u73ed\u5fb7\u62c9\u65af", "\u67e5\u7406\u00b7\u5e0c\u987f", "\u6d77\u76ae\u00b7\u5b89\u5fb7\u68ee", "\u4ea8\u5229\u00b7\u624e\u683c", "\u5e03\u9c81\u00b7\u4ea8\u7279", "\u838e\u62c9\u00b7\u8d1d\u7eb3\u5c3c", "Colbi Gannett", "Tony Saquett", "Thomas Kee", "Mickey Gilmore", "Jeffrey Corazzini"], "director": "\u7ea6\u4ec0\u00b7\u5e03\u6069"},
{"url": "https://movie.douban.com/subject/26357307/", "title": "\u82b1\u6728\u5170 Mulan", "actors": ["\u5218\u4ea6\u83f2", "\u7504\u5b50\u4e39", "\u5de9\u4fd0", "\u674e\u8fde\u6770", "\u674e\u622a", "\u5b89\u67da\u946b", "\u9a6c\u6cf0", "\u8d75\u5bb6\u73b2", "\u90d1\u4f69\u4f69", "\u6e29\u660e\u5a1c", "\u66fe\u6653\u7ae5", "\u8881\u6587\u5fe0", "\u5510\u8fb0\u701b", "\u9053\u963f\u00b7\u8302\u963f", "\u9ec4\u8c37\u60a6", "\u5c3c\u5c14\u68ee\u00b7\u674e", "\u674e\u52cb", "\u9976\u96ea\u6676", "\u8881\u4e4b\u6b63", "\u4ec1\u6210\u5916\u6865", "\u52a0\u91cc\u00b7\u626c", "\u6b27\u6587\u00b7\u909d", "\u4e4c\u7279\u5361\u4ec0\u00b7\u5b89\u90a6\u5fb7\u5361\u5c14", "\u94b1\u59c6\u00b7\u827e\u5e0c\u52d2\u73c0\u62c9", "\u5927\u536b\u00b7T\u00b7\u6797", "\u8a79\u68ee\u00b7\u90d1", "Jun Yu"], "director": "\u59ae\u742a\u00b7\u5361\u7f57"},
{"url": "https://movie.douban.com/subject/30479644/", "title": "\u94c1\u96e82\uff1a\u9996\u8111\u5cf0\u4f1a \uac15\ucca0\ube442: \uc815\uc0c1\ud68c\ub2f4", "actors": ["\u90d1\u96e8\u76db", "\u90ed\u5ea6\u6c85", "\u67f3\u6f14\u9521", "\u5b89\u53e4\u65af\u00b7\u9ea6\u514b\u83f2\u767b", "\u5f90\u4e1c\u7532", "\u674e\u5357\u5e0c", "\u91d1\u91cd\u7199", "\u67f3\u79c0\u8363", "\u674e\u6cf0\u4ea8", "\u7533\u6b63\u6839", "\u5ec9\u6676\u96c5", "\u91d1\u5bb9\u7433", "\u91d1\u660e\u5764", "\u5f20\u5149", "\u674e\u5728\u52c7", "\u5b89\u5185\u76f8", "\u5b59\u949f\u5b66", "\u767d\u9f99", "\u5bc7\u6bd4\u00b7\u6cd5\u5170\u5947", "\u65af\u79d1\u7279\u00b7\u6d1b\u5a01\u5c14", "\u514b\u91cc\u65af\u6c40\u00b7\u8fbe\u5c14\u987f", "\u91d1\u80dc\u6cf0", "\u90d1\u9547\u73cf", "\u4fde\u6210\u67f1", "\u91d1\u91cd\u57fa", "\u7533\u79c0\u598d", "\u6c88\u7199\u71ee"], "director": "\u6768\u5b87\u7855"},
{"url": "https://movie.douban.com/subject/30299515/", "title": "\u91dc\u5c71\u884c2\uff1a\u534a\u5c9b \ubd80\uc0b0\ud5892-\ubc18\ub3c4", "actors": ["\u59dc\u680b\u5143", "\u674e\u8d1e\u8d24", "\u6743\u6d77\u9a81", "\u674e\u6765", "\u91d1\u654f\u8f7d", "\u5177\u6559\u7115", "\u91d1\u5ea6\u5141", "\u674e\u827a\u5a9b"], "director": "\u5ef6\u5c1a\u660a"},
{"url": "https://movie.douban.com/subject/30129061/", "title": "\u6211\u60f3\u7ed3\u675f\u8fd9\u4e00\u5207 I'm Thinking of Ending Things", "actors": ["\u6770\u897f\u00b7\u666e\u83b1\u8499", "\u6770\u897f\u00b7\u5df4\u514b\u5229", "\u6258\u59ae\u00b7\u79d1\u83b1\u7279", "\u5927\u536b\u00b7\u4f11\u91cc\u65af", "\u76d6\u4f0a\u00b7\u535a\u4f0a\u5fb7", "\u54c8\u5fb7\u8389\u00b7\u7f57\u5bbe\u900a", "\u683c\u65af\u00b7\u4f2f\u5c3c", "\u827e\u6bd4\u00b7\u594e\u56e0", "\u853b\u78a7\u00b7\u7c73\u7eb3\u83f2", "\u5b89\u4e1c\u5c3c\u00b7\u683c\u62c9\u7d22", "\u6cf0\u8fea\u00b7\u5e93\u5362\u5361", "\u6770\u68ee\u00b7\u62c9\u5c14\u592b", "\u5965\u5229\u5f17\u00b7\u666e\u83b1\u7279", "\u5f17\u96f7\u5fb7\u91cc\u514b\u00b7\u6c83\u4e01", "\u745e\u6069\u00b7\u65af\u8482\u5c14"], "director": "\u67e5\u7406\u00b7\u8003\u592b\u66fc"}
]
  • 也可以通过在settings.py中自定义ItemExporter实现其它输出。
设置 默认 功能
FEED_URI None 导出Feed的URI。
启用Feed导出时需要此设置。
FEED_FORMAT None 要用于Feed的序列化格式。
FEED_EXPORT_ENCODING None 要用于Feed的编码。
FEED_EXPORT_FIELDS None 要导出的字段的列表。
FEED_STORE_EMPTY False 是否导出空Feed
FEED_STORAGES_BASE 包含Scrapy支持的内置Feed存储后端的字典。
FEED_EXPORTERS {} 包含您的项目支持的其他导出器的字典。
FEED_EXPORTERS_BASE 一个包含Scrapy支持的内置feed导出器的dict。

参考资料



本文作者:大师兄(superkmi)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353