导读:本期聚焦于小伙伴创作的《PythonWeb爬虫高级教程:Scrapy框架与数据存储实践怎么做》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《PythonWeb爬虫高级教程:Scrapy框架与数据存储实践怎么做》有用,将其分享出去将是对创作者最好的鼓励。

Scrapy是Python生态中功能完善的Web爬虫框架,它基于异步IO实现,能够高效处理大规模的网页采集任务,同时提供了丰富的中间件和扩展接口,方便开发者根据需求定制功能。本文将从框架核心组件、项目搭建、数据存储实践三个维度展开讲解。

PythonWeb爬虫高级教程:Scrapy框架与数据存储实践怎么做

Scrapy框架核心组件解析

Scrapy的架构由多个核心组件协同工作,理解这些组件的作用是实现高级功能的基础:

  • Spider:爬虫逻辑的核心,负责定义采集的起始URL、解析响应数据、提取目标字段和生成新的请求。
  • Engine:框架的调度中枢,负责控制所有组件之间的数据流,触发事务处理。
  • Scheduler:请求调度器,接收Engine发来的请求并排队,在合适的时候返回给Engine。
  • Downloader:下载器,负责发送请求获取网页响应,然后将响应返回给Engine。
  • Item Pipeline:数据管道,负责处理Spider提取到的数据,常见的操作包括数据清洗、验证、存储。
  • Middleware:包括Spider中间件和Downloader中间件,用于在请求和响应的处理过程中插入自定义逻辑,比如添加请求头、处理反爬、重试失败请求等。

Scrapy项目搭建与基础爬虫实现

首先需要通过pip安装Scrapy框架:

pip install scrapy

安装完成后,使用命令行创建Scrapy项目:

scrapy startproject book_spider
cd book_spider
scrapy genspider book_douban douban.com

上述命令会创建一个名为book_spider的项目,并在spiders目录下生成book_douban爬虫文件。接下来编写基础爬虫逻辑,以采集豆瓣图书的基本信息为例:

import scrapy

class BookDoubanSpider(scrapy.Spider):
    name = "book_douban"  # 爬虫名称,运行爬虫时需要使用
    allowed_domains = ["douban.com"]  # 允许采集的域名
    start_urls = ["https://www.douban.com/tag/小说/book"]  # 起始URL

    def parse(self, response):
        # 提取所有图书条目
        book_list = response.xpath('//div[@class="mod book-list"]/dl/dd')
        for book in book_list:
            item = {
                "title": book.xpath('./a/text()').get(),
                "author": book.xpath('./p[1]/text()').get(),
                "score": book.xpath('./p[2]/span[@class="rating_nums"]/text()').get(),
                "link": book.xpath('./a/@href').get()
            }
            yield item

        # 提取下一页链接,生成新的请求
        next_page = response.xpath('//span[@class="next"]/a/@href').get()
        if next_page:
            yield scrapy.Request(url=response.urljoin(next_page), callback=self.parse)

数据存储实践方案

Scrapy提供了多种数据存储的方式,开发者可以根据数据规模和后续使用场景选择合适的方案,以下是三种常见的存储实践。

方案一:存储到JSON文件

Scrapy内置了Feed Exports功能,可以直接将采集到的数据导出为JSON、CSV等格式的文件,无需额外编写存储逻辑。运行爬虫时指定输出格式和路径即可:

scrapy crawl book_douban -o book_data.json

如果需要自定义JSON的输出格式,比如设置编码、缩进,可以在项目的settings.py中配置:

# settings.py中添加配置
FEED_EXPORT_ENCODING = "utf-8"  # 设置输出编码
FEED_FORMAT = "json"  # 默认输出格式
FEED_URI = "book_data.json"  # 默认输出路径

方案二:存储到MySQL关系型数据库

当需要对采集到的数据进行结构化查询和管理时,MySQL是常用的选择。首先需要安装pymysql驱动:

pip install pymysql

然后在settings.py中配置MySQL连接信息:

# settings.py中添加配置
MYSQL_HOST = "127.0.0.1"
MYSQL_PORT = 3306
MYSQL_USER = "root"
MYSQL_PASSWORD = "123456"
MYSQL_DATABASE = "spider_data"

接下来编写Item Pipeline实现数据入库,首先在pipelines.py中定义存储管道:

import pymysql
from itemadapter import ItemAdapter

class MysqlPipeline:
    def __init__(self, mysql_host, mysql_port, mysql_user, mysql_password, mysql_database):
        self.host = mysql_host
        self.port = mysql_port
        self.user = mysql_user
        self.password = mysql_password
        self.database = mysql_database
        self.conn = None
        self.cursor = None

    @classmethod
    def from_crawler(cls, crawler):
        # 从settings中获取配置参数
        return cls(
            mysql_host=crawler.settings.get("MYSQL_HOST"),
            mysql_port=crawler.settings.get("MYSQL_PORT"),
            mysql_user=crawler.settings.get("MYSQL_USER"),
            mysql_password=crawler.settings.get("MYSQL_PASSWORD"),
            mysql_database=crawler.settings.get("MYSQL_DATABASE")
        )

    def open_spider(self, spider):
        # 爬虫启动时建立数据库连接
        self.conn = pymysql.connect(
            host=self.host,
            port=self.port,
            user=self.user,
            password=self.password,
            database=self.database,
            charset="utf8mb4"
        )
        self.cursor = self.conn.cursor()
        # 创建数据表,如果不存在则创建
        create_table_sql = """
        CREATE TABLE IF NOT EXISTS douban_book (
            id INT PRIMARY KEY AUTO_INCREMENT,
            title VARCHAR(255) NOT NULL,
            author VARCHAR(255),
            score VARCHAR(10),
            link VARCHAR(500),
            create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
        """
        self.cursor.execute(create_table_sql)
        self.conn.commit()

    def process_item(self, item, spider):
        adapter = ItemAdapter(item)
        # 插入数据
        insert_sql = """
        INSERT INTO douban_book (title, author, score, link)
        VALUES (%s, %s, %s, %s)
        """
        self.cursor.execute(insert_sql, (
            adapter.get("title"),
            adapter.get("author"),
            adapter.get("score"),
            adapter.get("link")
        ))
        self.conn.commit()
        return item

    def close_spider(self, spider):
        # 爬虫关闭时释放资源
        if self.cursor:
            self.cursor.close()
        if self.conn:
            self.conn.close()

最后在settings.py中启用该管道:

ITEM_PIPELINES = {
    "book_spider.pipelines.MysqlPipeline": 300,  # 数值越小优先级越高
}

方案三:存储到MongoDB非关系型数据库

如果采集的数据结构不固定,或者需要更高的写入性能,MongoDB是更合适的选择。首先安装pymongo驱动:

pip install pymongo

在settings.py中配置MongoDB连接信息:

# settings.py中添加配置
MONGO_URI = "127.0.0.1:27017"
MONGO_DATABASE = "spider_data"

编写MongoDB存储管道:

import pymongo
from itemadapter import ItemAdapter

class MongoPipeline:
    def __init__(self, mongo_uri, mongo_database):
        self.mongo_uri = mongo_uri
        self.mongo_database = mongo_database
        self.client = None
        self.db = None

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get("MONGO_URI"),
            mongo_database=crawler.settings.get("MONGO_DATABASE")
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_database]

    def process_item(self, item, spider):
        adapter = ItemAdapter(item)
        # 插入数据到douban_book集合
        self.db["douban_book"].insert_one(dict(adapter))
        return item

    def close_spider(self, spider):
        if self.client:
            self.client.close()

同样在settings.py中启用该管道即可。

高级功能扩展

请求去重与增量爬取

Scrapy默认使用RFPDupeFilter进行请求去重,基于请求的URL进行判断。如果需要实现增量爬取,避免重复采集已经获取过的数据,可以自定义去重逻辑,比如基于数据的唯一标识(如图书的ID)进行去重。可以在Spider中维护一个已采集ID的集合,或者在Pipeline中判断数据是否已经存在再决定是否入库。

反爬处理中间件

很多网站会有反爬机制,比如检测请求头、限制访问频率、返回验证码等。可以通过自定义Downloader中间件来处理这些问题:

class CustomDownloaderMiddleware:
    def process_request(self, request, spider):
        # 添加随机User-Agent
        user_agent_list = [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15"
        ]
        request.headers["User-Agent"] = random.choice(user_agent_list)
        # 添加自定义请求头
        request.headers["Referer"] = "https://www.douban.com"
        return None

    def process_response(self, request, response, spider):
        # 如果响应状态码是403,说明被反爬,重新发送请求
        if response.status == 403:
            return request.replace(dont_filter=True)
        return response

将该中间件配置到settings.py的DOWNLOADER_MIDDLEWARES中即可生效。

常见问题与优化建议

在实际使用Scrapy时,可能会遇到一些问题,以下是常见的优化方向:

  • 调整并发请求数量:在settings.py中设置CONCURRENT_REQUESTS参数,默认是16,可以根据目标网站的承受能力和自身网络情况调整,但不要设置过高避免被封禁。
  • 设置请求延迟:通过DOWNLOAD_DELAY参数设置每个请求之间的延迟时间,降低被反爬的概率。
  • 启用自动限速:设置AUTOTHROTTLE_ENABLED为True,Scrapy会根据目标网站的响应延迟自动调整请求频率。
  • 处理请求失败重试:默认的RetryMiddleware会自动重试失败的请求,可以通过RETRY_TIMES参数调整重试次数。

通过上述内容的实践,开发者可以掌握Scrapy框架的核心用法,并且能够根据实际需求选择合适的存储方案,实现稳定高效的Web爬虫数据采集与存储。

ScrapyPython_Web_crawlerdata_storagespider_middleware修改时间:2026-07-16 10:21:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。