urllib2.HTTPError: Błąd HTTP 403: Dostęp zabroniony

102

Próbuję zautomatyzować pobieranie historycznych danych giełdowych za pomocą Pythona. Adres URL, który próbuję otworzyć, odpowiada plikowi CSV, ale nie mogę otworzyć go za pomocą urllib2. Próbowałem zmienić klienta użytkownika, jak określono w kilku pytaniach wcześniej, próbowałem nawet zaakceptować pliki cookie odpowiedzi, ale bez powodzenia. Czy możesz mi pomóc.

Uwaga: ta sama metoda działa w przypadku Yahoo Finance.

Kod:

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)

Błąd

Plik „C: \ Python27 \ lib \ urllib2.py”, wiersz 527, w http_error_default podnieś błąd HTTPError (req.get_full_url (), code, msg, hdrs, fp) urllib2.HTTPError: Błąd HTTP 403: zabronione

Dziękuję za Twoją pomoc

kumar
źródło
Czy używasz okien jako platformy?
Denis

Odpowiedzi:

170

Dodając kilka dodatkowych nagłówków, udało mi się uzyskać dane:

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

Właściwie działa tylko z tym jednym dodatkowym nagłówkiem:

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
andrean
źródło
Którego z tych nagłówków, Twoim zdaniem, brakowało w pierwotnym żądaniu?
1
wireshark wykazał, że wysłano tylko User-Agent, wraz z Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
andrean
1
Nie ma za co. Naprawdę sprawdziłem adres URL z twojego skryptu w przeglądarce, a ponieważ tam działało, po prostu skopiowałem wszystkie nagłówki żądań, które wysłała przeglądarka, i dodałem je tutaj, i to było rozwiązanie.
andrean
1
@Mee, czy spojrzałeś na odpowiedź poniżej? został zaadresowany specjalnie dla Pythona 3, sprawdź, czy działa dla Ciebie ...
andrean
1
spróbuj dodać również inne nagłówki (z mojej odpowiedzi) do żądania. nadal istnieje wiele innych powodów, dla których serwer może zwrócić błąd 403, sprawdź również inne odpowiedzi na ten temat. jeśli chodzi o cel, Google jest szczególnie trudny, trochę trudny do zeskrobania, wdrożyli wiele metod, aby zapobiec skrobaniu.
andrean
50

To zadziała w Pythonie 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
źródło
2
Prawdą jest, że niektóre witryny (w tym Wikipedia) blokują typowe ciągi agentów użytkownika spoza przeglądarki, takie jak „Python-urllib / xy” wysyłane przez biblioteki Pythona. Nawet zwykła „Mozilla” lub „Opera” zwykle wystarcza, aby to ominąć. Oczywiście nie dotyczy to pierwotnego pytania, ale warto wiedzieć.
efotinis
7

Witryna NSE uległa zmianie i starsze skrypty są częściowo optymalne w stosunku do obecnej witryny. Ten fragment może gromadzić codzienne szczegóły dotyczące bezpieczeństwa. Szczegóły obejmują symbol, typ papieru wartościowego, poprzednie zamknięcie, cenę otwarcia, wysoką cenę, niską cenę, średnią cenę, ilość będącą przedmiotem obrotu, obrót, liczbę transakcji, ilości do dostarczenia oraz stosunek ilości dostarczonych do sprzedanych w procentach. Te wygodnie przedstawione jako lista w formie słownikowej.

Wersja Pythona 3.X z żądaniami i 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)

Poza tym jest to stosunkowo modułowy i gotowy do użycia fragment kodu.

Supreet Sethi
źródło
Dzięki! to zadziałało dla mnie zamiast powyższej odpowiedzi od @andrean
Nitish Kumar Pal
Cześć, naprawdę nie wiem już, gdzie uderzyć się w głowę, próbowałem tego rozwiązania i wielu innych, ale ciągle pojawia się błąd 403. Czy jest coś jeszcze, co mogę spróbować?
Francesco
Status 403 ma na celu poinformowanie, że Twoja przeglądarka nie jest uwierzytelniona do korzystania z tej usługi. Może się zdarzyć, że w twoim przypadku naprawdę wymaga uwierzytelnienia za pomocą podstawowego uwierzytelnienia, oauth itp.
Supreet Sethi