scrapy使用redis实现增量式爬取

增量式爬虫


监测网站数据更新的情况,只会爬取网站最新更新出来的数据。


需求:

爬取某个电影网站,然后把电影的名称和简介进行持久化存储

实现思路

指定一个起始url


基于CrawISpider获取其他页码链接

基于Rule将其他页码链接进行请求


从每一个页码对应的页面源码中解析出每一个电影详情页的URL,然后解析出电影的名称和简介进行持久化存储

实现增量式核心内容:

使用redis sets检测电影详情页的url之前有没有请求过


将未爬取过的url页的
详情页的url发起请求,

实现代码

创建工程

scrapy startproject  moviePro

cd moviePro
scrapy genspider -t crawl movie www.xxx.com

spider文件

# -*- coding: utf-8 -*-
import scrapy
from redis import Redis
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from moviePro.items import MovieproItem
import sys

class MovieSpider(CrawlSpider):
    name = 'movie'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.4567kan.com/frim/index1.html']
    # 得到默认编码
    print(sys.getdefaultencoding())
    # 连接redis
    conn = Redis(host='127.0.0.1', encoding='utf-8', port=6379)
    print(conn)

    rules = (
        Rule(LinkExtractor(allow=r'/frim/index1-\d+\.html'), callback='parse_item', follow=True),
        # 获取页码对应的url
    )

    def parse_item(self, response):
        print(response)
        li_list = response.xpath('//ul[@class="stui-vodlist clearfix"]/li')
        for li_item in li_list:
            title = li_item.xpath('./div[@class="stui-vodlist__box"]/div[1]/h4/a/text()').extract_first()
            # 标题
            new_url = 'https://www.4567kan.com/'+li_item.xpath('./div[@class="stui-vodlist__box"]/div[1]/h4/a/@href').extract_first()
            # url
            # 将url存入redis的set集合中
            item = MovieproItem()
            item['name'] = title
            ex = self.conn.sadd('urls',new_url)
            # print(title)
            # print(new_url)
            if ex==1:
                print("该url没有被爬取过,可以进行数据爬取")
                yield scrapy.http.Request(url=new_url, callback=self.parse_detail, meta={'item':item})
            else:
                print("数据没有进行更新,没有数据爬取")

    def parse_detail(self, response):

        # 简介
        desc = response.xpath('//div[@class="stui-content__detail"]/p[5]/span[2]/text()').extract()
        item = response.meta['item']
        item['desc']=''.join(desc).strip()
        # print(desc)

        yield item

Pipeline文件

from redis import Redis
class MovieproPipeline(object):
    conn = None
    def open_spider(self,spider):
        self.conn = spider.conn
    def process_item(self, item, spider):
        dic = {
            'name':item['name'],
            'desc':item['desc']
        }
        print(dic)
        self.conn.lpush('movieData',dic)
        return item

 

items文件

import scrapy


class MovieproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field()
    desc = scrapy.Field()
    pass

 

运行

scrapy crawl movie

该url没有被爬取过,可以进行数据爬取
……

{'name': '游戏改变者2015', 'desc': '丹尼尔·雷德克里夫有望加盟一部关于《侠盗猎车手》创始人的BBC电视电影,双方正在谈判中丹尼尔将出演山姆·豪泽是Rockstar公司的总裁,他一手推出了《侠盗猎车手》、《马克·佩恩
》等热门游戏,影片将围'}
['象人(约翰•赫特 John Hurt 饰)是一个天生的畸形症患者,他的脸长得就像大象的脸,因此而得名象人一直被利欲昏心的马戏团老板利用,带到世界各地去巡回演出,受尽了非人的虐待。象人所经受的遭遇社会名']
{'name': '象人', 'desc': '象人(约翰•赫特 John Hurt 饰)是一个天生的畸形症患者,他的脸长得就像大象的脸,因此而得名象人一直被利欲昏心的马戏团老板利用,带到世界各地去巡回演出,受尽了非人的虐待。象人所经受
的遭遇社会名'}


……

 

 

 

解决redis中文显示乱码

第一步,打开命令窗口,如果我们要修改成UTF8编码,输入命令

CHCP 65001

 

 查看验证

 

 设置字体

 

 登录redis客户端

C:\redis64>redis-cli --raw
127.0.0.1:6379> keys *
fbs:items
age
names
urls
fbs:requests
movieData
fbs:dupefilter
name
127.0.0.1:6379> lrange movieData 0 2
{'name': '飞虎', 'desc': '米妮(梁咏琪 饰)是海关督察,近日里,她获得消息,得知大量毒品即将抵达香港,于是决心调查此案,然而却遭到了毒贩
冰后”强大的火力抵抗,败下阵来飞虎队队长王东(王敏德 饰)带领队员们进驻海关,王东更是坦'}
{'name': '恶魔湾', 'desc': 'An interracial lesbian couple commit a murder and have
to flee for their lives.'}
{'name': '象人', 'desc': '象人(约翰•赫特 John Hurt 饰)是一个天生的畸形症患者,他的脸长得就像大象的脸,因此而得名象人一直被
欲昏心的马戏团老板利用,带到世界各地去巡回演出,受尽了非人的虐待。象人所经受的遭遇社会名'}
127.0.0.1:6379>

 

posted @ 2020-04-09 14:34  一只小小的寄居蟹  阅读(1704)  评论(0编辑  收藏  举报