Error HTTP 403 en Python 3 Web Scraping

100

Estaba tratando de eliminar un sitio web para practicar, pero seguí obteniendo el error HTTP 403 (¿cree que soy un bot)?

Aquí está mi código:

#import requests
import urllib.request
from bs4 import BeautifulSoup
#from urllib import urlopen
import re

webpage = urllib.request.urlopen('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1').read
findrows = re.compile('<tr class="- banding(?:On|Off)>(.*?)</tr>')
findlink = re.compile('<a href =">(.*)</a>')

row_array = re.findall(findrows, webpage)
links = re.finall(findlink, webpate)

print(len(row_array))

iterator = []

El error que obtengo es:

 File "C:\Python33\lib\urllib\request.py", line 160, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 479, in open
    response = meth(req, response)
  File "C:\Python33\lib\urllib\request.py", line 591, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python33\lib\urllib\request.py", line 517, in error
    return self._call_chain(*args)
  File "C:\Python33\lib\urllib\request.py", line 451, in _call_chain
    result = func(*args)
  File "C:\Python33\lib\urllib\request.py", line 599, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
Josh
fuente

Respuestas:

209

Esto probablemente se deba a mod_securityalguna característica de seguridad del servidor similar que bloquea a los agentes de usuario de araña / bot conocidos ( urllibusa algo como python urllib/3.3.0, se detecta fácilmente). Intente configurar un agente de usuario de navegador conocido con:

from urllib.request import Request, urlopen

req = Request('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1', headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()

Esto funciona para mi.

Por cierto, en su código le falta el ()después .readen la urlopenlínea, pero creo que es un error tipográfico.

SUGERENCIA: dado que este es un ejercicio, elija un sitio diferente y no restrictivo. Tal vez estén bloqueando urllibpor alguna razón ...

Stefano Sanfilippo
fuente
Supongo que es seguro reutilizarlo reqpara varias urlopenllamadas.
Acumenus
Puede que sea un poco tarde, pero ya tengo User-Agent en mi código, todavía me lo daError 404: Access denied
Reema Parakh
Esto funciona, pero siento que deben tener una buena razón para bloquear bots y estoy violando sus términos de servicio
xjcl
39

Definitivamente está bloqueando debido a su uso de urllib basado en el agente de usuario. Lo mismo me está pasando con OfferUp. Puede crear una nueva clase llamada AppURLopener que anula el agente de usuario con Mozilla.

import urllib.request

class AppURLopener(urllib.request.FancyURLopener):
    version = "Mozilla/5.0"

opener = AppURLopener()
response = opener.open('http://httpbin.org/user-agent')

Fuente

zeta
fuente
2
La respuesta principal no funcionó para mí, mientras que la tuya sí. ¡Muchas gracias!
Tarun Uday
Esto funciona bien, pero necesito adjuntar la configuración ssl a esto. ¿Cómo hago esto? Antes, lo agregué como segundo parámetro (urlopen (request, context = ctx))
Hauke
2
parece que se abrió pero dice 'ValueError: read of closed file'
Martian2049
@zeta ¿Cómo se las arregló para eliminar OfferUp y proporcionar las coordenadas geográficas necesarias para realizar la búsqueda desde un script?
CJ Travis
@CJTravis, no estaba eliminando OfferUp. Solo estaba recuperando valores de elementos basados ​​en una URL exacta de un elemento. Eso no requirió coordenadas geográficas para mí
zeta
13

"Esto probablemente se deba a mod_security o alguna característica de seguridad del servidor similar que bloquea

araña / bot

agentes de usuario (urllib usa algo como python urllib / 3.3.0, se detecta fácilmente) "- como ya lo mencionó Stefano Sanfilippo

from urllib.request import Request, urlopen
url="https://stackoverflow.com/search?q=html+error+403"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})

web_byte = urlopen(req).read()

webpage = web_byte.decode('utf-8')

El web_byte es un objeto de byte devuelto por el servidor y el tipo de contenido presente en la página web es principalmente UTF-8 . Por lo tanto, necesita decodificar web_byte usando el método de decodificación.

Esto resuelve el problema completo mientras intentaba eliminar de un sitio web usando PyCharm

PD -> uso Python 3.4

Royatirek
fuente
2

Basado en la respuesta anterior,

from urllib.request import Request, urlopen       
#specify url
url = 'https://xyz/xyz'
req = Request(url, headers={'User-Agent': 'XYZ/3.0'})
response = urlopen(req, timeout=20).read()

Esto funcionó para mí al extender el tiempo de espera.

VICTOR IWUOHA
fuente
1

Dado que la página funciona en el navegador y no cuando se llama dentro del programa Python, parece que la aplicación web que sirve esa url reconoce que usted solicita el contenido no por el navegador.

Demostración:

curl --dump-header r.txt http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1

...
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
You don't have permission to access ...
</HTML>

y el contenido en r.txt tiene una línea de estado:

HTTP/1.1 403 Forbidden

Intente publicar el encabezado 'User-Agent' que falsifica el cliente web.

NOTA: La página contiene una llamada Ajax que crea la tabla que probablemente desee analizar. Deberá verificar la lógica javascript de la página o simplemente usar el depurador del navegador (como la pestaña Firebug / Net) para ver a qué URL debe llamar para obtener el contenido de la tabla.

Robert Lujo
fuente
1

Puedes intentarlo de dos formas. El detalle está en este enlace .

1) vía pip

instalar pip - actualizar certifi

2) Si no funciona, intente ejecutar un comando Cerificates.com que viene incluido con Python 3. * para Mac: (Vaya a su ubicación de instalación de Python y haga doble clic en el archivo)

abrir / Aplicaciones / Python \ 3. * / Install \ Certificates.command

Johnson
fuente
0

Si se siente culpable por fingir que el agente de usuario es Mozilla (comente en la respuesta principal de Stefano), también podría funcionar con un agente de usuario que no sea de urllib. Esto funcionó para los sitios a los que hago referencia:

    req = urlrequest.Request(link, headers={'User-Agent': 'XYZ/3.0'})
    urlrequest.urlopen(req, timeout=10).read()

Mi aplicación es para probar la validez raspando enlaces específicos a los que me refiero en mis artículos. No es un raspador genérico.

Sudeep Prasad
fuente
0

Según las respuestas anteriores, esto me ha funcionado con Python 3.7

from urllib.request import Request, urlopen

req = Request('Url_Link', headers={'User-Agent': 'XYZ/3.0'})
webpage = urlopen(req, timeout=10).read()

print(webpage)
Jonny_P
fuente