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文档
  • 爬虫法律法规与道德规范

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

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

相关文章

SpringBoot配置文件的合并

需求:想分类将mysql数据库的配置放在一个文件,redis的配置放在另外一个文件 就不去引入mysql和redis了,看能否得到值就行了 测试结果 model的包放错了 应该移动到demo里 能否用yml或者yaml呢 这里注意yml的写法 测试结果也是可以的 注意如果主配置文件是yml或者yaml的话

深入理解 BFC:网页布局的关键机制

在前端开发的世界里&#xff0c;网页布局是一项至关重要的任务。而在众多布局相关的概念中&#xff0c;BFC&#xff08;Block Formatting Context&#xff0c;块级格式化上下文&#xff09;扮演着极为关键的角色。今天&#xff0c;就让我们深入剖析 BFC 的方方面面。 一、BFC …

04-Web后端基础(基础知识)

而像HTML、CSS、JS 以及图片、音频、视频等这些资源&#xff0c;我们都称为静态资源。 所谓静态资源&#xff0c;就是指在服务器上存储的不会改变的数据&#xff0c;通常不会根据用户的请求而变化。 那与静态资源对应的还有一类资源&#xff0c;就是动态资源。那所谓动态资源&…

Vue3 Element Plus el-table-column Sortable 排序失效

问题描述&#xff1a; vue3中 element plus 中 el-table 的 el-table-column使用了插槽后&#xff0c;为什么sortable不起效果&#xff0c;不能点击排序 <el-table-columnlabel"记账日期"width"110"fixed"left"header-align"left"…

Unity中SRP Batcher使用整理

SRP Batcher 是一种绘制调用优化,可显著提高使用 SRP 的应用程序的性能,SRP Batcher 减少了Unity为使用相同着色器变体的材质准备和调度绘制调用所需的CPU 时间。 工作原理: 传统优化方法通过减少绘制调用次数提升性能,而SRP Batcher的核心理念在于降低绘制调用间的渲染状…

服务器的基础知识

什么是服务器 配置牛、运行稳、价格感人的高级计算机&#xff0c;家用电脑不能比拟的。 服务器的组成&#xff1a;电源、raid卡、网卡、内存、cpu、主板、风扇、硬盘。 服务器的分类 按计算能力分类 超级计算机 小型机AIX x86服务器&#xff08;服务器cpu架构&#xff09; …

服务器网络配置 netplan一个网口配置两个ip(双ip、辅助ip、别名IP别名)

文章目录 问答 问 # This is the network config written by subiquity network:ethernets:enp125s0f0:dhcp4: noaddresses: [192.168.90.180/24]gateway4: 192.168.90.1nameservers:addresses:- 172.0.0.207- 172.0.0.208enp125s0f1:dhcp4: trueenp125s0f2:dhcp4: trueenp125…

高级SQL技巧:时序数据查询优化与性能调优实战

高级SQL技巧&#xff1a;时序数据查询优化与性能调优实战 引言 在现代数据驱动型系统中&#xff0c;时序数据&#xff08;时间序列数据&#xff09;正成为企业核心资产之一。然而&#xff0c;随着数据量激增和复杂业务需求的不断涌现&#xff0c;传统的SQL查询方式已难以满足…

DDoS攻击应对指南:提升网站安全性的有效策略

DDoS&#xff08;分布式拒绝服务&#xff09;攻击成为了企业面临的主要网络安全威胁之一。随着技术的不断发展&#xff0c;DDoS攻击手段也在不断升级&#xff0c;给企业的网络安全带来了极大的挑战。针对这一问题&#xff0c;企业需要采取有效的防御措施&#xff0c;以保障网站…

Appium 的 enableMultiWindows 参数

引言 在移动应用自动化测试中&#xff0c;​​混合应用&#xff08;Hybrid App&#xff09;​​ 和多窗口场景&#xff08;如分屏、弹窗、多 WebView&#xff09;的处理一直是技术难点。Appium 的 enableMultiWindows 参数为这类场景提供了关键支持&#xff0c;但在实际使用中常…

C++中的菱形继承问题

假设有一个问题&#xff0c;类似于鸭子这样的动物有很多种&#xff0c;如企鹅和鱿鱼&#xff0c;它们也可能会有一些共同的特性。例如&#xff0c;我们可以有一个叫做 AquaticBird &#xff08;涉禽&#xff0c;水鸟的一类&#xff09;的类&#xff0c;它又继承自 Animal 和 Sw…

前端excel表格解析为json,并模仿excel显示

前端环境&#xff1a;elementUI vue2 <style lang"scss" scoped> 页面效果 jsondata为mock数据&#xff0c;为方便调试其内容可清空&#xff0c;首行&#xff08;字母坐标&#xff09;随数据内容自动变化&#xff0c;首列也是一样&#xff0c;模拟excel …

NAT(网络地址转换)逻辑图解+实验详解

原理 NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09; 是一种网络技术&#xff0c;用于在IP数据包通过路由器或防火墙时&#xff0c;修改其源IP地址或目标IP地址&#xff0c;以实现不同网络之间的通信。 基础概念 本来NAT是来解决 IPv4 地…

Qt+线段拖曳示例代码

Qt线段拖曳示例代码&#xff0c;功能见下图。 代码如下&#xff1a; canvaswidget.h #ifndef CANVASWIDGET_H #define CANVASWIDGET_H#include <QWidget> #include <QPainter> #include <QMouseEvent> #include <QVector>class CanvasWidget : publi…

高等数学-求导

一、求导数的原函数就是求导数的积分 1&#xff09;设函数f(t)在区间[a,b]上连续&#xff0c;则对任意的x∈[a,b],f(t)在[a,x]上连续&#xff0c;从而在[a,x]上可积。令其积分为Φ(x)∫*a^x f(t)dt, x∈[a,b],则Φ(x)为定义在区间[a,b]上的一个函数&#xff0c;通常称作积分上…

(第94天)OGG 微服务搭建 Oracle 19C CDB 架构同步

前言 Oracle GoldenGate Microservice Architecture (OGGMA) 是在 OGG 12.3 版本推出的全新架构。相比传统架构,OGGMA 基于 Rest API,通过 WEB 界面即可完成 OGG 的配置和监控,大大简化了部署和管理流程。 本文将详细介绍如何在 Oracle 19C CDB 环境中部署 OGG 19.1.0.4 微…

前端vscode学习

1.安装python 打开Python官网&#xff1a;Welcome to Python.org 一定要点PATH&#xff0c;要不然要自己设 点击install now,就自动安装了 键盘winR 输入cmd 点击确定 输入python&#xff0c;回车 显示这样就是安装成功了 2.安装vscode 2.1下载软件 2.2安装中文 2.2.1当安…

uniapp vue 开发微信小程序 分包梳理经验总结

嗨&#xff0c;我是小路。今天主要和大家分享的主题是“uniapp vue 开发微信小程序 分包梳理经验总结”。 在使用 UniAppvue框架开发微信小程序时&#xff0c;当项目比较大的时候&#xff0c;经常需要分包加载。它有助于控制主包的大小&#xff0c;从而提升小程序的启…

git合并多次commit提交

首先查看历史记录 git log 查看你想要合并的commit是哪些&#xff08;注意&#xff1a;这里是逆序&#xff0c;最上的是最新提交&#xff09; 找到当前想要合并的最后一个记录&#xff0c;复制该记录的下一个记录的 id&#xff08;黄色部分commit id&#xff09;&#xff0c…

系统架构设计(七):数据流图

定义 数据流图&#xff08;Data Flow Diagram, DFD&#xff09;是一种用于表示信息系统数据流转及处理过程的图形工具。 它反映系统功能及数据之间的关系&#xff0c;是结构化分析与设计的重要工具。 主要符号 符号说明描述举例方框外部实体&#xff08;源或终点&#xff09…