当前位置:   article > 正文

用scrapy写爬虫(七)存储数据_def open_spider(self,spider)

def open_spider(self,spider)

基于管道的持久化存储

  (1)编写爬虫文件进行数据解析

  (2)在items.py中定义相关字段(用于存储解析的数据)

  (3)在爬虫文件中将解析到的数据封装在实例化的item对象中

  (4)通过yield将item对象提交到pipelines.py中的管道

  (5)在管道中进行任意方式的数据持久化(数据库持久化需要重写两个方法open_spider和close_spider)

  (6)在settings.py配置文件中开启管道(ITEM_PIPELINES ,同时处理ROBOTSTXT_OBEY协议、USER_AGENT 伪装和LOG_LEVEL='ERROR'日志输出等级)

  (7)启动爬虫:scrapy crawl  爬虫文件

管道pipilines.py处理类定义

(1)要想使用管道进行数据持久化,必须在settings.py中进行开启配置
(2)可以定义多个管道类进行处理,但是在每个process_item函数中必须return item 传递给其它管道使用
(3)process_item参数item只接受爬虫文件提交来的item对象,参数spider是爬虫文件中类的实例化对象,可以进行数据传递;
(4)如果要对数九持久化写入到数据库,需要在管道类中重写open_spider和close_spider方法,这两个方法只会被执行一次;
(5)对于图片类(视频、音频等二进制)数据的下载有可以定义新的管道继承相关类既可以直接实现图片的下载

  1. # (1)自定义的文件持久化管道
  2. class TofilePipeline(object):
  3. # 构造方法初始化一个属性文件句柄,也可以定义一个类变量:fp=None
  4. def __init__(self):
  5. self.fp = None
  6. # 打开文件句柄
  7. def open_spider(self, spider):
  8. print('开始写入数据...')
  9. self.fp = open('a.text', 'w', encoding='utf-8')
  10. # 关闭文件进行系统资源回收
  11. def close_spider(self, spider):
  12. self.fp.close()
  13. print('数据下载成功,爬虫结束!')
  14. def process_item(self, item, spider):
  15. self.fp.write(f'{item["title"]}:{item["url"]}\n')
  16. return item
  17. 1)自定义的文件持久化管道


 

scrapy 数据的储存主要靠 pipelines 模块

  1. # -*- coding: utf-8 -*-
  2. # Define your item pipelines here
  3. #
  4. # Don't forget to add your pipeline to the ITEM_PIPELINES setting
  5. # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
  6. import codecs
  7. # 本模块定义标准Python 编码解码器(编码器和解码器)的基类
  8. import json
  9. from scrapy.pipelines.images import ImagesPipeline
  10. # scrapy 自带的图片处理的类
  11. from scrapy.exporters import JsonItemExporter
  12. # scrapy 导出json类 JsonItemExporter
  13. import pymysql
  14. import pymysql.cursors
  15. # 导入pymysql 数据包
  16. import pymongo
  17. # 导入 Pymongo
  18. from twisted.enterprise import adbapi
  19. """
  20. Twisted 是一个异步网络框架,不幸的是大部分数据库api实现只有阻塞式接口,
  21. twisted.enterprise.adbapi为此产生,它是DB-API 2.0 API的非阻塞接口,可以访问各种关系数据库
  22. """

Mysql同步存储

  1. class MysqlPipeline(object):
  2. #采用同步的机制写入mysql
  3. def __init__(self):
  4. self.conn = pymysql.connect('192.168.0.106', 'root', 'root', 'article', charset="utf8", use_unicode=True)
  5. # 链接MySQL 数据库
  6. self.cursor = self.conn.cursor()
  7. # 获取MySQL 数据库指针
  8. def process_item(self, item, spider):
  9. insert_sql = """
  10. insert into article(title, url, create_date, fav_nums)
  11. VALUES (%s, %s, %s, %s)
  12. """
  13. self.cursor.execute(insert_sql, (item["title"], item["url"], item["create_date"], item["fav_nums"]))
  14. # 执行 导入数据
  15. self.conn.commit()
  16. # 提交数据

MySQL非阻塞 异步存储

       1. 导入adbapi

  2. 生成数据库连接池

  3. 执行数据数据库插入操作

  4. 打印错误信息,并排错

  1. class MysqlTwistedPipline(object):
  2. """
  3. 异步存储数据
  4. 非阻塞型
  5. """
  6. def __init__(self, dbpool):
  7. self.dbpool = dbpool
  8. @classmethod
  9. def from_settings(cls, settings):
  10. dbparms = dict(
  11. host = settings["MYSQL_HOST"],
  12. db = settings["MYSQL_DBNAME"],
  13. user = settings["MYSQL_USER"],
  14. passwd = settings["MYSQL_PASSWORD"],
  15. charset='utf8',
  16. cursorclass=pymysql.cursors.DictCursor,
  17. use_unicode=True,
  18. )
  19. dbpool = adbapi.ConnectionPool("MySQLdb", **dbparms)
  20. return cls(dbpool)
  21. def process_item(self, item, spider):
  22. #使用twisted将mysql插入变成异步执行
  23. query = self.dbpool.runInteraction(self.do_insert, item)
  24. query.addErrback(self.handle_error, item, spider) #处理异常
  25. def handle_error(self, failure, item, spider):
  26. # 处理异步插入的异常
  27. print (failure)
  28. def do_insert(self, cursor, item):
  29. #执行具体的插入
  30. #根据不同的item 构建不同的sql语句并插入到mysql中
  31. insert_sql, params = item.get_insert_sql()
  32. print (insert_sql, params)
  33. cursor.execute(insert_sql, params)

json 数据存储

  1. class JsonExporterPipleline(object):
  2. #调用scrapy提供的json export导出json文件
  3. def __init__(self):
  4. self.file = open('articleexport.json', 'wb')
  5. self.exporter = JsonItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
  6. # 打开文件
  7. self.exporter.start_exporting()
  8. # 导出文件
  9. def close_spider(self, spider):
  10. self.exporter.finish_exporting()
  11. self.file.close()
  12. # 文件关闭
  13. def process_item(self, item, spider):
  14. self.exporter.export_item(item)
  15. return item

mongo 数据存储

  1. class MongoPipeline(object):
  2. # <span class='wp_keywordlink_affiliate'><a href="https://www.168seo.cn/tag/mongodb" title="View all posts in mongodb" target="_blank">mongodb</a></span> 数据库存储
  3. collection_name = 'scrapy_items'
  4. # 数据库名称
  5. def __init__(self, mongo_uri, mongo_db):
  6. self.mongo_uri = mongo_uri
  7. self.mongo_db = mongo_db
  8. @classmethod
  9. def from_crawler(cls, crawler):
  10. # 从settings 获取 MONGO_URI,MONGO_DATABASE
  11. return cls(
  12. mongo_uri=crawler.settings.get('MONGO_URI'),
  13. mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
  14. )
  15. def open_spider(self, spider):
  16. # 数据库打开配置
  17. self.client = pymongo.MongoClient(self.mongo_uri)
  18. self.db = self.client[self.mongo_db]
  19. def close_spider(self, spider):
  20. # 数据库关闭
  21. self.client.close()
  22. def process_item(self, item, spider):
  23. # 数据库储存
  24. self.db[self.collection_name].insert_one(dict(item))
  25. return item
  26. # 切记 一定要返回item进行后续的pipelines 数据处理

自定义的基于redis数据库持久化管道

  1. import redis
  2. class RedisPipeline(object):
  3. conn = None
  4. # 建立数据库连接
  5. def open_spider(self, spider):
  6. print('建立数据库连接...')
  7. self.conn = redis.Redis(host='127.0.0.1', port=6379)
  8. def process_item(self, item, spider):
  9. self.conn.lpush('data', dict(item)) # 将item对象以字典形式存储在redis列表结构中
  10. return item
自定义图片等文件的下载管道
  1. #IMAGES_STORE='filepath'在settings设置文件中指定存储图片的下载路径
  2. import os
  3. import scrapy
  4. from scrapy.pipelines.images import ImagesPipeline
  5. class ImageDownloadPipeline(ImagesPipeline):
  6. #接收item且将item中存储的url进行请求发送
  7. def get_media_requests(self, item, info): # 下载图片
  8. url=item["url"]
  9. yield scrapy.Request(url, meta={'item': item})
  10. # 指定下载路径
  11. def file_path(self, request, response=None, info=None):
  12. item = request.meta['item']
  13. img_name = request.url.split('/')[-1]
  14. path='图片'#自动会创建文件夹,同时存放在settings.py中指定的IMAGES_STORE配置路径下
  15. filename = os.path.join(path, img_name)
  16. print(f'正在下载------{filename}...')
  17. return filename
  18. # 将item传递给下一个即将被执行的管道类
  19. def item_completed(self, result, item, info):
  20. return item

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/433049
推荐阅读
相关标签
  

闽ICP备14008679号