scrapy分布式浅谈+京东示例:

学习目标:

  1. 分布式概念与使用场景

  2. 浅谈去重

  3. 浅谈断点续爬

  4. 分布式爬虫编写流程

  5. 基于scrapy_redis的分布式爬虫(阳关院务与京东图书案例)

环境准备:

  1. 下载redis-cli(客户端)以及redis-server(服务端)

  2. 安装Another Redis Desktop Manager可视化工具

  3. 链接:https://pan.baidu.com/s/1rl8IUY7Lq54aePT54LnAkQ 提取码:1234

  4. scrapy-redis源码:git clone https://github.com/rolando/scrapy-redis.git

分布式概念与使用场景:

  1. 分布式听起来很高大上,但是它只是提高爬虫功能与运行效率的一个环节,

  2. 当你的数据是海量的时候,或者老板叫你在短时间内获得大量的数据,这时候才是分布式出场的时候,然而当你使用分布式的时候,难点不在于怎么部署以及编写代码;

  3. 爬虫的速度越快,所造成对方的服务器负担越重,这时候反爬才是你所真正考虑以及应对的。

  4. 概念:需要搭建一个分布式机群,然后再机群的每一台电脑中执行同一组程序,让对某一个网站的数据进行联合分布爬取

浅谈去重:

  1. 好处:能够减少服务器的压力以及保证数据的准确性;

  2. 每核心次请求的时候,先判断这个请求是否在已经爬取的队列当中,存在舍去,不存在爬取;

  3. 采用scrapy-redis中的set集合做的去重(可做持久化存储)。

浅谈断点续爬:

  1. 如果运行爬虫down掉了,在下一次启动的时候可以接入上次end的位置继续。

  2. 断点续爬就是将数据队列 集合以及任务队列实现本地持久化存储

分布式爬虫编写流程:

  1. 编写普通scrapy爬虫

    • 创建项目

    • 明确目标

    • 创建爬虫(普通scrapy爬虫以及crawlSpider爬虫)

    • 保存内容

  2. 改造分布式爬虫

    • 导入scrapy-redis中的分布式爬虫类

    • 继承类

    • 注销start_url & allowed-domains

    • 设置redis_key获取start_urls

    • 设置__init__获取允许的域

  3. 改造settings文件

    • copy配置文件(配置如下)

    •  
       #所有的JDspider---换成自己的爬虫名称
      SPIDER_MODULES = ['JDspider.spiders']
      NEWSPIDER_MODULE = 'JDspider.spiders'

      USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 Edg/84.0.522.40'

      # 设置重复过滤器的模块
      DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
      # 设置调取器,scrap_redis中的调度器具备与数据库交互的功能
      SCHEDULER = "scrapy_redis.scheduler.Scheduler"
      # 设置当爬虫结束的时候是否保持redis数据库中的去重集合与任务队列,程序结束后不清空redis数据库
      SCHEDULER_PERSIST = True
      #SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
      #SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
      #SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"

      ITEM_PIPELINES = {
      # 'JD.pipelines.ExamplePipeline': 300,
      # 当开启该管道,该管道将会把数据存到Redis数据库中,也可以自己设置数据库
      'scrapy_redis.pipelines.RedisPipeline': 400,
      }
      # 设置redis数据库
      REDIS_URL = "redis://127.0.0.1:6379"

      # LOG_LEVEL = 'DEBUG'

      # Introduce an artifical delay to make use of parallelism. to speed up the
      # crawl.
      #请求间隔时长
      DOWNLOAD_DELAY = 1

阳光院务平台scrapy-redis-Crawlspider:

编写Spider:基本代码很好理解就没写注释

 
 import scrapy
from sunsite.items import SunsiteItem

class SunproSpider(scrapy.Spider):
name = 'sunpro'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']

def parse(self, response):
li_list = response.xpath("/html/body/div[2]/div[3]/ul[2]//li")
for li in li_list:
item = SunsiteItem()
item['title'] = li.xpath("./span[3]/a/text()").extract_first()
status= li.xpath("./span[2]/text()").extract_first().split('\n ')[1]

item['status'] = status.split("\n ")[0]
# print(item)
yield item

编写CrawlSpider:

 
 import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from sunsite.items import SunsiteItem
from scrapy_redis.spiders import RedisCrawlSpider

class SunprocrawlSpider(RedisCrawlSpider):
name = 'Sunprocrawl'
# allowed_domains = ['www.xxx.com']
# start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']
redis_key = 'sunurl'
rules = (
Rule(LinkExtractor(allow=r'id=1&page=\d+'), callback='parse_item', follow=True),
)

def parse_item(self, response):
li_list = response.xpath("/html/body/div[2]/div[3]/ul[2]//li")
for li in li_list:
item = SunsiteItem()
item['title'] = li.xpath("./span[3]/a/text()").extract_first()
status = li.xpath("./span[2]/text()").extract_first().split('\n ')[1]

item['status'] = status.split("\n ")[0]
# print(item)
yield item

item编写:

 import scrapy


class SunsiteItem(scrapy.Item):
title = scrapy.Field()
status = scrapy.Field()

京东图书scrapy-redis:

JDSpider:(基础代码在Github中)

 # -*- coding: utf-8 -*-
#该spider在基础spider上进行分布式修改
import scrapy
from JDspider.items import JdspiderItem
import json
#-----1导入分布式爬虫类
from scrapy_redis.spiders import RedisSpider

class JdproSpider(RedisSpider): #----2继承RedisSpider类方法
name = 'JDpro'
# start_urls = ['https://book.jd.com/booksort.html']
# ----4 设置redis-key
redis_key = 'tranurl'

# ----5 设置__init__
def __init__(self, *args, **kwargs):
domain = kwargs.pop('domain', '')
self.allowed_domains = list(filter(None, domain.split(',')))
super(JdproSpider, self).__init__(*args, **kwargs)

def parse(self, response):
#获取图书大分类中的列表
big_node_list = response.xpath("//div[@class='mc']//dt/a")

# 【:1】切片,先获取一类数据测试
# for big_node in big_node_list[:1]:
for big_node in big_node_list:
#大分类的名称
big_category = big_node.xpath("./text()").extract_first()
#大分类的URL
big_category_link = response.urljoin(big_node.xpath("./@href").extract_first())
# print(big_category, big_category_link)
# 获取所有图书小分类节点列表
#注意点---获取兄弟节点的xpath语法结构;小分类的整体节点
small_node_list = big_node.xpath("../following-sibling::dd[1]/em/a")
#【:1】切片,先获取一类数据测试
for small_node in small_node_list[:1]:
temp = {}
temp['big_category'] = big_category
temp['big_category_link'] = big_category_link
#获取小分类的名称
temp['small_category'] = small_node.xpath("./text()").extract_first()
#获取小分类的URL
temp['small_category_link'] = response.urljoin(small_node.xpath("./@href").extract_first())
# print(temp)
#注意点,筛选出来的数据持续传输,meta的使用
yield scrapy.Request(
url=temp['small_category_link'],
callback= self.parse_book_link,
#上面保存的item传递给下一个解析函数
meta = {'data':temp}
)

#解析详情
def parse_book_link(self,response):
temp = response.meta['data']

#获取到Book的标签
book_list = response.xpath("//*[@id='J_goodsList']/ul/li/div")
# print(len(book_list))
#遍历标签页
for book in book_list:
item = JdspiderItem()

item['big_category'] = temp['big_category']
item['big_category_link'] = temp['big_category_link']
item['small_category'] = temp['small_category']
item['small_category_link'] = temp['small_category_link']
#书的名字
item['bookname'] = book.xpath('./div[3]/a/em/text()|./div/div[2]/div[2]/div[3]/a/em/text()').extract_first()
#书的作者
item['author'] = book.xpath('./div[4]/span[1]/a/text()|./div/div[2]/div[2]/div[4]/span[1]/span[1]/a/text()').extract_first()
#书的URL
item['link'] = response.urljoin(book.xpath('./div[1]/a/@href|./div/div[2]/div[2]/div[1]/a/@href').extract_first())
# print(item)
# 获取图书编号,目的拼接图书的Price
skuid = book.xpath('.//@data-sku').extract_first()
# skuid = book.xpath('./@data-sku').extract_first()
# print("skuid:",skuid)
# 拼接图书价格地址
pri_url = 'https://p.3.cn/prices/mgets?skuIds=J_' + skuid
# print(pri_url)

yield scrapy.Request(url=pri_url, callback=self.parse_price, meta={'meta_1': item})
#拿到一条数据测试,可以开启
# break
def parse_price(self,response):
#拿到传递过来的item
item = response.meta['meta_1']
#解析json页面
dict_data = json.loads(response.body)
#解析价钱,传递到item中
item['price'] = dict_data[0]['p']
# print(item)
yield item

程序运行方式:

  1. 打开redis-server.exe

  2. 打开redis-cli.exe

  3. 找到爬虫文件下的spider

  4. scrapy runspider spiderName

  5. 在redis-cli中输入:lpush redis-keyName(spider中定义的redis-key名字) URL(网页的链接)

实现效果:

完整项目代码:

Github:https://github.com/xbhog/scrapyRedis

致谢:如果对您有帮助,希望随手一个star,感谢!!

scrapy分布式浅谈+京东示例的更多相关文章

  1. 视频课程 | 云原生下的Serverless浅谈

    京东云开发者社区在3月底于北京举行了以"Cloud Native时代的应用之路与开源创新"为主题的技术沙龙,现场多位技术大咖与开发者们面对面就Cloud Native进行了深入交流 ...

  2. 基于puppet分布式集群管理公有云多租户的架构浅谈

    基于puppet分布式集群管理公有云多租户的架构浅谈 一.架构介绍   在此架构中,每个租户的业务集群部署一台puppet-master作为自己所在业务集群的puppet的主服务器,在每个业务集群所拥 ...

  3. 【转】浅谈分布式服务协调技术 Zookeeper

    非常好介绍Zookeeper的文章, Google的三篇论文影响了很多很多人,也影响了很多很多系统.这三篇论文一直是分布式领域传阅的经典.根据MapReduce,于是我们有了Hadoop:根据GFS, ...

  4. 浅谈分布式消息技术 Kafka(转)

    一只神秘的程序猿. Kafka的基本介绍 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可 ...

  5. 浅谈分布式消息技术 Kafka

    Kafka的基本介绍Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/ngin ...

  6. 搞懂分布式技术21:浅谈分布式消息技术 Kafka

    搞懂分布式技术21:浅谈分布式消息技术 Kafka 浅谈分布式消息技术 Kafka 本文主要介绍了这几部分内容: 1基本介绍和架构概览 2kafka事务传输的特点 3kafka的消息存储格式:topi ...

  7. 示例浅谈PHP与手机APP开发,即API接口开发

    示例浅谈PHP与手机APP开发,即API接口开发 API(Application Programming Interface,应用程序接口)架构,已经成为目前互联网产品开发中常见的软件架构模式,并且诞 ...

  8. 五分钟DBA:浅谈伪分布式数据库架构

    [IT168 技术]12月25日消息,2010互联网行业技术研讨峰会今日在上海华东理工大学召开.本次峰会以“互联网行业应用最佳实践”为主题,定位于互联网架构设计.应用开发.应用运维管理,同时,峰会邀请 ...

  9. [转帖]浅谈分布式一致性与CAP/BASE/ACID理论

    浅谈分布式一致性与CAP/BASE/ACID理论 https://www.cnblogs.com/zhang-qc/p/6783657.html ##转载请注明 CAP理论(98年秋提出,99年正式发 ...

随机推荐

  1. Python实用笔记 (27)面向对象高级编程——使用枚举类

    枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例.Python提供了Enum类来实现这个功能: from enum import Enum Month = Enum('Mon ...

  2. caffe的python接口学习(3)训练模型training

    如果不进行可视化,只想得到一个最终的训练model, 那么代码非常简单,如下 : import caffe caffe.set_device(0) caffe.set_mode_gpu() solve ...

  3. Java BigDecimal和double BigDecimal类

    BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数 ...

  4. JavaScript基础避免隐式的类型转换(004)

    JavaScript在普通对比运算符“==”执行时可能会进行隐式的类型转换.比如:false==0和""==0的结果都是true.同理也适合于"!="运算符.要 ...

  5. 深入理解JavaScript系列(2):揭秘命名函数表达式(转)

    前言 网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨JavaScript关于命名函数表达式的优缺点. 简 单的说,命名函数 ...

  6. JQuery 优缺点略谈

    1.jQuery实现脚本与页面的分离 ; 2.最少的代码做最多的事情; 3.性能; 在大型JavaScript框架中,jQuery对性能的理解最好.尽管不同版本拥有众多新功能,其最精简版本只有18KB ...

  7. Windows7 PowerShell 2.0升级到 PowerShell 5.1

    Windows7 sp1内置的PowerShell的版本是v2.0,现需要将其升级到v5.1,过程中有一个环节需要引起注意,为了以后查阅的方便,现将其记录下来. 1 查看PowerShell版本 Wi ...

  8. sql多列排序

    从左到右依次排列,如果出现重复值,则按照右侧的排序规则进行排序: 例如:分数倒序排序,但是遇到重复值,则再按照class_id倒序排 例如:分数倒序排序,没有重复值,进行了正常的排序,则不再按照cla ...

  9. 如何使用SVG及其动画技术为你的 Web 前端开发带来一些新鲜的体验

    任何有开发经验的前端工程师都会考虑到不成体系的设备生态所带来的挑战.设备间不同的屏幕尺寸.分辨率和比例使得产品难以提供一致的体验,对于那些对产品有着像素级完美追求的人这种体验差异尤其显著! SVG(可 ...

  10. 云小课 | “VPC连接”知多少

    摘要:华为云提供了丰富的网络服务,可满足多种网络互连场景. 同Region的两个VPC怎么连通?” “跨Region的两个VPC又怎么连通?” “VPC内的ECS搭建了一个应用,需要访问Interne ...