zoukankan      html  css  js  c++  java
  • Scrapy003-项目流程

    Scrapy003-项目流程

    @(Spider)[POSTS]

    前两篇文章我们了解到Scrapy的原理和安装的相关知识,这节就需要知道创建项目流程的小知识。

    根据官方文档:http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html中的入门教程,将流程进一步细化。

    有些知识现在不需要明白,理解这个流程工作流程即可。

    1. 创建项目工程

    这里和Django很类似,基本上一个模子出来的。

    python
    scrapy startproject tutorial
    

    此命令属于全局命令,帮我们创建很多内容:

    python
    tutorial/
        scrapy.cfg
        tutorial/
            __init__.py
            items.py
            pipelines.py
            settings.py
            spiders/
                __init__.py
    

    这些文件的作用:

    • scrapy.cfg
      项目的配置文件,用于检测项目所在位置,加载默认配置文件的 入口

    • tutorial
      创建的项目目录

    • items.py
      项目中的Item文件,就是前面说过的:创建容器用于存储目标结果

    • piplines
      项目管道文件,对结果的进一步处理,然后持久化结果

    • settings
      整个项目的配置文件

    • spiders
      自定义爬虫的目录,将所有自定义的爬虫文件全部放在该目录

    还有很多其他目录,但是需要自己去添加,比如:添加自定义的中间件

    2. 定义数据容器Item

    Item是用来保存爬取到的数据的容器,其实Item是继承于Dict,也可以理解为Python字典的别名,并且提供了额外的保护机制来避免错误导致的未定义字段错误。

     具体情况,看看Item的源码就清楚了!

    类似Django里面的ORM操作,通过继承scrapy.Item类,根据定义类型scrapy.Field,来定义一个Item数据容器。

    比如:我们需要获取目标网页的

    • 名称
    • 链接
    • 描述内容

    对此,在items.py中定义相关的字段,具体如下:

    import scrapy
    
    class TutorialItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title = scrapy.Field()
        link = scrapy.Field()
        desc = scrapy.Field()
    

    在项目创建的时候,就已经为我们创建好对应的TutorialItem类,只需要我们添加对应的字段即可。

    3. 编写爬虫Spider

    我们需要在tutorial/spiders/目录下载创建自定义的爬虫文件,这里我们使用命令行工具(你也可以鼠标创建):

    scrapy genspider -t basic dmoz dmoz.org
    #scrapy genspider生成爬虫命令
    #-t 模板类型
    #domz 爬虫名称
    #dmoz.org 爬取的域名
    

    这里需要知道有这个命令即可。

    执行完以上命令后,会在tutorial/spiders/下自动生成dmoz.py文件,文件内容:

    import scrapy
    
    class DmozSpider(scrapy.Spider):
        name = "dmoz"
        allowed_domains = ["dmoz.org"]
        start_urls = ['http://dmoz.org/']
    
        def parse(self, response):
            pass
    

    命令行工具下,为我们自动创建了很多内容:

    • DmozSpider(scrapy.Spider)
      定义的爬虫类:名称+Spider,并继承scrapy.Spider类

    • name
      定义的爬虫名称,该名称必须是唯一的,用于区分Spider。

    • allowed_domains
      可爬取的域名

    • start_urls
      Spider启动时进行爬取的URL列表,也就是我们所说的种子URL。后续的URL从这些种子URL获取到数据。

    • parse()
      父类中的一个方法,该方法负责解析返回的数据(response data),并提取数据生成数据容器Item或生成需要进一步处理的URL的Request对象。当该爬虫被调用时,每个初始URL(种子URL)经过一系列流程到下载器处理后生成的响应对象(response)将会作为唯一的参数传递给该函数。

    responseDjango视图函数中的request原理一样

    下面开始写一个简单的爬虫实例

    在dmoz.py文件中,进行如下修改:

    import scrapy
    
    class DmozSpider(scrapy.Spider):
        name = "dmoz"
        allowed_domains = ["dmoz.org"]
        start_urls = [
            "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
            "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
        ]
    
        def parse(self, response):
            filename = response.url.split("/")[-2]
            with open(filename, 'wb') as f:
                f.write(response.body)
    

    上面是使用官方文档的例子

    4. 爬取

    此时,我们需要进入项目的根目录下,执行下列命令启动spider

    scrapy crawl dmoz #局部命令
    

    屏幕输出:

    2016-12-01 11:45:42 [scrapy] INFO: Scrapy 1.2.1 started (bot: tutorial)
    2016-12-01 11:45:42 [scrapy] INFO: Overridden settings: {'SPIDER_MODULES': ['tutoria
    l.spiders'], 'BOT_NAME': 'tutorial', 'NEWSPIDER_MODULE': 'tutorial.spiders', 'ROBOTS
    TXT_OBEY': True}
    2016-12-01 11:45:42 [scrapy] INFO: Enabled extensions:
    ['scrapy.extensions.corestats.CoreStats',
     'scrapy.extensions.logstats.LogStats',
     'scrapy.extensions.telnet.TelnetConsole']
    2016-12-01 11:45:42 [scrapy] INFO: Enabled downloader middlewares:
    ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
     'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
     'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
     'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
     'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
     'scrapy.downloadermiddlewares.retry.RetryMiddleware',
     'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
     'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
     'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
     'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
     'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware',
     'scrapy.downloadermiddlewares.stats.DownloaderStats']
    2016-12-01 11:45:42 [scrapy] INFO: Enabled spider middlewares:
    ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
     'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
     'scrapy.spidermiddlewares.referer.RefererMiddleware',
     'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
     'scrapy.spidermiddlewares.depth.DepthMiddleware']
    2016-12-01 11:45:42 [scrapy] INFO: Enabled item pipelines:
    []
    2016-12-01 11:45:42 [scrapy] INFO: Spider opened
    2016-12-01 11:45:42 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items
     (at 0 items/min)
    2016-12-01 11:45:42 [scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023
    2016-12-01 11:45:43 [scrapy] DEBUG: Crawled (200) <GET http://www.dmoz.org/robots.tx
    t> (referer: None)
    2016-12-01 11:45:44 [scrapy] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers
    /Programming/Languages/Python/Resources/> (referer: None)
    2016-12-01 11:45:44 [scrapy] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers
    /Programming/Languages/Python/Books/> (referer: None)
    2016-12-01 11:45:44 [scrapy] INFO: Closing spider (finished)
    2016-12-01 11:45:44 [scrapy] INFO: Dumping Scrapy stats:
    {'downloader/request_bytes': 734,
     'downloader/request_count': 3,
     'downloader/request_method_count/GET': 3,
     'downloader/response_bytes': 16013,
     'downloader/response_count': 3,
     'downloader/response_status_count/200': 3,
     'finish_reason': 'finished',
     'finish_time': datetime.datetime(2016, 12, 1, 3, 45, 44, 251572),
     'log_count/DEBUG': 4,
     'log_count/INFO': 7,
     'response_received_count': 3,
     'scheduler/dequeued': 2,
     'scheduler/dequeued/memory': 2,
     'scheduler/enqueued': 2,
     'scheduler/enqueued/memory': 2,
     'start_time': datetime.datetime(2016, 12, 1, 3, 45, 42, 567933)}
    2016-12-01 11:45:44 [scrapy] INFO: Spider closed (finished)
    

    查看包含 [dmoz] 的输出,可以看到输出的log中包含定义在start_urls的初始URL,并且与spider中是一一对应的。在log中可以看到其没有指向其他页面( (referer:None) )。

    同时还创建了两个文件:Book,Resources

    上述过程大致如下:

    ScrapySpiderstart_urls中的每个种子URL创建了一个scrapy.request请求对象,并将parse方法作为回调函数(callback)赋值给Request

    Request经过一些流程,生成scrapy.http.response响应对象,并发送给parse()处理。

    这个过程就是种子URL的整体数据流过程,后续处理的URL几乎都是在重复此流程。

    5. 提取数据到数据容器Item

    提取数据我们就需要一些选择器Selectors的知识,在网页中提取数据有很多方法。Scrapy使用了一种基于XpathCSS表达式的机制:Scrapy Selectors

    这里简单介绍四个基本方法:

    • xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。
    • css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.
    • extract(): 序列化该节点为unicode字符串并返回list
    • re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表

    推荐使用Xpath,简单方便,性能好,当然正则也是必须要熟练使用的。

    接下来,对dmoz.py进一步的修改:

    import scrapy
    from tutorial.items import TutorialItem #导入数据容器类
    
    class DmozSpider(scrapy.Spider):
        name = "dmoz"
        allowed_domains = ["dmoz.org"]
        start_urls = [
            "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
            "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
        ]
    
        def parse(self, response):
            for sel in response.xpath('//ul/li'):
                item = TutorialItem()
                item['title'] = sel.xpath('a/text()').extract()
                item['link'] = sel.xpath('a/@href').extract()
                item['desc'] = sel.xpath('text()').extract()
                yield item
    

    yield起到传值的作用,具体会在后面的源码分析中提到,敬请期待!

    做进一步的爬取:

    scrapy  crawl   dmoz
    

    在不禁用日志的情况下,我们可以看到爬取的内容:

    [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
         {'desc': [u' - By David Mertz; Addison Wesley. Book in progress, full text, ASCII format. Asks for feedback. [author website, Gnosis Software, Inc.
    ],
          'link': [u'http://gnosis.cx/TPiP/'],
          'title': [u'Text Processing in Python']}
    [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/>
         {'desc': [u' - By Sean McGrath; Prentice Hall PTR, 2000, ISBN 0130211192, has CD-ROM. Methods to build XML applications fast, Python tutorial, DOM and SAX, new Pyxie open source XML processing library. [Prentice Hall PTR]
    '],
          'link': [u'http://www.informit.com/store/product.aspx?isbn=0130211192'],
          'title': [u'XML Processing with Python']}
    

    6.保存爬取的数据

    最简单的存储方式是使用Feed exports

    scrapy crawl dmoz -o items.json
    

    该命令将采用 JSON 格式对爬取的数据进行序列化,生成 items.json 文件。


    以上流程是使用Scrapy框架的组基本的流程,还有很多内容没有涉及到,在后面的实战篇将提及到。

  • 相关阅读:
    143、Java内部类之访问方法中定义的参数或变量
    142、Java内部类之在普通方法里面定义内部类
    141、Java内部类之实例化外部类对象
    140、Java内部类之实例化内部类对象
    139、Java内部类之使用this访问外部类属性
    138、Java内部类之访问内部类的私有属性
    137、Java内部类之把内部类放到外部
    136、Java的内部类
    135、Java中的静态块,构造方法和构造块
    134、Java中的构造方法和构造块
  • 原文地址:https://www.cnblogs.com/liu-yao/p/6166491.html
Copyright © 2011-2022 走看看