Python: 使用Redis和SQLAlchemy对Scrapy Item去重并存储
May 26, 2015
在上篇博客中,我们讲解了如何通过维护多个网站的爬取规则来抓取各个网站的数据。本文将简要地谈谈如何使用Scrapy的 Item Pipline将爬取的数据去重并存储到数据库中。
Scrapy框架的高度灵活性得益于其数据管道的架构设计,开发者可以通过简单的配置就能轻松地添加新特性。我们可以通过如下的方式添加一个pipline。
settings.set("ITEM_PIPELINES>" , {'pipelines.DataBasePipeline' : 300 })
这里
Table of Contents
存储到数据库
在上一篇博客中,我们已经介绍了使用 SQLAlchemy作为我们的ORM。同样的,为了将爬取的文章保存到数据库,我们先要有一个
from sqlalchemy import Column, String , DateTime, Integer from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Article (Base) : __tablename__ = 'articles' id = Column(Integer, primary_key=True ) title = Column(String) url = Column(String) body = Column(String) publish_time = Column(DateTime) source_site = Column(String)
之后在
from model.config import DBSession from model.article import Article class DataBasePipeline (object) : def open_spider (self, spider) : self.session = DBSession() def process_item (self, item, spider) : a = Article(title=item["title>" ].encode("utf-8>" ), url=item["url>" ], body=item["body>" ].encode("utf-8>" ), publish_time=item["publish_time>" ].encode("utf-8>" ), source_site=item["source_site>" ].encode("utf-8>" )) self.session.add(a) self.session.commit() def close_spider (self,spider) : self.session.close()
使用Redis去重
为了防止同一个网页爬取两遍,我们使用Redis来去重,因为 Redis 作为Key/Value数据库在这个场景是非常适合的。我们认为一个URL能唯一代表一个网页。所以使用URL作为键值存储。
我们希望在存储之前就进行去重操作,所以需要更改下
settings.set("ITEM_PIPELINES>" , { 'pipelines.DuplicatesPipeline' : 200 , 'pipelines.DataBasePipeline' : 300 , })
from scrapy.exceptions import DropItem from model.config import Redis class DuplicatesPipeline (object) : def process_item (self, item, spider) : if Redis.exists('url:%s' % item['url' ]): raise DropItem("Duplicate item found: %s>" % item) else : Redis.set('url:%s' % item['url' ],1 ) return item
当检测到Item已经存在,会抛出DropItem 异常,被丢弃的item将不会被之后的pipeline组件所处理。
最后,运行脚本,你能看到我们的程序欢快地跑起来了。
python run.py
你可以在 GitHub上看到本文的完整项目。
原文:http://wuchong.me/blog/2015/05/22/using-redis-and-sqlalchemy-to-checkd-dup-and-store-scrapy-item/
0 Comments