urllib2.HTTPError: HTTP-Fehler 403: Verboten


102

Ich versuche, das Herunterladen historischer Bestandsdaten mit Python zu automatisieren. Die URL, die ich öffnen möchte, antwortet mit einer CSV-Datei, kann jedoch nicht mit urllib2 geöffnet werden. Ich habe versucht, den Benutzeragenten zu ändern, wie in einigen Fragen zuvor angegeben. Ich habe sogar versucht, Antwort-Cookies zu akzeptieren, ohne Glück. Können Sie bitte helfen.

Hinweis: Die gleiche Methode funktioniert für 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)

Error

Datei "C: \ Python27 \ lib \ urllib2.py", Zeile 527, in http_error_default HTTPError (req.get_full_url (), Code, msg, hdrs, fp) auslösen urllib2.HTTPError: HTTP-Fehler 403: Verboten

Danke für deine Hilfe


Verwenden Sie Windows als Plattform?
Denis

Antworten:


169

Durch Hinzufügen einiger weiterer Header konnte ich die Daten abrufen:

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

Eigentlich funktioniert es nur mit diesem einen zusätzlichen Header:

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

Welcher dieser Header fehlte Ihrer Meinung nach in der ursprünglichen Anfrage?

1
wireshark zeigte, dass nur der User-Agent zusammen mit Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
andrean

1
Gern geschehen. Nun, was ich wirklich getan habe, ist, dass ich die URL Ihres Skripts in einem Browser überprüft habe. Da dies dort funktioniert hat, habe ich einfach alle vom Browser gesendeten Anforderungsheader kopiert und hier hinzugefügt, und das war die Lösung.
andrean

1
@Mee hast du dir die Antwort unten angesehen? Es wurde speziell für Python 3 angesprochen. Überprüfen Sie, ob es für Sie funktioniert ...
andrean

1
Versuchen Sie, die anderen Header (aus meiner Antwort) ebenfalls zur Anfrage hinzuzufügen. Es gibt noch viele andere Gründe, warum ein Server einen 403 zurückgeben könnte. Lesen Sie auch die anderen Antworten zu diesem Thema. Was das Ziel betrifft, ist Google besonders schwierig, etwas schwer zu kratzen. Sie haben viele Methoden implementiert, um das Kratzen zu verhindern.
andrean

50

Dies funktioniert in 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

2
Es ist wahr, dass einige Websites (einschließlich Wikipedia) gängige Zeichenfolgen von Nicht-Browser-Benutzeragenten blockieren, wie z. B. "Python-urllib / xy", das von Pythons Bibliotheken gesendet wird. Sogar ein einfaches "Mozilla" oder "Opera" reicht normalerweise aus, um das zu umgehen. Dies gilt natürlich nicht für die ursprüngliche Frage, aber es ist immer noch nützlich zu wissen.
Efotinis

7

Die NSE-Website hat sich geändert und die älteren Skripte sind für die aktuelle Website halboptimal. Dieses Snippet kann tägliche Details zur Sicherheit erfassen. Zu den Details gehören Symbol, Wertpapierart, vorheriger Schlusskurs, offener Preis, hoher Preis, niedriger Preis, Durchschnittspreis, gehandelte Menge, Umsatz, Anzahl der Geschäfte, lieferbare Mengen und Verhältnis von geliefertem zu gehandeltem Prozentsatz. Diese werden bequem als Liste der Wörterbuchform dargestellt.

Python 3.X Version mit Anfragen und 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)

Außerdem ist dies relativ modular und gebrauchsfertig.


Danke, Mann! Dies funktionierte für mich anstelle der obigen Antwort von @andrean
Nitish Kumar Pal

Hallo, ich weiß wirklich nicht mehr, wo ich meinen Kopf schlagen soll. Ich habe diese und viele weitere Lösungen ausprobiert, aber ich erhalte immer wieder den Fehler 403. Kann ich noch etwas ausprobieren?
Francesco

Der Status 403 soll darüber informieren, dass Ihr Browser für die Nutzung dieses Dienstes nicht authentifiziert ist. Es kann sein, dass in Ihrem Fall wirklich eine Authentifizierung mit Basic Auth, Oauth usw. erforderlich ist.
Supreet Sethi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.