🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟
📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主!
👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"挖山不止"的毅力为开发者们搬开知识道路上的重重阻碍!
💎【行业认证·权威头衔】
✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家
✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主
✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者
🏆【荣誉殿堂】
🎖 连续三年蝉联"华为云十佳博主"(2022-2024)
🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)
🎖 十余个技术社区年度杰出贡献奖得主
📚【知识宝库】
覆盖全栈技术矩阵:
◾ 编程语言:.NET/Java/Python/Go/Node…
◾ 移动生态:HarmonyOS/iOS/Android/小程序
◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙
◾ 游戏开发:Unity3D引擎深度解析
每日更新硬核教程+实战案例,助你打通技术任督二脉!
💌【特别邀请】
正在构建技术人脉圈的你:
👍 如果这篇推文让你收获满满,点击"在看"传递技术火炬
💬 在评论区留下你最想学习的技术方向
⭐ 点击"收藏"建立你的私人知识库
🔔 关注公众号获取独家技术内参
✨与其仰望大神,不如成为大神!关注"愚公搬代码",让坚持的力量带你穿越技术迷雾,见证从量变到质变的奇迹!✨ |
文章目录
- 🚀前言
- 🚀一、分布式爬取中文日报新闻数据
- 🔎1.网页分析
- 🔎2.数据库设计
- 🔎3.Scrapy项目搭建
- 🔎4.分布式配置 (`settings.py`)
- 🔎5.启动分布式爬虫
🚀前言
在前几篇中,我们已经深入探讨了 Scrapy 和 Redis 的基本应用,以及如何利用 Scrapy-Redis 实现分布式爬虫系统。今天,我们将带领大家实际操作,通过分布式爬取中文日报新闻数据,进一步提升我们在实际项目中的应用能力。
在爬虫开发中,新闻数据的爬取是一个非常典型的应用场景。通过爬取中文日报网站的新闻数据,我们不仅可以获取到实时的新闻信息,还能够深入分析新闻内容,进行数据挖掘与应用。而使用分布式爬虫架构,可以让我们在面对大规模新闻数据时,轻松实现高效的数据抓取与处理。
在本篇文章中,我们将通过实际案例,学习如何分布式爬取中文日报的新闻数据,并实现以下功能:
- 分析中文日报网站结构:如何解析中文日报网站的 HTML 结构,定位新闻数据,提取有价值的信息。
- Scrapy-Redis 实现分布式抓取:结合 Scrapy 和 Redis,实现新闻数据的分布式爬取,提高爬取效率。
- 新闻数据存储与清洗:如何存储抓取到的新闻数据,并进行简单的数据清洗和处理,使数据更加有用。
- 数据去重与分布式管理:使用 Redis 的去重功能,避免重复抓取新闻数据,实现任务的高效分发与管理。
- 处理中文文本:如何处理中文文本数据,并对新闻标题、内容等进行进一步的分析和存储。
通过本篇文章的学习,你将能够运用分布式爬虫技术,抓取并存储中文日报的新闻数据,为你后续的数据分析和项目开发打下坚实的基础。如果你希望深入了解分布式爬虫在实际项目中的应用,那么今天的教程将是一个绝佳的实践机会。
🚀一、分布式爬取中文日报新闻数据
🔎1.网页分析
-
目标网址
- 示例分页地址规律:
http://china.chinadaily.com.cn/5bd5639ca3101a87ca8ff636/page_{页码}.html
- 通过修改末尾页码实现翻页(1-100页)。
- 示例分页地址规律:
-
数据定位
- 使用开发者工具定位以下字段的HTML位置:
- 新闻标题
<h3>
标签内文本 - 新闻简介
<p>
标签内文本 - 新闻详情页地址
<a>
标签的href
属性 - 发布时间
<b>
标签内文本
- 新闻标题
- 使用开发者工具定位以下字段的HTML位置:
🔎2.数据库设计
-
创建数据库
- 数据库名:
news_data
- 字符集:
utf8mb4
,排序规则:utf8mb4_0900_ai_ci
- 数据库名:
-
数据表结构
- 表名:
news
- 字段:
id
(主键,自增)title
(新闻标题,VARCHAR 255)synopsis
(简介,VARCHAR 255)url
(详情页地址,VARCHAR 255)time
(发布时间,VARCHAR 20)
- 表名:
🔎3.Scrapy项目搭建
-
创建项目
scrapy startproject distributed cd distributed scrapy genspider distributedSpider china.chinadaily.com.cn
-
项目结构
items.py
:定义数据字段middlewares.py
:随机请求头中间件pipelines.py
:MySQL数据存储管道settings.py
:分布式配置
核心代码实现
-
随机请求头中间件 (
middlewares.py
)from 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")@classmethoddef from_crawler(cls, crawler):# 返回cls()实例对象return cls(crawler)# 发送网络请求时调用该方法def process_request(self, request, spider):# 设置随机生成的请求头request.headers.setdefault('User-Agent', getattr(self.ua, self.type))
-
数据项定义 (
items.py
)import scrapyclass DistributedItem(scrapy.Item):news_title = scrapy.Field() # 保存新闻标题news_synopsis = scrapy.Field() # 保存新闻简介news_url = scrapy.Field() # 保存新闻详情页面的地址news_time = scrapy.Field() # 保存新闻发布时间pass
-
MySQL存储管道 (
pipelines.py
)# -*- 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.htmlimport pymysql # 导入数据库连接pymysql模块 class DistributedPipeline(object):# 初始化数据库参数def __init__(self,host,database,user,password,port):self.host = hostself.database = databaseself.user = userself.password = passwordself.port = port@classmethoddef 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(self.host, self.user, self.password, self.database, 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 news (title,synopsis,url,time) values(%s,%s,%s,%s)'# 执行插入多条数据self.cursor.executemany(sql, [(data['news_title'], data['news_synopsis'],data['news_url'],data['news_time'])])self.db.commit() # 提交return item # 返回item
-
爬虫逻辑 (
distributedSpider.py
)# -*- coding: utf-8 -*- import scrapy from distributed.items import DistributedItem # 导入Item对象 class DistributedspiderSpider(scrapy.Spider):name = 'distributedSpider'allowed_domains = ['china.chinadaily.com.cn']start_urls = ['http://china.chinadaily.com.cn/']# 发送网络请求def start_requests(self):for i in range(1,101): # 由于新闻网页共计100页,所以循环执行100次# 拼接请求地址url = self.start_urls[0] + '5bd5639ca3101a87ca8ff636/page_{page}.html'.format(page=i)# 执行请求yield scrapy.Request(url=url,callback=self.parse)# 处理请求结果def parse(self, response):item = DistributedItem() # 创建item对象all = response.css('.busBox3') # 获取每页所有新闻内容for i in all: # 循环遍历每页中每条新闻title = i.css('h3 a::text').get() # 获取每条新闻标题synopsis = i.css('p::text').get() # 获取每条新闻简介url = 'http:'+i.css('h3 a::attr(href)').get() # 获取每条新闻详情页地址time_ = i.css('p b::text').get() # 获取新闻发布时间item['news_title'] = title # 将新闻标题添加至itemitem['news_synopsis'] = synopsis # 将新闻简介内容添加至itemitem['news_url'] = url # 将新闻详情页地址添加至itemitem['news_time'] = time_ # 将新闻发布时间添加至itemyield 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('distributedSpider')# 启动爬虫process.start()
🔎4.分布式配置 (settings.py
)
BOT_NAME = 'distributed'SPIDER_MODULES = ['distributed.spiders']
NEWSPIDER_MODULE = 'distributed.spiders'# Obey robots.txt rules
ROBOTSTXT_OBEY = True# 启用redis调度存储请求队列
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
#确保所有爬虫通过redis共享相同的重复筛选器。
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
#不清理redis队列,允许暂停/恢复爬虫
SCHEDULER_PERSIST =True
#使用默认的优先级队列调度请求
SCHEDULER_QUEUE_CLASS ='scrapy_redis.queue.PriorityQueue'
REDIS_URL ='redis://127.0.0.1:6379'
DOWNLOADER_MIDDLEWARES = {# 启动自定义随机请求头中间件'distributed.middlewares.RandomHeaderMiddleware': 200,# 'distributed.middlewares.DistributedDownloaderMiddleware': 543,
}
# 配置请求头类型为随机,此处还可以设置为ie、firefox以及chrome
RANDOM_UA_TYPE = "random"
ITEM_PIPELINES = {'distributed.pipelines.DistributedPipeline': 300,'scrapy_redis.pipelines.RedisPipeline':400
}
# 配置数据库连接信息
SQL_HOST = '127.0.0.1' # 数据库地址
SQL_USER = 'root' # 用户名
SQL_PASSWORD='123456' # 密码
SQL_DATABASE = 'news_data' # 数据库名称
SQL_PORT = 3306 # 端口
🔎5.启动分布式爬虫
-
数据库远程配置
- Redis:修改
redis.windows-service.conf
的bind
为服务器IP,重启服务。 - MySQL:执行以下SQL开启远程连接:
UPDATE mysql.user SET host='%' WHERE user='root'; FLUSH PRIVILEGES;
- Redis:修改
-
多节点运行
- 在多台机器部署爬虫代码,修改
settings.py
中的数据库IP为服务器地址。 - 同时启动爬虫,观察Redis任务队列与MySQL数据入库情况。
- 在多台机器部署爬虫代码,修改
效果验证
- Redis Desktop Manager 查看去重URL (
dupefilter
) 和爬取数据 (items
)。 - MySQL 中
news
表应包含所有爬取的新闻数据。