Jenkins 插件深度應用:讓你的CI/CD流水線如虎添翼 [特殊字符]

Jenkins 插件深度應用:讓你的CI/CD流水線如虎添翼 🚀

嘿,各位開發小伙伴!今天咱們來聊聊Jenkins的插件生態系統。如果說Jenkins是一臺強大的引擎,那插件就是讓這臺引擎發揮最大威力的各種零部件。準備好了嗎?讓我們一起探索Jenkins插件的奇妙世界!

📋 本期導航

  • 🔍 常用插件推薦:SonarQube代碼質量檢測插件深度解析
  • 📦 插件安裝與管理:官方插件庫使用與第三方插件配置技巧
  • 🛠? 自定義插件開發:從零開始打造屬于你的Jenkins插件
  • 🔧 插件沖突解決:版本兼容問題處理與最佳實踐

🔍 常用插件推薦:SonarQube代碼質量檢測插件

為什么選擇SonarQube插件?

想象一下,你的代碼就像一道菜,SonarQube就是那個挑剔的美食評委,它會從各個角度檢查你的"菜品":

  • 代碼異味檢測 🦨:發現那些看起來沒問題但實際上有隱患的代碼
  • 安全漏洞掃描 🔒:提前發現潛在的安全風險
  • 代碼覆蓋率分析 📊:告訴你測試到底覆蓋了多少代碼
  • 技術債務評估 💰:量化代碼質量,讓管理層也能看懂

安裝SonarQube插件

# 方式一:通過Jenkins管理界面安裝
# 進入 Manage Jenkins -> Manage Plugins -> Available
# 搜索 "SonarQube Scanner" 并安裝

配置SonarQube服務器

// Jenkins Pipeline 配置示例
pipeline {agent anyenvironment {SONAR_TOKEN = credentials('sonar-token')}stages {stage('代碼檢出') {steps {git 'https://github.com/your-repo/project.git'}}stage('SonarQube分析') {steps {script {def scannerHome = tool 'SonarQubeScanner'withSonarQubeEnv('SonarQube') {sh """${scannerHome}/bin/sonar-scanner \-Dsonar.projectKey=my-project \-Dsonar.sources=src \-Dsonar.host.url=${SONAR_HOST_URL} \-Dsonar.login=${SONAR_TOKEN}"""}}}}stage('質量門檢查') {steps {timeout(time: 1, unit: 'HOURS') {waitForQualityGate abortPipeline: true}}}}
}

實戰技巧

技巧1:設置合理的質量門

# sonar-project.properties
sonar.qualitygate.wait=true
sonar.coverage.exclusions=**/*Test.java,**/test/**
sonar.cpd.exclusions=**/*DTO.java,**/*Entity.java

技巧2:集成到Pull Request檢查

// 在PR構建中添加SonarQube檢查
when {changeRequest()
}
steps {script {def prKey = env.CHANGE_IDsh """sonar-scanner \-Dsonar.pullrequest.key=${prKey} \-Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} \-Dsonar.pullrequest.base=${env.CHANGE_TARGET}"""}
}

📦 插件安裝與管理:官方插件庫使用與第三方插件配置

官方插件庫:你的插件寶庫

通過Web界面安裝
  1. 進入插件管理頁面

    Jenkins首頁 -> Manage Jenkins -> Manage Plugins
    
  2. 瀏覽可用插件

    • Available:可安裝的插件
    • Installed:已安裝的插件
    • Updates:可更新的插件
    • Advanced:高級配置
命令行安裝插件
# 使用Jenkins CLI安裝插件
java -jar jenkins-cli.jar -s http://localhost:8080/ install-plugin plugin-name# 批量安裝插件
cat plugins.txt | while read plugin; dojava -jar jenkins-cli.jar -s http://localhost:8080/ install-plugin $plugin
done

plugins.txt示例:

blue-ocean
pipeline-stage-view
git
maven-plugin
sonar
docker-plugin
kubernetes
slack
email-ext
build-timeout

第三方插件配置

手動安裝.hpi文件
# 1. 下載插件文件
wget https://example.com/custom-plugin.hpi# 2. 復制到Jenkins插件目錄
cp custom-plugin.hpi $JENKINS_HOME/plugins/# 3. 重啟Jenkins
sudo systemctl restart jenkins
通過Dockerfile預裝插件
FROM jenkins/jenkins:lts# 切換到root用戶安裝插件
USER root# 復制插件列表
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt# 安裝插件
RUN jenkins-plugin-cli --plugin-file /usr/share/jenkins/ref/plugins.txt# 安裝自定義插件
COPY custom-plugins/*.hpi /usr/share/jenkins/ref/plugins/# 切換回jenkins用戶
USER jenkins

插件管理最佳實踐

實踐1:插件版本鎖定

// Jenkinsfile中指定插件版本
@Library('my-shared-library@v1.2.3') _pipeline {agent {label 'docker && plugin-version-1.5.0'}// ...
}

實踐2:插件依賴檢查腳本

#!/bin/bash
# check-plugin-dependencies.shJENKINS_URL="http://localhost:8080"
USER="admin"
TOKEN="your-api-token"# 獲取已安裝插件列表
curl -s -u $USER:$TOKEN "$JENKINS_URL/pluginManager/api/json?depth=1" | \jq -r '.plugins[] | "\(.shortName):\(.version)"' > installed-plugins.txt# 檢查插件依賴
echo "檢查插件依賴關系..."
while read plugin; doplugin_name=$(echo $plugin | cut -d':' -f1)echo "檢查插件: $plugin_name"curl -s "$JENKINS_URL/plugin/$plugin_name/api/json" | \jq -r '.dependencies[]? | "依賴: \(.shortName) (\(.version))"'
done < installed-plugins.txt

🛠? 自定義插件開發基礎:插件開發流程與示例

開發環境準備

環境要求
# Java 8 或更高版本
java -version# Maven 3.6+
mvn -version# Jenkins Plugin Parent POM
創建插件項目
# 使用Maven archetype創建插件項目
mvn archetype:generate \-DarchetypeGroupId=org.jenkins-ci.tools \-DarchetypeArtifactId=maven-hpi-plugin \-DgroupId=com.example \-DartifactId=my-awesome-plugin \-Dversion=1.0-SNAPSHOTcd my-awesome-plugin

插件基礎結構

pom.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.jenkins-ci.plugins</groupId><artifactId>plugin</artifactId><version>4.40</version><relativePath /></parent><groupId>com.example</groupId><artifactId>my-awesome-plugin</artifactId><version>1.0-SNAPSHOT</version><packaging>hpi</packaging><name>My Awesome Plugin</name><description>一個超棒的Jenkins插件示例</description><properties><jenkins.version>2.361.4</jenkins.version><java.level>8</java.level></properties><dependencies><dependency><groupId>org.jenkins-ci.plugins</groupId><artifactId>structs</artifactId><version>1.23</version></dependency></dependencies>
</project>

實戰示例:構建通知插件

主插件類:

package com.example.myawesomeplugin;import hudson.Extension;
import hudson.Launcher;
import hudson.model.*;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import jenkins.tasks.SimpleBuildStep;
import org.kohsuke.stapler.DataBoundConstructor;public class AwesomeNotifier extends Recorder implements SimpleBuildStep {private final String webhookUrl;private final boolean notifyOnSuccess;private final boolean notifyOnFailure;@DataBoundConstructorpublic AwesomeNotifier(String webhookUrl, boolean notifyOnSuccess, boolean notifyOnFailure) {this.webhookUrl = webhookUrl;this.notifyOnSuccess = notifyOnSuccess;this.notifyOnFailure = notifyOnFailure;}@Overridepublic void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) {Result result = run.getResult();if (shouldNotify(result)) {sendNotification(run, listener);}}private boolean shouldNotify(Result result) {if (result == Result.SUCCESS && notifyOnSuccess) {return true;}if (result != Result.SUCCESS && notifyOnFailure) {return true;}return false;}private void sendNotification(Run<?, ?> run, TaskListener listener) {try {String message = String.format("構建 %s #%d %s", run.getParent().getDisplayName(),run.getNumber(),run.getResult().toString());// 發送HTTP請求到webhook// 這里簡化處理,實際應該使用HttpClientlistener.getLogger().println("發送通知: " + message);} catch (Exception e) {listener.getLogger().println("發送通知失敗: " + e.getMessage());}}@Overridepublic BuildStepMonitor getRequiredMonitorService() {return BuildStepMonitor.NONE;}// Getter方法public String getWebhookUrl() { return webhookUrl; }public boolean isNotifyOnSuccess() { return notifyOnSuccess; }public boolean isNotifyOnFailure() { return notifyOnFailure; }@Extensionpublic static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {@Overridepublic boolean isApplicable(Class<? extends AbstractProject> aClass) {return true;}@Overridepublic String getDisplayName() {return "Awesome 構建通知";}}
}

配置頁面(config.jelly):

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"><f:entry title="Webhook URL" field="webhookUrl"><f:textbox /></f:entry><f:entry title="通知設置"><f:checkbox field="notifyOnSuccess" title="構建成功時通知" /><f:checkbox field="notifyOnFailure" title="構建失敗時通知" /></f:entry></j:jelly>

插件測試

package com.example.myawesomeplugin;import hudson.model.FreeStyleProject;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;public class AwesomeNotifierTest {@Rulepublic JenkinsRule jenkins = new JenkinsRule();@Testpublic void testConfigRoundtrip() throws Exception {FreeStyleProject project = jenkins.createFreeStyleProject();AwesomeNotifier notifier = new AwesomeNotifier("https://hooks.slack.com/test", true, true);project.getPublishersList().add(notifier);project = jenkins.configRoundtrip(project);AwesomeNotifier configured = project.getPublishersList().get(AwesomeNotifier.class);jenkins.assertEqualDataBoundBeans(notifier, configured);}
}

構建和部署

# 本地測試運行
mvn hpi:run# 構建插件
mvn clean package# 生成的插件文件
ls target/*.hpi

🔧 插件沖突解決與版本兼容問題處理

常見插件沖突類型

1. 依賴版本沖突

問題現象:

java.lang.NoSuchMethodError: com.example.SomeClass.someMethod()
ClassNotFoundException: org.apache.commons.lang.StringUtils

解決方案:

# 檢查插件依賴樹
mvn dependency:tree# 查看Jenkins插件依賴
curl -s "http://localhost:8080/plugin/plugin-name/api/json" | jq '.dependencies'
2. 類加載沖突

診斷腳本:

// 在Jenkins Script Console中運行
import jenkins.model.Jenkinsdef plugins = Jenkins.instance.pluginManager.plugins
plugins.each { plugin ->println "${plugin.shortName}:${plugin.version}"plugin.dependencies.each { dep ->println "  -> ${dep.shortName}:${dep.version}"}
}

版本兼容性檢查工具

自動化檢查腳本
#!/usr/bin/env python3
# plugin-compatibility-checker.pyimport requests
import json
import sys
from packaging import versionclass PluginCompatibilityChecker:def __init__(self, jenkins_url, username, token):self.jenkins_url = jenkins_urlself.auth = (username, token)def get_installed_plugins(self):"""獲取已安裝插件列表"""url = f"{self.jenkins_url}/pluginManager/api/json?depth=2"response = requests.get(url, auth=self.auth)return response.json()['plugins']def check_plugin_compatibility(self, plugin_name, target_version):"""檢查插件版本兼容性"""url = f"https://updates.jenkins.io/current/plugin/{plugin_name}.json"try:response = requests.get(url)plugin_info = response.json()# 檢查Jenkins版本要求required_jenkins = plugin_info.get('requiredCore', '0')current_jenkins = self.get_jenkins_version()if version.parse(current_jenkins) < version.parse(required_jenkins):return False, f"需要Jenkins {required_jenkins},當前版本 {current_jenkins}"return True, "兼容"except Exception as e:return False, f"檢查失敗: {str(e)}"def get_jenkins_version(self):"""獲取Jenkins版本"""url = f"{self.jenkins_url}/api/json"response = requests.get(url, auth=self.auth)return response.headers.get('X-Jenkins', '未知')def generate_compatibility_report(self):"""生成兼容性報告"""plugins = self.get_installed_plugins()report = []for plugin in plugins:name = plugin['shortName']current_version = plugin['version']# 檢查是否有更新compatible, message = self.check_plugin_compatibility(name, current_version)report.append({'name': name,'current_version': current_version,'compatible': compatible,'message': message})return report# 使用示例
if __name__ == "__main__":checker = PluginCompatibilityChecker("http://localhost:8080","admin","your-api-token")report = checker.generate_compatibility_report()print("插件兼容性報告:")print("=" * 50)for item in report:status = "?" if item['compatible'] else "?"print(f"{status} {item['name']} ({item['current_version']}) - {item['message']}")

沖突解決策略

策略1:版本降級
# 下載特定版本插件
wget "https://updates.jenkins.io/download/plugins/plugin-name/1.2.3/plugin-name.hpi"# 停止Jenkins
sudo systemctl stop jenkins# 替換插件文件
cp plugin-name.hpi $JENKINS_HOME/plugins/# 啟動Jenkins
sudo systemctl start jenkins
策略2:依賴隔離
<!-- 在插件pom.xml中排除沖突依賴 -->
<dependency><groupId>org.jenkins-ci.plugins</groupId><artifactId>some-plugin</artifactId><version>1.0</version><exclusions><exclusion><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId></exclusion></exclusions>
</dependency>
策略3:插件替換
// 插件遷移腳本
def oldPlugin = "old-plugin-name"
def newPlugin = "new-plugin-name"// 獲取使用舊插件的Job
def jobs = Jenkins.instance.getAllItems(Job.class)
jobs.each { job ->if (job.getBuilders().any { it.class.name.contains(oldPlugin) }) {println "Job ${job.name} 使用了 ${oldPlugin}"// 這里添加遷移邏輯}
}

預防措施

1. 插件更新策略
# docker-compose.yml - 使用固定版本
version: '3.8'
services:jenkins:image: jenkins/jenkins:2.401.3-ltsenvironment:- JENKINS_OPTS=--httpPort=8080volumes:- jenkins_home:/var/jenkins_home- ./plugins.txt:/usr/share/jenkins/ref/plugins.txtports:- "8080:8080"- "50000:50000"volumes:jenkins_home:
2. 測試環境驗證
#!/bin/bash
# test-plugin-update.shecho "創建測試環境..."
docker run -d --name jenkins-test \-p 8081:8080 \-v jenkins-test:/var/jenkins_home \jenkins/jenkins:ltsecho "等待Jenkins啟動..."
sleep 60echo "安裝插件..."
cat plugins-to-test.txt | while read plugin; dodocker exec jenkins-test jenkins-plugin-cli --plugins $plugin
doneecho "重啟Jenkins..."
docker restart jenkins-testecho "檢查插件狀態..."
curl -s http://localhost:8081/pluginManager/api/json | \jq '.plugins[] | select(.enabled == false) | .shortName'echo "清理測試環境..."
docker rm -f jenkins-test
docker volume rm jenkins-test

🎯 總結

通過這篇文章,我們深入探索了Jenkins插件的方方面面:

🔑 關鍵要點

  1. 插件選擇要謹慎:不是越多越好,選擇適合團隊需求的核心插件
  2. 版本管理很重要:建立插件版本控制和兼容性檢查機制
  3. 自定義開發有門檻:但掌握基礎開發技能能解決特殊需求
  4. 沖突預防勝于治療:建立完善的測試和驗證流程

🚀 下一步行動

  • 審查當前Jenkins實例的插件使用情況
  • 建立插件更新和測試流程
  • 考慮開發團隊特定需求的自定義插件
  • 制定插件沖突應急處理預案

💡 小貼士

記住,Jenkins插件生態系統就像一個大型的樂高積木庫,合理搭配能構建出強大的CI/CD流水線。但也要避免"插件依賴癥",保持系統的簡潔和穩定性。


如果這篇文章對你有幫助,別忘了點贊收藏哦!有問題歡迎在評論區交流討論! 😊

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87634.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87634.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87634.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

密碼學(斯坦福)

密碼學筆記 \huge{密碼學筆記} 密碼學筆記 斯坦福大學密碼學的課程筆記 課程網址&#xff1a;https://www.bilibili.com/video/BV1Rf421o79E/?spm_id_from333.337.search-card.all.click&vd_source5cc05a038b81f6faca188e7cf00484f6 概述 密碼學的使用背景 安全信息保護…

代碼隨想錄算法訓練營第四十六天|動態規劃part13

647. 回文子串 題目鏈接&#xff1a;647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; 文章講解&#xff1a;代碼隨想錄 思路&#xff1a; 以dp【i】表示以s【i】結尾的回文子串的個數&#xff0c;發現遞推公式推導不出來此路不通 以dp【i】【j】表示s【i】到s【j】的回…

基于四種機器學習算法的球隊數據分析預測系統的設計與實現

文章目錄 有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主項目介紹項目展示隨機森林模型XGBoost模型邏輯回歸模型catboost模型每文一語 有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主 項目介紹 本項目旨在設計與實現…

http、SSL、TLS、https、證書

一、基礎概念 1.HTTP HTTP (超文本傳輸協議) 是一種用于客戶端和服務器之間傳輸超媒體文檔的應用層協議&#xff0c;是萬維網的基礎。 簡而言之&#xff1a;一種獲取和發送信息的標準協議 2.SSL 安全套接字層&#xff08;SSL&#xff09;是一種通信協議或一組規則&#xf…

在 C++ 中,判斷 `std::string` 是否為空字符串

在 C 中&#xff0c;判斷 std::string 是否為空字符串有多種方法&#xff0c;以下是最常用的幾種方式及其區別&#xff1a; 1. 使用 empty() 方法&#xff08;推薦&#xff09; #include <string>std::string s; if (s.empty()) {// s 是空字符串 }特性&#xff1a; 時間…

【Harmony】鴻蒙企業應用詳解

【HarmonyOS】鴻蒙企業應用詳解 一、前言 1、應用類型定義速覽&#xff1a; HarmonyOS目前針對應用分為三種類型&#xff1a;普通應用&#xff0c;游戲應用&#xff0c;企業應用。 而企業應用又分為&#xff0c;企業普通應用和設備管理應用MDM&#xff08;Mobile Device Man…

Linux云計算基礎篇(8)

VIM 高級特性插入模式按 i 進入插入模式。按 o 在當前行下方插入空行并進入插入模式。按 O 在當前行上方插入空行并進入插入模式。命令模式:set nu 顯示行號。:set nonu 取消顯示行號。:100 光標跳轉到第 100 行。G 光標跳轉到文件最后一行。gg 光標跳轉到文件第一行。30G 跳轉…

Linux進程單例模式運行

Linux進程單例模式運行 #include <iostream> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int write_pid(const cha…

【Web 后端】部署服務到服務器

文章目錄 前言一、如何啟動服務二、掛載和開機啟動服務1. 配置systemctl 服務2. 創建server用戶3. 啟動服務 總結 前言 如果你的后端服務寫好了如果部署到你的服務器呢&#xff0c;本次通過fastapi寫的服務實例&#xff0c;示范如何部署到服務器&#xff0c;并做服務管理。 一…

國產MCU學習Day5——CW32F030C8T6:窗口看門狗功能全解析

每日更新教程&#xff0c;評論區答疑解惑&#xff0c;小白也能變大神&#xff01;" 目錄 一.窗口看門狗&#xff08;WWDG&#xff09;簡介 二.窗口看門狗寄存器列表 三.窗口看門狗復位案例 一.窗口看門狗&#xff08;WWDG&#xff09;簡介 CW32F030C8T6 內部集成窗口看…

2025年文件加密軟件分享:守護數字世界的核心防線

在數字化時代&#xff0c;數據已成為個人與企業的寶貴資產&#xff0c;文件加密軟件通過復雜的算法&#xff0c;確保信息在存儲、傳輸與共享過程中的保密性、完整性與可用性。一、文件加密軟件的核心原理文件加密軟件算法以其高效性與安全性廣泛應用&#xff0c;通過對文件數據…

node.js下載教程

1.項目環境文檔 語雀 2.nvm安裝教程與nvm常見命令,超詳細!-阿里云開發者社區 C:\Windows\System32>nvm -v 1.2.2 C:\Windows\System32>nvm list available Error retrieving "http://npm.taobao.org/mirrors/node/index.json": HTTP Status 404 C:\Window…

(AI如何解決問題)在一個項目,跳轉到外部html頁面,頁面布局

問題描述目前&#xff0c;ERP后臺有很多跳轉外部鏈接的地方&#xff0c;會直接打開一個tab顯示。因為有些頁面是適配手機屏幕顯示&#xff0c;放在瀏覽器會超級大。不美觀&#xff0c;因此提出優化。修改前&#xff1a;修改后&#xff1a;思考過程1、先看下代碼&#xff1a;log…

網絡通信協議與虛擬網絡技術相關整理(上)

#作者&#xff1a;程宏斌 文章目錄 tcp協議udp協議arp協議icmp協議dhcp協議BGP協議OSPF協議BGP vs OSPF 對比表VLAN&#xff08;Virtual LAN&#xff09;VXLAN&#xff08;Virtual Extensible LAN&#xff09;IPIP&#xff08;IP-in-IP&#xff09;vxlan/vlan/ipip網橋/veth網…

物聯網軟件層面的核心技術體系

物聯網軟件層面的核心技術體系 物聯網(IoT)軟件技術棧是一個多層次的復雜體系&#xff0c;涵蓋從設備端到云平臺的完整解決方案。以下是物聯網軟件層面的關鍵技術分類及詳細說明&#xff1a; 一、設備端軟件技術 1. 嵌入式操作系統 實時操作系統(RTOS)&#xff1a; FreeRTO…

GreatSQL通過偽裝從庫回放Binlog文件

GreatSQL通過偽裝從庫回放Binlog文件 一、適用場景說明 1、主庫誤操作恢復 利用 Binlog 在其他實例解析、回放&#xff0c;根據gtid只回放到指定位點。 2、網絡隔離環境同步 備份恢復后可以拉去主庫Binlog文件至新實例同步增量數據。 3、備份恢復遇到Binlog文件過大處理 恢復實…

MVC 架構設計模式

在現代軟件開發中&#xff0c;架構設計決定了一個項目的可維護性與可擴展性。MVC&#xff08;Model-View-Controller&#xff09;作為經典的分層設計模式&#xff0c;廣泛應用于 Web 系統、前端應用乃至移動端開發中。本文不僅介紹 MVC 的核心思想和機制&#xff0c;還將結合具…

(18)python+playwright自動化測試鼠標拖拽-上

1.簡介 本文主要介紹兩個在測試過程中可能會用到的功能&#xff1a;在selenium中介紹了Actions類中的拖拽操作和Actions類中的劃取字段操作。例如&#xff1a;需要在一堆log字符中隨機劃取一段文字&#xff0c;然后右鍵選擇摘取功能。playwright同樣可以實現元素的拖拽和釋放的…

Android 網絡全棧攻略(四)—— TCPIP 協議族與 HTTPS 協議

Android 網絡全棧攻略系列文章&#xff1a; Android 網絡全棧攻略&#xff08;一&#xff09;—— HTTP 協議基礎 Android 網絡全棧攻略&#xff08;二&#xff09;—— 編碼、加密、哈希、序列化與字符集 Android 網絡全棧攻略&#xff08;三&#xff09;—— 登錄與授權 Andr…

Python爬蟲實戰:從零構建完整項目(數據采集+存儲+異常處理)

Python爬蟲實戰&#xff1a;從零構建完整項目&#xff08;數據采集存儲異常處理&#xff09; 爬蟲不是簡單的請求解析&#xff0c;而是一個系統工程。本文將帶你體驗企業級爬蟲開發的核心流程。 一、前言&#xff1a;為什么需要完整的爬蟲項目&#xff1f; 作為初學者&#xf…