【问题标题】:Precisely catch DNS error with Python requests使用 Python 请求精确捕获 DNS 错误
【发布时间】:2017-03-01 22:25:26
【问题描述】:

我正在尝试使用python-requests 检查过期域名。

import requests

try:
    status = requests.head('http://wowsucherror')
except requests.ConnectionError as exc:
    print(exc)

这段代码看起来太笼统了。它产生以下输出:

HTTPConnectionPool(host='wowsucherror', port=80): Max retries exceeded with url: / (Caused by NewConnectionError(': 无法建立新连接: [Errno 11001] getaddrinfo failed',))

我想做的只是捕捉这个 DNS 错误(比如 Chrome 中的ERR_NAME_NOT_RESOLVED)。作为最后的手段,我可​​以只进行字符串匹配,但也许有更好、更结构化和向前兼容的方式来处理这个错误?

理想情况下,它应该是DNSErrorrequests 的扩展。

更新:Linux上的错误不同。

HTTPConnectionPool(host='wowsucherror', port=80): Max retries exceeded with url: / (Caused by NewConnectionError(': 无法建立新连接: [Errno -2] Name or service not known',) )

将错误报告给requests -> urllib3 https://github.com/shazow/urllib3/issues/1003

UPDATE2:OS X 也会报告不同的错误。

requests.exceptions.ConnectionError: HTTPConnectionPool(host='wowsucherror', port=80): Max retries exceeded with url: / (Caused by NewConnectionError(': 无法建立新连接: [Errno 8] nodename or servname提供,或不知道',))

【问题讨论】:

  • 我认为您将无法从字符串中解析 errno,此处捕获了套接字错误github.com/kennethreitz/requests/blob/master/requests/packages/…,但在任何地方都没有设置 errno 属性,因此您得到的只是错误消息。如果您实际上可以访问e,如果您只是检查 e.errno。
  • @PadraicCunningham 它看起来也像那个错误消息它不是跨平台的,我需要知道它在 Linux 和 OS X 上的样子。
  • 确实,它在我的 Ubuntu 机器上抛出了 [errno -2],我尝试了 except (NewConnectionError, socket.error) as exc:,但套接字错误被吞没了。可能值得开始一个问题,因为这似乎是一件合理的事情,它只是传递 e.errno 的问题。

标签: dns python-requests


【解决方案1】:

通过这个 hack 完成此操作,但请监视 https://github.com/psf/requests/issues/3630 以获取正确的显示方式。

# for Python 2 compatibility
from __future__ import print_function
import requests

def sitecheck(url):
    status = None
    message = ''
    try:
        resp = requests.head('http://' + url)
        status = str(resp.status_code)
    if ("[Errno 11001] getaddrinfo failed" in str(exc) or     # Windows
        "[Errno -2] Name or service not known" in str(exc) or # Linux
        "[Errno 8] nodename nor servname " in str(exc)):      # OS X
        message = 'DNSLookupError'
    else:
        raise

    return url, status, message

print(sitecheck('wowsucherror'))
print(sitecheck('google.com'))

【讨论】:

    【解决方案2】:

    您可以使用较低级别的网络接口,socket.getaddrinfohttps://docs.python.org/3/library/socket.html#socket.getaddrinfo

    import socket
    
    
    def dns_lookup(host):
        try:
            socket.getaddrinfo(host, 80)
        except socket.gaierror:
            return False
        return True
    
    
    print(dns_lookup('wowsucherror'))
    print(dns_lookup('google.com'))
    
    

    【讨论】:

      【解决方案3】:

      我有一个基于上述较早答案的功能,该功能似乎不再起作用。此函数根据分辨率以及请求 .ok 函数检查 url 的“活跃度”,而不仅仅是特定于分辨率错误,但可以轻松调整以适应。

      def check_live(url):
          try:
              r = requests.get(url)
              live = r.ok
          except requests.ConnectionError as e:
              if 'MaxRetryError' not in str(e.args) or 'NewConnectionError' not in str(e.args):
                  raise
              if "[Errno 8]" in str(e) or "[Errno 11001]" in str(e) or ["Errno -2"] in str(e):
                  print('DNSLookupError')
                  live = False
              else:
                  raise
          except:
              raise
          return live
      

      【讨论】:

        猜你喜欢
        • 2015-10-08
        • 2018-08-05
        • 2016-09-16
        • 2021-07-27
        • 1970-01-01
        • 2016-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多