在这里插入图片描述

文章目录


学习目标

学完这一课,你将能够:

  1. 区分GET与POST场景——不仅知道“GET用于获取数据、POST用于提交数据”的口诀,还能在真实抓包时判断登录接口应该用哪种方法、参数格式是Form还是JSON
  2. 掌握两种POST传参方式——清楚data=json=的业务差别,能根据登录页F12抓包的结果判断应该选哪种格式
  3. 理解Cookie与Session原理——画得出“登录→下发Session ID→后续请求携带→服务端识别”的完整流程图,而不是停留在背诵概念
  4. 使用Session对象自动管理Cookie——写出Session模拟登录的完整代码,全程不需要手动提取/拼接Cookie字符串
  5. 爬取登录可见数据——成功登录后访问需要登录才能查看的页面,拿到登录态保护的数据
  6. 处理常见登录失效问题——Cookie过期、验证码拦截、表单参数动态变化时,知道排查方向和解决方案

这一课终于要处理那些“必须登录才能看到”的数据了。我们会用爬虫去模拟一个真实的登录过程,像真人一样提交用户名和密码,拿到服务器下发的Cookie,然后用这个Cookie去访问需要登录权限的页面。

整个学习过程完全使用公开的爬虫练习网站**(httpbin.org、scrapingclub.com等)** ,不涉密、不违规,所有代码都能在你的电脑上安全运行。

注意:本课所有实战网站均专为爬虫教学设计。请勿将本课代码直接用于爬取他人账号、批量采集用户个人数据或绕过你家公司的业务网站登录流程,否则自愿承担法律风险。

一、再谈GET vs POST:不只是“一个拿数据、一个发数据”

我们在第2课已经学过GET和POST的基础概念,但当时更多是语法层面的认识。在登录这个场景里,我们必须在理解原理的基础上,搞清楚**“登录接口到底该怎么找”**。

1.1 登录场景中GET和POST的真正分工

在浏览器里完成一次登录提交时,事情的本质是:

  • 浏览器收到用户填写的HTML表单(<form>标签内的所有字段,例如type="text"的账号输入框和type="password"的密码框)
  • 浏览器按照这个表单指定的method属性(GET或POST),将这些字段打包成HTTP请求发送给服务器。

现在绝大多数现代网站登录页的formmethod属性都是POST,原因有三:

  1. 安全性:登录参数(用户名、密码、口令token)放在URL里,会被浏览器历史、网络路由日志、代理服务器等环节看到,风险极高。
  2. 长度限制:复杂Token/二次校验参数可能超出URL的长度限制。
  3. 操作语义匹配:登录本质上是创建一个新的“已认证会话”,这在HTTP规范中更接近POST语义。

实际工作中,如果某个登录页的method="GET",你要么加白名单绕过检查,要么就先去建议前端同事改成POST——在现代专业开发中,GET方式提交登录参数几乎等于在事故边缘试探。

那么,以后你在F12里看到一个登录请求,怎么快速判断它应该用POST模拟?

打开开发者工具的Network面板,点击登录按钮,找到请求列表中的那个请求。看一眼它的Method列——几乎所有现代登录流程都是POST。接下来看请求的参数格式(是Form Data还是JSON),这决定了我们写代码时应该用data=还是json=传参,我们5分钟后就会详细讲到。

1.2 POST的本质:请求体里放数据

GET请求把参数放在URL的查询字符串中(?key1=value1&key2=value2),用户能清清楚楚看到自己填了什么账号密码——这不合适身份验证(暴露隐私)也不漂亮。而POST请求将参数放在HTTP请求体中,不暴露在URL上。

在Python requests库中,只写requests.post()并不能帮你发真正的表单数据,还需要配套data=json=来填充请求体。

1.3 data= vs json= —— 不是选美,是后端说了算

这是新手写模拟登录时最容易卡住的环节。我们结合一个非常生动的对比来理解。

data= —— 模拟HTML表单提交

当你在浏览器里填写一个登录表单,点击“登录”按钮,浏览器默认发送的是Content-Type: application/x-www-form-urlencoded,意味着请求体的格式是这样的:username=admin&password=123456

模拟这种登录,你应该写:

login_data = {
    'username': 'your_username',
    'password': 'your_password'
}
response = session.post(login_url, data=login_data)

注意 data= 而不是 json=。requests库会自动把字典转换成username=admin&password=123456这样的字符串,并设置正确的Content-Type

json= —— 提交JSON数据

现在很多网站已经用前后端分离的REST API代替传统表单了。你的浏览器在登录时发送的不是表单字符串,而是一个JSON对象放在请求体中,例如{"username":"admin","password":"123456"},并且请求头里Content-Type: application/json

这时你应该写成:

login_data = {
    'username': 'your_username',
    'password': 'your_password'
}
response = session.post(login_url, json=login_data)

requests会自动将字典转成JSON字符串,并设置Content-Type: application/json

如果不确定登录接口需要哪一种,怎么办?

用F12看一下。在Network面板中找到登录请求,点开查看Request Headers中的Content-Type

  • application/x-www-form-urlencoded → 用data=
  • application/json → 用json=

如果选错了,后端可能收不到参数,返回400 Bad Request,或者登录成功后Session ID生成但你后续请求依然带不上正确的Cookie。

二、Cookie与Session原理(爬虫必须懂的核心)

2.1 为什么需要Cookie和Session?

HTTP本身是无状态的协议。每一次浏览器发给服务器的请求都与上一次独立,服务器不会自动"记住"你是谁。你在淘宝首页点了登录按钮,登录成功。下一秒你在购物车里刷新页面,服务器又想不起来你刚才登录过了——没有Cookie和Session,在线购物的体验就是“每点一步都要重新登录一次”。

为了解决这个问题,Cookie和Session机制诞生了。

  • Cookie(小饼干):存储在浏览器的一小块数据。服务器通过Set-Cookie响应头把这块数据发送给客户端。客户端(浏览器)将其保存下来,并在后续每次请求中带上它发回给服务器,作为凭证。
  • Session(会话):存在服务器端的一块存储区域。每个用户被分配一个唯一的Session ID,服务器把该用户在一段时间内的状态(登录信息、购物车等)存在这个Session里。
  • 流程:服务器在响应里让浏览器保存一个Set-Cookie: sessionid=abc123 → 浏览器收到后,把sessionid=abc123存在Cookie中 [7†L5-L7] → 下一次请求,浏览器自动带上Cookie → 服务器通过sessionid找到用户的Session,知道“哦,是admin已经登录过了”。

所以,爬虫登录的任务就是:模拟浏览器发送登录POST请求,接收服务器的Set-Cookie,然后带着这些Cookie去访问后续受保护的页面

2.2 会话Cookie vs 持久Cookie

会话Cookie(Session Cookie):没有设置过期时间(Expires)或存在Max-Age参数被标记为-1,关闭浏览器就消失。大多数页面的登录态就是会话Cookie,浏览器进程结束就丢失。

持久Cookie(Persistent Cookie):设置了Expires或Max-Age属性,超时后才会失效。爬虫把这部分存到本地文件里,可以跨脚本跨天复用。

2.3 爬虫绝不能硬塞假Cookie

有些人图省事,爬虫代码里直接写死了从浏览器复制来的一段Cookie字符串:

# ❌ 危险的写死Cookie写法
headers = {
    'Cookie': 'sessionid=abc123; token=xyz789'
}
response = requests.get(url, headers=headers)

这是低级行为:不做登录校验、不模拟登录,只靠复用旧的Cookie。几小时或几天后Cookie就过期了,爬虫直接失效,且这种在代码里嵌入真正的Cookie值(还带着敏感账号数据)是严重违规——一旦被代码仓库公开或上传到GitHub,你的账号信息就全暴露了。

2.4 专业做法:requests.Session()自动管理Cookie

requests.Session()是Python requests库中专门用来管理会话状态的对象。你用一个Session()对象发送登录请求,它会自动接收并保存服务端返回的Set-Cookie,然后在同一个Session后续发起的请求中自动帮你携带这些Cookie。整个过程你完全不用手动碰Cookie字符串。

# ✅ 推荐写法
session = requests.Session()           # 创建"浏览器"实例
response = session.post(login_url, data=login_data)  # 浏览器记住了Set-Cookie
protected_response = session.get(protected_url)      # 自动带上Cookie

三、实战篇一:用httpbin.org理解GET/POST与Cookie

在开始模拟真实登录之前,我们先在一个不会阻挠你的调试网站上把机械知识弄清楚。httpbin.org是一种“回声服务器”:你向它发送请求,它会把请求的信息原封不动返回给你。

这样做的好处是:我们可以100%确信自己写的POST参数格式、Cookie携带方式是否正确,不必踩网站反爬的地雷。

3.1 向httpbin发送GET请求

import requests

url = 'https://httpbin.org/get'
params = {'page': 1, 'size': 10}
response = requests.get(url, params=params)
print(response.json())

params=这个参数会让requests自动把字典解析成?page=1&size=10拼接到URL上。返回结果中就能看到完整的请求信息。

3.2 向httpbin发送POST请求(data方式 vs json方式)

import requests

url = 'https://httpbin.org/post'

# data方式(表单格式)
form_data = {'username': 'alice', 'password': 'secret'}
resp1 = requests.post(url, data=form_data)
print(resp1.json()['form'])  # 输出 {'username': 'alice', 'password': 'secret'}
print(resp1.json()['headers']['Content-Type'])  # 'application/x-www-form-urlencoded'

# json方式
json_data = {'username': 'alice', 'password': 'secret'}
resp2 = requests.post(url, json=json_data)
print(resp2.json()['json'])   # 输出 {'username': 'alice', 'password': 'secret'}
print(resp2.json()['headers']['Content-Type'])  # 'application/json'

看到区别了吗?

  • data=:参数在响应JSON的"form"字段里,Content-Type为application/x-www-form-urlencoded
  • json=:参数在响应JSON的"json"字段里,Content-Type为application/json

你在使用requests库写登录时,拿不准应该用哪个,就先在httpbin上把自己的代码重放一遍——查看"form""json"哪个字段有数据。

3.3 使用Session向httpbin发送带Cookie的请求

import requests

session = requests.Session()
# 手动设置Cookie(只是为了演示)
session.cookies.set('session_id', 'abc123')
response = session.get('https://httpbin.org/cookies')
print(response.json())  # {'cookies': {'session_id': 'abc123'}}

服务器原样返回了你在请求中发送的Cookie。

四、实战篇二:scrapingclub模拟登录完整流程

scrapingclub.com/exercise/basic_login/ 是一个专门为爬虫登录练习设计的公开网站,无验证码、表单参数简单、专门容错爬虫访问。它非常适合作为新手模拟登录的第一站。

4.1 分析登录请求(F12抓包)

步骤(参考第3课的抓包流程):

  1. 在Chrome中打开 https://scrapingclub.com/exercise/basic_login/
  2. 按F12打开开发者工具,切换到Network标签
  3. 在登录界面输入任意用户名密码(随便输,因为这是练习网站,它不校验真实账号)
  4. 观察Network中出现的请求:找到一个POST类型的请求,URL是https://scrapingclub.com/exercise/basic_login/
  5. 点开它,查看:
    • Request Method:POST
    • Request Headers → Content-Type: application/x-www-form-urlencoded(说明应该用data=传参)
    • Payload / Form Dataname=hijacker&password=123456

发现没有任何动态参数(无csrf_token、无时间戳等),登录参数只有namepassword两个字段。

4.2 第一次尝试:不带Session直接登录

import requests

login_url = 'https://scrapingclub.com/exercise/basic_login/'
data = {'name': 'test_user', 'password': 'test_pass'}

response = requests.post(login_url, data=data)
print(response.status_code)
print(response.text[:500])

这段代码会返回200,但页面可能仍然是登录前的状态。为什么?如果响应里包含了登录成功后的跳转URL,但因为我们没告诉浏览器去跟随,就看不到后面的页面,更不会把Cookie带回后续请求。而真正的模拟登录需要把这次请求的Cookie保存下来,并用于下一次访问。

4.3 使用Session模拟登录完整流程(推荐)

import requests
from bs4 import BeautifulSoup

# 1. 创建Session对象(就像一个全新的浏览器窗口)
session = requests.Session()

login_url = 'https://scrapingclub.com/exercise/basic_login/'
protected_url = 'https://scrapingclub.com/exercise/basic_login/'  # 登录后可见的内容页,我这里还是用同一个URL代替

# 2. 可选:先GET一下登录页,收集可能隐藏的字段,并预热Session
# 有些网站需要CSRF token才能登录,先get登录页从中提取token
get_response = session.get(login_url)
soup = BeautifulSoup(get_response.text, 'lxml')
# 假设有csrf_token隐藏表单,取出它
token_tag = soup.find('input', {'name': 'csrf_token'})
csrf_token = token_tag.get('value') if token_tag else None

# 3. 构造登录数据
login_data = {
    'name': 'your_username',  # 这个网站注册的账号是你的邮箱?不对,此练习网站不需要注册!直接随便填一个账号即可。但为了体验流程,建议注册一个测试账号。
    'password': 'your_password'
}
# 若有csrf_token,加到data字典里
if csrf_token:
    login_data['csrf_token'] = csrf_token

# 4. 发送登录POST请求(用data参数,因为Content-Type是表单格式)
login_response = session.post(login_url, data=login_data)

# 5. 检查登录是否成功(通过状态码或页面内容中的特定文本)
if login_response.status_code == 200 and 'Your Profile' in login_response.text:
    print("✅ 登录成功!")
else:
    print("❌ 登录失败,检查表单参数或账号密码")
    print(login_response.text[:500])
    exit()

# 6. 现在Session里已经有了登录Cookie,直接请求受保护页面
profile_response = session.get(protected_url)
print("受保护页面长度:", len(profile_response.text))
# 可以进一步解析profile_response.text提取用户数据

重点理解:只要登录POST请求成功,后续所有通过同一个session对象发送的请求,都会自动带上之前收到的Cookie。这和你在浏览器里登录后点链接是同一个逻辑。

4.4 验证Cookie是否正确保存

# 打印当前Session中存储的所有Cookie
for cookie in session.cookies:
    print(f"{cookie.name}: {cookie.value}")

你会看到类似sessioncsrftoken等名称的Cookie键值对。这些值就是你所穿“会员卡”。不需要手动提取再放到headers里。

五、实战篇三:httpbin Basic Auth认证方式

有些网站(或内部API服务)使用的是HTTP Basic Authentication——即在请求头里内置Authorization: Basic <base64编码的字符串>。requests库已内置支持。

打开https://httpbin.org/basic-auth/user/pass,这个接口期望传入user作为用户名,pass作为密码。如果认证通过,返回200;否则返回401 Unauthorized。

import requests

url = 'https://httpbin.org/basic-auth/user/pass'
# 方法一:直接在auth参数里传一个元组
response = requests.get(url, auth=('user', 'pass'))
print(response.status_code)  # 200
print(response.json())

很多企业内部API均采用这种认证,一个auth = (用户名, 密码)就搞定了,不需要自己算Base64。

六、实战篇四:Cookie持久化存储(程序重启后仍能使用登录态)

如果你的爬虫较长运行时间后停止,下次任务开始时如果网站Cookie没有过期,你其实不必每次启动都重新登录。可以把登录后获得的Cookie存到本地文件,下次启动时预先加载到Session中。

6.1 保存Cookie到文件

import pickle

# 假设session已经登录成功
with open('cookies.pkl', 'wb') as f:
    pickle.dump(session.cookies, f)

6.2 从文件恢复Cookie

with open('cookies.pkl', 'rb') as f:
    cookies = pickle.load(f)

new_session = requests.Session()
new_session.cookies.update(cookies)

# 现在new_session里已经有了登录态,可以直接请求受保护页面,使用前先检测一下有没有失效
test_resp = new_session.get(protected_url)
if test_resp.status_code == 200 and len(test_resp.text) > 500:
    print("Cookie有效,继续任务")
else:
    print("Cookie已失效,需要重新登录")

6.3 存储Cookie的安全注意事项

  • 不要把cookies.pkl文件提交到Git仓库。
  • 多账户登录时,按账号分别存储Cookie文件。
  • Cookie过期检测:建议每次从文件加载后,先请求一个轻量级受保护接口(如/api/user/profile或登录后才会显示的用户头像的URL),检查响应状态码200且包含用户信息字段。如果重新请求时返回401或302跳转到登录页,则需重新执行登录流程。

七、新手常见问题和解决方案

7.1 登录失败:参数位置放错(data vs json 搞反)

现象:登录请求返回400 Bad Request,或者服务端返回"Missing parameters"

分析:你用json=提交表单数据,但后端仅支持传统的application/x-www-form-urlencoded。或者反过来,后端只认JSON,你误用了data=

解决方案:登录接口支持哪种格式在Network面板的Request Headers里一清二楚,不要靠猜。根据Content-Type决定用哪一类参数。

7.2 Cookie失效与自动重登录

现象:登录后运行10分钟,突然所有请求返回401或302跳转到登录页。

本质:服务端校验Cookie失效,例如sessionid过期。

解决方案

  • 在每次关键请求前先检查响应(如状态码401或页面标题包含“login”)判断Session是否过期。
  • 检测到过期后自动触发重新登录流程,然后继续未完成的采集任务。
  • 限制重试次数,避免无限循环(设置最大重登次数3次)。
def ensure_logged_in(session, login_func):
    """检查登录状态,过期则重新登录"""
    test_url = 'https://scrapingclub.com/exercise/basic_login/'
    resp = session.get(test_url)
    if resp.status_code != 200 or 'login' in resp.url:
        print("检测到登录失效,正在重新登录...")
        login_func(session)

7.3 登录页有CSRF Token怎么办

现象:F12抓包看到登录POST请求里除了usernamepassword外,还有一个动态的csrf_tokenauthenticity_token

本质:网站防止跨站请求伪造,每次进入登录页都会生成一个令牌,提交时必须携带该令牌。

解决方案:登录前先发一个GET请求到登录页,用BeautifulSoup从HTML中提取该隐藏字段的值,再将其连同用户名密码一起POST提交。

# 先GET登录页,提取csrf_token
login_page = session.get(login_url)
soup = BeautifulSoup(login_page.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrf_token'}).get('value')

# 构造data时加上它
login_data = {
    'username': 'user',
    'password': 'pass',
    'csrf_token': csrf_token
}
session.post(login_url, data=login_data)

7.4 验证码拦截

现象:接连几次数正常登录请求后,登录接口忽然返回一个图片链接或“请输入右侧验证码”的响应,干扰爬虫正常识别。

本质:网站检测到你的请求频率异常(或来自云服务器IP)、User-Agent特征过于单一,认定是机器行为,临时插入了验证码。

解决方案(按难度和合规性排序):

  • 优先绕开:加长两次登录尝试的间隔,模拟人类操作的等待时间(比如真实用户手动输入账号密码耗时5~8秒,你的脚本第二次登录争取间隔6秒以上)。
  • 手动打码:对于低频爬虫,可把验证码图片下载到本地,人工看一眼后填入再继续。
  • 第三方打码平台:若批量运行必须自动化,对接打码平台API(如超级鹰、云打码),代价是每次几毛钱。但不建议新手过早接触,请先搞明白基础登录流程后再评估商业成本。

7.5 前端加密密码——这是模拟登录中最难的一环

现象:输入密码123456,经过抓包分析发现login_requestpassword字段的值看起来是ef92b778bafe771e89245b89ecbf08之类的一串乱码(哈希值)。表示前端JS把密码加密了之后再提交。

本质:网站用了前端加密库(如RSA加密、MD5加盐)。仅靠简单模拟POST请求已不够,你必须理解加密逻辑。

解决方案:这是一种软性反爬。

  • 逆向JS:在开发者工具的Sources里找到加密函数,用PyExecJS、Node.js等复刻加密逻辑。
  • 浏览器自动化:换用Selenium或Playwright,直接驱动真实浏览器执行登录,让JS自己加密,爬虫只需等待结果。
  • 降低难度预期:本专栏第14课之后才会开展前端加密逆向。

如果遇到前端加密,先确认你的目标是不是公开发布的教学训练站点。若用于商业目的,建议优先查找是否有官方开放API。

八、Cookie和Session的安全边界(法律法规重申)

Cookie和Session在合法爬虫中的使用权绝不是无限制的。

  • 仅用于你自己的账号:爬取自己的电商订单记录做个人记账管理,合规且安静。企图通过批量获取他人的Cookie来“借用”他的登录态,必然涉及非法获取他人计算机信息系统数据(侵犯公民个人信息罪)。
  • 永远不要硬编码Cookie:不要从浏览器复制Cookie字符串硬塞进爬虫代码,更不要把这种代码公开到GitHub。
  • 尊重网站robots.txt:即使你已登录账号,大型社交平台、电商平台的服务条款里通常禁止自动化采集用户生成内容。
  • 低频、以人为本模拟:应使登录求请求的间隔、User-Agent旋转等符合真人行为模式,不要短时间内对同账号频繁调用登录登出接口。

作为新手,你可以明确划一条红线:只模拟登录你自己的账号,并只采集与自己身份相符的数据

九、总结

本课核心知识清单

知识点 掌握程度
GET vs POST在登录场景中的应用 能准确判断登录接口使用哪种方法
data= vs json=的登录应用场景 能通过F12的Content-Type决定传参格式
Cookie与Session工作原理 能讲出Session ID的传递过程
requests.Session()自动管理Cookie 能独立写出模拟登录并访问受保护页面代码
Cookie持久化存储与恢复 能跨程序复用登录态
常见登录失败问题的分析解决路径 CSRF token、验证码、前端加密等问题的排查手段

一步一个脚印

从这一节课开始,你爬虫的“权限”进一步扩展:从爬取所有人都能访问的公开新闻,到爬取“仅登录后可见”的个人数据。这不仅是功能的延伸,更是责任的升级。请在每一行代码里都写清楚“这是我的账号,我为自己授权”

下一课预告:当Session也无法直接模拟登录的网站(如有复杂JS加密、二次验证),我们将借助浏览器自动化工具Selenium,让它像真人一样在浏览器里点击、输入,然后从渲染后的最终页面拿数据。跨越动态渲染这道坎,你的爬虫技术深度又能上一个台阶。

十、课后作业

作业1:用httpbin测试data和json差异(必做)

请求https://httpbin.org/post,分别用data=json=提交以下参数:

{'name': 'crawler', 'level': 9}

分析两个响应中"form""json"字段的差异,并输出Content-Type的值。

作业2:使用requests.Session模拟登录scrapingclub(必做)

  1. 注册一个scrapingclub.com账号(需邮箱验证),或直接用该练习网站的demo账号登录。
  2. F12抓包找出登录接口URL及各参数名。
  3. 编写Python代码完成模拟登录并检测登录成功的标志。
  4. 登录成功后,统计登录后的返回页面中包含多少个<div>标签。

作业3:处理CSRF的保护网站(选做)

选择一个有CSRF保护的Demo网站(可在GitHub找到flask-login的csrftoken-demo,或自己本地启动flask应用),完成代码:

  • 先发送GET请求获登录页,从HTML提取csrf_token
  • 构造包含csrf_token的POST参数,完成登录
  • 验证登录成功后可以访问一个受保护的路由

作业4:Cookie持久化实验(必做)

  • 将作业2中成功的Session Cookie,用pickle保存到my_cookies.pkl
  • 关闭当前Python解释器,新开一个进程中加载该Cookie文件。
  • 请求一个受保护页面,判断加载的Cookie是否仍有效。
  • 如果无效,写出失效排查思路。

作业5:登录过期自动重登(选做)

基于作业2模拟登录成功的代码,写入一个函数get_with_retry(session, url, max_retries=2)

  • 请求受保护页面时检测是否跳转到登录页
  • 若已跳转(失效迹象),执行重新登录函数,然后重试请求
  • 限制最大重登次数,超过则抛出异常

作业6:阅读和遵守模拟登录的法务红线(必做)

阅读你常用的某一个社交平台的服务条款(如知乎、微博,搜索关键词"自动化程序"),找出至少两条关于禁止爬虫/模拟登录的条款,把你的理解和应对策略写在文档里。培养“先看条款,再写代码”的职业习惯。

结束语:

学到这里,你已经拥有了爬虫工程师的常规武器:requests、正则、BeautifulSoup、XPath、Session模拟登录。从静态网页到登录态数据,你现在都具备了应付的能力。很多公司内部的简单数据采集任务,你已经完全可以胜任了。但在遇到更强悍的反爬网站时,模拟登录可能还不够(代码层面的请求能伪造得再像是浏览器,也终究不是真实浏览器)。下一节课,我们将在Selenium中,请出浏览器真正的本体。


🔗《20节课精通网页爬虫》系列课程导航

GO


🌟 感谢您耐心阅读到这里!
💡 如果本文对您有所启发欢迎:
👍 点赞📌 收藏 📤 分享给更多需要的伙伴。
🗣️ 期待在评论区看到您的想法, 共同进步。
🔔 关注我,持续获取更多干货内容~
🤗 我们下篇文章见~

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐