简介
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()