¿Cuál es la mejor forma de obtener un código de respuesta HTTP desde una URL?

82

Estoy buscando una forma rápida de obtener un código de respuesta HTTP de una URL (es decir, 200, 404, etc.). No estoy seguro de qué biblioteca usar.

alexwlchan
fuente

Respuestas:

99

Actualice utilizando la maravillosa biblioteca de solicitudes . Tenga en cuenta que estamos utilizando la solicitud HEAD, que debería suceder más rápidamente que una solicitud GET o POST completa.

import requests
try:
    r = requests.head("https://stackoverflow.com")
    print(r.status_code)
    # prints the int of the status code. Find more at httpstatusrappers.com :)
except requests.ConnectionError:
    print("failed to connect")
Gourneau
fuente
Las solicitudes son mucho mejores que urllib2, para un enlace de este tipo: dianping.com/promo/208721#mod=4 , urllib2 me da un 404 y las solicitudes me dan un 200 tal como lo que obtengo de un navegador.
WKPlus
5
httpstatusrappers.com ... increíble !! ¡Mi código está en ese estado de Lil Jon, hijo!
tmthyjames
1
Esta es la mejor solución. Mucho mejor que cualquiera de los demás.
Awn
@WKPlus para el registro, ahora requestsproporciona 403su enlace, aunque todavía funciona en el navegador.
Dennis Golomazov
2
@Gourneau ¡Ja! Eso no era lo que pretendía con mi comentario, creo que estuvo perfectamente bien, y en este contexto, la gente debería intentar entender por qué "Simplemente funciona" en el navegador, pero devuelve un 403 en código, cuando en realidad, lo mismo algo está sucediendo en ambos lugares.
Seaders
65

Aquí hay una solución que usa en su httpliblugar.

import httplib

def get_status_code(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
        None instead.
    """
    try:
        conn = httplib.HTTPConnection(host)
        conn.request("HEAD", path)
        return conn.getresponse().status
    except StandardError:
        return None


print get_status_code("stackoverflow.com") # prints 200
print get_status_code("stackoverflow.com", "/nonexistant") # prints 404
Evan Fosmark
fuente
14
+1 para la solicitud HEAD: no es necesario recuperar toda la entidad para una verificación de estado.
Ben Blank
7
Aunque realmente debería restringir ese exceptbloque al menos StandardErrorpara no captar incorrectamente cosas como KeyboardInterrupt.
Ben Blank
3
Me preguntaba si las solicitudes HEAD son confiables. Porque es posible que los sitios web no hayan implementado (correctamente) el método HEAD, lo que podría resultar en códigos de estado como 404, 501 o 500. ¿O estoy siendo paranoico?
Blaise
2
¿Cómo se puede hacer que esto siga a los 301?
Randall Hunt
2
@Blaise Si un sitio web no permite solicitudes HEAD, entonces realizar una solicitud HEAD debería generar un error 405. Para ver un ejemplo de esto, intente ejecutar curl -I http://www.amazon.com/.
Nick
24

Deberías usar urllib2, así:

import urllib2
for url in ["http://entrian.com/", "http://entrian.com/does-not-exist/"]:
    try:
        connection = urllib2.urlopen(url)
        print connection.getcode()
        connection.close()
    except urllib2.HTTPError, e:
        print e.getcode()

# Prints:
# 200 [from the try block]
# 404 [from the except block]
RichieHindle
fuente
3
Esta no es una solución válida porque urllib2 seguirá las redirecciones, por lo que no obtendrá ninguna respuesta 3xx.
sorin
1
@sorin: Eso depende, es posible que desee seguir las redirecciones. Quizás desee hacer la pregunta "Si visitara esta URL con un navegador, ¿mostraría contenido o daría un error?" En ese caso, si cambiara http://entrian.com/a http://entrian.com/blogen mi ejemplo, el 200 resultante sería correcto a pesar de que implicaba una redirección a http://entrian.com/blog/(observe la barra inclinada final).
RichieHindle
8

En el futuro, para aquellos que usan python3 y versiones posteriores, aquí hay otro código para encontrar el código de respuesta.

import urllib.request

def getResponseCode(url):
    conn = urllib.request.urlopen(url)
    return conn.getcode()
Nickanor
fuente
2
Esto generará un HTTPError para códigos de estado como 404, 500, etc.
Niklas R
3

La urllib2.HTTPErrorexcepción no contiene ningún getcode()método. En su lugar, utilice el codeatributo.

Martijn Pieters
fuente
2
Lo hace para mí, usando Python 2.6.
RichieHindle
2

Dirigiendo el comentario de @Niklas R a la respuesta de @ nickanor:

from urllib.error import HTTPError
import urllib.request

def getResponseCode(url):
    try:
        conn = urllib.request.urlopen(url)
        return conn.getcode()
    except HTTPError as e:
        return e.code
EL
fuente
0

Aquí hay una httplibsolución que se comporta como urllib2. Simplemente puede darle una URL y simplemente funciona. No hay necesidad de meterse en dividir las URL en nombre de host y ruta. Esta función ya hace eso.

import httplib
import socket
def get_link_status(url):
  """
    Gets the HTTP status of the url or returns an error associated with it.  Always returns a string.
  """
  https=False
  url=re.sub(r'(.*)#.*$',r'\1',url)
  url=url.split('/',3)
  if len(url) > 3:
    path='/'+url[3]
  else:
    path='/'
  if url[0] == 'http:':
    port=80
  elif url[0] == 'https:':
    port=443
    https=True
  if ':' in url[2]:
    host=url[2].split(':')[0]
    port=url[2].split(':')[1]
  else:
    host=url[2]
  try:
    headers={'User-Agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0',
             'Host':host
             }
    if https:
      conn=httplib.HTTPSConnection(host=host,port=port,timeout=10)
    else:
      conn=httplib.HTTPConnection(host=host,port=port,timeout=10)
    conn.request(method="HEAD",url=path,headers=headers)
    response=str(conn.getresponse().status)
    conn.close()
  except socket.gaierror,e:
    response="Socket Error (%d): %s" % (e[0],e[1])
  except StandardError,e:
    if hasattr(e,'getcode') and len(e.getcode()) > 0:
      response=str(e.getcode())
    if hasattr(e, 'message') and len(e.message) > 0:
      response=str(e.message)
    elif hasattr(e, 'msg') and len(e.msg) > 0:
      response=str(e.msg)
    elif type('') == type(e):
      response=e
    else:
      response="Exception occurred without a good error message.  Manually check the URL to see the status.  If it is believed this URL is 100% good then file a issue for a potential bug."
  return response
Sam Gleske
fuente
1
No estoy seguro de por qué fue rechazado sin comentarios. Funciona con URL HTTP y HTTPS. Utiliza el método HEAD de HTTP.
Sam Gleske