urllib2.HTTPError: Erreur HTTP 403: Interdit

102

J'essaie d'automatiser le téléchargement des données de stock historiques à l'aide de python. L'URL que j'essaie d'ouvrir répond par un fichier CSV, mais je ne parviens pas à ouvrir en utilisant urllib2. J'ai essayé de changer d'agent utilisateur comme spécifié dans quelques questions plus tôt, j'ai même essayé d'accepter les cookies de réponse, sans succès. Peux-tu aider s'il te plait.

Remarque: la même méthode fonctionne pour Yahoo Finance.

Code:

import urllib2,cookielib

site= "http://www.nseindia.com/live_market/dynaContent/live_watch/get_quote/getHistoricalData.jsp?symbol=JPASSOCIAT&fromDate=1-JAN-2012&toDate=1-AUG-2012&datePeriod=unselected&hiddDwnld=true"

hdr = {'User-Agent':'Mozilla/5.0'}

req = urllib2.Request(site,headers=hdr)

page = urllib2.urlopen(req)

Erreur

Fichier "C: \ Python27 \ lib \ urllib2.py", ligne 527, dans http_error_default, lever HTTPError (req.get_full_url (), code, msg, hdrs, fp) urllib2.HTTPError: HTTP Error 403: Forbidden

Merci pour votre aide

Kumar
la source
Utilisez-vous Windows comme plate-forme?
Denis

Réponses:

170

En ajoutant quelques en-têtes supplémentaires, j'ai pu obtenir les données:

import urllib2,cookielib

site= "http://www.nseindia.com/live_market/dynaContent/live_watch/get_quote/getHistoricalData.jsp?symbol=JPASSOCIAT&fromDate=1-JAN-2012&toDate=1-AUG-2012&datePeriod=unselected&hiddDwnld=true"
hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
       'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
       'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
       'Accept-Encoding': 'none',
       'Accept-Language': 'en-US,en;q=0.8',
       'Connection': 'keep-alive'}

req = urllib2.Request(site, headers=hdr)

try:
    page = urllib2.urlopen(req)
except urllib2.HTTPError, e:
    print e.fp.read()

content = page.read()
print content

En fait, cela fonctionne avec juste cet en-tête supplémentaire:

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
andréen
la source
Selon vous, lequel de ces en-têtes manquait dans la demande d'origine?
1
WireShark a montré que seul le User-Agent a été envoyé, avec Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
andrean
1
De rien, ce que j'ai vraiment fait, c'est que j'ai vérifié l'url de votre script dans un navigateur, et comme cela fonctionnait là-bas, j'ai simplement copié tous les en-têtes de requête envoyés par le navigateur et les ai ajoutés ici, et c'était la solution.
andrean
1
@Mee avez-vous jeté un œil à la réponse ci-dessous? il a été adressé spécifiquement pour python 3, vérifiez si cela fonctionne pour vous ...
andrean
1
essayez également d'ajouter les autres en-têtes (de ma réponse) à la demande. il existe encore de nombreuses autres raisons pour lesquelles un serveur peut renvoyer un 403, consultez également les autres réponses sur le sujet. quant à la cible, google est particulièrement difficile, un peu difficile à gratter, ils ont mis en œuvre de nombreuses méthodes pour éviter le grattage.
andrean
50

Cela fonctionnera dans Python 3

import urllib.request

user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'

url = "http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers"
headers={'User-Agent':user_agent,} 

request=urllib.request.Request(url,None,headers) #The assembled request
response = urllib.request.urlopen(request)
data = response.read() # The data u need
Eish
la source
2
Il est vrai que certains sites (y compris Wikipédia) bloquent sur les chaînes d'agents utilisateurs non-navigateurs courantes, comme le "Python-urllib / xy" envoyé par les bibliothèques de Python. Même un simple "Mozilla" ou "Opera" suffit généralement pour contourner cela. Cela ne s'applique pas à la question d'origine, bien sûr, mais il est toujours utile de le savoir.
efotinis
7

Le site Web de NSE a changé et les anciens scripts sont semi-optimaux par rapport au site Web actuel. Cet extrait peut rassembler des détails quotidiens de sécurité. Les détails incluent le symbole, le type de titre, la clôture précédente, le prix ouvert, le prix élevé, le prix bas, le prix moyen, la quantité échangée, le chiffre d'affaires, le nombre de transactions, les quantités livrables et le rapport entre livrés et négociés en pourcentage. Ceux-ci sont présentés sous forme de liste sous forme de dictionnaire.

Version Python 3.X avec requêtes et BeautifulSoup

from requests import get
from csv import DictReader
from bs4 import BeautifulSoup as Soup
from datetime import date
from io import StringIO 

SECURITY_NAME="3MINDIA" # Change this to get quote for another stock
START_DATE= date(2017, 1, 1) # Start date of stock quote data DD-MM-YYYY
END_DATE= date(2017, 9, 14)  # End date of stock quote data DD-MM-YYYY


BASE_URL = "https://www.nseindia.com/products/dynaContent/common/productsSymbolMapping.jsp?symbol={security}&segmentLink=3&symbolCount=1&series=ALL&dateRange=+&fromDate={start_date}&toDate={end_date}&dataType=PRICEVOLUMEDELIVERABLE"




def getquote(symbol, start, end):
    start = start.strftime("%-d-%-m-%Y")
    end = end.strftime("%-d-%-m-%Y")

    hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
         'Referer': 'https://cssspritegenerator.com',
         'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
         'Accept-Encoding': 'none',
         'Accept-Language': 'en-US,en;q=0.8',
         'Connection': 'keep-alive'}

    url = BASE_URL.format(security=symbol, start_date=start, end_date=end)
    d = get(url, headers=hdr)
    soup = Soup(d.content, 'html.parser')
    payload = soup.find('div', {'id': 'csvContentDiv'}).text.replace(':', '\n')
    csv = DictReader(StringIO(payload))
    for row in csv:
        print({k:v.strip() for k, v in row.items()})


 if __name__ == '__main__':
     getquote(SECURITY_NAME, START_DATE, END_DATE)

En outre, c'est un extrait de code relativement modulaire et prêt à l'emploi.

Supreet Sethi
la source
Merci mec! cela a fonctionné pour moi au lieu de la réponse ci-dessus de @andrean
Nitish Kumar Pal
Salut, je ne sais vraiment plus où me cogner la tête, j'ai essayé cette solution et bien d'autres, mais je reçois toujours l'erreur 403. Est-ce que je peux essayer autre chose?
Francesco
Le statut 403 est destiné à informer que votre navigateur n'est pas authentifié pour utiliser ce service. Il se peut que dans votre cas, cela nécessite vraiment une authentification avec authentification de base, oauth, etc.
Supreet Sethi