Open *response* in a local web browser, adjusting the `base tag`_ for external links to work, e.g. so that images and styles are displayed. .. _base tag: https://www.w3schools.com/tags/tag_base.asp For example: .. code-block:: python from scrapy.utils.response import open
(
response: TextResponse,
_openfunc: Callable[[str], Any] = webbrowser.open,
)
| 72 | |
| 73 | |
| 74 | def open_in_browser( |
| 75 | response: TextResponse, |
| 76 | _openfunc: Callable[[str], Any] = webbrowser.open, |
| 77 | ) -> Any: |
| 78 | """Open *response* in a local web browser, adjusting the `base tag`_ for |
| 79 | external links to work, e.g. so that images and styles are displayed. |
| 80 | |
| 81 | .. _base tag: https://www.w3schools.com/tags/tag_base.asp |
| 82 | |
| 83 | For example: |
| 84 | |
| 85 | .. code-block:: python |
| 86 | |
| 87 | from scrapy.utils.response import open_in_browser |
| 88 | |
| 89 | |
| 90 | def parse_details(self, response): |
| 91 | if "item name" not in response.body: |
| 92 | open_in_browser(response) |
| 93 | """ |
| 94 | # circular imports |
| 95 | from scrapy.http import HtmlResponse, TextResponse # noqa: PLC0415 |
| 96 | |
| 97 | # XXX: this implementation is a bit dirty and could be improved |
| 98 | body = response.body |
| 99 | if isinstance(response, HtmlResponse): |
| 100 | if b"<base" not in body: |
| 101 | _remove_html_comments(body) |
| 102 | repl = rf'\g<0><base href="{response.url}">' |
| 103 | body = re.sub(rb"<head(?:[^<>]*?>)", to_bytes(repl), body, count=1) |
| 104 | ext = ".html" |
| 105 | elif isinstance(response, TextResponse): |
| 106 | ext = ".txt" |
| 107 | else: |
| 108 | raise TypeError(f"Unsupported response type: {response.__class__.__name__}") |
| 109 | fd, fname = tempfile.mkstemp(ext) |
| 110 | os.write(fd, body) |
| 111 | os.close(fd) |
| 112 | return _openfunc(f"file://{fname}") |