Playwright新手必看:从安装到实战的完整指南(含常见问题解决)
Playwright实战入门从零构建你的首个自动化脚本最近在帮团队搭建自动化测试流程时我重新审视了市面上主流的浏览器自动化工具。Selenium 虽然经典但配置繁琐、执行速度慢的问题在复杂场景下愈发明显Puppeteer 专注于 Chrome生态相对单一。直到深度使用了 Playwright我才发现它真正解决了现代 Web 自动化中的诸多痛点——跨浏览器支持、自动等待、网络拦截、移动端模拟这些特性让开发效率提升了不止一个档次。如果你正在寻找一个既能用于端到端测试又能胜任数据抓取任务的工具Playwright 值得你投入时间学习。这篇文章不会照本宣科地复述官方文档而是结合我近半年的实战经验从环境搭建到脚本调试带你避开新手最容易踩的坑。无论你是测试工程师、爬虫开发者还是需要自动化 Web 交互的全栈工程师都能找到即拿即用的代码片段和思路。1. 环境搭建与核心概念解析在开始写第一行代码之前我们需要理解 Playwright 的设计哲学。它不是一个简单的“浏览器驱动”而是一个浏览器自动化框架。这意味着它直接与浏览器内核通信无需额外的 WebDriver 二进制文件。这种架构带来了两个直接好处执行速度更快稳定性更高。1.1 安装与初始化一步到位的正确姿势很多教程会告诉你直接pip install playwright但这只是开始。我推荐使用虚拟环境来管理依赖避免与系统 Python 环境冲突。# 创建并激活虚拟环境以 macOS/Linux 为例 python -m venv playwright-env source playwright-env/bin/activate # 安装 Playwright Python 包 pip install playwright # 安装浏览器二进制文件关键步骤 playwright install注意playwright install会下载 Chromium、Firefox 和 WebKit 的专用版本。这些不是普通的浏览器而是经过优化、适用于自动化的版本。下载大小约 300-500 MB请确保网络通畅。如果你只需要特定浏览器可以指定安装# 仅安装 Chromium playwright install chromium # 或安装 Chrome/Edge 的稳定频道版本 playwright install chrome playwright install msedge安装完成后验证是否成功python -c import playwright; print(playwright.__version__)1.2 同步 vs 异步 API如何选择Playwright 提供了两套 API同步sync_api和异步async_api。选择哪套取决于你的项目架构和个人偏好。同步 API更符合传统脚本的编写习惯代码直观易读from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page() page.goto(https://example.com) # ... 同步操作 browser.close()异步 API适合高性能场景特别是需要并发控制多个浏览器实例时import asyncio from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: browser await p.chromium.launch() page await browser.new_page() await page.goto(https://example.com) # ... 异步操作 await browser.close() asyncio.run(main())我个人的经验法则是新手或简单脚本从同步 API 开始减少认知负担生产环境或复杂任务使用异步 API充分利用现代 Python 的并发能力已有异步框架的项目自然选择异步 API 保持一致性2. 浏览器启动与页面控制实战启动浏览器看似简单但合理的配置能避免后续很多奇怪的问题。Playwright 的浏览器启动选项非常丰富理解每个参数的作用至关重要。2.1 浏览器启动参数详解下面这个表格整理了最常用的启动参数及其实际影响参数类型默认值作用使用场景headlessboolTrue是否无头模式调试时设为 False生产环境设为 TruechannelstrNone指定浏览器渠道chrome, msedge, chrome-beta 等argsList[str][]传递给浏览器的命令行参数修改窗口大小、禁用功能等slow_moint0操作延迟毫秒调试时观察执行过程devtoolsboolFalse是否打开开发者工具调试 CSS、网络请求时使用timeoutint30000启动超时时间毫秒网络慢时适当增加一个完整的启动示例from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch( headlessFalse, # 显示浏览器窗口 channelchrome, # 使用系统安装的 Chrome args[ --start-maximized, # 启动时最大化 --disable-blink-featuresAutomationControlled, # 隐藏自动化特征 --disable-dev-shm-usage, # Docker 环境中常用 ], slow_mo100, # 每个操作延迟 100ms方便观察 devtoolsTrue, # 打开开发者工具 ) # 创建上下文隔离的浏览器会话 context browser.new_context( viewport{width: 1920, height: 1080}, user_agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ) page context.new_page() page.goto(https://example.com) # 业务逻辑... context.close() browser.close()提示browser.new_context()创建的是一个隔离的会话每个上下文有独立的 cookies、localStorage 和缓存。这在多账号操作或并行测试时非常有用。2.2 页面导航与网络优化页面导航不只是page.goto()那么简单。现代网站大量使用 JavaScript 动态加载内容我们需要智能地等待页面完全就绪。# 基础导航 page.goto(https://example.com) # 带超时设置的导航单位毫秒 page.goto(https://example.com, timeout60000, wait_untilnetworkidle) # wait_until 参数的可选值 # - loadload 事件触发 # - domcontentloadedDOMContentLoaded 事件触发 # - networkidle至少 500ms 没有网络请求 # - commit收到响应时对于需要登录或加载大量资源的网站我们可以通过路由拦截来优化性能import re from playwright.sync_api import sync_playwright def block_unnecessary_resources(route): 拦截不必要的资源请求 resource_type route.request.resource_type # 拦截列表 blocked_types [image, stylesheet, font, media] blocked_domains [analytics.example.com, ads.google.com] request_url route.request.url # 拦截图片和特定域名的请求 if resource_type in blocked_types: route.abort() elif any(domain in request_url for domain in blocked_domains): route.abort() else: route.continue_() with sync_playwright() as p: browser p.chromium.launch(headlessTrue) context browser.new_context() page context.new_page() # 注册路由拦截器 page.route(**/*, block_unnecessary_resources) # 设置超时和重试 try: page.goto(https://data-heavy-site.com, timeout45000, wait_untilnetworkidle) except TimeoutError: print(页面加载超时尝试继续执行...) # 即使超时也可能已经加载了部分内容 # 验证页面是否成功加载 if page.title(): print(f页面标题: {page.title()}) else: print(页面可能未完全加载)这种拦截策略在我的爬虫项目中通常能将页面加载时间从 8-10 秒减少到 2-3 秒。3. 元素定位与交互超越 XPath 的现代方案虽然 XPath 功能强大但 Playwright 提供了更直观、更稳定的定位方式。我建议优先使用这些内置定位器只在复杂场景下使用 XPath。3.1 多种定位策略对比Playwright 支持多种定位策略每种都有其适用场景# 1. 文本定位 - 最直观的方式 page.click(text登录) # 点击包含登录文本的元素 page.click(text精确文本) # 点击文本完全匹配的元素 # 2. CSS 选择器 - 最常用的方式 page.click(button.submit) # class 为 submit 的 button page.fill(input[nameusername], myuser) # name 属性为 username 的 input # 3. 组合选择器 - 更精确的定位 page.click(div.header button.login) # header div 内的 login button # 4. 按角色定位 - ARIA 语义化 page.click(rolebutton[name提交]) # 名称为提交的按钮角色 # 5. XPath - 复杂场景的备选 page.click(xpath//button[idsubmit])实际项目中我通常按这个优先级选择定位器文本定位器用于按钮、链接等有明确文本的元素CSS 选择器大多数情况下的首选组合选择器需要更精确的上下文时角色定位器无障碍友好的网站XPath前四种都无法精确定位时3.2 元素操作的最佳实践定位到元素后如何稳定地操作它们这里有几个我踩过坑后总结的技巧# 等待元素出现再操作推荐 page.wait_for_selector(button.submit, statevisible, timeout10000) page.click(button.submit) # 或者使用更简洁的写法 page.locator(button.submit).click() # 处理动态加载的内容 def wait_for_content(page, selector, max_attempts10): 等待动态内容加载 for attempt in range(max_attempts): try: element page.locator(selector) if element.count() 0: return element except: pass page.wait_for_timeout(1000) # 等待1秒再重试 raise TimeoutError(f元素 {selector} 未在指定时间内出现) # 处理下拉选择 page.select_option(select#country, valueCN) # 通过 value 选择 page.select_option(select#country, label中国) # 通过显示文本选择 # 处理文件上传 page.set_input_files(input[typefile], path/to/file.pdf) # 处理弹窗/对话框 page.on(dialog, lambda dialog: dialog.accept()) # 自动接受弹窗 page.click(button#trigger-dialog) # 触发弹窗的操作 # 获取元素属性和文本的可靠方法 element page.locator(h1.title) if element.is_visible(): title_text element.inner_text() # 获取可见文本 title_html element.inner_html() # 获取 HTML 内容 data_id element.get_attribute(data-id) # 获取自定义属性 # 对于列表元素 items page.locator(ul.items li) item_count items.count() all_texts items.all_inner_texts() # 所有元素的文本列表注意inner_text()和text_content()的区别很重要。inner_text()返回可见文本考虑 CSS 样式text_content()返回所有文本包括隐藏的。大多数情况下应该使用inner_text()。3.3 处理 iframe 和 Shadow DOM现代 Web 应用经常使用 iframe 和 Shadow DOM这些是自动化测试的难点。# 处理 iframe # 方法1直接定位 iframe 内的元素Playwright 自动处理 page.frame_locator(iframe[namecontent]).locator(button.submit).click() # 方法2获取 frame 对象进行操作 frame page.frame(namecontent) # 或使用 url、selector if frame: frame.click(button.submit) # 处理 Shadow DOM # Playwright 可以穿透 Shadow DOM page.locator(custom-element::shadow-dom).locator(inner-element).click() # 实际示例处理复杂的 Web Component def click_in_shadow_dom(page, host_selector, inner_selector): 点击 Shadow DOM 内的元素 # 方法1使用 pierce 选择器 page.click(f{host_selector} {inner_selector}) # 方法2使用 JavaScript 穿透 page.evaluate(f (host, inner) {{ const hostElement document.querySelector(host); if (hostElement hostElement.shadowRoot) {{ const innerElement hostElement.shadowRoot.querySelector(inner); if (innerElement) innerElement.click(); }} }} , host_selector, inner_selector)4. 等待策略与性能优化不合理的等待是自动化脚本不稳定和速度慢的主要原因。Playwright 提供了多种等待机制理解它们的区别很重要。4.1 智能等待 vs 强制等待强制等待尽量避免使用import time time.sleep(5) # 固定等待5秒无论页面状态如何 page.wait_for_timeout(5000) # Playwright 版本的强制等待智能等待推荐使用# 等待元素出现 page.wait_for_selector(.loaded, statevisible, timeout10000) # 等待元素消失 page.wait_for_selector(.loading, statehidden) # 等待特定条件成立 page.wait_for_function( () { return document.readyState complete window.jQuery ! undefined; } ) # 等待网络请求完成 page.wait_for_load_state(networkidle) # 网络空闲 page.wait_for_load_state(domcontentloaded) # DOM 加载完成 # 等待特定响应 with page.expect_response(**/api/data) as response_info: page.click(button#load-data) response response_info.value print(f收到数据: {response.json()})我常用的等待模式组合def safe_click(page, selector, max_wait30000): 安全点击元素包含完整的等待逻辑 try: # 1. 等待元素可交互 page.wait_for_selector(selector, statevisible, timeoutmax_wait) # 2. 确保元素在视口中 element page.locator(selector) element.scroll_into_view_if_needed() # 3. 等待元素可点击非 disabled page.wait_for_function(f (selector) {{ const el document.querySelector(selector); return el !el.disabled el.offsetParent ! null; }} , selector) # 4. 执行点击 element.click() # 5. 等待点击后的状态变化可选 page.wait_for_load_state(networkidle, timeout5000) return True except Exception as e: print(f点击失败 {selector}: {e}) # 可以在这里添加重试逻辑或截图 page.screenshot(pathferror_{selector.replace(/, _)}.png) return False4.2 缓存管理与状态持久化对于需要登录或加载大量资源的应用合理使用缓存可以大幅提升执行速度。import os import json from pathlib import Path from playwright.sync_api import sync_playwright class BrowserManager: def __init__(self, user_data_dir./browser_data): self.user_data_dir Path(user_data_dir) self.user_data_dir.mkdir(exist_okTrue) def get_persistent_context(self, browser_typechromium): 获取持久化上下文保留 cookies 和缓存 with sync_playwright() as p: if browser_type chromium: browser p.chromium elif browser_type firefox: browser p.firefox else: browser p.webkit # 启动持久化上下文 context browser.launch_persistent_context( user_data_dirstr(self.user_data_dir), headlessFalse, viewport{width: 1920, height: 1080}, args[--start-maximized], # 忽略 HTTPS 错误测试环境 ignore_https_errorsTrue, # 接受所有下载 accept_downloadsTrue, # 设置下载路径 downloads_path./downloads, ) return context def save_auth_state(self, context, filenameauth_state.json): 保存认证状态cookies, localStorage storage_state context.storage_state() with open(filename, w) as f: json.dump(storage_state, f) print(f认证状态已保存到 {filename}) def load_auth_state(self, context, filenameauth_state.json): 加载认证状态 if os.path.exists(filename): with open(filename, r) as f: storage_state json.load(f) context.add_cookies(storage_state[cookies]) print(f已从 {filename} 加载认证状态) def clear_cache_keep_auth(self, context): 清除缓存但保留认证信息 # 获取当前认证状态 storage_state context.storage_state() # 创建新上下文清除缓存 browser context.browser context.close() new_context browser.new_context( viewport{width: 1920, height: 1080}, ignore_https_errorsTrue, ) # 恢复认证状态 new_context.add_cookies(storage_state[cookies]) return new_context # 使用示例 manager BrowserManager() context manager.get_persistent_context() page context.new_page() # 首次登录 page.goto(https://example.com/login) page.fill(input[nameusername], your_username) page.fill(input[namepassword], your_password) page.click(button[typesubmit]) # 保存登录状态 manager.save_auth_state(context) # 后续使用 - 直接加载状态无需重新登录 new_context manager.get_persistent_context() manager.load_auth_state(new_context) page2 new_context.new_page() page2.goto(https://example.com/dashboard) # 已保持登录状态4.3 性能监控与优化了解脚本的性能瓶颈有助于优化执行速度from playwright.sync_api import sync_playwright import time class PerformanceMonitor: def __init__(self): self.metrics {} def start_timing(self, name): self.metrics[name] {start: time.time()} def end_timing(self, name): if name in self.metrics: self.metrics[name][end] time.time() self.metrics[name][duration] ( self.metrics[name][end] - self.metrics[name][start] ) def print_report(self): print(\n 性能报告 ) for name, data in self.metrics.items(): if duration in data: print(f{name}: {data[duration]:.2f}秒) total sum(d[duration] for d in self.metrics.values() if duration in d) print(f总耗时: {total:.2f}秒) # 使用性能监控 monitor PerformanceMonitor() with sync_playwright() as p: monitor.start_timing(total) monitor.start_timing(browser_launch) browser p.chromium.launch(headlessTrue) monitor.end_timing(browser_launch) monitor.start_timing(page_navigation) page browser.new_page() # 启用性能监控 page.route(**/*, lambda route: route.continue_()) page.goto(https://example.com, wait_untilnetworkidle) monitor.end_timing(page_navigation) # 执行一些操作 monitor.start_timing(interactions) page.click(textLearn More) page.wait_for_load_state(networkidle) monitor.end_timing(interactions) monitor.end_timing(total) # 获取浏览器性能指标 performance_timing page.evaluate(() { return JSON.stringify(window.performance.timing); }) print(浏览器性能数据:, performance_timing) browser.close() monitor.print_report()5. 调试技巧与常见问题解决即使有了完善的脚本调试仍然是不可避免的环节。Playwright 提供了强大的调试工具但知道如何有效使用它们才是关键。5.1 调试模式与工具使用 Playwright Inspector# 方式1设置环境变量 PWDEBUG1 python your_script.py # 方式2在代码中启用 import os os.environ[PWDEBUG] 1 # 方式3使用 slow_mo 和 headlessFalse 观察执行 browser p.chromium.launch(headlessFalse, slow_mo500)代码中插入调试点# 1. 暂停执行打开调试器 page.pause() # 执行到这里会暂停打开 Playwright Inspector # 2. 控制台输出 page.on(console, lambda msg: print(fConsole: {msg.text})) page.on(pageerror, lambda err: print(fPage error: {err})) page.on(request, lambda req: print(fRequest: {req.url})) page.on(response, lambda res: print(fResponse: {res.status} {res.url})) # 3. 截图和录屏 page.screenshot(pathdebug.png, full_pageTrue) # 全屏截图 page.screenshot(pathelement.png, clip{x: 100, y: 100, width: 200, height: 200}) # 区域截图 # 录屏需要配置 context browser.new_context( record_video_dir./videos/, record_video_size{width: 1920, height: 1080} ) # 4. 执行 JavaScript 调试 page.evaluate(() { debugger; # 在浏览器开发者工具中触发断点 console.log(当前URL:, window.location.href); console.log(用户代理:, navigator.userAgent); })5.2 常见问题与解决方案下面这个表格整理了我遇到的一些典型问题及其解决方法问题现象可能原因解决方案TimeoutError: Timeout 30000ms exceeded网络慢、元素未出现、页面卡死1. 增加超时时间2. 检查选择器是否正确3. 添加更具体的等待条件Element is not attached to the DOM元素被动态移除1. 使用page.wait_for_selector重新等待2. 使用更稳定的选择器3. 捕获异常并重试Target closed浏览器或页面被意外关闭1. 检查关闭逻辑2. 使用 try-except 包装操作3. 确保操作在页面生命周期内无法输入中文输入法问题1. 使用page.type()而非page.fill()2. 设置合适的输入法上下文被网站检测为机器人浏览器指纹被识别1. 使用channelchrome2. 添加--disable-blink-featuresAutomationControlled3. 设置合理的 user-agent内存泄漏页面或上下文未正确关闭1. 使用with语句确保资源释放2. 定期重启浏览器3. 监控内存使用重试机制的实现import time from functools import wraps from playwright.sync_api import TimeoutError def retry_on_failure(max_retries3, delay1): 失败重试装饰器 def decorator(func): wraps(func) def wrapper(*args, **kwargs): last_exception None for attempt in range(max_retries): try: return func(*args, **kwargs) except Exception as e: last_exception e print(f尝试 {attempt 1}/{max_retries} 失败: {e}) if attempt max_retries - 1: time.sleep(delay * (attempt 1)) # 指数退避 raise last_exception return wrapper return decorator class RobustPage: def __init__(self, page): self.page page retry_on_failure(max_retries3) def reliable_click(self, selector, timeout30000): 可靠的点击方法包含重试逻辑 try: # 等待元素可交互 self.page.wait_for_selector( selector, statevisible, timeouttimeout ) # 滚动到视图中 element self.page.locator(selector) element.scroll_into_view_if_needed() # 点击 element.click() # 等待点击后的状态 self.page.wait_for_load_state(networkidle, timeout5000) except TimeoutError: # 尝试备用选择器 alt_selectors [ selector, ftext{selector}, fbutton:has-text({selector}), f[class*{selector}], ] for alt_selector in alt_selectors: try: self.page.click(alt_selector, timeout5000) return except: continue raise retry_on_failure(max_retries2) def reliable_fill(self, selector, text, timeout15000): 可靠的填充表单方法 self.page.wait_for_selector(selector, statevisible, timeouttimeout) # 先清空再输入 self.page.fill(selector, ) self.page.type(selector, text, delay100) # 模拟人工输入 # 验证输入内容 actual_value self.page.input_value(selector) if actual_value ! text: raise ValueError(f输入验证失败: 期望 {text}, 实际 {actual_value})5.3 日志与错误处理完善的日志系统能帮助快速定位问题import logging from datetime import datetime from pathlib import Path def setup_logging(): 配置日志系统 log_dir Path(./logs) log_dir.mkdir(exist_okTrue) timestamp datetime.now().strftime(%Y%m%d_%H%M%S) log_file log_dir / fplaywright_{timestamp}.log logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(log_file), logging.StreamHandler() ] ) return logging.getLogger(__name__) class AutomatedBrowser: def __init__(self): self.logger setup_logging() self.screenshot_dir Path(./screenshots) self.screenshot_dir.mkdir(exist_okTrue) def take_screenshot(self, page, name): 截图并记录日志 timestamp datetime.now().strftime(%H%M%S) filename f{name}_{timestamp}.png path self.screenshot_dir / filename page.screenshot(pathstr(path), full_pageTrue) self.logger.info(f截图已保存: {path}) return path def run_with_error_handling(self, page, operation, *args, **kwargs): 带错误处理的操作执行 operation_name operation.__name__ if hasattr(operation, __name__) else str(operation) try: self.logger.info(f开始执行: {operation_name}) result operation(page, *args, **kwargs) self.logger.info(f完成执行: {operation_name}) return result except Exception as e: self.logger.error(f操作失败 {operation_name}: {e}) # 错误时截图 error_screenshot self.take_screenshot(page, ferror_{operation_name}) self.logger.info(f错误截图: {error_screenshot}) # 记录页面状态 try: page_url page.url page_title page.title() self.logger.info(f页面状态 - URL: {page_url}, 标题: {page_title}) except: self.logger.warning(无法获取页面状态) raise def execute_workflow(self): 执行完整的工作流 from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) context browser.new_context() page context.new_page() try: # 示例工作流 self.run_with_error_handling( page, lambda p: p.goto(https://example.com), 访问首页 ) self.run_with_error_handling( page, lambda p: p.fill(input[namesearch], Playwright), 搜索输入 ) self.run_with_error_handling( page, lambda p: p.click(button[typesubmit]), 提交搜索 ) # 验证结果 search_results page.locator(.result-item) count search_results.count() self.logger.info(f找到 {count} 个搜索结果) if count 0: self.take_screenshot(page, no_results) raise ValueError(未找到搜索结果) finally: # 清理资源 context.close() browser.close() self.logger.info(浏览器已关闭)在实际项目中我发现最耗时的往往不是编写主要逻辑而是处理各种边界情况和异常。建立完善的错误处理、日志记录和重试机制能让脚本在无人值守时也能稳定运行。Playwright 的 API 设计考虑了很多实际使用场景但真正发挥其威力需要结合具体的业务需求进行调整和优化。记得第一次用 Playwright 完成一个复杂的多步骤表单自动化时那种“一次编写长期运行”的成就感至今难忘。工具本身在不断进化但解决问题的思路是相通的——理解原理、善用工具、耐心调试。

相关新闻

LaTeX小白必看:5分钟搞定数学论文排版(附模板下载)

LaTeX小白必看:5分钟搞定数学论文排版(附模板下载)

LaTeX数学论文排版:从格式焦虑到五分钟成稿的实战指南 如果你正在为数学论文的排版而头疼,对着Word里那些永远对不齐的公式编号、混乱的交叉引用和难以统一的格式感到绝望,那么这篇文章就是为你准备的。我完全理解那种感觉——明明内容已经打…

2026/5/17 10:33:25 阅读更多 →
PyTorch模型微调实战:如何用预训练模型提升小数据集准确率(附代码示例)

PyTorch模型微调实战:如何用预训练模型提升小数据集准确率(附代码示例)

PyTorch模型微调实战:如何用预训练模型提升小数据集准确率(附代码示例) 手里只有几千张图片,却想训练一个靠谱的图像分类模型?这听起来像是让一个新手厨师用几样食材去复刻国宴大菜,难度不小。直接从头训练…

2026/7/3 20:12:15 阅读更多 →
通义千问2.5-7B监控告警:异常请求检测部署教程

通义千问2.5-7B监控告警:异常请求检测部署教程

通义千问2.5-7B监控告警:异常请求检测部署教程 你是不是遇到过这种情况:部署了一个大模型服务,运行得好好的,突然有一天响应变慢了,或者开始返回一些莫名其妙的错误?更头疼的是,你根本不知道问…

2026/7/4 7:42:23 阅读更多 →

最新新闻

Umi-OCR终极指南:免费离线文字识别软件的完整配置与优化教程

Umi-OCR终极指南:免费离线文字识别软件的完整配置与优化教程

Umi-OCR终极指南:免费离线文字识别软件的完整配置与优化教程 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。内置多…

2026/7/4 22:12:22 阅读更多 →
postcss-write-svg:革命性CSS SVG编写工具,让图形开发效率提升10倍!

postcss-write-svg:革命性CSS SVG编写工具,让图形开发效率提升10倍!

postcss-write-svg:革命性CSS SVG编写工具,让图形开发效率提升10倍! 【免费下载链接】postcss-write-svg Write SVGs directly in CSS 项目地址: https://gitcode.com/gh_mirrors/po/postcss-write-svg 你是否厌倦了在CSS和SVG文件之间…

2026/7/4 22:12:21 阅读更多 →
3大架构优化策略:如何构建高可用AI网关服务

3大架构优化策略:如何构建高可用AI网关服务

3大架构优化策略:如何构建高可用AI网关服务 【免费下载链接】new-api A unified AI model hub for aggregation & distribution. It supports cross-converting various LLMs into OpenAI-compatible, Claude-compatible, or Gemini-compatible formats. A cent…

2026/7/4 22:12:21 阅读更多 →
Agent Skills技能发现机制:如何让AI助手智能匹配任务与技能

Agent Skills技能发现机制:如何让AI助手智能匹配任务与技能

Agent Skills技能发现机制:如何让AI助手智能匹配任务与技能 【免费下载链接】agentskills Specification and documentation for Agent Skills 项目地址: https://gitcode.com/GitHub_Trending/ag/agentskills Agent Skills是GitHub推荐项目精选(…

2026/7/4 22:10:20 阅读更多 →
RestFB实战教程:10个常见Facebook API操作示例

RestFB实战教程:10个常见Facebook API操作示例

RestFB实战教程:10个常见Facebook API操作示例 【免费下载链接】restfb RestFB is a simple and flexible Facebook Graph API client written in Java. 项目地址: https://gitcode.com/gh_mirrors/re/restfb 想要在Java应用中快速集成Facebook功能&#xff…

2026/7/4 22:10:20 阅读更多 →
如何搭建Leela Chess Zero环境?5分钟快速启动你的AI象棋之旅

如何搭建Leela Chess Zero环境?5分钟快速启动你的AI象棋之旅

如何搭建Leela Chess Zero环境?5分钟快速启动你的AI象棋之旅 【免费下载链接】leela-chess **MOVED TO https://github.com/LeelaChessZero/leela-chess ** A chess adaption of GCPs Leela Zero 项目地址: https://gitcode.com/gh_mirrors/le/leela-chess L…

2026/7/4 22:08:18 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻