Great! I’ll create a concise yet comprehensive guide to Playwright’s `sync_api` that focuses on the features and arguments most useful for your web scraping node—especially for scraping images, videos, and metadata like titles, captions, alt text, and credits. I'll organize it around topics like browser and page control, DOM interaction, attribute extraction, lazy loading handling, authentication, and navigating subpages. This will serve as a reference you can pass to an LLM. I’ll get started and let you know when it’s ready. # Python Playwright `sync_api` Reference Guide for Scraping Images & Metadata ## Browser Control (Launching Browser & Contexts) - **Launching a Browser:** Use the `sync_playwright()` context manager to initialize Playwright and launch a browser. For example, launch Chromium in headless mode (no GUI) or headful mode (for debugging): ```python from playwright.sync_api import sync_playwright with sync_playwright() as pw: browser = pw.chromium.launch(headless=True) # headless False to see the browser page = browser.new_page() # ... your code ... browser.close() ``` *Key options:* `headless` (bool, default `True`), `slow_mo` (ms delay for each action, useful for debugging), `devtools` (open devtools when headful). - **Browser Contexts:** A Browser **Context** is like an incognito browser session. Multiple contexts can run in one Browser instance, each with isolated cookies/storage ([BrowserContext | Playwright Python](https://playwright.dev/python/docs/api/class-browsercontext#:~:text=BrowserContexts%20provide%20a%20way%20to,operate%20multiple%20independent%20browser%20sessions)). Use `browser.new_context(**options)` to create one. If you call `browser.new_page()`, Playwright will create a new context under the hood for that page (isolating it from others). - **Context Options:** `viewport={"width": 1280, "height": 720}` (control resolution), `user_agent="Custom UA"` (masquerade as a specific device or browser), `locale="en-US"`, `timezone_id="UTC"`, etc. - **Persistent Context:** If you need to preserve login/session across runs, use `pw.chromium.launch_persistent_context(user_data_dir="path/to/profile")` instead of `browser.new_context()`. This uses a profile directory on disk to save cookies, localStorage, etc. - **Pages:** Once you have a context, open pages with `context.new_page()`. All pages in a context share that session’s cookies and storage. For example: ```python context = browser.new_context() page1 = context.new_page() page2 = context.new_page() # shares cookies with page1 ``` - **Closing:** Call `browser.close()` to close the browser (this closes all contexts and pages). You can also close individual contexts with `context.close()` when done ([BrowserContext | Playwright Python](https://playwright.dev/python/docs/api/class-browsercontext#:~:text=,close)). ## Page Navigation (Loading Websites and Handling Navigation) - **Navigating to a URL:** Use `page.goto(url, timeout=ms, wait_until="load")`. This loads the page and waits for the load event by default. Example: ```python response = page.goto("https://example.com", timeout=30000, wait_until="domcontentloaded") ``` Here `wait_until` could be `"load"`, `"domcontentloaded"`, or `"networkidle"`: - `"load"` waits for the full load (HTML, scripts, CSS, images) ([Page | Playwright Python](https://playwright.dev/python/docs/api/class-page#:~:text=%2A%20%60state%60%20,%28optional)). - `"domcontentloaded"` waits for initial HTML DOM to be ready (faster) ([Page | Playwright Python](https://playwright.dev/python/docs/api/class-page#:~:text=%2A%20%60%27load%27%60%20,there%20are%20no%20network%20connections)). - `"networkidle"` waits for network to be idle (no requests for ~500 ms) ([Page | Playwright Python](https://playwright.dev/python/docs/api/class-page#:~:text=%2A%20%60%27load%27%60%20,testing%2C%20rely%20on%20web%20assertions)) – useful for SPAs but *discouraged for testing* ([Page | Playwright Python](https://playwright.dev/python/docs/api/class-page#:~:text=%2A%20%60%27load%27%60%20,testing%2C%20rely%20on%20web%20assertions)). - **Controlling Timeouts:** By default, navigation and actions timeout after 30s. You can override per call (`timeout=5000`) or globally: ```python page.set_default_timeout(10000) # 10s for actions (like click, selectors) page.set_default_navigation_timeout(20000) # 20s for page.goto or wait_for_navigation ``` - **After Navigation:** It’s good practice to wait for critical elements to load. For example, wait for a specific element that indicates the page is ready: ```python page.goto("https://reddit.com/r/Art") page.wait_for_selector("div#siteTable", state="visible") # sample selector ``` This ensures the main content container is visible before proceeding. - **Page URL and Title:** Access `page.url` for current URL (which may change after navigation or redirects) and use `page.title()` to get the `