增量式爬虫

增量式爬虫–转载

18.增量式爬虫

增量式爬虫

引言:

​ 当我们在浏览相关网页的时候会发现,某些网站定时会在原有网页数据的基础上更新一批数据,例如某电影网站会实时更新一批最近热门的电影。小说网站会根据作者创作的进度实时更新最新的章节数据等等。那么,类似的情景,当我们在爬虫的过程中遇到时,我们是不是需要定时更新程序以便能爬取到网站中最近更新的数据呢?

一.增量式爬虫

概念:通过爬虫程序监测某网站数据更新的情况,以便可以爬取到该网站更新出的新数据。

如何进行增量式的爬取工作:

在发送请求之前判断这个URL是不是之前爬取过

在解析内容后判断这部分内容是不是之前爬取过

写入存储介质时判断内容是不是已经在介质中存在

分析:

​ 不难发现,其实增量爬取的核心是去重, 至于去重的操作在哪个步骤起作用,只能说各有利弊。在我看来,前两种思路需要根据实际情况取一个(也可能都用)。第一种思路适合不断有新页面出现的网站,比如说小说的新章节,每天的最新新闻等等;第二种思路则适合页面内容会更新的网站。第三个思路是相当于是最后的一道防线。这样做可以最大程度上达到去重的目的。

去重方法

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

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

二.项目案例

- 需求:爬取4567tv网站中所有的电影详情数据。

爬虫文件:

# -- coding: utf-8 --

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

管道文件:

# -- coding: utf-8 --

# Define your item pipelines here

#

# Don't forget to add your pipeline to the ITEM_PIPELINES setting

# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

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

- 需求:爬取糗事百科中的段子和作者数据。

爬虫文件:

# -- coding: utf-8 --

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('该条数据已经爬取过了,不需要再次爬取了!!!')

管道文件:

# -- coding: utf-8 --

# Define your item pipelines here

#

# Don't forget to add your pipeline to the ITEM_PIPELINES setting

# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容