爬虫 - 二手交易电商平台数据采集 (一)

news2024/11/13 3:12:52

背景: 近期有一个需求需要采集某电商网站平台的商品数据进行分析。因此,我计划先用Python实现一个简单的版本,以快速测试技术的实现可能性,再用PHP实现一个更完整的版本。文章中涉及的技术仅为学习和测试用途,请勿用于商业或非法用途,以免对相关网站服务器造成不良影响。

一、需求分析

在网页抓取过程中,需要留意有些网站使用了动态渲染技术,这意味着页面内容并不是初始加载时直接从服务器获取,而需要JavaScript渲染后才会显示完整内容。应对动态渲染页面时,我们可以采用以下几种方法来获取数据:

1. 使用 Selenium

Selenium 是一种自动化测试框架,可模拟用户在浏览器中执行操作,获取渲染后的页面内容。它适合处理需要登录、填写表单等复杂的页面交互。使用 Selenium WebDriver 可以控制浏览器自动加载页面、执行 JavaScript 代码等,以便抓取到动态渲染的数据。

优缺点

  • 优点:适合复杂交互场景,如模拟登录、表单提交,能完整抓取动态内容。
  • 缺点:需要开启浏览器,消耗资源较大,速度相对较慢。

2. 使用 Headless 浏览器

Headless 浏览器没有图形界面,但具备处理JavaScript、HTML、CSS等渲染能力,是抓取动态渲染页面的理想选择。常见的 Headless 浏览器有 PhantomJS 和 Puppeteer。

优缺点

  • 优点:不需要可视化界面,效率较高,且可以完整执行JavaScript。
  • 缺点:对于需要频繁交互的操作不如 Selenium 灵活。

3. 直接调用网站 API

部分网站提供公开 API 接口,直接向这些接口发送请求即可获取数据,省去渲染页面的步骤。可以使用抓包工具找到这些接口的请求数据,直接模拟请求参数。

优缺点

  • 优点:相比前两种方法,调用 API 更高效、直接,适合抓取特定数据。
  • 缺点:某些 API 可能会有访问限制或加密,且并非所有网站提供公开 API。

4. 分析 JavaScript 渲染逻辑

一些网站通过 JavaScript 动态生成内容时,可以分析页面源代码,找到生成页面的 JS 代码块,模拟执行获取数据。这种方法对没有 API 接口且较复杂的动态页面尤其适用,但对开发者的 JavaScript 分析能力有较高要求。

优缺点

  • 优点:适合特定没有 API 且动态生成内容的网站。
  • 缺点:需要较高的分析和 JS 知识。

案例网站

本次我们选择了日本的二手交易平台 mercari.com 进行数据抓取。经分析页面结构,发现其采用了动态渲染,适合使用 Selenium + Chrome 浏览器模拟获取数据。


二、Selenium 介绍

1. 什么是 Selenium

Selenium 是一个强大的开源工具集,最初设计用于 Web 应用程序的自动化测试,后来也被广泛应用于网页抓取(Web Scraping)。通过 Selenium,程序可以自动控制浏览器,就像用户手动操作一样,执行各种交互,如点击、输入文本、滚动页面等。Selenium 的核心组件是 WebDriver,它负责与浏览器进行交互。

Selenium 的工作原理:

  • WebDriver 是 Selenium 的核心,它通过与浏览器的 “驱动程序”(如 ChromeDriver、GeckoDriver)进行通信来控制浏览器。WebDriver 会将程序指令转换成浏览器能够识别的命令,模拟用户操作。
  • WebDriver 通过 HTTP 协议发送指令,这些指令被浏览器驱动(如 ChromeDriver)接收、解析,并在浏览器中执行。执行完成后,驱动程序将执行结果返回给 WebDriver。
  • 例如,当程序发送一个点击按钮的指令时,WebDriver 会发送 HTTP 请求给驱动,驱动再将该指令转换为浏览器能识别的点击操作。

2. 在代码中如何使用 Selenium 以及它的工作流程

在代码中,Selenium 的典型使用流程如下:

  1. 配置浏览器驱动:首先需要下载并配置与浏览器对应的驱动程序,如 ChromeDriver 对应 Chrome 浏览器。该驱动是 Selenium 控制浏览器的桥梁,必须版本匹配。

  2. 初始化 WebDriver:在代码中创建一个 WebDriver 实例来启动浏览器。例如,在 Python 中可以通过 webdriver.Chrome() 来启动 Chrome。

  3. 编写自动化操作:通过 WebDriver 提供的 API,编写各种模拟操作,如访问页面、查找元素、执行点击、输入文本等。例如,driver.find_element_by_id() 可以找到页面元素,driver.get("https://example.com") 用于访问网址。

  4. 关闭浏览器:任务完成后,调用 driver.quit() 来关闭浏览器并释放资源。

3. Chrome 和 Chrome Headless Shell 的选择

在使用 Selenium 进行网页自动化时,有两种配置方式:

  1. 完整 Chrome 浏览器(支持 GUI)

    • 适用有图形界面的系统(如 Windows 和 Mac)。
    • 通过 --headless 启动 Chrome 的无界面模式。
    • 优点:与系统 Chrome 保持一致,直接更新浏览器即可。
  2. Chrome Headless Shell(不依赖 GUI)

    • 适合无界面的服务器(如 Linux 环境中的 Ubuntu 无 GUI 版)。
    • 直接在命令行中安装和使用,不依赖任何图形界面。
    • 优点:更轻量,资源占用更低,适合容器环境(如 Docker)。

4. 使用 ChromeDriver 启动 Chrome 和 Chrome Headless Shell 的代码示例

1. 在有 GUI 系统上启动 Chrome 的无界面模式

配置完整 Chrome 浏览器,并通过 --headless 参数启动无界面模式:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# 配置 Chrome 选项
chrome_options = Options()
// chrome_options.add_argument("--headless")  # 启用无界面模式
chrome_options.add_argument("--no-sandbox")  # 适用于 Linux 系统,防止运行 Chrome 时沙箱模式导致的问题
chrome_options.add_argument("--disable-gpu")  # 用于 Windows 系统,避免无界面模式下的 GPU 渲染问题
chrome_options.add_argument("--window-size=1920x1080")  # 指定浏览器窗口大小,模拟不同屏幕分辨率
chrome_options.add_argument("--disable-dev-shm-usage")  # 避免共享内存问题

# 启动 ChromeDriver
service = Service("/usr/local/bin/chromedriver")  # 替换为 ChromeDriver 路径
driver = webdriver.Chrome(service=service, options=chrome_options)

driver.get("https://example.com")
print("页面标题:", driver.title)
driver.quit()

2. 在无 GUI 系统上启动 Chrome Headless Shell

使用 Chrome Headless Shell 路径启动无界面浏览器:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.binary_location = "/path/to/chrome-headless-shell"  # 替换为 Chrome Headless Shell 路径
chrome_options.add_argument("--headless")  # 无界面模式
chrome_options.add_argument("--no-sandbox")  # Linux 推荐设置,防止运行 Chrome 时沙箱模式导致的问题
chrome_options.add_argument("--disable-dev-shm-usage")  # 避免共享内存问题

service = Service("/usr/local/bin/chromedriver")
driver = webdriver.Chrome(service=service, options=chrome_options)

driver.get("https://example.com")
print("页面标题:", driver.title)
driver.quit()

三、Python 版本实现

环境安装

1. 安装 Python

确保已安装 Python,并使用 python --version 查看是否为兼容版本(推荐 3.8 及以上)。
可以使用nvm来进行python

2. 下载 ChromeDriver

根据 Chrome 浏览器的版本(本地已安装Chrome浏览器),下载对应版本的 ChromeDriver 并将其添加到系统路径中。

  • 使用chrome浏览器打开 Google Chrome Testing,会自动检测你本地安装的chrome浏览器版本,并为你推荐合适的ChromeDriver版本,因为我是Mac Intel系统,所以选择的是mac-x64的ChromeDriver
    在这里插入图片描述
  • 将下载的 chromedriver 文件解压缩,得到一个可执行文件 chromedriver
  • 将 chromedriver 文件复制到 /usr/local/bin,以便全局访问。可以使用以下命令:
sudo mv /path/to/chromedriver /usr/local/bin/
  • 验证 ChromeDriver 是否配置成功,运行以下命令:
chromedriver --version

如果成功配置,会显示 ChromeDriver 的版本信息。
在这里插入图片描述

3. 安装 Selenium

使用以下命令安装 Selenium:

pip install selenium

4. 测试 Selenium 是否正常运行

  • 编写一个简单的测试脚本打开浏览器,访问百度并检查是否能正确加载页面。
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
 
# 配置 Chrome 选项
chrome_options = Options()
chrome_options.add_argument("--headless")  # 启用无界面模式
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")

# 启动 ChromeDriver
service = Service("/usr/local/bin/chromedriver")  # 替换为 ChromeDriver 路径
driver = webdriver.Chrome(service=service, options=chrome_options)
    
try:
    # 访问百度首页
    driver.get("https://www.baidu.com")
    time.sleep(1)  # 等待页面加载
   
    # 打印页面标题
    print("页面标题:", driver.title)

    # 在搜索框中输入关键词 "China" 并执行搜索
    search_box = driver.find_element(By.CSS_SELECTOR, "#kw")
    search_box.send_keys("China")
    
    search_button = driver.find_element(By.CSS_SELECTOR, "#su")
    search_button.click()
    time.sleep(2)  # 等待搜索结果加载

    # 打印搜索结果页面标题
    print("搜索结果页面标题:", driver.title)

finally:
    # 关闭浏览器
    driver.quit()
  • 控制台输出成功:
    在这里插入图片描述

5. 使用python抓取 mercari.com 网站指定品类的商品信息

# -*- coding: utf-8 -*-

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time

# 配置 Chrome 选项
chrome_options = Options()
chrome_options.add_argument("--headless")  # 启用无界面模式
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")

# 初始化浏览器
driver = webdriver.Chrome(options=chrome_options)

# 打开网页
driver.get("https://jp.mercari.com/")

# 找到搜索框并输入内容
search_box = driver.find_element(By.CSS_SELECTOR, "input[placeholder='なにをお探しですか?']")
search_box.send_keys("Adidas")

# 等待加载并点击搜索按钮
search_button = driver.find_element(By.CSS_SELECTOR, "button[aria-label='検索']")
search_button.click()

# 等待搜索结果加载
# 等待直到搜索结果的元素出现在页面中
WebDriverWait(driver, 20).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "div[data-testid='search-item-grid'] ul"))  # 根据实际情况修改选择器
)

# 定义获取产品信息的函数
def get_product_info():
    # 获取页面源代码
    page_source = driver.page_source

    # 使用BeautifulSoup解析页面
    soup = BeautifulSoup(page_source, 'html.parser')
    # 获取商品信息
    products = soup.select('div[data-testid="search-item-grid"] ul > li[data-testid="item-cell"]')  # 选择 ul 下的 li 元素

    # results = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='search-item-grid'] ul")
    product_info = []
    for product in products:
        name_elem = product.select_one('span[data-testid="thumbnail-item-name"]')
        price_elem = product.select_one('[class*="priceContainer"]')
        img_elem = product.select_one('img')

        # 检查元素是否存在并处理 Unicode
        name = name_elem.text.strip() if name_elem else u'未找到名称'
        price = price_elem.text.strip() if price_elem else u'未找到价格'
        img_url = img_elem['src'] if img_elem else u'未找到图片链接'

        product_info.append((name, price, img_url))
    return product_info

# 向下滚动以加载更多商品
def scroll_and_load_more():
    last_height = driver.execute_script("return document.body.scrollHeight")
    
    while True:
        # 向下滚动到页面底部
        driver.execute_script("window.scrollBy(0, 300);")
        
        # 等待新的内容加载
        time.sleep(2)

        # 计算新的滚动高度并与上一次高度进行比较
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break  # 如果没有新的内容加载,退出循环
        last_height = new_height

# 调用向下滚动的函数
scroll_and_load_more()

# 获取产品信息
products = get_product_info()

# 打印结果
for name, price, img_url in products:
    print(u'名称: {}, 价格: {}, 图片链接: {}'.format(name, price, img_url))

# 关闭浏览器
driver.quit()
  • 等待抓取成功后并输出抓取到的商品信息:
    在这里插入图片描述

四、PHP 版本实现

环境安装

1. 安装 PHP Selenium WebDriver 库

  • 使用 Composer 安装 WebDriver:
composer require facebook/webdriver
  • 使用文档
    具体的使用方法见 PHP Selenium WebDriver Github 仓库WIKI文档

2. 下载 ChromeDriver

根据 Chrome 浏览器版本,下载对应版本的 ChromeDriver 并将其添加到系统路径中。
(步骤同上面的Python版本中的ChromeDriver安装)

3. 安装 Java

  • PHP、Java 等语言没有直接支持 WebDriver API 的库,因此需要借助 Selenium Server 发送 WebDriver 请求。通过 Selenium Server,PHP 和 Java 客户端可以间接与 ChromeDriver 等浏览器驱动通信。
  • Python 中不需要单独启动 Selenium Server,是因为它可以直接使用浏览器驱动程序(如 ChromeDriver 或 GeckoDriver)与浏览器通信,而无需通过 Selenium Server 的中间层。这是因为 Python 的 Selenium 库内置支持 WebDriver API,可以直接控制浏览器驱动,免去额外的服务器进程。
  • 启动 Selenium Server 需要通过 Java 命令运行 JAR 文件。Selenium Server 是基于 Java 构建的,所以无论在什么操作系统上(包括 macOS),都需要安装 Java,并用 Java 命令来启动它。

  • 前往 Java官网 下载Java安装包,根据自己的操作系统选择合适的版本,这里我下载的是Mac OS 的 x64 DMG Installer :
    在这里插入图片描述

  • 下载后双击安装同意即可

  • 最后在控制台输入检查Java是否安装成功

java --version
  • 输出版本信息代表安装成功
    在这里插入图片描述

4. 下载 Selenium Server JAR 文件

  • Selenium Server 主要用于以下场景:

    • 分布式测试环境:在多台机器上进行测试,尤其是在集成和自动化测试场景中,Selenium Server 可以集中管理多台机器上的浏览器控制。
    • 非本地浏览器控制:例如,如果需要在远程服务器上控制浏览器,Selenium Server 作为一个中间层,可以通过 WebDriver 协议远程控制浏览器。
    • 多语言支持:Java、PHP 等客户端库通过 Selenium Server 来发送 WebDriver 请求,因为这些语言没有像 Python 一样的浏览器驱动的直接连接支持。
  • 前往Selenium官网下载最新版本的Selenium Server JAR 文件。

在这里插入图片描述

  • 下载后,将Selenium Server jar文件放置在一个便于管理的目录下,例如 ~/selenium/

5. 启动 Selenium 服务

  1. 通过以下命令启动 Selenium Server 服务:
cd ~/selenium-java/
java -jar selenium-server-4.26.0.jar standalone
  • 此时,Selenium Server 将在默认的 http://localhost:4444 端口启动。
  • 验证 Selenium Server 是否启动成功
    • 打开浏览器,访问 http://localhost:4444。如果页面显示了 Selenium Server 的信息,则说明启动成功。
      在这里插入图片描述
  1. 还有一种方式是不通过Selenium Server服务,直接启动chromedriver服务,比较适合本地的单机服务来运行抓取业务(可以不安装Java和Selenium Server)
chromedriver --port=4444
  1. Selenium Server 提供了几种不同的启动模式,每种模式适用于不同的分布式或本地测试需求。以下是常见模式的启动命令和适用场景:
  • Standalone 模式

    • 命令: java -jar selenium-server.jar standalone
    • 场景: 适用于单机环境,将所有组件(Session 管理、路由、分发)整合到一个服务中。适合无需分布式的简单测试。
  • Hub 模式

    • 命令: java -jar selenium-server.jar hub
    • 场景: 作为集群中心管理节点,用于接收测试请求并分配到各个 Node。适合需要分布式测试的场景。
  • Node 模式

    • 命令: java -jar selenium-server.jar node --detect-drivers true --hub
    • 场景: 作为测试执行节点注册到 Hub,实际执行测试任务。适用于分布式集群的场景。
  • SessionQueue 模式

    • 命令: java -jar selenium-server.jar sessionqueue
    • 场景: 单独管理请求队列,适合高并发场景。通常配合 Hub 使用,提高请求的调度效率。
  • Router 模式

    • 命令: java -jar selenium-server.jar router
    • 场景: 充当路由器,将请求分发至不同的 Hub。适合大型集群,提高请求分配效率。
  • Distributor 模式

    • 命令: java -jar selenium-server.jar distributor
    • 场景: 管理和分发 Session,适合复杂的分布式集群,通常和 Hub、Node 配合使用。

6. 测试服务是否正常运行

在 PHP 中编写一个简单脚本,测试能否正常启动 Selenium 并控制浏览器。

<?php

// 引入 PHP WebDriver 的库
require_once('vendor/autoload.php');

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\WebDriverBy;

try {
    // 配置 Chrome 选项
    $chromeOptions = new ChromeOptions();
    $chromeOptions->addArguments(['--headless', '--disable-gpu', '--no-sandbox']);
    $capabilities = DesiredCapabilities::chrome();
    $capabilities->setCapability(ChromeOptions::CAPABILITY, $chromeOptions);

    // 启动 ChromeDriver,替换为 ChromeDriver 路径
    $driver = RemoteWebDriver::create("http://localhost:4444", $capabilities);

    // 访问百度首页
    $driver->get("https://www.baidu.com");
    sleep(1);  // 等待页面加载

    // 打印页面标题
    echo "页面标题: " . $driver->getTitle() . "\n";

    // 在搜索框中输入关键词 "China" 并执行搜索
    $searchBox = $driver->findElement(WebDriverBy::cssSelector("#kw"));
    $searchBox->sendKeys("China");

    $searchButton = $driver->findElement(WebDriverBy::cssSelector("#su"));
    $searchButton->click();
    sleep(2);  // 等待搜索结果加载

    // 打印搜索结果页面标题
    echo "搜索结果页面标题: " . $driver->getTitle() . "\n";
    $driver->quit();
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
    // 关闭浏览器
    if (isset($driver)) {
        $driver->quit();
    }
}
  • 等待抓取成功后并输出抓取到的商品信息:
    在这里插入图片描述

以上就是完整的实现流程和代码示例。

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

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

相关文章

「C/C++」C++标准库 之 #include<iostream> 标准输入输出

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

AI出图,在家装行业杀疯了!

家装行业作为一个庞大的产业&#xff0c;长期以来面临着诸多难题&#xff0c;而随着AIGC技术的蓬勃发展&#xff0c;AI促进家装设计行业迎来了新的春天。 在传统家装设计流程中&#xff0c;相信大家对“设计环节充满了繁琐与复杂”有着非常深刻的体验&#xff0c;设计师需要花…

MySQL核心业务大表归档过程

记录一下2年前的MySQL大表的归档&#xff0c;当时刚到公司&#xff0c;发现MySQL的业务核心库&#xff0c;超过亿条的有7张表&#xff0c;最大的表有9亿多条&#xff0c;有37张表超过5百万条&#xff0c;部分表行数如下&#xff1a; 在测试的MySQL环境 &#xff1a; pt-archiv…

深度学习——权重初始化、评估指标、梯度消失和梯度爆炸

文章目录 &#x1f33a;深度学习面试八股汇总&#x1f33a;权重初始化零初始化 (Zero Initialization)随机初始化 (Random Initialization)Xavier 初始化&#xff08;Glorot 初始化&#xff09;He 初始化正交初始化&#xff08;Orthogonal Initialization&#xff09;预训练模型…

Proteus中数码管动态扫描显示不全(已解决)

文章目录 前言解决方法后记 前言 我是直接把以前写的 51 数码管程序复制过来的&#xff0c;当时看的郭天祥的视频&#xff0c;先送段选&#xff0c;消隐后送位选&#xff0c;最后来个 1ms 的延时。 代码在 Proteus 中数码管静态是可以的&#xff0c;动态显示出了问题——显示…

简单说一下Pinia 和 Vuex的区别

Pinia 和 Vuex 是 Vue.js 生态系统中两种状态管理库&#xff0c;它们都用于管理复杂应用的状态。尽管它们的目标相似&#xff0c;但在设计和使用上有许多不同之处。以下是 Pinia 和 Vuex 的主要区别&#xff1a; 1. 设计理念 Vuex 集中式存储&#xff1a;Vuex 采用单一的集中…

个人博客静态样式部署

首页部分 views/layout/layoutwave.vue <script setup> import router from /router; import { ref, onMounted, onUnmounted } from vue import /assets/img/icons/font_p81061dps7l/iconfont.cssconst canvas ref(null) const canvasFa ref(null) const fish ref(n…

综合文化信息管理系统|基于java和小程序的综合文化信息管理系统设计与实现(源码+数据库+文档)

综合文化信息管理系统 目录 基于java和小程序的打印室预约系统设计与实现 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&…

渗透测试(socket,namp,scapy)

socket:可以用来实现不同虚拟机或者不同计算机之间的通信。 socket常用函数&#xff1a; sock.bind(host,port) //host可接受client范围&#xff0c;以及连接的端口 sock.listen()//sever开启监听连接 sock.accpet()//返回 sock&#xff0c;addr 用来接受和发送数据 addr…

leetcode刷题记录(二十六)——151. 反转字符串中的单词

&#xff08;一&#xff09;问题描述 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/reverse-words-in-a-string/desc…

python中常见的8种数据结构之一数组的应用

在Python中&#xff0c;数组是一种常见的数据结构&#xff0c;用于存储一系列相同类型的元素。在实际应用中&#xff0c;数组可以用于解决各种问题。 以下是数组在Python中的一些常见应用&#xff1a; 1. 存储和访问数据&#xff1a;数组可以用于存储和访问一组数据。可以通过…

JS禁用鼠标滚动条功能且滚动条不消失教程

这个JS功能我找了好久好久才找到的&#xff0c;希望能够帮助到大家&#xff0c;网上有很多教程虽然能够实现禁用滚动条的效果&#xff0c;但是滚动条却直接消失不见了&#xff0c;那么今天我就把禁用滚动条但滚动条不消失的JS代码分享给大家。 实例代码如下&#xff1a; JS禁用…

学习虚幻C++开发日志——定时器

官方文档&#xff1a;虚幻引擎中的Gameplay定时器 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 定时器 安排在经过一定延迟或一段时间结束后要执行的操作。例如&#xff0c;您可能希望玩家在获取某个能力提升道具后变得无懈可击&#xff0c;…

记录Postman接口测试,配置token为全局变量,配置测试环境

软件测试资料领取&#xff1a;[内部资源] 想拿年薪40W的软件测试人员&#xff0c;这份资料必须领取~ 软件测试面试刷题工具&#xff1a;软件测试面试刷题【800道面试题答案免费刷】 为什么要进行接口测试&#xff1a; 因为不同端&#xff08;前段&#xff0c;后端&#xff0…

单臂路由技术,eNSP实验讲解

单臂路由技术&#xff0c;eNSP实验讲解 一、简要介绍1、概念2、工作原理3、优点4、缺点5、应用场景举例 二、eNSP仿真实验1、步骤一&#xff1a;2、步骤二&#xff1a;3、步骤三&#xff1a;4、步骤四&#xff1a; 三、总结。 一、简要介绍 1、概念 单臂路由&#xff08;Rout…

数据库SQL——什么是实体-联系模型(E-R模型)?

目录 什么是实体-联系模型&#xff1f; 1.实体集 2.联系集 3.映射基数 一对一&#xff08;1:1&#xff09; 一对多&#xff08;1:n&#xff09; 多对一&#xff08;n:1&#xff09; 多对多&#xff08;m:n&#xff09; 全部参与&#xff1a; 4.主码 弱实体集&#xf…

WPS Office手机去广高级版

工具介绍功能特点 WPS Office是使用人数最多的移动办公软件&#xff0c;独有手机阅读模式&#xff0c;字体清晰翻页流畅&#xff1b;完美支持文字&#xff0c;表格&#xff0c;演示&#xff0c;PDF等51种文档格式&#xff1b;新版本具有海量精美模版及高级功能 安装环境 [名称…

【微服务】Docker 容器化

一、初识Docker 1. 为什么需要 Docker 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会遇到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性的问题开发、测试、生产环境有差异 Docker 如何解决依赖的兼容问题 将应用的Libs&#xff08;…

Yocto 项目下通过网络更新内核、设备树及模块

Yocto 项目下通过网络更新内核、设备树及模块 前言 在 Yocto 项目的开发过程中&#xff0c;特别是在进行 BSP&#xff08;Board Support Package&#xff09;开发时&#xff0c;经常需要调整特定软件包的版本&#xff0c;修改内核、设备树以及内核模块。然而&#xff0c;每次…

EasyExcel级联下拉

代码 package com.xc.excel.select;import com.alibaba.excel.EasyExcel; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.FileOutputStream; import java.i…