网站建设客户需求分析调研表,潮州网络推广,山东做网站三五,百姓网二手房目录 一、背景1、数据库的发展历史2、NoSQL 和 SQL 数据库的比较 二、Redis1、特性2、作用3、应用场景4、用法5、安装及启动6、Redis 数据库简单使用7、Redis 常用五大数据类型7.1 Redis-String7.2 Redis-List (单值多value)7.3 Redis-Hash7.4 Redis-Set (不重复的)7.5 Redis-Z… 目录 一、背景1、数据库的发展历史2、NoSQL 和 SQL 数据库的比较 二、Redis1、特性2、作用3、应用场景4、用法5、安装及启动6、Redis 数据库简单使用7、Redis 常用五大数据类型7.1 Redis-String7.2 Redis-List (单值多value)7.3 Redis-Hash7.4 Redis-Set (不重复的)7.5 Redis-Zset (有序集合) 8、Python 操作 Redis8.1、安装8.2、导入 Redis 模块和创建连接8.3、字符串相关操作8.4、列表相关操作8.5、集合相关操作8.6、哈希相关操作8.7、有序集合相关操作8.8、连接 Redis 数据库 三、Scrapy-分布式1、启动 Redis2、Scrapy-Redis 简介3、Scrapy 工作流程4、Scrapy-Redis 工作流程5、github 示例代码6、Scrapy-Redis 中的 settings 文件7、Scrapy-Redis 运行 四、案例1、页面分析2、使用 Scrapy 框架实现3、改写成 Scrapy-Redis4、改写分布式总结 一、背景
随着互联网大数据时代的来临传统的关系型数据库已经不能满足中大型网站日益增长的访问量和数据量。这个时候就需要⼀种能够快速存取数据的组件来缓解数据库服务 I/O 的压力来解决系统性能上的瓶颈。
1、数据库的发展历史
1、在互联网大数据时代来临之前企业的一些内部信息管理系统一个单个数据库实例就能满足系统的需求。
2、随着系统访问用户的增多数据量的增大单个数据库实例已经无法满足系统的读取需求采用缓存memcache单数据库实例。
3、缓存可以缓解系统的读取压力但是数据量的写入压力持续增大使用缓存主从数据库读写分离。
4、数据量再次增大读写分离以后主数据库的写库压力出现瓶颈使用缓存主从数据库集群读写分离分库分表。
5、互联网大数据时代来临关系型数据库不能很好地存取一些并发性高、实时性高并且数据格式不固定的数据采用 NoSQL 主从数据库集群读写分离分库分表。
2、NoSQL 和 SQL 数据库的比较
1、适用场景不同SQL 数据库适合用于关系特别复杂的数据查询场景NoSQL 则相反。
2、事务SQL 对事务的支持非常完善而 NoSQL 基本不支持事务。
3、两者在不断的取长补短。
二、Redis
是⼀个高性能的开源的C 语言开发的键值对存储数据的 nosqlnot only sql泛指非关系型数据库 数据库。
点击阅读官方文档
1、特性
Redis 支持数据的持久化可以将内存中的数据保存在磁盘中重启的时候可以再次加载进行使用。
Redis 不仅仅支持简单的 key-value 类型的数据同时还提供 List、Set 等数据类型。
Redis 支持数据的备份。
2、作用
快速存取。
3、应用场景
点赞、秒杀、直播平台的在线好友列表、商品排行榜等。
4、用法
官方地址https://redis.io/
命令地址http://doc.redisfans.com/
5、安装及启动
查看帮助命令 redis-server --help 启动服务 redis-server.exe 连接客户端 redis-cli.exe 6、Redis 数据库简单使用 DBSIZE 查看当前数据库的 key 数量 KEYS * 查看所有 key 的内容 FLUSHDB 清空当前数据库的所有 key FLUSHALL 清空所有库的所有 key谨慎使用 EXISTS key 判断 key 是否存在 7、Redis 常用五大数据类型
7.1 Redis-String
Redis 中的 String 是最基本的数据类型一个 key 对应一个 value。String 可以包含任何数据但最大不能超过 512M。
常用操作
SET设置值GET获取值MSET设置多个值MGET获取多个值APPEND添加字段DEL删除STRLEN返回字符串长度
数值操作
INCR增加DECR减少INCRBY指定增加多少DECRBY指定减少多少
范围操作
GETRANGE获取指定区间范围内的值类似 SQL 中的 BETWEEN … AND …SETRANGE从指定位置开始替换索引从 0 开始从 0 到 -1 表示全部
7.2 Redis-List (单值多value)
Redis 的 List 类型是一个简单的字符串列表按照插入顺序排序可以在列表的头部左边或尾部右边添加元素。它的底层实际上是一个链表。
常用操作
LPUSH/RPUSH/LRANGE从左/从右/获取指定长度LPOP/RPOP移除最左/最右的元素LINDEX按照索引下标获取元素LLEN求列表长度LREM删除指定数量的元素LTRIM截取指定范围的值RPOPLPUSH将最后一个元素从一个列表弹出并推入另一个列表的头部LSET设置指定位置的元素值LINSERT在指定元素前或后插入新元素
7.3 Redis-Hash
Redis 的 Hash 是一种键值对集合。它是一个字符串类型的字段和值的映射表特别适合存储对象。
常用操作
HSET/HGET/HMSET/HMGET/HGETALL/HDEL设值/取值/设值多个值/取多个值/取全部值/删除值HLEN求哈希长度HEXISTS检查某个值是否存在HKEYS/HVALS获取所有字段名/获取所有字段值
7.4 Redis-Set (不重复的)
Redis 的 Set 类型是一个无序集合存储的值是唯一的。
常用操作
SADD/SMEMBERS/SISMEMBER添加/查看集合/查看是否存在SCARD获取集合里的元素个数SREM删除集合中的元素SPOP随机移除集合中的一个元素SMOVE将一个元素从一个集合移到另一个集合SDIFF/SINTER/SUNION求差集/交集/并集
7.5 Redis-Zset (有序集合)
Redis 的 Zset 是一种有序集合每个元素都关联着一个分数根据分数的排名来排序。
常用操作
ZADD/ZRANGE添加元素/获取范围内的元素ZRANGEBYSCORE根据分数范围获取元素ZREM删除元素ZCARD获取有序集合的总数ZCOUNT获取分数范围内的元素个数ZRANK获取元素在有序集合中的排名
8、Python 操作 Redis
8.1、安装 pip install redis 8.2、导入 Redis 模块和创建连接
# 导入 Redis 模块
import redis# 创建一个用于字符串操作的测试类
class TestString(object):def __init__(self):# 连接 Redis 服务器self.r redis.StrictRedis(host192.168.75.130, port6379, db0)# 创建一个用于列表操作的测试类
class TestList(object):def __init__(self):# 连接 Redis 服务器self.r redis.StrictRedis(host192.168.75.130, port6379)# 创建一个用于集合操作的测试类
class TestSet(object):def __init__(self):# 连接 Redis 服务器self.r redis.StrictRedis(host192.168.75.130, port6379)# 创建一个用于哈希操作的测试类
class TestHash(object):def __init__(self):# 连接 Redis 服务器self.r redis.StrictRedis(host192.168.75.130, port6379)8.3、字符串相关操作
# 设置值
def test_set(self):res self.r.set(user1, juran-1) # 设置 key user1 的值为 juran-1print(res)# 取值
def test_get(self):res self.r.get(user1) # 获取 key user1 的值print(res)# 设置多个值
def test_mset(self):d {user2: juran-2,user3: juran-3}res self.r.mset(d) # 批量设置多个键值对print(res)# 取多个值
def test_mget(self):l [user2, user3]res self.r.mget(l) # 批量获取多个键的值print(res)# 删除
def test_del(self):self.r.delete(user2) # 删除 key user28.4、列表相关操作
# 插入记录
def test_push(self):res self.r.lpush(common, 1) # 将元素 1 插入到列表 common 的左边res self.r.rpush(common, 2) # 将元素 2 插入到列表 common 的右边# 弹出记录
def test_pop(self):res self.r.lpop(common) # 从列表 common 的左边弹出一个元素res self.r.rpop(common) # 从列表 common 的右边弹出一个元素# 范围取值
def test_range(self):res self.r.lrange(common, 0, -1) # 获取列表 common 中的所有元素print(res)8.5、集合相关操作
# 添加数据
def test_sadd(self):res self.r.sadd(set01, 1, 2) # 向集合 set01 中添加元素 1 和 2lis [Cat, Dog]res self.r.sadd(set02, *lis) # 向集合 set02 中添加多个元素# 删除数据
def test_del(self):res self.r.srem(set01, 1) # 从集合 set01 中删除元素 1# 随机删除数据
def test_pop(self):res self.r.spop(set02) # 随机从集合 set02 中弹出一个元素8.6、哈希相关操作
# 批量设值
def test_hset(self):dic {id: 1,name: huawei}res self.r.hmset(mobile, dic) # 批量设置哈希表 mobile 的字段及对应的值# 批量取值
def test_hgetall(self):res self.r.hgetall(mobile) # 获取哈希表 mobile 中的所有字段及对应的值# 判断是否存在 存在返回1 不存在返回0
def test_hexists(self):res self.r.hexists(mobile, id) # 检查字段 id 是否存在于哈希表 mobileprint(res)8.7、有序集合相关操作
class TestSortedSet(object):def __init__(self):# 连接 Redis 服务器self.r redis.StrictRedis(host192.168.75.130, port6379)# 批量设值
def test_zadd(self):score_members {v1: 60,v2: 70,v3: 80,v4: 90,v5: 100}res self.r.zadd(zset01, score_members) # 向有序集合 zset01 添加带有分数的成员# 批量取值
def test_zrange(self):res self.r.zrange(zset01, 0, -1) # 获取有序集合 zset01 中的所有成员print(res)8.8、连接 Redis 数据库
def main():# 创建字符串操作测试类的实例test_string TestString()# 调用字符串相关操作test_string.test_set()test_string.test_get()test_string.test_mset()test_string.test_mget()test_string.test_del()# 创建列表操作测试类的实例test_list TestList()# 调用列表相关操作test_list.test_push()test_list.test_pop()test_list.test_range()# 创建集合操作测试类的实例test_set TestSet()# 调用集合相关操作test_set.test_sadd()test_set.test_del()test_set.test_pop()# 创建哈希操作测试类的实例test_hash TestHash()# 调用哈希相关操作test_hash.test_hset()test_hash.test_hgetall()test_hash.test_hexists()# 创建有序集合操作测试类的实例test_sorted_set TestSortedSet()# 调用有序集合相关操作test_sorted_set.test_zadd()test_sorted_set.test_zrange()if __name__ __main__:main()三、Scrapy-分布式
1、启动 Redis
点击下载 Redis
1、下载后解压到文件夹进入解压后的目录下在地址栏输入 cmd 后按回车。
2、启动 Redis 服务运行命令 redis-server 3、新开一个窗口启动 Redis 客户端运行命令 redis-cli 2、Scrapy-Redis 简介
Scrapy-Redis 是 Scrapy 框架的一个扩展用于实现分布式爬虫。它将 Scrapy 与 Redis 数据库集成允许多个爬虫实例共享数据并协同工作以提高爬取效率和可扩展性。
Scrapy-Redis 使用 Redis 的集合来进行 URL 的去重处理。每个爬虫实例都会在将 URL 添加到队列之前检查它是否已经存在于集合中以避免重复爬取。
查看 GitHub 源代码
3、Scrapy 工作流程 4、Scrapy-Redis 工作流程 5、github 示例代码
安装 scrapy-redis终端运行命令 pip install scrapy-redis 在 github 上拉取示例代码终端运行命令 git clone https://github.com/rolando/scrapy-redis.git 6、Scrapy-Redis 中的 settings 文件
# Scrapy settings for example project
#
# For simplicity, this file contains only the most important settings by
# default. All the other settings are documented here:
#
# http://doc.scrapy.org/topics/settings.html
#
SPIDER_MODULES [example.spiders]
NEWSPIDER_MODULE example.spiders
USER_AGENT scrapy-redis (https://github.com/rolando/scrapy-redis)
DUPEFILTER_CLASS scrapy_redis.dupefilter.RFPDupeFilter # 指定那个去重⽅法给 request 对象去重
SCHEDULER scrapy_redis.scheduler.Scheduler # 指定 Scheduler 队列
SCHEDULER_PERSIST True # 队列中的内容是否持久保存为 false 的时候在关闭 Redis 的时候清空 Redis
#SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderPriorityQueue
#SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderQueue
#SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderStack
ITEM_PIPELINES {example.pipelines.ExamplePipeline: 300,scrapy_redis.pipelines.RedisPipeline: 400, # scrapy_redis 实现的 items 保存到 Redis 的 pipeline
}
LOG_LEVEL DEBUG
# Introduce an artificial delay to make use of parallelism. to speed up the crawl.
DOWNLOAD_DELAY 17、Scrapy-Redis 运行
allowed_domains [dmoztools.net]
start_urls [http://www.dmoztools.net/]
scrapy crawl dmoz运行结束后Redis 中会多出三个键 “dmoz:requests”存放待爬取的 requests 对象。“dmoz:item”存放爬取到的信息。“dmoz:dupefilter”存放爬取的 requests 的指纹信息。 四、案例 目标网站https://www.daomubiji.com/ 需求 爬取整套小说分为1级、2级、3级页面。 将爬取内容分门别类存放在文件夹中有一个小说文件夹里面新建文件夹每一个文件夹存放每一套盗墓笔记。 小说具体内容保存为 txt 文件。 1、页面分析
1级页面获取标题以及2级页面的 URL。 1级标题‘//li[contains(id, “menu-item”)]/a/text()’ 2级 URL‘//li[contains(id, “menu-item”)]/a/href’ 2级页面获取章节标题以及3级页面的 URL。 2级标题a_lst ‘//article/a/text()’ 3级的 URLa_url ‘//article/a/href’ 3级页面获取的文本内容。 content response.xpath(‘//article/p/text()’) 2、使用 Scrapy 框架实现
1、在终端输入命令创建一个 Scrapy 框架。 scrapy startproject dmbj cd dmbj scrapy genspider dm daomubiji.com 2、修改 setting.py 文件。
# setting.py
LOG_LEVEL WARNING
# Obey robots.txt rules
ROBOTSTXT_OBEY False
# Override the default request headers:
DEFAULT_REQUEST_HEADERS {Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8,Accept-Language: en,User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36
}
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES {dmbj.pipelines.DmbjPipeline: 300,
}3、在 dmbj 文件夹下新建一个 start.py 文件。
# start.py
# 使用 cmdline 模块来执行命令行命令
from scrapy import cmdline# 使用 Scrapy 执行名为 dm 的爬虫
cmdline.execute(scrapy crawl dm.split())4、编写 spiders 文件夹下的 dm.py 文件的代码获取一级标题和二级 url。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫# 创建一个名为 DmSpider 的 Scrapy 爬虫类
class DmSpider(scrapy.Spider):name dm # 爬虫的名称allowed_domains [daomubiji.com] # 允许爬取的域名start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 一级标题first_title a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 打印一级标题和二级 urlprint(first_title, second_url)5、编写 item.py 文件的代码保存一级标题。
# item.py
import scrapy # 导入 Scrapy 库用于构建爬虫class DmbjItem(scrapy.Item):# define the fields for your item here like:# name scrapy.Field()# 一级标题first_title scrapy.Field()pass6、编写 spiders 文件夹下的 dm.py 文件的代码构造二级页面。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫
from dmbj.items import DmbjItem # 导入自定义的 Item 类# 创建一个名为 DmSpider 的 Scrapy 爬虫类
class DmSpider(scrapy.Spider):name dm # 爬虫的名称allowed_domains [daomubiji.com] # 允许爬取的域名start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 创建一个 DmbjItem 实例item DmbjItem()# 一级标题item[first_title] a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 构造二级页面使用 parse_article 方法处理yield scrapy.Request(urlsecond_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_article)# 解析二级页面def parse_article(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 三级 url章节标题a_lst response.xpath(//article/a)for a in a_lst:# 存储章节标题到 item 对象item[second_title] a.xpath(./text()).get()# 三级 urlthird_url a.xpath(./href).get()print(item)7、编写 item.py 文件的代码保存二级标题。
# item.py
import scrapy # 导入 Scrapy 库用于构建爬虫class DmbjItem(scrapy.Item):# define the fields for your item here like:# name scrapy.Field()# 一级标题first_title scrapy.Field()# 二级标题second_title scrapy.Field()pass8、编写 spiders 文件夹下的 dm.py 文件的代码获取文章内容的段落。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫
from dmbj.items import DmbjItem # 导入自定义的 Item 类# 创建一个名为 DmSpider 的 Scrapy 爬虫类
class DmSpider(scrapy.Spider):name dm # 爬虫的名称allowed_domains [daomubiji.com] # 允许爬取的域名start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 创建一个 DmbjItem 实例item DmbjItem()# 一级标题item[first_title] a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 构造二级页面使用 parse_article 方法处理yield scrapy.Request(urlsecond_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_article)# 解析二级页面def parse_article(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 三级 url章节标题a_lst response.xpath(//article/a)for a in a_lst:# 存储章节标题到 item 对象item[second_title] a.xpath(./text()).get()# 三级 urlthird_url a.xpath(./href).get()# print(item)# 向三级页面发请求yield scrapy.Request(urlthird_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_content)# 解析获取数据内容def parse_content(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 使用 XPath 选择器提取文章内容的段落content_lst response.xpath(//article[classarticle-content]/p/text()).getall()# 将段落文本连接成一个字符串并存储到 item 对象item[content] \n.join(content_lst)print(item)# 将 item 传递给下一个处理管道yield item9、编写 item.py 文件的代码保存内容。
# item.py
import scrapy # 导入 Scrapy 库用于构建爬虫class DmbjItem(scrapy.Item):# define the fields for your item here like:# name scrapy.Field()# 一级标题first_title scrapy.Field()# 二级标题second_title scrapy.Field()# 内容content scrapy.Field()pass10、创建文件夹保存获取的数据。
方式一在 spiders 文件夹下的 dm.py 文件里编写代码。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫
from dmbj.items import DmbjItem # 导入自定义的 Item 类
import re # 导入正则表达式模块
import os # 导入操作系统模块# 创建一个名为 DmSpider 的 Scrapy 爬虫类
class DmSpider(scrapy.Spider):name dm # 爬虫的名称allowed_domains [daomubiji.com] # 允许爬取的域名start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 创建一个 DmbjItem 实例item DmbjItem()# 一级标题s a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 使用正则表达式替换一级标题中的特殊字符为下划线item[first_title] re.sub(r[\\*? ], _, s)# 构造一级标题的文件夹路径dir_path r小说/{}.format(item[first_title])# 创建之前一定要做判断如果文件夹不存在则创建if not os.path.exists(dir_path):os.makedirs(dir_path)# 构造二级页面使用 parse_article 方法处理yield scrapy.Request(urlsecond_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_article)# 解析二级页面def parse_article(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 三级 url章节标题a_lst response.xpath(//article/a)for a in a_lst:# 存储章节标题到 item 对象item[second_title] a.xpath(./text()).get()# 三级 urlthird_url a.xpath(./href).get()# print(item)# 向三级页面发请求yield scrapy.Request(urlthird_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_content)# 解析获取数据内容def parse_content(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 使用 XPath 选择器提取文章内容的段落content_lst response.xpath(//article[classarticle-content]/p/text()).getall()# 将段落文本连接成一个字符串并存储到 item 对象item[content] \n.join(content_lst)print(item)# 将 item 传递给下一个处理管道yield item方式二在管道文件 pipelines.py 中创建。
# pipelines.py
import re # 导入 re 模块用于正则表达式操作# 定义 DmbjPipeline 类
class DmbjPipeline:# 处理爬取到的数据项def process_item(self, item, spider):# 构建保存小说文件的文件夹路径使用一级标题和二级标题将特殊字符替换为下划线dir_path r小说/{}/{}.format(item[first_title],re.sub(r[\\*? ], _, item[second_title]))# 构建保存小说内容的文件路径加上 .txt 后缀filename dir_path .txt# 将小说内容写入文件中使用 UTF-8 编码with open(filename, w, encodingutf-8) as f:f.write(item[content])# 返回 item 对象用于后续的处理或保存return item11、对数据做一个深拷贝处理使用 Scrapy 框架实现就完成了。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫
from dmbj.items import DmbjItem # 导入自定义的 Item 类
import re # 导入正则表达式模块
import os # 导入操作系统模块
from copy import deepcopy # 导入深拷贝函数# 创建一个名为 DmSpider 的 Scrapy 爬虫类
class DmSpider(scrapy.Spider):name dm # 爬虫的名称allowed_domains [daomubiji.com] # 允许爬取的域名start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 创建一个 DmbjItem 实例item DmbjItem()# 一级标题s a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 使用正则表达式替换一级标题中的特殊字符为下划线item[first_title] re.sub(r[\\*? ], _, s)# 构造一级标题的文件夹路径dir_path r小说/{}.format(item[first_title])# 创建之前一定要做判断如果文件夹不存在则创建if not os.path.exists(dir_path):os.makedirs(dir_path)# 构造二级页面使用 parse_article 方法处理yield scrapy.Request(urlsecond_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_article)# 解析二级页面def parse_article(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 三级 url章节标题a_lst response.xpath(//article/a)for a in a_lst:# 存储章节标题到 item 对象item[second_title] a.xpath(./text()).get()# 三级 urlthird_url a.xpath(./href).get()# print(item)# 向三级页面发请求yield scrapy.Request(urlthird_url,meta{item: deepcopy(item)}, # 将 item 传递给下一个回调函数callbackself.parse_content)# 解析获取数据内容def parse_content(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 使用 XPath 选择器提取文章内容的段落content_lst response.xpath(//article[classarticle-content]/p/text()).getall()# 将段落文本连接成一个字符串并存储到 item 对象item[content] \n.join(content_lst)print(item)# 将 item 传递给下一个处理管道yield item3、改写成 Scrapy-Redis
1、导入 Scrapy-Redis修改继承类。
# spiders/dm.py
import scrapy # 导入 Scrapy 库用于构建爬虫
from dmbj.items import DmbjItem # 导入自定义的 Item 类
import re # 导入正则表达式模块
import os # 导入操作系统模块
from copy import deepcopy # 导入深拷贝函数
from scrapy_redis.spiders import RedisSpider # 导入 Scrapy-Redis 中的 RedisSpider 类# 创建一个名为 DmSpider 的 Scrapy 爬虫类继承自 RedisSpider
class DmSpider(RedisSpider):name dm # 爬虫的名称redis_key daomu_key # 指定 Redis 的键名从中读取起始 URL# allowed_domains [daomubiji.com] # 允许爬取的域名# start_urls [http://daomubiji.com/] # 起始 URL 列表# 解析函数用于处理响应并提取数据def parse(self, response):a_list response.xpath(//li[contains(id, menu-item)]/a)for a in a_list:# 创建一个 DmbjItem 实例item DmbjItem()# 一级标题s a.xpath(./text()).get()# 二级 urlsecond_url a.xpath(./href).get()# 使用正则表达式替换一级标题中的特殊字符为下划线item[first_title] re.sub(r[\\*? ], _, s)# 构造一级标题的文件夹路径dir_path r小说/{}.format(item[first_title])# 创建之前一定要做判断如果文件夹不存在则创建if not os.path.exists(dir_path):os.makedirs(dir_path)# 构造二级页面使用 parse_article 方法处理yield scrapy.Request(urlsecond_url,meta{item: item}, # 将 item 传递给下一个回调函数callbackself.parse_article)# 解析二级页面def parse_article(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 三级 url章节标题a_lst response.xpath(//article/a)for a in a_lst:# 存储章节标题到 item 对象item[second_title] a.xpath(./text()).get()# 三级 urlthird_url a.xpath(./href).get()# print(item)# 向三级页面发请求yield scrapy.Request(urlthird_url,meta{item: deepcopy(item)}, # 将 item 传递给下一个回调函数callbackself.parse_content)# 解析获取数据内容def parse_content(self, response):# 从响应的 meta 中获取之前传递的 item 对象item response.meta.get(item)# 使用 XPath 选择器提取文章内容的段落content_lst response.xpath(//article[classarticle-content]/p/text()).getall()# 将段落文本连接成一个字符串并存储到 item 对象item[content] \n.join(content_lst)print(item)# 将 item 传递给下一个处理管道yield item2、修改 setting.py 文件。
# setting.py
# Scrapy settings for dmbj project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
# https://docs.scrapy.org/en/latest/topics/settings.html
# https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
# https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlBOT_NAME dmbj
LOG_LEVEL WARNING
SPIDER_MODULES [dmbj.spiders]
NEWSPIDER_MODULE dmbj.spiders# 设置用户代理信息
USER_AGENT scrapy-redis (https://github.com/rolando/scrapy-redis)
# 指定去重方式给请求对象去重
DUPEFILTER_CLASS scrapy_redis.dupefilter.RFPDupeFilter
# 设置调度器
SCHEDULER scrapy_redis.scheduler.Scheduler
# 队列中的内容是否进行持久保留
# True redis 关闭的时候数据会保留
# False 不会保留
SCHEDULER_PERSIST True
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderPriorityQueue
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderQueue
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderStack# LOG_LEVEL DEBUG# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
DOWNLOAD_DELAY 1# 配置 Redis 连接信息
REDIS_URL redis://127.0.0.1:6379# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT dmbj (http://www.yourdomain.com)# Obey robots.txt rules
ROBOTSTXT_OBEY False# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS 32# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN 16
#CONCURRENT_REQUESTS_PER_IP 16# Disable cookies (enabled by default)
#COOKIES_ENABLED False# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED False# Override the default request headers:
DEFAULT_REQUEST_HEADERS {Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8,Accept-Language: en,User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36
}# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES {
# dmbj.middlewares.dmbjSpiderMiddleware: 543,
#}# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES {
# dmbj.middlewares.dmbjDownloaderMiddleware: 543,
#}# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS {
# scrapy.extensions.telnet.TelnetConsole: None,
#}# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES {dmbj.pipelines.DmbjPipeline: 300,scrapy_redis.pipelines.RedisPipeline: 400, # 保存数据到 Redis 数据库
}# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED True
# The initial download delay
#AUTOTHROTTLE_START_DELAY 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG False# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED True
#HTTPCACHE_EXPIRATION_SECS 0
#HTTPCACHE_DIR httpcache
#HTTPCACHE_IGNORE_HTTP_CODES []
#HTTPCACHE_STORAGE scrapy.extensions.httpcache.FilesystemCacheStorage3、启动 Redis
进入 Redis 目录在地址栏输入 cmd 后按回车两次分别启动 Redis 服务端和 Redis 客户端。
启动 Redis 服务端运行命令 redis-server 启动 Redis 客户端运行命令 redis-cli 在 Redis 客户端输入命令 清空 flushal 查询 keys * 4、启动程序
在 Redis 客户端输入命令 lpush Redis键名 网址 lpush daomu_key http://daomubiji.com/ 在 Redis 服务端输入命令 cd 项目的绝对路径 scrapy crawl dm 可以开多个终端运行以上两条命令会同时爬取数据。
4、改写分布式总结
1、导入类修改继承类。
from scrapy_redis.spiders import RedisSpider
class DmSpider(RedisSpider):2、修改配置文件。
# 设置用户代理信息
USER_AGENT scrapy-redis (https://github.com/rolando/scrapy-redis)
# 指定去重方式给请求对象去重
DUPEFILTER_CLASS scrapy_redis.dupefilter.RFPDupeFilter
# 设置调度器
SCHEDULER scrapy_redis.scheduler.Scheduler
# 队列中的内容是否进行持久保留
# True redis 关闭的时候数据会保留
# False 不会保留
SCHEDULER_PERSIST True
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderPriorityQueue
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderQueue
# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.SpiderStack# LOG_LEVEL DEBUG# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
DOWNLOAD_DELAY 1# 配置 Redis 连接信息
REDIS_URL redis://127.0.0.1:6379# 管道
ITEM_PIPELINES {dmbj.pipelines.DmbjPipeline: 300,scrapy_redis.pipelines.RedisPipeline: 400, # 保存数据到 Redis 数据库
}3、注意爬取数据前要在 Redis 客户端输入命令。 lpush Redis键名 网址 lpush daomu_key http://daomubiji.com/ 记录学习过程欢迎讨论交流尊重原创转载请注明出处~ 文章转载自: http://www.morning.clndl.cn.gov.cn.clndl.cn http://www.morning.rxhs.cn.gov.cn.rxhs.cn http://www.morning.nrgdc.cn.gov.cn.nrgdc.cn http://www.morning.jltmb.cn.gov.cn.jltmb.cn http://www.morning.hlkxb.cn.gov.cn.hlkxb.cn http://www.morning.nxtgb.cn.gov.cn.nxtgb.cn http://www.morning.fpqsd.cn.gov.cn.fpqsd.cn http://www.morning.sfdky.cn.gov.cn.sfdky.cn http://www.morning.jjzrh.cn.gov.cn.jjzrh.cn http://www.morning.routalr.cn.gov.cn.routalr.cn http://www.morning.fldk.cn.gov.cn.fldk.cn http://www.morning.jqkjr.cn.gov.cn.jqkjr.cn http://www.morning.clpdm.cn.gov.cn.clpdm.cn http://www.morning.lsmgl.cn.gov.cn.lsmgl.cn http://www.morning.mldrd.cn.gov.cn.mldrd.cn http://www.morning.mhmsn.cn.gov.cn.mhmsn.cn http://www.morning.lmfmd.cn.gov.cn.lmfmd.cn http://www.morning.wfcqr.cn.gov.cn.wfcqr.cn http://www.morning.yrjhr.cn.gov.cn.yrjhr.cn http://www.morning.kyctc.cn.gov.cn.kyctc.cn http://www.morning.skkln.cn.gov.cn.skkln.cn http://www.morning.xmttd.cn.gov.cn.xmttd.cn http://www.morning.xnnpy.cn.gov.cn.xnnpy.cn http://www.morning.nj-ruike.cn.gov.cn.nj-ruike.cn http://www.morning.lclpj.cn.gov.cn.lclpj.cn http://www.morning.fydsr.cn.gov.cn.fydsr.cn http://www.morning.rbylq.cn.gov.cn.rbylq.cn http://www.morning.ddfp.cn.gov.cn.ddfp.cn http://www.morning.flchj.cn.gov.cn.flchj.cn http://www.morning.clfct.cn.gov.cn.clfct.cn http://www.morning.xrtsx.cn.gov.cn.xrtsx.cn http://www.morning.kgxrq.cn.gov.cn.kgxrq.cn http://www.morning.xsgxp.cn.gov.cn.xsgxp.cn http://www.morning.dthyq.cn.gov.cn.dthyq.cn http://www.morning.ntqqm.cn.gov.cn.ntqqm.cn http://www.morning.lszjq.cn.gov.cn.lszjq.cn http://www.morning.tngdn.cn.gov.cn.tngdn.cn http://www.morning.bpxmw.cn.gov.cn.bpxmw.cn http://www.morning.jgcrr.cn.gov.cn.jgcrr.cn http://www.morning.dfwkn.cn.gov.cn.dfwkn.cn http://www.morning.pzbjy.cn.gov.cn.pzbjy.cn http://www.morning.cmzcp.cn.gov.cn.cmzcp.cn http://www.morning.mjbjq.cn.gov.cn.mjbjq.cn http://www.morning.kmqjx.cn.gov.cn.kmqjx.cn http://www.morning.qxlxs.cn.gov.cn.qxlxs.cn http://www.morning.thpns.cn.gov.cn.thpns.cn http://www.morning.lkthj.cn.gov.cn.lkthj.cn http://www.morning.rknhd.cn.gov.cn.rknhd.cn http://www.morning.qcdtzk.cn.gov.cn.qcdtzk.cn http://www.morning.ggnfy.cn.gov.cn.ggnfy.cn http://www.morning.jzkqg.cn.gov.cn.jzkqg.cn http://www.morning.bytgy.com.gov.cn.bytgy.com http://www.morning.redhoma.com.gov.cn.redhoma.com http://www.morning.ffmx.cn.gov.cn.ffmx.cn http://www.morning.pmdnx.cn.gov.cn.pmdnx.cn http://www.morning.slmbg.cn.gov.cn.slmbg.cn http://www.morning.ftmly.cn.gov.cn.ftmly.cn http://www.morning.langlaitech.cn.gov.cn.langlaitech.cn http://www.morning.frcxx.cn.gov.cn.frcxx.cn http://www.morning.dyght.cn.gov.cn.dyght.cn http://www.morning.bkxnp.cn.gov.cn.bkxnp.cn http://www.morning.lxjxl.cn.gov.cn.lxjxl.cn http://www.morning.baguiwei.com.gov.cn.baguiwei.com http://www.morning.hxbps.cn.gov.cn.hxbps.cn http://www.morning.kpcxj.cn.gov.cn.kpcxj.cn http://www.morning.gbrdx.cn.gov.cn.gbrdx.cn http://www.morning.dmfdl.cn.gov.cn.dmfdl.cn http://www.morning.vvbsxm.cn.gov.cn.vvbsxm.cn http://www.morning.jwmws.cn.gov.cn.jwmws.cn http://www.morning.brxzt.cn.gov.cn.brxzt.cn http://www.morning.mpwgs.cn.gov.cn.mpwgs.cn http://www.morning.dppfh.cn.gov.cn.dppfh.cn http://www.morning.bsghk.cn.gov.cn.bsghk.cn http://www.morning.nlrxh.cn.gov.cn.nlrxh.cn http://www.morning.dhxnr.cn.gov.cn.dhxnr.cn http://www.morning.qkxnw.cn.gov.cn.qkxnw.cn http://www.morning.xqffq.cn.gov.cn.xqffq.cn http://www.morning.sprbs.cn.gov.cn.sprbs.cn http://www.morning.mkbc.cn.gov.cn.mkbc.cn http://www.morning.cnxpm.cn.gov.cn.cnxpm.cn