惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
The Last Watchdog
The Last Watchdog
Security Latest
Security Latest
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
H
Help Net Security
T
The Exploit Database - CXSecurity.com
Know Your Adversary
Know Your Adversary
博客园_首页
S
Securelist
S
Schneier on Security
G
GRAHAM CLULEY
Cisco Talos Blog
Cisco Talos Blog
V
Visual Studio Blog
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
有赞技术团队
有赞技术团队
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Stack Overflow Blog
Stack Overflow Blog
量子位
L
Lohrmann on Cybersecurity
Hugging Face - Blog
Hugging Face - Blog
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
Arctic Wolf
P
Privacy & Cybersecurity Law Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
SegmentFault 最新的问题
The Hacker News
The Hacker News
罗磊的独立博客
博客园 - 司徒正美
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
K
Kaspersky official blog
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
L
LINUX DO - 热门话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
V2EX
V
Vulnerabilities – Threatpost
AWS News Blog
AWS News Blog
小众软件
小众软件
Project Zero
Project Zero

Jark's Blog

Flink 1.16:Hive SQL 如何平迁到 Flink SQL Flink CDC 如何简化实时数据入湖入仓 基于 Flink SQL 构建流批一体的 ETL 数据集成 Nexmark: 如何设计一个流计算基准测试? Demo:基于 Flink SQL 构建流式应用 Flink 1.9 实战:使用 SQL 读取 Kafka 并写入 MySQL Flink SQL 编程实践 如何从小白成长为 Apache Committer? 聊聊Blink开源和Flink社区近况 Flink 小贴士 (7): 4个步骤,让 Flink 应用达到生产状态 Flink 小贴士 (6): 使用 Broadcast State 的 4 个注意事项 Flink 小贴士 (5): Savepoint 和 Checkpoint 的 3 个不同点 Flink 小贴士 (4): 如何选择状态后端 Flink 小贴士 (3): 轻松理解 Watermark 一文了解 Apache Flink 核心技术 Flink 零基础实战教程:如何计算实时热门商品 5分钟从零构建第一个 Flink 应用 Flink 小贴士 (2):Flink 如何管理 Kafka 消费位点 Flink小贴士 (1):确定Flink作业所需资源大小时要考虑的6件事 Flink在美团的实践与应用 我在阿里的这两年 Flink 原理与实现:Aysnc I/O Flink 原理与实现:Table & SQL API Flink 原理与实现:Session Window Flink 原理与实现:Window 机制 Flink 原理与实现:数据流上的类型和操作 Flink 原理与实现:如何生成 JobGraph Flink 原理与实现:理解 Flink 中的计算资源 Flink 原理与实现:如何生成 StreamGraph Flink 原理与实现:架构和拓扑概览 Flink 原理与实现:内存管理 Flink 原理与实现:如何处理反压问题 Flink官方文档翻译:安装部署(集群模式) Flink官方文档翻译:安装部署(本地模式) 迟到的2015年终总结 高效Macbook开发之道(工具篇) Clojure学习笔记(三):并发与引用 Clojure学习笔记(二):语法 Clojure学习笔记(一):数据结构 Thrift 实践 Thrift 入门 Metrics 是个什么鬼 之入门教程 使用Scrapy定制可动态配置的爬虫 编程方式下运行 Scrapy spider 读《程序员必读的职业规划书》 Spark 下操作 HBase(1.0.0 新 API) HBase 集群安装部署 Spark On YARN 集群安装部署 Git 常用技能
使用Redis和SQLAlchemy对Scrapy Item去重并存储
WuChong · 2015-05-22 · via Jark's Blog

发表于   |   分类于 程序设计   |  

在上篇博客中,我们讲解了如何通过维护多个网站的爬取规则来抓取各个网站的数据。本文将简要地谈谈如何使用Scrapy的Item Pipline将爬取的数据去重并存储到数据库中。

Scrapy框架的高度灵活性得益于其数据管道的架构设计,开发者可以通过简单的配置就能轻松地添加新特性。我们可以通过如下的方式添加一个pipline。

settings.set("ITEM_PIPELINES", {'pipelines.DataBasePipeline': 300})

这里ITEM_PIPELINES是一个Python字典,其中key保存的pipline类在项目中的位置,value为整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内。

存储到数据库

在上一篇博客中,我们已经介绍了使用SQLAlchemy 作为我们的ORM。同样的,为了将爬取的文章保存到数据库,我们先要有一个Article模型,包含了 URL,标题,正文等字段。

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)

之后在DataBasePipeline中,我们需要生成Aticle对象,并将item中对应的字段赋给Aticle对象,最后通过SQLAlchemy将文章插入到数据库中。

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作为键值存储。

我们希望在存储之前就进行去重操作,所以需要更改下ITEM_PIPELINES的配置。

settings.set("ITEM_PIPELINES" , {
'pipelines.DuplicatesPipeline': 200,
'pipelines.DataBasePipeline': 300,
})

DuplicatesPipeline长这个样子。

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 上看到本文的完整项目。

注:本文使用的 Scrapy 版本是 0.24,GitHub 上的master分支已支持 Scrapy 1.0

本系列的三篇文章

  1. 编程方式下运行 Scrapy spider
  2. 使用Scrapy定制可动态配置的爬虫
  3. 使用Redis和SQLAlchemy对Scrapy Item去重并存储

hoxis wechat