当前位置: 首页 > news >正文

Java+Selenium+快代理实现高效爬虫

目录

  • 一、前言
  • 二、Selenium简介
  • 三、环境准备
  • 四、代码实现
    • 4.1 创建WebDriver工厂类
    • 4.2 创建爬虫主类
    • 4.3 配置代理的注意事项
  • 六、总结与展望

一、前言

在Web爬虫技术中,Selenium作为一款强大的浏览器自动化工具,能够模拟真实用户操作,有效应对JavaScript渲染、Ajax加载等复杂场景。而集成代理服务则能够解决IP限制、地域访问限制等问题。本文将详细介绍如何利用Java+Selenium+快代理实现高效的爬虫系统。

二、Selenium简介

Selenium是一个用于Web应用程序自动化测试的工具集,它主要用于自动化浏览器操作,可以模拟用户与网页的交互行为,如点击按钮、填写表单、滚动页面等。在爬虫领域,Selenium特别适合处理那些需要JavaScript渲染、需要登录或有反爬措施的网站。

三、环境准备

  • JDK1.8
  • Maven项目管理
  • 相关依赖
<!-- Selenium -->
<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>3.141.59</version>
</dependency>
<dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.3.2</version>
</dependency>

四、代码实现

本系统采用的是工厂模式创建WebDriver实例,这样做的好处主要是可以提供统一的创建方法,不管使用那种浏览器都适用,自由配置。其次就是维护方便,浏览器配置变更只需修改工厂类中的相关方法,扩展性也不错,可以轻松添加新的浏览器支持,比如Opera或者Safari等等。

4.1 创建WebDriver工厂类

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.PageLoadStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** WebDriver工厂类,负责创建和配置各种浏览器驱动实例* 设计思路:* 1. 使用工厂模式统一管理不同浏览器的WebDriver创建逻辑* 2. 采用构建器模式(Builder Pattern)使配置更加灵活* 3. 封装复杂的浏览器选项设置,简化调用代码* 4. 支持多种浏览器类型和代理配置* * 好处:* 1. 代码复用性高,减少重复代码* 2. 配置灵活,通过链式调用设置参数* 3. 职责单一,仅负责创建WebDriver* 4. 易于扩展,可轻松添加新的浏览器类型支持*/
public class WebDriverFactory {// 使用SLF4J记录日志,便于问题排查private static final Logger log = LoggerFactory.getLogger(WebDriverFactory.class);// 默认配置,可通过构建器方法修改private boolean headless = true;                // 默认无头模式private int pageLoadTimeoutSeconds = 30;        // 页面加载超时时间private int scriptTimeoutSeconds = 30;          // 脚本执行超时时间private int implicitWaitSeconds = 10;           // 隐式等待时间// 代理配置private boolean proxyEnabled = false;           // 是否启用代理private String proxyHost;                       // 代理主机地址private int proxyPort;                          // 代理端口private String proxyUsername;                   // 代理用户名(认证用)private String proxyPassword;                   // 代理密码(认证用)/*** 支持的浏览器类型枚举* 便于扩展,后续可以增加其他浏览器支持*/public enum BrowserType {CHROME, EDGE, FIREFOX}/*** 设置是否使用无头模式* 无头模式下浏览器不会显示界面,更加节省资源* * @param headless true表示使用无头模式,false表示显示浏览器界面* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withHeadless(boolean headless) {this.headless = headless;return this;}/*** 设置页面加载超时时间* * @param seconds 超时秒数* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withPageLoadTimeout(int seconds) {this.pageLoadTimeoutSeconds = seconds;return this;}/*** 设置JavaScript脚本执行超时时间* * @param seconds 超时秒数* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withScriptTimeout(int seconds) {this.scriptTimeoutSeconds = seconds;return this;}/*** 设置元素查找隐式等待时间* * @param seconds 等待秒数* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withImplicitWait(int seconds) {this.implicitWaitSeconds = seconds;return this;}/*** 配置代理服务器* * @param host 代理主机地址* @param port 代理端口* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withProxy(String host, int port) {this.proxyEnabled = true;this.proxyHost = host;this.proxyPort = port;return this;}/*** 配置代理服务器认证信息* * @param username 代理用户名* @param password 代理密码* @return 当前工厂实例,支持链式调用*/public WebDriverFactory withProxyAuth(String username, String password) {this.proxyUsername = username;this.proxyPassword = password;return this;}/*** 创建指定类型的WebDriver实例* 工厂方法核心,根据指定的浏览器类型创建对应的WebDriver* * @param browserType 浏览器类型枚举* @return 配置好的WebDriver实例*/public WebDriver createWebDriver(BrowserType browserType) {switch (browserType) {case CHROME:return createChromeDriver();case EDGE:return createEdgeDriver();case FIREFOX:return createFirefoxDriver();default:// 默认使用Edge浏览器log.info("未指定浏览器类型,默认使用Edge浏览器");return createEdgeDriver();}}/*** 创建Edge浏览器WebDriver实例* * @return 配置好的Edge WebDriver*/private WebDriver createEdgeDriver() {// 自动下载与系统浏览器匹配的WebDriver,避免版本不匹配问题WebDriverManager.edgedriver().setup();EdgeOptions options = new EdgeOptions();// 配置浏览器选项Map<String, Object> edgePrefs = new HashMap<>();// 禁用自动扩展,减少资源占用和干扰edgePrefs.put("useAutomationExtension", false);// 获取通用浏览器参数List<String> args = getCommonBrowserArgs();Map<String, Object> edgeOptions = new HashMap<>();edgeOptions.put("args", args);// 设置User-Agent,模拟真实浏览器,减少被网站识别为爬虫的可能options.setCapability("ms.edge.userAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");// 设置页面加载策略为NORMAL,确保页面完整加载// 可选值:NONE (不等待加载), EAGER (DOM就绪即可), NORMAL (等待完全加载)options.setPageLoadStrategy(PageLoadStrategy.NORMAL);// Edge特有配置options.setCapability("ms:edgeChromium", true);options.setCapability("ms:edgeOptions", edgeOptions);// 使用隐私模式,避免历史记录、cookie等信息的干扰options.setCapability("inPrivate", true);// 配置代理configureProxy(options);// 创建WebDriver实例WebDriver driver = new EdgeDriver(options);// 配置超时设置configureTimeouts(driver);log.info("Edge WebDriver创建成功");return driver;}/*** 创建Chrome浏览器WebDriver实例* * @return 配置好的Chrome WebDriver*/private WebDriver createChromeDriver() {// 自动下载与系统浏览器匹配的WebDriverWebDriverManager.chromedriver().setup();ChromeOptions options = new ChromeOptions();// 根据配置决定是否使用无头模式if (headless) {options.addArguments("--headless");}// 添加通用浏览器参数for (String arg : getCommonBrowserArgs()) {options.addArguments(arg);}// 设置页面加载策略options.setPageLoadStrategy(PageLoadStrategy.NORMAL);// Chrome浏览器特殊处理代理配置configureProxyForChrome(options);// 创建WebDriver实例WebDriver driver = new ChromeDriver(options);// 配置超时设置configureTimeouts(driver);log.info("Chrome WebDriver创建成功");return driver;}/*** 创建Firefox浏览器WebDriver实例* * @return 配置好的Firefox WebDriver*/private WebDriver createFirefoxDriver() {// 自动下载与系统浏览器匹配的WebDriverWebDriverManager.firefoxdriver().setup();FirefoxOptions options = new FirefoxOptions();// 根据配置决定是否使用无头模式if (headless) {options.addArguments("--headless");}// 配置代理configureProxy(options);// 创建WebDriver实例WebDriver driver = new FirefoxDriver(options);// 配置超时设置configureTimeouts(driver);log.info("Firefox WebDriver创建成功");return driver;}/*** 获取通用浏览器启动参数* 这些参数适用于基于Chromium的浏览器(Chrome, Edge)* * @return 参数列表*/private List<String> getCommonBrowserArgs() {List<String> args = new ArrayList<>();// 无头模式相关参数if (headless) {args.add("--headless");  // 不显示浏览器界面args.add("--disable-gpu");  // 在某些系统上无头模式需要禁用GPU加速}// 禁用扩展和插件,减少资源占用和干扰args.add("--disable-extensions");// 禁用图片加载,提高性能args.add("--blink-settings=imagesEnabled=false");// 解决在Docker容器中可能出现的共享内存问题args.add("--disable-dev-shm-usage");// 禁用平滑滚动,减少自动滚动问题args.add("--disable-smooth-scrolling");// 设置固定窗口大小,避免响应式变化导致的元素定位问题args.add("--window-size=1366,768");// 禁用站点隔离,减少内存使用args.add("--disable-features=site-per-process");// 禁用默认应用,减少启动时间args.add("--disable-default-apps");// 减少日志输出,提高性能args.add("--disable-logging");// 禁用信息栏,避免干扰args.add("--disable-infobars");// 禁用通知,避免干扰args.add("--disable-notifications");// 添加性能优化参数args.add("--disable-web-security");  // 禁用同源策略检查args.add("--no-sandbox");  // 禁用沙箱模式,提高性能(注意安全风险)args.add("--disable-setuid-sandbox");  // 禁用setuid沙箱,配合--no-sandbox使用args.add("--disable-accelerated-2d-canvas");  // 禁用加速2D Canvas,减少GPU使用args.add("--disable-crash-reporter");  // 禁用崩溃报告args.add("--disable-in-process-stack-traces");  // 禁用进程内堆栈跟踪args.add("--disable-breakpad");  // 禁用断点调试args.add("--aggressive-cache-discard");  // 积极丢弃缓存,减少内存使用args.add("--disable-ipc-flooding-protection");  // 禁用IPC洪水保护// 限制JavaScript引擎内存使用,防止内存溢出args.add("--js-flags=--max-old-space-size=512");return args;}/*** 为浏览器选项配置代理* 适用于Edge和Firefox浏览器* * @param options 浏览器选项对象*/private void configureProxy(Object options) {if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {try {// 构建代理URL,处理是否需要认证String proxyUrl;if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {// 带认证的代理格式:http://username:password@host:portproxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;} else {// 不带认证的代理格式:http://host:portproxyUrl = "http://" + proxyHost + ":" + proxyPort;}// 创建代理对象Proxy proxy = new Proxy();// 同时设置HTTP和HTTPS代理,确保所有请求都通过代理proxy.setHttpProxy(proxyUrl);proxy.setSslProxy(proxyUrl);// 根据浏览器类型设置代理能力if (options instanceof EdgeOptions) {((EdgeOptions) options).setCapability(CapabilityType.PROXY, proxy);} else if (options instanceof FirefoxOptions) {((FirefoxOptions) options).setCapability(CapabilityType.PROXY, proxy);}log.info("WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);} catch (Exception e) {log.error("配置代理时出错: {}", e.getMessage());}}}/*** 为Chrome浏览器特别配置代理* Chrome处理代理的方式与Edge和Firefox略有不同* * @param options Chrome浏览器选项对象*/private void configureProxyForChrome(ChromeOptions options) {if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {try {// 构建代理URL,处理是否需要认证String proxyUrl;if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {// 带认证的代理proxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;} else {// 不带认证的代理proxyUrl = "http://" + proxyHost + ":" + proxyPort;}// 创建代理对象Proxy proxy = new Proxy();proxy.setHttpProxy(proxyUrl);proxy.setSslProxy(proxyUrl);// 为Chrome设置代理能力options.setCapability(CapabilityType.PROXY, proxy);log.info("Chrome WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);} catch (Exception e) {log.error("配置Chrome代理时出错: {}", e.getMessage());}}}/*** 配置WebDriver的各种超时设置* * @param driver WebDriver实例*/private void configureTimeouts(WebDriver driver) {// 设置页面加载超时时间driver.manage().timeouts().pageLoadTimeout(pageLoadTimeoutSeconds, TimeUnit.SECONDS);// 设置脚本执行超时时间driver.manage().timeouts().setScriptTimeout(scriptTimeoutSeconds, TimeUnit.SECONDS);// 设置隐式等待时间,查找元素时使用driver.manage().timeouts().implicitlyWait(implicitWaitSeconds, TimeUnit.SECONDS);log.debug("WebDriver超时配置完成:页面加载={}秒,脚本执行={}秒,隐式等待={}秒",pageLoadTimeoutSeconds, scriptTimeoutSeconds, implicitWaitSeconds);}
}

4.2 创建爬虫主类

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.List;/*** Selenium爬虫示例主类* 演示如何使用WebDriverFactory创建浏览器实例并进行网页爬取*/
public class SeleniumCrawler {private static final Logger log = LoggerFactory.getLogger(SeleniumCrawler.class);public static void main(String[] args) {// 推荐使用快代理的隧道代理:https://www.kuaidaili.com/?ref=soi1rkc6rd82String proxyHost = "";  // 快代理隧道代理主机int proxyPort = 15818;                // 端口,根据实际情况修改String proxyUsername = "yourUsername"; // 替换为您的快代理用户名String proxyPassword = "yourPassword"; // 替换为您的快代理密码// 创建WebDriver工厂实例,配置爬虫参数// 使用构建器模式,代码可读性强,配置灵活WebDriverFactory factory = new WebDriverFactory().withHeadless(false)  // 设置为false可以看到浏览器界面,方便调试.withPageLoadTimeout(30)  // 页面加载超时设置为30秒.withScriptTimeout(30)    // 脚本执行超时设置为30秒  .withImplicitWait(10)     // 查找元素隐式等待10秒.withProxy(proxyHost, proxyPort)           // 设置快代理的主机和端口.withProxyAuth(proxyUsername, proxyPassword);  // 设置代理认证信息WebDriver driver = null;try {// 创建Edge浏览器实例,也可以选择Chrome或Firefoxlog.info("正在初始化WebDriver...");driver = factory.createWebDriver(WebDriverFactory.BrowserType.EDGE);// 开始爬虫任务crawlWebsite(driver);} catch (Exception e) {// 异常处理,记录详细错误信息便于排错log.error("爬虫执行出错: {}", e.getMessage(), e);} finally {// 确保WebDriver正确关闭,避免资源泄露if (driver != null) {driver.quit();log.info("WebDriver已关闭,爬虫任务结束");}}}/*** 爬虫核心逻辑,可根据实际需求扩展* * @param driver 已配置好的WebDriver实例* @throws InterruptedException 如果线程休眠被中断*/private static void crawlWebsite(WebDriver driver) throws InterruptedException {// 访问目标网站log.info("开始访问目标网站");driver.get("https://www.baidu.com");log.info("网页标题: {}", driver.getTitle());// 显式等待某个元素出现,确保页面加载完成// 比简单的Thread.sleep更智能WebDriverWait wait = new WebDriverWait(driver, 10);wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("body")));// 获取页面内容示例:提取所有链接log.info("开始提取页面链接");List<WebElement> links = driver.findElements(By.tagName("a"));log.info("共发现{}个链接", links.size());// 处理提取到的链接for (WebElement link : links) {String text = link.getText().trim();String href = link.getAttribute("href");// 只记录有效链接if (href != null && !href.isEmpty()) {log.info("链接: {} -> {}", text.isEmpty() ? "[无文本]" : text, href);}}// 模拟更多爬虫操作,例如点击某个元素、填写表单等// 这里作为示例,只是简单等待log.info("等待页面进一步处理...");Thread.sleep(2000);// 如果需要,可以继续访问更多页面// driver.get("https://www.another-site.com");// ...log.info("爬虫任务完成");}
}

4.3 配置代理的注意事项

在使用代理时,需要注意以下几点:

  1. 选择合适的代理类型:隧道代理适合大规模爬虫,普通代理适合小规模测试
  2. 正确配置认证信息:确保用户名和密码正确,特殊字符需要URL编码
  3. 测试代理连通性:使用前先测试代理是否可用
  4. 合理设置请求频率:遵循代理服务商的使用建议,避免触发反爬机制
  5. 注意IP切换时机:适时切换IP,避免同一IP频繁访问目标网站

六、总结与展望

本文详细介绍了如何使用Java+Selenium+快代理实现高效的网页爬虫。通过工厂模式和构建器模式的应用,我们实现了一个灵活、可扩展且易于使用的爬虫框架。该框架解决了代理认证配置的难题,优化了浏览器参数设置,提高了爬虫的稳定性和效率。

Selenium与代理服务的结合为我们提供了强大的爬虫能力:Selenium模拟真实用户行为应对JavaScript渲染和复杂交互,而快代理则提供了稳定的IP资源池,有效规避IP封禁和地域限制问题。这种组合特别适合需要处理登录验证、动态加载内容或有反爬措施的网站。

在实际应用中,请务必遵守相关法律法规和网站的使用条款,合理设置爬虫的请求频率和数量,避免对目标网站造成不必要的负担。同时,定期更新Selenium和WebDriver版本,以适应浏览器的更新和网站的变化。

如果你在使用过程中遇到问题,可以参考快代理或查阅Selenium的相关资料。希望本文对你的爬虫开发有所帮助!

最后,随着网站反爬技术的不断进化,爬虫技术也需要持续更新迭代。未来,我们可以考虑结合机器学习技术识别验证码,或通过更智能的策略调整爬取行为,使爬虫更加智能和高效。

欢迎在评论区分享你的使用经验和改进建议!


推荐阅读:

  • Selenium官方文档
  • WebDriverManager使用指南
  • 快代理API文档
  • 爬虫法律法规与道德规范

相关文章:

Java+Selenium+快代理实现高效爬虫

目录 一、前言二、Selenium简介三、环境准备四、代码实现4.1 创建WebDriver工厂类4.2 创建爬虫主类4.3 配置代理的注意事项 六、总结与展望 一、前言 在Web爬虫技术中&#xff0c;Selenium作为一款强大的浏览器自动化工具&#xff0c;能够模拟真实用户操作&#xff0c;有效应对…...

掌握Multi-Agent实践(三):ReAct Agent集成Bing和Google搜索功能,采用推理与执行交替策略,增强处理复杂任务能力

一个普遍的现象是,大模型通常会根据给定的提示直接生成回复。对于一些简单的任务,大模型或许能够较好地应对。然而,当我们面对更加复杂的任务时,往往希望大模型能够表现得更加“智能”,具备适应多样场景和解决复杂问题的能力。为此,AgentScope 提供了内置的 ReAct 智能体…...

【愚公系列】《Manus极简入门》028-创业规划顾问:“创业导航仪”

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

SpringBoot统一功能处理

一.拦截器&#xff08;实现两个接口&#xff0c;并重写方法&#xff09; 1. 定义拦截器 ⾃定义拦截器&#xff1a; 实现HandlerInterceptor接⼝&#xff0c; 并重写其所有⽅法 preHandle()⽅法&#xff1a;⽬标⽅法执⾏前执⾏. 返回true: 继续执⾏后续操作; 返回false: 中断后…...

并发设计模式实战系列(19):监视器(Monitor)

&#x1f31f; 大家好&#xff0c;我是摘星&#xff01; &#x1f31f; 今天为大家带来的是并发设计模式实战系列&#xff0c;第十九章监视器&#xff08;Monitor&#xff09;&#xff0c;废话不多说直接开始~ 目录 一、核心原理深度拆解 1. 监视器三要素模型 2. 线程调度…...

Oracle Fusion常用表

模块表名表描述字段说明sodoo_headers_all销售订单头表sodoo_lines_all销售订单行表sodoo_fulfill_lines_all销售订单明细行表popo_headers_all采购订单头表popo_lines_all采购订单行表popo_line_locations_all采购订单分配表popo_distributions_all采购订单发运表invEGP_SYSTE…...

虚假AI工具通过Facebook广告传播新型Noodlophile窃密木马

网络安全公司Morphisec的研究人员发现&#xff0c;攻击者正利用虚假人工智能&#xff08;AI&#xff09;平台传播名为Noodlophile Stealer的新型信息窃取木马。这种复杂攻击手法利用AI工具的热度诱骗用户下载恶意软件&#xff0c;窃取浏览器凭证、加密货币钱包&#xff0c;并可…...

华为云Flexus+DeepSeek征文|从开通到应用:华为云DeepSeek-V3/R1商用服务深度体验

前言 本文章主要讲述在华为云ModelArts Studio上 开通DeepSeek-V3/R1商用服务的流程&#xff0c;以及开通过程中的经验分享和使用感受帮我更多开发者&#xff0c;在华为云平台快速完成 DeepSeek-V3/R1商用服务的开通以及使用入门注意&#xff1a;避免测试过程中出现部署失败等问…...

在Cline上调用MCP服务之MCP实践篇

目录 引言一、准备工作1、安装 Visual Studio Code2、安装Cline插件配置支持模型 二、安装MCP Server并调用MCP Server三、本地手动安装MCP Server结尾 引言 上一篇《模型上下文协议&#xff08;Model Context Protocol&#xff0c;MCP&#xff09;初见概念篇》我们说到什么是…...

大模型应用开发之模型架构

一、Transformer 架构 1. 编码器Encoder&#xff08;“阅读理解大师”&#xff09; 1&#xff09;核心任务&#xff1a;编码器的唯一目标就是彻底理解输入的句子。它要把输入的每个词&#xff08;或者说词元 Token&#xff09;都转化成一个充满上下文信息的“向量表示”&#…...

敦普水性无铬锌铝涂层:汽车紧固件防锈15年,解决螺栓氢脆腐蚀双痛点

汽车紧固件低能耗涂装 在汽车工业体系中&#xff0c;紧固件承担着连接关键部件的重任。螺栓的抗拉强度、螺母的锁紧力矩&#xff0c;直接决定着整车的可靠性。当前&#xff0c;传统涂层技术始终面临一道难题&#xff1a;如何在保障防锈性能的同时&#xff0c;实现真正的环保无有…...

基环树(模板) 2876. 有向图访问计数

对于基环树&#xff0c;我们可以通过拓扑排序去掉所有的树枝&#xff0c;只剩下环&#xff0c;题目中可能会有多个基环树 思路&#xff1a;我们先利用拓扑排序将树枝去掉&#xff0c;然后求出每个基环树&#xff0c;之后反向dfs求得所有树枝的长度即可 class Solution { publi…...

26考研——中央处理器_指令执行过程(5)

408答疑 文章目录 二、指令执行过程指令周期定义指令周期的多样性指令执行的过程注意事项 指令周期的数据流取指周期间址周期执行周期中断周期 指令执行方案单周期处理器多周期处理器流水线处理器 八、参考资料鲍鱼科技课件26王道考研书 九、总结 二、指令执行过程 指令周期 …...

Unity基础学习(九)输入系统全解析:鼠标、键盘与轴控制

目录 一、Input类 1. 鼠标输入 2. 键盘输入 3. 默认轴输入 &#xff08;1&#xff09; 基础参数 &#xff08;2&#xff09;按键绑定参数 &#xff08;3&#xff09;输入响应参数 &#xff08;4&#xff09;输入类型与设备参数 &#xff08;5&#xff09;不同类型轴的参…...

如何清除windows 远程桌面连接的IP记录

问题 在远程桌面连接后&#xff0c;会在输入列表留下历史IP记录&#xff0c;无用的IP多了会影响我们查找效率&#xff0c;也不安全。 现介绍如何手动删除这些IP记录。 解决方案 1、打开注册表 按 Win R&#xff0c;输入 regedit&#xff0c;回车定位到远程桌面记录的注册表…...

C#参数数组全解析

在C#编程中&#xff0c;参数数组是一个重要的概念&#xff0c;它为方法调用提供了更大的灵活性。下面我们将详细介绍参数数组的相关内容。 参数数组的基本规则 在本书所述的参数类型里&#xff0c;通常一个形参需严格对应一个实参&#xff0c;但参数数组不同&#xff0c;它允…...

设计模式-策略模式(Strategy Pattern)

设计模式-策略模式&#xff08;Strategy Pattern&#xff09; 一、概要 在软件设计中&#xff0c;策略模式&#xff08;Strategy Pattern&#xff09;是一种非常重要的行为型设计模式。它的核心思想是将算法或行为封装在不同的策略类中&#xff0c;使得它们可以互换&#xff…...

LeetCode面试题 17.21 直方图的水量

题目 解答 package leetcode.editor.cn;//leetcode submit region begin(Prohibit modification and deletion) class Solution {public int trap(int[] height) {int length height.length;if (length 0) {return 0;}int[] leftMax new int[length];leftMax[0] 0;for (i…...

数据库系统概论(七)初识SQL与SQL基本概念

数据库系统概论&#xff08;七&#xff09;初识SQL与SQL基本概念 前言一、什么是SQL语言&#xff1f;1.1 SQL的产生和发展1.2 SQL的特点1.3 SQL的基本概念1.3.1 数据库相关“术语”&#xff08;类比Excel表格&#xff09;1.3.2 四大类核心语句&#xff08;后面会详细讲&#xf…...

Jenkins Maven 带权限 搭建方案2025

1、使用docker搭建jenkins version: 3.8services:jenkins:image: jenkins_lzh:1.0container_name: jenkinsports:- "8080:8080" # Jenkins Web UI- "50000:50000" # Jenkins Agent通信端口volumes:- ./jenkins_home:/var/jenkins_home # 持久化Jenkins…...

服务器配置错误导致SSL/TLS出现安全漏洞,如何进行排查?

SSL/TLS 安全漏洞排查与修复指南 一、常见配置错误类型‌ 弱加密算法与密钥问题‌ 使用弱密码套件&#xff08;如DES、RC4&#xff09;或密钥长度不足&#xff08;如RSA密钥长度<2048位&#xff09;&#xff0c;导致加密强度不足。 密钥管理不当&#xff08;如私钥未加密存…...

【高并发】Celery + Redis异步任务队列方案提高OCR任务时的并发

线程池处理OCR仍然会阻塞请求的原因主要有以下几点&#xff0c;以及为什么CeleryRedis是更好的解决方案&#xff1a; 1. 线程池的阻塞本质 请求-响应周期未分离&#xff1a;即使使用线程池&#xff0c;HTTP请求仍需要等待线程池任务完成才能返回响应。当所有线程都繁忙时&#…...

c/c++的Libevent 和OpenSSL构建HTTPS客户端详解(附带源码)

使用 Libevent 和 OpenSSL 构建 HTTPS 客户端详解 在现代网络应用中&#xff0c;HTTPS 协议的普及使得安全通信成为标配。Libevent 是一个功能强大且广泛应用的事件通知库&#xff0c;能够帮助开发者编写高性能、可移植的网络程序。然而&#xff0c;libevent 本身并不直接处理…...

关于fastjson与fastjson2中toJava操作的区别

关于fastjson与fastjson2中toJava操作的区别 一、场景二、 区别1、前置条件2、对比1. fastjson2. fastjson2 三、解决方案 一、场景 在Java中会有将json转为实体类的需求&#xff0c;其中fastjson是一个常用的选择&#xff0c;今天在升级项目依赖的过程中&#xff0c;将fastjs…...

PX4开始之旅(二)通过自定义 MAVLink 消息与 QGroundControl (QGC) 通信

核心知识点&#xff1a;通过自定义 MAVLink 消息与 QGroundControl (QGC) 通信 1. 通俗易懂的解释 想象一下&#xff0c;MAVLink 就像是无人机&#xff08;飞控&#xff09;和地面站&#xff08;QGroundControl&#xff09;之间约定好的一种“语言”。这种语言有很多标准的“…...

Docker组件详解:核心技术与架构分析

Docker详解&#xff1a;核心技术与架构分析 Docker作为一种容器化技术&#xff0c;已经彻底改变了软件的开发、交付和部署方式。要充分理解和利用Docker的强大功能&#xff0c;我们需要深入了解其核心组件以及它们如何协同工作。本文将详细介绍Docker的主要组件、架构设计以及…...

uni-app,小程序中的addPhoneContact,保存联系人到手机通讯录

文章目录 方法详解简介 基本语法参数说明基础用法使用示例平台差异说明注意事项最佳实践 方法详解 简介 addPhoneContact是uni-app框架提供的一个实用API&#xff0c;用于向系统通讯录添加联系人信息。这个方法在需要将应用内的联系人信息快速保存到用户设备通讯录的场景下非…...

uniapp小程序轮播图高度自适应优化详解

在微信小程序开发过程中&#xff0c;轮播图组件(swiper)是常用的UI元素&#xff0c;但在实际应用中经常遇到高度不匹配导致的空白问题。本文详细记录了一次轮播图高度优化的完整过程&#xff0c;特别是针对固定宽高比图片的精确适配方案。 问题背景 在开发"零工市场&quo…...

赛季7靶场 - Environment

本系列仅说明靶场的攻击思路&#xff0c;不会给出任何的详细代码执行步骤&#xff0c;因为个人觉得找到合适的工具以实现攻击思路的能力也非常重要。 1.Nmap扫描发现80和22端口 2.访问80端口&#xff0c;使用katana查看js代码&#xff0c;快速发现laravel框架。 【*】希望知道…...

JVM——即时编译

分层编译模式&#xff1a;动态平衡启动速度与执行效率 分层编译是现代JVM&#xff08;如HotSpot、GraalVM&#xff09;实现高性能的核心策略之一&#xff0c;其核心思想是根据代码的执行热度动态选择不同的编译层次&#xff0c;实现启动速度与运行效率的最佳平衡。以HotSpot虚…...

武汉火影数字|数字科技馆打造:开启科技探索新大门

足不出户&#xff0c;就能畅游科技的奇幻世界&#xff0c;你相信吗&#xff1f;数字科技馆就能帮你实现&#xff01;在这个数字化的时代&#xff0c;数字科技馆如同一颗璀璨的新星&#xff0c;照亮了我们探索科学的道路。 那么&#xff0c;数字科技馆究竟是什么呢&#xff1f; …...

升级 Azure Kubernetes 服务群集的关键注意事项

升级 Azure Kubernetes 服务 (AKS) 集群不仅是为了保持最新状态&#xff0c;更是为了保护您的工作负载、提升性能并降低运营风险。但如果操作不当&#xff0c;可能会导致停机、工作负载中断&#xff0c;甚至访问问题。 在本指南中&#xff0c;我们将介绍&#xff1a; 生产环境…...

数据类型详解(布尔值、整型、浮点型、字符串等)-《Go语言实战指南》

Go语言是一门静态强类型语言&#xff0c;所有变量在编译时必须明确其数据类型。本章将详细介绍Go的基础数据类型&#xff0c;帮助你理解并正确使用它们。 一、数据类型分类总览 Go 的基础数据类型可以分为以下几类&#xff1a; 类型分类代表类型示例布尔类型booltrue, false整…...

单片机-STM32部分:9-1、触控检测芯片

飞书文档https://x509p6c8to.feishu.cn/wiki/ILBsw4EaQiWaUukWrxEcO4XZnXc 传统物理按键 原理 玻璃盖板下通过一个触摸PAD连接到触摸芯片中&#xff0c;触摸PAD可以用PCB铜箔、金属片、平顶圆柱弹簧、导电棉、导电油墨、导电橡胶、导电玻璃的ITO层等。 当有人体手指靠近触摸按…...

从 JMS 到 ActiveMQ:API 设计与扩展机制分析(二)

&#xff08;三&#xff09;消息结构与 API 操作 JMS 消息结构&#xff1a;JMS 消息主要由消息头&#xff08;Header&#xff09;、属性&#xff08;Properties&#xff09;和消息体&#xff08;Body&#xff09;三部分组成。消息头包含了许多预定义的字段&#xff0c;用于标识…...

CSS display: none

在 CSS 中&#xff0c;display: none; 是一个用于控制元素显示与隐藏的属性值&#xff0c;其核心作用是完全从文档流中移除元素&#xff0c;使元素在页面中不占据任何空间&#xff0c;也不会被渲染。以下是详细解释&#xff1a; 核心作用 隐藏元素&#xff1a;使元素在页面中…...

vison transformer vit 论文阅读

An Image is Worth 16x16 Words 20年的论文看成10年的哈斯我了 [2010.11929] 一张图像胜过 16x16 个单词&#xff1a;用于大规模图像识别的转换器 --- [2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 为什么transformer好训练&am…...

dropout层

从你提供的图片来看&#xff0c;里面讨论了 Dropout 层&#xff0c;让我为你解释一下它的工作原理和作用。 Dropout 层是什么&#xff1f; Dropout 是一种常用的正则化技术&#xff0c;用于避免神经网络的 过拟合&#xff08;overfitting&#xff09;。过拟合是指模型在训练数…...

openssl中BIO的使用

BIO是OpenSSL的一个重要的结构和概念&#xff0c;是对数据IO与传递处理的一种类型抽象和功能封装&#xff0c;这里所说的数据IO与传递的“介质”包括&#xff1a;内存、文件、日志、标准设备、网络socket等&#xff0c;“处理”包括简单、加/解密、摘要、ssl协议下的读/写等的数…...

电动汽车充电设施可调能力聚合评估与预测

电动汽车充电设施可调能力聚合评估与预测 项目概述 本项目基于论文《大规模电动汽车充换电设施可调能力聚合评估与预测》(鲍志远&#xff0c;胡泽春)&#xff0c;实现了电动汽车充电设施可调能力的聚合评估与预测方法。 主要文件 real_data_model.m: 使用真实数据实现LSTM线…...

Git clone时出现SSL certificate problem unable to get local issuer certificate

正确解决方法 git config --global http.sslVerify false错误解决方法&#xff1a;&#xff08;主要是看错了嘿嘿&#xff0c;但是如果是 OpenSSL SSL_read: Connection was reset, errno 10054 Failed to connect to github.com port 443: Timed out 原…...

requests库

模拟请求获取网页源代码 如下 import requestsr requests.get(https://spa1.scrape.center/page/1) print(r.text) 源码如下 GET请求 示例网站为 https://httpbin.org import requests r requests.get(https://httpbin.org/) print(r.text) 所显示的结果如下 {"a…...

基于springboot的海洋环保知识分享系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…...

安科瑞ADL3000-E-A/KC三相交流电能表CE认证导轨表

1 概述 ADL3000-E-A 是一款为供电系统、工矿企业以及公用事业单位设计的智能电表&#xff0c;用于计算耗电量并管理用电需求。它具备高精度、体积小以及安装简便的特点。它将所有电气参数的测量与综合电能计量及管理功能集成在一起&#xff0c;可提供过去 12 个月的各类数据&a…...

红黑树算法笔记

文章目录 红黑树 (Red-Black Tree) 学习笔记0. 节点结构与哨兵节点1. 什么是红黑树&#xff1f;2. 红黑树的五个核心性质3. 为什么需要红黑树&#xff1f;4. 红黑树的基本操作a. 查找 (Search)b. 插入 (Insert)c. 删除 (Delete) 5. 维护平衡的关键操作a. 变色 (Recoloring)b. 旋…...

【Axios】解决Axios下载二进制文件返回空对象的问题

【Axios】解决Axios下载二进制文件返回空对象的问题 问题背景 在一个基于Vue 3的项目中,我们使用Axios下载Excel文件,但遇到了一个奇怪的问题:文件能成功下载下来,但打开时显示内容为[object Object]无法使用。 当我们执行下载代码: const response = await downloadT…...

2.MySQL数据库操作

一.MySQL数据库介绍 数据库目前标准指令集是SQL&#xff0c;即结构化查询语言。SQL语言主要由以下几部分组成 DDL&#xff08;数据定义语言&#xff09;&#xff1a;用来建立数据库、数据库对象和定义字段&#xff0c;如create、alter、drop。 DML&#xff08;数据操纵语言&…...

01.three官方示例+编辑器+AI快速学习webgl_animation_keyframes

实例&#xff1a;examples/webgl_animation_keyframes.html 在这里插入图片描述 重点关注&#xff1a; AnimationMixer&#xff1a;管理模型的所有动画AnimationClip&#xff1a;表示一个完整的动画ClipAction&#xff1a;控制动画的播放状态&#xff08;播放、暂停、速度等&am…...

在 Spring Boot 中实现动态线程池的全面指南

动态线程池是一种线程池管理方案&#xff0c;允许在运行时根据业务需求动态调整线程池参数&#xff08;如核心线程数、最大线程数、队列容量等&#xff09;&#xff0c;以优化资源利用率和系统性能。在 Spring Boot 中&#xff0c;动态线程池可以通过 Java 的 ThreadPoolExecut…...

餐饮行业新风口:上门厨师服务系统的技术实现路径

上门做饭正在成为下一个万亿级风口&#xff01;当外卖平台被预制菜攻陷&#xff0c;当年轻人对着料理包无可奈何&#xff0c;一个全新的餐饮模式正在悄然崛起。 我们的市场调研显示&#xff0c;83%的消费者无法分辨外卖是否使用预制菜&#xff0c;76%的年轻人愿意为透明烹饪过程…...