scrapy过滤重复数据和增量爬取
原文链接
前言
这篇笔记基于上上篇笔记的---《scrapy电影天堂实战(二)创建爬虫项目》,而这篇又涉及redis,所以又先熟悉了下redis,记录了下《redis基础笔记》,这篇为了节省篇幅所以只添加改动部分代码。
个人实现思路
- 过滤重复数据
在pipeline写个redispipeline,要爬的内容hash后的键movie_hash通过pipeline时与从redis获取的movie_hash(set类型)比对,如果在redis里面则在pipeline里raise DropItem将这个item去掉,在通过pipeline的mysqlpipeline存入数据库时就不会有重复数据了。
- 增量爬取
虽然没有重复数据了,但是不能增量爬取,一旦停止了爬虫,又会从头爬取,效率很低。想到在downloader middleware中增加对request和response的url进行处理将它放到redis,然后比对,有在redis里面就raise IgnoreRequest忽略掉这个请求,测试也的确忽略了,但其实还是从头开始爬取,只不过忽略了这个请求,效率并没有提升多少,好像并不是增量爬取。最后默默删掉自己的代码。。。
求助
折腾了许久,熬不住了,还是求助吧。其实之前google就搜到了一个scrapy-redis的开源项目就实现了这些功能,但自己试了下没有实现效果(我自己的问题),所以想找本书系统看看scrapy,然后就找了下python scrapy相关的pdf(穷逼买不起书)。找到了一本也引用了scrapy-redis这个项目的书,什么书就不说了,尊重别人的劳动,土豪另当别论。按照书里的配置了下,过滤重复数据是ok了,但增量爬取死活不行,一旦停止、重新爬取,它只会将redis里面的requests爬完就完了,之后再重启爬虫都不会有新的requests生成了。又折腾了许久,在某个群里有个大佬回答了,将爬取page的链接的yield那设置dont_filter = True,自己设置测试了下,的确实现了增量爬取。再次感谢那位大佬的帮助。
具体实现
创建个redis容器
具体查看《redis基础笔记》的使用redis镜像这里的方法,这里不再赘述。
引用scrapy-redis
修改settings.py添加配置,完整配置查看:https://github.com/rmax/scrapy-redis#usage
###### scrapy-redis settings start ######
# https://github.com/rmax/scrapy-redis
# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# Specify the full Redis URL for connecting (optional).
# If set, this takes precedence over the REDIS_HOST and REDIS_PORT settings.
REDIS_URL = 'redis://:123123@192.168.229.128:8889'
# Don't cleanup redis queues, allows to pause/resume crawls.
SCHEDULER_PERSIST = True
###### scrapy-redis settings end ######
修改spider
我一开始引用了scrapy-redis不成功的原因是我将这个参数设置成了
dont_filter = False,还有就是爬取下一页和详情页的顺序反了,应该先爬页链接在爬详情页。
def parse(self, response):
item = MovieHeavenBarItem()
domain = "https://www.dytt8.net"
# 爬取下一页
last_page_num = response.xpath('//select[@name="sldd"]//option[last()]/text()').extract()[0]
last_page_url = 'list_23_' + last_page_num + '.html'
next_page_url = response.xpath('//div[@class="x"]//a[last() - 1]/@href').extract()[0]
next_page_num = next_page_url.split('_')[-1].split('.')[0]
if next_page_url != last_page_url:
url = 'https://www.dytt8.net/html/gndy/dyzz/' + next_page_url
logging.log(logging.INFO, f'***************** crawling page {next_page_num} ***************** ')
yield Request(url=url, callback=self.parse, meta={'item': item}, dont_filter = True)
# 爬取详情页
urls = response.xpath('//b/a/@href').extract() # list type
#print('urls', urls)
for url in urls:
url = domain + url
yield Request(url=url, callback=self.parse_single_page, meta={'item': item}, dont_filter = False)
见证奇迹的时刻
日志输出
2019-07-24 09:45:31 [scrapy.crawler] INFO: Received SIGINT, shutting down gracefully. Send again to force从中可以看到我按了两次ctrl+c强行停止了爬虫,在这之前是在爬取这个链接的2019-07-24 09:45:30 [root] INFO: movie_link: https://www.dytt8.net/html/gndy/dyzz/20180826/57328.html,然后我重新启动爬虫看到接着爬取这个链接了2019-07-24 09:46:03 [root] INFO: crawling url: https://www.dytt8.net/html/gndy/dyzz/20180718/57146.html
忽略部分...
2019-07-24 09:45:30 [root] INFO: crawling url: https://www.dytt8.net/html/gndy/dyzz/20180826/57328.html
2019-07-24 09:45:30 [root] INFO: **************** movie detail log ****************
2019-07-24 09:45:30 [root] INFO: movie_link: https://www.dytt8.net/html/gndy/dyzz/20180826/57328.html
2019-07-24 09:45:30 [root] INFO: movie_name: 金蝉脱壳2/金蝉脱壳2:冥府
2019-07-24 09:45:30 [root] INFO: movie_publish_date: 2018-06-13(菲律宾)/2018-06-29(中国)/2018-06-29(美国)
2019-07-24 09:45:30 [root] INFO: movie_score: 4.0/10 from 1,180 users
2019-07-24 09:45:30 [root] INFO: movie_directors: 史蒂芬·C·米勒 Steven C. Miller
2019-07-24 09:45:30 [root] INFO: ***************** commit to mysql *****************
2019-07-24 09:45:31 [scrapy.crawler] INFO: Received SIGINT, shutting down gracefully. Send again to force
2019-07-24 09:45:31 [scrapy.core.engine] INFO: Closing spider (shutdown)
2019-07-24 09:45:58 [scrapy.extensions.telnet] INFO: Telnet Password: 4e5dbb60f52f81fe
2019-07-24 09:45:58 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
'scrapy.extensions.telnet.TelnetConsole',
'scrapy.extensions.memusage.MemoryUsage',
'scrapy.extensions.logstats.LogStats']
2019-07-24 09:45:58 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'movie_heaven_bar.middlewares.MovieHeavenBarDownloaderMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2019-07-24 09:45:58 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
'scrapy.spidermiddlewares.referer.RefererMiddleware',
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2019-07-24 09:45:58 [scrapy.middleware] INFO: Enabled item pipelines:
['movie_heaven_bar.pipelines.MovieHeavenBarPipeline']
2019-07-24 09:45:58 [scrapy.core.engine] INFO: Spider opened
2019-07-24 09:45:58 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-07-24 09:45:58 [newest_movie] INFO: Spider opened: newest_movie
2019-07-24 09:45:58 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2019-07-24 09:46:03 [root] INFO: crawling url: https://www.dytt8.net/html/gndy/dyzz/20180718/57146.html
2019-07-24 09:46:03 [root] INFO: **************** movie detail log ****************
2019-07-24 09:46:03 [root] INFO: movie_link: https://www.dytt8.net/html/gndy/dyzz/20180718/57146.html
2019-07-24 09:46:03 [root] INFO: movie_name: Operation Red Sea
2019-07-24 09:46:03 [root] INFO: movie_publish_date: 2018-02-16(中国)
2019-07-24 09:46:03 [root] INFO: movie_score: 8.3/10 from 433,101 users
2019-07-24 09:46:03 [root] INFO: movie_directors: 林超贤 Dante Lam
2019-07-24 09:46:03 [root] INFO: movie_actors: 张译 Yi Zhang , 黄景瑜 Jingyu Huang , 海清 Hai-Qing , 杜江 Jiang Du , 蒋璐霞 Luxia Jiang , 尹昉 Fang Yin , 王强 Qiang Wang , 郭郁滨 Yubin Guo , 王雨甜 Yutian Wang , 麦亨利 Henry Mai , 张涵>予 Hanyu Zhang , 王彦霖 Yanlin Wang
2019-07-24 09:46:03 [root] INFO: movie_download_link: magnet:?xt=urn:btih:3c1188fdbec2f63ce1e30d2061913fcba15ebb90&dn=%e9%98%b3%e5%85%89%e7%94%b5%e5%bd%b1www.ygdy8.com.%e7%ba%a2%e6%b5%b7%e8%a1%8c%e5%8a%a8.BD.720p.%e5%9b%bd%e8%af%ad%e4%b8%ad%e5%ad%97.mkv&tr=udp%3a%2f%2ftracker.leechers-paradise.org%3a6969%2fannounce&tr=udp%3a%2f%2ftracker.opentrackr.org%3a1337%2fannounce&tr=udp%3a%2f%2feddie4.nl%3a6969%2fannounce&tr=udp%3a%2f%2fshadowshq.eddie4.nl%3a6969%2fannounce
2019-07-24 09:46:03 [root] INFO: ***************** commit to mysql *****************
忽略部分...
查看redis key的变化
scrapy-redis 会在redis生成两个set,用于存储请求有序集合requests和过滤链接无序集合dupefilter,当请求消费完了,有序集合requests就会被干掉,直到有新请求时才重新生成,如果未消费完就一直追加。而无序集合dupefilter由于设置了
SCHEDULER_PERSIST = True就不会被干掉,有新的请求就会追加进来。
root@fa2b076097e9:/data# redis-cli
127.0.0.1:6379> AUTH 123123
OK
127.0.0.1:6379> KEYS *
1) "newest_movie:requests"
2) "newest_movie:dupefilter"
127.0.0.1:6379> TYPE newest_movie:requests
zset
127.0.0.1:6379> TYPE newest_movie:dupefilter
set
127.0.0.1:6379> ZCARD newest_movie:requests
(integer) 47
127.0.0.1:6379> ZCARD newest_movie:requests
(integer) 45
127.0.0.1:6379> ZCARD newest_movie:requests
(integer) 0
忽略部分...
127.0.0.1:6379> KEYS *
1) "newest_movie:dupefilter"
127.0.0.1:6379> SCARD newest_movie:dupefilter
(integer) 775
127.0.0.1:6379> ZRANGE newest_movie:requests 0 -1
1) "\x80\x04\x95\x7f\x01\x00\x00\x00\x00\x00\x00}\x94(\x8c\x03url\x94\x8c8https://www.dytt8.net/html/gndy/dyzz/20180107/56002.html\x94\x8c\bcallback\x94\x8c\x11parse_single_page\x94\x8c\aerrback\x94N\x8c\x06method\x94\x8c\x03GET\x94\x8c\aheaders\x94}\x94C\aReferer\x94]\x94C4https://www.dytt8.net/html/gndy/dyzz/list_23_31.html\x94as\x8c\x04body\x94C\x00\x94\x8c\acookies\x94}\x94\x8c\x04meta\x94}\x94(\x8c\x04item\x94\x8c\x16movie_heaven_bar.items\x94\x8c\x12MovieHeavenBarItem\x94\x93\x94)\x81\x94}\x94\x8c\a_values\x94}\x94sb\x8c\x05depth\x94K\x1fu\x8c\t_encoding\x94\x8c\x05utf-8\x94\x8c\bpriority\x94K\x00\x8c\x0bdont_filter\x94\x89\x8c\x05flags\x94]\x94u."
2) "\x80\x04\x95\x7f\x01\x00\x00\x00\x00\x00\x00}\x94(\x8c\x03url\x94\x8c8https://www.dytt8.net/html/gndy/dyzz/20180108/56021.html\x94\x8c\bcallback\x94\x8c\x11parse_single_page\x94\x8c\aerrback\x94N\x8c\x06method\x94\x8c\x03GET\x94\x8c\aheaders\x94}\x94C\aReferer\x94]\x94C4https://www.dytt8.net/html/gndy/dyzz/list_23_31.html\x94as\x8c\x04body\x94C\x00\x94\x8c\acookies\x94}\x94\x8c\x04meta\x94}\x94(\x8c\x04item\x94\x8c\x16movie_heaven_bar.items\x94\x8c\x12MovieHeavenBarItem\x94\x93\x94)\x81\x94}\x94\x8c\a_values\x94}\x94sb\x8c\x05depth\x94K\x1fu\x8c\t_encoding\x94\x8c\x05utf-8\x94\x8c\bpriority\x94K\x00\x8c\x0bdont_filter\x94\x89\x8c\x05flags\x94]\x94u."
忽略部分...
127.0.0.1:6379> SMEMBERS newest_movie:dupefilter
1) "1bff65c147e71ea6d43b7e4a4ac86fc982375939"
2) "9d99491255ee83dd4ffb72c3c59c17c938dbe08f"
忽略部分...
检查数据
将数据库数据导出到excel发现500条记录还是有4条重复值,这可能是我多次测试强行停止导致,所以也算是基本实现了过滤重复数据,增量爬取数据的功能了。
结语
这个项目基本功能是实现了,但还是有写细节要处理下,而且scrapy-redis的原理还不了解,下一篇就了解下scrapy-redis的原理。
scrapy过滤重复数据和增量爬取的更多相关文章
- scrapy增量爬取
开始接触爬虫的时候还是初学Python的那会,用的还是request.bs4.pandas,再后面接触scrapy做个一两个爬虫,觉得还是框架好,可惜都没有记录都忘记了,现在做推荐系统需要爬取一定的 ...
- 通过scrapy,从模拟登录开始爬取知乎的问答数据
这篇文章将讲解如何爬取知乎上面的问答数据. 首先,我们需要知道,想要爬取知乎上面的数据,第一步肯定是登录,所以我们先介绍一下模拟登录: 先说一下我的思路: 1.首先我们需要控制登录的入口,重写star ...
- 使用scrapy实现去重,使用Redis实现增量爬取
面试场景: 要求对正在爬取的内容与mysql数据库中的数据进行比较去重 解决方式: 通过Redis来作为中间件,通过url来确保爬过的数据不会再爬,做到增量爬取. Redis数据库其实就是一个中间件, ...
- webmagic 增量爬取
webmagic 是一个很好并且很简单的爬虫框架,其教程网址:http://my.oschina.net/flashsword/blog/180623 webmagic参考了scrapy的模块划分, ...
- 手把手教你如何用java8新特性将List中按指定属性排序,过滤重复数据
在java中常常会遇到这样一个问题,在实际应用中,总会碰到对List排序并过滤重复的问题,如果List中放的只是简单的String类型过滤so easy,但是实际应用中并不会这么easy,往往List ...
- Elasticsearch去重查询/过滤重复数据(聚合)
带家好,我是马儿,这次来讲一下最近遇到的一个问题 我司某个环境的es中被导入了重复数据,导致查询的时候会出现一些重复数据,所以要我们几个开发想一些解决方案,我们聊了聊,相出了下面一些方案: 1.从源头 ...
- python3下scrapy爬虫(第八卷:循环爬取网页多页数据)
之前我们做的数据爬取都是单页的现在我们来讲讲多页的 一般方式有两种目标URL循环抓取 另一种在主页连接上找规律,现在我用的案例网址就是 通过点击下一页的方式获取多页资源 话不多说全在代码里(因为刚才写 ...
- (4)分布式下的爬虫Scrapy应该如何做-规则自动爬取及命令行下传参
本次探讨的主题是规则爬取的实现及命令行下的自定义参数的传递,规则下的爬虫在我看来才是真正意义上的爬虫. 我们选从逻辑上来看,这种爬虫是如何工作的: 我们给定一个起点的url link ,进入页面之后提 ...
- 【图文详解】scrapy安装与真的快速上手——爬取豆瓣9分榜单
写在开头 现在scrapy的安装教程都明显过时了,随便一搜都是要你安装一大堆的依赖,什么装python(如果别人连python都没装,为什么要学scrapy….)wisted, zope interf ...
随机推荐
- Node.js实战7:你了解buffer吗?
Buffer是NodeJS的重要数据类型,很有广泛的应用. Buffer是代表原始堆的分配额的数据类型.在NodeJS中以类数组的方式使用. 比如,用法示例: var buf = new Buffer ...
- 2019寒假作业三:PTA7-1抓老鼠啊~亏了还是赚了
- 抓老鼠啊~亏了还是赚了? ( 分) 某地老鼠成灾,现悬赏抓老鼠,每抓到一只奖励10元,于是开始跟老鼠斗智斗勇:每天在墙角可选择以下三个操作:放置一个带有一块奶酪的捕鼠夹(T),或者放置一块奶酪(C ...
- [Git] 013 远程仓库篇 第零话 使用前的一些配置
0. 前言 本地仓库和 GitHub 上的远程仓库之间的传输是通过 "SSH" 加密的,所以使用前需要进行一些设置 这回的任务 设置"身份象征" 创建 &quo ...
- CentOS7 通过YUM安装MySQL5.7 linux
CentOS7 通过YUM安装MySQL5.7 1.进入到要存放安装包的位置 cd /home/lnmp 2.查看系统中是否已安装 MySQL 服务,以下提供两种方式: rpm -qa | grep ...
- httplib模块:(一个相对底层的http请求模块)
httplib是一个相对底层的http请求模块,期上有专门的包装模块,如urllib内建模块,goto第三方模块,但是封装的越高就约不灵活,比如urllib模块里的请求错误是就不会返回结果页的内容,只 ...
- vue.js(19)--vue中子组件调用父组件的方法
子组件是不能直接使用父组件中的方法的,需要进行事件绑定(v-on:自定义方法名="父组件方法名"),然后在子组件中再定义一个方法,使用this.$emit('自定义方法名')语句完 ...
- 基于socket 实现单线程并发
基于socket 实现单线程并发: 基于协程实现内IO的快速切换,我们必须提前导入from gevent import monkey;monkey pacth_all() 以为 gevent spaw ...
- 14DBCP连接池
实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection.这样我们就不需要每次都创建连接.释放连接了,这些操作 ...
- 【串线篇】spring boot配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件 (1)–file:./config/ ...
- prototype的用法
定义: prototype 属性使您有能力向对象添加属性和方法. 语法: object.prototype.name=value 实例: function prot(){ this.name = 'J ...