爬虫篇 ---增量式爬虫

Posted crazysheldon1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬虫篇 ---增量式爬虫相关的知识,希望对你有一定的参考价值。

What is 增量式爬虫?

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

增量式爬虫的核心

  去重,因为你爬取到的数据是不可以出现重复的

怎么进行增量式爬取呢?

  • 在发送请求之前判断这个URL是不是之前爬取过
  • 在解析内容后判断这部分内容是不是之前爬取过
  • 写入存储到 redis 时判断内容是不是已经在介质中存在
    #总结分析
        对比三种方式增量爬取的核心是去重, 至于去重的操作在哪个步骤起作用,只能说各有利弊。在我看来,前两种思路需要根据实际情况取一个(也可能都用)。
    
    #第一种思路适合不断有新页面出现的网站,比如说小说的新章节,每天的最新新闻等等;
    #第二种思路则适合页面内容会更新的网站。
    #第三个思路是相当于是最后的一道防线。这样做可以最大程度上达到去重的目的。

去重方法

1. 将爬取过程中产生的url进行存储,存储在redis的set中。当下次进行数据爬取时,首先对即将要发起的请求对应的url在存储的url的set中做判断,如果存在则不进行请求,否则才进行请求。

2. 对爬取到的网页内容进行唯一标识的制定,然后将该唯一表示存储至redis的set中。当下次爬取到网页数据的时候,在进行持久化存储之前,首先可以先判断该数据的唯一标识在redis的set中是否存在,在决定是否进行持久化存储。

项目实例

demo1 爬取4567tv网站中所有的电影详情数据

spider.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

from redis import Redis
from incrementPro.items import IncrementproItem
class MovieSpider(CrawlSpider):
    name = movie
    # allowed_domains = [‘www.xxx.com‘]
    start_urls = [http://www.4567tv.tv/frim/index7-11.html]

    rules = (
        Rule(LinkExtractor(allow=r/frim/index7-\d+\.html), callback=parse_item, follow=True),
    )
    #创建redis链接对象
    conn = Redis(host=127.0.0.1,port=6379)
    def parse_item(self, response):
        li_list = response.xpath(//li[@class="p1 m1"])
        for li in li_list:
            #获取详情页的url
            detail_url = http://www.4567tv.tv+li.xpath(./a/@href).extract_first()
            #将详情页的url存入redis的set中
            ex = self.conn.sadd(urls,detail_url)
            if ex == 1:
                print(该url没有被爬取过,可以进行数据的爬取)
                yield scrapy.Request(url=detail_url,callback=self.parst_detail)
            else:
                print(数据还没有更新,暂无新数据可爬取!)

    #解析详情页中的电影名称和类型,进行持久化存储
    def parst_detail(self,response):
        item = IncrementproItem()
        item[name] = response.xpath(//dt[@class="name"]/text()).extract_first()
        item[kind] = response.xpath(//div[@class="ct-c"]/dl/dt[4]//text()).extract()
        item[kind] = ‘‘.join(item[kind])
        yield item

pipeline.py

from redis import Redis
class IncrementproPipeline(object):
    conn = None
    def open_spider(self,spider):
        self.conn = Redis(host=127.0.0.1,port=6379)
    def process_item(self, item, spider):
        dic = {
            name:item[name],
            kind:item[kind]
        }
        print(dic)
        self.conn.lpush(movieData,dic)
        return item

demo2 爬取糗事百科中的段子和作者数据。

spider.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from incrementByDataPro.items import IncrementbydataproItem
from redis import Redis
import hashlib
class QiubaiSpider(CrawlSpider):
    name = qiubai
    # allowed_domains = [‘www.xxx.com‘]
    start_urls = [https://www.qiushibaike.com/text/]

    rules = (
        Rule(LinkExtractor(allow=r/text/page/\d+/), callback=parse_item, follow=True),
        Rule(LinkExtractor(allow=r/text/$), callback=parse_item, follow=True),
    )
    #创建redis链接对象
    conn = Redis(host=127.0.0.1,port=6379)
    def parse_item(self, response):
        div_list = response.xpath(//div[@id="content-left"]/div)

        for div in div_list:
            item = IncrementbydataproItem()
            item[author] = div.xpath(./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()).extract_first()
            item[content] = div.xpath(.//div[@class="content"]/span/text()).extract_first()

            #将解析到的数据值生成一个唯一的标识进行redis存储
            source = item[author]+item[content]
            source_id = hashlib.sha256(source.encode()).hexdigest()
            #将解析内容的唯一表示存储到redis的data_id中
            ex = self.conn.sadd(data_id,source_id)

            if ex == 1:
                print(该条数据没有爬取过,可以爬取......)
                yield item
            else:
                print(该条数据已经爬取过了,不需要再次爬取了!!!)


pipeline.py

from redis import Redis
class IncrementbydataproPipeline(object):
    conn = None

    def open_spider(self, spider):
        self.conn = Redis(host=127.0.0.1, port=6379)

    def process_item(self, item, spider):
        dic = {
            author: item[author],
            content: item[content]
        }
        # print(dic)
        self.conn.lpush(qiubaiData, dic)
        return item

 

以上是关于爬虫篇 ---增量式爬虫的主要内容,如果未能解决你的问题,请参考以下文章

大学本科4年总结---4年残念(学习篇,工作篇,保研篇,生活篇,遗憾篇,畅想篇)

QT学习之路

这200道java大厂面试题全部掌握,“面试”想去哪就去哪

WDA-文档-基础篇/进阶篇/讨论篇

第一篇随笔 - Hello world!

性能优化篇)