Photoshop Web版本用了哪些CSS技术

news2024/11/25 2:26:08

本文翻译自 CSS Findings From Photoshop Web Version
,作者:Ahmad, 略有删改。

几周前,Adobe发布了一个Web版的Photoshop,它是用WebAssembly、Web组件、P3颜色等网络技术构建的。

Photoshop是我14岁时学会的第一个专业设计应用程序。这是我成为设计师并最终成为前端开发人员的原因之一。正因为如此,我认为看看CSS是如何助力像Photoshop这样的大型应用开发会很有趣。

在这篇文章中,我将分享在Web版的Photoshop中我觉得有趣的CSS发现。

Photoshop 旧版Logo

我注意到的第一件事是在浏览器控制台中使用Photoshop(1990-1991)的旧Logo。

你会对这样的东西是如何制作的感到好奇吗?以下是代码:

console.info(
  "%c %cAdobe %cPhotoshop Web%c  %c2023.22.0.0%c  %c56043548b47",
  "padding-left: 36px; line-height: 36px; background-image: url('data:image/gif;base64,R0lGODlhIAAgAPEBAAAAAP///wAAAAAAACH5BAEAAAIALAAAAAAgACAAAAKkhC+py3zfopxGvIsztsCGD4La2FVAGBoBuZnox45WcqLsum5KDWdvf1nwTo+fLbgDqo7LFCJJbOY0oidt6ozVKrtib0qaCnlYcJh7rf5iK6HZaM64VeS6L+pWf89WT+6vRAUBBVQ1gpOTJ4IYdxCnOBSJ8ZhkZNekk5ZSxpTpt6Y1eEVm00j3VALDmBXVyPEJB2r2ShoLh2ASqvU60dsr5yuBUQAAOw=='); background-size: 32px; background-repeat: no-repeat; background-position: 2px 2px", "background: #666; border-radius:0.5em 0 0 0.5em; padding:0.2em 0em 0.1em 0.5em; color: white; font-weight: bold", "background: #666; border-radius:0 0.5em 0.5em 0; padding:0.2em 0.5em 0.1em 0em; color: white;", "", "background: #c3a650; border-radius:0.5em; padding:0.2em 0.5em 0.1em 0.5em; color: white;", "", "background: #15889f; border-radius:0.5em; padding:0.2em 0.5em 0.1em 0.5em; color: white;");

body 元素

要让Photoshop这样的应用在Web网页上有真实应用的感觉,首先需要防止滚动。为了实现这一点,<body>元素设置了position: fixedoverflow: hidden

body,
html {
  height: 100%;
}

body {
  font-family: adobe-clean, sans-serif;
  margin: 0;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

<body>元素内部,也有多个根元素。

<psw-app>
  <psw-app-context>
    <ue-video-surface>
      <ue-drawer>
        <div id="appView">
          <psw-app-navbar></psw-app-navbar>
          <psw-document-page></psw-document-page>
        </div>
      </ue-drawer>
    </ue-video-surface>
  </psw-app-context>
</psw-app>

最里面是包含导航和文档页面的元素 #appView

#appView {
  background-color: var(--editor-background-color);
  color: var(--spectrum-global-color-gray-800);
  display: flex;
  flex-direction: column;
}

几乎都是 Flexbox 布局

当构建一个web应用程序时,使用flexbox有很多好处。当我想到Flexbox和Photoshop一起出现时,我的感觉是很复杂。

Photoshop是一个著名的设计软件,是许多人进入设计领域的第一款软件。另一方面使用Flexbox构建组件变得更容易,对CSS对新手来说更容易。

无需使用clearfix清除浮动,只需添加display: flex,然后根据需要设置子项的样式。让我们探索Photoshop中的相关Flexbox使用情况。

导航栏

我喜欢这里的命名。他们使用“start”,“center”和“end”,而不是使用“leftcenterright”,。

对于可以从左到右(LTR)或从右到左(RTL)工作的应用程序来说,这种逻辑命名是正确的。

Context Bar

在构建像Photoshop这样的复杂应用程序时,嵌套的flexbox容器是必要的。在下图中,我在上下文栏中突出显示了两个容器。

第一个容器用于抓取动作。第二个容器包含所有操作和按钮。

.container {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--spectrum-global-dimension-size-50);
}
  • gap的使用对定义间距有很大帮助。相比使用margin或padding就好多了。

  • 名称.container太通用了,但它在这里恰到好处,因为这是一个Web组件,所有的样式都被封装在内部。

图层

由于图层功能是Photoshop的重要组成部分,因此它可能是新手将要学习的前几件事之一。我好奇地检查了它们背后的CSS实现。

这里是层组件的HTML代码:

<psw-tree-view-item indent="0" layer-visible can-open dir="ltr" open>
  <div id="link">
    <span id="first-column"></span>
    <span id="second-column"></span>
    <span id="label"></span>
  </div>
</psw-tree-view-item>

你认为这里使用ID是完全可以的吗?由于这是一个Web组件,所以#first-column ID在页面上出现多少次并不重要。

#link元素是主要的flexbox包装器,#label中的元素也是flexbox包装器。

<div class="layer-content layer-wrapper selected">
  <psw-layer-thumbnail></psw-layer-thumbnail>
  <div class="name" title="Layer name">Layer name</div>
  <div class="actions"></div>
  <overlay-trigger></overlay-trigger>
</div>

让我们看看子层的缩进是如何完成的。

  • :host()表示层组件
  • 如果有HTML属性存在indent=1,则更改第一列的padding-right

CSS :host 是一个伪类选择器,它用于选择当前组件的宿主元素。:host 选择器只能在 Shadow DOM 中使用,因为它选择的是组件的根元素,而不是组件内部的子元素。

:host([dir="ltr"][indent="1"]) #first-column {
  padding-right: var(--spectrum-global-dimension-size-200);
}

如果是indent=2,则通过CSS calc()函数将padding-right的值乘以2。

:host([dir="ltr"][indent="2"]) #first-column {
  padding-right: calc(2 * var(--spectrum-global-dimension-size-200));
}

在浏览器中,我尝试嵌套到第6级。下面是一张真实的截图:

当看到这个的时候,我检查Figma背后的CSS实现。他们使用了一个间隔组件来增加嵌套层的间距。

有趣的是,两个主要的设计应用程序使用了不同的技术来实现相同的目标。

关于 CSS Grid 布局

新建文件弹窗

创建新的Photoshop文件时,您可以选择预定义的大小列表。为了实现这一点,有一个包含多个选项卡和一个活动面板的布局。

HTML代码如下:

<sp-tabs
  id="tabs"
  quiet=""
  selected="2"
  size="m"
  direction="horizontal"
  dir="ltr"
  focusable=""
>
  <div id="list"></div>
  <slot name="tab-panel"></slot>
</sp-tabs>

在CSS中,有一个1列2行的主网格。第一行是auto,第二行跨越可用空间。

:host {
  display: grid;
  grid-template-columns: 100%;
}

:host(:not([direction^="vertical"])) {
  grid-template-rows: auto 1fr;
}

这里有几件事:

  • 使用CSS:not()选择器
  • 使用[attr^=value]选择器排除属性direction的值以vertical开头的HTML元素。

我认为这是一种条件CSS技术。

我尝试将direction属性更改为vertical。

下面是基于属性更改的CSS:

:host([direction^="vertical"]) {
  grid-template-columns: auto 1fr;
}

:host([direction^="vertical-right"]) #list #selection-indicator,
:host([direction^="vertical"]) #list #selection-indicator {
  inline-size: var(
    --mod-tabs-divider-size,
    var(--spectrum-tabs-divider-size)
  );
  inset-block-start: 0px;
  inset-inline-start: 0px;
  position: absolute;
}

要突出显示哪个选项卡项处于活动状态,有一个相对于选项卡列表定位的#selection-indicator元素。

图层属性

我很喜欢这里的CSS网格。它适用于在网格中对齐多个元素的问题。

在CSS中,我注意到以下代码:

.content {
  position: relative;
  display: grid;
  grid-template-rows: [horizontal] min-content [vertical] min-content [transforms] min-content [end];
  grid-template-columns: [size-labels] min-content [size-inputs] auto [size-locks] min-content [space] min-content [position-labels] min-content [position-inputs] auto [end];
  row-gap: var(--spectrum-global-dimension-size-150);
}

这里使用的技术称为命名网格线。这个想法是你命名每个列或网格,然后定义其宽度。列和行的宽度为automin-content。这是制作动态网格的好方法。

这样每个网格项都应该定位在网格中。以下是一些例子:

.horizontal-size-label {
  grid-area: horizontal / size-labels / horizontal / size-labels;
}

.vertical-position-input {
  grid-area: vertical / position-inputs / vertical / position-inputs;
}

.horizontal-position-input {
  grid-area: horizontal / position-inputs / horizontal /
    position-inputs;
}

另一个引起我注意的细节是在网格项中使用position: absolute。锁定按钮被放置在网格的中心,但它需要在lefttop位置稍微偏移一些。

.lock-button {
  grid-area: horizontal / size-locks / horizontal / size-locks;
  position: absolute;
  left: 8px;
  top: 22px;
}

Drop-Shadow 输入框

这是许多CSS网格用于输入字段布局的示例。

:host([editable]) {
  display: grid;
  grid-template-areas:
    "label ."
    "slider number";
  grid-template-columns: 1fr auto;
}

:host([editable]) #label-container {
  grid-area: label / label / label / label;
}

:host([editable]) #label-container + div {
  grid-area: slider / slider / slider / slider;
}

:host([editable]) sp-number-field {
  grid-area: number / number / number / number;
}

在浏览器中检查时,可以看到轴网线名称或轴网区域名称。

对应网格线名称:

你可以用两种不同的方式查看布局,对于调试或理解您试图构建/修复的布局非常有用。
CSS网格应该在我们的Web应用程序中更多地使用,但绝对不像下面的例子。

菜单网格

我认为在这里使用CSS网格布局有点过头了,下面说明一下我的理解。

sp-menu-item {
  display: grid;
  grid-template-areas:
    ". chevronAreaCollapsible . iconArea sectionHeadingArea . . ."
    "selectedArea chevronAreaCollapsible checkmarkArea iconArea labelArea valueArea actionsArea chevronAreaDrillIn"
    ". . . . descriptionArea . . ."
    ". . . . submenuArea . . .";
  grid-template-columns: auto auto auto auto 1fr auto auto auto;
  grid-template-rows: 1fr auto auto auto;
}

这是一个包含8列 * 4行的网格。从我花费的时间来理解他们为什么这样做,似乎一次只有一行网格是活跃的,其他行会因为内容为空或者缺少HTML元素而折叠。

有趣的是,上面的CSS是我简化后的。原始版本看起来像这样,团队使用了grid-template速记。

以下是我可以在应用程序中找到的相关菜单项。

这个 CSS 网格是为了这个小组件而设计的,我认为在这里使用 CSS 网格是一种过度设计。

下面是一个使用网格的例子。

.checkmark {
  align-self: start;
  grid-area: checkmarkArea / checkmarkArea / checkmarkArea /
    checkmarkArea;
}

#label {
  grid-area: labelArea / labelArea / labelArea / labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea / valueArea / valueArea / valueArea;
}

请注意 CSS 网格中的灰色部分是不活动的。它们因为没有内容而被折叠了。对于这个具体的例子,作者也可以这样做:

.checkmark {
  align-self: start;
  grid-area: checkmarkArea;
}

#label {
  grid-area: labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea;
}

当它们是相同的值时,不需要定义每个列和行的开始和结束。

大量使用CSS变量

我真的很喜欢CSS变量如何用来改变UI。我将着重指出这方面的多个例子。

更改图层缩略图的大小

如果您熟悉Photoshop,则可以控制缩略图大小并使其更小。当您有很多层,并希望在更少的空间中查看更多层时,这很有用。

首先层面板的主容器上有一个HTML属性large-thumbs

<psw-layers-panel large-thumbs></psw-layers-panel>

在CSS中,有:host([large-thumbs])分配特定的CSS变量。

:host([large-thumbs]) {
  --psw-custom-layer-thumbnail-size: var(
    --spectrum-global-dimension-size-800
  );
  --psw-custom-layer-thumbnail-border-size: var(
    --spectrum-global-dimension-size-50
  );
}

对于每个层,都有一个名为psw-layer-thumbnail的元素。这是CSS变量将被应用的地方。它将从主容器继承它。

<psw-layers-panel-item>
  <psw-tree-view-item>
    <psw-layer-thumbnail class="thumb"></psw-layer-thumbnail>
  </psw-tree-view-item>
</psw-layers-panel-item>

这里CSS变量被分配给缩略图。

:host {
  --layer-thumbnail-size: var(
    --psw-custom-layer-thumbnail-size,
    var(--spectrum-global-dimension-size-400)
  );
  --layer-badge-size: var(--spectrum-global-dimension-size-200);
  position: relative;
  width: var(--layer-thumbnail-size);
  min-width: var(--layer-thumbnail-size);
  height: var(--layer-thumbnail-size);
}

Loading 进度条

管理组件的大小是通过使用属性size来完成的,CSS变量根据大小而变化。

:host([size="m"]) {
  --spectrum-progressbar-size-default: var(
    --spectrum-progressbar-size-2400
  );
  --spectrum-progressbar-font-size: var(--spectrum-font-size-75);
  --spectrum-progressbar-thickness: var(
    --spectrum-progress-bar-thickness-large
  );
  --spectrum-progressbar-spacing-top-to-text: var(
    --spectrum-component-top-to-text-75
  );
}

图像控件

如果HTML属性quite存在,则UI更简单。

这也可以通过CSS变量来实现。

:host([quiet]) {
  --spectrum-actionbutton-background-color-default: var(
    --system-spectrum-actionbutton-quiet-background-color-default
  );
  --spectrum-actionbutton-background-color-hover: var(
    --system-spectrum-actionbutton-quiet-background-color-hover
  );
  /* And a lot more styles that I removed for the purpose of keeping the article clean. */
}

单选按钮

在这个例子中,团队使用CSS变量根据size HTML属性更改单选按钮的大小。

<sp-radio size="m" checked="" role="radio"></sp-radio>
:host([size="m"]) {
  --spectrum-radio-height: var(--spectrum-component-height-100);
  --spectrum-radio-button-control-size: var(
    --spectrum-radio-button-control-size-medium
  );
  /* And a lot more styles that I removed for the purpose of keeping the article clean. */
}

当菜单处于活动状态时锁定页面

当主菜单处于活动状态时,有一个“保持器”元素填充整个屏幕,位于菜单下方。

#actual[aria-hidden] + #holder {
  display: flex;
}

#holder {
  display: none;
  align-items: center;
  justify-content: center;
  flex-flow: column;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

此元素用于防止用户点击或悬停在页面的其他部分,看起来像在模仿桌面应用程序。

混合模式菜单

我在这里发现了CSS viewport单元的用途。混合模式菜单的最大高度为55vh

sp-menu {
  max-height: 55vh;
  --mod-menu-item-min-height: auto;
}

::slotted(*) {
  overscroll-behavior: contain;
}

overscroll-behavior: contain也有用到。这是一个很好的功能,可以避免滚动正文内容。

注释组件

用户可以在画布上的任何地方钉上注释或绘图。我检查了组件,以了解它是如何构建的。

我喜欢动态定位和颜色的CSS变量

为了将每个评论放置在用户选择的位置,团队使用了通过JS提供的CSS变量来处理。

<div
  data-html2canvas-ignore="true"
  class="Pin__component ccx-annotation"
  style="
    --offset-x: 570.359375px;
    --offset-y: 74.23046875px;
    --ccx-comments-pin-color: #16878C;
  "
></div>
.Pin__component {
  --pin-diameter: 24px;
  left: calc(var(--offset-x) - var(--pin-diameter) / 2);
  top: calc(var(--offset-y) - var(--pin-diameter) / 2);
  position: absolute;
  height: var(--pin-diameter);
  width: var(--pin-diameter);
  border-radius: var(--pin-diameter);
  border: 1px solid white;
  background: var(--ccx-comments-pin-color);
}

使用SVG进行工程图标注

当你将图片缩小时,SVG笔划不会调整大小,而且看起来很粗。

据我所知,这可以通过添加vector-effect: non-scaling-stroke来解决。但我没试过。

对图层缩略图使用 Object-Fit: Contain

在图层面板中,缩略图使用object-fit: contain以避免失真。

最后

文章到此就结束了,介绍了Photoshop Web版本使用的一些CSS技术。与国内常见的CSS技术相比,有许多不同之处,其中很多部分值得学习和借鉴。当然这只是其中的一部分,如果你感兴趣,可以查看他们的源代码来深入研究。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

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

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

相关文章

【I2C】熟悉I2C的传输时序。根据I2C的时序图,标出每段时序对应的含义

参考&#xff1a;I2C -- I2C总线详解_i2c频率-CSDN博客 首先看下I2C协议中数据传输的时序&#xff1a; I2C空闲&#xff1a;SCL和SDA同时处于“高电平”。 I2C起始&#xff1a;SCL维持高电平&#xff0c;SDA由“高电平跳变为低电平”&#xff0c;下降沿。 I2C终止&#xff1a…

机组 硬件

典型的冯诺伊曼计算机是以运算器为中心 现代的计算机已转化为以存储器为中心 运算器&#xff1a;完成算术运算和逻辑运算&#xff0c;并将运算的中间结果暂存在运算器内存储器&#xff1a;存放数据和程序控制器&#xff1a;控制、指挥程序和数据的输入、运行以及处理运算结果输…

【LeetCode】每日一题 2023_11_7 统计范围内的元音字符串数

文章目录 刷题前唠嗑题目&#xff1a;最大单词长度乘积题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode? 启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;最大单词长度乘积 题目链接&#xff1a;2586. 统计范围内的元音字符串数 题目描述 代码与…

上海亚商投顾:创业板指放量涨3.26% 两市近4500股飘红

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日高开后展开震荡&#xff0c;深成指涨超2%&#xff0c;创业板指大涨超3%&#xff0c;宁德时代涨超5%。…

世界土壤数据库(HWSD)土壤数据集

简介&#xff1a; HWSD&#xff08;Harmonized World Soil Database&#xff09;是联合国粮食及农业组织&#xff08;FAO&#xff09;和国际土壤参考与信息中心&#xff08;ISRIC&#xff09;共同开发的世界土壤数据集。该数据集是一份高分辨率&#xff08;1 km&#xff09;&a…

Gin框架如何使用并搭建一个后台管理系统(四)

到这个时候&#xff0c;我们应该安装上Mysql 开始工作。首先下载安装包mysql-installer-community-8.0.20.0.msi ps&#xff1a;看到有的人window环境下安装不成功可以下载一下依赖的包 NDP452-KB2901907-x86-x64-AllOS-ENU.exe 一、安装mysql 环境和可视化工具 二、导入…

linux修改rocketmq的日志文件位置

文章目录 &#x1f50a;修改rocketmq的日志文件位置&#x1f4d5;原来的文件&#x1f4cc;修改后文件&#x1f4c7;rocketmq中的Rocketmq_client.log文件在配置文件中改不了 需要在代码logback文件中进行修改&#x1f58a;️最后总结 &#x1f50a;修改rocketmq的日志文件位置 …

面试官:Spring 用到了哪些设计模式?

文章目录 前言一、策略模式二、工厂方法模式三、Builder模式总结 前言 关于设计模式&#xff0c;如果使用得当&#xff0c;将会使我们的代码更加简洁&#xff0c;并且更具扩展性。本文主要讲解Spring中如何使用策略模式&#xff0c;工厂方法模式以及Builder模式。 一、策略模式…

数字滤波器之高通滤波器设计

文章来源地址&#xff1a;https://www.yii666.com/blog/393376.html 通过在Z平面放置零极点的来设计数字滤波器 要求&#xff1a;设计一款高通滤波器&#xff0c;用在音频信号处理过程中&#xff0c;滤掉100Hz以下的信号。 实现方法&#xff1a;通过在Z平面放置零极点的来设…

多测师肖sir_高级金牌讲师__git讲解

git 一、git的介绍 &#xff08;一&#xff09;git的理论介绍&#xff08;版本控制工具&#xff09; git &#xff0c;目前世界上最先级的分布式版本控制系统&#xff0c;可以有效&#xff0c;高速的处理从很小到非常大的项目版本管理。 git是linus torvalds 为了帮助管理linu…

什么是柴油发电机组负载测试

柴油发电机组负载测试是对柴油发电机组在不同负载条件下进行性能和稳定性测试的过程&#xff0c;负载测试旨在评估发电机组在实际运行中的工作能力和性能表现&#xff0c;以确保其能够在负载变化时稳定可靠地提供电力。在负载测试中&#xff0c;需要确定测试负载的大小和类型。…

idea使用gradle教程 (idea gradle springboot)2024

这里白眉大叔&#xff0c;写一下我工作时候idea怎么使用gradle的实战步骤吧 ----windows 环境----------- 1-本机安装gradle 环境 &#xff08;1&#xff09;下载gradle Gradle需要JDK的支持&#xff0c;安装Gradle之前需要提前安装JDK8及以上版本 https://downloads.gra…

MES生产执行系统源码

MES生产执行系统源码 MES系统介绍 MES系统着重解决生产过程管控、防错防呆、产质量追溯、设备运行等相关管理目标&#xff0c;具体如下&#xff1a; &#xff08;1&#xff09;全面集成。承上启下&#xff0c;完成公司所有与MES系统链接的信息化系统 &#xff08;如ERP、PLM…

BSP-STM32移植FreeRTOS

在stm32裸机工程中的Middlewares目录添加freeRtos源码 在裸机工程中的main中调用freertos接口

最新版Office2024安装教程

一. 介绍&#xff1a;Office版本都是每三年发布一个版本&#xff0c;从Office 2007、2010、2013、2016、2019&#xff0c;2021到现在的2024。 二. 下载&#xff1a; http://dt1.8tupian.net/2/29913a54b1000.pg3三. 安装教程&#xff1a; 1.用到的软件是开源的脚本&#xff0c…

菜鸟打印组件系列-vue3快速接入

文章目录 前言1. 相关名词或语句2. CAINIAO打印组件能力3. 安装与下载4. vue3集成步骤4.1 使用pina 创建websoket相关处理的模块。4.2 创建本地自定义模板&#xff08;要打印的模板以及样式&#xff09;4.3 结合el-table &#xff0c;实现批量打印 总结 前言 文章主要记录不注…

unity Holoens2开发,使用Vuforia识别实体或图片 触发交互

建议&#xff1a;先看官方文档 我使用的utniy 版本&#xff1a;2020.3.48f1c1 官方建议&#xff1a;混合现实工具包简介 - 设置项目并使用手势交互 - Training | Microsoft Learn 配置了正确工具的 Windows 10 或 11 电脑Windows 10 SDK 10.0.18362.0 或更高版本安装了 Unit…

界面控件DevExpress WPF PDF Viewer,更快实现应用的PDF文档浏览

DevExpress WPF PDF Viewer控件可以轻松地直接在Windows应用程序中显示PDF文档&#xff0c;而无需在最终用户的机器上安装外部PDF查看器。 P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress…

怎么恢复永久删除的文件?这3个方法很实用!

“非常着急&#xff01;永久删除的文件还有机会恢复吗&#xff1f;大家怎么恢复永久删除的文件的呀&#xff1f;快帮帮我吧&#xff01;” 在数字化时代&#xff0c;文件的意外永久删除可能是一个常见问题.有些朋友可能不小心永久删除了文件之后会感到很绝望&#xff0c;但是别…

Python翻页代码示例

1. 首先&#xff0c;我们需要一个依赖于Ruby的库来帮助我们进行网络请求&#xff0c;这个库叫做Open-uri。我们可以使用require open-uri来引入这个库。 2. 接下来&#xff0c;我们需要定义一个变量来存储信息。在这个例子中&#xff0c;代理信息是proxy_host: 和proxy_port: &…