Jaki jest najlepszy sposób uzyskania kodu odpowiedzi HTTP z adresu URL?

82

Szukam szybkiego sposobu na uzyskanie kodu odpowiedzi HTTP z adresu URL (np. 200, 404 itd.). Nie wiem, której biblioteki użyć.

alexwlchan
źródło

Odpowiedzi:

99

Zaktualizuj za pomocą wspaniałej biblioteki żądań . Zauważ, że używamy żądania HEAD, które powinno nastąpić szybciej niż pełne żądanie GET lub POST.

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
źródło
request jest znacznie lepszy niż urllib2, dla takiego linku: dianping.com/promo/208721#mod=4 , urllib2 daje mi 404, a żądania 200, tak jak to, co otrzymuję z przeglądarki.
WKPlus,
5
httpstatusrappers.com ... niesamowite !! Mój kod dotyczy statusu Lil Jona, synu!
tmthyjames
1
To najlepsze rozwiązanie. Znacznie lepiej niż jakikolwiek inny.
Awn
@WKPlus dla rekordu, teraz requestspodaje 403twój link, chociaż nadal działa w przeglądarce.
Dennis Golomazov
2
@Gourneau Ha! Nie o to mi chodziło w moim komentarzu, myślę, że to było w porządku iw tym kontekście ludzie powinni spróbować zrozumieć, dlaczego to „po prostu działa” w przeglądarce, ale zwraca kod 403, podczas gdy w rzeczywistości to samo coś się dzieje w obu miejscach.
seaders
65

Oto rozwiązanie, które httplibzamiast tego używa .

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
źródło
14
+1 dla żądania HEAD - nie ma potrzeby pobierania całej jednostki w celu sprawdzenia statusu.
Ben Blank,
7
Chociaż naprawdę powinieneś ograniczyć ten exceptblok przynajmniej do StandardError, aby nie złapać nieprawidłowo takich rzeczy jak KeyboardInterrupt.
Ben Blank,
3
Zastanawiałem się, czy żądania HEAD są wiarygodne. Ponieważ strony internetowe mogą nie mieć (prawidłowo) zaimplementować metody HEAD, co może skutkować kodami statusu, takimi jak 404, 501 lub 500. A może mam paranoję?
Blaise,
2
Jak można to zrobić po 301?
Randall Hunt
2
@Blaise Jeśli witryna nie zezwala na żądania HEAD, wykonanie żądania HEAD powinno spowodować błąd 405. Na przykład spróbuj biegać curl -I http://www.amazon.com/.
Nick
24

Powinieneś użyć urllib2, na przykład:

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
źródło
3
To nie jest poprawne rozwiązanie, ponieważ urllib2 będzie podążać za przekierowaniami, więc nie otrzymasz żadnych odpowiedzi 3xx.
sorin
1
@sorin: To zależy - możesz chcieć śledzić przekierowania. Być może chcesz zadać pytanie: „Gdybym miał odwiedzić ten adres URL za pomocą przeglądarki, czy wyświetlałby treść, czy powodowałby błąd?” W takim przypadku, gdybym zmienił http://entrian.com/na http://entrian.com/blogw moim przykładzie, wynikowa 200 byłaby poprawna, mimo że obejmowała przekierowanie do http://entrian.com/blog/(zwróć uwagę na końcowy ukośnik).
RichieHindle,
8

W przyszłości dla tych, którzy używają python3 i nowszych wersji, oto kolejny kod do znalezienia kodu odpowiedzi.

import urllib.request

def getResponseCode(url):
    conn = urllib.request.urlopen(url)
    return conn.getcode()
nickanor
źródło
2
Spowoduje to zgłoszenie błędu HTTPError dla kodów stanu, takich jak 404, 500 itp.
Niklas R
3

urllib2.HTTPErrorWyjątek nie zawierają getcode()metody. codeZamiast tego użyj atrybutu.

Martijn Pieters
źródło
2
Robi to dla mnie, używając Pythona 2.6.
RichieHindle
2

Adresowanie komentarza @Niklas R do odpowiedzi @ 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
źródło
0

Oto httplibrozwiązanie, które zachowuje się jak urllib2. Możesz po prostu nadać mu adres URL i po prostu działa. Nie musisz się martwić dzieleniem adresów URL na nazwę hosta i ścieżkę. Ta funkcja już to robi.

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
źródło
1
Nie jestem pewien, dlaczego głosowano negatywnie bez opinii. Działa z adresami URL HTTP i HTTPS. Wykorzystuje metodę HEAD protokołu HTTP.
Sam Gleske,