- 需求:将爬取到的数据一份存储到本地一份存储到数据库(对应project:qiubaipro)
- 思路:开启两个管道,pipelines.py中,一个管道负责将数据存储到一个平台(载体),多个管道就可存储到多个平台。
PS:
1.有多个管道的情况下,爬虫文件将封装好的item提交给管道时,会提交给优先级最高的管道;
该管道处理完成后,return item,下一个管道才会收到item。因此每个管道必须要return item!!!!
2. 结束时,先执行优先级较低管道的close_spider
爬虫文件中的代码:
import scrapy
from qiubaipro.items import QiubaiproItem
class QiubaiSpider(scrapy.Spider):
name = 'qiubai'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
#step1:解析作者名称以及发布的内容
info_nodes = response.xpath('// *[ @ id = "content"] / div / div[2]/div')
print('有几个节点:',len(info_nodes))
for node in info_nodes:
author = node.xpath('./div/a[2]/h2/text()')[0].extract()
content = node.xpath('.//div[@class="content"]/span//text()').extract()
content = ''.join(content)
#step3:实例化一个item对象
item = QiubaiproItem()
item['author'] = author
item['content'] = content
#step4:将该item对象提交给管道
yield item
items.py文件中的代码:
import scrapy
class QiubaiproItem(scrapy.Item):
# step2:在item中定义相关的属性
author = scrapy.Field()
content = scrapy.Field()
pipelines.py中的代码:
import pymysql
class QiubaiproPipeline:
fp = None
#重写父类的open_spider方法,该方法只在开始爬虫的时候被调用一次。名字只能是open_spider!!!
def open_spider(self,spider):
print('开始爬虫...')
self.fp = open('./qiubai.txt','w',encoding='utf-8')
# step5:process_item函数对item中封装的数据进行持久化存储操作
#专门用于处理item类型的对象
#该方法可以接收爬虫文件提交过来的item对象
#该方法每接收到一个item就会被调用一次
def process_item(self, item, spider):
print('存入本地啦!!!!!!!!!!!!!')
author = item['author']
content = item['content']
self.fp.write('\n'+author.strip()+':'+content.strip()+'\n')
return item
#重写父类的close_spider方法,该方法只在结束时关闭文件。名字只能是close_spider!!!!
def close_spider(self,spider):
print('结束爬虫!')
self.fp.close()
class MysqlPipeline(object):
# PS:要先在MySQL中建好库和表
conn = None
cursor = None
def open_spider(self,spider):
print('连接数据库')
self.conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',password='9755',db='qiubai',charset='utf8')
def process_item(self,item,spider):
print('存入数据库')
self.cursor = self.conn.cursor()
try:
self.cursor.execute('insert into qiubai values("%s","%s")'%(item["author"],item["content"]))
self.conn.commit()
except Exception as e:
print('数据存入数据库时发生错误!!!!!!!!!!!!')
print(e)
self.conn.rollback()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn.close()
print('数据存入数据库')
class LocalPipeline: #这个管道也是将数据存放在本地
fp = None
def open_spider(self,spider):
print('开始爬虫...')
self.fp = open('./qiubai2.txt','w',encoding='utf-8')
def process_item(self, item, spider):
print('local2')
author = item['author']
content = item['content']
self.fp.write('\n'+author.strip()+':'+content.strip()+'\n')
return item
def close_spider(self,spider):
print('local2结束!')
self.fp.close()
in a nutshell:
每个管道负责一个存储平台,
每个管道中open_spider和close_spider只调用一次
有多少条记录,就有多少个item,process_item函数就会被调用多少次
settings.py文件中添加:
#step6:在配置文件中开启管道
ITEM_PIPELINES = {
'qiubaipro.pipelines.QiubaiproPipeline': 300,
#300表示优先级,数值越小,优先级越高
'qiubaipro.pipelines.MysqlPipeline': 301,
'qiubaipro.pipelines.LocalPipeline': 302,
}
数据库中存储的数据: