zoukankan      html  css  js  c++  java
  • 11,scrapy框架持久化存储

    今日总结

    • 基于终端指令的持久化存储
    • 基于管道的持久化存储

    今日详情

    1.基于终端指令的持久化存储

    • 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作。
    执行输出指定格式进行存储:将爬取到的数据写入不同格式的文件中进行存储
        scrapy crawl 爬虫名称 -o xxx.json
        scrapy crawl 爬虫名称 -o xxx.xml
        scrapy crawl 爬虫名称 -o xxx.csv

    2.基于管道的持久化存储

    scrapy框架中已经为我们专门集成好了高效、便捷的持久化操作功能,我们直接使用即可。要想使用scrapy的持久化操作功能,我们首先来认识如下两个文件:

        items.py:数据结构模板文件。定义数据属性。
        pipelines.py:管道文件。接收数据(items),进行持久化操作。
    
    持久化流程:
        1.爬虫文件爬取到数据后,需要将数据封装到items对象中。
        2.使用yield关键字将items对象提交给pipelines管道进行持久化操作。
        3.在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储
        4.settings.py配置文件中开启管道

    小试牛刀:将boss招聘网站中的招聘爬虫的数据爬取下来,然后进行持久化存储

    - 爬虫文件:boss.py

    # -*- coding: utf-8 -*-
    import scrapy
    
    from bossPro.items import BossproItem
    
    class BossSpider(scrapy.Spider):
        name = 'boss'
        # allowed_domains = ['www.xxx.com']
        start_urls = [
            'https://www.zhipin.com/job_detail/?query=python%E7%88%AC%E8%99%AB&scity=101010100&industry=&position=']
    
        url = 'https://www.zhipin.com/c101010100/?query=python爬虫&page=%d&ka=page-2'
        page = 1
        #  解析+管道持久化存储
        def parse(self, response):
            li_list = response.xpath('//div[@class="job-list"]/ul/li')
            for li in li_list:
                job_name = li.xpath('.//div[@class="info-primary"]/h3/a/div/text()').extract_first()
                salary = li.xpath('.//div[@class="info-primary"]/h3/a/span/text()').extract_first()
                company = li.xpath('.//div[@class="company-text"]/h3/a/text()').extract_first()
    
                # print(company)
                item = BossproItem()
                item['job_name'] = job_name
                item['salary'] = salary
                item['company'] = company
                yield item
    
            if self.page <= 3:
                print(f'执行第{self.page+1}页')
                self.page += 1
                new_url = format(self.url % self.page)
    
                yield scrapy.Request(url=new_url, callback=self.parse)
    

    - items文件:items.py

    import scrapy
    
    class BossproItem(scrapy.Item):
        # define the fields for your item here like:
        job_name = scrapy.Field()
        salary = scrapy.Field()
        company = scrapy.Field()
    

    - 管道文件:pipelines.py

    import os
    import pymysql
    from redis import Redis
    
    # 文件存储
    class BossproPipeline(object):
    
        fp = None
        def open_spider(self, spider):
            print('开始爬虫.............................')
            if not os.path.exists('./boss'):
                os.mkdir('./boss')
            self.fp = open('./boss/boss.txt', 'w', encoding='utf8')
    
        def close_spider(self, spider):
            print('结束爬虫.............................')
            self.fp.close()
    
        def process_item(self, item, spider):
            self.fp.write(item['job_name']+':'+item['salary']+':'+item['company']+'
    ')
            return item
    
    # mysql数据库存储
    class mysqlPipeline(object):
        conn = None
        cursor =None
        def open_spider(self,spider):
            self.conn = pymysql.Connect(host='127.0.0.1', port=3306, user='root', password='', db='boss', charset="utf8")
            print(self.conn)
        def process_item(self, item, spider):
            self.cursor = self.conn.cursor()
            try:
                print('insert into boss values ("%s","%s","%s")'%(item['job_name'],item['salary'],item['company']))
                self.cursor.execute('insert into boss(job_name,salary,company) values ("%s","%s","%s")'%(item['job_name'],item['salary'],item['company']))
                self.conn.commit()
            except Exception as e:
                self.conn.rollback()
        def close_spider(self,spider):
            self.conn.close()
            self.cursor.close()
    
    # redis存储
    class redisPipeLine(object):
        conn = None
    
        def open_spider(self,spider):
            self.conn = Redis(host='127.0.0.1', port=6379, db=2, charset='utf-8')
            print(self.conn)
    
        def process_item(self, item, spider):
            # print(item['salary'],)
            dic = {
                'name': item['job_name'],
                'salary': item['salary'],
                'company': item['company']
            }
    
            self.conn.lpush('boss', dic)
    

    - 配置文件:settings.py

    #开启管道
    ITEM_PIPELINES = {
       'bossPro.pipelines.BossproPipeline': 300,
       'bossPro.pipelines.mysqlPipeline': 301,
       'bossPro.pipelines.redisPipeLine': 302,
    }
    

     

    - 面试题:如果最终需要将爬取到的数据值一份存储到磁盘文件,一份存储到数据库中,则应该如何操作scrapy?  

    - 答:管道文件中的代码为

    #该类为管道类,该类中的process_item方法是用来实现持久化存储操作的。
    class DoublekillPipeline(object):
    
        def process_item(self, item, spider):
            #持久化操作代码 (方式1:写入磁盘文件)
            return item
    
    #如果想实现另一种形式的持久化操作,则可以再定制一个管道类:
    class DoublekillPipeline_db(object):
    
        def process_item(self, item, spider):
            #持久化操作代码 (方式1:写入数据库)
            return item
    
     在settings.py开启管道操作代码为:
    
    #下列结构为字典,字典中的键值表示的是即将被启用执行的管道文件和其执行的优先级。
    ITEM_PIPELINES = {
       'doublekill.pipelines.DoublekillPipeline': 300,
        'doublekill.pipelines.DoublekillPipeline_db': 200,
    }
    
    #上述代码中,字典中的两组键值分别表示会执行管道文件中对应的两个管道类中的process_item方法,实现两种不同形式的持久化操作。
    

      

     
     
     
  • 相关阅读:
    python中的函数编程
    Python中的类型关系和继承关系
    MySQLdb for Python使用指南
    调试模式
    js window.open打开新页面
    JVM调优
    jacoco(spring boot启动) agent tcpserver使用方案
    C#多线程之ManualResetEvent和AutoResetEvent
    下载verycd的方法下载电驴资源隐藏资源的最新可用方法
    C# 多线程之信号量Semaphore
  • 原文地址:https://www.cnblogs.com/feifeifeisir/p/10458554.html
Copyright © 2011-2022 走看看