通过Python检查网站是否正常运行

93

使用Python,我如何检查一个网站是否可以访问?从我的阅读中得出,我需要检查“HTTP HEAD”,并查看状态码“200 OK”,但是如何做到这一点呢?

谢谢

相关


2
请发送一个Python中的HEAD HTTP请求。 - Daniel Roseman
15个回答

137

您可以尝试使用urllib中的getcode()来实现此操作。

import urllib.request

print(urllib.request.urlopen("https://www.stackoverflow.com").getcode())
200

对于 Python 2 版本,请使用:

print urllib.urlopen("http://www.stackoverflow.com").getcode()
200

9
以下问题是:使用 urlopen.getcode 能否获取完整页面内容? - OscarRyz
1
@Oscar,urllib中没有任何指示它使用HEAD而不是GET的内容,但是Daniel上面提到的重复问题显示了如何执行前者。 - Peter Hansen
似乎在Python 3.x中已经没有urlopen方法了。我一直收到ImportError:无法导入名称'urlopen'的错误信息。我该如何解决这个问题? - l1zard
1
@l1zard 像这样:req = urllib.request.Request(url, headers = headers) resp = urllib.request.urlopen(req) - james-see
对我来说,这实际上返回的是403而不是200代码。 - David Okwii
显示剩余3条评论

36

我认为最简单的方法是使用Requests模块。

import requests

def url_ok(url):
    r = requests.head(url)
    return r.status_code == 200

8
针对 url = "http://foo.example.org/",这种方法行不通。我本来期望得到404状态码,但实际上程序崩溃了。 - Jonas Stein
1
这将针对除200(OK)以外的任何其他响应代码返回“False”。 因此,您不会知道它是否为404。 它仅检查网站是否正在运行并且_可供公众使用_。 - caisah
1
@caisah,你测试过了吗?Jonas是对的,我遇到了一个异常; raise ConnectionError(e) requests.exceptions.ConnectionError: HTTPConnectionPool(host='nosuch.org2', port=80): Max retries exceeded with url: / (Caused by <class 'socket.gaierror'>: [Errno 8] nodename nor servname provided, or not known) - AnneTheAgile
2
我在发布之前已经进行了测试。问题是,它只检查站点是否正常运行,无法处理主机名不正确或其他问题的情况。您应该考虑这些异常并加以捕获。 - caisah
在我看来,这并不测试网站是否正常运行,因为它会崩溃(正如之前的评论者所说)。这是我尝试的一个简短的、Pythonic 的实现:https://dev59.com/AHI-5IYBdhLWcg3wQV4Z#57999194 - vauhochzett
我们对代码责任有不同的看法。在所有级别上都考虑到错误处理可能过早、不必要且明显错误。所以不要轻视一个简单解决方案,它实际上解决了所述问题,然后将必要的处理添加到适当的位置。也许在这个级别上,也许在更高的级别上。但并非总是如此。 - Magnus Bodin

11
你可以使用 httplib
import httplib
conn = httplib.HTTPConnection("www.python.org")
conn.request("HEAD", "/")
r1 = conn.getresponse()
print r1.status, r1.reason

打印

200 OK

当然,前提是www.python.org正常运行。


这只检查域名,需要像这样适用于网页的高效工具。 - User

9
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
req = Request("http://stackoverflow.com")
try:
    response = urlopen(req)
except HTTPError as e:
    print('The server couldn\'t fulfill the request.')
    print('Error code: ', e.code)
except URLError as e:
    print('We failed to reach a server.')
    print('Reason: ', e.reason)
else:
    print ('Website is working fine')

适用于 Python 3


8
import httplib
import socket
import re

def is_website_online(host):
    """ This function checks to see if a host name has a DNS entry by checking
        for socket info. If the website gets something in return, 
        we know it's available to DNS.
    """
    try:
        socket.gethostbyname(host)
    except socket.gaierror:
        return False
    else:
        return True


def is_page_available(host, path="/"):
    """ This function retreives the status code of a website by requesting
        HEAD data from the host. This means that it only requests the headers.
        If the host cannot be reached or something else goes wrong, it returns
        False.
    """
    try:
        conn = httplib.HTTPConnection(host)
        conn.request("HEAD", path)
        if re.match("^[23]\d\d$", str(conn.getresponse().status)):
            return True
    except StandardError:
        return None

6
"is_website_online" 只是告诉你一个主机名是否有 DNS 记录,而不是网站是否在线。 - Craig McQueen

6
我会为此使用requests,这样做很简单且清晰易懂。 可以定义和调用新函数(通过电子邮件通知等),而不是使用print函数。使用try-except块是必要的,因为如果主机不可达,则会引发许多异常,因此您需要捕获它们全部。
import requests

URL = "https://api.github.com"

try:
    response = requests.head(URL)
except Exception as e:
    print(f"NOT OK: {str(e)}")
else:
    if response.status_code == 200:
        print("OK")
    else:
        print(f"NOT OK: HTTP response code {response.status_code}")

5
您可以使用requests库来查找网站是否正常运行,即检查网站的status code是否为200
import requests
url = "https://www.google.com"
page = requests.get(url)
print (page.status_code) 

>> 200

4
如果服务器宕机,Python 2.7 x86 Windows下的urllib没有超时功能,程序会被锁死。因此,请使用urllib2。
import urllib2
import socket

def check_url( url, timeout=5 ):
    try:
        return urllib2.urlopen(url,timeout=timeout).getcode() == 200
    except urllib2.URLError as e:
        return False
    except socket.timeout as e:
        print False


print check_url("http://google.fr")  #True 
print check_url("http://notexist.kc") #False     

4

标准库中httplib模块的HTTPConnection对象可能适合您的需求。顺便提一下,如果您在Python中开始进行任何高级HTTP操作,请务必查看httplib2;这是一个很棒的库。


2
在我看来,caisah's answer 没有涵盖你问题中一个重要的部分,即如何处理服务器离线的情况。
尽管如此,使用 requests 是我的首选,不过需要这样做:
import requests

try:
    requests.get(url)
except requests.exceptions.ConnectionError:
    print(f"URL {url} not reachable")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接