Scrapy笔记06- Item Pipeline

当一个item被蜘蛛爬取到之后会被发送给Item Pipeline,然后多个组件按照顺序处理这个item。 每个Item Pipeline组件其实就是一个实现了一个简单方法的Python类。他们接受一个item并在上面执行逻辑,还能决定这个item到底是否还要继续往下传输,如果不要了就直接丢弃。

使用Item Pipeline的常用场景:

  • 清理HTML数据
  • 验证被抓取的数据(检查item是否包含某些字段)
  • 重复性检查(然后丢弃)
  • 将抓取的数据存储到数据库中

编写自己的Pipeline

定义一个Python类,然后实现方法process_item(self, item, spider)即可,返回一个字典或Item,或者抛出DropItem异常丢弃这个Item。

或者还可以实现下面几个方法:

  • open_spider(self, spider) 蜘蛛打开的时执行
  • close_spider(self, spider) 蜘蛛关闭时执行
  • from_crawler(cls, crawler) 可访问核心组件比如配置和信号,并注册钩子函数到Scrapy中

Item Pipeline示例

价格验证

我们通过一个价格验证例子来看看怎样使用

from scrapy.exceptions import DropItem

class PricePipeline(object):

    vat_factor = 1.15

    def process_item(self, item, spider):
if item['price']:
if item['price_excludes_vat']:
item['price'] = item['price'] * self.vat_factor
return item
else:
raise DropItem("Missing price in %s" % item)

将item写入json文件

下面的这个Pipeline将所有的item写入到一个单独的json文件,一行一个item

import json

class 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

将item存储到MongoDB中

这个例子使用pymongo来演示怎样讲item保存到MongoDB中。 MongoDB的地址和数据库名在配置中指定,这个例子主要是向你展示怎样使用from_crawler()方法,以及如何清理资源。

import pymongo

class 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

重复过滤器

假设我们的item里面的id字典是唯一的,但是我们的蜘蛛返回了多个相同id的item

from scrapy.exceptions import DropItem

class DuplicatesPipeline(object):

    def __init__(self):
self.ids_seen = set() def process_item(self, item, spider):
if item['id'] in self.ids_seen:
raise DropItem("Duplicate item found: %s" % item)
else:
self.ids_seen.add(item['id'])
return item

激活一个Item Pipeline组件

你必须在配置文件中将你需要激活的Pipline组件添加到ITEM_PIPELINES

ITEM_PIPELINES = {
'myproject.pipelines.PricePipeline': 300,
'myproject.pipelines.JsonWriterPipeline': 800,
}

后面的数字表示它的执行顺序,从低到高执行,范围0-1000

Feed exports

这里顺便提下Feed exports,一般有的爬虫直接将爬取结果序列化到文件中,并保存到某个存储介质中。只需要在settings里面设置几个即可:

* FEED_FORMAT= json # json|jsonlines|csv|xml|pickle|marshal
* FEED_URI= file:///tmp/export.csv|ftp://user:pass@ftp.example.com/path/to/export.csv|s3://aws_key:aws_secret@mybucket/path/to/export.csv|stdout:
* FEED_EXPORT_FIELDS = ["foo", "bar", "baz"] # 这个在导出csv的时候有用

请求和响应

Scrapy使用RequestResponse对象来爬取网站。Request对象被蜘蛛生成,然后被传递给下载器,之后下载器处理这个Request后返回Response对象,然后返回给生成Request的这个蜘蛛。

给回调函数传递额外的参数

Request对象生成的时候会通过关键字参数callback指定回调函数,Response对象被当做第一个参数传入,有时候我们想传递额外的参数,比如我们构建某个Item的时候,需要两步,第一步是链接属性,第二步是详情属性,可以指定Request.meta

def parse_page1(self, response):
item = MyItem()
item['main_url'] = response.url
request = scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2)
request.meta['item'] = item
return request def parse_page2(self, response):
item = response.meta['item']
item['other_url'] = response.url
return item

Request子类

Scrapy为各种不同的场景内置了很多Request子类,你还可以继承它自定义自己的请求类。

FormRequest这个专门为form表单设计,模拟表单提交的示例

return [FormRequest(url="http://www.example.com/post/action",
formdata={'name': 'John Doe', 'age': ''},
callback=self.after_post)]

我们再来一个例子模拟用户登录,使用了FormRequest.from_response()

import scrapy

class LoginSpider(scrapy.Spider):
name = 'example.com'
start_urls = ['http://www.example.com/users/login.php'] def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': 'john', 'password': 'secret'},
callback=self.after_login
) def after_login(self, response):
# check login succeed before going on
if "authentication failed" in response.body:
self.logger.error("Login failed")
return # continue scraping with authenticated session...

Response子类

一个scrapy.http.Response对象代表了一个HTTP相应,通常是被下载器下载后得到,并交给Spider做进一步的处理。Response也有很多默认的子类,用于表示各种不同的响应类型。

  • TextResponse 在基本Response类基础之上增加了编码功能,专门用于二进制数据比如图片、声音或其他媒体文件
  • HtmlResponse 此类是TextResponse的子类,通过查询HTML的meta http-equiv属性实现了编码自动发现
  • XmlResponse 此类是TextResponse的子类,通过查询XML声明实现编码自动发现
 

Scrapy笔记06- Item Pipeline的更多相关文章

  1. scrapy框架中Item Pipeline用法

    scrapy框架中item pipeline用法 当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的pyt ...

  2. Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法

    当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的python类,负责接收到item并通过它执行一些行为, ...

  3. Python之爬虫(十八) Scrapy框架中Item Pipeline用法

    当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的python类,负责接收到item并通过它执行一些行为, ...

  4. 二、Item Pipeline和Spider-----基于scrapy取校花网的信息

    Item Pipeline 当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item. 每个Item Pipeline ...

  5. Scrapy爬虫框架第七讲【ITEM PIPELINE用法】

    ITEM PIPELINE用法详解:  ITEM PIPELINE作用: 清理HTML数据 验证爬取的数据(检查item包含某些字段) 去重(并丢弃)[预防数据去重,真正去重是在url,即请求阶段做] ...

  6. Scrapy框架-Item Pipeline

    目录 1. Item Pipeline 3. 完善之前的案例: 3.1. item写入JSON文件 3.2. 启用一个Item Pipeline组件 3.3. 重新启动爬虫 1. Item Pipel ...

  7. scrapy item pipeline

    item pipeline process_item(self, item, spider) #这个是所有pipeline都必须要有的方法在这个方法下再继续编辑具体怎么处理 另可以添加别的方法 ope ...

  8. Scrapy学习篇(七)之Item Pipeline

    在之前的Scrapy学习篇(四)之数据的存储的章节中,我们其实已经使用了Item Pipeline,那一章节主要的目的是形成一个笼统的认识,知道scrapy能干些什么,但是,为了形成一个更加全面的体系 ...

  9. 爬虫框架Scrapy之Item Pipeline

    Item Pipeline 当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item. 每个Item Pipeline ...

随机推荐

  1. git拆分仓库

    1.git filter-branch拆分当前分支 修改仓库目录,改成拆分后的结构 创建一个当前分支的拷贝分支 git filter-branch -f --tag-name-filter cat - ...

  2. 整理在Spring IOC容器初始化后可以处理特定逻辑的多种实现方式

    Spring框架的核心是依赖注入.切面:Spring Boot是在Spring框架的基础上为其提供许多默认配置.默认约定(约定优于配置),从而达到减少或减化配置进而可开箱即用.快速上手:Spring ...

  3. Navicat 连接远程数据库报错:1130 - Host "XX.XX.XX.XX" is not allowed to connect to this MySQL server

    Navicat 连接远程数据库报错:1130 - Host "XX.XX.XX.XX" is not allowed to connect to this MySQL server ...

  4. HTTP之网关的分类

    网关的分类 ========================摘自<HTTP权威指南>============================= 1.  HTTP/*:服务器端Web网关 请 ...

  5. python笔记 利用python 自动生成条形码 二维码

    1. ean13标准条形码 from pystrich.ean13 import EAN13Encoder encode = EAN13Encoder(') encode.save('d:/barco ...

  6. Appium+python自动化(八)- 初识琵琶女Appium(千呼万唤始出来,犹抱琵琶半遮面)- 下(超详解)

    ​简介 通过上一篇宏哥给各位小伙伴们的引荐,大家移动对这位美女有了深刻的认识,而且她那高超的技艺和婀娜的身姿久久地浮现在你的脑海里,是不是这样呢???不要害羞直接告诉宏哥:是,就对了.宏哥要的就是这个 ...

  7. SublimeText3安装Markdown插件

    由于Webstrom对md文件的预览效果并不理想(与实际网页编译效果差别较大),所以我又改用Sublime进行本地编辑,下面介绍一下怎么搭建环境. 插件安装 整套环境我们就需要两个插件:Markdow ...

  8. Golang程序调试工具介绍(gdb vs dlv)

    原文:http://lday.me/2017/02/27/0005_gdb-vs-dlv/ 通过log库输出日志,我们可以对程序进行异常分析和问题追踪.但有时候,我也希望能有更直接的程序跟踪及定位工具 ...

  9. PIE创建带压缩的栅格数据集

    这段时间我一直在研究如何用PIE创建带压缩的栅格数据集,由于我在比赛中使用的原始影像大小普遍都在300M以上,软件加载较慢,因此希望能对原始影像进行压缩,加快加载时间. 首先,该方法的关键是修改Dat ...

  10. Filco圣手二代双模蓝牙机械键盘的连接方法

    常规方法 确认键盘的电源接通. 同时按下「Ctrl」+「Alt」+「Fn」执行装置切换模式.配对LED灯(蓝)和低电量显示LED灯(红)约同时亮10秒左右. 想移除已登录的装置时,请从「蓝牙装置登录/ ...