• Scrapy持久化存储


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

      保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作;

    执行输出指定格式进行存储:将爬取到的数据写入不同格式的文件中进行存储

        scrapy crawl 爬虫名称 -o xxx.json
        scrapy crawl 爬虫名称 -o xxx.xml
        scrapy crawl 爬虫名称 -o xxx.csv

    基于管道的持久化存储

      scrapy框架中已经为我们专门集成好了高效、便捷的持久化操作功能,我们直接使用即可:

           items.py : 数据结构模板文件,定义数据属性;

        pipelines.py : 管道文件,接受item类型的数据,进行持久化操作;

    持久化流程:

    1. 在爬虫文件中获取到数据后,将数据封装到 items对象中;
    2. 通过 yield 关键字将items对象提交给pipelines管道进行持久化操作;
    3. 在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象存储的数据进行持久化存储;

    settings.py文件中开启管道:

    ITEM_PIPELINES = {
        'qiubaiPro.pipelines.QiubaiproPipelineByRedis': 300,
    }

    终端持久化存储示例:

      将糗事百科首页中的段子和作者数据爬取下来,然后进行持久化存储

    爬虫程序

    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class QiubaiSpider(scrapy.Spider):
        name = 'qiubai'
        # allowed_domains = ['www.qiushibaike.com']
        start_urls = ['https://www.qiushibaike.com/text/']
    
        def parse(self, response):
            div_list = response.xpath('//div[@id="content-left"]/div')
            all_data = []
            # xpath返回的列表元素类型为Selector类型
            for div in div_list:
                # title = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()')[0].extract()
                author = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()').extract_first()
                content = div.xpath('./a[1]/div/span/text()').extract_first()
    
                dic = {
                    'author': author,
                    'content': content
                }
    
                all_data.append(dic)
            # 基于终端指令的持久化存储:可以通过终端指令的形式将parse方法的返回值中存储的数据进行本地磁盘的持久化存储
            return all_data

    settings

    BOT_NAME = 'qiubaiPro'
    USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
    SPIDER_MODULES = ['qiubaiPro.spiders']
    NEWSPIDER_MODULE = 'qiubaiPro.spiders'
    ROBOTSTXT_OBEY = False

    执行:

    scrapy crawl qiubai -o qiubai.csv

    执行完之后的结果:

    管道持久化存储示例:

    爬取Boss直聘网中Python爬虫岗位的职位名称,薪资,公司名称

    爬虫程序

    # -*- 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爬虫&scity=101010100&industry=&position=']
    
        def parse(self, response):
            li_list = response.xpath('//div[@class="job-list"]/ul/li')
            for li in li_list:
                title = li.xpath('.//div[@class="info-primary"]/h3[@class="name"]/a/div/text()').extract_first()
                salary = li.xpath('.//div[@class="info-primary"]/h3[@class="name"]/a/span/text()').extract_first()
                company = li.xpath('.//div[@class="company-text"]/h3/a/text()').extract_first()
    
                # 实例化一个item类型的对象
                item = BossproItem()
                # 将解析到的数据存储到item对象中
                item["title"] = title
                item["salary"] = salary
                item["company"] = company
    
                # 将item对象提交给管道进行持久化存储
                yield item

    items

    # -*- 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 BossproItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title = scrapy.Field()
        salary = scrapy.Field()
        company = scrapy.Field()

    pipelines

    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    # 管道文件:需要接收爬虫文件提交过来的数据,并对数据进行持久化存储.(IO操作)
    class BossproPipeline(object):
        fp = None
        # 只会被执行一次(开始爬虫的时候执行一次)
        def open_spider(self,spider):
            print("开始爬虫")
            self.fp = open('./job.txt','w',encoding='utf-8')
        # 爬虫文件每提交一次,该方法就会被调用一次
        def process_item(self, item, spider): #300表示为优先级,值越小优先级越高
            self.fp.write(item['title'] + "	" + item['salary'] + '	' + item['company'] + '
    ')
            return item
        # 结束爬虫时执行
        def close_spider(self,spider):
            self.fp.close()
            print("爬虫结束")
    
    # 注意:默认情况下,管道机制并没有开启,需要手动在配置文件中进行开启
    
    # 使用管道进行持久化的流程:
    #   1.获取解析到的数据
    #   2.将解析的数据存储到item对象(item类中进行相关属性的声明)
    #   3.通过yield关键字将item提交到管道
    #   4.管道文件中进行持久化存储代码的编写(process_item)
    #   5.在配置文件中开启管道

    settings

    #开启管道
    ITEM_PIPELINES = {
        'secondblood.pipelines.SecondbloodPipeline': 300, #300表示为优先级,值越小优先级越高
    }

    执行:

    scrapy crawl boss --nolog

    基于MySQL的持久化存储

    pipelines

    import pymysql
    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='spider')
            print(self.conn)
        def process_item(self, item, spider):
            self.cursor = self.conn.cursor()
            sql = 'insert into boss values("%s","%s","%s")'%(item['title'],item['salary'],item['company'])
            try:
                self.cursor.execute(sql)
                self.conn.commit()
            except Exception as e:
                print (e)
                self.conn.rollback()
    
        def close_spider(self,spider):
            self.cursor.close()
            self.conn.close()

    settings

    # 开启管道,自定义管道向不用的数据库存储数据
    # 300是优先级,数字越小,优先级越高
     
    ITEM_PIPELINES = {
       'boss.pipelines.BossPipeline': 300,
       'boss.pipelines.mysqlPipeLine': 301,
    }

    执行爬虫程序,并去数据库中查看数据

    基于redis管道存储

     pipelines

    from redis import Redis
    class RedisPipeline(object):
        conn = None
        def process_item(self,item,spider):
            dic = {
                "title":item["title"],
                "salary":item["salary"],
                "company":item["company"]
            }
            self.conn.lpush("jobInfo",json.dumps(dic))
        def open_spider(self,spider):
            self.conn = Redis(host='127.0.0.1',port=6379)
            print (self.conn)

    settings

    ITEM_PIPELINES = {
       #'bossPro.pipelines.BossproPipeline': 300,
       #'bossPro.pipelines.mysqlPipeline': 301,
       'bossPro.pipelines.RedisPipeline': 302,
    }

    执行代码并且查看redis中的数据

    redis已经存在数据了,因为编码问题所以不显示中文.

  • 相关阅读:
    windows中80端口被System占用,PID=4的问题
    SpringBoot中动态加载(热部署)
    eclipse中Cannot change version of project facet Dynamic Web Module to 3.0的问题解决
    Eclipse启动tomcat后404错误
    Eclipse在当前行之上插入一行
    Java中==规则
    简明log4j配置教程
    CentOS7 配置静态IP
    CentOS7 mini安装后没有ifconfig命令的解决办法
    shell编程学习笔记之sed编辑器
  • 原文地址:https://www.cnblogs.com/zycorn/p/10273797.html
Copyright © 2020-2023  润新知