挂起请求,尽管设置了超时值

2024-05-03 20:56:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经建立了一个程序,并行地从多个网站抓取数据。我面临的问题是,尽管设置了超时值,但我的请求通常挂起在一个无限循环中,而没有实际执行

对于每个网站(总共5个),在开始时创建一个单独的线程,每个线程每分钟调用以下函数一次:

def proxy_request(my_url):
    while True: #try request over and over again if it fails for some reason
        try:
            proxies = {"https": "XXXXXXXX", "http": "XXXXXXX"}
            headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.73.11 (KHTML, like Gecko) Version/7.0.1 Safari/537.73.11'}
            source = requests.get(my_url, proxies=proxies, headers=headers, timeout=5)
            return source
            break #stop if the request worked out

        except(requests.exceptions.SSLError, requests.exceptions.ReadTimeout) as error:
            logging.exception("{} {}".format(my_url, datetime.datetime.utcnow()))
            print(error)

为了清楚地了解这个问题,我修改了代码:

def proxy_request(my_url):
    while True:
        try:

            proxies = {"http": "XXXXXXXXX", "https":"XXXXXXX"} # Webshare
            headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36', "Upgrade-Insecure-Requests": "1","DNT": "1","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language": "en-US,en;q=0.5","Accept-Encoding": "gzip, deflate"}
            source = requests.get(my_url, proxies=proxies, headers=headers, timeout=10)
            return source
            break

        except Exception as error:
            logging.exception("{} {}".format(my_url, datetime.datetime.utcnow()))
            print(error)

        finally:
            print(my_url[0:30], "Request completed")

finally不会在请求不成功的情况下执行,不会引发错误,未完成的请求不会显示在日志文件中,只有成功的请求才会显示。因此,我假设在无限循环中挂起的确实是请求本身

我的第一个想法是,网站必须有一个适当的保护,以防止人们刮取数据。不太可能出现这种情况的原因是,连续多次重新启动脚本(始终使用相同的代理设置)通常可以解决此问题。不可预测的是,哪些站点在每次启动时都能工作,并且最多需要10次重新启动,直到相当数量的站点工作为止,但是如果一个站点从一开始就工作,它通常会工作很长一段时间(测试时间超过24小时)。我对所有请求使用同一个代理,并且在重新启动时不更改它

我怎样才能对请求挂起的原因做出更清楚的诊断

在一段时间后终止请求的最优雅的方式是什么

我曾尝试使用eventlet(如建议的here)执行此操作,但结果是“递归错误:超过最大递归深度”。我不能使用signal,因为我希望我的代码在Windows和Linux上工作

谢谢


Tags: 数据urlsourcedatetime站点网站requestmy