¿Por qué urllib.request.urlopen a veces no funciona, pero los navegadores funcionan?

Estoy tratando de descargar algo de contenido usando urllib.request de Python. El siguiente comando produce una excepción:

 import urllib.request print(urllib.request.urlopen("https://fpgroup.foreignpolicy.com/foreign-policy-releases-mayjune-spy-issue/").code) 

resultado:

 ... HTTPError: HTTP Error 403: Forbidden 

si uso Firefox o enlaces (navegador de línea de comandos) obtengo el contenido y un código de estado de 200. Si uso lynx, lo suficientemente extraño, también obtengo 403.

Espero que todos los métodos funcionen.

  1. de la misma manera
  2. exitosamente

¿Por qué ese no es el caso?

Lo más probable es que el sitio esté impidiendo que la gente raspe sus sitios. Puedes engañarlos a un nivel básico al incluir información del encabezado junto con otras cosas. Vea aqui para mas informacion.

Cotizando desde: https://docs.python.org/3/howto/urllib2.html#headers

 import urllib.parse import urllib.request url = 'http://www.someserver.com/cgi-bin/register.cgi' user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' values = {'name' : 'Michael Foord', 'location' : 'Northampton', 'language' : 'Python' } headers = { 'User-Agent' : user_agent } data = urllib.parse.urlencode(values) data = data.encode('ascii') req = urllib.request.Request(url, data, headers) with urllib.request.urlopen(req) as response: the_page = response.read() 

Hay muchas razones por las que las personas no quieren que los scripts rasguen sus sitios web. Toma su ancho de banda para uno. No quieren que la gente se beneficie (en términos de dinero) al hacer un robot raspador. Tal vez no quieran que usted copie la información de su sitio. También puedes considerarlo como un libro. Los autores quieren que la gente lea sus libros, pero tal vez algunos de ellos no quieran que un robot escanee sus libros, cree una copia en papel, o tal vez el robot pueda resumirlo.

La segunda parte de su pregunta en el comentario es vaga y amplia para responder aquí, ya que hay demasiadas respuestas de opinión.

Intenté con este código y todo estaba bien.

Acabo de añadir headers a la solicitud. Vea el ejemplo a continuación:

 from urllib.request import Request, urlopen, HTTPError from time import sleep def get_url_data(url = ""): try: request = Request(url, headers = {'User-Agent' :\ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36"}) response = urlopen(request) data = response.read().decode("utf8") return data except HTTPError: return None url = "https://fpgroup.foreignpolicy.com/foreign-policy-releases-mayjune-spy-issue/" for i in range(50): d = get_url_data(url) if d != None: print("Attempt %d was a Success" % i) else: print("Attempt %d was a Failure" % i) sleep(1) 

Salida:

 Attempt 0 was a Success Attempt 1 was a Success Attempt 2 was a Success Attempt 3 was a Success Attempt 4 was a Success Attempt 5 was a Success Attempt 6 was a Success Attempt 7 was a Success Attempt 8 was a Success Attempt 9 was a Success ... Attempt 42 was a Success Attempt 43 was a Success Attempt 44 was a Success Attempt 45 was a Success Attempt 46 was a Success Attempt 47 was a Success Attempt 48 was a Success Attempt 49 was a Success