Pydoll 是一个创新的 Python 库,正在重新定义 Chromium 浏览器自动化!与其他解决方案不同,Pydoll 完全消除了对 WebDriver 的依赖,提供了更流畅、更可靠的自动化体验。

⭐ 卓越功能

  • 无需 WebDriver! 告别 WebDriver 兼容性问题和繁琐的配置
  • 原生验证码绕过! 可自然通过 Cloudflare Turnstile 和 reCAPTCHA v3 *
  • 高性能,得益于原生异步编程
  • 真实交互,模拟人类行为
  • 高级事件系统,支持复杂和响应式自动化

注意:对于 Cloudflare 验证码,您需要手动点击复选框。只需找到包含 iframe 的 div 并使用 .click() 方法。自动检测和点击功能即将推出!

目录

🔥 安装

  1. pip install pydoll-python

⚡ 快速开始

看看 Pydoll 有多简单——无需 WebDriver 配置!

  1. import asyncio
  2. from pydoll.browser.chrome import Chrome
  3. from pydoll.constants import By
  4. async def main():
  5. # 无需额外 WebDriver 配置即可启动浏览器!
  6. async with Chrome() as browser:
  7. await browser.start()
  8. page = await browser.get_page()
  9. # 轻松访问受 Cloudflare 保护的网站
  10. await page.go_to('https://example-with-cloudflare.com')
  11. button = await page.find_element(By.CSS_SELECTOR, 'button')
  12. await button.click()
  13. asyncio.run(main())

如果您需要自定义浏览器配置,可以这样做:

  1. from pydoll.browser.chrome import Chrome
  2. from pydoll.browser.options import Options
  3. options = Options()
  4. # 选择使用公共或私有代理!
  5. options.add_argument('--proxy-server=username:password@ip:port')
  6. # 需要更改默认浏览器路径?没问题!
  7. options.binary_location = '/path/to/your/browser'
  8. async with Chrome(options=options) as browser:
  9. await browser.start()

您可以在此处找到所有可用的浏览器选项:Chromium 命令行参数

🎯 核心组件

浏览器接口

Browser 领域提供对浏览器本身的直接控制,允许全局管理整个浏览器实例。与特定页面操作不同,这些方法影响整个浏览器,支持管理多个页面、窗口属性、全局 Cookie 以及整个会话的事件监听。

示例代码:

  1. async def browser_examples():
  2. async with Chrome() as browser:
  3. await browser.start()
  4. # 轻松管理多个页面
  5. pages = [await browser.get_page() for _ in range(3)]
  6. # 只需一行代码即可调整窗口大小
  7. await browser.set_window_maximized()

浏览器管理

async start() -> None

启动浏览器,为自动化做好准备!

  1. async with Chrome() as browser:
  2. await browser.start() # 启动浏览器
async stop() -> None

优雅地关闭浏览器。

  1. await browser.stop() # 关闭浏览器
async get_page() -> Page

获取现有页面或创建新页面。

  1. page = await browser.get_page()
  2. await page.go_to("https://www.example.com")
async new_page(url: str = '') -> str

打开新页面并返回其 ID,适用于多标签自动化。

  1. page_id = await browser.new_page("https://www.example.com")
async get_page_by_id(page_id: str) -> Page

根据页面 ID 获取特定页面。

  1. page = await browser.get_page_by_id(page_id)
async get_targets() -> list

获取所有打开的页面。

  1. targets = await browser.get_targets()
  2. for target in targets:
  3. print(f"页面: {target.get('title')} - URL: {target.get('url')}")
async set_window_bounds(bounds: dict) -> None

设置窗口大小和位置。

  1. await browser.set_window_bounds({
  2. 'left': 100,
  3. 'top': 100,
  4. 'width': 1024,
  5. 'height': 768
  6. })
async get_cookies() -> list[dict]

获取浏览器存储的所有 Cookie。

  1. cookies = await browser.get_cookies()
  2. for cookie in cookies:
  3. print(f"名称: {cookie['name']}, 值: {cookie['value']}")
async delete_all_cookies() -> None

清除所有 Cookie。

  1. await browser.delete_all_cookies()
async set_download_path(path: str) -> None

设置下载目录。

  1. await browser.set_download_path("/path/to/downloads")

页面接口

Page 代表单个浏览器标签页,提供精准的页面控制功能,例如交互、事件监听、截图等。

示例代码:

  1. async def page_examples():
  2. await page.go_to('https://example.com')
  3. # 获取页面信息
  4. current_url = await page.current_url
  5. content = await page.page_source
  6. # 截图
  7. await page.get_screenshot('/screenshots/evidence.png')
  8. # 操作 Cookie
  9. cookies = await page.get_cookies()
  10. await page.set_cookies([{'name': 'session', 'value': 'xyz123'}])
  11. # 执行 JavaScript
  12. await page.execute_script('return document.title')

页面管理

async go_to(url: str, timeout=300) -> None

访问指定 URL。

  1. await page.go_to("https://www.example.com", timeout=60)
async refresh() -> None

刷新页面。

  1. await page.refresh()
async close() -> None

关闭当前页面。

  1. await page.close()
async current_url -> str

获取当前页面 URL。

  1. url = await page.current_url
  2. print(f"当前 URL: {url}")
async get_screenshot(path: str) -> None

截图并保存。

  1. await page.get_screenshot("/path/to/screenshot.png")
async print_to_pdf(path: str) -> None

将页面保存为 PDF。

  1. await page.print_to_pdf("/path/to/document.pdf")
async has_dialog() -> bool

检测是否有弹窗。

  1. if await page.has_dialog():
  2. print("检测到弹窗")
async accept_dialog() -> None

自动接受弹窗。

  1. if await page.has_dialog():
  2. await page.accept_dialog()
async set_download_path(path: str) -> None

设置页面的下载目录。

  1. await page.set_download_path("/my_downloads")
async get_network_logs(matches: list[str] = []) -> list

获取网络请求日志。

  1. await page.enable_network_events() # 必须先启用网络监听
  2. await page.go_to('https://example.com')
  3. logs = await page.get_network_logs(['/api'])
  1. {
  2. "method": "Network.requestWillBeSent",
  3. "params": {
  4. "requestId": "764F3179D5C6D0A1A3F67E7C0ECD88DB",
  5. "loaderId": "764F3179D5C6D0A1A3F67E7C0ECD88DB",
  6. "documentURL": "https://google.com/",
  7. "request": {
  8. "url": "https://google.com/",
  9. "method": "GET",
  10. "headers": {
  11. "Upgrade-Insecure-Requests": "1",
  12. "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
  13. "sec-ch-ua": "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
  14. "sec-ch-ua-mobile": "?0",
  15. "sec-ch-ua-platform": "\"Linux\""
  16. },
  17. "mixedContentType": "none",
  18. "initialPriority": "VeryHigh",
  19. "referrerPolicy": "strict-origin-when-cross-origin",
  20. "isSameSite": true
  21. },
  22. "timestamp": 152714.232433,
  23. "wallTime": 1741737850.444337,
  24. "initiator": {
  25. "type": "other"
  26. },
  27. "redirectHasExtraInfo": false,
  28. "type": "Document",
  29. "frameId": "2EC0B50381EB2D8CF48BE3CF1D933B59",
  30. "hasUserGesture": false
  31. }
  32. }
async get_network_response_bodies(matches: list[str] = []) -> list

捕获 API 调用的实际响应数据 - 非常适合验证!

  1. # 获取 API 请求的响应
  2. responses = await page.get_network_response_bodies(['google.com'])

你将得到类似这样的数据:

  1. [
  2. {
  3. 'body': '...',
  4. 'base64Encoded': False
  5. }
  6. ]
async get_network_response_body(request_id: str) -> tuple

针对特定请求进行详细分析。

  1. # 获取特定请求的响应体
  2. logs = await page.get_network_logs(['api/products'])
  3. body, encoded = await page.get_network_response_body(logs[0]['params']['requestId'])
async on(event_name: str, callback: callable, temporary: bool = False) -> int

使你的自动化能够实时响应页面事件!详细信息请查看 事件系统 部分。

async execute_script(script: str, element: WebElement = None)

直接从你的 Python 代码执行 JavaScript,释放 JavaScript 的全部威力!

  1. # 在页面上执行 JavaScript
  2. title = await page.execute_script('return document.title')
  3. # 在特定元素上执行 JavaScript
  4. button = await page.find_element(By.CSS_SELECTOR, 'button')
  5. await page.execute_script('arguments[0].click()', button)

WebElement 接口

WebElement 代表浏览器中的 DOM 元素,允许你以模拟真实用户行为的方式与其交互。本节介绍与网页元素交互的最有用的方法。

value -> str

获取元素的当前值 - 非常适合检查表单字段。

  1. # 检查输入框的值
  2. input_element = await page.find_element(By.CSS_SELECTOR, 'input')
  3. print(f"当前值: {input_element.value}")
class_name -> str

访问元素的 CSS 类 - 用于样式验证。

  1. # 检查 CSS 类
  2. button = await page.find_element(By.CSS_SELECTOR, 'button')
  3. print(f"类名: {button.class_name}")
id -> str

获取元素的 ID - 适用于唯一标识。

  1. # 获取元素的 ID
  2. element = await page.find_element(By.CSS_SELECTOR, 'div')
  3. print(f"ID: {element.id}")
is_enabled -> bool

快速检查元素是否可交互。

  1. # 在点击前检查按钮是否可用
  2. button = await page.find_element(By.CSS_SELECTOR, 'button')
  3. if button.is_enabled:
  4. await button.click()
async bounds -> list

获取元素的精确边界坐标。

  1. # 获取元素的坐标
  2. element = await page.find_element(By.CSS_SELECTOR, 'div')
  3. bounds = await element.bounds
  4. print(f"坐标: {bounds}")
async inner_html -> str

获取元素的内部 HTML - 适用于网页抓取!

  1. # 获取容器的内部 HTML
  2. container = await page.find_element(By.CSS_SELECTOR, '.container')
  3. html = await container.inner_html
  4. print(f"内部 HTML: {html}")
async get_element_text() -> str

获取元素的文本内容 - 干净且可直接使用。

  1. # 获取元素的文本
  2. element = await page.find_element(By.CSS_SELECTOR, 'p')
  3. text = await element.get_element_text()
  4. print(f"文本: {text}")
async click(x_offset: int = 0, y_offset: int = 0)

精确点击元素 - 甚至可以带偏移量。

  1. # 进行带偏移的点击
  2. slider = await page.find_element(By.CSS_SELECTOR, '.slider')
  3. # 在元素中心的右侧 10 像素处点击
  4. await slider.click(x_offset=10, y_offset=0)
async send_keys(text: str)

快速向表单字段输入文本。

  1. # 填写文本框
  2. input_field = await page.find_element(By.CSS_SELECTOR, 'input[name="username"]')
  3. await input_field.send_keys("user123")
async type_keys(text: str)

像真实用户一样逐键输入文本,模拟人工输入。

  1. # 模拟真实输入 - 每个键之间有短暂停顿
  2. password_field = await page.find_element(By.CSS_SELECTOR, 'input[type="password"]')
  3. await password_field.type_keys("secure_password123") # 真实的打字体验!
async get_screenshot(path: str)

捕获元素的截图 - 适用于测试或存档。

  1. # 截取特定元素的截图
  2. error_message = await page.find_element(By.CSS_SELECTOR, '.error-message')
  3. await error_message.get_screenshot('/screenshots/error.png')

🚀 高级功能

事件系统

Pydoll 的事件系统让你的自动化变得更智能!实时监听并响应浏览器事件,使你的脚本更加动态。

async on(event_name: str, callback: callable, temporary: bool = False) -> int

为任何浏览器事件注册回调函数。例如,监听页面加载事件:

  1. from pydoll.events.page import PageEvents
  2. # 监听任何页面的导航事件
  3. async def on_page_loaded(event):
  4. print(f"🌐 正在导航到: {event['params'].get('url')}")
  5. await browser.enable_page_events() # 激活页面事件
  6. await browser.on(PageEvents.PAGE_LOADED, on_page_loaded) # 全局监听!
async enable_network_events() -> None

实时查看所有网络活动 - 适用于调试或 API 监控!

  1. from pydoll.events.network import NetworkEvents
  2. async def on_request(event):
  3. print(f"🔄 发送请求至: {event['params']['request']['url']}")
  4. await browser.enable_network_events()
  5. await browser.on(NetworkEvents.REQUEST_WILL_BE_SENT, on_request)

这只是 Pydoll 提供的一部分功能,你可以利用它来实现高效的自动化!🚀