# pydoll **Repository Path**: noobyang/pydoll ## Basic Information - **Project Name**: pydoll - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-21 - **Last Updated**: 2025-10-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Pydoll Logo

Pydoll: Automate the Web, Naturally

Tests Ruff CI MyPy CI Python >= 3.10 Ask DeepWiki

📖 文档 • 🚀 快速上手 • ⚡ 高级特性 • 🤝 贡献 • 💖 赞助我

- [English](README.md) 设想以下场景:你需要实现浏览器任务的自动化操作——无论是测试Web应用程序、从网站采集数据,还是批量处理重复性流程。传统方法往往需要配置外部驱动程序、进行复杂的系统设置,还可能面临诸多兼容性问题。 **Pydoll的诞生就是解决这些问题!!!** Pydoll 采用全新设计理念,从零构建,直接对接 Chrome DevTools Protocol(CDP),无需依赖外部驱动。 这种精简的实现方式,结合高度拟真的点击、导航及元素交互机制,使其行为与真实用户几乎毫无区别。 我们坚信,真正强大的自动化工具,不应让用户困于繁琐的配置学习,也不该让用户疲于应对反爬系统的风控。使用Pydoll,你只需专注核心业务逻辑——让自动化回归本质,而非纠缠于底层技术细节或防护机制。

做一个好人,给我们一个星星 ⭐

没有星星,就没有Bug修复。开玩笑的(也许)
## 🌟 Pydoll 的核心优势 - **零 WebDriver 依赖**:彻底告别驱动兼容性烦恼 - **类人交互引擎**:能够通过行为验证码如 reCAPTCHA v3 或 Turnstile,取决于 IP 声誉和交互模式 - **异步高性能**:支持高速自动化与多任务并行处理 - **拟真交互体验**:完美复刻真实用户行为模式 - **极简部署**:安装即用,开箱即自动化 ## 最新功能 ### 通过 WebSocket 进行远程连接 —— 随时随地控制浏览器! 现在你可以使用浏览器的 WebSocket 地址直接连接到已运行的实例,并立即使用完整的 Pydoll API: ```python from pydoll.browser.chromium import Chrome chrome = Chrome() tab = await chrome.connect('ws://YOUR_HOST:9222/devtools/browser/XXXX') # 直接开干:导航、元素自动化、请求、事件… await tab.go_to('https://example.com') title = await tab.execute_script('return document.title') print(title) ``` 这让你可以轻松对接远程/CI 浏览器、容器或共享调试目标——无需本地启动,只需指向 WS 端点即可自动化。 ### 像专业人士一样漫游 DOM:get_children_elements() 与 get_siblings_elements() 两个让复杂布局遍历更优雅的小助手: ```python # 获取容器的直接子元素 container = await tab.find(id='cards') cards = await container.get_children_elements(max_depth=1) # 想更深入?这将返回子元素的子元素(以此类推) elements = await container.get_children_elements(max_depth=2) # 在横向列表中无痛遍历兄弟元素 active = await tab.find(class_name='item--active') siblings = await active.get_siblings_elements() print(len(cards), len(siblings)) ``` 用更少样板代码表达更多意图,特别适合动态网格、列表与菜单的场景,让抓取/自动化逻辑更清晰、更可读。 ### WebElement:状态等待与新的公共 API - 新增 `wait_until(...)` 用于等待元素状态,使用更简单: ```python # 等待元素变为可见,直到超时 await element.wait_until(is_visible=True, timeout=5) # 等待元素变为可交互(可见、位于顶层并可接收事件) await element.wait_until(is_interactable=True, timeout=10) ``` - 以下 `WebElement` 方法现已公开: - `is_visible()` - 判断元素是否具有可见区域、未被 CSS 隐藏,并在需要时滚动进入视口。适用于交互前的快速校验。 - `is_interactable()` - “可点击”状态:综合可见性、启用状态与指针事件命中等条件,适合构建更稳健的交互流程。 - `is_on_top()` - 检查元素在点击位置是否为顶部命中目标,避免被覆盖导致点击失效。 - `execute_script(script: str, return_by_value: bool = False)` - 在元素上下文中执行 JavaScript(this 指向该元素),便于细粒度调整与快速检查。 ```python # 使用 JS 高亮元素 await element.execute_script("this.style.outline='2px solid #22d3ee'") # 校验状态 visible = await element.is_visible() interactable = await element.is_interactable() on_top = await element.is_on_top() ``` 以上新增能力能显著简化“等待+验证”场景,降低自动化过程中的不稳定性,使用例更可预测。 ### 浏览器上下文 HTTP 请求 - 混合自动化的游戏规则改变者! 你是否曾经希望能够发出自动继承浏览器所有会话状态的 HTTP 请求?**现在你可以了!**
`tab.request` 属性为你提供了一个美观的 `requests` 风格接口,可在浏览器的 JavaScript 上下文中直接执行 HTTP 调用。这意味着每个请求都会自动获得 cookies、身份验证标头、CORS 策略和会话状态,就像浏览器本身发出请求一样。 **混合自动化的完美选择:** ```python # 使用 PyDoll 正常导航到网站并登录 await tab.go_to('https://example.com/login') await (await tab.find(id='username')).type_text('user@example.com') await (await tab.find(id='password')).type_text('password') await (await tab.find(id='login-btn')).click() # 现在发出继承已登录会话的 API 调用! response = await tab.request.get('https://example.com/api/user/profile') user_data = response.json() # 在保持身份验证的同时 POST 数据 response = await tab.request.post( 'https://example.com/api/settings', json={'theme': 'dark', 'notifications': True} ) # 以不同格式访问响应内容 raw_data = response.content text_data = response.text json_data = response.json() # 检查设置的 cookies for cookie in response.cookies: print(f"Cookie: {cookie['name']} = {cookie['value']}") # 向你的请求添加自定义标头 headers = [ {'name': 'X-Custom-Header', 'value': 'my-value'}, {'name': 'X-API-Version', 'value': '2.0'} ] await tab.request.get('https://api.example.com/data', headers=headers) ``` **为什么这很棒:** - **无需会话切换** - 请求自动继承浏览器 cookies - **CORS 无缝工作** - 请求遵循浏览器安全策略 - **现代 SPA 的完美选择** - 无缝混合 UI 自动化与 API 调用 - **身份验证变得简单** - 通过 UI 登录一次,然后调用 API - **混合工作流** - 为每个步骤使用最佳工具(UI 或 API) 这为需要浏览器交互和 API 效率的自动化场景开启了令人难以置信的可能性! ### 使用自定义首选项完全控制浏览器!(感谢 [@LucasAlvws](https://github.com/LucasAlvws)) 想要完全自定义 Chrome 的行为?**现在你可以控制一切!**
新的 `browser_preferences` 系统让你可以访问数百个之前无法通过编程方式更改的内部 Chrome 设置。我们说的是远超命令行标志的深度浏览器自定义! **可能性是无限的:** ```python options = ChromiumOptions() # 创建完美的自动化环境 options.browser_preferences = { 'download': { 'default_directory': '/tmp/downloads', 'prompt_for_download': False, 'directory_upgrade': True, 'extensions_to_open': '' # 不自动打开任何下载 }, 'profile': { 'default_content_setting_values': { 'notifications': 2, # 阻止所有通知 'geolocation': 2, # 阻止位置请求 'media_stream_camera': 2, # 阻止摄像头访问 'media_stream_mic': 2, # 阻止麦克风访问 'popups': 1 # 允许弹窗(对自动化有用) }, 'password_manager_enabled': False, # 禁用密码提示 'exit_type': 'Normal' # 始终正常退出 }, 'intl': { 'accept_languages': 'zh-CN,zh,en-US,en', 'charset_default': 'UTF-8' }, 'browser': { 'check_default_browser': False, # 不询问默认浏览器 'show_update_promotion_infobar': False } } # 或使用便捷的辅助方法 options.set_default_download_directory('/tmp/downloads') options.set_accept_languages('zh-CN,zh,en-US,en') options.prompt_for_download = False ``` **实际应用的强大示例:** - **静默下载** - 无提示、无对话框,只有自动化下载 - **阻止所有干扰** - 通知、弹窗、摄像头请求,应有尽有 - **CI/CD 的完美选择** - 禁用更新检查、默认浏览器提示、崩溃报告 - **多区域测试** - 即时更改语言、时区和区域设置 - **安全加固** - 锁定权限并禁用不必要的功能 - **高级指纹控制** - 修改浏览器安装日期、参与历史和行为模式 **用于隐蔽自动化的指纹自定义:** ```python import time # 模拟一个已经存在几个月的浏览器 fake_engagement_time = int(time.time()) - (7 * 24 * 60 * 60) # 7天前 options.browser_preferences = { 'settings': { 'touchpad': { 'natural_scroll': True, } }, 'profile': { 'last_engagement_time': fake_engagement_time, 'exit_type': 'Normal', 'exited_cleanly': True }, 'newtab_page_location_override': 'https://www.google.com', 'session': { 'restore_on_startup': 1, # 恢复上次会话 'startup_urls': ['https://www.google.com'] } } ``` 这种控制级别以前只有 Chrome 扩展开发者才能使用 - 现在它在你的自动化工具包中! 查看[文档](https://pydoll.tech/docs/zh/features/#custom-browser-preferences/)了解更多详情。 ### 新的 `get_parent_element()` 方法 检索任何 WebElement 的父元素,使导航 DOM 结构更加容易: ```python element = await tab.find(id='button') parent = await element.get_parent_element() ``` ### 新的 start_timeout 选项 (感谢 [@j0j1j2](https://github.com/j0j1j2)) 添加到 ChromiumOptions 来控制浏览器启动可以花费多长时间。在较慢的机器或 CI 环境中很有用。 ```python options = ChromiumOptions() options.start_timeout = 20 # 等待 20 秒 ``` ### 新的 expect_download() 上下文管理器 —— 稳健、优雅的文件下载! 还在为不稳定的下载流程、丢失的文件或混乱的事件监听而头疼吗?`tab.expect_download()` 来了:一种可靠、简洁的下载方式。 - 自动配置浏览器下载行为 - 支持自定义下载目录或临时目录(自动清理!) - 内置超时等待,防止任务卡住 - 提供便捷句柄:读取字节/BASE64,获取 `file_path` 一个“开箱即用”的小示例: ```python import asyncio from pathlib import Path from pydoll.browser import Chrome async def download_report(): async with Chrome() as browser: tab = await browser.start() await tab.go_to('https://example.com/reports') target_dir = Path('/tmp/my-downloads') async with tab.expect_download(keep_file_at=target_dir, timeout=10) as dl: # 触发页面上的下载(按钮/链接等) await (await tab.find(text='Download latest report')).click() # 等待完成并读取内容 data = await dl.read_bytes() print(f"已下载 {len(data)} 字节,保存至: {dl.file_path}") asyncio.run(download_report()) ``` 想要“零成本清理”?不传 `keep_file_at` 即可——我们会创建临时目录,并在上下文退出后自动清理。对测试场景非常友好。 ## 📦 安装 ```bash pip install pydoll-python ``` 就这么简单!安装即用,马上开始自动化 ## 🚀 快速上手 ### 你的第一个自动化任务 让我们从一个实际例子开始:一个自动执行谷歌搜索并点击第一个结果的自动化流程。通过这个示例,你可以了解该库的工作原理,以及如何开始将日常任务自动化。 ```python import asyncio from pydoll.browser import Chrome from pydoll.constants import Key async def google_search(query: str): async with Chrome() as browser: tab = await browser.start() await tab.go_to('https://www.google.com') search_box = await tab.find(tag_name='textarea', name='q') await search_box.insert_text(query) await search_box.press_keyboard_key(Key.ENTER) await (await tab.find( tag_name='h3', text='autoscrape-labs/pydoll', timeout=10, )).click() await tab.find(id='repository-container-header', timeout=10) asyncio.run(google_search('pydoll python')) ``` 无需任何配置,只需一个简单脚本,我们就能完成一次完整的谷歌搜索! 好了,现在让我们看看如何从网页中提取数据,依然沿用之前的示例。 假设在以下代码中,我们已经进入了 Pydoll 项目页面。我们需要提取以下信息: - 项目描述 - 星标数量 - Fork 数量 - Issue 数量 - Pull Request 数量 如果想要获取项目描述,我们将使用 XPath 查询。你可以查阅相关文档,学习如何构建自己的查询语句。 ```python description = await (await tab.query( '//h2[contains(text(), "About")]/following-sibling::p', timeout=10, )).text ``` 下面让我们来理解这条查询语句的作用: 1. `//h2[contains(text(), "About")]` - 选择第一个包含"About"的 `

` 标签 2. `/following-sibling::p` - 选择第一个在`

` 标签之后的`

`标签 然后你可以获取到剩下的数据: ```python number_of_stars = await (await tab.find( id='repo-stars-counter-star' )).text number_of_forks = await (await tab.find( id='repo-network-counter' )).text number_of_issues = await (await tab.find( id='issues-repo-tab-count', )).text number_of_pull_requests = await (await tab.find( id='pull-requests-repo-tab-count', )).text data = { 'description': description, 'number_of_stars': number_of_stars, 'number_of_forks': number_of_forks, 'number_of_issues': number_of_issues, 'number_of_pull_requests': number_of_pull_requests, } print(data) ``` 下图展示了本次自动化任务的执行速度与结果。 (为演示需要,浏览器界面未显示。) ![google_seach](./docs/images/google-search-example.gif) 短短5秒内,我们就成功提取了所需数据! 这就是使用Pydoll进行自动化所能达到的速度。 ### 更多复杂的例子 接下来我们来看一个你可能经常遇到的场景:类似Cloudflare的验证码防护。 Pydoll提供了相应的处理方法,但需要说明的是,正如前文所述,其有效性会受到多种因素影响。 下面的代码展示了一个完整的Cloudflare验证码处理示例。 ```python import asyncio from pydoll.browser import Chrome from pydoll.constants import By async def cloudflare_example(): async with Chrome() as browser: tab = await browser.start() async with tab.expect_and_bypass_cloudflare_captcha(): await tab.go_to('https://2captcha.com/demo/cloudflare-turnstile') print('Captcha handled, continuing...') await asyncio.sleep(5) # just to see the result :) asyncio.run(cloudflare_example()) ``` 执行结果如下: ![cloudflare_example](./docs/images/cloudflare-example.gif) 仅需数行代码,我们就成功攻克了最棘手的验证码防护之一。 而这仅仅是Pydoll所提供的众多强大功能之一。但这还远不是全部! ### 自定义配置 有时我们需要对浏览器进行更精细的控制。Pydoll提供了灵活的配置方式来实现这一点。下面我们来看具体示例: ```python from pydoll.browser import Chrome from pydoll.browser.options import ChromiumOptions as Options async def custom_automation(): # Configure browser options options = Options() options.add_argument('--proxy-server=username:password@ip:port') options.add_argument('--window-size=1920,1080') options.binary_location = '/path/to/your/browser' options.start_timeout = 20 async with Chrome(options=options) as browser: tab = await browser.start() # Your automation code here await tab.go_to('https://example.com') # The browser is now using your custom settings asyncio.run(custom_automation()) ``` 本示例中,我们配置浏览器使用代理服务器,并设置窗口分辨率为1920x1080。此外,还指定了Chrome二进制文件的自定义路径——适用于您的安装位置与常规默认路径不同的情况。 ## ⚡ 高级功能 Pydoll提供了一系列高级特性满足高端玩家的需求。 ### 高级元素定位 我们提供多种页面元素定位方式。无论您偏好那种方法,都能找到适合您的解决方案: ```python import asyncio from pydoll.browser import Chrome async def element_finding_examples(): async with Chrome() as browser: tab = await browser.start() await tab.go_to('https://example.com') # Find by attributes (most intuitive) submit_btn = await tab.find( tag_name='button', class_name='btn-primary', text='Submit' ) # Find by ID username_field = await tab.find(id='username') # Find multiple elements all_links = await tab.find(tag_name='a', find_all=True) # CSS selectors and XPath nav_menu = await tab.query('nav.main-menu') specific_item = await tab.query('//div[@data-testid="item-123"]') # With timeout and error handling delayed_element = await tab.find( class_name='dynamic-content', timeout=10, raise_exc=False # Returns None if not found ) # Advanced: Custom attributes custom_element = await tab.find( data_testid='submit-button', aria_label='Submit form' ) asyncio.run(element_finding_examples()) ``` find 方法更为友好。我们可以通过常见属性(如 id、tag_name、class_name 等)进行元素查找,甚至支持自定义属性(例如 data-testid)。 如果这些基础方式仍不能满足需求,还可使用 query 方法,通过 CSS 选择器、XPath 查询语句等多种方式进行元素定位。Pydoll 会自动识别当前使用的查询类型。 ### 并发自动化 Pydoll 的一大优势在于其基于异步实现的多任务并行处理能力。我们可以同时自动化操作多个浏览器标签页!下面来看具体示例: ```python import asyncio from pydoll.browser import Chrome async def scrape_page(url, tab): await tab.go_to(url) title = await tab.execute_script('return document.title') links = await tab.find(tag_name='a', find_all=True) return { 'url': url, 'title': title, 'link_count': len(links) } async def concurrent_scraping(): browser = Chrome() tab_google = await browser.start() tab_duckduckgo = await browser.new_tab() tasks = [ scrape_page('https://google.com/', tab_google), scrape_page('https://duckduckgo.com/', tab_duckduckgo) ] results = await asyncio.gather(*tasks) print(results) await browser.stop() asyncio.run(concurrent_scraping()) ``` 下方展示令人惊叹的执行速度: ![concurrent_example](./docs/images/concurrent-example.gif) 这个例子,我们成功实现了同时对两个页面的数据提取. 还有更多强大功能!响应式自动化的事件系统、请求拦截与修改等等。赶快查阅文档! ## 🔧 快速问题排查 **找不到浏览器?** ```python from pydoll.browser import Chrome from pydoll.browser.options import ChromiumOptions options = ChromiumOptions() options.binary_location = '/path/to/your/chrome' browser = Chrome(options=options) ``` **浏览器在 FailedToStartBrowser 错误后启动?** ```python from pydoll.browser import Chrome from pydoll.browser.options import ChromiumOptions options = ChromiumOptions() options.start_timeout = 20 # 默认是 10 秒 browser = Chrome(options=options) ``` **需要代理?** ```python options.add_argument('--proxy-server=your-proxy:port') ``` **在 Docker 中运行?** ```python options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') ``` ## 📚 文档 Pydoll 的完整文档、详细示例以及对所有功能的深入探讨可以通过以下链接访问: [官方文档](https://autoscrape-labs.github.io/pydoll/). 文档包含以下部分: - **快速上手指南** - 分步教程 - **API 参考** - 完整的方法文档 - **高级技巧** - 网络拦截、事件处理、性能优化 >此 README 的中文版本在[这里](README_zh.md)。 ## 🤝 贡献 我们很乐意看到您的帮助让 Pydoll 变得更好!查看我们的[贡献指南](CONTRIBUTING.md)开始贡献。无论是修复错误、添加功能还是改进文档 - 所有贡献都受欢迎! 请确保: - 为新功能或错误修复编写测试 - 遵循代码风格和约定 - 对拉取请求使用约定式提交 - 在提交前运行 lint 检查和测试 ## 💖 支持我的工作 如果您发现 Pydoll 有用,请考虑[在 GitHub 上支持我](https://github.com/sponsors/thalissonvs)。 您将获得独家优惠,如优先支持、自定义功能等等! 现在无法赞助?没问题,您仍然可以通过以下方式提供很大帮助: - 为仓库加星 - 在社交媒体上分享 - 撰写文章或教程 - 提供反馈或报告问题 每一点支持都很重要/ ## 💬 传播消息 如果 Pydoll 为您节省了时间、心理健康或者拯救了一个键盘免于被砸,请给它一个 ⭐,分享它,或者告诉您奇怪的开发者朋友。 ## 📄 许可证 Pydoll 在 [MIT 许可证](LICENSE) 下获得许可。

Pydoll — 让浏览器自动化变得神奇!