分布式爬虫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