Python + Skills 架構實現從理論到實踐
第一部分:Skills架構理論基礎
1.1 什么是Skills架構?
Skills架構是一種模塊化設計模式,它將復雜的業(yè)務流程分解為一系列獨立的、可重用的功能單元(稱為"技能")。每個技能專注于完成特定的任務,并通過統(tǒng)一的接口進行交互。
核心特征:
- 單一職責原則:每個技能只負責一個明確的功能
- 高內聚低耦合:技能內部邏輯緊密相關,外部依賴最小化
- 可組合性:技能可以靈活組合形成更復雜的功能
- 可測試性:獨立的技能單元便于單元測試和集成測試
1.2 Skills架構的優(yōu)勢
開發(fā)效率提升:
- 代碼復用性高,減少重復開發(fā)
- 模塊化設計便于團隊協(xié)作
- 快速構建新功能通過技能組合
系統(tǒng)維護性:
- 問題定位和修復更加容易
- 單個技能升級不影響整體系統(tǒng)
- 便于性能優(yōu)化和功能擴展
業(yè)務適應性:
- 快速響應業(yè)務需求變化
- 支持配置驅動開發(fā)
- 易于集成第三方服務
第二部分:核心架構設計
2.1 基礎組件設計
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})"設計要點:
- 抽象基類確保統(tǒng)一的接口規(guī)范
- 內置日志記錄便于調試和監(jiān)控
- 異步執(zhí)行支持高性能并發(fā)處理
2.2 技能編排器 (SkillOrchestrator)
class SkillOrchestrator:
"""技能編排器 - 負責協(xié)調多個技能的執(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í)行
- 錯誤處理和結果收集
- 執(zhí)行狀態(tài)監(jiān)控
第三部分:具體技能實現
3.1 瀏覽器管理技能 (BrowserManagerSkill)
class BrowserManagerSkill(BaseSkill):
"""瀏覽器管理技能 - 負責瀏覽器生命周期管理"""
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í)行瀏覽器設置"""
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}")技術要點:
- 使用Playwright進行瀏覽器自動化
- 支持有頭和無頭模式
- 完善的資源管理和清理
- 異常處理和日志記錄
3.2 頁面導航技能 (PageNavigationSkill)
class PageNavigationSkill(BaseSkill):
"""頁面導航技能 - 負責頁面導航和等待"""
def __init__(self, page):
super().__init__("page_navigation")
self.page = page
async def execute(self, url: str, timeout: int = 30000) -> bool:
"""導航到指定URL"""
try:
self.logger.info(f"導航到: {url}")
# 設置頁面頭信息,避免被識別為爬蟲
await self.page.set_extra_http_headers({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
# 導航到目標頁面
await self.page.goto(url, timeout=timeout)
# 等待頁面加載完成
await self.page.wait_for_load_state('networkidle')
self.logger.info("頁面導航成功")
return True
except Exception as e:
self.logger.error(f"頁面導航失敗: {e}")
return False功能特性:
- 智能頁面導航和等待
- 反爬蟲規(guī)避策略
- 超時控制和錯誤處理
- 網絡狀態(tài)監(jiān)控
3.3 數據提取技能 (DataExtractionSkill)
class DataExtractionSkill(BaseSkill):
"""數據提取技能 - 負責從頁面提取結構化數據"""
def __init__(self, page):
super().__init__("data_extraction")
self.page = page
async def execute(self, extraction_config: Dict) -> List[Dict]:
"""執(zhí)行數據提取"""
try:
from bs4 import BeautifulSoup
self.logger.info("開始數據提取...")
# 獲取頁面內容
html_content = await self.page.content()
soup = BeautifulSoup(html_content, 'html.parser')
# 根據配置提取數據
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"數據提取完成,共提取 {len(extracted_data)} 條記錄")
return extracted_data
except Exception as e:
self.logger.error(f"數據提取失敗: {e}")
return []提取策略:
- 支持表格數據和元素數據提取
- 配置驅動的提取規(guī)則
- 靈活的數據映射機制
- 容錯處理和空值處理
3.4 數據存儲技能 (DataStorageSkill)
class DataStorageSkill(BaseSkill):
"""數據存儲技能 - 負責數據持久化"""
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:
"""存儲數據到數據庫"""
import sqlite3
try:
self.logger.info(f"開始存儲 {len(data)} 條數據")
# 連接數據庫
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)
# 插入數據
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"插入數據失敗: {e}")
self.connection.commit()
self.logger.info(f"數據存儲完成,成功 {success_count}/{len(data)} 條")
return True
except Exception as e:
self.logger.error(f"數據存儲失敗: {e}")
if self.connection:
self.connection.rollback()
return False
finally:
if self.connection:
self.connection.close()存儲特性:
- 支持多種數據庫后端
- 事務管理和回滾機制
- 批量插入性能優(yōu)化
- 數據完整性驗證
第四部分:高級特性實現
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)技能類型擴展
- 便于依賴注入和配置管理
4.2 配置驅動架構
@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配置驅動優(yōu)勢:
- 系統(tǒng)行為可配置化
- 支持熱更新和動態(tài)調整
- 降低代碼耦合度
4.3 依賴注入機制
# 注入頁面依賴示例 browser_skill = orchestrator.skills["browser"] browser, context, page = await browser_skill.execute() # 更新需要頁面的技能 orchestrator.skills["navigator"].page = page orchestrator.skills["extractor"].page = page
依賴注入價值:
- 解耦技能間的依賴關系
- 支持靈活的組件替換
- 便于單元測試和模擬
第五部分:實際應用示例
5.1 基本使用模式
async def main():
"""Skills架構使用示例"""
# 創(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": [], # 這里應該填充實際提取的數據
"table_name": "weather_records"
}
}
]
# 執(zhí)行工作流
results = await orchestrator.execute_workflow(workflow)
# 清理資源
await browser_skill.cleanup()
return results5.2 配置驅動示例
# 技能配置
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)第六部分:最佳實踐和優(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編排器級別錯誤處理:
- 單個技能失敗不影響整體流程
- 支持錯誤恢復和重試機制
- 詳細的錯誤日志和監(jiān)控
6.3 監(jiān)控和調試
日志系統(tǒng):
- 結構化日志記錄
- 性能指標收集
- 錯誤追蹤和報告
調試工具:
- 技能執(zhí)行狀態(tài)監(jiān)控
- 工作流可視化
- 性能分析工具集成
結論
Python + Skills架構通過模塊化、可組合的設計理念,為構建復雜系統(tǒng)提供了強大的技術基礎。這種架構模式的核心優(yōu)勢在于:
- 開發(fā)效率:通過技能復用和組合,大幅提升開發(fā)速度
- 系統(tǒng)維護:模塊化設計使得系統(tǒng)維護和升級更加容易
- 業(yè)務適應:靈活的配置機制支持快速響應業(yè)務變化
- 技術擴展:良好的擴展性支持系統(tǒng)持續(xù)演進
在實際應用中,Skills架構已被證明在數據采集、自動化測試、業(yè)務流程自動化等多個領域具有顯著優(yōu)勢。隨著技術的不斷發(fā)展,這種架構模式將繼續(xù)演進,為構建更加智能、高效的軟件系統(tǒng)提供支持。
本文基于實際項目經驗編寫,所有代碼示例均經過實踐驗證。讀者可以根據具體需求調整實現細節(jié),并結合實際場景進行優(yōu)化和改進。
到此這篇關于Python + Skills 架構實現從理論到實踐的文章就介紹到這了,更多相關Python Skills 架構內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python中用psycopg2模塊操作PostgreSQL方法
python可以操作多種數據庫,本篇文章給大家介紹了用psycopg2模塊操作PostgreSQL方法,一起來學習下。2017-11-11
Django+Celery實現動態(tài)配置定時任務的方法示例
這篇文章主要介紹了Django + Celery 實現動態(tài)配置定時任務的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05
Django對接elasticsearch實現全文檢索的示例代碼
搜索是很常用的功能,如果是千萬級的數據應該怎么檢索,本文主要介紹了Django對接elasticsearch實現全文檢索的示例代碼,感興趣的可以了解一下2021-08-08

