🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟
📣开发者圈持续输出高质量干货的"愚公精神"践行者------全网百万开发者都在追更的顶级技术博主!
👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"挖山不止"的毅力为开发者们搬开知识道路上的重重阻碍!
💎【行业认证·权威头衔】
✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家
✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主
✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者
🏆【荣誉殿堂】
🎖 连续三年蝉联"华为云十佳博主"(2022-2024)
🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)
🎖 十余个技术社区年度杰出贡献奖得主
📚【知识宝库】
覆盖全栈技术矩阵:
◾ 编程语言:.NET/Java/Python/Go/Node...
◾ 移动生态:HarmonyOS/iOS/Android/小程序
◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙
◾ 游戏开发:Unity3D引擎深度解析
每日更新硬核教程+实战案例,助你打通技术任督二脉!
💌【特别邀请】
正在构建技术人脉圈的你:
👍 如果这篇推文让你收获满满,点击"在看"传递技术火炬
💬 在评论区留下你最想学习的技术方向
⭐ 点击"收藏"建立你的私人知识库
🔔 关注公众号获取独家技术内参
✨与其仰望大神,不如成为大神!关注"愚公搬代码",让坚持的力量带你穿越技术迷雾,见证从量变到质变的奇迹!✨ |
文章目录
🚀前言
在前几篇中,我们已经系统学习了如何搭建分布式爬虫系统,并使用 Scrapy 和 Redis 实现数据的高效抓取与存储。今天,我们将带领大家走进一个更具创意的项目------自定义分布式爬取诗词排行榜数据。
诗词文化作为中国传统文化的重要组成部分,一直以来都备受人们喜爱。在互联网上,很多平台会定期发布各类诗词排行榜,展示热门的诗词作品、作者以及相关的评论和评分。通过分布式爬虫抓取这些数据,不仅可以帮助我们了解当下热门的诗词,还能进行更深层次的数据分析与挖掘。
在本篇文章中,我们将从实际需求出发,学习如何自定义一个分布式爬虫,用于爬取诗词排行榜的数据,并实现以下功能:
- 分析诗词排行榜网站结构:学习如何解析并提取诗词排行榜中的诗词、作者、评分等信息。
- 自定义分布式爬虫:通过 Scrapy 和 Redis 实现分布式任务调度和数据存储,提升爬取效率。
- 数据存储与清洗:将抓取到的诗词数据进行存储和清洗,去除冗余信息,确保数据的准确性与完整性。
- 多线程与分布式管理:如何利用分布式架构,将任务和数据进行高效的分发和管理。
- 深入分析诗词数据:如何对爬取到的诗词数据进行初步的分析,揭示诗词的流行趋势和相关属性。
通过本篇文章的学习,你将能够掌握如何自定义一个分布式爬虫,专门爬取诗词排行榜数据。无论是为了深入了解诗词文化,还是进行数据分析,本篇教程都将为你提供实战经验,帮助你在爬虫项目中取得突破。
🚀一、自定义分布式爬虫:诗词排行榜
使用Scrapy结合Redis实现自定义分布式爬虫,爬取"诗词排行榜"(http://www.shicimingju.com/paiming)的诗词数据。

🔎1.核心步骤
🦋1.1 网页分析
-
分页规律
首页地址:
http://www.shicimingju.com/paiming
第N页地址:
http://www.shicimingju.com/paiming?p={页码}
(页码范围1-100) -
数据定位
- 诗词标题:
<h3>
标签内文本 - 作者:
<div class="list_num_info">
的文本内容 - 内容:
<div class="shici_content>
的文本(需处理"展开全文"标签)
- 诗词标题:

🦋1.2 数据库设计
-
创建数据库
- 数据库名:
poetry_data
- 字符集:
utf8mb4
,排序规则:utf8mb4_0900_ai_ci
- 数据库名:
-
数据表结构
- 表名:
poetry
- 字段:
id
(主键,自增)title
(标题,VARCHAR 20)author
(作者,VARCHAR 10)content
(内容,VARCHAR 1000)
- 表名:

🦋1.3 Scrapy项目搭建
-
创建项目
bashscrapy startproject poetry cd poetry scrapy genspider poetrySpider shicimingju.com/paiming
-
项目结构
items.py
:定义数据字段middlewares.py
:随机请求头中间件pipelines.py
:MySQL存储管道settings.py
:分布式配置

🦋1.4 核心代码实现
-
数据项定义 (
items.py
)pythonimport scrapy class PoetryItem(scrapy.Item): title = scrapy.Field() # 保存诗词标题 author = scrapy.Field() # 保存诗词作者 content = scrapy.Field() # 保存诗词内容 pass
-
中间件 (
middlewares.py
)pythonfrom fake_useragent import UserAgent # 导入请求头类 # 自定义随机请求头的中间件 class RandomHeaderMiddleware(object): def __init__(self, crawler): self.ua = UserAgent() # 随机请求头对象 # 如果配置文件中不存在就使用默认的Google Chrome请求头 self.type = crawler.settings.get("RANDOM_UA_TYPE", "chrome") @classmethod def from_crawler(cls, crawler): # 返回cls()实例对象 return cls(crawler) # 发送网络请求时调用该方法 def process_request(self, request, spider): # 设置随机生成的请求头 request.headers.setdefault('User-Agent', getattr(self.ua, self.type))
-
MySQL存储管道 (
pipelines.py
)python# -*- 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 import pymysql # 导入数据库连接pymysql模块 class PoetryPipeline(object): # 初始化数据库参数 def __init__(self,host,database,user,password,port): self.host = host self.database = database self.user = user self.password = password self.port = port @classmethod def from_crawler(cls, crawler): # 返回cls()实例对象,其中包含通过crawler获取配置文件中的数据库参数 return cls( host=crawler.settings.get('SQL_HOST'), user=crawler.settings.get('SQL_USER'), password=crawler.settings.get('SQL_PASSWORD'), database=crawler.settings.get('SQL_DATABASE'), port=crawler.settings.get('SQL_PORT') ) # 打开爬虫时调用 def open_spider(self, spider): # 数据库连接 self.db = pymysql.connect(host=self.host, user=self.user, password=self.password, database=self.database, port=self.port, charset='utf8') self.cursor = self.db.cursor() # 床架游标 # 关闭爬虫时调用 def close_spider(self, spider): self.db.close() def process_item(self, item, spider): data = dict(item) # 将item转换成字典类型 # sql语句 sql = 'insert into poetry (title,author,content) values(%s,%s,%s)' # 执行插入多条数据 self.cursor.executemany(sql, [(data['title'], data['author'], data['content'])]) self.db.commit() # 提交 return item # 返回item
-
爬虫逻辑 (
poetrySpider.py
)python# -*- coding: utf-8 -*- import scrapy from poetry.items import PoetryItem # 导入Item对象 from redis import Redis # 导入Redis对象 import re # 导入正则表达式 class PoetryspiderSpider(scrapy.Spider): name = 'poetrySpider' allowed_domains = ['shicimingju.com/paiming'] start_urls = ['http://shicimingju.com/paiming/'] # 实现网络请求 def start_requests(self): # 创建redis链接对象 conn = Redis(host='192.168.3.67', port=6379) for i in range(1,101): # 由于诗词排行榜网页共计100页,所以循环执行100次 # 拼接请求地址 url = self.start_urls[0].strip('/') + '?p={page}'.format(page=i) add = conn.sadd('poetry_url', url) # 添加请求地址 if add==1: # redis中没有当前url,就发送请求 print(url) # 执行请求 yield scrapy.Request(url=url, callback=self.parse) else: print('第',i,'页请求地址已存在无需请求!') # 处理请求结果 def parse(self, response): item = PoetryItem() # 创建item对象 shici_all=response.css('.card.shici_card') # 获取每页所有诗词内容 for shici in shici_all: # 循环遍历每页中每个诗词 title= shici.css('h3 a::text').get() # 获取诗词标题名称 author = shici.xpath('./div[@class= "list_num_info"]')\ .xpath('string()').get() # 获取作者 author = author.strip() # 删除所有空格 content = shici.css('.shici_content').xpath('string()').getall()[0] if '展开全文'in content: # 判断诗词内容是否为展开全文模式 content=re.sub(' |展开全文|收起|\n','',content) else: content = re.sub(' |\n','',content) item['title'] = title # 将诗词标题名称添加至item item['author'] = author # 将诗词作者添加至item item['content'] = content # 将诗词内容添加至item yield item # 打印item信息 pass # 导入CrawlerProcess类 from scrapy.crawler import CrawlerProcess # 导入获取项目配置信息 from scrapy.utils.project import get_project_settings # 程序入口 if __name__=='__main__': # 创建CrawlerProcess类对象并传入项目设置信息参数 process = CrawlerProcess(get_project_settings()) # 设置需要启动的爬虫名称 process.crawl('poetrySpider') # 启动爬虫 process.start()
🦋1.5 分布式配置 (settings.py
)
python
BOT_NAME = 'poetry'
SPIDER_MODULES = ['poetry.spiders']
NEWSPIDER_MODULE = 'poetry.spiders'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
DOWNLOADER_MIDDLEWARES = {
'poetry.middlewares.PoetryDownloaderMiddleware': 543,
}
# 配置请求头类型为随机,此处还可以设置为ie、firefox以及chrome
RANDOM_UA_TYPE = "random"
ITEM_PIPELINES = {
'poetry.pipelines.PoetryPipeline': 300,
}
# 配置数据库连接信息
SQL_HOST = '127.0.0.1' # 数据库地址
SQL_USER = 'root' # 用户名
SQL_PASSWORD='root' # 密码
SQL_DATABASE = 'poetry_data' # 数据库名称
SQL_PORT = 3306 # 端口
🦋1.6 启动分布式爬虫
-
Redis配置
- 修改
redis.conf
中的bind
为服务器IP,并重启服务。 - 测试远程连接:
redis-cli -h [IP] -p 6379
。
- 修改
-
MySQL远程访问
sqlUPDATE mysql.user SET host='%' WHERE user='root'; FLUSH PRIVILEGES;
-
多节点运行
-
在多台机器部署代码,修改
settings.py
中的SQL_HOST
和 Redis连接IP。 -
同时启动爬虫:
bashscrapy crawl poetrySpider
-
🔎2.效果验证
-
Redis去重验证
- 使用
Redis Desktop Manager
查看poetry_url
集合中的URL去重记录。
- 使用
-
MySQL数据验证
- 执行查询语句
SELECT * FROM poetry;
,确认数据完整入库。
- 执行查询语句

🔎3.注意事项
- IP替换:所有
[你的IP]
需替换为实际服务器地址。 - 请求头中间件:参考18.3节的
RandomHeaderMiddleware
实现随机User-Agent。 - 错误处理:添加异常捕获逻辑(如数据库连接失败重试)。