
1.详细介绍Item + pipelineitem和pipeline的作用以及介绍
1. item是用来定义存储抓取数据的字段,定义爬取的数据结构
定义每个实体类的Item类要继承自scrapy.items
实体类的字段要用scrapy.field(不需要区分数据类型)
数据类型取决于赋值的时候原始的数据类型,它使用的方法和字典类似
2.pipeline 当item在spider爬虫中被收集之后,会传递到Item Pipeline ,
pipeline主要是讲return过去的数据传递到数据库,文件持久化模块。
3.spider中的requests中meta参数的含义是:把需要传递的信息赋值给meta作为中间存储。
但是吧,meta存储的数据为键值对所以转化为key ---- value ,如果想在函数中去到value就要找到meta[key]即可
博客文章详细讲解item和pipeline
1.在item中定义获取的爬取数据字段,存放相对应的网站信息 JobboleArticleItem 类
2.通过Request函数的meta参数获取到image_url 数据类型是字典格式。
yield Request(url= parse.urljoin(response.url,post_url),meta={"front_img":image_url},callback= self.parse_detail)
meta的值成功随response传入到了parse_detail函数中并且可以根据详情来获得每个字段数据。(front_img)
3.#初始化一个item对象
article_item=JobboleArticleItem()
#根据response中的meta键值对来获取封面图片
front_img=response.meta.get('front_img','')
#数据存储到item中
article_item['title']=title
article_item['create_time']=create_time
article_item['article_type']=article_type
article_item['praise_number']=praise_number
article_item['collection_number']=collection_number
article_item['comment_number']=comment_number
article_item['front_img']=front_img
#将item中的数据存储清洗到pipeline中
yield article_item
4.激活item_pipeline 激活pipeline
ITEM_PIPELINE={
key(爬虫项目名称)* value (优先级)
}

在Pipeline 中进行数据存储操作(MySql) 创建表格
CREATE TABLE `bole_db`.`article` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(100) NULL,
`create_time` VARCHAR(45) NULL,
`article_type` VARCHAR(50) NULL,
`praise_number` INT NULL,
`collection_number` INT NULL,
`comment_number` INT NULL,
`url` VARCHAR(100) NULL,
`front_img` VARCHAR(150) NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COMMENT = '伯乐在线文章信息';
存储数据
在Pipelien中创建一个数据库操作类,并配置到setting中。
pipeline.py中:
class MysqlPipeline(object):
def __init__(self):
# 数据库连接
self.conn = pymysql.connect(host="localhost", port=3306, user="root", password="root", charset="utf8",
database="bole_db")
self.cur = self.conn.cursor()
# 插入数据
def sql_insert(self,sql):
self.cur.execute(sql)
self.conn.commit()
def process_item(self, item, spider):
# 存入mysql数据库
sql_word = "insert into article (title,create_time,article_type,praise_number,collection_number,comment_number,url,front_img) values ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}')".format(item["title"],item["create_time"],item["article_type"],item["praise_number"],item["collection_number"],item["comment_number"],item["url"],item["front_img"])
self.sql_insert(sql_word)
return item
setting.py中
ITEM_PIPELINES={'spider_bole_blog.pipelines.SpiderBoleBlogPipeline':300,'spider_bole_blog.pipelines.MysqlPipeline':100}:
1.分布式的话,那就有足够强壮的爬虫调度,快速的横向部署扩展加入节点,任务到达保障,容错等等基本要稳定好。
2.抓回来的数据,如果有需求的情况下,应该离线下来,包括http header、http body,方便你离线分析,而不是抓完就扔,要用再抓,节省下网络资源
3.有个很成熟的解析器。
a.能够解析合法/不合法的标签,对错误写法以主流浏览器的修正方法为准,并且解析足够高效
b.能够面对flash swf解析,把url抓出来
c.能够面对ajax、各种2次元的动态生成的请求
4.有很好的插件机制,随时可以发布更新,把核心和插件应用分离,方便业务和基础服务层的分离
5.维护网络资源知识库
a.域名库,包括域名的解析情况,跳转情况,各地网络通畅(存活)情况,并以此基础自动优化抓取策略
b.上面提到的抓回来的静态资源维护
c.自动发现新入库加入资源库
d.聪明地解决掉泛解析到相同地方、www与根域重复等优化问题
2.item+pipeline遇到的不同情景
当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理
每个item pipeline组件是实现了简单的方法的python类,负责接收到item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或者被丢弃而不再进行处理
item pipeline的主要作用:
清理html数据
验证爬取的数据
去重并丢弃
讲爬取的结果保存到数据库中或文件中
编写自己的item pipeline
process_item(self,item,spider)
每个item piple组件是一个独立的pyhton类,必须实现以process_item(self,item,spider)方法
每个item pipeline组件都需要调用该方法,这个方法必须返回一个具有数据的dict,或者item对象,或者抛出DropItem异常,被丢弃的item将不会被之后的pipeline组件所处理
下面的方法也可以选择实现
open_spider(self,spider)
表示当spider被开启的时候调用这个方法
close_spider(self,spider)
当spider挂去年比时候这个方法被调用
from_crawler(cls,crawler)
这个和我们在前面说spider的时候的用法是一样的,可以用于获取settings配置文件中的信息,需要注意的这个是一个类方法,用法例子如下:

例子1
这个例子实现的是判断item中是否包含price以及price_excludes_vat,如果存在则调整了price属性,都让item['price'] = item['price'] * self.vat_factor,如果不存在则返回DropItem
fromscrapy.exceptionsimport DropItemclass PricePipeline(object):
vat_factor = 1.15def process_item(self, item, spider):
ifitem['price']:
ifitem['price_excludes_vat']:
item['price'] = item['price'] * self.vat_factor
return item
else:
raiseDropItem("Missing price in %s"% item)
例子2
这个例子是将item写入到json文件中
import jsonclass JsonWriterPipeline(object):
def__init__(self):
self.file = open('items.jl','wb')
def process_item(self, item, spider):
line = json.dumps(dict(item)) +"\n" self.file.write(line)
return item
例子3
将item写入到MongoDB,同时这里演示了from_crawler的用法
import pymongoclass MongoPipeline(object):
collection_name ='scrapy_items'def__init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE','items')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
self.db[self.collection_name].insert(dict(item))
return item
例子4:去重
一个用于去重的过滤器,丢弃那些已经被处理过的item,假设item有一个唯一的id,但是我们spider返回的多个item中包含了相同的id,去重方法如下:这里初始化了一个集合,每次判断id是否在集合中已经存在,从而做到去重的功能
from scrapy.exceptions import DropItemclass DuplicatesPipeline(object):
def__init__(self):
self.ids_seen = set()
def process_item(self, item, spider):
ifitem['id']in self.ids_seen:
raiseDropItem("Duplicate item found: %s"% item)
else:
self.ids_seen.add(item['id'])
returnitem
在settings配置文件中y9ou一个ITEM_PIPELINES的配置参数,例子如下:
ITEM_PIPELINES = {
'myproject.pipelines.PricePipeline': 300,
'myproject.pipelines.JsonWriterPipeline': 800,
}
网友评论