Python + Skills 架構(gòu)實(shí)現(xiàn)從理論到實(shí)踐
第一部分:Skills架構(gòu)理論基礎(chǔ)
1.1 什么是Skills架構(gòu)?
Skills架構(gòu)是一種模塊化設(shè)計(jì)模式,它將復(fù)雜的業(yè)務(wù)流程分解為一系列獨(dú)立的、可重用的功能單元(稱為"技能")。每個技能專注于完成特定的任務(wù),并通過統(tǒng)一的接口進(jìn)行交互。
核心特征:
- 單一職責(zé)原則:每個技能只負(fù)責(zé)一個明確的功能
- 高內(nèi)聚低耦合:技能內(nèi)部邏輯緊密相關(guān),外部依賴最小化
- 可組合性:技能可以靈活組合形成更復(fù)雜的功能
- 可測試性:獨(dú)立的技能單元便于單元測試和集成測試
1.2 Skills架構(gòu)的優(yōu)勢
開發(fā)效率提升:
- 代碼復(fù)用性高,減少重復(fù)開發(fā)
- 模塊化設(shè)計(jì)便于團(tuán)隊(duì)協(xié)作
- 快速構(gòu)建新功能通過技能組合
系統(tǒng)維護(hù)性:
- 問題定位和修復(fù)更加容易
- 單個技能升級不影響整體系統(tǒng)
- 便于性能優(yōu)化和功能擴(kuò)展
業(yè)務(wù)適應(yīng)性:
- 快速響應(yīng)業(yè)務(wù)需求變化
- 支持配置驅(qū)動開發(fā)
- 易于集成第三方服務(wù)
第二部分:核心架構(gòu)設(shè)計(jì)
2.1 基礎(chǔ)組件設(shè)計(jì)
BaseSkill - 技能基類
from abc import ABC, abstractmethod
from typing import Any
import logging
class BaseSkill(ABC):
"""技能基類 - 所有技能的抽象基類"""
def __init__(self, name: str):
self.name = name
self.logger = logging.getLogger(f"skill.{name}")
@abstractmethod
async def execute(self, *args, **kwargs) -> Any:
"""執(zhí)行技能的核心邏輯"""
pass
def __str__(self):
return f"Skill({self.name})"設(shè)計(jì)要點(diǎn):
- 抽象基類確保統(tǒng)一的接口規(guī)范
- 內(nèi)置日志記錄便于調(diào)試和監(jiān)控
- 異步執(zhí)行支持高性能并發(fā)處理
2.2 技能編排器 (SkillOrchestrator)
class SkillOrchestrator:
"""技能編排器 - 負(fù)責(zé)協(xié)調(diào)多個技能的執(zhí)行"""
def __init__(self):
self.skills = {}
self.logger = logging.getLogger("orchestrator")
def register_skill(self, name: str, skill: BaseSkill):
"""注冊技能"""
self.skills[name] = skill
self.logger.info(f"注冊技能: {name}")
async def execute_workflow(self, workflow: List[Dict]) -> Dict[str, Any]:
"""執(zhí)行工作流"""
results = {}
for step in workflow:
skill_name = step['skill']
skill_args = step.get('args', {})
if skill_name not in self.skills:
self.logger.error(f"未注冊的技能: {skill_name}")
continue
try:
self.logger.info(f"執(zhí)行技能: {skill_name}")
result = await self.skills[skill_name].execute(**skill_args)
results[skill_name] = result
self.logger.info(f"技能執(zhí)行完成: {skill_name}")
except Exception as e:
self.logger.error(f"技能執(zhí)行失敗 {skill_name}: {e}")
results[skill_name] = None
return results編排器功能:
- 技能注冊和管理
- 工作流順序執(zhí)行
- 錯誤處理和結(jié)果收集
- 執(zhí)行狀態(tài)監(jiān)控
第三部分:具體技能實(shí)現(xiàn)
3.1 瀏覽器管理技能 (BrowserManagerSkill)
class BrowserManagerSkill(BaseSkill):
"""瀏覽器管理技能 - 負(fù)責(zé)瀏覽器生命周期管理"""
def __init__(self, headless: bool = True):
super().__init__("browser_manager")
self.headless = headless
self.browser = None
self.context = None
self.page = None
async def execute(self, setup_only: bool = True) -> tuple:
"""執(zhí)行瀏覽器設(shè)置"""
try:
from playwright.async_api import async_playwright
self.logger.info("啟動瀏覽器...")
playwright = await async_playwright().start()
# 啟動瀏覽器
self.browser = await playwright.chromium.launch(
headless=self.headless,
args=[
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-blink-features=AutomationControlled'
]
)
# 創(chuàng)建上下文
self.context = await self.browser.new_context(
ignore_https_errors=True
)
# 創(chuàng)建頁面
self.page = await self.context.new_page()
self.logger.info("瀏覽器啟動成功")
return self.browser, self.context, self.page
except Exception as e:
self.logger.error(f"瀏覽器啟動失敗: {e}")
raise
async def cleanup(self):
"""清理瀏覽器資源"""
try:
if self.context:
await self.context.close()
if self.browser:
await self.browser.close()
self.logger.info("瀏覽器資源清理完成")
except Exception as e:
self.logger.error(f"資源清理失敗: {e}")技術(shù)要點(diǎn):
- 使用Playwright進(jìn)行瀏覽器自動化
- 支持有頭和無頭模式
- 完善的資源管理和清理
- 異常處理和日志記錄
3.2 頁面導(dǎo)航技能 (PageNavigationSkill)
class PageNavigationSkill(BaseSkill):
"""頁面導(dǎo)航技能 - 負(fù)責(zé)頁面導(dǎo)航和等待"""
def __init__(self, page):
super().__init__("page_navigation")
self.page = page
async def execute(self, url: str, timeout: int = 30000) -> bool:
"""導(dǎo)航到指定URL"""
try:
self.logger.info(f"導(dǎo)航到: {url}")
# 設(shè)置頁面頭信息,避免被識別為爬蟲
await self.page.set_extra_http_headers({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
# 導(dǎo)航到目標(biāo)頁面
await self.page.goto(url, timeout=timeout)
# 等待頁面加載完成
await self.page.wait_for_load_state('networkidle')
self.logger.info("頁面導(dǎo)航成功")
return True
except Exception as e:
self.logger.error(f"頁面導(dǎo)航失敗: {e}")
return False功能特性:
- 智能頁面導(dǎo)航和等待
- 反爬蟲規(guī)避策略
- 超時控制和錯誤處理
- 網(wǎng)絡(luò)狀態(tài)監(jiān)控
3.3 數(shù)據(jù)提取技能 (DataExtractionSkill)
class DataExtractionSkill(BaseSkill):
"""數(shù)據(jù)提取技能 - 負(fù)責(zé)從頁面提取結(jié)構(gòu)化數(shù)據(jù)"""
def __init__(self, page):
super().__init__("data_extraction")
self.page = page
async def execute(self, extraction_config: Dict) -> List[Dict]:
"""執(zhí)行數(shù)據(jù)提取"""
try:
from bs4 import BeautifulSoup
self.logger.info("開始數(shù)據(jù)提取...")
# 獲取頁面內(nèi)容
html_content = await self.page.content()
soup = BeautifulSoup(html_content, 'html.parser')
# 根據(jù)配置提取數(shù)據(jù)
extracted_data = []
if 'table_selector' in extraction_config:
table_data = await self._extract_table_data(soup, extraction_config)
extracted_data.extend(table_data)
if 'element_selectors' in extraction_config:
element_data = await self._extract_elements_data(soup, extraction_config)
extracted_data.extend(element_data)
self.logger.info(f"數(shù)據(jù)提取完成,共提取 {len(extracted_data)} 條記錄")
return extracted_data
except Exception as e:
self.logger.error(f"數(shù)據(jù)提取失敗: {e}")
return []提取策略:
- 支持表格數(shù)據(jù)和元素?cái)?shù)據(jù)提取
- 配置驅(qū)動的提取規(guī)則
- 靈活的數(shù)據(jù)映射機(jī)制
- 容錯處理和空值處理
3.4 數(shù)據(jù)存儲技能 (DataStorageSkill)
class DataStorageSkill(BaseSkill):
"""數(shù)據(jù)存儲技能 - 負(fù)責(zé)數(shù)據(jù)持久化"""
def __init__(self, db_path: str = "weather_data.db"):
super().__init__("data_storage")
self.db_path = db_path
self.connection = None
async def execute(self, data: List[Dict], table_name: str = "weather_data") -> bool:
"""存儲數(shù)據(jù)到數(shù)據(jù)庫"""
import sqlite3
try:
self.logger.info(f"開始存儲 {len(data)} 條數(shù)據(jù)")
# 連接數(shù)據(jù)庫
self.connection = sqlite3.connect(self.db_path)
cursor = self.connection.cursor()
# 創(chuàng)建表(如果不存在)
create_table_sql = f"""
CREATE TABLE IF NOT EXISTS {table_name} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
province_name TEXT,
city_name TEXT,
collection_date TEXT,
temperature TEXT,
weather TEXT,
created_time DATETIME DEFAULT CURRENT_TIMESTAMP
)
"""
cursor.execute(create_table_sql)
# 插入數(shù)據(jù)
insert_sql = f"""
INSERT INTO {table_name} (province_name, city_name, collection_date, temperature, weather)
VALUES (?, ?, ?, ?, ?)
"""
success_count = 0
for record in data:
try:
cursor.execute(insert_sql, (
record.get('province_name', ''),
record.get('city_name', ''),
record.get('date', ''),
record.get('temperature', ''),
record.get('weather', '')
))
success_count += 1
except Exception as e:
self.logger.warning(f"插入數(shù)據(jù)失敗: {e}")
self.connection.commit()
self.logger.info(f"數(shù)據(jù)存儲完成,成功 {success_count}/{len(data)} 條")
return True
except Exception as e:
self.logger.error(f"數(shù)據(jù)存儲失敗: {e}")
if self.connection:
self.connection.rollback()
return False
finally:
if self.connection:
self.connection.close()存儲特性:
- 支持多種數(shù)據(jù)庫后端
- 事務(wù)管理和回滾機(jī)制
- 批量插入性能優(yōu)化
- 數(shù)據(jù)完整性驗(yàn)證
第四部分:高級特性實(shí)現(xiàn)
4.1 技能工廠模式
class AdvancedSkillFeatures:
"""高級技能特性示例"""
@staticmethod
def skill_factory(skill_type: str, **kwargs) -> BaseSkill:
"""技能工廠方法"""
skill_map = {
"browser": BrowserManagerSkill,
"navigation": PageNavigationSkill,
"extraction": DataExtractionSkill,
"storage": DataStorageSkill
}
if skill_type not in skill_map:
raise ValueError(f"未知的技能類型: {skill_type}")
return skill_map[skill_type](**kwargs)工廠模式優(yōu)勢:
- 統(tǒng)一的對象創(chuàng)建接口
- 支持動態(tài)技能類型擴(kuò)展
- 便于依賴注入和配置管理
4.2 配置驅(qū)動架構(gòu)
@staticmethod
def create_skill_pipeline(skills_config: List[Dict]) -> SkillOrchestrator:
"""創(chuàng)建技能管道"""
orchestrator = SkillOrchestrator()
for config in skills_config:
skill = AdvancedSkillFeatures.skill_factory(
config['type'],
**config.get('params', {})
)
orchestrator.register_skill(config['name'], skill)
return orchestrator配置驅(qū)動優(yōu)勢:
- 系統(tǒng)行為可配置化
- 支持熱更新和動態(tài)調(diào)整
- 降低代碼耦合度
4.3 依賴注入機(jī)制
# 注入頁面依賴示例 browser_skill = orchestrator.skills["browser"] browser, context, page = await browser_skill.execute() # 更新需要頁面的技能 orchestrator.skills["navigator"].page = page orchestrator.skills["extractor"].page = page
依賴注入價值:
- 解耦技能間的依賴關(guān)系
- 支持靈活的組件替換
- 便于單元測試和模擬
第五部分:實(shí)際應(yīng)用示例
5.1 基本使用模式
async def main():
"""Skills架構(gòu)使用示例"""
# 創(chuàng)建技能編排器
orchestrator = SkillOrchestrator()
# 創(chuàng)建并注冊技能
browser_skill = BrowserManagerSkill(headless=True)
orchestrator.register_skill("browser_manager", browser_skill)
# 啟動瀏覽器
browser, context, page = await browser_skill.execute()
# 注冊其他需要頁面的技能
navigation_skill = PageNavigationSkill(page)
extraction_skill = DataExtractionSkill(page)
storage_skill = DataStorageSkill()
orchestrator.register_skill("page_navigation", navigation_skill)
orchestrator.register_skill("data_extraction", extraction_skill)
orchestrator.register_skill("data_storage", storage_skill)
# 定義工作流
workflow = [
{
"skill": "page_navigation",
"args": {
"url": "https://example.com/weather",
"timeout": 30000
}
},
{
"skill": "data_extraction",
"args": {
"extraction_config": {
"table_selector": ".weather-table",
"column_mapping": {
"date": 0,
"temperature": 1,
"weather": 2
}
}
}
},
{
"skill": "data_storage",
"args": {
"data": [], # 這里應(yīng)該填充實(shí)際提取的數(shù)據(jù)
"table_name": "weather_records"
}
}
]
# 執(zhí)行工作流
results = await orchestrator.execute_workflow(workflow)
# 清理資源
await browser_skill.cleanup()
return results5.2 配置驅(qū)動示例
# 技能配置
skills_config = [
{
"name": "browser",
"type": "browser",
"params": {"headless": True}
},
{
"name": "navigator",
"type": "navigation",
"params": {}
},
{
"name": "extractor",
"type": "extraction",
"params": {}
},
{
"name": "storage",
"type": "storage",
"params": {"db_path": "config_driven.db"}
}
]
# 創(chuàng)建技能管道
orchestrator = AdvancedSkillFeatures.create_skill_pipeline(skills_config)第六部分:最佳實(shí)踐和優(yōu)化策略
6.1 錯誤處理策略
分級錯誤處理:
# 技能級別錯誤處理
async def execute_with_retry(self, max_retries=3):
for attempt in range(max_retries):
try:
return await self.execute()
except TemporaryError as e:
if attempt == max_retries - 1:
raise
await asyncio.sleep(2 ** attempt)
except PermanentError as e:
self.logger.error(f"永久性錯誤: {e}")
raise編排器級別錯誤處理:
- 單個技能失敗不影響整體流程
- 支持錯誤恢復(fù)和重試機(jī)制
- 詳細(xì)的錯誤日志和監(jiān)控
6.3 監(jiān)控和調(diào)試
日志系統(tǒng):
- 結(jié)構(gòu)化日志記錄
- 性能指標(biāo)收集
- 錯誤追蹤和報告
調(diào)試工具:
- 技能執(zhí)行狀態(tài)監(jiān)控
- 工作流可視化
- 性能分析工具集成
結(jié)論
Python + Skills架構(gòu)通過模塊化、可組合的設(shè)計(jì)理念,為構(gòu)建復(fù)雜系統(tǒng)提供了強(qiáng)大的技術(shù)基礎(chǔ)。這種架構(gòu)模式的核心優(yōu)勢在于:
- 開發(fā)效率:通過技能復(fù)用和組合,大幅提升開發(fā)速度
- 系統(tǒng)維護(hù):模塊化設(shè)計(jì)使得系統(tǒng)維護(hù)和升級更加容易
- 業(yè)務(wù)適應(yīng):靈活的配置機(jī)制支持快速響應(yīng)業(yè)務(wù)變化
- 技術(shù)擴(kuò)展:良好的擴(kuò)展性支持系統(tǒng)持續(xù)演進(jìn)
在實(shí)際應(yīng)用中,Skills架構(gòu)已被證明在數(shù)據(jù)采集、自動化測試、業(yè)務(wù)流程自動化等多個領(lǐng)域具有顯著優(yōu)勢。隨著技術(shù)的不斷發(fā)展,這種架構(gòu)模式將繼續(xù)演進(jìn),為構(gòu)建更加智能、高效的軟件系統(tǒng)提供支持。
本文基于實(shí)際項(xiàng)目經(jīng)驗(yàn)編寫,所有代碼示例均經(jīng)過實(shí)踐驗(yàn)證。讀者可以根據(jù)具體需求調(diào)整實(shí)現(xiàn)細(xì)節(jié),并結(jié)合實(shí)際場景進(jìn)行優(yōu)化和改進(jìn)。
到此這篇關(guān)于Python + Skills 架構(gòu)實(shí)現(xiàn)從理論到實(shí)踐的文章就介紹到這了,更多相關(guān)Python Skills 架構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中用psycopg2模塊操作PostgreSQL方法
python可以操作多種數(shù)據(jù)庫,本篇文章給大家介紹了用psycopg2模塊操作PostgreSQL方法,一起來學(xué)習(xí)下。2017-11-11
Python?調(diào)用GPT-3?API實(shí)現(xiàn)過程詳解
這篇文章主要為大家介紹了Python?調(diào)用GPT-3?API實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Django+Celery實(shí)現(xiàn)動態(tài)配置定時任務(wù)的方法示例
這篇文章主要介紹了Django + Celery 實(shí)現(xiàn)動態(tài)配置定時任務(wù)的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Django對接elasticsearch實(shí)現(xiàn)全文檢索的示例代碼
搜索是很常用的功能,如果是千萬級的數(shù)據(jù)應(yīng)該怎么檢索,本文主要介紹了Django對接elasticsearch實(shí)現(xiàn)全文檢索的示例代碼,感興趣的可以了解一下2021-08-08
python實(shí)現(xiàn)驗(yàn)證碼識別功能
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)驗(yàn)證碼識別功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06

