前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >scrapy笔记六 scrapy运行架构的实例配合解析

scrapy笔记六 scrapy运行架构的实例配合解析

作者头像
十四君
发布2019-11-27 15:08:02
7710
发布2019-11-27 15:08:02
举报
文章被收录于专栏:Urlteam

在之前的项目中已经可以正常运行出scrapy框架下的爬虫程序,但是如果换一个项目换一个爬取任务,要活学活用还需要进行针对scrapy是如何运行的进行深入的学习.

目录:

基本概念

具体从代码中解析

item

pipelines

spiders

可以从这里学习详细的结构说明:

http://www.tuicool.com/articles/fiyIbq

基本概念

Scrapy框架主要由五大组件组成,调试器(Scheduler)、下载器(Downloader)、爬虫(Spider)和实体管道(Item Pipeline)、Scrapy引擎(Scrapy Engine)。

如下图.

Scrapy运行流程

  1. 首先,引擎从调度器中取出一个链接(URL)用于接下来的抓取
  2. 引擎把URL封装成一个请求(Request)传给下载器,下载器把资源下载下来,并封装成应答包(Response)
  3. 然后,爬虫解析Response
  4. 若是解析出实体(Item),则交给实体管道进行进一步的处理。
  5. 若是解析出的是链接(URL),则把URL交给Scheduler等待抓取

具体解析:

参照项目 meizitu 源代码在:

https://github.com/luyishisi/WebCrawlers/tree/master/scrapy_code/meizitu

item.py : 定义提取的数据结构:

在定义这部分时,要考虑项目目标是为了爬取妹子图网的图片,因此需要的结构有:

  • url : 页面路径 ;
  • name:页面名字 ;
  • tags : 页面标签(用于图片分类)
  • image_urls = 图片的地址 ;
  • images = 图片的名字

item代码如下:

代码语言:javascript
复制
import scrapy
class MeizituItem(scrapy.Item):
    url = scrapy.Field()
    name = scrapy.Field()
    tags = scrapy.Field()
    image_urls = scrapy.Field()
    images = scrapy.Field()
关于field

Field对象指明了每个字段的元数据(metadata)。

您可以为每个字段指明任何类型的元数据。Field 对象对接受的值没有任何限制。也正是因为这个原因,文档也无法提供所有可用的元数据的键(key)参考列表。Field 对象中保存的每个键可以由多个组件使用,并且只有这些组件知道这个键的存在

关于items.的实例化

可从抓取进程中得到这些信息, 比如预先解析提取到的原生数据,items 提供了盛装抓取到的数据的*容器* , 而Item Loaders提供了构件*装载populating*该容器。

在用于下面例子的管道功能时.在spiders中使用了item的实例化:代码如下:

代码语言:javascript
复制
def parse_item(self, response):
        #l=用ItemLoader载入MeizituItem()
        l = ItemLoader(item=MeizituItem(), response=response)
        #名字
        l.add_xpath('name', '//h2/a/text()')
        #标签
        l.add_xpath('tags', "//div[@id='maincontent']/div[@class='postmeta  clearfix']/div[@class='metaRight']/p")
        #图片连接
        l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity())
        #url
        l.add_value('url', response.url)
 
        return l.load_item()

最终, 当所有数据被收集起来之后, 调用 ItemLoader.load_item() 方法, 实际上填充并且返回了之前通过调用 add_xpath(), add_css(), and add_value() 所提取和收集到的数据的Item.

pipeline.py : (管道.用于保存数据)

需要导入settings配置文件,根据你保存的内容需要不同的包,例如,保存文本数据往往需要json包,本项目保存的是图片,则导入os包用于设定保存路径等.最重要的是要导入requests包.用于发送请求给图片的url,将返回的应答包进行保存.

本部分至少需要重写图片下载类,返回的是item对象.

这部分的特性是:
  • 避免重新下载最近已经下载过的数据
  • 指定存储数据位置
  • 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
  • 缩略图生成
  • 检测图像的宽/高,确保它们满足最小限制
 典型的工作流程如下:
  1. 在一个爬虫(在spiders.py中),你抓取一个项目,把其中图片的URL放入 file_urls 组内。 l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity()
  2. 项目从爬虫(在spiders.py中)内返回,进入项目管道(到pipeline.py中)。 return l.load_item()
  3. 当项目进入 Pipelinefile_urls || image_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载(将url请求发送到下载器)。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。
  4. 当文件下载完后,另一个字段(files)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 file_urls 组获得)和图片的校验码(checksum)。 files 列表中的文件顺序将和源 file_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 files 组中。
附录:

为了启用 media pipeline,你首先需要在项目中添加它setting.

对于 Images Pipeline, 使用:

代码语言:javascript
复制
<span class="n">ITEM_PIPELINES</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'scrapy.pipeline.<span style="color: #ff0000;">images</span>.<span style="color: #ff0000;">Images</span>Pipeline'</span><span class="p">:</span> <span class="mi">1</span><span class="p">}</span>

对于 Files Pipeline, 使用:

代码语言:javascript
复制
<span class="n">ITEM_PIPELINES</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'scrapy.pipeline.<span style="color: #ff0000;">files</span>.<span style="color: #ff0000;">Files</span>Pipeline'</span><span class="p">:</span> <span class="mi">1</span><span class="p">}</span>

因此配置文件如下:

代码语言:javascript
复制
BOT_NAME = 'meizitu'
 
SPIDER_MODULES = ['meizitu.spiders']
NEWSPIDER_MODULE = 'meizitu.spiders'
#载入ImageDownLoadPipeline类
#为了启用一个Item Pipeline组件,你必须将它的类添加到 ITEM_PIPELINES 配置
#分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,
TEM_PIPELINES = {'meizitu.pipelines.ImageDownloadPipeline': 1}
#图片储存,第一个meizitu是项目名称,imagedown部分则是类的名字.
IMAGES_STORE = '.'
pipeline代码如下:
代码语言:javascript
复制
# -*- coding: utf-8 -*-
 
#图片下载部分(自动增量)
import requests
from meizitu import settings
import os
 
#导入重写图片下载类
class ImageDownloadPipeline(object):
    def process_item(self, item, spider):
        #每个item pipeline组件都需要调用该方法,这个方法必须返回一个 Item (或任何继承类)对象,
        # 或是抛出 DropItem 异常,被丢弃的item将不会被之后的pipeline组件所处理
        if 'image_urls' in item:#如果‘图片地址’在项目中
            images = []#定义图片空集
            
            dir_path = '%s/%s' % (settings.IMAGES_STORE, spider.name)
 
            #建立目录名字和项目名称一致
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
    
            #根据item字典进行查询   
            for image_url in item['image_urls']:
                us = image_url.split('/')[3:]
                image_file_name = '_'.join(us)
                file_path = '%s/%s' % (dir_path, image_file_name)
                images.append(file_path)
 
            #如果这个文件存在则跳过
                if os.path.exists(file_path):
                    continue
            #进行图片文件写入,wb模式打开文件,然后requests.get获取图片流,
                with open(file_path, 'wb') as handle:
                    response = requests.get(image_url, stream=True)
                    for block in response.iter_content(1024):
                        #获取的流如果有不存在的,则使用break结束,如果没有一次结束则进行写入
                        if not block:
                            break
 
                        handle.write(block)
 
            item['images'] = images
           
        return item

Spiders

Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是定义爬取的动作及分析某个网页(或者是有些网页)的地方。

对spider来说,爬取的循环类似下文:

  1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。 spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request
  2. 在回调函数内分析返回的(网页)内容,返回 Item 对象、dict、 Request 或者一个包括三者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。
  3. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。
  4. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

虽然该循环对任何类型的spider都(多少)适用,但Scrapy仍然为了不同的需求提供了多种默认spider。

分析代码:

导入选择器,itemloader等.重写类,从start_urls开始爬取

代码语言:javascript
复制
# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector
from scrapy.contrib.loader import ItemLoader, Identity
from meizitu.items import MeizituItem
 
 
class MeiziSpider(scrapy.Spider):
    name = "meizi"
    allowed_domains = ["meizitu.com"]
    start_urls = (
        'http://www.meizitu.com/',
    )
 
    def parse(self, response):
        #sel是页面源代码,载入scrapy.selector
        sel = Selector(response)
        #每个连接,用@href属性
        for link in sel.xpath('//h2/a/@href').extract():
            #请求=Request(连接,parese_item)
            request = scrapy.Request(link, callback=self.parse_item)
            yield request#返回请求
        #获取页码集合
        pages = sel.xpath('//*[@id="wp_page_numbers"]/ul/li/a/@href').extract()
        print('pages: %s' % pages)#打印页码
        if len(pages) > 2:#如果页码集合>2
            page_link = pages[-2]#图片连接=读取页码集合的倒数第二个页码
            page_link = page_link.replace('/a/', '')#图片连接=page_link(a替换成空)
            request = scrapy.Request('http://www.meizitu.com/a/%s' % page_link, callback=self.parse)
            yield request#返回请求
 
    def parse_item(self, response):
        #l=用ItemLoader载入MeizituItem()
        l = ItemLoader(item=MeizituItem(), response=response)
        #名字
        l.add_xpath('name', '//h2/a/text()')
        #标签
        l.add_xpath('tags', "//div[@id='maincontent']/div[@class='postmeta  clearfix']/div[@class='metaRight']/p")
        #图片连接
        l.add_xpath('image_urls', "//div[@id='picture']/p/img/@src", Identity())
        #url
        l.add_value('url', response.url)
 
        return l.load_item()

阿萨德 阿斯顿

原创文章,转载请注明: 转载自URl-team

本文链接地址: scrapy笔记六 scrapy运行架构的实例配合解析

Related posts:

  1. Scrapy-笔记一 入门项目 爬虫抓取w3c网站
  2. Scrapy笔记四 自动爬取网页之使用CrawlSpider
  3. Scrapy笔记五 爬取妹子图网的图片 详细解析
  4. Scrapy笔记零 环境搭建与五大组件架构
  5. 基于百度IP定位的网站访问来源分析的python实战项目–实践笔记二–调百度地图将经纬信息可视化呈现
  6. scrapy学习笔记十一 scrapy实战效率测评
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-07-082,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录:
  • 基本概念
    • Scrapy运行流程
    • 具体解析:
      • item.py : 定义提取的数据结构:
        • 关于field
        • 关于items.的实例化
      • pipeline.py : (管道.用于保存数据)
        • 这部分的特性是:
        •  典型的工作流程如下:
        • 附录:
        • pipeline代码如下:
      • Spiders
        • 分析代码:
          • Related posts:
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档