首页 > 解决方案 > 对同一页面的多个 HTTP 请求而不会消耗太多 CPU

问题描述

目前,我正在尝试改进向网页发送多个 HTTP 请求的代码,直到它可以捕获一些文本(代码通过已知模式本地化)或直到 180 秒用完(我们等待页面给出的时间我们回答)。这是代码的一部分(出于隐私目的稍作编辑):

       if matches == None:
            txt = "No answer til now"
            print(txt)
            Solution = False
            start = time.time()
            interval = 0
            while interval < 180:
                response   = requests.get("page address")
                subject  = response.text
                matches = re.search(pattern, subject, re.IGNORECASE)
                if matches != None:
                    Solution =matches.group(1)
                    time = "{:.2f}".format(time.time()-start) 
                    txt = "Found an anwswer "+ Solution + "time needed : "+ time
                    print(txt)
                    break
                interval = time.time()-start
        else:
            Solution = matches.group(1)

它运行正常,但有人告诉我,执行“循环中的无限请求”可能会导致服务器的 CPU 使用率过高。你们知道我可以使用什么来避免这种情况吗?

Ps:我听说在 PHP 中人们使用 curl_multi_select() 来处理这些事情。虽然不知道我是否正确。

标签: python-3.xpython-requestshttprequestcpu-usage

解决方案


通常,HTTP REST API 会在文档中指定在给定时间段内您可以针对哪些端点资源发出多少请求。

对于一个网站,如果您没有达到请求限制并且因为太多请求而被标记/禁止,那么您应该可以像这样连续循环,但您可能希望在循环中引入time.sleep调用while

180 秒超时的替代方法:

由于 HTTP 请求是 I/O 操作并且可能需要可变的时间,因此您可能希望将循环的退出案例更改为一定数量的请求(如 25 个或其他),然后合并上述sleep调用。

这可能看起来像:

# ...
if matches is None:
    solution = None
    num_requests = 25
    start = time.time()

    while num_requests:
        response = requests.get("page address")

        if response.ok:  # It's good to attempt to handle potential HTTP/Connectivity errors
            subject = response.text
            matches = re.search(pattern, subject, re.IGNORECASE)
            if matches:
                solution = matches.group(1)
                elapsed = "{:.2f}".format(time.time()-start) 
                txt = "Found an anwswer " + solution + "time needed : " + elapsed
            print(txt)
            break
        else:
            # Maybe raise an error here?
            pass

        time.sleep(2)
        num_requests -= 1

else:
    solution = matches.group(1)

备注

  • 关于 PHP curl_multi_select- (这里不是 PHP 专家......)似乎这个函数旨在让您以异步方式查看到不同 URL 的多个连接。异步在这里并不真正适用于您的用例,因为您只是在抓取一个网页(URL),并且只是在等待一些数据出现在那里。
  • 如果response.text您正在搜索的是 HTML,并且您还没有在代码中的其他地方使用它,我会推荐Beautiful Soupscrapy to(在正则表达式之前)在网页标记中搜索字符串模式。

推荐阅读