Skip to content

Commit 4375e4a

Browse files
committed
docs: add multi-tab management section with singleton pattern details
1 parent 7b201dc commit 4375e4a

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

docs/features.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,133 @@ asyncio.run(background_bypass_example())
209209

210210
Access websites that actively block automation tools without using third-party captcha solving services. This native captcha handling makes Pydoll suitable for automating previously inaccessible websites.
211211

212+
## Multi-Tab Management
213+
214+
Pydoll provides sophisticated tab management capabilities with a singleton pattern that ensures efficient resource usage and prevents duplicate Tab instances for the same browser tab.
215+
216+
### Tab Singleton Pattern
217+
218+
Pydoll implements a singleton pattern for Tab instances based on the browser's target ID. This means:
219+
220+
- **One Tab instance per browser tab**: Multiple references to the same browser tab return the same Tab object
221+
- **Automatic resource management**: No duplicate connections or handlers for the same tab
222+
- **Consistent state**: All references to a tab share the same state and event handlers
223+
224+
```python
225+
import asyncio
226+
from pydoll.browser.chromium import Chrome
227+
from pydoll.browser.tab import Tab
228+
229+
async def singleton_demonstration():
230+
async with Chrome() as browser:
231+
tab = await browser.start()
232+
233+
# Get the same tab through different methods - they're identical objects
234+
same_tab = Tab(browser, browser._connection_port, tab._target_id)
235+
opened_tabs = await browser.get_opened_tabs()
236+
237+
# All references point to the same singleton instance
238+
print(f"Same object? {tab is same_tab}") # May be True if same target_id
239+
print(f"Tab instances are managed as singletons")
240+
241+
asyncio.run(singleton_demonstration())
242+
```
243+
244+
### Creating New Tabs Programmatically
245+
246+
Use `new_tab()` to create tabs programmatically with full control:
247+
248+
```python
249+
import asyncio
250+
from pydoll.browser.chromium import Chrome
251+
252+
async def programmatic_tab_creation():
253+
async with Chrome() as browser:
254+
# Start with the initial tab
255+
main_tab = await browser.start()
256+
257+
# Create additional tabs with specific URLs
258+
search_tab = await browser.new_tab('https://google.com')
259+
news_tab = await browser.new_tab('https://news.ycombinator.com')
260+
docs_tab = await browser.new_tab('https://docs.python.org')
261+
262+
# Work with multiple tabs simultaneously
263+
await search_tab.find(name='q').type_text('Python automation')
264+
await news_tab.find(class_name='storylink', find_all=True)
265+
await docs_tab.find(id='search-field').type_text('asyncio')
266+
267+
# Get all opened tabs
268+
all_tabs = await browser.get_opened_tabs()
269+
print(f"Total tabs open: {len(all_tabs)}")
270+
271+
# Close specific tabs when done
272+
await search_tab.close()
273+
await news_tab.close()
274+
275+
asyncio.run(programmatic_tab_creation())
276+
```
277+
278+
### Handling User-Opened Tabs
279+
280+
When users click links that open new tabs (target="_blank"), use `get_opened_tabs()` to detect and manage them:
281+
282+
```python
283+
import asyncio
284+
from pydoll.browser.chromium import Chrome
285+
286+
async def handle_user_opened_tabs():
287+
async with Chrome() as browser:
288+
main_tab = await browser.start()
289+
await main_tab.go_to('https://example.com')
290+
291+
# Get initial tab count
292+
initial_tabs = await browser.get_opened_tabs()
293+
initial_count = len(initial_tabs)
294+
print(f"Initial tabs: {initial_count}")
295+
296+
# Click a link that opens a new tab (target="_blank")
297+
external_link = await main_tab.find(text='Open in New Tab')
298+
await external_link.click()
299+
300+
# Wait for new tab to open
301+
await asyncio.sleep(2)
302+
303+
# Detect new tabs
304+
current_tabs = await browser.get_opened_tabs()
305+
new_tab_count = len(current_tabs)
306+
307+
if new_tab_count > initial_count:
308+
print(f"New tab detected! Total tabs: {new_tab_count}")
309+
310+
# Get the newly opened tab (last in the list)
311+
new_tab = current_tabs[-1]
312+
313+
# Work with the new tab
314+
await new_tab.go_to('https://different-site.com')
315+
title = await new_tab.execute_script('return document.title')
316+
print(f"New tab title: {title}")
317+
318+
# Close the new tab when done
319+
await new_tab.close()
320+
321+
asyncio.run(handle_user_opened_tabs())
322+
```
323+
324+
### Key Benefits of Pydoll's Tab Management
325+
326+
1. **Singleton Pattern**: Prevents resource duplication and ensures consistent state
327+
2. **Automatic Detection**: `get_opened_tabs()` finds all tabs, including user-opened ones
328+
3. **Concurrent Processing**: Handle multiple tabs simultaneously with asyncio
329+
4. **Resource Management**: Proper cleanup prevents memory leaks
330+
5. **Event Isolation**: Each tab maintains its own event handlers and state
331+
332+
This sophisticated tab management makes Pydoll ideal for:
333+
- **Multi-page workflows** that require coordination between tabs
334+
- **Parallel data extraction** from multiple sources
335+
- **Testing applications** that use popup windows or new tabs
336+
- **Monitoring user behavior** across multiple browser tabs
337+
338+
212339
## Concurrent Scraping
213340

214341
Pydoll's async architecture allows you to scrape multiple pages or websites simultaneously for maximum efficiency:

0 commit comments

Comments
 (0)