urllib2.HTTPError: ошибка HTTP 403: запрещено


104

Я пытаюсь автоматизировать загрузку исторических данных о запасах с помощью python. URL-адрес, который я пытаюсь открыть, отвечает CSV-файлом, но я не могу открыть его с помощью urllib2. Я попытался изменить пользовательский агент, как указано в нескольких вопросах ранее, я даже попытался принять ответные файлы cookie, но безуспешно. Не могли бы вы помочь.

Примечание. Тот же метод работает для Yahoo Finance.

Код:

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)

ошибка

Файл «C: \ Python27 \ lib \ urllib2.py», строка 527, в http_error_default вызывает HTTPError (req.get_full_url (), code, msg, hdrs, fp) urllib2.HTTPError: Ошибка HTTP 403: запрещено

Спасибо за твою помощь


Вы используете окна в качестве платформы?
Денис

Ответы:


171

Добавив еще несколько заголовков, я смог получить данные:

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

На самом деле он работает только с одним дополнительным заголовком:

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

Как вы думаете, какой из этих заголовков отсутствовал в исходном запросе?

1
WireShark показал, что был отправлен только User-Agent вместе с Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
andrean

1
Пожалуйста, на самом деле я проверил URL-адрес вашего скрипта в браузере, и, поскольку он там работал, я просто скопировал все заголовки запросов, отправленные браузером, и добавил их сюда, и это было решением.
andrean 09

1
@Mee вы смотрели на ответ ниже? он был адресован специально для python 3, проверьте, работает ли он для вас ...
andrean

1
попробуйте добавить и другие заголовки (из моего ответа) в запрос. тем не менее, есть много других причин, по которым сервер может возвращать 403, ознакомьтесь также с другими ответами по этой теме. Что касается цели, Google особенно сложен, его сложно очистить, они реализовали множество методов для предотвращения очистки.
andrean

51

Это будет работать в 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
Это правда, что некоторые сайты (включая Википедию) блокируют стандартные строки пользовательских агентов, не относящихся к браузеру, такие как «Python-urllib / xy», отправляемые библиотеками Python. Даже простой "Mozilla" или "Opera" обычно достаточно, чтобы обойти это. Это, конечно, не относится к исходному вопросу, но все же полезно знать.
efotinis

8

Веб-сайт NSE изменился, и старые скрипты частично оптимальны для текущего веб-сайта. Этот фрагмент может собирать ежедневные сведения о безопасности. Подробная информация включает символ, тип ценной бумаги, предыдущее закрытие, цену открытия, максимальную цену, минимальную цену, среднюю цену, количество сделок, оборот, количество сделок, количество поставленных сделок и соотношение поставленных и проданных сделок в процентах. Они удобно представлены в виде списка в виде словаря.

Версия Python 3.X с запросами и 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)

Кроме того, это относительно модульный и готовый к использованию сниппет.


Спасибо чувак! это сработало для меня вместо вышеуказанного ответа от @andrean
Кумар Пал

Привет, я действительно не знаю, куда больше биться головой, я пробовал это решение и многие другие, но все время получаю ошибку 403. Могу ли я еще что-нибудь попробовать?
Francesco

Статус 403 предназначен для информирования о том, что ваш браузер не прошел аутентификацию для использования этой службы. Возможно, в вашем случае это действительно требует аутентификации с использованием базовой аутентификации, oauth и т. Д.
Суприт Сетхи
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.