{"record":{"id":"e387222817c5c865","repo":"NanmiCoder/MediaCrawler","slug":"playwright-page-is-required-for-browser-based-note","errorCode":null,"errorMessage":"playwright_page is required for browser-based note detail fetching","messagePattern":"playwright_page is required for browser-based note detail fetching","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"media_platform/tieba/client.py","lineNumber":439,"sourceCode":"            utils.logger.info(f\"[BaiduTieBaClient.get_notes_by_keyword] Extracted {len(notes)} posts\")\n            return notes\n\n        except Exception as e:\n            utils.logger.error(f\"[BaiduTieBaClient.get_notes_by_keyword] Search failed: {e}\")\n            raise\n\n    async def get_note_by_id(self, note_id: str) -> TiebaNote:\n        \"\"\"\n        Get post details by post ID (uses Playwright to access page, avoiding API detection)\n        Args:\n            note_id: Post ID\n\n        Returns:\n            TiebaNote: Post detail object\n        \"\"\"\n        if not self.playwright_page:\n            utils.logger.error(\"[BaiduTieBaClient.get_note_by_id] playwright_page is None, cannot use browser mode\")\n            raise Exception(\"playwright_page is required for browser-based note detail fetching\")\n\n        utils.logger.info(f\"[BaiduTieBaClient.get_note_by_id] Accessing post detail API, note_id: {note_id}\")\n\n        try:\n            api_data = await self._get_pc_page_data(note_id=note_id, page=1)\n            note_detail = self._page_extractor.extract_note_detail_from_api(api_data)\n            return note_detail\n\n        except Exception as e:\n            utils.logger.error(f\"[BaiduTieBaClient.get_note_by_id] Failed to get post details: {e}\")\n            raise\n\n    async def get_note_all_comments(\n        self,\n        note_detail: TiebaNote,\n        crawl_interval: float = 1.0,\n        callback: Optional[Callable] = None,\n        max_count: int = 10,","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/NanmiCoder/MediaCrawler/blob/d6f7c5bb906b6dac40ddf343ef9e26438a3de092/media_platform/tieba/client.py#L421-L457","documentation":"Raised by BaiduTieBaClient.get_note_by_id (media_platform/tieba/client.py:439) when self.playwright_page is None. Post-detail fetching is implemented by navigating a real browser page at the post URL and extracting embedded JSON, so a missing page makes the operation impossible. The guard fails fast with a clear message instead of an opaque NoneType error.","triggerScenarios":"Calling get_note_by_id(note_id) on a client constructed without playwright_page, or after the browser/page has been torn down. Any detail crawl (search-result follow-up, direct note_id lookup) under these conditions triggers it.","commonSituations":"Scripts that instantiate the client for testing/mocking without a browser; running detail crawl before the login/browser setup step completes; browser crash mid-session leaving a stale client.","solutions":["Create and attach a Playwright page (via the standard crawler login flow) before calling get_note_by_id","Verify the browser is still alive (page.is_closed()) and re-create the context if it crashed","In tests, pass a mocked playwright_page exposing goto/content/evaluate"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"assert client.playwright_page is not None and not client.playwright_page.is_closed(), \"attach a live Playwright page first\"","typeGuard":"def ready_for_detail_fetch(client) -> bool:\n    return (\n        getattr(client, \"playwright_page\", None) is not None\n        and not client.playwright_page.is_closed()\n    )","tryCatchPattern":null,"preventionTips":["Create the browser context/page in crawler setup, not lazily mid-crawl","Wrap detail crawls in a browser-liveness check that re-creates the context on failure","Mock playwright_page (goto/content/evaluate) in unit tests"],"tags":["playwright","tieba","browser-context","validation"],"backgroundTag":null,"analyzedSha":"d6f7c5bb906b6dac40ddf343ef9e26438a3de092","analyzedAt":"2026-08-15T01:39:07.505Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}