DC-01:爬虫框架scrapy入门

本主题主要是scrapy入门,包含内容如下:
  1. Scrapy框架环境搭建;
  2. 理解scrapy框架结构;
  3. 理解并能处理简单的数据流;
  
如果想关注爬虫的高级技术与应用场景,请关注后继内容与马哥教育。这个系列包括数据采集,数据分析与数据可视化。

一、Scrapy安装

  Scrapy的安装是比较简单的,直接使用pip可以完成最新版本的安装。
  
  目前最新版本是:1.6。

1.官网地址

  Scrapy的官方地址是:https://scrapy.org !

《DC-01:爬虫框架scrapy入门》 scrapy官网截图

2. 安装

  安装指令


pip install scrapy

  安装过程
《DC-01:爬虫框架scrapy入门》 安装过程截图

3. 测试安装

  只需要启动python交互式编程终端,看看能否import模块scrapy即可;
《DC-01:爬虫框架scrapy入门》 安装测试截图

4. scrapy帮助

  在交互式编程终端,使用import引入scrapy模块,并使用help(scrapy)获取scrapy框架API整体模块结构(其他更加详细的帮助可以使用help与dir获取)
《DC-01:爬虫框架scrapy入门》 scrapy帮助使用截图

5. 教程与参考资料

  最好的教程我个人认为还是官方的教程+API帮助。
《DC-01:爬虫框架scrapy入门》 官方教程与API截图

二、Scrapy组件结构与工作流程

1. 核心组件介绍

1.1. 组件01:引擎(Scrapy Engine)

  Scrapy Engine引擎作用有两个:
    1. 控制Scrapy框架中所有组件之间的数据流;
    2. 并在某些爬取动作发生的时候触发数据处理事件。

1.2. 组件02:调度器(Scheduler)

  调度器(Scheduler)接收来自引擎的请求,并将它们排队,以便在引擎请求时向引擎提供这些请求。

1.3. 组件03:下载器(Downloader)

  下载者(Downloader)负责下载网页并将其发送给引擎,引擎把下载的网页发送给蜘蛛/爬虫处理。

1.4. 组件04:蜘蛛/爬虫(Spiders)

  蜘蛛/爬虫(Spider)负责解析下载器下载的网页,并从中提取数据项(ITEM)(也称为爬取项)或后续的爬取请求。
  蜘蛛/爬虫(Spider)一般由用户实现,用来实现用户的爬取逻辑。一般继承Spider类来定制实现。

1.5. 组件05:数据项管道(Item Pipeline)

  数据项管道(Item Pipeline)负责处理被蜘蛛/爬虫提取(或爬取)的数据项。典型的任务包括:
    1. 清理;
    2. 验证;
    3. 持久存储(如将数据项存储在数据库关系数据库或者NoSQL数据库中)。

1.6. 组件06:下载器中间件(Downloader middlewares)

  下载器中间件(Downloader middlewares)是位于引擎和下载器之间的特定功能的回调Hook,负责处理从引擎传递到下载器时处理请求,以及从下载器传递到引擎的响应
  使用下载器中间件(Downloader middlewares)的几种情况:
    1. 在将请求发送给下载者之前处理该请求(即在Scrapy将请求发送到网站之前);
    2. 在传递给spider之前改变接受到的响应;
    3. 重新发送新的请求,而不是将收到的响应传递给spider;
    4. 在没有爬取到网页的情况下,发送一个响应给spider;
    5. 需要根据条件放弃一些请求。

1.7. 组件07:蜘蛛/爬虫中间件(Spider middlewares)

  蜘蛛/爬虫中间件(Spider middlewares)是位于引擎和蜘蛛之间的特定功能的Hook,负责处理Spider的输入(响应)和输出(数据项或者请求)。
  蜘蛛/爬虫中间件(Spider middlewares)的几种情况:
    1. spider回调的输出后的处理:包含:更改/添加/删除请求或数据项;
    2. 开始请求的后处理;
    3. 处理spider异常;
    4. 对一些基于响应内容的请求调用errback,而不是回调。

2. 核心工作流程

  Scrapy的工作流程是按照爬取的数据设计的流程,并据此设计组件结构。(下图是来自Scrapy的官方文档)
《DC-01:爬虫框架scrapy入门》 scrapy框架核心组件与数据流示意图

2.1. 流程01-获取请求

  引擎从蜘蛛获取需要爬取的初始请求。
    源:Spider
    目标:Engine
    数据:请求

2.2. 流程02-请求调度安排

  引擎调度爬取请求到调度器,并申请下一个需要爬取的爬取请求。
    源:Engine
    目标:Scheduler
    数据:请求

2.3. 流程03-调度爬取请求

  引擎器返回下一个爬取请求给引擎。(为什么不直接爬取,而是需要经过调度器处理呢?调度的好处在于:多任务爬取,还可以处理爬取请求与爬取过程的时间不一致的时间差。)
    源:Scheduler
    目标:Engine
    数据:请求

2.4. 流程04-发送请求给下载器

  引擎将请求发送到下载器,并通过下载器中间软件传递(process_request回调函数可以处理请求数据)。
    源:Engine
    目标:Downloader
    数据:请求

2.5. 流程05-下载器完成下载

  一旦页面下载器完成页面下载,下载器将使用下载好的页面生成一个响应(使用该页面),并将其发送到引擎,通过下载器中间软件(process_response回调函数完成下载后的页面数据处理)。
    源:Downloader
    目标:Engine
    数据:响应

2.6. 流程06-数据项抽取

  引擎从下载器接收响应并将其发送到spider进行处理,并通过spider中间件进行处理(process_spider_input回调函数处理爬取的网页数据)。
    源:Engine
    目标:Spider
    数据:响应

2.7. 流程07-返回抽取的数据与请求

  Spider处理响应(从爬取的网页中抽取需要的数据项),并通过spider中间件(process_spider_output回调函数处理Spider处理过的数据)向引擎返回抽取的数据项或者新的附加请求。
    源:Spider
    目标:Engine
    数据:数据项(附加的请求)

2.8. 流程08-存储抽取的数据项

  引擎将已处理的数据项发送到数据项管道,然后将已附加的请求发送到调度程序,并请求可能的下一个请求进行爬取。
    源:Engine
    目标:Item Pipeline/Scheduler
    数据:数据项/附加请求

2.9. 流程09-结束爬取

  重复01-08,直到调度器中没有请求调度为止。

三、Scrapy入门

  这个入门是按照官方的教程组织。
  不是上面介绍的每个组件都需要我们开发,实际只需要我们开发业务部分,爬虫的通用功能部分都封装到框架中,所以我们需要一个框架的环境,并理解整个工作流程,并关注需要开发的部分,以及开发部分与整个框架组件的关系。

1. 创建一个爬虫项目

  爬虫项目使用scrapy框架提供的一个工具创建:scrapy,该工具创建的项目会提供业务部分运行的环境与配置。

1.1. scrapy工具介绍

1.1.1. 获取scrapy工具帮助

  直接在终端输入scrapy,可以直接输出scrapy工具的帮助。
命令:

localhost:~ yangqiang$ scrapy 

《DC-01:爬虫框架scrapy入门》 scrapy工具帮助获取截图

  其中startproject命令项就是我们马上要使用来创建项目的。

1.1.2. 获取startproject命令项帮助

  获取帮助的指令:


localhost:~ yangqiang$ scrapy startproject -h

《DC-01:爬虫框架scrapy入门》 创建爬虫项目指令startproject帮助获取截图

1.2. 使用scrapy工具创建一个爬虫项目

  创建爬虫项目的两个重要参数:
    1. 项目名称
    2. 项目存放目录(可选,默认当前目录)

1.2.1. 创建项目


localhost:codes yangqiang$ scrapy startproject FirstScrapy

《DC-01:爬虫框架scrapy入门》 创建项目过程与结果截图

1.2.2. 创建好的项目文件

  可以查看创建的项目,其中的文件结合上面的组件与工作流程,大致也知道其用途与作用。
《DC-01:爬虫框架scrapy入门》 创建的爬虫项目工程

1.3. 使用pycharn打开创建的项目

  可以使用pycharm IDE工具打开创建的爬虫项目:

《DC-01:爬虫框架scrapy入门》 使用pycharm打开爬虫项目工程

2. 实现爬虫业务

  因为在框架在开发,为了保证框架能顺利工作,需要按照设计的结构,继承scrapy.Spider类,并发起一个爬取请求,并处理。

2.1. 创建爬虫代码模块

  在项目的spiders包路径下,创建一个python源代码文件:spiders.home_spider.py

《DC-01:爬虫框架scrapy入门》 使用pycharm创建的爬虫代码模块

2.2. 继承Spider

  由于Spider是抽象类,需要override其中的抽象函数。


   def parse(self, response):
        raise NotImplementedError('{}.parse callback is not defined'.format(self.__class__.__name__))

  继承Spider类后的子类:

# coding = utf-8
import scrapy


class HomeSpider(scrapy.Spider):

    def parse(self, response):
        pass

2.3. 爬虫中两个重要的属性

2.3.1. name属性

  name属性,用来在执行爬虫的时候指定爬虫。属性类型是字符串。

2.3.2. start_urls属性

  start_urls属性用来发起一个爬虫任务请求。属性类型是列表。

2.3.3. 属性实现代码

# coding = utf-8
import scrapy


class HomeSpider(scrapy.Spider):
    name = 'home'
    start_urls = [
        'https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1',
    ]
    
    def parse(self, response):
        pass

3. scrapy工具与运行爬虫项目

3.1. 在项目目录下的scrapy工具的帮助

  在scrapy工具创建的爬虫项目顶层目录下,执行scrapy工具获取的帮助会更多。
  命令:


localhost:FirstScrapy yangqiang$ scrapy

  执行效果:

《DC-01:爬虫框架scrapy入门》 在爬虫项目目录下获取scrapy工具与在其他地方得到的帮助内容存在不同

  与项目相关的命令有(6个):
    list:列出项目中爬虫列表。
    check:检查爬虫。
    crawl:启动爬虫任务。
    edit:编辑爬虫。
    fetch:获取。
    parse:解析。
  上述命令的使用,使用帮助可以获取。具体的使用在后面会介绍。

《DC-01:爬虫框架scrapy入门》 scrapy的edit指令帮助截图

3.2. list爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy list

  效果:
《DC-01:爬虫框架scrapy入门》 list指令使用截图

3.3. edit爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy edit home

  一般不使用这个指令在字符界面下编辑,而是使用IDE工具编辑。不过远程维护使用字符界面是非常方便的,

  效果:
《DC-01:爬虫框架scrapy入门》 edit指令使用截图

3.4. crawl爬虫-运行爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy crawl home

  使用该命令启动爬虫任务,其中home是爬虫程序中name指定的爬虫名。
  效果:

《DC-01:爬虫框架scrapy入门》 crawl指令执行截图

3.5. check爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy check home

  检查爬虫代码中的错误。

  下面是没有错误的例子:
《DC-01:爬虫框架scrapy入门》 对没有错误的爬虫check执行的截图

  下面是有错误的例子(随便在代码中设计几个错误即可)。
《DC-01:爬虫框架scrapy入门》 对存在语法错误的爬虫代码执行check的截图

3.6. parse爬虫

  parse命令用来测试爬虫的parse函数。
  parse命令的帮助:

《DC-01:爬虫框架scrapy入门》 parse指令的帮助

  命令:

localhost:FirstScrapy yangqiang$ scrapy parse --spider=home https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1

  效果(当没有指定爬虫名,这会使用url直接创建一个爬虫,但是scrapy存在bug,会报错,在github上已经有人修正这个bug,可以通过百度找到这个帖子):

《DC-01:爬虫框架scrapy入门》 parse指令执行的截图

3.7. fetch爬虫

  直接下载页面,并显示在终端。
  命令:

localhost:FirstScrapy yangqiang$ scrapy fetch https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1

  效果:

《DC-01:爬虫框架scrapy入门》 fetch指令执行截图

3.8. genspider生成爬虫

  genspider可以查看爬虫模板,创建爬虫,编辑爬虫等功能。其帮助如下:

《DC-01:爬虫框架scrapy入门》 genspider指令的帮助

3.8.1. 查看模板

  一般默认的模板是basic。
  命令:

localhost:FirstScrapy yangqiang$ scrapy genspider -l

  效果:

《DC-01:爬虫框架scrapy入门》 查看已有的爬虫模板

3.8.2. 创建爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy genspider -t crawl  myspider https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1

  效果:
《DC-01:爬虫框架scrapy入门》 使用genspide创建爬虫的过程截图

  创建后,在项目工程中能看见这个爬虫代码文件:!
《DC-01:爬虫框架scrapy入门》 在pycharm中查看创建的爬虫代码模块

3.8.3. 创建并编辑爬虫

  命令:

localhost:FirstScrapy yangqiang$ scrapy genspider -e  myspider 'https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1'

  这个命令是先创建,后编辑。注意:编辑中需要项目的模块导入,否则编辑不会正常。不过一般创建好以后,也不会在终端下编辑。

3.9. view查看爬取页面

  该命令首先下载页面,然后使用浏览器打开。
  命令:

localhost:FirstScrapy yangqiang$ scrapy  view https://www.baidu.com

  效果:
《DC-01:爬虫框架scrapy入门》 view指令执行截图

3.10. shell交互式爬虫处理

  使用交互式处理爬虫数据处理。与代码一样,只是交互式开发模式。
  命令:

localhost:FirstScrapy yangqiang$ scrapy shell 'https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1'

  效果(绿色的表示代码输入):
《DC-01:爬虫框架scrapy入门》 shell交互式爬虫处理截图

  交互式编程示例:
《DC-01:爬虫框架scrapy入门》 交互式代码输入与执行截图

3.11. settings获取settings.py中的配置

  settings指令用来获取与设置settings.py中的配置值。
  命令:

localhost:FirstScrapy yangqiang$ scrapy settings --get=SPIDER_MODULES

  效果:
《DC-01:爬虫框架scrapy入门》 使用settings指令获取settings文件中定义的配置

  下面是settings.py文件:
《DC-01:爬虫框架scrapy入门》 settings.py文件截图

3.12. runspider运行爬虫文件

  这个命令是直接执行爬虫代码文件,与crawl的区别在于,crawl执行的是爬虫项目spiders目录下的有爬虫名的爬虫。
  命令:

localhost:FirstScrapy yangqiang$ scrapy runspider ./FirstScrapy/spiders/home_spider.py

  效果:
《DC-01:爬虫框架scrapy入门》 独立于爬虫项目来执行某个爬虫代码

四、爬虫中的数据流与数据处理

1. 创建一个测试项目

  使用scrapy工具创建一个爬虫数据流与数据处理的测试项目。
  创建命令:

localhost:codes yangqiang$ scrapy  startproject  Scra_DataFlow

  创建过程:
《DC-01:爬虫框架scrapy入门》 创建一个数据流演示项目工程

  下面主要关注点在数据上,所以其他scarpy工具等使用细节可以参考上面的帮助。
  同时,scrapy爬虫框架提供了一些快捷实现方式,下面都采用传统的思路实现,这样容易理解,快捷方式的介绍不作为重点,甚至不在这里介绍。

2. 爬虫目标

2.1. 爬取站点

  爬取腾讯课堂上的数据。爬取腾讯课堂基础课程中的Python付费课程信息。
《DC-01:爬虫框架scrapy入门》 爬取目标网站截图

2.2. 爬取数据

  课程名称,培训机构,购买人数,课程价格,开课方式等。

2.3. 理解domain与url

  domain:https://ke.qq.com
  urls:https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1

3. 使用命令创建爬虫

  使用scrapy的genspider指令创建spider代码模板。
  命令:

localhost:Scra_DataFlow yangqiang$ scrapy genspider -t basic  course  ke.qq.com

《DC-01:爬虫框架scrapy入门》 使用genspider用basic模板创建一个爬虫模块

  创建好的代码如下:

# -*- coding: utf-8 -*-
import scrapy


class CourseSpider(scrapy.Spider):
    name = 'course'
    allowed_domains = ['ke.qq.com']
    start_urls = ['http://ke.qq.com/']

    def parse(self, response):
        pass


  在Pycharm中,代码在项目中的截图:

《DC-01:爬虫框架scrapy入门》 在pycharm中打开创建的爬虫代码

4. 爬取URL

  实际需要爬取的页面URL为:
    https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1

  这是scrapy框架数据流的第01步。从爬虫发起一个请求。
  该请求,使用迭代器的方式返回给爬虫引擎:
    方式一:是引擎调用def start_requests(self)函数,通过返回值得到请求。
    方式二:覆盖父类的start_urls属性,用来替代默认的 start_requests函数,返回请求。

  然后爬虫引擎,把请求发送给调度器(流程02),根据处理资源的情况,引擎从调度器获取请求(流程03),再发送给下载器(流程04)。

  下载器使用引擎发送过来的请求,完成下载任务,并把下载的响应返回给引擎(流程05)。引擎把响应通过parse函数传递给爬虫程序(流程06),爬虫通过parse函数参数,得到下载响应。其中想用通过response对象获取,该响应对象的类型是:<class ‘scrapy.http.response.html.HtmlResponse’>。

  注意:流程01,02,03,04,05,06都是框架自动完成,如果不做特别的处理,可以不干预框架的流程,直接在流程06的结束得到一个响应对象。

  scrapy框架的数据流,注意其中的编号,对应这我们这里的一样的编号。
《DC-01:爬虫框架scrapy入门》 为了查看方便,再显示下官方的数据流示意图

5. 通过parse函数的参数,获取下载响应

5.1. scrapy.http.response.html.HtmlResponse类

  数据成员:
    |- encoding
    |- selector
    |- text
    |- body
    |- meta
    |- url
  函数成员:
    |- body_as_unicode(self)
      |- 返回一个unicode的body
    |- css(self, query)
    follow(self, url, callback=None, method=’GET’, headers=None, body=None, cookies=None, meta=None, encoding=None, priority=0, dont_filter=False, errback=None)
      |- 返回Request类型的对象。
    |- replace(self, *args, **kwargs)
    |- urljoin(self, url)
    |- xpath(self, query, **kwargs)

  获取解码后的文本页面内容。
    |- text
  数据解析接口:
    |- css(self, query)
    |- xpath(self, query, **kwargs)

5.2. 直接处理(中断数据流)

5.2.1. 直接保存成文件

  这类直接保存成html文本文件。

# -*- coding: utf-8 -*-
import scrapy


class CourseSpider(scrapy.Spider):
    name = 'course'
    allowed_domains = ['ke.qq.com']
    start_urls = ['https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1']

    def parse(self, response):
        # 2019-02-14 15:00:14 [course] DEBUG: <class 'scrapy.http.response.html.HtmlResponse'>
        # self.log(type(response))
        # utf-8
        # self.log(response.encoding)
        # <Selector xpath=None data='<html lang="zh">\n<head>\n    <meta charse'>
        # self.log(response.selector)
        # self.log(response.text)   # unicode的文本内容
        # self.log(response.body)     # 二进制内容
        #  {'download_timeout': 180.0, 'download_slot': 'ke.qq.com', 'download_latency': 0.592094898223877}
        # self.log(response.meta)
        # https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1
        # self.log(response.url)
        # 保存下载的页面到文件,护或者到数据库(可以考虑文档数据库或者mysql关系数据库)
        with open('page.html', 'w') as fd:
            fd.write(response.text)

  下载后保存的文件内容。
《DC-01:爬虫框架scrapy入门》 直接保存的下载页面的截图

5.2.2. 解析保存成csv文件

  从浏览器获取XPATH格式(/html/body/section[1]/div/div[3]/ul):

《DC-01:爬虫框架scrapy入门》 从浏览器获取xpath数据的截图

  把浏览器中获取的XPATH按照我们的需求修改:
    | – 浏览器XPATH:/html/body/section[1]/div/div[3]/ul
    | – 修改后XPATH://section[1]/div/div[3]/ul/li
  
  因为XPATH是从body文档开始解析的,同时我们希望获取页面上24门课程的内容。
  代码如下:

# -*- coding: utf-8 -*-
import scrapy


class CourseSpider(scrapy.Spider):
    name = 'course'
    allowed_domains = ['ke.qq.com']
    start_urls = ['https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1']

    def parse(self, response):
        # 解析数据,并保存成csv文件。
        result = response.xpath('//section[1]/div/div[3]/ul/li')
        self.log('XXXX:{}'.format(len(result)))

  运行爬虫的输出结果是:
《DC-01:爬虫框架scrapy入门》 使用xpath获取到我们需要爬取得24们课程列表截图

  xpath返回的是一个list列表,其中元素的类型是:<class ‘scrapy.selector.unified.Selector’>,该类型的API帮助可以使用help获取。
  下面我们可以直接解析得到需要的字段(保存到csv的实现,这里就略掉,其中使用了xpath或者css,这个知识点,下面专门讲解)。

# -*- coding: utf-8 -*-
import scrapy


class CourseSpider(scrapy.Spider):
    name = 'course'
    allowed_domains = ['ke.qq.com']
    start_urls = ['https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1']

    def parse(self, response):
        # 解析数据,并保存成csv文件。
        result = response.xpath('//section[1]/div/div[3]/ul/li')
        for course_ in result:
            # self.log(type(course_))
            # 课程名称
            course_name = course_.xpath('h4[@class="item-tt"]/a/text()').get()
            self.log('课程名称:{}'.format(course_name.strip() if course_name else ''))
            # 培训机构
            course_organization = course_.xpath(
                'div[@class="item-line item-line--middle"]/span[@class="item-source"]/a/text()').get()
            self.log('培训机构:{}'.format(course_organization.strip() if course_organization else ''))
            # 课程连接
            course_link = course_.xpath('h4[@class="item-tt"]/a/@href').get()
            self.log('课程连接:{}'.format(course_link.strip() if course_link else ''))
            # 报名人数
            course_number = course_.xpath(
                'div[@class="item-line item-line--middle"]/span[@class="line-cell item-user"]/text()').get()
            self.log('报名人数:{}'.format(course_number.strip()  if course_number else ''))
            # 课程状态
            course_status = course_.xpath('div[@class="item-status"]/text()').get()
            self.log('课程状态:{}'.format(course_status.strip() if course_status else ''))
            # 课程价格
            course_price = course_.xpath('div[@class="item-line item-line--bottom"]/span/text()').get()
            self.log('课程价格:{}'.format(course_price.strip() if course_price else ''))

  解析的效果:
《DC-01:爬虫框架scrapy入门》 每门课程解析的结果输出截图

5.3. 返回数据项到管道(流程07与流程08)

  在parse函数中,实际是可以返回数据的:
    | – 返回的数据是Items,则引擎接受到数据后,会发送给管道Pipeline。
    | – 返回Request请求,则把Request发送给调度器,继续爬取数据。
  
  这里只关注返回Items,返回Request的情路,后面说明。

5.3.1. 定义Items的数据项

  继承scrapy.Item类,对应需要接续的字段定义数据项。


# -*- 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 ScraDataflowItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 课程名称
    course_name = scrapy.Field()
    # 培训机构
    course_organization = scrapy.Field()
    # 课程连接
    course_link = scrapy.Field()
    # 报名人数
    course_number = scrapy.Field()
    # 课程状态
    course_status = scrapy.Field()
    # 课程价格
    course_price = scrapy.Field()

5.3.2. 使用数据项,缓存爬取的数据字段

  使用数据项比较模式化,比较容易理解。 下面是实现代码:

# -*- coding: utf-8 -*-
import scrapy
from  Scra_DataFlow.items import ScraDataflowItem

class CourseSpider(scrapy.Spider):
    name = 'course'
    allowed_domains = ['ke.qq.com']
    start_urls = ['https://ke.qq.com/course/list?mt=1001&st=2002&tt=3019&price_min=1&page=1']

    def parse(self, response):
        result = response.xpath('//section[1]/div/div[3]/ul/li')
        items = []    # 数据项数组列表
        for course_ in result:
            # 数据项
            item_ = ScraDataflowItem()
            course_name = course_.xpath('h4[@class="item-tt"]/a/text()').get()
            item_['course_name'] = '{}'.format(course_name.strip() if course_name else '')
            # 培训机构
            course_organization = course_.xpath(
                'div[@class="item-line item-line--middle"]/span[@class="item-source"]/a/text()').get()
            item_['course_organization'] = course_organization.strip() if course_organization else ''
            # 课程连接
            course_link = course_.xpath('h4[@class="item-tt"]/a/@href').get()
            item_['course_link'] = course_link.strip() if course_link else ''
            # 报名人数
            course_number = course_.xpath(
                'div[@class="item-line item-line--middle"]/span[@class="line-cell item-user"]/text()').get()
            item_['course_number'] = course_number.strip()  if course_number else ''
            # 课程状态
            course_status = course_.xpath('div[@class="item-status"]/text()').get()
            item_['course_status'] = course_status.strip() if course_status else ''
            # 课程价格
            course_price = course_.xpath('div[@class="item-line item-line--bottom"]/span/text()').get()
            item_['course_price'] = course_price.strip() if course_price else ''
            items.append(item_)
        # 返回数据项到管道
        return items

5.3.3. 使用管道保存数据

  使用命令:

localhost:Scra_DataFlow yangqiang$ scrapy crawl course  -o course.csv

  执行过程:
《DC-01:爬虫框架scrapy入门》 输出csv文件的爬虫执行过程截图

  提示:pycharm可以安装csv的插件,用来显示csv文件
《DC-01:爬虫框架scrapy入门》 pycharm的csv插件安装截图

  使用管道保存的文件(不使用插件在pycharm显示):
《DC-01:爬虫框架scrapy入门》 使用管道保存的文件显示截图(pychar无插件文本显示)

  使用管道保存的文件(使用插件在pycharm显示)
《DC-01:爬虫框架scrapy入门》 使用pycharm插件显示位表格

附录

  需要掌握爬虫的高级应用,以及一些经典场景应用,可以关注后继内容与马哥教育。

    原文作者:杨强AT南京
    原文地址: https://www.jianshu.com/p/0081ebcafe40
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞