分布式爬虫Item+Pipeline

作者: 幼姿沫 | 来源:发表于2021-03-27 10:51 被阅读0次

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

启用一个item Pipeline组件

在settings配置文件中y9ou一个ITEM_PIPELINES的配置参数,例子如下:

ITEM_PIPELINES = {

    'myproject.pipelines.PricePipeline': 300,

    'myproject.pipelines.JsonWriterPipeline': 800,

}

每个pipeline后面有一个数值,这个数组的范围是0-1000,这个数值确定了他们的运行顺序,数字越小越优先

相关文章

网友评论

    本文标题:分布式爬虫Item+Pipeline

    本文链接:https://www.haomeiwen.com/subject/wqwfhltx.html