Scrapy_redis的实现原理及腾讯招聘爬虫案例

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » Scrapy_redis的实现原理及腾讯招聘爬虫案例

Scrapy_Redis的介绍

Scrapy_redis是一个基于redis的scrapy组件(redis based compontents for scrapy)。Scrapy_redis在Scrapy的基础上实现了更多强大的功能,具体体现在:request去重爬虫持久化轻松实现分布式

Scrapy自带url去重功能,对重复的url不在抓取,我们今天请求过的url,Scrapy不会再抓取,但是我们明天再请求同样的url,那么Scrapy就会抓取,这通常不是我们想要的。我们想要的是今天请求过的url,明天也不要再请求,这时候就可以通过Scrapy_redis来实现。

我们根据Scrapy的流程图,来分析,要想实现url去重,我们的重点就是在存放url的地方,可以放到数据库中,把所有的调度器中的request请求放到redis中,通过redis实现去重。

Scrapy_redis的实现原理及腾讯招聘爬虫案例
Scrapy_redis的实现原理及腾讯招聘爬虫案例

由于是手画的图片,存在有很多问题。我们只需要把重点放在redis实现调度器队列和指纹集合,通过一个案例,你可能会明白的更多。

腾讯招聘案例演示

我们以腾讯招聘作为演示,首先创建项目和爬虫:

scrapy startproject tencent
cd tencent
scrapy genspider -t crawl tc tencent.com

修改起始的url地址,我们使用CrawlSpider来实现翻页,通过parse_item解析列表页,parse_detail函数解析详情页,非常简单是吧。

但是一番观察发现,事情不是我们预想的呢样,在网页中找不到详情页的url地址,和翻页的地址,它是通过json接口传递的。

Scrapy_redis的实现原理及腾讯招聘爬虫案例

我们发现详情页的地址,需要在一个json接口:https://careers.tencent.com/tencentcareer/api/post/Query?&pageIndex=1&pageSize=10中寻找,将PostId和PostURL组合就是详情页的地址。但是详情页的数据也是json接口,所以我们直接构造详情页的URL地址交给parse_detail函数处理,代码参考;

# -*- coding: utf-8 -*-
import scrapy
import json

class TcSpider(scrapy.Spider):
    name = 'tc'
    allowed_domains = ['careers.tencent.com']
    #开始的url是一个json接口,参数非常简单
    start_urls = ['https://careers.tencent.com/tencentcareer/api/post/Query?&pageIndex=1&pageSize=10']

    def parse(self, response):
        #json数据转换为字典可以方便的拿到我们需要的数据
        html=json.loads(response.body.decode())

        lis=html['Data']['Posts']
        for i in lis:
            item={}
            item['postid'] = i['PostId']
            item['name']=i['RecruitPostName']
            item['location']=i['LocationName']
            item['data']=i['LastUpdateTime']
            #构造详情页的url地址,交给parse_detail函数处理
            detail = 'https://careers.tencent.com/tencentcareer/api/post/ByPostId?postId='
            detail_url = detail + item['postid']
            yield scrapy.Request(
                detail_url,
                callback=self.parse_detail,
                meta={'item':item}
            )
    def parse_detail(self,response):
        #接收item字典,添加工作介绍和工作要求
        item=response.meta['item']
        html=json.loads(response.body.decode())
        item['Responsibility']=html['Data']['Responsibility']
        item['Requirement']=html['Data']['Requirement']
        print(item)


翻页的操作很简单就可以实现,可以修改起始url的参数pageIndex页码和pageSize尺寸,我们可以随意修改尺寸就是显示的数量,这个可以直接修改不用翻页也可以。

Scrapy_Redis的安装

我们的重点是用scrapy_redis来实现去重功能,那么首先安装scrapy-redis。我使用的是pycharm,个人比较喜欢使用命令安装,在Terminal的终端输入命令:

pip install --default-timeout=5000 scrapy-redis

设置为不超时,什么时候安装好什么时候退出,避免安装超时。我们怎么使用呢,先看一下演示,使用方法很简单,我么只需要修改settings文件就可以,在此之前你需要了解redis的基本使用,这里不再详细介绍redis的有关知识。

修改腾讯招聘案例为scrapy_redis爬虫

我们只需要在settings文件中添加下面的代码(删掉了注释的代码):

# -*- coding: utf-8 -*-

#指定哪个去重方法结合request对象去重
DUPEFILTER_CLASS='scrapy_redis.dupefilter.RFPDupeFilter'
#指定scheduler队列
SCHEDULER='scrapy_redis.scheduler.Scheduler'
#队列中的内容是否持久保存,为False的时候,关闭redis的同时会清空redis数据
SCHEDULER_PERSIST=True

#SpiderPriorityQueue是scrapy_redis默认使用的队列模式(有自己的优先级)
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"

#使用了队列的形式,任务先进先出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"

#采用了栈的形式,任务先进后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"


#scrapy_redis实现的item保存到redis的pipeline
ITEM_PIPELINES = {
   'tencent.pipelines.TencentPipeline': 300,
   'scrapy_redis.pipelines.RedisPipeline':400,
}

DOWNLOAD_DELAY = 1

LOGLEVEL='DEBUG'

#指定redis的地址,为本机
REDIS_URL='redis://127.0.0.1:6379'

BOT_NAME = 'tencent'

SPIDER_MODULES = ['tencent.spiders']
NEWSPIDER_MODULE = 'tencent.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'

ROBOTSTXT_OBEY = False



然后我们开启redis服务端和客户端,服务端让爬虫操作,客户端来查看一些信息。运行爬虫,然后在redis客户端查看数据。在redis客户端输入:

keys *
1) "tc:requests"   #类型zset 待爬的requests对象
2) "tc:items"    #类型list
3) "tc:dupefilter"    #类型set爬取过的requests指纹

那么使用scrapy_redis爬虫,会在redis数据库中生成固定的一些信息,包括:

  • 爬虫名字:requests。schedulter队列,存放待请求的request对象,获取的过程是pop操作,即获取一个会删除一个
  • 爬虫名字:items。存放获取到的item信息,在pipeline中开启RedisPipeline时才会存入
  • 爬虫名字:dupefilter。指纹集合,存放已经进入schedulter队列的request对象的指纹,指纹默认由请求方法,url和请求体组成

意味着我们不开启scrapy_redis.pipelines.RedisPipeline管道,redis数据库中就不会有items。换句话说scrapy_redis.pipelines.RedisPipeline仅仅实现了item数据存储到redis的过程,那么我们可以新建一个pipeline(或者修改默认的pipeline),让数据存放到任意地方。

我们重点放在redis数据库中的三个新增的键值,reqeusts的解释已经很明确了,这就是问什么我们在爬虫结束的时候,redis数据库中只显示items和dupefilter。爬虫停止的时候意味着,requests没有了请求对象,那么就会删除这个键。你可以修改一下腾讯招聘的json接口,把每页显示的数量增加(pageSize参数的值),尽量修改大一点,这样,你有足够的时间去输入命令查看,在爬虫没有运行完的时候,是存在requests的,具体自己尝试方能悟解!哈哈哈

Scrapy_Redis爬虫源码分析

我们需要真正的了解scrapy_redis原理,那么就需要通过源码。对于小白来说,看懂源码是一件非常有挑战性的困难,但是只有这样才可以不断进步。具体的内容本文不再介绍,篇幅有限,详情可点击:Scrapy_Redis源码介绍和分析

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《Scrapy_redis的实现原理及腾讯招聘爬虫案例》 发布于2020-03-19

分享到:
赞(2) 赏杯咖啡

评论 抢沙发

3 + 9 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册