赞
踩
管道文件 pipelines.py 主要用来对抓取的数据进行处理:一般一个类即为一个管道,比如创建存入MySQL、MongoDB 的管道类。管道文件中 process_item() 方法即为处理所抓数据的具体方法。
process_item(self,item,spider):
处理爬虫抓取的具体数据,在 process_item() 函数中 必须要 return item,因为存在多管道时,会把此函数的返回值继续交由下一个管道继续处理;
init():爬虫项目启动时只执行一次,一般用于数据库连接;
close_spider():爬虫项目结束时只执行一次,一般用于收尾工作,如数据库的关闭。
settings.py文件
关于settings具体设置点击查看 Scrapy_settings配置文件设置
# 管道文件设置,保存为哪个,就打开对应的管道,可以同时保存
ITEM_PIPELINES = {
# 300是最后一个
"douban.pipelines.DoubanPipeline": 300,
# Mysql管道
"douban.pipelines.MysqlDoubanPipeline": 299,
# mongodb管道
"douban.pipelines.MongodbDoubanPipeline": 298,
}
pipelines.py文件
# Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html # useful for handling different item types with a single interface import csv import pymongo import pymysql from itemadapter import ItemAdapter # 保存csv class DoubanPipeline: def __init__(self): headers = ('title', 'score') self.f = open('douban.csv', 'w+', encoding='utf-8', newline='') self.f_csv = csv.DictWriter(self.f, headers) self.f_csv.writeheader() # 写入表头 def process_item(self, item, spider): self.f_csv.writerow(item) return item def close_spider(self, spider): self.f.close() print('douban.csv文件写入完成') # 保存Mysql class MysqlDoubanPipeline: def __init__(self): # 创建链接 self.db = pymysql.Connect( host="127.0.0.1", port=3306, user="root", password="密码", db="数据库" ) # 创建游标,用于传递python给MySQL的命令和MySQL返回的内容 self.cursor = self.db.cursor() # 不想手动创建数据库,也可以在init方法中实现 # sql_1 = """ # create table xiangxue009.douban_top250 # ( # `title` text null, # `score` text null # ); # """ # self.cursor.execute(sql_1) def process_item(self, item, spider): # SQL插入语句 sql = "insert into `douban_Top250`(`title`, `score`) values (%s,%s)" # 执行SQL语句 self.cursor.execute(sql,[item['title'], item['score']]) # 放值 # 提交到数据库执行 self.db.commit() return item def close_spider(self, spider): # 关闭游标 self.cursor.close() # 关闭连接 self.db.close() print('Mysql文件写入完成') # 保存Mongodb class MongodbDoubanPipeline: # 初始化方法 def __init__(self): # 连接mongo self.myclient = pymongo.MongoClient("mongodb://localhost:27017") # 连接mydb数据库,账号密码认证 # self.myclient = self.myclient.admin # 连接系统默认数据库admin # self.myclient.authenticate("用户名", "密码") """ 如果出错了,报错:pymongo.errors.OperationFailure: auth failed,可以增加mechanism参数,因为mongoDB有不同的认证机制 3.0版本以后采用的是'SCRAM-SHA-1', 之前的版本采用的是'MONGODB-CR' 即:self.myclient.authenticate("用户名", "密码",mechanism='MONGODB-CR') """ # 连接数据库,没有则自动创建 self.db = self.myclient.xiangxue009 def process_item(self, item, spider): # print(item) # 连接集合,没有集合则自动创建,连接后导入单条数据(类型为字典) self.db.douban_Top250.insert_one(dict(item)) return item # spider一定要加在参数里,不然会报错 def close_spider(self, spider): print('Mongo文件写入完成') print('爬虫结束!!') print('当前爬虫的名字',spider) # 当前爬虫的名字
关于spider参数
我们有时候爬的数据不需要存在一张表里,但是如果需要爬两次,或者全部保存在一个item里在提取就不方便
所以我们会设置多个items,多个items的时候pipelines.py文件怎么保存呢
大致分为三步:
items.py
# Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.html import scrapy # 第一个管道 class DoubanItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 创建标题字段 title = scrapy.Field() # 创建评分字段 score = scrapy.Field() # 第二个管道 class DoubanItem2(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 创建标题字段 abstract_name = scrapy.Field() # 创建导演字段 abstract = scrapy.Field()
douban_data.py
import scrapy # 导入两个管道 from ..items import DoubanItem,DoubanItem2 class DoubanDataSpider(scrapy.Spider): name = "douban_data" allowed_domains = ["www.douban.com"] # 把url换成我们需要爬取的 start_urls = ["https://www.douban.com/doulist/124084417/?start=0&sort=seq&playable=0&sub_type="] # 爬虫函数 添加**kwargs就不会报黄 def parse(self, response,**kwargs): # print(response) # print(type(response)) # 获取25个大盒子 data_divs = response.xpath('//*[@class="doulist-item"]') print(data_divs,len(data_divs)) # 创建第一个管道实例 items = DoubanItem() # 创建第二个管道实例 items2 = DoubanItem2() for data in data_divs: # 电影标题 title = ''.join(data.xpath('./div/div[2]/div[@class="title"]//text()').getall()).strip() # 电影评分 score = ''.join(data.xpath('./div/div[2]/div[@class="rating"]//text()').getall()).replace('\n','').strip().replace(' ','') # 电影导演 abstract = '-'.join(data.xpath('./div/div[2]/div[@class="abstract"]//text()').getall()).replace('\n','').strip().replace(' ','') print(title) print(score) print(abstract) # 第一个管道 items['title'] = title items['score'] = score # 第二个管道 items2['abstract_name'] = title items2['abstract'] = abstract print('items',items) print('items2',items2) # 返回数据 yield items # 可以yield 很多次 yield items2
pipelines.py文件,核心文件
# 导入管道 import csv # 导入管道,注意要带. 不然管道的类型就和item的数据类型不一样 from .items import DoubanItem,DoubanItem2 class DoubanPipeline: def __init__(self): # 第一个管道保存文件 headers = ('title', 'score') self.f = open('douban.csv', 'w+', encoding='utf-8', newline='') self.f_csv = csv.DictWriter(self.f, headers) self.f_csv.writeheader() # 写入表头 # 第二个管道保存文件 headers = ('abstract_name', 'abstract') self.f2 = open('douban2.csv', 'w+', encoding='utf-8', newline='') self.f_csv2 = csv.DictWriter(self.f2, headers) self.f_csv2.writeheader() # 写入表头 def process_item(self, item, spider): #### 核心代码 # 判断是不是第一个管道 if isinstance(item,DoubanItem): self.f_csv.writerow(item) # 是的话保存过后直接返回,告诉引擎保存好了,可以下一个了,就不用在执行elif了 return item # 判断是不是第二个管道 elif isinstance(item,DoubanItem2): self.f_csv2.writerow(item) # 是的话保存过后直接返回,告诉引擎保存好了,可以下一个了 return item def close_spider(self, spider): # 关闭文件 self.f.close() print('douban.csv文件写入完成') self.f2.close() print('douban2.csv文件写入完成')
pipelines.py文件,核心文件解读
def process_item(self, item, spider):
# 看他们的类型
print(item,type(item))
print(DoubanItem)
print('isinstance(item,DoubanItem)',isinstance(item,DoubanItem))
print(DoubanItem2)
print('isinstance(item,DoubanItem2)',isinstance(item,DoubanItem2))
可以看到 <class ‘douban.items.DoubanItem’>和<class ‘douban.items.DoubanItem2’>两个类型
所有我们只需要判断item的类型就行,将相应的管道存入相应的数据就行
比如第一个管道的数据存csv,第二个管道存Mysql,这样就只需要在item加一个判断即可
操作性可大了
后面还会更新图片管道和视频管道教程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。