【问题标题】:Python check if website existsPython 检查网站是否存在
【发布时间】:2013-05-22 14:53:46
【问题描述】:

我想检查某个网站是否存在,这就是我正在做的:

user_agent = 'Mozilla/20.0.1 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent':user_agent }
link = "http://www.abc.com"
req = urllib2.Request(link, headers = headers)
page = urllib2.urlopen(req).read() - ERROR 402 generated here!

如果页面不存在(错误 402 或任何其他错误),我可以在 page = ... 行中执行什么操作以确保我正在阅读的页面确实退出?

【问题讨论】:

  • 如果你得到 200 则只读取 if 检查怎么样?

标签: python html urlopen


【解决方案1】:

您可以使用 HEAD 请求代替 GET。它只会下载标题,但不会下载内容。然后您可以从标头中检查响应状态。

对于python 2.7.x,可以使用httplib

import httplib
c = httplib.HTTPConnection('www.example.com')
c.request("HEAD", '')
if c.getresponse().status == 200:
   print('web site exists')

urllib2:

import urllib2
try:
    urllib2.urlopen('http://www.example.com/some_page')
except urllib2.HTTPError, e:
    print(e.code)
except urllib2.URLError, e:
    print(e.args)

或者对于 2.7 和 3.x,你可以安装 requests

import requests
response = requests.get('http://www.example.com')
if response.status_code == 200:
    print('Web site exists')
else:
    print('Web site does not exist') 

【讨论】:

  • 请注意,www.abc.com 返回 301(已移动)status code
  • 请注意,即使 URL 存在,HEAD 请求也可能失败。例如,亚马逊为其首页返回状态 405(不允许使用方法)。在这种情况下,可能需要额外的 GET。
  • 我不确定旧的 requests 模块是什么样的,但现在,requests.head 是要使用的函数,而不是 requests.get
  • @AdemÖztaş,使用requests,如果特定网站不可用,则抛出requests.exceptions.ConnectionError
  • 这个答案是错误的。除了 200 之外,网站还返回了许多其他代码。这也不能处理通过长长的网站列表出现的错误。
【解决方案2】:

最好检查状态代码是否 here。以下是状态码的含义(取自wikipedia):

  • 1xx - 信息性
  • 2xx - 成功
  • 3xx - 重定向
  • 4xx - 客户端错误
  • 5xx - 服务器错误

如果你想检查页面是否存在并且不想下载整个页面,你应该使用Head Request

import httplib2
h = httplib2.Http()
resp = h.request("http://www.google.com", 'HEAD')
assert int(resp[0]['status']) < 400

取自this answer

如果您想下载整个页面,只需发出正常请求并检查状态码即可。使用requests 的示例:

import requests

response = requests.get('http://google.com')
assert response.status_code < 400

另见类似主题:

希望对您有所帮助。

【讨论】:

  • 我确实想下载该页面,但这是查看该页面是否存在的初步步骤
  • 解析这个链接有什么问题吗:http://www.cmegroup.com/trading/energy/electricity/caiso-sp15-ez-gen-hub-5-mw-peak-calendar-month-day-ahead-lmp-swap-futures_contract_specifications.html ?
  • 您提供的链接中包含无效字符。正确的链接是cmegroup.com/trading/energy/electricity/…。只需在我的示例中将 http://google.com 替换为它即可。
  • 好的,谢谢,请检查alexce的答案,它也很好用。
【解决方案3】:
from urllib2 import Request, urlopen, HTTPError, URLError

user_agent = 'Mozilla/20.0.1 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent':user_agent }
link = "http://www.abc.com/"
req = Request(link, headers = headers)
try:
        page_open = urlopen(req)
except HTTPError, e:
        print e.code
except URLError, e:
        print e.reason
else:
        print 'ok'

回答unutbu的评论:

因为默认处理程序处理重定向(300 范围内的代码),而 100-299 范围内的代码表示成功,您通常只会看到 400-599 范围内的错误代码。 Source

【讨论】:

  • 我收到这个错误:NameError: global name 'HTTPError' is not defined
  • 您是否也包含了导入?稍后我会看看它,但我在我的机器上测试了这段代码
  • 我发现了我的错误,我必须这样做:urllib.HTTPError(或者像你说的那样导入)。谢谢,效果很好
【解决方案4】:

代码:

a="http://www.example.com"
try:    
    print urllib.urlopen(a)
except:
    print a+"  site does not exist"

【讨论】:

    【解决方案5】:
    def isok(mypath):
        try:
            thepage = urllib.request.urlopen(mypath)
        except HTTPError as e:
            return 0
        except URLError as e:
            return 0
        else:
            return 1
    

    【讨论】:

    • 考虑在您的代码中添加描述;仅仅发布代码并不能帮助社区,因为它不能帮助他们理解它是如何工作的。为了吸引社区的支持,请考虑添加一些有关您的代码如何工作的详细信息。
    • 我认为不止一个人理解我的代码,但你是对的。感谢您的反馈!
    【解决方案6】:

    试试这个::

    import urllib2  
    website='https://www.allyourmusic.com'  
    try:  
        response = urllib2.urlopen(website)  
        if response.code==200:  
            print("site exists!")  
        else:  
            print("site doesn't exists!")  
    except urllib2.HTTPError, e:  
        print(e.code)  
    except urllib2.URLError, e:  
        print(e.args)  
    

    【讨论】:

      【解决方案7】:

      @Adem Öztaş 提供了一个很好的答案,用于httpliburllib2。对于requests,如果问题是严格的资源存在,那么在资源存在的情况下可以改进答案。

      requests 的先前答案建议如下:

      def uri_exists_get(uri: str) -> bool:
          try:
              response = requests.get(uri)
              try:
                  response.raise_for_status()
                  return True
              except requests.exceptions.HTTPError:
                  return False
          except requests.exceptions.ConnectionError:
              return False
      

      requests.get 尝试一次拉取整个资源,因此对于大型媒体文件,上面的 sn-p 会尝试将整个媒体拉入内存。为了解决这个问题,我们可以流式传输响应。

      def uri_exists_stream(uri: str) -> bool:
          try:
              with requests.get(uri, stream=True) as response:
                  try:
                      response.raise_for_status()
                      return True
                  except requests.exceptions.HTTPError:
                      return False
          except requests.exceptions.ConnectionError:
              return False
      

      我运行上面的 sn-ps 并针对两个 Web 资源附加了计时器:

      1)http://bbb3d.renderfarming.net/download.html,一个非常轻量级的html页面

      2) http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4,一个大小适中的视频文件

      计时结果如下:

      uri_exists_get("http://bbb3d.renderfarming.net/download.html")
      # Completed in: 0:00:00.611239
      
      uri_exists_stream("http://bbb3d.renderfarming.net/download.html")
      # Completed in: 0:00:00.000007
      
      uri_exists_get("http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4")
      # Completed in: 0:01:12.813224
      
      uri_exists_stream("http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4")
      # Completed in: 0:00:00.000007
      

      最后一点:此功能也适用于资源主机不存在的情况。例如"http://abcdefghblahblah.com/test.mp4" 将返回False

      【讨论】:

        【解决方案8】:

        您可以简单地使用stream 方法不下载完整文件。与最新的 Python3 一样,您不会获得 urllib2。最好使用经过验证的请求方法。这个简单的功能将解决您的问题。

        def uri_exists(url):
            r = requests.get(url, stream=True)
            if r.status_code == 200:
                return True
            else:
                return False
        

        【讨论】:

        • 函数中的参数是“uri” - 应该是“url”
        【解决方案9】:

        我看到很多使用requests.get 的答案,但我建议您只使用requests.head 这个解决方案,因为它不需要发回正文,所以对网络服务器来说更快、更好。

        import requests
        
        def check_url_exists(url: str):
            """
            Checks if a url exists
            :param url: url to check
            :return: True if the url exists, false otherwise.
            """
            return requests.head(url, allow_redirects=True).status_code == 200
        

        响应 HEAD 请求的 HTTP 标头中包含的元信息应与响应 GET 请求而发送的信息相同。

        【讨论】:

          猜你喜欢
          • 2012-07-16
          • 1970-01-01
          • 2011-10-06
          • 1970-01-01
          • 2011-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-26
          相关资源
          最近更新 更多