160 votes

Problème d'erreur HTTP 403 dans Python 3 Web Scraping

J'essayais de gratter un site web pour m'entraîner, mais je continue à obtenir l'erreur HTTP 403 (est-ce qu'il pense que je suis un robot) ?

Voici mon code :

#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 = []

L'erreur que je reçois est la suivante :

 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

316voto

Stefano Sanfilippo Points 11123

Cela s'explique probablement par mod_security ou une autre fonction de sécurité similaire du serveur qui bloque les agents utilisateurs connus des araignées et des robots ( urllib utilise quelque chose comme python urllib/3.3.0 il est facile à détecter). Essayez de définir un agent utilisateur de navigateur connu avec :

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()

Cela fonctionne pour moi.

Au fait, dans votre code, il manque l'élément () après .read en el urlopen mais je pense que c'est une faute de frappe.

CONSEIL : comme il s'agit d'un exercice, choisissez un autre site, non restrictif. Peut-être qu'ils bloquent urllib pour une raison quelconque...

0 votes

Je suppose qu'on peut le réutiliser en toute sécurité req pour de multiples urlopen appels.

1 votes

C'est peut-être un peu tard, mais j'ai déjà mis User-Agent dans mon code, mais cela me donne quand même Error 404: Access denied

0 votes

Cela fonctionne mais j'ai l'impression qu'ils doivent avoir une bonne raison de bloquer les robots et que je viole leurs conditions d'utilisation.

52voto

zeta Points 56

Il est certain que le blocage est dû à votre utilisation d'urllib en fonction de l'agent utilisateur. La même chose m'arrive avec OfferUp. Vous pouvez créer une nouvelle classe appelée AppURLopener qui remplace l'agent utilisateur par Mozilla.

import urllib.request

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

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

Source :

3 votes

La réponse du haut n'a pas fonctionné pour moi, alors que la vôtre a fonctionné. Merci beaucoup !

1 votes

Cela fonctionne très bien, mais j'ai besoin de joindre la configuration ssl à cela. Comment dois-je m'y prendre ? Avant, je l'ajoutais simplement comme deuxième paramètre (urlopen(request,context=ctx)).

4 votes

Il semble qu'il se soit ouvert mais il est écrit 'ValueError : read of closed file'.

27voto

royatirek Points 156

"C'est probablement à cause mod_security ou un autre dispositif de sécurité similaire qui bloque les

araignée/bot

agents utilisateurs (urllib utilise quelque chose comme python urllib/3.3.0, c'est facilement détectable)" - comme déjà mentionné par 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 est un objet octet retourné par le serveur et le type de contenu présent dans la page web est principalement utf-8 . Vous devez donc décoder web_byte en utilisant la méthode de décodage.

Cela résout tout le problème que j'avais en essayant de gratter à partir d'un site web en utilisant PyCharm

P.S -> J'utilise python 3.4

6voto

Jonny_P Points 89

D'après les réponses précédentes, cela a fonctionné pour moi avec Python 3.7 en augmentant le délai d'attente à 10.

from urllib.request import Request, urlopen

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

print(webpage)

2voto

Robert Lujo Points 2743

Puisque la page fonctionne dans le navigateur et pas lors de l'appel dans le programme python, il semble que l'application web qui sert cette url reconnaît que vous demandez le contenu non par le navigateur.

Démonstration :

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>

et le contenu de r.txt a une ligne d'état :

HTTP/1.1 403 Forbidden

Essayez d'afficher l'en-tête 'User-Agent' qui faux client web.

NOTA: La page contient un appel Ajax qui crée le tableau que vous voulez probablement analyser. Vous devrez vérifier la logique javascript de la page ou simplement utiliser le débogueur du navigateur (comme Firebug / Net tab) pour voir quelle url vous devez appeler pour obtenir le contenu de la table.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X