【愚公系列】《Python网络爬虫从入门到精通》057-分布式爬取中文日报新闻数据

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟

📣开发者圈持续输出高质量干货的"愚公精神"践行者------全网百万开发者都在追更的顶级技术博主!

👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"挖山不止"的毅力为开发者们搬开知识道路上的重重阻碍!

💎【行业认证·权威头衔】

✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家

✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主

✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者

🏆【荣誉殿堂】

🎖 连续三年蝉联"华为云十佳博主"(2022-2024)

🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)

🎖 十余个技术社区年度杰出贡献奖得主

📚【知识宝库】

覆盖全栈技术矩阵:

◾ 编程语言:.NET/Java/Python/Go/Node...

◾ 移动生态:HarmonyOS/iOS/Android/小程序

◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙

◾ 游戏开发:Unity3D引擎深度解析

每日更新硬核教程+实战案例,助你打通技术任督二脉!

💌【特别邀请】

正在构建技术人脉圈的你:

👍 如果这篇推文让你收获满满,点击"在看"传递技术火炬

💬 在评论区留下你最想学习的技术方向

⭐ 点击"收藏"建立你的私人知识库

🔔 关注公众号获取独家技术内参

✨与其仰望大神,不如成为大神!关注"愚公搬代码",让坚持的力量带你穿越技术迷雾,见证从量变到质变的奇迹!✨ |

文章目录


🚀前言

在前几篇中,我们已经深入探讨了 Scrapy 和 Redis 的基本应用,以及如何利用 Scrapy-Redis 实现分布式爬虫系统。今天,我们将带领大家实际操作,通过分布式爬取中文日报新闻数据,进一步提升我们在实际项目中的应用能力。

在爬虫开发中,新闻数据的爬取是一个非常典型的应用场景。通过爬取中文日报网站的新闻数据,我们不仅可以获取到实时的新闻信息,还能够深入分析新闻内容,进行数据挖掘与应用。而使用分布式爬虫架构,可以让我们在面对大规模新闻数据时,轻松实现高效的数据抓取与处理。

在本篇文章中,我们将通过实际案例,学习如何分布式爬取中文日报的新闻数据,并实现以下功能:

  1. 分析中文日报网站结构:如何解析中文日报网站的 HTML 结构,定位新闻数据,提取有价值的信息。
  2. Scrapy-Redis 实现分布式抓取:结合 Scrapy 和 Redis,实现新闻数据的分布式爬取,提高爬取效率。
  3. 新闻数据存储与清洗:如何存储抓取到的新闻数据,并进行简单的数据清洗和处理,使数据更加有用。
  4. 数据去重与分布式管理:使用 Redis 的去重功能,避免重复抓取新闻数据,实现任务的高效分发与管理。
  5. 处理中文文本:如何处理中文文本数据,并对新闻标题、内容等进行进一步的分析和存储。

通过本篇文章的学习,你将能够运用分布式爬虫技术,抓取并存储中文日报的新闻数据,为你后续的数据分析和项目开发打下坚实的基础。如果你希望深入了解分布式爬虫在实际项目中的应用,那么今天的教程将是一个绝佳的实践机会。

🚀一、分布式爬取中文日报新闻数据

🔎1.网页分析

  1. 目标网址

    • 示例分页地址规律:
      http://china.chinadaily.com.cn/5bd5639ca3101a87ca8ff636/page_{页码}.html
    • 通过修改末尾页码实现翻页(1-100页)。
  2. 数据定位

    • 使用开发者工具定位以下字段的HTML位置:
      • 新闻标题 <h3> 标签内文本
      • 新闻简介 <p> 标签内文本
      • 新闻详情页地址 <a> 标签的 href 属性
      • 发布时间 <b> 标签内文本

🔎2.数据库设计

  1. 创建数据库

    • 数据库名:news_data
    • 字符集:utf8mb4,排序规则:utf8mb4_0900_ai_ci
  2. 数据表结构

    • 表名:news
    • 字段:
      • id (主键,自增)
      • title (新闻标题,VARCHAR 255)
      • synopsis (简介,VARCHAR 255)
      • url (详情页地址,VARCHAR 255)
      • time (发布时间,VARCHAR 20)

🔎3.Scrapy项目搭建

  1. 创建项目

    bash 复制代码
    scrapy startproject distributed
    cd distributed
    scrapy genspider distributedSpider china.chinadaily.com.cn
  2. 项目结构

    • items.py:定义数据字段
    • middlewares.py:随机请求头中间件
    • pipelines.py:MySQL数据存储管道
    • settings.py:分布式配置

核心代码实现

  1. 随机请求头中间件 (middlewares.py)

    python 复制代码
    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")
    
        @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))
  2. 数据项定义 (items.py)

    python 复制代码
    import scrapy
    
    class DistributedItem(scrapy.Item):
        news_title = scrapy.Field()  # 保存新闻标题
        news_synopsis = scrapy.Field()  # 保存新闻简介
        news_url = scrapy.Field()  # 保存新闻详情页面的地址
        news_time = scrapy.Field()  # 保存新闻发布时间
        pass
  3. 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 DistributedPipeline(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(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
  4. 爬虫逻辑 (distributedSpider.py)

    python 复制代码
    # -*- 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            # 将新闻标题添加至item
                item['news_synopsis'] = synopsis      # 将新闻简介内容添加至item
                item['news_url'] = url                # 将新闻详情页地址添加至item
                item['news_time'] = time_                   # 将新闻发布时间添加至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('distributedSpider')
        # 启动爬虫
        process.start()

🔎4.分布式配置 (settings.py)

python 复制代码
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.启动分布式爬虫

  1. 数据库远程配置

    • Redis:修改 redis.windows-service.confbind 为服务器IP,重启服务。

    • MySQL:执行以下SQL开启远程连接:

      sql 复制代码
      UPDATE mysql.user SET host='%' WHERE user='root';
      FLUSH PRIVILEGES;
  2. 多节点运行

    • 在多台机器部署爬虫代码,修改 settings.py 中的数据库IP为服务器地址。
    • 同时启动爬虫,观察Redis任务队列与MySQL数据入库情况。

效果验证

  • Redis Desktop Manager 查看去重URL (dupefilter) 和爬取数据 (items)。
  • MySQL 中 news 表应包含所有爬取的新闻数据。



相关推荐
心扬21 分钟前
python生成器
开发语言·python
mouseliu26 分钟前
python之二:docker部署项目
前端·python
狂小虎44 分钟前
亲测解决self.transform is not exist
python·深度学习
Python智慧行囊1 小时前
Python 中 Django 中间件:原理、方法与实战应用
python·中间件·架构·django·开发
深科文库1 小时前
构建 MCP 服务器:第 3 部分 — 添加提示
服务器·python·chatgpt·langchain·prompt·aigc·agi
蓝婷儿1 小时前
6个月Python学习计划 Day 17 - 继承、多态与魔术方法
开发语言·python·学习
Mikhail_G2 小时前
Python应用变量与数据类型
大数据·运维·开发语言·python·数据分析
hello kitty w2 小时前
Python学习(7) ----- Python起源
linux·python·学习
华科云商xiao徐2 小时前
Java HttpClient实现简单网络爬虫
java·爬虫