Python库学习(十三):爬虫框架Scrapy

微信搜索【猿码记】查看更多文章...

1.介绍

Scrapy是一个用于爬取网站数据的Python框架。它提供了一套强大而灵活的工具,使开发者能够轻松地创建和管理爬虫,从而从网站中提取所需的信息。框架要求Python的版本 3.8+

  • Github Star:49.6k: https://github.com/scrapy/scrapy
  • 中文文档: https://www.osgeo.cn/scrapy/intro/tutorial.html

1.1 特点和优势

以下是一些Scrapy的主要特点和优势:

  1. 结构化的框架: Scrapy提供了一个清晰的结构,将爬虫的不同部分组织起来,包括爬虫代码、中间件、下载器等。这种结构使得代码模块化,易于维护和扩展。
  2. 异步处理: Scrapy使用 Twisted异步网络引擎,能够并行处理多个请求,提高爬取效率。这使得 Scrapy适用于大规模的数据抓取任务。
  3. 内置的选择器: Scrapy内置了强大的选择器( XPath和CSS选择器),使得开发者能够方便地从 HTMLXML文档中提取所需的数据。
  4. 中间件支持: 可以通过中间件进行请求和响应的预处理,例如添加代理、修改 User-Agent等,从而提高爬虫的灵活性和适应性。
  5. 自动限速: Scrapy支持自动限速功能,可以设置每秒发送请求的数量,防止对目标服务器造成过大的负担,也有助于规避反爬虫策略。
  6. 扩展性: Scrapy提供了丰富的插件系统,允许开发者通过编写扩展或中间件来自定义爬虫的行为,使其更适应特定的需求。
  7. 数据存储: 支持将爬取到的数据存储到多种格式,包括 JSON、CSV、XML等,也可以存储到数据库中。
  8. 调试工具: Scrapy提供了命令行工具和图形界面( Scrapy Shell)用于调试和测试爬虫,方便开发者查看和验证提取的数据。

1.2 安装

# 安装
$ pip install scrapy

#
 查看版本
$ scrapy version
Scrapy 2.11.0

1.3 子命令

$ scrapy
Scrapy 2.11.0 - active project: scrapy_study_demo

Usage:
  scrapy <command> [options] [args]

Available commands:
  bench         Run quick benchmark test
  check         Check spider contracts
  crawl         Run a spider
  edit          Edit spider
  fetch         Fetch a URL using the Scrapy downloader
  genspider     Generate new spider using pre-defined templates
  list          List available spiders
  parse         Parse URL (using its spider) and print the results
  runspider     Run a self-contained spider (without creating a project)
  settings      Get settings values
  shell         Interactive scraping console
  startproject  Create new project
  version       Print Scrapy version
  view          Open URL in browser, as seen by Scrapy

主要子命令及其作用:

  • bench: 运行快速的性能基准测试,用于评估 Scrapy的性能。
  • check: 用于检查 Scrapy项目的代码并执行一些基本的检查,以确保项目的结构和配置正确;
  • crawl: 用于启动一个爬虫,如: scrapy crawl xxx;
  • edit: 用于编辑爬虫代码,可以指定使用哪个编辑器打开,一般不用;
  • fetch: 使用 Scrapy下载器获取指定 URL的内容,并将其显示在命令行中。用于测试单个 URL的下载和解析。
  • genspider: 生成新的爬虫 spider,使用预定义的模板来快速创建新的爬虫项目。可以指定爬虫的名称、域名等参数。
  • list: 用于列出可用的爬虫,需求在爬虫项目目录下执行;
  • runspider: 运行一个独立的爬虫,而不必创建整个 Scrapy项目。这是一种简便的方式来测试或运行单个爬虫文件。
  • settings: 获取当前 Scrapy项目的设置值。可以查看当前项目的配置信息。
  • shell: 启动一个交互式的 Scrapy控制台,方便开发者在命令行中测试和调试爬虫代码,查看和提取数据。
  • startproject: 创建一个新的 Scrapy项目。该命令将生成一个包含基本结构的新目录,包括默认的设置、爬虫模板等。
  • version: 显示当前安装的 Scrapy版本号。
  • view: 在默认的 Web浏览器中打开指定的 URL,以查看网页内容。可以帮助开发者直观地查看网页,了解其结构。

2.初始化项目

scrapy提供了类似脚手架子命令:scrapy startproject xxx,可以用来直接创建一个项目,免去我们一些繁琐工作;

2.1 创建项目

startproject: 创建一个新的Scrapy项目。该命令将生成一个包含基本结构的新目录,包括默认的设置、爬虫模板等。

# 创建项目
$ scrapy startproject scrapy_study_demo
New Scrapy project 'scrapy_study_demo', using template directory '/opt/anaconda3/envs/py310/lib/python3.10/site-packages/scrapy/templates/project', created in:
    /Users/hui/ProjectSpace/PythonItem/scrapy_study_demo

You can start your first spider with:
    cd scrapy_study_demo
    scrapy genspider example example.com
   
# 添加示例
$ cd scrapy_study_demo && scrapy genspider example example.com
Created spider 'example' using template 'basic' in module:
  scrapy_study_demo.spiders.example

2.2 目录介绍

scrapy_study_demo # 项目目录
├── scrapy.cfg # 配置文件
└── scrapy_study_demo # 项目的Python包
    ├── items.py # 定义爬取的数据结构(Item)
    ├── middlewares.py# 中间件
    ├── pipelines.py # 管道
    ├── settings.py #项目的配置文件
    └── spiders # 存放爬虫代码的目录
        └── example.py # scrapy genspider example example.com 创建的实例代码

上述部分文件的具体作用说明:

  • items.py: 定义爬取的数据结构( Item)。每个 Item对应爬虫要提取的信息的数据模型。
  • middlewares.py: 包含中间件的文件。中间件是在 Scrapy引擎和下载器之间处理请求和响应的钩子。
  • pipelines.py: 包含管道的文件。管道负责处理爬取到的 Item,例如存储到数据库或文件。
  • settings.py: 项目的配置文件,包含各种配置选项,如下载延迟、用户代理等

3.实战示例

下面以爬取豆瓣:【全年代日本动画Top500口碑排行榜】为实战示例,仅供学习使用,勿做其他用途~

访问地址: https://www.douban.com/doulist/45955373/

alt

3.1 创建爬虫

genspider: 生成新的爬虫spider,使用预定义的模板来快速创建新的爬虫项目。可以指定爬虫的名称、域名等参数。

# 在当前项目执行,后面网址是我们需要爬的网页
$ scrapy genspider animeRank https://www.douban.com/doulist/45955373/
Created spider 'animeRank' using template 'basic' in module:
  scrapy_study_demo.spiders.animeRank

上述命令会创建文件:scrapy_study_demo/spiders/animeRank.py,并生成填充一些代码,个人感觉代码生成的有写瑕疵,如下:

alt

@注: 创建的类名,手动做了修改,上图未标注;

优化后代码如下:

import scrapy
from typing import Any
from scrapy.http import Response

class AnimeRankSpider(scrapy.Spider):
    name = "animeRank" # 爬虫名称,必须是唯一 
    allowed_domains = ["www.douban.com"
    start_urls = ["https://www.douban.com/doulist/45955373/"]

    def parse(self, response: Response, **kwargs: Any):
        # 打印抓取的网页HTML
        print("网页内容:", response.text)
        pass

3.2 启动爬虫

crawl: 用于启动一个爬虫,如:scrapy crawl xxx;

# animeRank取自 name = "animeRank"
$ scrapy crawl animeRank
...
2023-12-20 12:04:17 [scrapy.core.engine] INFO: Spider opened
2023-12-20 12:04:17 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2023-12-20 12:04:17 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2023-12-20 12:04:17 [scrapy.core.engine] DEBUG: Crawled (403) <GET https://www.douban.com/robots.txt> (referer: None)
2023-12-20 12:04:18 [scrapy.core.engine] DEBUG: Crawled (403) <GET https://www.douban.com/doulist/45955373/> (referer: None)
# 具体错误信息
2023-12-20 12:04:18 [scrapy.spidermiddlewares.httperror] INFO: Ignoring response <403 https://www.douban.com/doulist/45955373/>: HTTP status code is not handled or not allowed
2023-12-20 12:04:18 [scrapy.core.engine] INFO: Closing spider (finished)
...

一般网站都会做一些反爬虫措施,从上面错误可以看出,在爬取网页时,豆瓣返回了403,用scrapy view验证下

$ scrapy view https://www.douban.com/doulist/45955373
alt

3.3 修改配置

a.常用配置信息

有时针对一些反爬虫网站,需要做些额外配置才能进行数据获取,我们简单了解下常用的配置有哪些?

  • USER_AGENT: 设置请求的 User-Agent头,模拟不同浏览器的请求。
  • DOWNLOAD_DELAY: 设置请求的下载延迟,以避免对目标网站的过度请求。
  • CONCURRENT_REQUESTS: 设置同时发送的请求数。
  • CONCURRENT_REQUESTS_PER_DOMAIN: 设置单个域名同时发送的请求数。
  • COOKIES_ENABLED: 是否启用 Cookies处理。
  • DEFAULT_REQUEST_HEADERS: 设置默认的请求头。
  • ROBOTSTXT_OBEY: 是否遵循网站的 robots.txt规则。 True/False
  • LOG_LEVEL: 设置日志输出的级别, DEBUG、INFO、WARNING、ERROR、CRITICAL
  • LOG_STDOUT: 输出日志信息到标准输出(控制台);
  • LOG_FILE: 可以指定日志文件,默认输出到控制台;
  • AUTOTHROTTLE_ENABLED: 启用自动限速调整下载延迟, True/False;
  • AUTOTHROTTLE_START_DELAY: 自动限速扩展时的初始等待时间,单位秒;
  • AUTOTHROTTLE_MAX_DELAY: 自动限速算法允许的最大等待时间,单位秒;

上面配置信息只是九牛一毛,更多配置信息可以查看文档: https://www.osgeo.cn/scrapy/topics/settings.html 记住一些常用的,其他的用到时候查看下文档即可;

b.修改配置

针对被扒网站返回403的问题,一般情况只需要设置下请求的User-Agent头,模拟是浏览器的请求即可。修改文件:scrapy_study_demo/settings.py

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'

c.再次运行爬虫

$ scrapy crawl animeRank
网页内容: <!DOCTYPE html>
<html lang="zh-CN" class="ua-windows ua-webkit">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="always">
    <meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
    <title>全年代日本动画Top500口碑排行榜</title>
    ...

3.4 debug爬虫

为了方便后面解析内容,验证代码是否解析有误,我们先研究下怎么使用pycharm+debug的方式来运行程序;不能每次都通过scrapy crawl animeRank,这样定位问题会很慢;

1.创建运行文件

创建目录和文件crawlrun/anime_rank.py,内容如下:

from scrapy.cmdline import execute

execute("scrapy crawl animeRank".split())
2.debug运行文件
alt

3.5 解析语法

走到这一步,说明我们学会了项目的基础使用,解决了403问题,但是我们还没有解析网页内容,网页往往是由一堆HTML组成,那如何获取我们想要的内容呢? Scrapy框架提供了两种机制,分别是基于 XPath 和 CSS 的表达式;

1.html代码

使用两种方式分别解析下面前端代码,并提取出标题和链接

<body>
    <div class="container">
        <h2 class="title">三国演义</h2>
        <a href="https://example.com/sanguo" class="link">Link 1</a>

        <h2 class="title">西游记</h2>
        <a href="https://example.com/xiyouji" class="link">Link 2</a>

        <h2 class="title">水浒传</h2>
        <a href="https://example.com/shuihu" class="link">Link 3</a>
    </div>
</body>
2.使用XPath解析
def parse(self, response: Response, **kwargs: Any):
    # 使用XPath选择器提取页面中的标题和链接
    titles = response.xpath('//h2[@class="title"]/text()').getall()
    links = response.xpath('//a[@class="link"]/@href').getall()
    # 打印结果
    for title, link in zip(titles, links):
        print(f'Title: {title}, Link: {link}')
3.使用CSS解析
    def parse(self, response: Response, **kwargs: Any):
        # 使用XPath选择器提取页面中的标题和链接
        titles = response.css('h2.title::text').getall()
        links = response.css('a.link::attr(href)').getall()
        # 打印结果
        for title, link in zip(titles, links):
            content = f'Title: {title}, Link: {link}'
            print(content)

@注: 限于文章篇幅,这里只做简单示例,不做过多讲解;更多使用方式请参考文档:https://www.osgeo.cn/scrapy/topics/selectors.html#selecting-attributes

3.6 解析内容

上面简单介绍了下解析语法,接着继续我们的爬虫示例,在爬取数据之前,我们先定义下数据结构,方便后面保存结构化数据;

1. 定义数据结构

在文件:scrapy_study_demo/items.py下定义数据结构:

import scrapy

class JapaneseAnimeItem(scrapy.Item):
    """ 定义动漫电影数据结构信息"""
    ranking = scrapy.Field()  # 排名
    title = scrapy.Field()  # 名称
    postImg = scrapy.Field()  # 图片海报
    year = scrapy.Field()  # 年份
    score = scrapy.Field()  # 评分
    ratingPeople = scrapy.Field()  # 评分人数
2.爬虫代码

修改完整代码如下:

import scrapy
from typing import Any, Optional, Union
from scrapy import Spider
from scrapy.http import Response
from twisted.internet.defer import Deferred
from scrapy_study_demo import JapaneseAnimeItem


class AnimeRankSpider(scrapy.Spider):
    name = "animeRank"
    allowed_domains = ["www.douban.com"]
    start_urls = ["https://www.douban.com/doulist/45955373/"]
    max_pages = 2
    result = []

    def __init__(self, name: Optional[str] = None, **kwargs: Any):
        super().__init__(name, **kwargs)
        self.page_count = 1  # 计数器,默认

    def parse(self, response: Response, **kwargs: Any):
        """解析网页内容"""
        # 打印抓取的网页HTML
        listItems = response.xpath('//div[@class="article"]//div[@class="doulist-item"]')
        for item in listItems:
            ranking = item.xpath('.//span[@class="pos"]/text()').get()
            title = item.xpath('.//div[@class="title"]/a/text()').get()
            score = item.xpath('.//span[@class="rating_nums"]/text()').get()
            ratingPeople = item.xpath('.//div[@class="rating"]/span[last()]/text()').get()
            postImg = item.xpath('.//div[@class="post"]/a/img/@src').get()
            year = item.xpath('.//div[@class="abstract"]/text()').re_first(r'年份:\s*(\d+)')
            tmp = JapaneseAnimeItem()
            tmp["ranking"] = ranking.strip() if ranking else None
            tmp["title"] = title.strip() if title else None
            tmp["postImg"] = postImg.strip() if postImg else None
            tmp["year"] = year.strip() if year else None
            tmp["score"] = score.strip() if score else None
            tmp["ratingPeople"] = ratingPeople.strip() if ratingPeople else None
            self.result.append(tmp)
            yield tmp

        # 处理分页
        next_page = response.css('.next a::attr(href)').get()
        if next_page and self.page_count < self.max_pages:
            self.page_count += 1
            print(f"准备请求{self.page_count}页, 链接:{next_page}")
            yield scrapy.Request(url=next_page, callback=self.parse)

    def close(self, reason: str) -> Union[Deferred, None]:
        # 这里可以打印汇总后的数据
        print("result:", self.result)
        return super().close(self, reason)

3.运行输出json

等代码调试完成后,可以运行下面程序,把爬取到的结果,输出到json文件,我们也可以在close或者parse函数中对数据进行入库操作,具体结合实际业务使用。

$ scrapy crawl animeRank -O animeRank.json
准备请求2页, 链接:https://www.douban.com/doulist/45955373/?start=25&sort=seq&playable=0&sub_type=
准备请求3页, 链接:https://www.douban.com/doulist/45955373/?start=50&sort=seq&playable=0&sub_type=
准备请求4页, 链接:https://www.douban.com/doulist/45955373/?start=75&sort=seq&playable=0&sub_type=
准备请求5页, 链接:https://www.douban.com/doulist/45955373/?start=100&sort=seq&playable=0&sub_type=
alt

Scrapy是一个很成熟,功能很强大的爬虫框架,通过本文我们只是触及到了它众多功能的表面,不同的项目有不同的需求,在使用Scrapy的过程中,可以不断查阅官方文档,来了解更多使用方法。后续有时间会在写一篇续篇....

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/237271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】Linux线程概念和线程控制

文章目录 一、Linux线程概念1.什么是线程2.线程的优缺点3.线程异常4.线程用途5.Linux进程VS线程 二、线程控制1.线程创建2.线程终止3.线程等待4.线程分离 一、Linux线程概念 1.什么是线程 线程是进程内的一个执行流。 我们知道&#xff0c;一个进程会有对应的PCB&#xff0c;…

GEE-Sentinel-2月度时间序列数据合成并导出

系列文章目录 第一章&#xff1a;时间序列数据合成 文章目录 系列文章目录前言时间序列数据合成总结 前言 利用每个月可获取植被指数数据取均值&#xff0c;合成月度平均植被指数&#xff0c;然后将12个月中的数据合成一个12波段的时间数据合成数据。 时间序列数据合成 代码…

ROS2 学习09--ros 中的通信接口的定义以及如何创建自定义msg、srv和action文件

在ROS系统中&#xff0c;无论话题还是服务&#xff0c;或者我们后续将要学习的动作&#xff0c;都会用到一个重要的概念——通信接口。 通信并不是一个人自言自语&#xff0c;而是两个甚至更多个人&#xff0c;你来我往的交流&#xff0c;交流的内容是什么呢&#xff1f;为了让…

数值分析(只为应付考试)

概述 研一时为应付高等工程数学考试整理的有关数值分析部分的内容&#xff0c;目的是为了应付考试。 误差 误差限与有效数字的联系 对于有 n n n 位有效数字的 x x x 的近似值 x ∗ x^* x∗, 其科学计数法表示形式 x ∗ a 1 . a 2 . . . a n 1 0 m ( a 1 ≠ 0 ) x^* …

Python开发GUI常用库PyQt6和PySide6介绍之二:设计师(Designer)

Python开发GUI常用库PyQt6和PySide6介绍之二&#xff1a;设计师&#xff08;Designer&#xff09; PySide6和PyQt6都有自己的设计师&#xff08;Designer&#xff09;&#xff0c;用于可视化地设计和布局GUI应用程序的界面。这些设计师提供了丰富的工具和功能&#xff0c;使开…

文件名生成excel清单,怎么操作?这里有简单办法

文件名生成excel清单&#xff0c;怎么操作&#xff1f;为了整理文件名称&#xff0c;有时候需要将所有的文件名称整理好并且生成excel清单&#xff0c;大家可能还不能理解是什么意思&#xff0c;其实就是将所有文件的名称整理到excel表格里&#xff0c;形成一个清单。这个操作很…

【ECharts】雷达图

let chart echarts.init(this.$refs.radar_chart); let option {title: {text: 关键过程指标,},grid: {left: 0,},legend: {data: [个人, 小组, 团队],bottom: 0,itemWidth: 6,itemHeight: 6,},radar: {// shape: circle,indicator: [{ name: 成交额, max: 30000 },{ name: 成…

yum install net-tools 命令报错,无法安装成功

编辑网卡文件 插入数据&#xff0c;输入&#xff1a; i 保存编辑&#xff1a;输入 Esc 然后:wq

数据结构学习 leetcode64最小路径和

动态规划 题目&#xff1a; 建议看这里&#xff0c;有这道题详细的解析。我觉得写的挺好。 这是我在学动态规划的时候&#xff0c;动手做的一道题。 虽然我在学动态规划&#xff0c;但是我之前学了dps&#xff0c;所以我就想先用dps试着做&#xff0c;结果发现不行&#xf…

使用Gitee中的CI/CD来完成代码的自动部署与发布(使用内网穿透把本地电脑当作服务器使用)

&#x1f4da;目录 &#x1f4da;简介:⚙️ 所需工具&#xff1a;&#x1f4a8;内网穿透配置&#x1f4ad;工具介绍✨命令安装&#x1f38a;配置Cpolar&#x1f573;️关闭防火墙&#x1f95b;防火墙端口放行规则&#xff08;关闭防火墙可以忽略&#xff09;&#x1f36c;小章总…

打造明厨亮灶工程,需要哪些AI视频智能算法助力?

旭帆科技AI智能监控可以通过摄像头、传感器和数据处理等技术手段&#xff0c;实时监测厨房人员着装、行为与烟火等&#xff0c;对厨房实时监控进行分析与记录&#xff0c;从而实现明厨亮灶场景的搭建&#xff0c;保障食品安全和服务质量。 1、烟火识别 对于后厨来说&#xff0…

字符串函数的模拟实现(部分字符串函数)

strlen函数模拟 size_t my_strlen(const char* arr) {int count 0;while(*arr){arr;count;}return count;} int main() { printf( " %zd", my_strlen("adsshadsa"));}//模拟实现strlen函数 strcpy函数模拟 char* my_strcpy(char* arr1, const char* ar…

在Windows上使用 Python

本文档旨在概述在 Microsoft Windows 上使用 Python 时应了解的特定于 Windows 的行为。 与大多数UNIX系统和服务不同&#xff0c;Windows系统没有预安装Python。多年来CPython 团队已经编译了每一个 发行版 的Windows安装程序&#xff08;MSI 包&#xff09;&#xff0c;已便…

C++——C++11(2)

我在我的C异常博客中曾提到&#xff0c;对于异常的处理经常会导致内存泄漏问题&#xff0c; 一种解决方法是异常的重新抛出&#xff0c;还有一种就是RAII&#xff0c;那么RAII的思想体现 在C中就是智能指针&#xff0c;所以接下来我将简单的介绍&#xff0c;什么是RAII&#xf…

计算机网络 网络层下 | IPv6 路由选择协议,P多播,虚拟专用网络VPN,MPLS多协议标签

文章目录 5 IPv65.1 组成5.2 IPv6地址5.3 从IPv4向IPv6过渡5.3.1 双协议栈5.3.2 隧道技术 6 因特网的路由选择协议6.1 内部网关协议RIP6.2 内部网关协议 OSPF基本特点 6.3 外部网关协议 BGP6.3.1 路由选择 6.4 路由器组成6.4.1 基本了解6.4.2 结构 7 IP多播7.1 硬件多播7.2 IP多…

Inscribe:应用非定向资产交易协议 布局巨大铭文赛道

随着比特币出现了一定的回调&#xff0c;铭文市场也出现了50%以上的跌幅&#xff0c;但是从市场的长期发展来看&#xff0c;铭文市场空间巨大&#xff0c;仍然是未来千亿级的蓝海市场&#xff0c;那么这样的回调阶段正式各类优质项目深度BUILD 扩展自己产品生态提升竞争力的关键…

还在用QQ拼音输入法吗?赶快卸载吧~!

最近总觉得我的C盘在莫名其妙的减少。之前的电脑C盘只有240G&#xff0c;所以我很在意C盘空间。但是&#xff0c;我发现买了新电脑&#xff0c;C盘空间也在莫名其妙减少。 随挨个文件夹检查。最后发现&#xff0c;QQ拼音的 dict 文件夹很大&#xff0c;居然有 30G多G。 30多~…

如何快速优化大数据量订单表

场景 本篇分享以前在广州一家互联网公司工作时遇到的状况及解决方案,这家公司有一个项目是SOA的架构,这个架构那几年是很流行的,哪怕是现在依然认为这个理念在当时比较先进。 当时的项目背景大概是这样,这家公司用的是某软提供的方案,项目已经运行3年多,整体稳定。 数据…

mysql mha高可用

一、前言 在原本的一主两从数据库架构中&#xff0c;是没有高可用功能的&#xff0c;当主库挂了时不会自动将剩下的从从升级为主库&#xff0c;只能等待主库恢复才能使用&#xff0c;或者手动切换&#xff0c;但是手动切换后需要更改后端服务中的数据库地址信息&#xff0c;在此…

架构设计到底是什么?

文章目录 架构设计有哪些内容&#xff1f;架构原理与技术认知分布式技术原理与设计中间件常用组件的原理和设计问题数据库原理与设计问题分布式缓存原理与设计问题互联网高性能高可用设计问题 技术认知架构分析问题分析能力边界 架构设计&#xff0c;是中高级研发工程师逃不开的…