Python爬虫之Scrapy框架系列(25)——分布式爬虫scrapy_redis完整实战【ZH小说爬取】

本文主要是介绍Python爬虫之Scrapy框架系列(25)——分布式爬虫scrapy_redis完整实战【ZH小说爬取】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本篇文章要做的是:将之前做的使用Scrapy中Crawl模板爬取纵横小说的项目改编为使用Scrapy_redis的项目!!!

目录:

  • 每篇前言:
  • 1.首先,将之前的项目改为单个的使用scrapy\_redis的分布式爬虫项目。
    • 第一步:settings.py进行如下配置!
    • 第二步:爬虫文件中进行如下修改!
    • 最后,运行观察!
    • 小拓展:如何使用Navicat工具清空Mysql数据库中数据表里的数据!
  • 2.然后,将项目改为完整的scrapy-redis分布式爬虫项目

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 🔥🔥本文已收录于Scrapy框架从入门到实战专栏:《Scrapy框架从入门到实战》
  • 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
  • 📝​📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
  • 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

在这里插入图片描述

1.首先,将之前的项目改为单个的使用scrapy_redis的分布式爬虫项目。

  • (如果运行OK,再直接复制一个进行少量更改即可实现分布式!)

第一步:settings.py进行如下配置!

# 日志写入.log文件,方便观察终端!
LOG_FILE="zh.log"
LOG_ENABLED=False# 第一步:加入以下代码:
#设置scrapy-redis
#1.启用调度将请求存储进redis
from scrapy_redis.scheduler import Scheduler
SCHEDULER="scrapy_redis.scheduler.Scheduler"#2.确保所有spider通过redis共享相同的重复过滤
from scrapy_redis.dupefilter import RFPDupeFilter
DUPEFILTER_CLASS="scrapy_redis.dupefilter.RFPDupeFilter"#3.指定连接到Redis时要使用的主机和端口     目的是连接上redis数据库
REDIS_HOST="localhost"
REDIS_PORT=6379# 不清理redis队列,允许暂停/恢复抓取    (可选)    允许暂停,redis数据不丢失     可以实现断点续爬!!!
SCHEDULER_PERSIST = True# 第二步:开启将数据存储进redis公共区域的管道!
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {# 开启保存Mysql数据库的管道'zongheng.pipelines.ZonghengPipeline': 300,# 开启保存数据至redis公共区域的数据库'scrapy_redis.pipelines.RedisPipeline': 100,
}

第二步:爬虫文件中进行如下修改!

在这里插入图片描述

最后,运行观察!

  1. 首先,命令运行项目,发现项目在等待。

  2. 然后,向redis数据库中放入第一个起始URL,命令为:lpush zh:start_urls http://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html

  3. 项目正常运行!可以通过Redis Desktop Manager工具观察到redis数据库中的URL数据等。
    在这里插入图片描述

  4. 运行结束后,通过Navicat工具观察到Mysql数据库中小说信息爬取正常!
    在这里插入图片描述在这里插入图片描述

小拓展:如何使用Navicat工具清空Mysql数据库中数据表里的数据!

使用truncate命令的原因是:删除速度快;而且如果再次对同一张表中写入数据,自增长key会从初始值开始!
在这里插入图片描述

2.然后,将项目改为完整的scrapy-redis分布式爬虫项目

  • 将此项目(称为项目一)再复制一个(称为项目二),并且为了便于观察,项目一的数据存入chapter和novel表中;项目二中的数据存入novel_copy和chapter表中。实质上两表结构一模一样!

因为项目二存入的表名更改了,所以要更改pipelines.py文件中的mysql语句中的表名(将所有的表名novel改为novel_copy;所有的chapter改为chapter_copy)!

  1. 但是,我们运行此分布式项目后,通过Navicat观察Mysql数据库中的数据时会发现——novel和novel_copy表中数据相加刚好为目标本数;但是,chapter和chapter_copy表会出现一个问题,比如:chapter_copy表中小说章节信息都有,然后有四章章节有具体章节内容,但是我们爬虫文件中限制的是六章章节有具体章节内容,理应chapter表中有另外两章章节的具体内容,但是观察会发现chapter表中是空的!!!

  2. 分析:
    在这里插入图片描述

  • 回想——我们之前向Mysql数据库中存入小说章节信息的思路是:先存入小说所有章节的信息(但不包括章节具体章节内容信息),注意是一次存入所有章节信息;然后:
    在这里插入图片描述

  • 存入章节具体章节信息的思路是:对应小说的章节URL(chapter_url)进行存储。即:先查询到表中有这个chapter_url,才会update其对应的章节具体章节内容!

  • 但是小说所有章节信息是一次性插入,即会出现一张表有一张表没有的现象!所以,会出现上述问题!!!(但是实质上,我们实现了分布式,缺具体章节内容的其实被另一个项目处理了,只是没能存储进数据库!)

  1. 那么,如何获取完整的数据呢?我们可以想到,在settings.py中开启了将所有数据都放入redis数据库中公共区域的管道!但是,redis是个内存数据库,数据不能持久化,这里就想到了将redis数据库中的数据搬运到Mysql数据库中,即可!!!
    ①首先,从Redsi中取出数据试试可不可以:

创建一个.py脚本文件即可:

import  redis
import pymysql
import json#指定redis数据库信息
rediscli=redis.StrictRedis(host="localhost",port=6379,db=0)#指定mysql数据库
mysqlconn=pymysql.connect(host="localhost",port=3306,user="root",password="123456",db="",charset="utf8")#取出数据
source, data = rediscli.blpop(["bh3:items"])     # 数据是字节码格式
print(source, data)
item = json.loads(data)
print(item)

打印观察数据:
在这里插入图片描述

②从Redsi中取出数据完全OK,接下来就进行存储进Mysql数据库的操作!(注意:Redis这个公共区域空间存储了框架运行过程中爬取的所有数据,所以进行Mysql存储操作时要进行判断,所取出的那一条数据属于什么数据,是小说信息;章节信息还是章节具体内容信息)

import datetime
import  redis
import pymysql
import json#指定redis数据库信息
rediscli=redis.StrictRedis(host="localhost",port=6379,db=0)#指定mysql数据库
mysqlconn=pymysql.connect(host="localhost",port=3306,user="root",password="123456",db="spider39",charset="utf8")while  True:#取出数据source, data = rediscli.blpop(["bh3:items"])     # 数据是字节码格式# print(source, data)item = json.loads(data)# print(item)#写入数据cursor=mysqlconn.cursor()if  b"book_name" in data:sql = "select id from  novel_from_redis  where  book_name=%s  and author=%s"cursor.execute(sql, (item["book_name"], item["author"]))if  not cursor.fetchone():#写入小说数据sql="insert  into  novel_from_redis(category,book_name,author,status,book_nums,description,c_time,book_url,catalog_url)" \"values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"cursor.execute(sql,(item["category"],item["book_name"],item["author"],item["status"],item["book_nums"],item["description"],item["c_time"],item["book_url"],item["catalog_url"],))mysqlconn.commit()cursor.close()elif  b"chapter_list"  in  data:sql = "insert into  chapter_from_redis(title,ordernum,c_time,chapter_url,catalog_url)  values(%s,%s,%s,%s,%s)"data_list = []  # [(%s,%s,%s,%s,%s),(%s,%s,%s,%s,%s),(%s,%s,%s,%s,%s)]for index, chapter in enumerate(item["chapter_list"]):title = chapter[0]ordernum = index + 1c_time = chapter[2]chapter_url = chapter[3]catalog_url = chapter[4]data_list.append((title, ordernum, c_time, chapter_url, catalog_url))cursor.executemany(sql, data_list)mysqlconn.commit()cursor.close()elif  b"content"  in  data:sql = "update chapter_from_redis set  content=%s where chapter_url=%s"content = item["content"]chapter_url = item["chapter_url"]cursor.execute(sql, (content, chapter_url))mysqlconn.commit()cursor.close()

运行此.py脚本文件即可发现Mysql数据库中数据完整!!!

项目完整代码:
链接:https://pan.baidu.com/s/16-Zx5PGERxg2SgRGKStxvA
提取码:j5qh

这篇关于Python爬虫之Scrapy框架系列(25)——分布式爬虫scrapy_redis完整实战【ZH小说爬取】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/854805

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Pandas使用SQLite3实战

《Pandas使用SQLite3实战》本文主要介绍了Pandas使用SQLite3实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1 环境准备2 从 SQLite3VlfrWQzgt 读取数据到 DataFrame基础用法:读

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2