增量式爬虫

简介

1. 概念: 通过爬虫程序监测某网站数据更新的情况, 只会爬取网站中更新出来的新数据。

2. 如何进行增量式的爬取工作 ?
	- 在发送请求之前判断这个URL是不是之前爬取过
	- 在解析内容后判断这部分内容是不是之前爬取过
	- 写入存储介质时判断内容是不是已经在介质中存在
	
3. 核心: 去重
- 去重方法: 
	1) 将爬取过程中产生的url进行存储,存储在redis的set中。当下次进行数据爬取时,首先对即将要发起的请求对应的url在存储的url的set中做判断,如果存在则不进行请求,否则才进行请求。
    
	2) 对爬取到的网页内容进行唯一标识的制定,然后将该唯一表示存储至redis的set中。当下次爬取到网页数据的时候,在进行持久化存储之前,首先可以先判断该数据的唯一标识在redis的set中是否存在,在决定是否进行持久化存储。

示例

爬取www.4567tv.tv电影网

# 爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from redis import Redis
from MoviePro.items import MovieproItem

class MovieSpider(CrawlSpider):
    # 建立连接redis
    conn = Redis(host='127.0.0.1', port=6379)
    name = 'movie'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.4567tv.tv/frim/index1.html']
    
	link = LinkExtractor(allow=r'/frim/index1-\d+\.html')
    rules = (
        Rule(link, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        li_list = response.xpath('//div[@class="stui-pannel_bd"]/ul/li')
        for li in li_list:
            # 解析详情页的url
            detail_url= 'https://www.4567tv.tv'+li.xpath('./div/a/@href').extract_first()
            # redis集合特性,当已经存在值, 就返回一个0, 不存在就存储并返回1
            ex = self.conn.sadd('movie_urls', detail_url)
            if ex == 1:
                print('有新的数据可以存储......')
                yield scrapy.Request(url=detail_url, callback=self.parse_detail)
            else:
                print("暂无数据可爬取 !")

    def parse_detail(self, response):
            name = response.xpath('//div[2]/h1/text()').extract_first()
            types = response.xpath('//div/div[2]/p[1]/a[1]/text()').extract_first()
            item = MovieproItem()
            item['name'] = name
            item['types'] = types

            yield item
# items文件
import scrapy

class MovieproItem(scrapy.Item):
    name = scrapy.Field()
    types = scrapy.Field()
# 管道持久化存储
import json

class MovieproPipeline(object):
    def process_item(self, item, spider):
        conn = spider.conn
        dic = {
            "name": item["name"],
            "types": item["types"]
        }
        conn.lpush("movie_data", json.dumps(dic))
        return item

爬取糗事百科

# 爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from redis import Redis
from QiuPro.items import QiuproItem
import hashlib

class QiutuSpider(scrapy.Spider):
    conn = Redis(host='127.0.0.1', port=6379)
    name = 'qiutu'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.qiushibaike.com/text/']

    def parse(self, response):
        div_list = response.xpath('//div[@id="content-left"]/div')
        for div in div_list:
            # 爬取数据: 爬取到一条数据的建立唯一标识
            author = div.xpath('./div/a[2]/h2/text() | ./div/span[2]/h2/text()').extract_first()
            content = div.xpath('./a/div/span//text()').extract()
            content = "".join(content)

            item = QiuproItem()
            item["author"] = author
            item['content'] = content

            # 利用hashlib加密创建数据指纹
            data = author + content
            hash_key = hashlib.sha256(data.encode()).hexdigest()
            ex = self.conn.sadd('hash_keys', hash_key)
            if ex == 1:
                print('有数据更新......')
                yield item
            else:
                print("无数据更新 !")
# item文件
import scrapy

class QiuproItem(scrapy.Item):
    author = scrapy.Field()
    content = scrapy.Field()
posted @ 2019-06-27 10:22  言值  阅读(314)  评论(0编辑  收藏  举报