zoukankan      html  css  js  c++  java
  • 二、Item Pipeline和Spider-----基于scrapy取校花网的信息

    Item Pipeline

    当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item。

    每个Item Pipeline都是实现了简单方法的Python类,比如决定此Item是丢弃而存储。以下是item pipeline的一些典型应用:

    • 验证爬取的数据(检查item包含某些字段,比如说name字段)
    • 查重(并丢弃)
    • 将爬取结果保存到文件或者数据库中

    编写item pipeline

    编写item pipeline很简单,item pipiline组件是一个独立的Python类,其中process_item()方法必须实现

     1  2 
     3 class SomethingPipeline(object):
     4     def __init__(self):    
     5         # 可选实现,做参数初始化等
     6         # doing something
     7 
     8     def process_item(self, item, spider):
     9         # item (Item 对象) – 被爬取的item
    10         # spider (Spider 对象) – 爬取该item的spider
    11         # 这个方法必须实现,每个item pipeline组件都需要调用该方法,
    12         # 这个方法必须返回一个 Item 对象,被丢弃的item将不会被之后的pipeline组件所处理。
    13         return item
    14 
    15     def open_spider(self, spider):
    16         # spider (Spider 对象) – 被开启的spider
    17         # 可选实现,当spider被开启时,这个方法被调用。
    18 
    19     def close_spider(self, spider):
    20         # spider (Spider 对象) – 被关闭的spider
    21         # 可选实现,当spider被关闭时,这个方法被调用

     启用一个Item Pipeline组件

    为了启用Item Pipeline组件,必须将它的类添加到 settings.py文件ITEM_PIPELINES 配置,就像下面这个例子:

    1 # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
    2 ITEM_PIPELINES = {
    3     #'mySpider.pipelines.SomePipeline': 300,
    4     "mySpider.pipelines.ItcastJsonPipeline":300
    5 }

     分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)。

    Spider

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

    class scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。

    __init__() : 初始化爬虫名字和start_urls列表

    start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response

    parse() : 解析response,并返回Item或Requests(需指定回调函数)。Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。

     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 
     4 
     5 class BaiduSpider(scrapy.Spider):
     6     name = 'baidu'
     7     allowed_domains = ['baidu.com']
     8     start_urls = ['http://baidu.com/']
     9 
    10     def parse(self, response):
    11         pass
     源码:

    1
    class Spider(object_ref): 2 """Base class for scrapy spiders. All spiders must inherit from this 3 class. 4 """ 5 # 定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 6 # name是spider最重要的属性,而且是必须的。 7 # 一般做法是以该网站(domain)(加或不加 后缀 )来命名spider。 8 9 name = None 10 custom_settings = None 11 12 # 初始化,提取爬虫名字,start_ruls 13 def __init__(self, name=None, **kwargs): 14 if name is not None: 15 self.name = name 16 # 如果爬虫没有名字,中断后续操作则报错 17 elif not getattr(self, 'name', None): 18 raise ValueError("%s must have a name" % type(self).__name__) 19 20 # python 对象或类型通过内置成员__dict__来存储成员信息 21 self.__dict__.update(kwargs) 22 23 # URL列表。当没有指定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。 24 if not hasattr(self, 'start_urls'): 25 self.start_urls = [] 26 27 @property 28 def logger(self): 29 logger = logging.getLogger(self.name) 30 return logging.LoggerAdapter(logger, {'spider': self}) 31 32 #打印Scrapy执行后的log信息 33 def log(self, message, level=logging.DEBUG, **kw): 34 """Log the given message at the given log level 35 36 This helper wraps a log call to the logger within the spider, but you 37 can use it directly (e.g. Spider.logger.info('msg')) or use any other 38 Python logger too. 39 """ 40 self.logger.log(level, message, **kw) 41 42 @classmethod 43 def from_crawler(cls, crawler, *args, **kwargs): 44 spider = cls(*args, **kwargs) 45 spider._set_crawler(crawler) 46 return spider 47 48 # 判断对象object的属性是否存在,不存在做断言处理 49 def set_crawler(self, crawler): 50 warnings.warn("set_crawler is deprecated, instantiate and bound the " 51 "spider to this crawler with from_crawler method " 52 "instead.", 53 category=ScrapyDeprecationWarning, stacklevel=2) 54 assert not hasattr(self, 'crawler'), "Spider already bounded to a " 55 "crawler" 56 self._set_crawler(crawler) 57 58 def _set_crawler(self, crawler): 59 self.crawler = crawler 60 self.settings = crawler.settings 61 crawler.signals.connect(self.close, signals.spider_closed) 62 63 # 该方法将读取start_urls内的地址,并为每一个地址生成一个Request对象,交给Scrapy下载并返回Response 64 def start_requests(self): 65 cls = self.__class__ 66 if method_is_overridden(cls, Spider, 'make_requests_from_url'): 67 warnings.warn( 68 "Spider.make_requests_from_url method is deprecated; it " 69 "won't be called in future Scrapy releases. Please " 70 "override Spider.start_requests method instead (see %s.%s)." % ( 71 cls.__module__, cls.__name__ 72 ), 73 ) 74 for url in self.start_urls: 75 yield self.make_requests_from_url(url) 76 else: 77 for url in self.start_urls: 78 yield Request(url, dont_filter=True) 79 80 # start_requests()中调用,实际生成Request的函数。 81 # Request对象默认的回调函数为parse(),提交的方式为get 82 def make_requests_from_url(self, url): 83 """ This method is deprecated. """ 84 return Request(url, dont_filter=True) 85 86 # 默认的Request对象回调函数,处理返回的response。 87 # 生成Item或者Request对象。用户必须实现这个类 88 def parse(self, response): 89 raise NotImplementedError('{}.parse callback is not defined'.format(self.__class__.__name__)) 90 91 92 @classmethod 93 def update_settings(cls, settings): 94 settings.setdict(cls.custom_settings or {}, priority='spider') 95 96 @classmethod 97 def handles_request(cls, request): 98 return url_is_from_spider(request.url, cls) 99 100 @staticmethod 101 def close(spider, reason): 102 closed = getattr(spider, 'closed', None) 103 if callable(closed): 104 return closed(reason) 105 106 def __str__(self): 107 return "<%s %r at 0x%0x>" % (type(self).__name__, self.name, id(self)) 108 109 __repr__ = __str__

    每天 一个小实例:(我取得是图片和图片名)

     1 items.py
     2 
     3 
     4 # -*- coding: utf-8 -*-
     5 
     6 # Define here the models for your scraped items
     7 #
     8 # See documentation in:
     9 # https://doc.scrapy.org/en/latest/topics/items.html
    10 
    11 import scrapy
    12 
    13 '''Item 定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误。
    14 
    15 可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item(可以理解成类似于ORM的映射关系)。'''
    16 class MyspiderItem(scrapy.Item):
    17     # define the fields for your item here like:
    18     img_name = scrapy.Field()
    19     img_url = scrapy.Field()
     1 xiaohua.py
     2 
     3 
     4 # -*- coding: utf-8 -*-
     5 import scrapy
     6 from myspider.items import MyspiderItem
     7 
     8 class BaisiSpider(scrapy.Spider):
     9     name = 'xiaohua'
    10     allowed_domains = ['www.521609.com']
    11     start_urls = ['http://www.521609.com/daxuexiaohua/list31.html']
    12     #   page = 31
    13     def parse(self, response):
    14 
    15         # 将我们得到的数据封装到一个 `MyspiderItem` 对象
    16         item = MyspiderItem()
    17 
    18         #提取数据
    19         img_list = response.xpath('//div[@class="index_img list_center"]/ul/li')
    20         for img in img_list:
    21             img_name = img.xpath('./a/img/@alt')[0].extract()
    22             img_url = img.xpath('./a/img/@src')[0].extract()
    23             item['img_name'] = img_name
    24             item['img_url'] = img_url
    25 
    26             # 将获取的数据交给pipelines
    27             yield item
    28 
    29         # if self.page < 35:
    30         #     self.page += 1
    31         #     curpage_url = 'http://www.521609.com/daxuexiaohua/list' + str(self.page) + '.html'
    32         #
    33         #  # 发送新的url请求加入待爬队列,并调用回调函数 self.parse
    34         #     yield scrapy.Request(curpage_url, callback=self.parse)
     1 pipelines.py
     2 
     3 
     4 # -*- coding: utf-8 -*-
     5 
     6 # Define your item pipelines here
     7 #
     8 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
     9 # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    10 import urllib.request
    11 import os
    12 class BaiSispiderPipeline():
    13 
    14     def process_item(self, item, spider):
    15         base_url = 'http://www.521609.com'
    16         file_name = item['img_name'] + '.png'
    17         file_path = os.path.join("F:\myspider\myspider\imgs", file_name)
    18         if item['img_url']:
    19              urllib.request.urlretrieve(base_url + item['img_url'],file_path)
    20         # with open(file_path, 'wb') as file:
    21         #     # 2. 获取图片里的内容
    22         #     images = requests.get(base_url + item['img_url'])
    23         #
    24         #     # 3. 调用文件对象write() 方法,将page_html的内容写入到文件里
    25         #     file.write(images.content)
    26         return item

     结果:

     

  • 相关阅读:
    15.Git版本控制系统
    14.sudo 获取root权限
    13.定时任务
    12.文件权限:RWX
    相信301跳转大家都知道 rewrite
    修改mysql密码
    mod_rewrite是Apache的一个非常强大的功能
    mysql 常用命令集锦[绝对精华]
    mysql安装完之后,登陆后发现只有两个数据库
    mysql命令
  • 原文地址:https://www.cnblogs.com/jiangzijiang/p/8478325.html
Copyright © 2011-2022 走看看