繁体   English   中英

Requests-html 我可以获取所有请求的状态代码(或 selenium 替代方案)

[英]Requests-html can I get status codes of all requests (or selenium alternative)

我有以下代码:

from requests_html import HTMLSession

ses = HTMLSession()
r = ses.get(MYURL)  # start a headless chrome browser and load MYURL
r.render(keep_page=True)  # This will now 'render' the html page
                          # which means like in a real browser trigger
                          # all requests for dependent links. 
                          # like .css, .js, .jpg, .gif

调用render()会触发对 Javascript、位图等的大量请求。有什么方法可以跟踪每个请求的状态代码。 我最感兴趣的是404 ,但4035xx错误也可能很有趣。

例如,一个用例是:

• Go 到一个页面或一系列页面

• 然后报告有多少请求失败以及访问了哪些网址。

如果这对于 requests-html 是不可能的,但对于 selenium 来说相当简单,我可以切换到 selenium

附录:丑陋的工作 1:

我可以设置日志记录以登录到文件并将日志级别设置为调试。 然后我可以尝试解析 websockets.protocol: 的日志,其中包含类似{\\"url\\":\\"https://my.server/example.gif\\",\\"status\\":404,\\"statusText\\":\\"...

问题:

将日志级别 DEBUG 激活到文件中似乎激活了其他东西,因为突然加载的调试信息也被记录到stdout中。

例如:

[I:pyppeteer.launcher] Browser listening on: ws://127.0.0.1:45945/devtools/browser/bc5ce097-e67d-455e-8a59-9a4c213263c1
[D:pyppeteer.connection.Connection] SEND: {"id": 1, "method": "Target.setDiscoverTargets", "params": {"discover": true}}

此外,实时解析它并将其与我在代码中使用的 url 相关联并不是很有趣。

附录:丑陋的工作 2:

更糟糕的是关联但更好的解析和识别404 s 并且只要控制 http 服务器就可以工作。

使用 nginx 解析日志 http 服务器的日志,我什至可以使用我感兴趣的数据设置 csv 格式的自定义记录器。

附录:丑陋的工作 3:

使用 python 日志记录(pyppeteer 的专用处理程序和过滤器),我可以拦截pyppeteer字符串,描述来自pyppeteer.connection.CDPSession记录器的响应,而不会污染stderr

过滤器允许我实时检索数据。

这仍然很骇人听闻。 所以寻求更好的解决方案。

尝试以下方法,看看它是否是您所追求的。 它严格来说是一个 pyppeteer 版本(而不是 requests_html),并且依赖于未公开的私有变量,因此很容易受到版本更新的破坏。

import asyncio
from pyppeteer import launch
from pyppeteer.network_manager import NetworkManager

def logit(event):
    req = event._request
    print("{0} - {1}".format(req.url, event._status))

async def main():
    browser = await launch({"headless": False})
    page = await browser.newPage()
    page._networkManager.on(NetworkManager.Events.Response, logit)
    await page.goto('https://www.google.com')
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())

检查 requests_html 的来源,浏览器页面 object 似乎被埋得很深——所以访问 NetworkManager 并不是很简单。 如果您真的希望它在 requests_html 中工作,那么猴子补丁可能最容易。 这是一个例子:

import asyncio
from requests_html import HTMLSession, TimeoutError, HTML
from pyppeteer.network_manager import NetworkManager
from typing import Optional, Union

def logit(event):
    req = event._request
    print("{0} - {1}".format(req.url, event._status))

async def _async_render(self, *, url: str, script: str = None, scrolldown, sleep: int, wait: float, reload, content: Optional[str], timeout: Union[float, int], keep_page: bool, cookies: list = [{}]):
    """ Handle page creation and js rendering. Internal use for render/arender methods. """
    try:
        page = await self.browser.newPage()
        page._networkManager.on(NetworkManager.Events.Response, logit)

        # Wait before rendering the page, to prevent timeouts.
        await asyncio.sleep(wait)

        if cookies:
            for cookie in cookies:
                if cookie:
                    await page.setCookie(cookie)

        # Load the given page (GET request, obviously.)
        if reload:
            await page.goto(url, options={'timeout': int(timeout * 1000)})
        else:
            await page.goto(f'data:text/html,{self.html}', options={'timeout': int(timeout * 1000)})

        result = None
        if script:
            result = await page.evaluate(script)

        if scrolldown:
            for _ in range(scrolldown):
                await page._keyboard.down('PageDown')
                await asyncio.sleep(sleep)
        else:
            await asyncio.sleep(sleep)

        if scrolldown:
            await page._keyboard.up('PageDown')

        # Return the content of the page, JavaScript evaluated.
        content = await page.content()
        if not keep_page:
            await page.close()
            page = None
        return content, result, page
    except TimeoutError:
        await page.close()
        page = None
        return None


ses = HTMLSession()
r = ses.get('https://www.google.com')  # start a headless chrome browser and load MYURL
html =  r.html
html._async_render = _async_render.__get__(html, HTML)
html.render()

在 Chrome 中使用 Selenium 也有可能有一个 Python package 用于称为Selenium-interceptor

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM